Offset() public method

public Offset ( int x, int y ) : void
x int
y int
return void
Exemplo n.º 1
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);
            }
        }
Exemplo n.º 2
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);
 }
Exemplo n.º 3
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);
     }
 }
Exemplo n.º 4
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);
     }
 }
Exemplo n.º 5
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);
 }
Exemplo n.º 6
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);
 }
Exemplo n.º 7
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);
        }
Exemplo n.º 8
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);
        }
Exemplo n.º 9
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);
        }
Exemplo n.º 10
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++];
            }
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
0
        byte Codec1(int xmoveCur, int ymoveCur)
        {
            int num_colors;
            bool use_scaling;
            int i, j;
            int skip = 0, startScaleIndexX, startScaleIndexY;
            Rect rect;
            int step;
            byte drawFlag = 1;
            var v1 = new Codec1();

            int scaletableSize = 384;

            /* implement custom scale table */

            // FIXME. HACK
            // For some illogical reason gcc 3.4.x produces wrong code if
            // smallCostumeScaleTable from costume.cpp is used here
            // So I had to put copy of it back here as it was before 1.227 revision
            // of this file.
            v1.Scaletable = bigCostumeScaleTable;
            var table = ((ScummEngine7)_vm).GetStringAddressVar(((ScummEngine7)_vm).VariableCustomScaleTable);
            if (table != null)
            {
                v1.Scaletable = table;
            }

            // Setup color decoding variables
            num_colors = akpl.Length;
            if (num_colors == 32)
            {
                v1.Mask = 7;
                v1.Shr = 3;
            }
            else if (num_colors == 64)
            {
                v1.Mask = 3;
                v1.Shr = 2;
            }
            else
            {
                v1.Mask = 15;
                v1.Shr = 4;
            }

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

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

            v1.BoundsRect.Left = 0;
            v1.BoundsRect.Top = 0;
            v1.BoundsRect.Right = _vm.MainVirtScreen.Width;
            v1.BoundsRect.Bottom = _vm.MainVirtScreen.Height;

            if (use_scaling)
            {

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

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

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

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

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

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

                if (skip != 0)
                    skip--;

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

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

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

                startScaleIndexY = 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;

                startScaleIndexX = scaletableSize;
                startScaleIndexY = scaletableSize;
            }

            v1.ScaleXIndex = startScaleIndexX;
            v1.ScaleYIndex = startScaleIndexY;
            v1.SkipWidth = _width;
            v1.ScaleXStep = _mirror ? 1 : -1;

            if (ActorHitMode)
            {
                if (ActorHitX < rect.Left || ActorHitX >= rect.Right || ActorHitY < rect.Top || ActorHitY >= rect.Bottom)
                    return 0;
            }
            else
                MarkRectAsDirty(rect);

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

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

            v1.RepLen = 0;

            if (_mirror)
            {
                if (!use_scaling)
                    skip = v1.BoundsRect.Left - v1.X;

                if (skip > 0)
                {
                    v1.SkipWidth -= skip;
                    Codec1IgnorePakCols(v1, skip);
                    v1.X = v1.BoundsRect.Left;
                }
                else
                {
                    skip = rect.Right - v1.BoundsRect.Right;
                    if (skip <= 0)
                    {
                        drawFlag = 2;
                    }
                    else
                    {
                        v1.SkipWidth -= skip;
                    }
                }
            }
            else
            {
                if (!use_scaling)
                    skip = rect.Right - v1.BoundsRect.Right + 1;
                if (skip > 0)
                {
                    v1.SkipWidth -= skip;
                    Codec1IgnorePakCols(v1, skip);
                    v1.X = v1.BoundsRect.Right - 1;
                }
                else
                {
                    skip = (v1.BoundsRect.Left - 1) - rect.Left;

                    if (skip <= 0)
                        drawFlag = 2;
                    else
                        v1.SkipWidth -= skip;
                }
            }

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

            if (rect.Left < v1.BoundsRect.Left)
                rect.Left = v1.BoundsRect.Left;

            if (rect.Top < v1.BoundsRect.Top)
                rect.Top = v1.BoundsRect.Top;

            if (rect.Top > v1.BoundsRect.Bottom)
                rect.Top = v1.BoundsRect.Bottom;

            if (rect.Bottom > v1.BoundsRect.Bottom)
                rect.Bottom = v1.BoundsRect.Bottom;

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

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

            Codec1GenericDecode(v1);

            return drawFlag;
        }
