Beispiel #1
0
        public int DrawCostume(VirtScreen vs, int numStrips, Actor actor, bool drawToBackBuf)
        {
            var pixelsNavigator = new PixelNavigator(vs.Surfaces[drawToBackBuf ? 1 : 0]);

            pixelsNavigator.OffsetX(vs.XStart);

            ActorX += (vs.XStart & 7);
            pixelsNavigator.OffsetX(-(vs.XStart & 7));
            startNav = new PixelNavigator(pixelsNavigator);

            if (_vm.Game.IsOldBundle)
            {
                _xmove = -72;
                _ymove = -100;
            }
            else
            {
                _xmove = _ymove = 0;
            }

            int result = 0;

            for (int i = 0; i < 16; i++)
            {
                result |= DrawLimb(actor, i);
            }
            return(result);
        }
Beispiel #2
0
        public void DrawBitmap(ImageData img, VirtScreen vs, int x, int y, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags)
        {
            // Check whether lights are turned on or not
            var lightsOn = _vm.IsLightOn();

            DrawBitmap(img, vs, new Point(x, y), width, height, stripnr, numstrip, roomWidth, flags, lightsOn);
        }
Beispiel #3
0
 protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                                           Point p, int width, int height,
                                           int stripnr, int numstrip)
 {
     if (_objectMode)
     {
         var imgData = (ImageData1)img;
         objectMap = imgData.ObjectMap;
     }
 }
Beispiel #4
0
 protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                                           Point p, int width, int height,
                                           int stripnr, int numstrip)
 {
     if (_objectMode)
     {
         var imgData = (ImageData1)img;
         objectMap = imgData.ObjectMap;
     }
 }
Beispiel #5
0
        protected CharsetRenderer(ScummEngine vm)
        {
            Top = 0;
            Left = 0;
            StartLeft = 0;
            Right = 0;

            Color = 0;

            Center = false;
            HasMask = false;
            TextScreen = vm.MainVirtScreen;
            BlitAlso = false;
            FirstChar = false;
            DisableOffsX = false;

            Vm = vm;
            CurId = -1;
        }
Beispiel #6
0
        protected CharsetRenderer(ScummEngine vm)
        {
            Top       = 0;
            Left      = 0;
            StartLeft = 0;
            Right     = 0;

            Color = 0;

            Center       = false;
            HasMask      = false;
            TextScreen   = vm.MainVirtScreen;
            BlitAlso     = false;
            FirstChar    = false;
            DisableOffsX = false;

            Vm    = vm;
            CurId = -1;
        }
Beispiel #7
0
        void UpdateDirtyScreen(VirtScreen vs)
        {
            // Do nothing for unused virtual screens
            if (vs.Height == 0)
                return;

            int i;
            int w = 8;
            int start = 0;

            for (i = 0; i < Gdi.NumStrips; i++)
            {
                if (vs.BDirty[i] != 0)
                {
                    int top = vs.TDirty[i];
                    int bottom = vs.BDirty[i];
                    vs.TDirty[i] = vs.Height;
                    vs.BDirty[i] = 0;
                    if (i != (Gdi.NumStrips - 1) && vs.BDirty[i + 1] == bottom && vs.TDirty[i + 1] == top)
                    {
                        // Simple optimizations: if two or more neighboring strips
                        // form one bigger rectangle, coalesce them.
                        w += 8;
                        continue;
                    }
                    DrawStripToScreen(vs, start * 8, w, top, bottom);
                    w = 8;
                }
                start = i + 1;
            }
        }
Beispiel #8
0
        void DumpRoomObjectImages(Room room, ObjectData obj, Gdi gdi)
        {
            var text = new ScummText(obj.Name);
            var sb = new StringBuilder();
            sb.Append("Object #" + obj.Number).Append(" ");

            var decoder = new TextDecoder(sb);
            text.Decode(decoder);

            sb.AppendFormat(" size: {0}x{1}", obj.Width, obj.Height);
            Console.WriteLine(sb);

            var j = 0;
            foreach (var img in obj.Images)
            {
//                try
//                {
                var screen = new VirtScreen(0, obj.Width, obj.Height, PixelFormat.Indexed8, 2);
                if (img.IsBomp)
                {
                    var bdd = new BompDrawData();
                    bdd.Src = img.Data;
                    bdd.Dst = new PixelNavigator(screen.Surfaces[0]);
                    bdd.X = 0;
                    bdd.Y = 0;

                    bdd.Width = obj.Width;
                    bdd.Height = obj.Height;

                    bdd.ScaleX = 255;
                    bdd.ScaleY = 255;
                    bdd.DrawBomp();
                }
                else
                {
                    gdi.DrawBitmap(img, screen, new Point(0, 0), obj.Width, obj.Height & 0xFFF8, 0, obj.Width / 8, room.Header.Width, DrawBitmaps.None, true);
                }

                using (var bmp = ToBitmap(room, screen))
                {
                    bmp.Save("obj_" + obj.Number + "_" + (++j) + ".png");
                }
//                }
//                catch (Exception e)
//                {
//                    Console.ForegroundColor = ConsoleColor.Red;
//                    Console.WriteLine(e);
//                    Console.ResetColor();
//                    Console.ReadLine();
//                }
            }
        }
Beispiel #9
0
        void DumpRoomImage(Room room, Gdi gdi)
        {
            var name = room.Name ?? "room_" + room.Number;

            var screen = new VirtScreen(0, room.Header.Width, room.Header.Height, PixelFormat.Indexed8, 2);
            var numStrips = room.Header.Width / 8;
            gdi.NumStrips = numStrips;
            gdi.IsZBufferEnabled = false;
            if (room.Header.Height > 0)
            {
                gdi.RoomChanged(room);
                gdi.DrawBitmap(room.Image, screen, new Point(), room.Header.Width, room.Header.Height, 0, numStrips, room.Header.Width, 0, true);

                using (var bmpRoom = ToBitmap(room, screen))
                {
                    bmpRoom.Save(name + ".png");
                }
            }

            DumpZPlanes(room, name);
        }
