Ejemplo n.º 1
0
        void Codec1IgnorePakCols(Codec1 v1, int num)
        {
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            num *= _height;

            do
            {
                v1.RepLen   = _loaded.CostumeReader.ReadByte();
                v1.RepColor = (byte)(v1.RepLen >> v1.Shr);
                v1.RepLen  &= v1.Mask;

                if (v1.RepLen == 0)
                {
                    v1.RepLen = _loaded.CostumeReader.ReadByte();
                }

                do
                {
                    if ((--num) == 0)
                    {
                        _srcptr = _loaded.CostumeReader.BaseStream.Position;
                        return;
                    }
                } while ((--v1.RepLen) != 0);
            } while (true);
        }
Ejemplo n.º 2
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]);
                }
            }
        }
Ejemplo n.º 3
0
        void Codec1IgnorePakCols(Codec1 v1, int num)
        {
            num *= _height;

            do
            {
                v1.RepLen   = akcd[_srcptr++];
                v1.RepColor = (byte)(v1.RepLen >> v1.Shr);
                v1.RepLen  &= v1.Mask;

                if (v1.RepLen == 0)
                {
                    v1.RepLen = akcd[_srcptr++];
                }

                do
                {
                    if (--num == 0)
                    {
                        return;
                    }
                } while (--v1.RepLen != 0);
            } while (true);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        void ProcC64(Codec1 v1, int actor)
        {
//            const byte *mask, *src;
//            byte *dst;
            byte len;
            int y;
            uint height;
            byte color;
            bool rep;

            y = v1.Y;
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            var dst = v1.DestPtr;
            len = v1.RepLen;
            color = v1.RepColor;
            height = (uint)_height;

            v1.SkipWidth /= 8;

            // Set up the palette data
            byte[] palette = new byte[4];
            if (_vm.GetCurrentLights().HasFlag(LightModes.ActorUseColors))
            {
                if (_vm.Game.GameId == GameId.Maniac)
                {
                    palette[1] = v1MMActorPalatte1[actor];
                    palette[2] = v1MMActorPalatte2[actor];
                }
                else
                {
                    // Adjust for C64 version of Zak McKracken
                    palette[1] = (byte)(_vm.Game.Platform == Platform.C64 ? 10 : 8);
                    palette[2] = (byte)_palette[actor];
                }
            }
            else
            {
                palette[2] = 11;
                palette[3] = 11;
            }
            var mask = v1.MaskPtr;

            var skipInit = false;
            if (len != 0)
                skipInit = true;

            do
            {
                if (!skipInit)
                {
                    len = Init(ref color);
                }
                else
                {
                    skipInit = false;
                }

                rep = (len & 0x80) != 0;
                len &= 0x7f;
                while ((len--) != 0)
                {
                    if (!rep)
                        color = _loaded.CostumeReader.ReadByte();

                    if (0 <= y && y < _h && 0 <= v1.X && v1.X < _w)
                    {
                        if (!_mirror)
                        {
                            Line(0, 0, v1, mask, dst, color, palette);
                            Line(2, 2, v1, mask, dst, color, palette);
                            Line(4, 4, v1, mask, dst, color, palette);
                            Line(6, 6, v1, mask, dst, color, palette);
                        }
                        else
                        {
                            Line(6, 0, v1, mask, dst, color, palette);
                            Line(4, 2, v1, mask, dst, color, palette);
                            Line(2, 4, v1, mask, dst, color, palette);
                            Line(0, 6, v1, mask, dst, color, palette);
                        }
                    }
                    dst.OffsetY(1);
                    y++;
                    mask.OffsetY(1);
                    if ((--height) == 0)
                    {
                        if ((--v1.SkipWidth) == 0)
                            return;
                        height = (uint)_height;
                        y = v1.Y;
                        v1.X += 8 * v1.ScaleXStep;
                        if (v1.X < 0 || v1.X >= _w)
                            return;
                        mask = v1.MaskPtr;
                        v1.DestPtr.OffsetX(8 * v1.ScaleXStep);
                        dst = v1.DestPtr;
                    }
                }
            } while (true);
        }
Ejemplo n.º 6
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]);
     }
 }
