Esempio n. 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);
        }
Esempio n. 2
0
        void DrawStripV1Object(PixelNavigator navDst, int stripnr, int width, int height)
        {
            int charIdx;

            height /= 8;
            width  /= 8;
            for (var y = 0; y < height; y++)
            {
                _v1.Colors[3] = (byte)(objectMap[(y + height) * width + stripnr] & 7);
                charIdx       = objectMap[y * width + stripnr] * 8;
                for (var i = 0; i < 8; i++)
                {
                    byte c     = _v1.CharMap[charIdx + i];
                    var  color = _v1.Colors[(c >> 6) & 3];
                    navDst.Write(0, color);
                    navDst.Write(1, color);
                    color = _v1.Colors[(c >> 4) & 3];
                    navDst.Write(2, color);
                    navDst.Write(3, color);
                    color = _v1.Colors[(c >> 2) & 3];
                    navDst.Write(4, color);
                    navDst.Write(5, color);
                    color = _v1.Colors[(c >> 0) & 3];
                    navDst.Write(6, color);
                    navDst.Write(7, color);
                    navDst.OffsetY(1);
                }
            }
        }
Esempio n. 3
0
        void DrawStripV1Background(PixelNavigator navDst, int stripnr, int height)
        {
            int charIdx;

            height /= 8;
            for (int y = 0; y < height; y++)
            {
                _v1.Colors[3] = (byte)(_v1.ColorMap[y + stripnr * height] & 7);
                // Check for room color change in V1 zak
                if (RoomPalette[0] == 255)
                {
                    _v1.Colors[2] = RoomPalette[2];
                    _v1.Colors[1] = RoomPalette[1];
                }

                charIdx = _v1.PicMap[y + stripnr * height] * 8;
                for (int i = 0; i < 8; i++)
                {
                    byte c     = _v1.CharMap[charIdx + i];
                    var  color = _v1.Colors[(c >> 6) & 3];
                    navDst.Write(0, color);
                    navDst.Write(1, color);
                    color = _v1.Colors[(c >> 4) & 3];
                    navDst.Write(2, color);
                    navDst.Write(3, color);
                    color = _v1.Colors[(c >> 2) & 3];
                    navDst.Write(4, color);
                    navDst.Write(5, color);
                    color = _v1.Colors[(c >> 0) & 3];
                    navDst.Write(6, color);
                    navDst.Write(7, color);
                    navDst.OffsetY(1);
                }
            }
        }
Esempio n. 4
0
        public PixelNavigator GetMaskBuffer(int x, int y, int i)
        {
            var nav = new PixelNavigator(maskBuffer[i], NumStrips, 1);

            nav.GoTo(x, y);
            return(nav);
        }
Esempio n. 5
0
        protected virtual void DrawBitsN(Surface s, PixelNavigator dst, System.Collections.Generic.IList <byte> src, int srcPos, byte bpp, int drawTop, int width, int height)
        {
            if (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8)
            {
                throw new ArgumentException("Invalid bpp", "bpp");
            }

            byte bits    = src[srcPos++];
            byte numbits = 8;
            var  cmap    = Vm.CharsetColorMap;

            for (int y = 0; y < height && y + drawTop < s.Height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int color = (bits >> (8 - bpp)) & 0xFF;

                    if (color != 0 && (y + drawTop >= 0))
                    {
                        dst.Write(cmap[color]);
                    }
                    dst.OffsetX(1);
                    bits   <<= bpp;
                    numbits -= bpp;
                    if (numbits == 0)
                    {
                        bits    = src[srcPos++];
                        numbits = 8;
                    }
                }
                dst.Offset(-width, 1);
            }
        }
Esempio n. 6
0
        void DrawStripRaw(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck)
        {
            int x;

            if (game.Features.HasFlag(GameFeatures.Old256))
            {
                int h = height;
                x = 8;
                while (true)
                {
                    navDst.Write(RoomPalette[src.ReadByte()]);
                    if (!NextRow(ref navDst, ref x, ref h, height))
                    {
                        return;
                    }
                }
            }
            do
            {
                for (x = 0; x < 8; x++)
                {
                    int color = src.ReadByte();
                    if (!transpCheck || color != TransparentColor)
                    {
                        navDst.OffsetX(x);
                        WriteRoomColor(navDst, color);
                        navDst.OffsetX(-x);
                    }
                }
                navDst.OffsetY(1);
            } while ((--height) != 0);
        }
Esempio n. 7
0
        void DrawStripV1Mask(PixelNavigator navDst, int stripnr, int width, int height)
        {
            int maskIdx;

            height /= 8;
            width  /= 8;
            for (var y = 0; y < height; y++)
            {
                if (_objectMode)
                {
                    maskIdx = objectMap[(y + 2 * height) * width + stripnr] * 8;
                }
                else
                {
                    maskIdx = _v1.MaskMap[y + stripnr * height] * 8;
                }
                for (var i = 0; i < 8; i++)
                {
                    byte c = _v1.MaskChar[maskIdx + i];

                    // V1/V0 masks are inverted compared to what ScummVM expects
                    navDst.Write((byte)(c ^ 0xFF));
                    navDst.OffsetY(1);
                }
            }
        }
Esempio n. 8
0
        static void DecompressMaskImg(PixelNavigator dst, Stream src, int height)
        {
            while (height != 0)
            {
                var b = (byte)src.ReadByte();

                if ((b & 0x80) != 0)
                {
                    b &= 0x7F;
                    var c = (byte)src.ReadByte();

                    do
                    {
                        dst.Write(c);
                        dst.OffsetY(1);
                        --height;
                    } while (--b != 0 && height != 0);
                }
                else
                {
                    do
                    {
                        dst.Write((byte)src.ReadByte());
                        dst.OffsetY(1);
                        --height;
                    } while (--b != 0 && height != 0);
                }
            }
        }
Esempio n. 9
0
        void DrawStripV1Background(PixelNavigator navDst, int stripnr, int height)
        {
            int charIdx;
            height /= 8;
            for (int y = 0; y < height; y++)
            {
                _v1.Colors[3] = (byte)(_v1.ColorMap[y + stripnr * height] & 7);
                // Check for room color change in V1 zak
                if (RoomPalette[0] == 255)
                {
                    _v1.Colors[2] = RoomPalette[2];
                    _v1.Colors[1] = RoomPalette[1];
                }

                charIdx = _v1.PicMap[y + stripnr * height] * 8;
                for (int i = 0; i < 8; i++)
                {
                    byte c = _v1.CharMap[charIdx + i];
                    var color = _v1.Colors[(c >> 6) & 3];
                    navDst.Write(0, color);
                    navDst.Write(1, color);
                    color = _v1.Colors[(c >> 4) & 3];
                    navDst.Write(2, color);
                    navDst.Write(3, color);
                    color = _v1.Colors[(c >> 2) & 3];
                    navDst.Write(4, color);
                    navDst.Write(5, color);
                    color = _v1.Colors[(c >> 0) & 3];
                    navDst.Write(6, color);
                    navDst.Write(7, color);
                    navDst.OffsetY(1);
                }
            }
        }