Beispiel #10
0
        internal void StartScene(byte room, Actor a = null, int objectNr = 0)
        {
            StopTalk();

            FadeOut(_switchRoomEffect2);
            _newEffect = _switchRoomEffect;

            if (CurrentScript != 0xFF)
            {
                if (_slots[CurrentScript].Where == WhereIsObject.Room || _slots[CurrentScript].Where == WhereIsObject.FLObject)
                {
                    //nukeArrays(CurrentScript);
                    CurrentScript = 0xFF;
                }
                else if (_slots[CurrentScript].Where == WhereIsObject.Local)
                {
                    //if (slots[CurrentScript].cutsceneOverride && _game.version >= 5)
                    //    error("Script %d stopped with active cutscene/override in exit", slots[CurrentScript].number);

                    //nukeArrays(CurrentScript);
                    CurrentScript = 0xFF;
                }
            }

            if (VariableNewRoom.HasValue)
                _variables[VariableNewRoom.Value] = room;

            RunExitScript();

            KillScriptsAndResources();

            if (_game.Version >= 4)
            {
                StopCycle(0);
            }

            for (var i = 1; i < Actors.Length; i++)
            {
                Actors[i].Hide();
            }

            if (Game.Version >= 7)
            {
                // Set the shadow palette(s) to all black. This fixes
                // bug #795940, and actually makes some sense (after all,
                // shadows tend to be rather black, don't they? ;-)
                Array.Clear(_shadowPalette, 0, _shadowPalette.Length);
            }
            else
            {
                for (var i = 0; i < 256; i++)
                {
                    Gdi.RoomPalette[i] = (byte)i;
                    if (_shadowPalette != null)
                        _shadowPalette[i] = (byte)i;
                }

                if (Game.Version < 5)
                {
                    SetDirtyColors(0, 255);
                }
            }

            Variables[VariableRoom.Value] = room;
            _fullRedraw = true;

            _currentRoom = room;

            if (room >= 0x80 && Game.Version < 7)
                _roomResource = _resourceMapper[room & 0x7F];
            else
                _roomResource = room;

            if (VariableRoomResource.HasValue)
                Variables[VariableRoomResource.Value] = _roomResource;

            if (room != 0)
                ResourceManager.LoadRoom(room);

            if (room != 0 && _game.Version == 5 && room == _roomResource)
                Variables[VariableRoomFlag.Value] = 1;

            ClearRoomObjects();

            if (_currentRoom == 0)
            {
                if (roomData != null)
                {
                    _ignoreEntryExitScript = true;
                    roomData.ExitScript.Data = new byte[0];
                    //roomData.Objects.Clear();
                }
                return;
            }

            roomData = _resManager.GetRoom(_roomResource);
            _ignoreEntryExitScript = false;
            if (roomData.HasPalette)
            {
                SetCurrentPalette(0);
            }

            Gdi.NumZBuffer = GetNumZBuffers();

            Gdi.TransparentColor = roomData.TransparentColor;
            ResetRoomSubBlocks();
            ResetRoomObjects();
            _drawingObjects.Clear();

            if (Game.Version >= 7)
            {
                // Resize main virtual screen in V7 games. This is necessary
                // because in V7, rooms may be higher than one screen, so we have
                // to accomodate for that.
                _mainVirtScreen = new VirtScreen(MainVirtScreen.TopLine, ScreenWidth, roomData.Header.Height - MainVirtScreen.TopLine, MainVirtScreen.PixelFormat, 2, true);
            }
            Gdi.SetMaskHeight(roomData.Header.Height);

            if (VariableRoomWidth.HasValue && VariableRoomHeight.HasValue)
            {
                Variables[VariableRoomWidth.Value] = roomData.Header.Width;
                Variables[VariableRoomHeight.Value] = roomData.Header.Height;
            }

            if (VariableCameraMinX.HasValue)
            {
                _variables[VariableCameraMinX.Value] = ScreenWidth / 2;
            }
            if (VariableCameraMaxX.HasValue)
            {
                _variables[VariableCameraMaxX.Value] = roomData.Header.Width - (ScreenWidth / 2);
            }

            if (Game.Version >= 7)
            {
                Variables[VariableCameraMinY.Value] = ScreenHeight / 2;
                Variables[VariableCameraMaxY.Value] = roomData.Header.Height - (ScreenHeight / 2);
                SetCameraAt(new Point((ScreenWidth / 2), (ScreenHeight / 2)));
            }
            else
            {
                _camera.Mode = CameraMode.Normal;
                _camera.CurrentPosition.X = _camera.DestinationPosition.X = (ScreenWidth / 2);
                _camera.CurrentPosition.Y = _camera.DestinationPosition.Y = (ScreenHeight / 2);
            }

            if (_roomResource == 0)
                return;

            Gdi.ClearGfxUsageBits();

            if (_game.Version >= 5 && a != null)
            {
                var where = GetWhereIsObject(objectNr);
                if (where != WhereIsObject.Room && where != WhereIsObject.FLObject)
                    throw new NotSupportedException(string.Format("StartScene: Object {0} is not in room {1}", objectNr, _currentRoom));

                Point pos;
                int dir;
                GetObjectXYPos(objectNr, out pos, out dir);
                a.PutActor(pos, _currentRoom);
                a.SetDirection(dir + 180);
                a.StopActorMoving();

                if (Game.GameId == Scumm.IO.GameId.SamNMax)
                {
                    Camera.CurrentPosition.X = Camera.DestinationPosition.X = a.Position.X;
                    SetCameraAt(a.Position);
                }
            }

            ShowActors();

            EgoPositioned = false;

            TownsResetPalCycleFields();

            RunEntryScript();

            if (Game.Version >= 1 && Game.Version <= 2)
            {
                RunScript(5, false, false, new int[0]);
            }
            else if ((Game.Version >= 5) && (Game.Version <= 6))
            {
                if (a != null && !EgoPositioned)
                {
                    var pos = GetObjectXYPos(objectNr);
                    a.PutActor(pos, _currentRoom);
                    a.Moving = 0;
                }
            }
            else if (_game.Version >= 7)
            {
                if (Camera.ActorToFollow != 0)
                {
                    a = Actors[Camera.ActorToFollow];
                    SetCameraAt(a.Position);
                }
            }

            _doEffect = true;

            // Hint the backend about the virtual keyboard during copy protection screens
            if (_game.GameId == GameId.Monkey2)
            {
                if (room == 108)
                    _inputManager.ShowVirtualKeyboard();
                else
                    _inputManager.HideVirtualKeyboard();
            }
            else if (_game.GameId == GameId.Monkey1 && _game.Variant == "ega")
            {   // this is my estimation that the room code is 90 (untested)
                if (room == 90)
                    _inputManager.ShowVirtualKeyboard();
                else
                    _inputManager.HideVirtualKeyboard();
            }
        }