Ejemplo n.º 7
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));
 }
Ejemplo n.º 8
0
        void Codec1IgnorePakCols(Codec1 v1, int num)
        {
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            num *= _height;

            do
            {
                v1.RepLen = _loaded.CostumeReader.ReadByte();
                v1.RepColor = (byte)(v1.RepLen >> v1.Shr);
                v1.RepLen &= v1.Mask;

                if (v1.RepLen == 0)
                    v1.RepLen = _loaded.CostumeReader.ReadByte();

                do
                {
                    if ((--num) == 0)
                    {
                        _srcptr = _loaded.CostumeReader.BaseStream.Position;
                        return;
                    }
                } while ((--v1.RepLen) != 0);
            } while (true);
        }
Ejemplo n.º 9
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;
        }
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
0
        void ProcC64(Codec1 v1, int actor)
        {
//            const byte *mask, *src;
//            byte *dst;
            byte len;
            int  y;
            uint height;
            byte color;
            bool rep;

            y = v1.Y;
            _loaded.CostumeReader.BaseStream.Seek(_srcptr, System.IO.SeekOrigin.Begin);
            var dst = v1.DestPtr;

            len    = v1.RepLen;
            color  = v1.RepColor;
            height = (uint)_height;

            v1.SkipWidth /= 8;

            // Set up the palette data
            byte[] palette = new byte[4];
            if (_vm.GetCurrentLights().HasFlag(LightModes.ActorUseColors))
            {
                if (_vm.Game.GameId == GameId.Maniac)
                {
                    palette[1] = v1MMActorPalatte1[actor];
                    palette[2] = v1MMActorPalatte2[actor];
                }
                else
                {
                    // Adjust for C64 version of Zak McKracken
                    palette[1] = (byte)(_vm.Game.Platform == Platform.C64 ? 10 : 8);
                    palette[2] = (byte)_palette[actor];
                }
            }
            else
            {
                palette[2] = 11;
                palette[3] = 11;
            }
            var mask = v1.MaskPtr;

            var skipInit = false;

            if (len != 0)
            {
                skipInit = true;
            }

            do
            {
                if (!skipInit)
                {
                    len = Init(ref color);
                }
                else
                {
                    skipInit = false;
                }

                rep  = (len & 0x80) != 0;
                len &= 0x7f;
                while ((len--) != 0)
                {
                    if (!rep)
                    {
                        color = _loaded.CostumeReader.ReadByte();
                    }

                    if (0 <= y && y < _h && 0 <= v1.X && v1.X < _w)
                    {
                        if (!_mirror)
                        {
                            Line(0, 0, v1, mask, dst, color, palette);
                            Line(2, 2, v1, mask, dst, color, palette);
                            Line(4, 4, v1, mask, dst, color, palette);
                            Line(6, 6, v1, mask, dst, color, palette);
                        }
                        else
                        {
                            Line(6, 0, v1, mask, dst, color, palette);
                            Line(4, 2, v1, mask, dst, color, palette);
                            Line(2, 4, v1, mask, dst, color, palette);
                            Line(0, 6, v1, mask, dst, color, palette);
                        }
                    }
                    dst.OffsetY(1);
                    y++;
                    mask.OffsetY(1);
                    if ((--height) == 0)
                    {
                        if ((--v1.SkipWidth) == 0)
                        {
                            return;
                        }
                        height = (uint)_height;
                        y      = v1.Y;
                        v1.X  += 8 * v1.ScaleXStep;
                        if (v1.X < 0 || v1.X >= _w)
                        {
                            return;
                        }
                        mask = v1.MaskPtr;
                        v1.DestPtr.OffsetX(8 * v1.ScaleXStep);
                        dst = v1.DestPtr;
                    }
                }
            } while (true);
        }
Ejemplo n.º 13
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));
 }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 15