Esempio n. 10
0
        static void DecompressMaskImgOr(PixelNavigator dst, Stream src, int height)
        {
            byte b, c;

            while (height != 0)
            {
                b = (byte)src.ReadByte();

                if ((b & 0x80) != 0)
                {
                    b &= 0x7F;
                    c  = (byte)src.ReadByte();

                    do
                    {
                        dst.Write((byte)(dst.Read() | c));
                        dst.OffsetY(1);
                        --height;
                    } while ((--b != 0) && (height != 0));
                }
                else
                {
                    do
                    {
                        dst.Write((byte)(dst.Read() | src.ReadByte()));
                        dst.OffsetY(1);
                        --height;
                    } while ((--b != 0) && (height != 0));
                }
            }
        }
Esempio n. 11
0
        void UnkDecode10(PixelNavigator navDst, BinaryReader src, int height)
        {
            int h             = height;
            int numcolors     = src.ReadByte();
            var local_palette = src.ReadBytes(numcolors);

            int x = 8;

            while (true)
            {
                int color = src.ReadByte();
                if (color < numcolors)
                {
                    navDst.Write(RoomPalette[local_palette[color]]);
                    if (!NextRow(ref navDst, ref x, ref h, height))
                    {
                        return;
                    }
                }
                else
                {
                    int run = color - numcolors + 1;
                    color = src.ReadByte();
                    for (var i = 0; i < run; i++)
                    {
                        navDst.Write(RoomPalette[color]);
                        if (!NextRow(ref navDst, ref x, ref h, height))
                        {
                            return;
                        }
                    }
                }
            }
        }
Esempio n. 12
0
 void WriteRoomColor(PixelNavigator navDst, int color)
 {
     // As described in bug #1294513 "FOA/Amiga: Palette problem (Regression)"
     // the original AMIGA version of Indy4: The Fate of Atlantis allowed
     // overflowing of the palette index. To have the same result in our code,
     // we need to do an logical AND 0xFF here to keep the result in [0, 255].
     navDst.Write(RoomPalette[(color + paletteMod) & 0xFF]);
 }
Esempio n. 13
0
        public override void DrawChar(int chr, Surface s, int x, int y)
        {
            if (!PrepareDraw(chr))
            {
                return;
            }
            var pn = new PixelNavigator(s);

            pn.GoTo(x, y);
            DrawBitsN(s, pn, _fontPtr, _charPos, _fontPtr[_fontPos], y, _width, _height);
        }
Esempio n. 14
0
 public PixelNavigator(PixelNavigator navigator)
     : this()
 {
     _startOffset = navigator._offset;
     _offset      = _startOffset;
     _pixels      = navigator._pixels;
     Pitch        = navigator.Pitch;
     BytesByPixel = navigator.BytesByPixel;
     Width        = navigator.Width;
     Height       = navigator.Height;
 }
Esempio n. 15
0
 public PixelNavigator(PixelNavigator navigator)
     : this()
 {
     _startOffset = navigator._offset;
     _offset = _startOffset;
     _pixels = navigator._pixels;
     Pitch = navigator.Pitch;
     BytesByPixel = navigator.BytesByPixel;
     Width = navigator.Width;
     Height = navigator.Height;
 }
Esempio n. 16
0
 public static void BompApplyShadow0(byte[] lineBuffer, int linePos, PixelNavigator dst, int size)
 {
     while (size-- > 0)
     {
         byte tmp = lineBuffer[linePos++];
         if (tmp != 255)
         {
             dst.Write(tmp);
         }
         dst.OffsetX(1);
     }
 }
Esempio n. 17
0
 static void Clear8Col(PixelNavigator nav, int height)
 {
     do
     {
         for (int i = 0; i < 8; i++)
         {
             nav.Write(0);
             nav.OffsetX(1);
         }
         nav.Offset(-8, 1);
     } while ((--height) != 0);
 }
Esempio n. 18
0
 public static void Fill(PixelNavigator dst, ushort color, int width, int height)
 {
     for (int h = 0; h < height; h++)
     {
         for (int w = 0; w < width; w++)
         {
             dst.WriteUInt16(color);
             dst.OffsetX(1);
         }
         dst.Offset(-width, 1);
     }
 }
Esempio n. 19
0
        protected virtual bool DrawStrip(PixelNavigator navDst, int width, int height, int stripnr, BinaryReader smapReader)
        {
            // Do some input verification and make sure the strip/strip offset
            // are actually valid. Normally, this should never be a problem,
            // but if e.g. a savegame gets corrupted, we can easily get into
            // trouble here. See also bug #795214.
            long offset = -1;
            long smapLen;

            if (game.Features.HasFlag(GameFeatures.SixteenColors))
            {
                smapLen = smapReader.ReadInt16();
                if (stripnr * 2 + 2 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 2, SeekOrigin.Current);
                    offset = smapReader.ReadInt16();
                }
            }
            else if (game.Version < 5)
            {
                smapLen = smapReader.ReadInt32();
                if (stripnr * 4 + 4 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Current);
                    offset = smapReader.ReadInt32();
                }
            }
            else if (game.Version == 8)
            {
                smapLen = smapReader.BaseStream.Length;
                // Skip to the BSTR->WRAP->OFFS chunk
                smapReader.BaseStream.Seek(24, SeekOrigin.Current);
                if (stripnr * 4 + 8 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Current);
                    offset = 16 + smapReader.ReadUInt32();
                }
            }
            else
            {
                smapLen = smapReader.BaseStream.Length;
                if (stripnr * 4 + 8 < smapLen)
                {
                    smapReader.BaseStream.Seek(stripnr * 4, SeekOrigin.Begin);
                    offset = smapReader.ReadUInt32() - 8;
                }
            }

            ScummHelper.AssertRange(0, offset, smapLen - 1, "screen strip");
            smapReader.BaseStream.Seek(offset, SeekOrigin.Begin);

            return(DecompressBitmap(navDst, smapReader, height));
        }
Esempio n. 20
0
        public void ResetBackground(int top, int bottom, int strip)
        {
            var vs = _vm.MainVirtScreen;

            if (top < 0)
            {
                top = 0;
            }

            if (bottom > vs.Height)
            {
                bottom = vs.Height;
            }

            if (top >= bottom)
            {
                return;
            }

            if (strip < 0 || strip >= NumStrips)
            {
                throw new ArgumentOutOfRangeException("strip");
            }

            if (top < vs.TDirty[strip])
            {
                vs.TDirty[strip] = top;
            }

            if (bottom > vs.BDirty[strip])
            {
                vs.BDirty[strip] = bottom;
            }

            int numLinesToProcess = bottom - top;

            if (numLinesToProcess > 0)
            {
                var navDest = new PixelNavigator(vs.Surfaces[0]);
                navDest.GoTo(strip * 8 + vs.XStart, top);
                if (_vm.IsLightOn())
                {
                    var bgBakNav = new PixelNavigator(vs.Surfaces[1]);
                    bgBakNav.GoTo(strip * 8 + vs.XStart, top);
                    Copy8Col(navDest, bgBakNav, numLinesToProcess);
                }
                else
                {
                    Clear8Col(navDest, numLinesToProcess);
                }
            }
        }
Esempio n. 21
0
        protected override bool DrawStrip(PixelNavigator navDst, int width, int height, int stripnr, System.IO.BinaryReader smapReader)
        {
            if (_objectMode)
            {
                DrawStripV1Object(navDst, stripnr, width, height);
            }
            else
            {
                DrawStripV1Background(navDst, stripnr, height);
            }

            return false;
        }