Beispiel #11
0
        void PrintCharIntern(byte[] fontPtr, int charPos, int origWidth, int origHeight, int width, int height, VirtScreen vs, bool ignoreCharsetMask)
        {
            int drawTop = Top - vs.TopLine;

            PixelNavigator?back = null;
            PixelNavigator dstPtr;
            Surface        dstSurface;

            if ((ignoreCharsetMask || !vs.HasTwoBuffers))
            {
                dstSurface = vs.Surfaces[0];
                dstPtr     = new PixelNavigator(vs.Surfaces[0]);
                dstPtr.GoTo(vs.XStart + Left, drawTop);
            }
            else
            {
                dstSurface = Vm.TextSurface;
                dstPtr     = new PixelNavigator(dstSurface);
                dstPtr.GoTo(Left, Top - Vm.ScreenTop);
            }

            if (BlitAlso && vs.HasTwoBuffers)
            {
                back       = dstPtr;
                dstSurface = vs.Surfaces[0];
                dstPtr     = new PixelNavigator(dstSurface);
                dstPtr.GoTo(vs.XStart + Left, drawTop);
            }

            if (!ignoreCharsetMask && vs.HasTwoBuffers)
            {
                drawTop = Top - Vm.ScreenTop;
            }

            DrawBitsN(dstSurface, dstPtr, fontPtr, charPos, fontPtr[_fontPos], drawTop, origWidth, origHeight);

            if (BlitAlso && vs.HasTwoBuffers)
            {
                // FIXME: Revisiting this code, I think the _blitAlso mode is likely broken
                // right now -- we are copying stuff from "dstPtr" to "back", but "dstPtr" really
                // only conatains charset data...
                // One way to fix this: don't copy etc.; rather simply render the char twice,
                // once to each of the two buffers. That should hypothetically yield
                // identical results, though I didn't try it and right now I don't know
                // any spots where I can test this...
                if (!ignoreCharsetMask)
                {
                    throw new NotSupportedException("This might be broken -- please report where you encountered this to Fingolfin");
                }

                // Perform some clipping
                int w = Math.Min(width, dstSurface.Width - Left);
                int h = Math.Min(height, dstSurface.Height - drawTop);
                if (Left < 0)
                {
                    w += Left;
                    back.Value.OffsetX(-Left);
                    dstPtr.OffsetX(-Left);
                }
                if (drawTop < 0)
                {
                    h += drawTop;
                    back.Value.OffsetY(-drawTop);
                    dstPtr.OffsetY(-drawTop);
                }

                // Blit the image data
                if (w > 0)
                {
                    while (h-- > 0)
                    {
                        for (int i = 0; i < w; i++)
                        {
                            back.Value.Write(dstPtr.Read());
                            back.Value.OffsetX(1);
                            dstPtr.OffsetX(1);
                        }
                        back.Value.Offset(-w, 1);
                        dstPtr.Offset(-w, 1);
                    }
                }
            }
        }
        public int DrawCostume(VirtScreen vs, int numStrips, Actor actor, bool drawToBackBuf)
        {
            var pixelsNavigator = new PixelNavigator(vs.Surfaces[drawToBackBuf ? 1 : 0]);
            pixelsNavigator.OffsetX(vs.XStart);

            ActorX += (vs.XStart & 7);
            _w = vs.Width;
            _h = vs.Height;
            pixelsNavigator.OffsetX(-(vs.XStart & 7));
            startNav = new PixelNavigator(pixelsNavigator);

            if (_vm.Game.Version <= 1)
            {
                _xmove = 0;
                _ymove = 0;
            }
            else if (_vm.Game.IsOldBundle)
            {
                _xmove = -72;
                _ymove = -100;
            }
            else
            {
                _xmove = _ymove = 0;
            }

            int result = 0;
            for (int i = 0; i < 16; i++)
                result |= DrawLimb(actor, i);
            return result;
        }