0
        void Codec1GenericDecode(Codec1 v1)
        {
            bool skip_column = false;

            var y = v1.Y;
            var src = _srcptr;
            var dst = v1.DestPtr;
            var len = v1.RepLen;
            var color = v1.RepColor;
            var height = _height;

            var scaleytab = v1.ScaleYIndex;
            var maskbit = ScummHelper.RevBitMask(v1.X & 7);

            var mask = _vm.GetMaskBuffer(v1.X - (_vm.MainVirtScreen.XStart & 7), v1.Y, ZBuffer);

            bool ehmerde = (len != 0);

            do
            {
                if (!ehmerde)
                {
                    len = akcd[src++];
                    color = (byte)(len >> v1.Shr);
                    len &= v1.Mask;
                    if (len == 0)
                        len = akcd[src++];
                }

                do
                {
                    if (!ehmerde)
                    {
                        if (ScaleY == 255 || v1.Scaletable[scaleytab++] < ScaleY)
                        {
                            if (ActorHitMode)
                            {
                                if (color != 0 && y == ActorHitY && v1.X == ActorHitX)
                                {
                                    ActorHitResult = true;
                                    return;
                                }
                            }
                            else
                            {
                                bool masked = (y < v1.BoundsRect.Top || y >= v1.BoundsRect.Bottom) || (v1.X < 0 || v1.X >= v1.BoundsRect.Right) || ((mask.Read() & maskbit) != 0);

                                if (color != 0 && !masked && !skip_column)
                                {
                                    var pcolor = _palette[color];
                                    if (ShadowMode == 1)
                                    {
                                        if (pcolor == 13)
                                            pcolor = ShadowTable[dst.Read()];
                                    }
                                    else if (ShadowMode == 2)
                                    {
                                        throw new NotImplementedException("codec1_spec2"); // TODO
                                    }
                                    else if (ShadowMode == 3)
                                    {
                                        if (_vm.Game.Features.HasFlag(GameFeatures.Is16BitColor))
                                        {
                                            ushort srcColor = (ushort)((pcolor >> 1) & 0x7DEF);
                                            ushort dstColor = (ushort)((dst.ReadUInt16() >> 1) & 0x7DEF);
                                            pcolor = (ushort)(srcColor + dstColor);
                                        }
                                        else if (pcolor < 8)
                                        {
                                            pcolor = (ushort)((pcolor << 8) + dst.Read());
                                            pcolor = ShadowTable[pcolor];
                                        }
                                    }
                                    if (_vm.MainVirtScreen.BytesPerPixel == 2)
                                    {
                                        dst.WriteUInt16(pcolor);
                                    }
                                    else
                                    {
                                        dst.Write((byte)pcolor);
                                    }
                                }
                            }
                            dst.OffsetY(1);
                            mask.OffsetY(1);
                            y++;
                        }
                        if (--height == 0)
                        {
                            if (--v1.SkipWidth == 0)
                                return;
                            height = _height;
                            y = v1.Y;

                            scaleytab = v1.ScaleYIndex;

                            if (ScaleX == 255 || v1.Scaletable[v1.ScaleXIndex] < ScaleX)
                            {
                                v1.X += v1.ScaleXStep;
                                if (v1.X < 0 || v1.X >= v1.BoundsRect.Right)
                                    return;
                                maskbit = ScummHelper.RevBitMask(v1.X & 7);
                                v1.DestPtr.OffsetX(v1.ScaleXStep);
                                skip_column = false;
                            }
                            else
                                skip_column = true;
                            v1.ScaleXIndex += v1.ScaleXStep;
                            dst = v1.DestPtr;
                            mask = _vm.GetMaskBuffer(v1.X - (_vm.MainVirtScreen.XStart & 7), v1.Y, ZBuffer);
                        }
                    }
                    ehmerde = false;
                } while (--len != 0);
            } while (true);
        }
Ejemplo n.º 16
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);
        }
Ejemplo n.º 17
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);
        }
Ejemplo n.º 18
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;
        }