Esempio n. 22
0
        protected override bool DrawStrip(PixelNavigator navDst, int width, int height, int stripnr, System.IO.BinaryReader smapReader)
        {
            if (_objectMode)
            {
                DrawStripV1Object(navDst, stripnr, width, height);
            }
            else
            {
                DrawStripV1Background(navDst, stripnr, height);
            }

            return(false);
        }
Esempio n. 23
0
        public PixelNavigator? GetLayerPixels(int layer, int x, int y)
        {
            if (layer < 0 || layer > 1)
                return null;

            var l = _layers[layer];
            if (!l.ready)
                return null;

            var pn = new PixelNavigator(l.pixels, l.pitch / l.bpp, l.bpp);
            pn.GoTo(x, y);
            return pn;
        }
Esempio n. 24
0
 static bool NextRow(ref PixelNavigator navDst, ref int x, ref int y, int height)
 {
     navDst.OffsetY(1);
     if (--y == 0)
     {
         if ((--x) == 0)
         {
             return(false);
         }
         navDst.Offset(1, -height);
         y = height;
     }
     return(true);
 }
Esempio n. 25
0
 static void Copy8Col(PixelNavigator navDst, PixelNavigator navSource, int height)
 {
     do
     {
         for (int i = 0; i < 8; i++)
         {
             navDst.Write(navSource.Read());
             navDst.OffsetX(1);
             navSource.OffsetX(1);
         }
         navDst.Offset(-8, 1);
         navSource.Offset(-8, 1);
     } while ((--height) != 0);
 }
Esempio n. 26
0
 public static void Blit(PixelNavigator dst, PixelNavigator src, int width, int height)
 {
     for (var h = 0; h < height; h++)
     {
         for (int w = 0; w < width; w++)
         {
             dst.Write(src.Read());
             src.OffsetX(1);
             dst.OffsetX(1);
         }
         src.Offset(-width, 1);
         dst.Offset(-width, 1);
     }
 }
Esempio n. 27
0
        void LINE(int c, int p, byte color, byte[] palette, PixelNavigator dst, PixelNavigator mask, int destX)
        {
            var pcolor = (color >> c) & 3;

            if (pcolor != 0)
            {
                if (!MASK_AT(p, mask, destX))
                {
                    dst.Write(p, palette[pcolor]);
                }
                if (!MASK_AT(p + 1, mask, destX))
                {
                    dst.Write(p + 1, palette[pcolor]);
                }
            }
        }
Esempio n. 28
0
        void Line(int c, int p, Codec1 v1, PixelNavigator?mask, PixelNavigator dst, byte color, byte[] palette)
        {
            var pcolor = (color >> c) & 3;

            if (pcolor != 0)
            {
                if (!MaskAt(p, v1, mask))
                {
                    dst.Write(p, palette[pcolor]);
                }
                if (!MaskAt(p + 1, v1, mask))
                {
                    dst.Write(p + 1, palette[pcolor]);
                }
            }
        }
Esempio n. 29
0
        void UnkDecode9(PixelNavigator navDst, BinaryReader src, int height)
        {
            int  c, color;
            int  i;
            int  buffer = 0;
            int  mask   = 128;
            int  h      = height;
            byte run    = 0;

            int x = 8;

            while (true)
            {
                c = ReadNBits(src, 4, ref mask, ref buffer);

                switch (c >> 2)
                {
                case 0:
                    color = ReadNBits(src, 4, ref mask, ref buffer);
                    for (i = 0; i < ((c & 3) + 2); i++)
                    {
                        navDst.Write(RoomPalette[run * 16 + color]);
                        if (!NextRow(ref navDst, ref x, ref h, height))
                        {
                            return;
                        }
                    }
                    break;

                case 1:
                    for (i = 0; i < ((c & 3) + 1); i++)
                    {
                        color = ReadNBits(src, 4, ref mask, ref buffer);
                        navDst.Write(RoomPalette[run * 16 + color]);
                        if (!NextRow(ref navDst, ref x, ref h, height))
                        {
                            return;
                        }
                    }
                    break;

                case 2:
                    run = (byte)ReadNBits(src, 4, ref mask, ref buffer);
                    break;
                }
            }
        }
Esempio n. 30
0
        void DrawStripBasicV(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck)
        {
            byte color = src.ReadByte();
            uint bits  = src.ReadByte();
            byte cl    = 8;
            int  inc   = -1;

            int x = 8;

            do
            {
                int h = height;
                do
                {
                    FillBits(ref cl, ref bits, src);
                    if (!transpCheck || color != transparentColor)
                    {
                        WriteRoomColor(navDst, color);
                    }
                    navDst.OffsetY(1);
                    if (!ReadBit(ref cl, ref bits))
                    {
                    }
                    else if (!ReadBit(ref cl, ref bits))
                    {
                        FillBits(ref cl, ref bits, src);
                        color  = (byte)(bits & decompMask);
                        bits >>= decompShr;
                        cl    -= decompShr;
                        inc    = -1;
                    }
                    else if (!ReadBit(ref cl, ref bits))
                    {
                        color = (byte)(color + inc);
                    }
                    else
                    {
                        inc   = -inc;
                        color = (byte)(color + inc);
                    }
                } while ((--h) != 0);
                navDst.Offset(1, -height);
            } while ((--x) != 0);
        }
Esempio n. 31
0
        public PixelNavigator?GetLayerPixels(int layer, int x, int y)
        {
            if (layer < 0 || layer > 1)
            {
                return(null);
            }

            var l = _layers[layer];

            if (!l.ready)
            {
                return(null);
            }

            var pn = new PixelNavigator(l.pixels, l.pitch / l.bpp, l.bpp);

            pn.GoTo(x, y);
            return(pn);
        }
Esempio n. 32
0
        void UnkDecode11(PixelNavigator navDst, BinaryReader src, int height)
        {
            int i;
            int buffer = 0, mask = 128;
            int inc   = 1;
            int color = src.ReadByte();

            int x = 8;

            do
            {
                int h = height;
                do
                {
                    navDst.Write(RoomPalette[color]);
                    navDst.OffsetY(1);
                    for (i = 0; i < 3; i++)
                    {
                        if (!ReadBit256(src, ref mask, ref buffer))
                        {
                            break;
                        }
                    }
                    switch (i)
                    {
                    case 1:
                        inc    = -inc;
                        color -= inc;
                        break;

                    case 2:
                        color -= inc;
                        break;

                    case 3:
                        inc   = 1;
                        color = ReadNBits(src, 8, ref mask, ref buffer);
                        break;
                    }
                } while ((--h) != 0);
                navDst.Offset(1, -height);
            } while ((--x) != 0);
        }
Esempio n. 33
0
        public void DrawChar(PixelNavigator dst, char c, int x, int y, byte color)
        {
            var width    = Math.Min((int)_chars[c].Width, dst.Width - x);
            var height   = Math.Min((int)_chars[c].Height, dst.Height - y);
            var src      = UnpackChar(c);
            var srcPitch = _chars[c].Width;
            var srcPos   = 0;

            var minX = x < 0 ? -x : 0;
            var minY = y < 0 ? -y : 0;

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

            if (minY != 0)
            {
                srcPos += minY * srcPitch;
                dst.OffsetY(minY);
            }

            for (int ty = minY; ty < height; ty++)
            {
                for (int tx = minX; tx < width; tx++)
                {
                    if (src[srcPos + tx] != _chars[c].Transparency)
                    {
                        if (src[srcPos + tx] == 1)
                        {
                            dst.Write(tx, color);
                        }
                        else
                        {
                            dst.Write(tx, src[srcPos + tx]);
                        }
                    }
                }
                srcPos += srcPitch;
                dst.OffsetY(1);
            }
        }