Beispiel #13
0
        protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                               Point p, int width, int height,
                               int stripnr, int numstrip)
        {
            var ptr = img.Data;
            //
            // Since V3, all graphics data was encoded in strips, which is very efficient
            // for redrawing only parts of the screen. However, V2 is different: here
            // the whole graphics are encoded as one big chunk. That makes it rather
            // difficult to draw only parts of a room/object. We handle the V2 graphics
            // differently from all other (newer) graphic formats for this reason.
            //
            var table = (_objectMode ? null : _roomStrips);
            int left = (stripnr * 8);
            int right = left + (numstrip * 8);
            PixelNavigator navDst;
            var srcOffset = 0;
            byte color, data = 0;
            int run;
            bool dither = false;
            byte[] dither_table = new byte[128];
            var ditherOffset = 0;
            int theX, theY, maxX;

            var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0];
            navDst = new PixelNavigator(surface);
            navDst.GoTo(p.X * 8, p.Y);

            var mask_ptr = GetMaskBuffer(p.X, p.Y, 1);

            if (table != null)
            {
                run = table.run[stripnr];
                color = (byte)table.color[stripnr];
                srcOffset = table.offsets[stripnr];
                theX = left;
                maxX = right;
            }
            else
            {
                run = 1;
                color = 0;
                srcOffset = 0;
                theX = 0;
                maxX = width;
            }

            // Decode and draw the image data.
            Debug.Assert(height <= 128);
            for (; theX < maxX; theX++)
            {
                ditherOffset = 0;
                for (theY = 0; theY < height; theY++)
                {
                    if (--run == 0)
                    {
                        data = ptr[srcOffset++];
                        if ((data & 0x80) != 0)
                        {
                            run = data & 0x7f;
                            dither = true;
                        }
                        else
                        {
                            run = data >> 4;
                            dither = false;
                        }
                        color = RoomPalette[data & 0x0f];
                        if (run == 0)
                        {
                            run = ptr[srcOffset++];
                        }
                    }
                    if (!dither)
                    {
                        dither_table[ditherOffset] = color;
                    }
                    if (left <= theX && theX < right)
                    {
                        navDst.Write(dither_table[ditherOffset++]);
                        navDst.OffsetY(1);
                    }
                }
                if (left <= theX && theX < right)
                {
                    navDst.Offset(1, -height);
                }
            }

            // Draw mask (zplane) data
            theY = 0;

            if (table != null)
            {
                srcOffset = table.zoffsets[stripnr];
                run = table.zrun[stripnr];
                theX = left;
            }
            else
            {
                run = ptr[srcOffset++];
                theX = 0;
            }
            while (theX < right)
            {
                byte runFlag = (byte)(run & 0x80);
                if (runFlag != 0)
                {
                    run &= 0x7f;
                    data = ptr[srcOffset++];
                }
                do
                {
                    if (runFlag == 0)
                        data = ptr[srcOffset++];

                    if (left <= theX)
                    {
                        mask_ptr.Write(data);
                        mask_ptr.OffsetY(1);
                    }
                    theY++;
                    if (theY >= height)
                    {
                        if (left <= theX)
                        {
                            mask_ptr.Offset(1, -height);
                        }
                        theY = 0;
                        theX += 8;
                        if (theX >= right)
                            break;
                    }
                } while ((--run) != 0);
                run = ptr[srcOffset++];
            }
        }
Beispiel #14
0
 static bool VirtScreenContains(VirtScreen vs, int y)
 {
     return (y >= vs.TopLine && y < vs.TopLine + vs.Height);
 }
Beispiel #15
0
 internal void MarkRectAsDirty(VirtScreen vs, Rect r, int dirtybit = 0)
 {
     MarkRectAsDirty(vs, r.Left, r.Right, r.Top, r.Bottom, dirtybit);
 }
Beispiel #16
0
        /// <summary>
        /// Blit the specified rectangle from the given virtual screen to the display.
        /// Note: t and b are in *virtual screen* coordinates, while x is relative to
        /// the *real screen*. This is due to the way tdirty/vdirty work: they are
        /// arrays which map 'strips' (sections of the real screen) to dirty areas as
        /// specified by top/bottom coordinate in the virtual screen.
        /// </summary>
        /// <param name="vs"></param>
        /// <param name="x"></param>
        /// <param name="width"></param>
        /// <param name="top"></param>
        /// <param name="bottom"></param>
        void DrawStripToScreen(VirtScreen vs, int x, int width, int top, int bottom)
        {
            // Short-circuit if nothing has to be drawn
            if (bottom <= top || top >= vs.Height)
                return;

            // Perform some clipping
            if (width > vs.Width - x)
                width = vs.Width - x;
            if (top < ScreenTop)
                top = ScreenTop;
            if (bottom > ScreenTop + ScreenHeight)
                bottom = ScreenTop + ScreenHeight;

            // Convert the vertical coordinates to real screen coords
            int y = vs.TopLine + top - ScreenTop;
            int height = bottom - top;

            if (width <= 0 || height <= 0)
                return;

            byte[] src;
            if (Game.Version < 7)
            {
                if (Game.Platform == Platform.FMTowns)
                {
                    TownsDrawStripToScreen(vs, x, y, x, top, width, height);
                    return;
                }

                var srcNav = new PixelNavigator(vs.Surfaces[0]);
                srcNav.GoTo(vs.XStart + x, top);

                var compNav = new PixelNavigator(_composite);
                var txtNav = new PixelNavigator(_textSurface);
                int m = _textSurfaceMultiplier;
                txtNav.GoTo(x * m, y * m);

                var vsPitch = vs.Pitch - width * vs.BytesPerPixel;
                var textPitch = _textSurface.Pitch - width * m;

                for (int h = height * m; h > 0; --h)
                {
                    for (int w = width * m; w > 0; w--)
                    {
                        var temp = txtNav.Read();
                        int mask = temp ^ CharsetMaskTransparency;
                        mask = (((mask & 0x7f) + 0x7f) | mask) & 0x80;
                        mask = ((mask >> 7) + 0x7f) ^ 0x80;

                        var dst = ((temp ^ srcNav.Read()) & mask) ^ temp;
                        compNav.Write((byte)dst);

                        srcNav.OffsetX(1);
                        txtNav.OffsetX(1);
                        compNav.OffsetX(1);
                    }

                    srcNav.OffsetX(vsPitch);
                    txtNav.OffsetX(textPitch);
                }

                src = _composite.Pixels;
            }
            else
            {
                src = new byte[width * height * vs.BytesPerPixel];
                var srcNav = new PixelNavigator(vs.Surfaces[0]);
                srcNav.GoTo(vs.XStart + x, top);
                for (int h = 0; h < height; h++)
                {
                    for (int w = 0; w < width; w++)
                    {
                        src[h * width + w] = srcNav.Read();
                        srcNav.OffsetX(1);
                    }
                    srcNav.Offset(-width, 1);
                }
            }

            // Finally blit the whole thing to the screen
            _gfxManager.CopyRectToScreen(src, width * vs.BytesPerPixel, x, y, width, height);
        }