Exemplo n.º 13
0
        void DrawStripComplex(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck)
        {
            byte color = src.ReadByte();
            uint bits = src.ReadByte();
            byte cl = 8;
            byte incm, reps;

            do
            {
                int x = 8;
                do
                {
                    FillBits(ref cl, ref bits, src);
                    if (!transpCheck || color != TransparentColor)
                    {
                        WriteRoomColor(navDst, color);
                    }
                    navDst.OffsetX(1);

againPos:
                    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;
                    }
                    else
                    {
                        incm   = (byte)((bits & 7) - 4);
                        cl    -= 3;
                        bits >>= 3;
                        if (incm != 0)
                        {
                            color += incm;
                        }
                        else
                        {
                            FillBits(ref cl, ref bits, src);
                            reps = (byte)(bits & 0xFF);
                            do
                            {
                                if ((--x) == 0)
                                {
                                    x = 8;
                                    navDst.Offset(-8, 1);
                                    if ((--height) == 0)
                                    {
                                        return;
                                    }
                                }
                                if (!transpCheck || color != TransparentColor)
                                {
                                    WriteRoomColor(navDst, color);
                                }
                                navDst.OffsetX(1);
                            } while ((--reps) != 0);
                            bits >>= 8;
                            bits  |= (uint)(src.ReadByte()) << (cl - 8);
                            goto againPos;
                        }
                    }
                } while ((--x) != 0);
                navDst.Offset(-8, 1);
            } while ((--height) != 0);
        }
Exemplo n.º 14
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);
 }
Exemplo n.º 15
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;
        }
Exemplo n.º 16
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);
            }
        }
Exemplo n.º 17
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);
     }
 }
Exemplo n.º 18
0
        void DrawStripComplex(PixelNavigator navDst, BinaryReader src, int height, bool transpCheck)
        {
            byte color = src.ReadByte();
            uint bits = src.ReadByte();
            byte cl = 8;
            byte incm, reps;

            do
            {
                int x = 8;
                do
                {
                    FillBits(ref cl, ref bits, src);
                    if (!transpCheck || color != TransparentColor)
                        WriteRoomColor(navDst, color);
                    navDst.OffsetX(1);

                    againPos:
                    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;
                    }
                    else
                    {
                        incm = (byte)((bits & 7) - 4);
                        cl -= 3;
                        bits >>= 3;
                        if (incm != 0)
                        {
                            color += incm;
                        }
                        else
                        {
                            FillBits(ref cl, ref bits, src);
                            reps = (byte)(bits & 0xFF);
                            do
                            {
                                if ((--x) == 0)
                                {
                                    x = 8;
                                    navDst.Offset(-8, 1);
                                    if ((--height) == 0)
                                        return;
                                }
                                if (!transpCheck || color != TransparentColor)
                                    WriteRoomColor(navDst, color);
                                navDst.OffsetX(1);
                            } while ((--reps) != 0);
                            bits >>= 8;
                            bits |= (uint)(src.ReadByte()) << (cl - 8);
                            goto againPos;
                        }
                    }
                } while ((--x) != 0);
                navDst.Offset(-8, 1);
            } while ((--height) != 0);
        }
Exemplo n.º 19
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);
 }
Exemplo n.º 20
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);
        }
Exemplo n.º 21
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;
 }
Exemplo n.º 22
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++];
            }
        }
Exemplo n.º 23
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);
        }
Exemplo n.º 24
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);
        }
Exemplo n.º 25
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);
     }
 }