Esempio n. 34
0
        public void DrawChar(PixelNavigator dst, char c, int x, int y, byte color)
        {
            var width = Math.Min((int)_chars[c].Width, dst.Width - x);
            var height = Math.Min((int)_chars[c].Height, dst.Height - y);
            var src = UnpackChar(c);
            var srcPitch = _chars[c].Width;
            var srcPos = 0;

            var minX = x < 0 ? -x : 0;
            var minY = y < 0 ? -y : 0;

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

            if (minY != 0)
            {
                srcPos += minY * srcPitch;
                dst.OffsetY(minY);
            }

            for (int ty = minY; ty < height; ty++)
            {
                for (int tx = minX; tx < width; tx++)
                {
                    if (src[srcPos + tx] != _chars[c].Transparency)
                    {
                        if (src[srcPos + tx] == 1)
                        {
                            dst.Write(tx, color);
                        }
                        else
                        {
                            dst.Write(tx, src[srcPos + tx]);
                        }
                    }
                }
                srcPos += srcPitch;
                dst.OffsetY(1);
            }
        }
Esempio n. 35
0
        void UnkDecode8(PixelNavigator navDst, BinaryReader src, int height)
        {
            int h = height;
            int x = 8;

            while (true)
            {
                int run   = src.ReadByte() + 1;
                int color = src.ReadByte();

                for (var i = 0; i < run; i++)
                {
                    navDst.Write(RoomPalette[color]);
                    if (!NextRow(ref navDst, ref x, ref h, height))
                    {
                        return;
                    }
                }
            }
        }
Esempio n. 36
0
 static void BompApplyShadow3(byte[] shadowPalette, byte[] lineBuffer, int linePos, PixelNavigator dst, int size, byte transparency)
 {
     while (size-- > 0)
     {
         byte tmp = lineBuffer[linePos++];
         if (tmp != transparency)
         {
             if (tmp < 8)
             {
                 tmp = shadowPalette[dst.Read() + (tmp << 8)];
             }
             dst.Write(tmp);
         }
         dst.OffsetX(1);
     }
 }
Esempio n. 37
0
        public void DrawBomp()
        {
            Rect clip;
            byte skip_y_bits = 0x80;
            byte skip_y_new = 0;
            byte[] bomp_scaling_x = new byte[64];
            byte[] bomp_scaling_y = new byte[64];

            if (X < 0)
            {
                clip.Left = -X;
            }
            else
            {
                clip.Left = 0;
            }

            if (Y < 0)
            {
                clip.Top = -Y;
            }
            else
            {
                clip.Top = 0;
            }

            clip.Right = Width;
            if (clip.Right > Dst.Width - X)
            {
                clip.Right = Dst.Width - X;
            }

            clip.Bottom = Height;
            if (clip.Bottom > Dst.Height - Y)
            {
                clip.Bottom = Dst.Height - Y;
            }

            var src = Src;
            var pn = new PixelNavigator(Dst);
            pn.GoTo(X + clip.Left, Y);

            var maskbit = ScummHelper.RevBitMask((X + clip.Left) & 7);
            PixelNavigator maskPtr = new PixelNavigator();
            // Mask against any additionally imposed mask
            if (MaskPtr.HasValue)
            {
                maskPtr = MaskPtr.Value;
                maskPtr.GoTo((X + clip.Left) / 8, Y);
            }

            var scalingYPtr = 0;

            // Setup vertical scaling
            if (ScaleY != 255)
            {
                var scaleBottom = SetupBompScale(bomp_scaling_y, Height, ScaleY);

                skip_y_new = bomp_scaling_y[scalingYPtr++];
                skip_y_bits = 0x80;

                if (clip.Bottom > scaleBottom)
                {
                    clip.Bottom = scaleBottom;
                }
            }

            // Setup horizontal scaling
            if (ScaleX != 255)
            {
                var scaleRight = SetupBompScale(bomp_scaling_x, Width, ScaleX);

                if (clip.Right > scaleRight)
                {
                    clip.Right = scaleRight;
                }
            }

            var width = clip.Right - clip.Left;

            if (width <= 0)
                return;

            int pos_y = 0;
            var line_buffer = new byte[1024];

            byte tmp;
            using (var br = new BinaryReader(new MemoryStream(src)))
            {
                // Loop over all lines
                while (pos_y < clip.Bottom)
                {
                    br.ReadUInt16();
                    // Decode a single (bomp encoded) line, reversed if we are in mirror mode
                    if (Mirror)
                        BompDecodeLineReverse(br, line_buffer, 0, Width);
                    else
                        // Decode a single (bomp encoded) line
                        BompDecodeLine(br, line_buffer, 0, Width);

                    // If vertical scaling is enabled, do it
                    if (ScaleY != 255)
                    {
                        // A bit set means we should skip this line...
                        tmp = (byte)(skip_y_new & skip_y_bits);

                        // Advance the scale-skip bit mask, if it's 0, get the next scale-skip byte
                        skip_y_bits /= 2;
                        if (skip_y_bits == 0)
                        {
                            skip_y_bits = 0x80;
                            skip_y_new = bomp_scaling_y[scalingYPtr++];
                        }

                        // Skip the current line if the above check tells us to
                        if (tmp != 0)
                            continue;
                    }

                    // Perform horizontal scaling
                    if (ScaleX != 255)
                    {
                        BompScaleFuncX(line_buffer, bomp_scaling_x, 0, 0x80, Width);
                    }

                    // The first clip.top lines are to be clipped, i.e. not drawn
                    if (clip.Top > 0)
                    {
                        clip.Top--;
                    }
                    else
                    {
                        // Replace the parts of the line which are masked with the transparency color
                        if (MaskPtr.HasValue)
                            BompApplyMask(line_buffer, clip.Left, maskPtr, (byte)maskbit, width, 255);

                        // Apply custom color map, if available
                        if (ActorPalette != null)
                            BompApplyActorPalette(ActorPalette, line_buffer, clip.Left, width);

                        // Finally, draw the decoded, scaled, masked and recolored line onto
                        // the target surface, using the specified shadow mode
                        BompApplyShadow(ShadowMode, ShadowPalette, line_buffer, clip.Left, pn, width, 255);
                    }

                    // Advance to the next line
                    pos_y++;
                    if (MaskPtr.HasValue)
                    {
                        maskPtr.OffsetY(1);
                    }
                    pn.OffsetY(1);
                }
            }
        }
Esempio n. 38
0
 public static void BompApplyShadow(int shadowMode, byte[] shadowPalette, byte[] lineBuffer, int linePos, PixelNavigator dst, int size, byte transparency)
 {
     Debug.Assert(size > 0);
     switch (shadowMode)
     {
         case 0:
             BompApplyShadow0(lineBuffer, linePos, dst, size);
             break;
         case 1:
             BompApplyShadow1(shadowPalette, lineBuffer, linePos, dst, size, transparency);
             break;
         case 3:
             BompApplyShadow3(shadowPalette, lineBuffer, linePos, dst, size, transparency);
             break;
         default:
             throw new ArgumentException(string.Format("Unknown shadow mode {0}", shadowMode));
     }
 }