Beispiel #17
0
 protected virtual void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                                          Point p, int width, int height,
                                          int stripnr, int numstrip)
 {
 }
Beispiel #18
0
        public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn)
        {
            var x = p.X;
            var y = p.Y;
            if ((_vm.TownsPaletteFlags & 2) != 0)
            {
                int cx = (x - _vm.ScreenStartStrip) << 3;
                Gdi.Fill(_vm.TextSurface, 
                    new Rect(cx * _vm.TextSurfaceMultiplier, y * _vm.TextSurfaceMultiplier, 
                        (cx + width - 1) * _vm.TextSurfaceMultiplier, (y + height - 1) * _vm.TextSurfaceMultiplier), 0);
            }

            _objectMode = flags.HasFlag(DrawBitmaps.ObjectMode);
            PrepareDrawBitmap(img, vs, p, width, height, stripnr, numstrip);

            int sx = x - vs.XStart / 8;
            if (sx < 0)
            {
                numstrip -= -sx;
                x += -sx;
                stripnr += -sx;
                sx = 0;
            }

            // Compute the number of strips we have to iterate over.
            // TODO/FIXME: The computation of its initial value looks very fishy.
            // It was added as a kind of hack to fix some corner cases, but it compares
            // the room width to the virtual screen width; but the former should always
            // be bigger than the latter (except for MM NES, maybe)... strange
            int limit = Math.Max(roomWidth, vs.Width) / 8 - x;
            if (limit > numstrip)
                limit = numstrip;
            if (limit > NumStrips - sx)
                limit = NumStrips - sx;

            for (int k = 0; k < limit; ++k, ++stripnr, ++sx, ++x)
            {
                if (y < vs.TDirty[sx])
                    vs.TDirty[sx] = y;

                if (y + height > vs.BDirty[sx])
                    vs.BDirty[sx] = y + height;

                // In the case of a double buffered virtual screen, we draw to
                // the backbuffer, otherwise to the primary surface memory.
                var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0];
                var navDst = new PixelNavigator(surface);
                navDst.GoTo(x * 8, y);

                bool transpStrip;
                using (var smapReader = new BinaryReader(new MemoryStream(img.Data)))
                {
                    transpStrip = DrawStrip(navDst, width, height, stripnr, smapReader);
                }

                // COMI and HE games only uses flag value
                if (game.Version == 8)
                    transpStrip = true;

                if (vs.HasTwoBuffers)
                {
                    var navFrontBuf = new PixelNavigator(vs.Surfaces[0]);
                    navFrontBuf.GoTo(x * 8, y);
                    if (isLightOn)
                        Copy8Col(navFrontBuf, navDst, height);
                    else
                        Clear8Col(navFrontBuf, height);
                }

                DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags);
            }
        }
Beispiel #19
0
 public void DrawBitmap(ImageData img, VirtScreen vs, int x, int y, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags)
 {
     // Check whether lights are turned on or not
     var lightsOn = _vm.IsLightOn();
     DrawBitmap(img, vs, new Point(x, y), width, height, stripnr, numstrip, roomWidth, flags, lightsOn);
 }
Beispiel #20
0
        protected void TownsDrawStripToScreen(VirtScreen vs, int dstX, int dstY, int srcX, int srcY, int width, int height)
        {
            if (width <= 0 || height <= 0)
                return;

            int m = _textSurfaceMultiplier;

            var src1 = new PixelNavigator(vs.Surfaces[0]);
            src1.GoTo(vs.XStart + srcX, srcY);
            var src2 = new PixelNavigator(_textSurface);
            src2.GoTo(srcX * m, (srcY + vs.TopLine - ScreenTop) * m);
            var dst1 = new PixelNavigator(_townsScreen.GetLayerPixels(0, dstX, dstY).Value);
            var dst2 = new PixelNavigator(_townsScreen.GetLayerPixels(1, dstX * m, dstY * m).Value);

            int dp1 = _townsScreen.GetLayerPitch(0) - width * _townsScreen.GetLayerBpp(0);
            int dp2 = _townsScreen.GetLayerPitch(1) - width * m * _townsScreen.GetLayerBpp(1);
            int sp1 = vs.Pitch - (width * Surface.GetBytesPerPixel(vs.PixelFormat));
            int sp2 = _textSurface.Pitch - width * m;

            if (vs == MainVirtScreen || Game.GameId == GameId.Indy3 || Game.GameId == GameId.Zak)
            {
                for (int h = 0; h < height; ++h)
                {
                    if (Surface.GetBytesPerPixel(_gfxManager.PixelFormat) == 2)
                    {
                        for (int w = 0; w < width; ++w)
                        {
                            dst1.WriteUInt16(_16BitPalette[src1.Read()]);
                            src1.OffsetX(1);
                            dst1.OffsetX(1);
                        }

                        src1.OffsetX(sp1 / src1.BytesByPixel);
                        dst1.OffsetX(dp1 / dst1.BytesByPixel);
                    }
                    else
                    {
                        for (int i = 0; i < width; i++)
                        {
                            dst1.Write(src1.Read());
                            dst1.OffsetX(1);
                            src1.OffsetX(1);
                        }
                    }

                    for (int sH = 0; sH < m; ++sH)
                    {
                        for (int i = 0; i < width * m; i++)
                        {
                            dst2.Write(src2.Read());
                            src2.OffsetX(1);
                            dst2.OffsetX(1);
                        }
                        src2.OffsetX(_textSurface.Width - (width * m));
                        dst2.OffsetX(dst2.Width - (width * m));
                    }
                }
            }
            else
            {
                dst1 = new PixelNavigator(dst2);
                for (int h = 0; h < height; ++h)
                {
                    for (int w = 0; w < width; ++w)
                    {
                        var t = (src1.Read()) & 0x0f;
                        src1.OffsetX(1);
                        for (int i = 0; i < m; i++)
                        {
                            dst1.Write((byte)((t << 4) | t));
                            dst1.OffsetX(1);
                        }
                    }

                    dst1 = new PixelNavigator(dst2);
                    var src3 = new PixelNavigator(src2);

                    if (m == 2)
                    {
                        dst2.OffsetY(1);
                        src3.OffsetY(1);
                    }

                    for (int w = 0; w < width * m; ++w)
                    {
                        dst2.Write((byte)(src3.Read() | dst1.Read() & _townsLayer2Mask[src3.Read()]));
                        dst2.OffsetX(1);
                        dst1.Write((byte)(src2.Read() | dst1.Read() & _townsLayer2Mask[src2.Read()]));
                        src2.OffsetX(1);
                        src3.OffsetX(1);
                        dst1.OffsetX(1);
                    }

                    src1.OffsetX(sp1 / src1.BytesByPixel);
                    src2 = new PixelNavigator(src3);
                    src2.OffsetX(sp2 / src2.BytesByPixel);
                    dst1 = new PixelNavigator(dst2);
                    dst1.OffsetX(dp2 / dst1.BytesByPixel);
                    dst2.OffsetX(dp2 / dst2.BytesByPixel);
                }
            }

            _townsScreen.AddDirtyRect(dstX * m, dstY * m, width * m, height * m);
        }