Exemplo n.º 26
0
        byte Codec1(int xmoveCur, int ymoveCur)
        {
            int  num_colors;
            bool use_scaling;
            int  i, j;
            int  skip = 0, startScaleIndexX, startScaleIndexY;
            Rect rect;
            int  step;
            byte drawFlag = 1;
            var  v1       = new Codec1();

            int scaletableSize = 384;

            /* implement custom scale table */

            // FIXME. HACK
            // For some illogical reason gcc 3.4.x produces wrong code if
            // smallCostumeScaleTable from costume.cpp is used here
            // So I had to put copy of it back here as it was before 1.227 revision
            // of this file.
            v1.Scaletable = bigCostumeScaleTable;
            var table = ((ScummEngine7)_vm).GetStringAddressVar(((ScummEngine7)_vm).VariableCustomScaleTable);

            if (table != null)
            {
                v1.Scaletable = table;
            }

            // Setup color decoding variables
            num_colors = akpl.Length;
            if (num_colors == 32)
            {
                v1.Mask = 7;
                v1.Shr  = 3;
            }
            else if (num_colors == 64)
            {
                v1.Mask = 3;
                v1.Shr  = 2;
            }
            else
            {
                v1.Mask = 15;
                v1.Shr  = 4;
            }

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

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

            v1.BoundsRect.Left   = 0;
            v1.BoundsRect.Top    = 0;
            v1.BoundsRect.Right  = _vm.MainVirtScreen.Width;
            v1.BoundsRect.Bottom = _vm.MainVirtScreen.Height;

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

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

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

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

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

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

                if (skip != 0)
                {
                    skip--;
                }

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

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

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

                startScaleIndexY = 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;

                startScaleIndexX = scaletableSize;
                startScaleIndexY = scaletableSize;
            }

            v1.ScaleXIndex = startScaleIndexX;
            v1.ScaleYIndex = startScaleIndexY;
            v1.SkipWidth   = _width;
            v1.ScaleXStep  = _mirror ? 1 : -1;

            if (ActorHitMode)
            {
                if (ActorHitX < rect.Left || ActorHitX >= rect.Right || ActorHitY < rect.Top || ActorHitY >= rect.Bottom)
                {
                    return(0);
                }
            }
            else
            {
                MarkRectAsDirty(rect);
            }

            if (rect.Top >= v1.BoundsRect.Bottom || rect.Bottom <= v1.BoundsRect.Top)
            {
                return(0);
            }

            if (rect.Left >= v1.BoundsRect.Right || rect.Right <= v1.BoundsRect.Left)
            {
                return(0);
            }

            v1.RepLen = 0;

            if (_mirror)
            {
                if (!use_scaling)
                {
                    skip = v1.BoundsRect.Left - v1.X;
                }

                if (skip > 0)
                {
                    v1.SkipWidth -= skip;
                    Codec1IgnorePakCols(v1, skip);
                    v1.X = v1.BoundsRect.Left;
                }
                else
                {
                    skip = rect.Right - v1.BoundsRect.Right;
                    if (skip <= 0)
                    {
                        drawFlag = 2;
                    }
                    else
                    {
                        v1.SkipWidth -= skip;
                    }
                }
            }
            else
            {
                if (!use_scaling)
                {
                    skip = rect.Right - v1.BoundsRect.Right + 1;
                }
                if (skip > 0)
                {
                    v1.SkipWidth -= skip;
                    Codec1IgnorePakCols(v1, skip);
                    v1.X = v1.BoundsRect.Right - 1;
                }
                else
                {
                    skip = (v1.BoundsRect.Left - 1) - rect.Left;

                    if (skip <= 0)
                    {
                        drawFlag = 2;
                    }
                    else
                    {
                        v1.SkipWidth -= skip;
                    }
                }
            }

            if (v1.SkipWidth <= 0 || _height <= 0)
            {
                return(0);
            }

            if (rect.Left < v1.BoundsRect.Left)
            {
                rect.Left = v1.BoundsRect.Left;
            }

            if (rect.Top < v1.BoundsRect.Top)
            {
                rect.Top = v1.BoundsRect.Top;
            }

            if (rect.Top > v1.BoundsRect.Bottom)
            {
                rect.Top = v1.BoundsRect.Bottom;
            }

            if (rect.Bottom > v1.BoundsRect.Bottom)
            {
                rect.Bottom = v1.BoundsRect.Bottom;
            }

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

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

            Codec1GenericDecode(v1);

            return(drawFlag);
        }
Exemplo n.º 27
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);
        }
Exemplo n.º 28
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;
            }
        }
Exemplo n.º 29
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;
 }