Ejemplo n.º 19
0
        void Codec1GenericDecode(Codec1 v1)
        {
            bool skip_column = false;

            var y      = v1.Y;
            var src    = _srcptr;
            var dst    = v1.DestPtr;
            var len    = v1.RepLen;
            var color  = v1.RepColor;
            var height = _height;

            var scaleytab = v1.ScaleYIndex;
            var maskbit   = ScummHelper.RevBitMask(v1.X & 7);

            var mask = _vm.GetMaskBuffer(v1.X - (_vm.MainVirtScreen.XStart & 7), v1.Y, ZBuffer);

            bool ehmerde = (len != 0);

            do
            {
                if (!ehmerde)
                {
                    len   = akcd[src++];
                    color = (byte)(len >> v1.Shr);
                    len  &= v1.Mask;
                    if (len == 0)
                    {
                        len = akcd[src++];
                    }
                }

                do
                {
                    if (!ehmerde)
                    {
                        if (ScaleY == 255 || v1.Scaletable[scaleytab++] < ScaleY)
                        {
                            if (ActorHitMode)
                            {
                                if (color != 0 && y == ActorHitY && v1.X == ActorHitX)
                                {
                                    ActorHitResult = true;
                                    return;
                                }
                            }
                            else
                            {
                                bool masked = (y < v1.BoundsRect.Top || y >= v1.BoundsRect.Bottom) || (v1.X < 0 || v1.X >= v1.BoundsRect.Right) || ((mask.Read() & maskbit) != 0);

                                if (color != 0 && !masked && !skip_column)
                                {
                                    var pcolor = _palette[color];
                                    if (ShadowMode == 1)
                                    {
                                        if (pcolor == 13)
                                        {
                                            pcolor = ShadowTable[dst.Read()];
                                        }
                                    }
                                    else if (ShadowMode == 2)
                                    {
                                        throw new NotImplementedException("codec1_spec2"); // TODO
                                    }
                                    else if (ShadowMode == 3)
                                    {
                                        if (_vm.Game.Features.HasFlag(GameFeatures.Is16BitColor))
                                        {
                                            ushort srcColor = (ushort)((pcolor >> 1) & 0x7DEF);
                                            ushort dstColor = (ushort)((dst.ReadUInt16() >> 1) & 0x7DEF);
                                            pcolor = (ushort)(srcColor + dstColor);
                                        }
                                        else if (pcolor < 8)
                                        {
                                            pcolor = (ushort)((pcolor << 8) + dst.Read());
                                            pcolor = ShadowTable[pcolor];
                                        }
                                    }
                                    if (_vm.MainVirtScreen.BytesPerPixel == 2)
                                    {
                                        dst.WriteUInt16(pcolor);
                                    }
                                    else
                                    {
                                        dst.Write((byte)pcolor);
                                    }
                                }
                            }
                            dst.OffsetY(1);
                            mask.OffsetY(1);
                            y++;
                        }
                        if (--height == 0)
                        {
                            if (--v1.SkipWidth == 0)
                            {
                                return;
                            }
                            height = _height;
                            y      = v1.Y;

                            scaleytab = v1.ScaleYIndex;

                            if (ScaleX == 255 || v1.Scaletable[v1.ScaleXIndex] < ScaleX)
                            {
                                v1.X += v1.ScaleXStep;
                                if (v1.X < 0 || v1.X >= v1.BoundsRect.Right)
                                {
                                    return;
                                }
                                maskbit = ScummHelper.RevBitMask(v1.X & 7);
                                v1.DestPtr.OffsetX(v1.ScaleXStep);
                                skip_column = false;
                            }
                            else
                            {
                                skip_column = true;
                            }
                            v1.ScaleXIndex += v1.ScaleXStep;
                            dst             = v1.DestPtr;
                            mask            = _vm.GetMaskBuffer(v1.X - (_vm.MainVirtScreen.XStart & 7), v1.Y, ZBuffer);
                        }
                    }
                    ehmerde = false;
                } while (--len != 0);
            } while (true);
        }
Ejemplo n.º 20
0
        void Codec1IgnorePakCols(Codec1 v1, int num)
        {
            num *= _height;

            do
            {
                v1.RepLen = akcd[_srcptr++];
                v1.RepColor = (byte)(v1.RepLen >> v1.Shr);
                v1.RepLen &= v1.Mask;

                if (v1.RepLen == 0)
                    v1.RepLen = akcd[_srcptr++];

                do
                {
                    if (--num == 0)
                        return;
                } while (--v1.RepLen != 0);
            } while (true);
        }