Beispiel #21
0
        public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn)
        {
            var x = p.X;
            var y = p.Y;

            if ((_vm.TownsPaletteFlags & 2) != 0)
            {
                int cx = (x - _vm.ScreenStartStrip) << 3;
                Gdi.Fill(_vm.TextSurface,
                         new Rect(cx * _vm.TextSurfaceMultiplier, y * _vm.TextSurfaceMultiplier,
                                  (cx + width - 1) * _vm.TextSurfaceMultiplier, (y + height - 1) * _vm.TextSurfaceMultiplier), 0);
            }

            _objectMode = flags.HasFlag(DrawBitmaps.ObjectMode);
            PrepareDrawBitmap(img, vs, p, width, height, stripnr, numstrip);

            int sx = x - vs.XStart / 8;

            if (sx < 0)
            {
                numstrip -= -sx;
                x        += -sx;
                stripnr  += -sx;
                sx        = 0;
            }

            // Compute the number of strips we have to iterate over.
            // TODO/FIXME: The computation of its initial value looks very fishy.
            // It was added as a kind of hack to fix some corner cases, but it compares
            // the room width to the virtual screen width; but the former should always
            // be bigger than the latter (except for MM NES, maybe)... strange
            int limit = Math.Max(roomWidth, vs.Width) / 8 - x;

            if (limit > numstrip)
            {
                limit = numstrip;
            }
            if (limit > NumStrips - sx)
            {
                limit = NumStrips - sx;
            }

            for (int k = 0; k < limit; ++k, ++stripnr, ++sx, ++x)
            {
                if (y < vs.TDirty[sx])
                {
                    vs.TDirty[sx] = y;
                }

                if (y + height > vs.BDirty[sx])
                {
                    vs.BDirty[sx] = y + height;
                }

                // In the case of a double buffered virtual screen, we draw to
                // the backbuffer, otherwise to the primary surface memory.
                var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0];
                var navDst  = new PixelNavigator(surface);
                navDst.GoTo(x * 8, y);

                bool transpStrip;
                using (var smapReader = new BinaryReader(new MemoryStream(img.Data)))
                {
                    transpStrip = DrawStrip(navDst, width, height, stripnr, smapReader);
                }

                // COMI and HE games only uses flag value
                if (game.Version == 8)
                {
                    transpStrip = true;
                }

                if (vs.HasTwoBuffers)
                {
                    var navFrontBuf = new PixelNavigator(vs.Surfaces[0]);
                    navFrontBuf.GoTo(x * 8, y);
                    if (isLightOn)
                    {
                        Copy8Col(navFrontBuf, navDst, height);
                    }
                    else
                    {
                        Clear8Col(navFrontBuf, height);
                    }
                }

                DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags);
            }
        }
Beispiel #22
0
        internal void MarkRectAsDirty(VirtScreen vs, int left, int right, int top, int bottom, int dirtybit = 0)
        {
            int lp, rp;

            if (left > right || top > bottom)
                return;
            if (top > vs.Height || bottom < 0)
                return;

            if (top < 0)
                top = 0;
            if (bottom > vs.Height)
                bottom = vs.Height;

            if (vs == MainVirtScreen && dirtybit != 0)
            {
                lp = left / 8 + _screenStartStrip;
                if (lp < 0)
                    lp = 0;

                rp = (right + vs.XStart) / 8;
                if (_game.Version >= 7)
                {
                    if (rp > 409)
                        rp = 409;
                }
                else
                {
                    if (rp >= 200)
                        rp = 200;
                }
                for (; lp <= rp; lp++)
                    Gdi.SetGfxUsageBit(lp, dirtybit);
            }

            // The following code used to be in the separate method setVirtscreenDirty
            lp = left / 8;
            rp = right / 8;

            if ((lp >= Gdi.NumStrips) || (rp < 0))
                return;
            if (lp < 0)
                lp = 0;
            if (rp >= Gdi.NumStrips)
                rp = Gdi.NumStrips - 1;

            while (lp <= rp)
            {
                if (top < vs.TDirty[lp])
                    vs.TDirty[lp] = top;
                if (bottom > vs.BDirty[lp])
                    vs.BDirty[lp] = bottom;
                lp++;
            }
        }
Beispiel #23
0
 protected virtual void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                                          Point p, int width, int height,
                                          int stripnr, int numstrip)
 {
 }