Esempio n. 39
0
 public static void BompApplyShadow0(byte[] lineBuffer, int linePos, PixelNavigator dst, int size)
 {
     while (size-- > 0)
     {
         byte tmp = lineBuffer[linePos++];
         if (tmp != 255)
         {
             dst.Write(tmp);
         }
         dst.OffsetX(1);
     }
 }
Esempio n. 40
0
        void Proc3Amiga(Codec1 v1)
        {
            byte len;
            int color;
            bool masked;

            var mask = new PixelNavigator(v1.MaskPtr);
            mask.OffsetX(v1.X / 8);
            var dst = new PixelNavigator(v1.DestPtr);
            byte height = (byte)_height;
            byte width = (byte)_width;
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7);
            var y = v1.Y;
            var oldXpos = v1.X;
            var oldScaleIndexX = _scaleIndexX;

            // Indy4 Amiga always uses the room map to match colors to the currently
            // setup palette in the actor code in the original, thus we need to do this
            // mapping over here too.
            var amigaMap = 
                (_vm.Game.Platform == Platform.Amiga && _vm.Game.GameId == GameId.Indy4) ? _vm.Gdi.RoomPalette : null;

            do
            {
                len = _loaded.CostumeReader.ReadByte();
                color = len >> v1.Shr;
                len &= v1.Mask;
                if (len == 0)
                    len = _loaded.CostumeReader.ReadByte();
                do
                {
                    if (ScaleY == 255 || v1.Scaletable[_scaleIndexY] < ScaleY)
                    {
                        masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0);

                        if (color != 0 && !masked)
                        {
                            byte pcolor;
                            if (amigaMap != null)
                                pcolor = amigaMap[_palette[color]];
                            else
                                pcolor = (byte)_palette[color];
                            dst.Write(pcolor);
                        }

                        if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX)
                        {
                            v1.X += v1.ScaleXStep;
                            dst.OffsetX(v1.ScaleXStep);
                            maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7);
                        }
                        _scaleIndexX += (byte)v1.ScaleXStep;
                        mask = new PixelNavigator(v1.MaskPtr);
                        mask.OffsetX(v1.X / 8);
                    }
                    if (--width == 0)
                    {
                        if (--height == 0)
                            return;

                        if (y >= _h)
                            return;

                        if (v1.X != oldXpos)
                        {
                            dst.Offset(-(v1.X - oldXpos), 1);
                            mask = new PixelNavigator(v1.MaskPtr);
                            mask.OffsetY(1);
                            v1.MaskPtr = mask;
                            mask.OffsetX(oldXpos / 8);
                            maskbit = (byte)ScummHelper.RevBitMask(oldXpos & 7);
                            y++;
                        }
                        width = (byte)_width;
                        v1.X = oldXpos;
                        _scaleIndexX = oldScaleIndexX;
                        _scaleIndexY++;
                    }
                } while (--len != 0);
            } while (true);
        }
Esempio n. 41
0
 public static void BompApplyMask(byte[] line_buffer, int linePos, PixelNavigator mask, byte maskbit, int size, byte transparency)
 {
     while (true)
     {
         do
         {
             if (size-- == 0)
                 return;
             if ((mask.Read() & maskbit) != 0)
             {
                 line_buffer[linePos] = transparency;
             }
             linePos++;
             maskbit >>= 1;
         } while (maskbit != 0);
         mask.OffsetX(1);
         maskbit = 128;
     }
 }
Esempio n. 42
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++];
            }
        }
Esempio n. 43
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;
 }
Esempio n. 44
0
        protected void RedefineBuiltinCursorFromChar(int index, int chr)
        {
            // Cursor image in both Loom versions are based on images from charset.
            // This function is *only* supported for Loom!
            if (_game.GameId != Scumm.IO.GameId.Loom)
                throw new NotSupportedException("RedefineBuiltinCursorFromChar is *only* supported for Loom!");
            if (index < 0 || index >= 4)
                throw new ArgumentException("index");

            //	const int oldID = _charset->getCurID();

            var ptr = _cursorImages[index];

            if (_game.Version == 3)
            {
                _charset.SetCurID(0);
            }
            else if (_game.Version >= 4)
            {
                _charset.SetCurID(1);
            }

            var s = new Surface(_charset.GetCharWidth(chr), _charset.GetFontHeight(), PixelFormat.Indexed8, false);
            var p = new PixelNavigator(s);
            Gdi.Fill(new PixelNavigator(s), 123, s.Width, s.Height);

            _charset.DrawChar(chr, s, 0, 0);

            Array.Clear(ptr, 0, ptr.Length);
            for (int h = 0; h < s.Height; h++)
            {
                for (int w = 0; w < s.Width; w++)
                {
                    p.GoTo(w, h);
                    if (p.Read() != 123)
                    {
                        ptr[h] |= (ushort)(1 << (15 - w));
                    }
                }
            }

            //	_charset->setCurID(oldID);
        }
Esempio n. 45
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);
                    }
                }

            }
        }
Esempio n. 46
0
 protected override bool DrawStrip(PixelNavigator navDst, int width, int height, int stripnr, BinaryReader smapReader)
 {
     return false;
 }
Esempio n. 47
0
        protected virtual void KernelGetFunctions()
        {
            var vs = MainVirtScreen;

            var args = GetStackList(30);

            switch (args[0])
            {
                case 113:
                    // WORKAROUND for bug #899249: The scripts used for screen savers
                    // in Sam & Max use hard coded values for the maximum height and width.
                    // This causes problems in rooms (ie. Credits) where their values are
                    // lower, so we set result to zero if out of bounds.
                    if (args[1] >= 0 && args[1] <= vs.Width && args[2] >= 0 && args[2] <= vs.Height)
                    {
                        var nav = new PixelNavigator(vs.Surfaces[0]);
                        nav.GoTo(args[1], args[2]);
                        var pixel = nav.Read();
                        Push(pixel);
                    }
                    else
                    {
                        Push(0);
                    }
                    break;
                case 115:
                    Push(GetSpecialBox(new Point((short)args[1], (short)args[2])));
                    break;
                case 116:
                    Push(CheckXYInBoxBounds(args[3], new Point((short)args[1], (short)args[2])));
                    break;
                case 206:
                    Push(RemapPaletteColor(args[1], args[2], args[3], -1));
                    break;
                case 207:
                    {
                        var i = GetObjectIndex(args[1]);
                        Debug.Assert(i != 0);
                        Push(_objs[i].Position.X);
                    }
                    break;
                case 208:
                    {
                        var i = GetObjectIndex(args[1]);
                        Debug.Assert(i != 0);
                        Push(_objs[i].Position.Y);
                    }
                    break;
                case 209:
                    {
                        var i = GetObjectIndex(args[1]);
                        Debug.Assert(i != 0);
                        Push(_objs[i].Width);
                    }
                    break;
                case 210:
                    {
                        var i = GetObjectIndex(args[1]);
                        Debug.Assert(i != 0);
                        Push(_objs[i].Height);
                    }
                    break;
                case 211:
                    /*
                   13 = thrust
                   336 = thrust
                   328 = thrust
                   27 = abort
                   97 = left
                   331 = left
                   115 = right
                   333 = right
                 */

                    Push(GetKeyState(args[1]));
                    break;
                case 212:
                    {
                        var a = Actors[args[1]];
                        // This is used by walk scripts
                        Push(a.Frame);
                    }
                    break;
                case 213:
                    {
                        var slot = GetVerbSlot(args[1], 0);
                        Push(Verbs[slot].CurRect.Left);
                    }
                    break;
                case 214:
                    {
                        var slot = GetVerbSlot(args[1], 0);
                        Push(Verbs[slot].CurRect.Top);
                    }
                    break;
                case 215:
                    if ((_extraBoxFlags[args[1]] & 0x00FF) == 0x00C0)
                    {
                        Push(_extraBoxFlags[args[1]]);
                    }
                    else
                    {
                        Push((int)GetBoxFlags((byte)args[1]));
                    }
                    break;
                default:
                    throw new NotSupportedException(string.Format("KernelGetFunctions: default case {0}", args[0]));
            }
        }