Beispiel #24
0
        public override void PrintChar(int chr, bool ignoreCharsetMask)
        {
            Rect shadow;

            Debug.Assert(_current != null);
            if (chr == '@')
            {
                return;
            }

            shadow.Left = Left;
            shadow.Top  = Top;

            if (FirstChar)
            {
                Str.Left   = (shadow.Left >= 0) ? shadow.Left : 0;
                Str.Top    = (shadow.Top >= 0) ? shadow.Top : 0;
                Str.Right  = Str.Left;
                Str.Bottom = Str.Top;
                FirstChar  = false;
            }

            int width  = _current.GetCharWidth((char)chr);
            int height = _current.GetCharHeight((char)chr);

//            bool is2byte = chr >= 256 && _vm._useCJKMode;
//            if (is2byte)
//                width = _vm._2byteWidth;

            shadow.Right  = Left + width;
            shadow.Bottom = Top + height;

            Surface s;

            if (!ignoreCharsetMask)
            {
                HasMask    = true;
                TextScreen = Vm.MainVirtScreen;
            }

            int offsetX = 0;
            int drawTop = Top;

            if (ignoreCharsetMask)
            {
                VirtScreen vs = Vm.MainVirtScreen;
                s       = vs.Surfaces[0];
                offsetX = vs.XStart;
            }
            else
            {
                s        = Vm.TextSurface;
                drawTop -= Vm.ScreenTop;
            }

            var dst = new PixelNavigator(s);

            dst.GoTo(Left + offsetX, drawTop);

//            if (chr >= 256 && _vm._useCJKMode)
//                _current.draw2byte(s, chr, _left, drawTop, _color);
//            else
            _current.DrawChar(dst, (char)chr, Left, drawTop, Color);
            Vm.MarkRectAsDirty(Vm.MainVirtScreen, shadow);

            if (Str.Left > Left)
            {
                Str.Left = Left;
            }

            // Original keeps glyph width and character dimensions separately
//            if ((_vm._language == Common::ZH_TWN || _vm._language == Common::KO_KOR) && is2byte)
//                width++;

            Left += width;

            if (Str.Right < shadow.Right)
            {
                Str.Right = shadow.Right;
            }

            if (Str.Bottom < shadow.Bottom)
            {
                Str.Bottom = shadow.Bottom;
            }
        }
Beispiel #25
0
        protected void InitScreens(int b, int h)
        {
            if (_townsScreen != null)
            {
                if (_townsClearLayerFlag == 0 && MainVirtScreen != null && ((h - b) != MainVirtScreen.Height))
                    _townsScreen.ClearLayer(0);

                if (Game.GameId != GameId.Monkey1)
                {
                    Gdi.Fill(TextSurface,
                        new Rect(0, 0, _textSurface.Width * _textSurfaceMultiplier, _textSurface.Height * _textSurfaceMultiplier), 0);
                    _townsScreen.ClearLayer(1);
                }
            }

            var format = Game.Features.HasFlag(GameFeatures.Is16BitColor) ? PixelFormat.Rgb16 : PixelFormat.Indexed8;

            _mainVirtScreen = new VirtScreen(b, ScreenWidth, h - b, format, 2, true);
            _textVirtScreen = new VirtScreen(0, ScreenWidth, b, format, 1);
            _verbVirtScreen = new VirtScreen(h, ScreenWidth, ScreenHeight - h, format, 1);

            // Since the size of screen 3 is fixed, there is no need to reallocate
            // it if its size changed.
            // Not sure what it is good for, though. I think it may have been used
            // in pre-V7 for the games messages (like 'Pause', Yes/No dialogs,
            // version display, etc.). I don't know about V7, maybe the same is the
            // case there. If so, we could probably just remove it completely.
            if (_game.Version >= 7)
            {
                _unkVirtScreen = new VirtScreen((ScreenHeight / 2) - 10, ScreenWidth, 13, format, 1);
            }
            else
            {
                _unkVirtScreen = new VirtScreen(80, ScreenWidth, 13, format, 1);
            }

            _screenB = b;
            _screenH = h;

            Gdi.Init();
        }
Beispiel #26
0
        protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                                                  Point p, int width, int height,
                                                  int stripnr, int numstrip)
        {
            var ptr = img.Data;
            //
            // Since V3, all graphics data was encoded in strips, which is very efficient
            // for redrawing only parts of the screen. However, V2 is different: here
            // the whole graphics are encoded as one big chunk. That makes it rather
            // difficult to draw only parts of a room/object. We handle the V2 graphics
            // differently from all other (newer) graphic formats for this reason.
            //
            var            table = (_objectMode ? null : _roomStrips);
            int            left  = (stripnr * 8);
            int            right = left + (numstrip * 8);
            PixelNavigator navDst;
            var            srcOffset = 0;
            byte           color, data = 0;
            int            run;
            bool           dither = false;

            byte[] dither_table = new byte[128];
            var    ditherOffset = 0;
            int    theX, theY, maxX;

            var surface = vs.HasTwoBuffers ? vs.Surfaces[1] : vs.Surfaces[0];

            navDst = new PixelNavigator(surface);
            navDst.GoTo(p.X * 8, p.Y);

            var mask_ptr = GetMaskBuffer(p.X, p.Y, 1);

            if (table != null)
            {
                run       = table.run[stripnr];
                color     = (byte)table.color[stripnr];
                srcOffset = table.offsets[stripnr];
                theX      = left;
                maxX      = right;
            }
            else
            {
                run       = 1;
                color     = 0;
                srcOffset = 0;
                theX      = 0;
                maxX      = width;
            }

            // Decode and draw the image data.
            Debug.Assert(height <= 128);
            for (; theX < maxX; theX++)
            {
                ditherOffset = 0;
                for (theY = 0; theY < height; theY++)
                {
                    if (--run == 0)
                    {
                        data = ptr[srcOffset++];
                        if ((data & 0x80) != 0)
                        {
                            run    = data & 0x7f;
                            dither = true;
                        }
                        else
                        {
                            run    = data >> 4;
                            dither = false;
                        }
                        color = RoomPalette[data & 0x0f];
                        if (run == 0)
                        {
                            run = ptr[srcOffset++];
                        }
                    }
                    if (!dither)
                    {
                        dither_table[ditherOffset] = color;
                    }
                    if (left <= theX && theX < right)
                    {
                        navDst.Write(dither_table[ditherOffset++]);
                        navDst.OffsetY(1);
                    }
                }
                if (left <= theX && theX < right)
                {
                    navDst.Offset(1, -height);
                }
            }

            // Draw mask (zplane) data
            theY = 0;

            if (table != null)
            {
                srcOffset = table.zoffsets[stripnr];
                run       = table.zrun[stripnr];
                theX      = left;
            }
            else
            {
                run  = ptr[srcOffset++];
                theX = 0;
            }
            while (theX < right)
            {
                byte runFlag = (byte)(run & 0x80);
                if (runFlag != 0)
                {
                    run &= 0x7f;
                    data = ptr[srcOffset++];
                }
                do
                {
                    if (runFlag == 0)
                    {
                        data = ptr[srcOffset++];
                    }

                    if (left <= theX)
                    {
                        mask_ptr.Write(data);
                        mask_ptr.OffsetY(1);
                    }
                    theY++;
                    if (theY >= height)
                    {
                        if (left <= theX)
                        {
                            mask_ptr.Offset(1, -height);
                        }
                        theY  = 0;
                        theX += 8;
                        if (theX >= right)
                        {
                            break;
                        }
                    }
                } while ((--run) != 0);
                run = ptr[srcOffset++];
            }
        }