Esempio n. 48
0
        protected void GetPixel(int x, int y)
        {
            var vs = FindVirtScreen(y);
            if (vs == null || x > ScreenWidth - 1 || x < 0)
            {
                Push(-1);
                return;
            }

            var nav = new PixelNavigator(vs.Surfaces[0]);
            nav.GoTo(x, y - vs.TopLine);
            var pixel = nav.Read();
            Push(pixel);
        }
Esempio n. 49
0
 public override void DrawChar(int chr, Surface s, int x, int y)
 {
     if (!PrepareDraw(chr))
         return;
     var pn = new PixelNavigator(s);
     pn.GoTo(x, y);
     DrawBitsN(s, pn, _fontPtr, _charPos, _fontPtr[_fontPos], y, _width, _height);
 }
Esempio n. 50
0
        void Proc3(Codec1 v1)
        {
            int y = v1.Y;
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            var dst = new PixelNavigator(v1.DestPtr);
            var len = v1.RepLen;
            uint color = v1.RepColor;
            var height = (uint)_height;

            var scaleIndexY = _scaleIndexY;
            var maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7);
            var mask = new PixelNavigator(v1.MaskPtr);
            mask.OffsetX(v1.X / 8);

            bool ehmerde = (len != 0);

            do
            {
                if (!ehmerde)
                {
                    len = _loaded.CostumeReader.ReadByte();
                    color = (uint)(len >> v1.Shr);
                    len &= v1.Mask;
                    if (len == 0)
                        len = _loaded.CostumeReader.ReadByte();
                }

                do
                {
                    if (!ehmerde)
                    {
                        if (ScaleY == 255 || v1.Scaletable[scaleIndexY++] < ScaleY)
                        {
                            var masked = (y < 0 || y >= _h) || (v1.X < 0 || v1.X >= _w) || ((mask.Read() & maskbit) != 0);

                            if (color != 0 && !masked)
                            {
                                byte pcolor;
                                if ((ShadowMode & 0x20) != 0)
                                {
                                    pcolor = ShadowTable[dst.Read()];
                                }
                                else
                                {
                                    pcolor = (byte)_palette[color];
                                    if (pcolor == 13 && ShadowTable != null)
                                        pcolor = ShadowTable[dst.Read()];
                                }
                                dst.Write(pcolor);
                            }
                            dst.OffsetY(1);
                            mask.OffsetY(1);
                            y++;
                        }
                        if ((--height) == 0)
                        {
                            if ((--v1.SkipWidth) == 0)
                                return;
                            height = (uint)_height;
                            y = v1.Y;

                            scaleIndexY = _scaleIndexY;

                            if (ScaleX == 255 || v1.Scaletable[_scaleIndexX] < ScaleX)
                            {
                                v1.X += v1.ScaleXStep;
                                if (v1.X < 0 || v1.X >= _w)
                                    return;
                                maskbit = (byte)ScummHelper.RevBitMask(v1.X & 7);
                                v1.DestPtr.OffsetX(v1.ScaleXStep);
                            }
                            _scaleIndexX = (byte)(_scaleIndexX + v1.ScaleXStep);
                            dst = new PixelNavigator(v1.DestPtr);
                            mask = new PixelNavigator(v1.MaskPtr);
                            mask.OffsetX(v1.X / 8);
                        }
                    }
                    ehmerde = false;
                } while ((--len) != 0);
            } while (true);
        }
Esempio n. 51
0
        protected virtual void DrawBitsN(Surface s, PixelNavigator dst, System.Collections.Generic.IList<byte> src, int srcPos, byte bpp, int drawTop, int width, int height)
        {
            if (bpp != 1 && bpp != 2 && bpp != 4 && bpp != 8)
                throw new ArgumentException("Invalid bpp", "bpp");

            byte bits = src[srcPos++];
            byte numbits = 8;
            var cmap = Vm.CharsetColorMap;

            for (int y = 0; y < height && y + drawTop < s.Height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int color = (bits >> (8 - bpp)) & 0xFF;

                    if (color != 0 && (y + drawTop >= 0))
                    {
                        dst.Write(cmap[color]);
                    }
                    dst.OffsetX(1);
                    bits <<= bpp;
                    numbits -= bpp;
                    if (numbits == 0)
                    {
                        bits = src[srcPos++];
                        numbits = 8;
                    }
                }
                dst.Offset(-width, 1);
            }
        }
Esempio n. 52
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;
        }
        protected override void DrawBitsN(Surface s, PixelNavigator dst, IList<byte> src, int srcPos, byte bpp, int drawTop, int width, int height)
        {
//            if (_sjisCurChar)
//            {
//                assert(Vm._cjkFont);
//                Vm._cjkFont.drawChar(Vm._textSurface, _sjisCurChar, _left * Vm._textSurfaceMultiplier, (_top - Vm._screenTop) * Vm._textSurfaceMultiplier, Vm._townsCharsetColorMap[1], _shadowColor);
//                return;
//            }

            bool scale2x = (Vm.TextSurfaceMultiplier == 2);
            dst = new PixelNavigator(Vm.TextSurface);
            dst.GoTo(Left * Vm.TextSurfaceMultiplier, (Top - Vm.ScreenTop) * Vm.TextSurfaceMultiplier);

            int y, x;
            int color;
            byte numbits, bits;

            int pitch = Vm.TextSurface.Pitch - width;

            Debug.Assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
            bits = src[srcPos++];
            numbits = 8;
            var cmap = Vm.CharsetColorMap;
            var dst2 = new PixelNavigator(dst);

            if (Vm.Game.Platform == Platform.FMTowns)
                cmap = Vm.TownsCharsetColorMap;
            if (scale2x)
            {
                dst2.OffsetY(1);
                pitch <<= 1;
            }

            for (y = 0; y < height && y + drawTop < Vm.TextSurface.Height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    color = (bits >> (8 - bpp)) & 0xFF;
                    if (color != 0 && y + drawTop >= 0)
                    {
                        dst.Write(cmap[color]);
                        if (scale2x)
                        {
                            dst.Write(1, dst.Read());
                            dst2.Write(dst.Read());
                            dst2.Write(1, dst.Read());
                        }
                    }
                    dst.OffsetX(1);

                    if (scale2x)
                    {
                        dst.OffsetX(1);
                        dst2.OffsetX(2);
                    }

                    bits <<= bpp;
                    numbits -= bpp;
                    if (numbits == 0)
                    {
                        bits = src[srcPos++];
                        numbits = 8;
                    }
                }
                dst.OffsetX(pitch / dst.BytesByPixel);
                dst2.OffsetX(pitch / dst2.BytesByPixel);
            }
        }
Esempio n. 54
0
 void Line(int c, int p, Codec1 v1, PixelNavigator? mask, PixelNavigator dst, byte color, byte[] palette)
 {
     var pcolor = (color >> c) & 3;
     if (pcolor != 0)
     { 
         if (!MaskAt(p, v1, mask))
             dst.Write(p, palette[pcolor]);
         if (!MaskAt(p + 1, v1, mask))
             dst.Write(p + 1, palette[pcolor]);
     }
 }
Esempio n. 55
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);
            _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;
        }
Esempio n. 56
0
 bool MaskAt(int xoff, Codec1 v1, PixelNavigator? mask)
 {
     return (mask.HasValue && ((mask.Value.Read(((v1.X + xoff) / 8)) & ScummHelper.RevBitMask((v1.X + xoff) & 7)) != 0));
 }
Esempio n. 57
0
        protected void RestoreBackground(Rect rect, byte backColor = 0)
        {
            VirtScreen vs;

            if (rect.Top < 0)
                rect.Top = 0;
            if (rect.Left >= rect.Right || rect.Top >= rect.Bottom)
                return;

            if ((vs = FindVirtScreen(rect.Top)) == null)
                return;

            if (rect.Left > vs.Width)
                return;

            // Convert 'rect' to local (virtual screen) coordinates
            rect.Top -= vs.TopLine;
            rect.Bottom -= vs.TopLine;

            rect.Clip(vs.Width, vs.Height);

            int height = rect.Height;
            int width = rect.Width;

            if (_game.Platform == Platform.FMTowns && Game.GameId == GameId.Monkey1 && vs == VerbVirtScreen && rect.Bottom <= 154)
                rect.Right = 319;

            MarkRectAsDirty(vs, rect.Left, rect.Right, rect.Top, rect.Bottom, Gdi.UsageBitRestored);

            var screenBuf = new PixelNavigator(vs.Surfaces[0]);
            screenBuf.GoTo(vs.XStart + rect.Left, rect.Top);

            if (height == 0)
                return;

            if (vs.HasTwoBuffers && _currentRoom != 0 && IsLightOn())
            {
                var back = new PixelNavigator(vs.Surfaces[1]);
                back.GoTo(vs.XStart + rect.Left, rect.Top);
                Gdi.Blit(screenBuf, back, width, height);
                if (vs == MainVirtScreen && _charset.HasMask)
                {
                    if (_game.Platform == Platform.FMTowns)
                    {
                        var mask = new PixelNavigator(_textSurface);
                        mask.GoTo(rect.Left * _textSurfaceMultiplier, (rect.Top + vs.TopLine) * _textSurfaceMultiplier);
                        Gdi.Fill(mask, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
                    }
                    else
                    {
                        var mask = new PixelNavigator(_textSurface);
                        mask.GoTo(rect.Left, rect.Top - ScreenTop);
                        Gdi.Fill(mask, CharsetMaskTransparency, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
                    }
                }
            }
            else
            {
                if (Game.Platform == Platform.FMTowns)
                {
                    backColor |= (byte)(backColor << 4);
                    var mask = new PixelNavigator(_textSurface);
                    mask.GoTo(rect.Left * _textSurfaceMultiplier, (rect.Top + vs.TopLine) * _textSurfaceMultiplier);
                    Gdi.Fill(mask, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
                }

                if (Game.Features.HasFlag(GameFeatures.Is16BitColor))
                    Gdi.Fill(screenBuf, _16BitPalette[backColor], width, height);
                else
                    Gdi.Fill(screenBuf, backColor, width, height);
            }
        }
Esempio n. 58
0
        int MainRoutine(int xmoveCur, int ymoveCur)
        {
            int i, skip = 0;
            byte drawFlag = 1;
            bool use_scaling;
            byte startScaleIndexX;
            int ex1, ex2;
            var rect = new Rect();
            int step;
            var v1 = new Codec1();

            const int ScaletableSize = 128;
            bool newAmiCost = (_vm.Game.Version == 5) && (_vm.Game.Platform == Platform.Amiga);
            v1.Scaletable = smallCostumeScaleTable;

            if (_loaded.NumColors == 32)
            {
                v1.Mask = 7;
                v1.Shr = 3;
            }
            else
            {
                v1.Mask = 15;
                v1.Shr = 4;
            }
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);

            switch (_loaded.Format)
            {
                case 0x60:
                case 0x61:
                    // This format is used e.g. in the Sam&Max intro
                    ex1 = _loaded.CostumeReader.ReadByte();
                    ex2 = _loaded.CostumeReader.ReadByte();
                    _srcptr += 2;
                    if (ex1 != 0xFF || ex2 != 0xFF)
                    {
                        _loaded.CostumeReader.BaseStream.Seek(_loaded.FrameOffsets + ex1 * 2, System.IO.SeekOrigin.Begin);
                        ex1 = _loaded.CostumeReader.ReadUInt16();
                        _loaded.CostumeReader.BaseStream.Seek(_loaded.BasePtr + ex1 + ex2 * 2, System.IO.SeekOrigin.Begin);
                        _srcptr = _loaded.BasePtr + _loaded.CostumeReader.ReadUInt16() + 14;
                    }
                    break;
            }

            use_scaling = (ScaleX != 0xFF) || (ScaleY != 0xFF);

            v1.X = ActorX;
            v1.Y = ActorY;

            if (use_scaling)
            {

                /* Scale direction */
                v1.ScaleXStep = -1;
                if (xmoveCur < 0)
                {
                    xmoveCur = -xmoveCur;
                    v1.ScaleXStep = 1;
                }

                // It's possible that the scale indexes will overflow and wrap
                // around to zero, so it's important that we use the same
                // method of accessing it both when calculating the size of the
                // scaled costume, and when drawing it. See bug #1519667.

                if (_mirror)
                {
                    /* Adjust X position */
                    startScaleIndexX = _scaleIndexX = (byte)(ScaletableSize - xmoveCur);
                    for (i = 0; i < xmoveCur; i++)
                    {
                        if (v1.Scaletable[_scaleIndexX++] < ScaleX)
                            v1.X -= v1.ScaleXStep;
                    }

                    rect.Left = rect.Right = v1.X;

                    _scaleIndexX = startScaleIndexX;
                    for (i = 0; i < _width; i++)
                    {
                        if (rect.Right < 0)
                        {
                            skip++;
                            startScaleIndexX = _scaleIndexX;
                        }
                        if (v1.Scaletable[_scaleIndexX++] < ScaleX)
                            rect.Right++;
                    }
                }
                else
                {
                    /* No mirror */
                    /* Adjust X position */
                    startScaleIndexX = _scaleIndexX = (byte)(xmoveCur + ScaletableSize);
                    for (i = 0; i < xmoveCur; i++)
                    {
                        if (v1.Scaletable[_scaleIndexX--] < ScaleX)
                            v1.X += v1.ScaleXStep;
                    }

                    rect.Left = rect.Right = v1.X;

                    _scaleIndexX = startScaleIndexX;
                    for (i = 0; i < _width; i++)
                    {
                        if (rect.Left >= _w)
                        {
                            startScaleIndexX = _scaleIndexX;
                            skip++;
                        }
                        if (v1.Scaletable[_scaleIndexX--] < ScaleX)
                            rect.Left--;
                    }
                }
                _scaleIndexX = startScaleIndexX;

                if (skip != 0)
                    skip--;

                step = -1;
                if (ymoveCur < 0)
                {
                    ymoveCur = -ymoveCur;
                    step = 1;
                }

                _scaleIndexY = (byte)(ScaletableSize - ymoveCur);
                for (i = 0; i < ymoveCur; i++)
                {
                    if (v1.Scaletable[_scaleIndexY++] < ScaleY)
                        v1.Y -= step;
                }

                rect.Top = rect.Bottom = v1.Y;
                _scaleIndexY = (byte)(ScaletableSize - ymoveCur);
                for (i = 0; i < _height; i++)
                {
                    if (v1.Scaletable[_scaleIndexY++] < ScaleY)
                        rect.Bottom++;
                }

                _scaleIndexY = (byte)(ScaletableSize - ymoveCur);
            }
            else
            {
                if (!_mirror)
                    xmoveCur = -xmoveCur;

                v1.X += xmoveCur;
                v1.Y += ymoveCur;

                if (_mirror)
                {
                    rect.Left = v1.X;
                    rect.Right = v1.X + _width;
                }
                else
                {
                    rect.Left = v1.X - _width;
                    rect.Right = v1.X;
                }

                rect.Top = v1.Y;
                rect.Bottom = rect.Top + _height;

            }

            v1.SkipWidth = _width;
            v1.ScaleXStep = _mirror ? 1 : -1;

            if (_vm.Game.Version == 1)
                // V1 games uses 8 x 8 pixels for actors
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, rect.Left, rect.Right + 8, rect.Top, rect.Bottom, ActorID);
            else
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, rect.Left, rect.Right + 1, rect.Top, rect.Bottom, ActorID);

            if (rect.Top >= _h || rect.Bottom <= 0)
                return 0;

            if (rect.Left >= _w || rect.Right <= 0)
                return 0;

            v1.RepLen = 0;

            if (_mirror)
            {
                if (!use_scaling)
                    skip = -v1.X;
                if (skip > 0)
                {
                    if (!newAmiCost && _loaded.Format != 0x57)
                    {
                        v1.SkipWidth -= skip;
                        Codec1IgnorePakCols(v1, skip);
                        v1.X = 0;
                    }
                }
                else
                {
                    skip = rect.Right - _w;
                    if (skip <= 0)
                    {
                        drawFlag = 2;
                    }
                    else
                    {
                        v1.SkipWidth -= skip;
                    }
                }
            }
            else
            {
                if (!use_scaling)
                    skip = rect.Right - _w;
                if (skip > 0)
                {
                    if (!newAmiCost && _loaded.Format != 0x57)
                    {
                        v1.SkipWidth -= skip;
                        Codec1IgnorePakCols(v1, skip);
                        v1.X = _w - 1;
                    }
                }
                else
                {
                    // V1 games uses 8 x 8 pixels for actors
                    if (_loaded.Format == 0x57)
                        skip = -8 - rect.Left;
                    else
                        skip = -1 - rect.Left;
                    if (skip <= 0)
                        drawFlag = 2;
                    else
                        v1.SkipWidth -= skip;
                }
            }

            if (v1.SkipWidth <= 0)
                return 0;

            if (rect.Left < 0)
                rect.Left = 0;

            if (rect.Top < 0)
                rect.Top = 0;

            if (rect.Top > _h)
                rect.Top = _h;

            if (rect.Bottom > _h)
                rect.Bottom = _h;

            if (DrawTop > rect.Top)
                DrawTop = rect.Top;
            if (DrawBottom < rect.Bottom)
                DrawBottom = rect.Bottom;

            if (_height + rect.Top >= 256)
            {
                return 2;
            }

            _pixelsNavigator = new PixelNavigator(startNav);
            _pixelsNavigator.Offset(v1.X, v1.Y);
            v1.DestPtr = _pixelsNavigator;

            v1.MaskPtr = _vm.GetMaskBuffer(0, v1.Y, ZBuffer);

            if (_loaded.Format == 0x57)
            {
                // The v1 costume renderer needs the actor number, which is
                // the same thing as the costume renderer's _actorID.
                ProcC64(v1, ActorID);
            }
            else if (newAmiCost)
            {
                Proc3Amiga(v1);
            }
            else
            {
                Proc3(v1);
            }

            return drawFlag;
        }