Beispiel #27
0
 System.Drawing.Color ToColor(Room room, VirtScreen screen, int x, int y)
 {
     var index = screen.Surfaces[0].Pixels[y * screen.Width + x];
     var c = Game.Features.HasFlag(GameFeatures.SixteenColors) ?
         Palette.Cga.Colors[index] : room.Palette.Colors[index];
     return System.Drawing.Color.FromArgb(c.R, c.G, c.B);
 }
        void PrintCharIntern(byte[] fontPtr, int charPos, int origWidth, int origHeight, int width, int height, VirtScreen vs, bool ignoreCharsetMask)
        {
            int drawTop = Top - vs.TopLine;

            PixelNavigator? back = null;
            PixelNavigator dstPtr;
            Surface dstSurface;
            if ((ignoreCharsetMask || !vs.HasTwoBuffers))
            {
                dstSurface = vs.Surfaces[0];
                dstPtr = new PixelNavigator(vs.Surfaces[0]);
                dstPtr.GoTo(vs.XStart + Left, drawTop);
            }
            else
            {
                dstSurface = Vm.TextSurface;
                dstPtr = new PixelNavigator(dstSurface);
                dstPtr.GoTo(Left, Top - Vm.ScreenTop);
            }

            if (BlitAlso && vs.HasTwoBuffers)
            {
                back = dstPtr;
                dstSurface = vs.Surfaces[0];
                dstPtr = new PixelNavigator(dstSurface);
                dstPtr.GoTo(vs.XStart + Left, drawTop);
            }

            if (!ignoreCharsetMask && vs.HasTwoBuffers)
            {
                drawTop = Top - Vm.ScreenTop;
            }

            DrawBitsN(dstSurface, dstPtr, fontPtr, charPos, fontPtr[_fontPos], drawTop, origWidth, origHeight);

            if (BlitAlso && vs.HasTwoBuffers)
            {
                // FIXME: Revisiting this code, I think the _blitAlso mode is likely broken
                // right now -- we are copying stuff from "dstPtr" to "back", but "dstPtr" really
                // only conatains charset data...
                // One way to fix this: don't copy etc.; rather simply render the char twice,
                // once to each of the two buffers. That should hypothetically yield
                // identical results, though I didn't try it and right now I don't know
                // any spots where I can test this...
                if (!ignoreCharsetMask)
                    throw new NotSupportedException("This might be broken -- please report where you encountered this to Fingolfin");

                // Perform some clipping
                int w = Math.Min(width, dstSurface.Width - Left);
                int h = Math.Min(height, dstSurface.Height - drawTop);
                if (Left < 0)
                {
                    w += Left;
                    back.Value.OffsetX(-Left);
                    dstPtr.OffsetX(-Left);
                }
                if (drawTop < 0)
                {
                    h += drawTop;
                    back.Value.OffsetY(-drawTop);
                    dstPtr.OffsetY(-drawTop);
                }

                // Blit the image data
                if (w > 0)
                {
                    while (h-- > 0)
                    {
                        for (int i = 0; i < w; i++)
                        {
                            back.Value.Write(dstPtr.Read());
                            back.Value.OffsetX(1);
                            dstPtr.OffsetX(1);
                        }
                        back.Value.Offset(-w, 1);
                        dstPtr.Offset(-w, 1);
                    }
                }

            }
        }
Beispiel #29
0
 System.Drawing.Color ToColor(byte[] pixels, Palette palette, VirtScreen screen, int x, int y)
 {
     var index = pixels[y * screen.Width + x];
     var c = palette.Colors[index];
     return System.Drawing.Color.FromArgb(c.R, c.G, c.B);
 }
Beispiel #30
0
 static byte[] Capture(VirtScreen screen, int x, int y, int w, int h)
 {
     var pixels = new byte[w * h];
     var nav = new PixelNavigator(screen.Surfaces[0]);
     nav.GoTo(x, y);
     for (int height = 0; height < h; height++)
     {
         for (int width = 0; width < w; width++)
         {
             pixels[height * w + width] = nav.Read();
             nav.OffsetX(1);
         }
         nav.Offset(-w, 1);
     }
     return pixels;
 }
Beispiel #31
0
        System.Drawing.Bitmap ToBitmap(Room room, VirtScreen screen)
        {
            var bmp = new System.Drawing.Bitmap(screen.Width, screen.Height);
//            DitherCGA(screen.Surfaces[0].Pixels, screen.Surfaces[0].Pitch, 0, 0, screen.Width, screen.Height);
            var palette = Game.Features.HasFlag(GameFeatures.SixteenColors) ? Palette.Ega : room.Palette;
            for (int x = 0; x < screen.Width; x++)
            {
                for (int y = 0; y < screen.Height; y++)
                {
                    bmp.SetPixel(x, y, ToColor(screen.Surfaces[0].Pixels, palette, screen, x, y));
                }
            }
            return bmp;
        }