Esempio n. 59
0
        void CheckV2MouseOver(Point pos)
        {
            var vs = VerbVirtScreen;
            Rect rect;
            int i, x, y, new_box = -1;

            // Don't do anything unless the inventory is active
            if (!_userState.HasFlag(UserStates.IFaceInventory))
            {
                _mouseOverBoxV2 = -1;
                return;
            }

            if (_cursor.State > 0)
            {
                for (i = 0; i < _mouseOverBoxesV2.Length; i++)
                {
                    if (_mouseOverBoxesV2[i].rect.Contains(pos.X, pos.Y - vs.TopLine))
                    {
                        new_box = i;
                        break;
                    }
                }
            }

            if ((new_box != _mouseOverBoxV2) || (Game.Version == 0))
            {
                if (_mouseOverBoxV2 != -1)
                {
                    rect = _mouseOverBoxesV2[_mouseOverBoxV2].rect;

                    var dst = new PixelNavigator(vs.Surfaces[0]);
                    dst.GoTo(rect.Left, rect.Top);

                    // Remove highlight.
                    for (y = rect.Height - 1; y >= 0; y--)
                    {
                        for (x = rect.Width - 1; x >= 0; x--)
                        {
                            if (dst.Read() == _mouseOverBoxesV2[_mouseOverBoxV2].hicolor)
                                dst.Write(_mouseOverBoxesV2[_mouseOverBoxV2].color);
                            dst.OffsetX(1);
                        }
                        dst.Offset(-rect.Width, 1);
                    }

                    MarkRectAsDirty(VerbVirtScreen, rect);
                }

                if (new_box != -1)
                {
                    rect = _mouseOverBoxesV2[new_box].rect;

                    var dst = new PixelNavigator(vs.Surfaces[0]);
                    dst.GoTo(rect.Left, rect.Top);

                    // Apply highlight
                    for (y = rect.Height - 1; y >= 0; y--)
                    {
                        for (x = rect.Width - 1; x >= 0; x--)
                        {
                            if (dst.Read() == _mouseOverBoxesV2[new_box].color)
                                dst.Write(_mouseOverBoxesV2[new_box].hicolor);
                            dst.OffsetX(1);
                        }
                        dst.Offset(-rect.Width, 1);
                    }

                    MarkRectAsDirty(VerbVirtScreen, rect);
                }

                _mouseOverBoxV2 = (sbyte)new_box;
            }
        }
Esempio n. 60
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);
        }