GoTo() публичный Метод

public GoTo ( int x, int y ) : void
x int
y int
Результат void
Пример #1
0
        public PixelNavigator GetMaskBuffer(int x, int y, int i)
        {
            var nav = new PixelNavigator(maskBuffer[i], NumStrips, 1);

            nav.GoTo(x, y);
            return(nav);
        }
Пример #2
0
        public override void DrawChar(int chr, Surface s, int x, int y)
        {
            if (!PrepareDraw(chr))
            {
                return;
            }
            var pn = new PixelNavigator(s);

            pn.GoTo(x, y);
            DrawBitsN(s, pn, _fontPtr, _charPos, _fontPtr[_fontPos], y, _width, _height);
        }
Пример #3
0
        public void ResetBackground(int top, int bottom, int strip)
        {
            var vs = _vm.MainVirtScreen;

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

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

            if (top >= bottom)
            {
                return;
            }

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

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

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

            int numLinesToProcess = bottom - top;

            if (numLinesToProcess > 0)
            {
                var navDest = new PixelNavigator(vs.Surfaces[0]);
                navDest.GoTo(strip * 8 + vs.XStart, top);
                if (_vm.IsLightOn())
                {
                    var bgBakNav = new PixelNavigator(vs.Surfaces[1]);
                    bgBakNav.GoTo(strip * 8 + vs.XStart, top);
                    Copy8Col(navDest, bgBakNav, numLinesToProcess);
                }
                else
                {
                    Clear8Col(navDest, numLinesToProcess);
                }
            }
        }
Пример #4
0
        public PixelNavigator? GetLayerPixels(int layer, int x, int y)
        {
            if (layer < 0 || layer > 1)
                return null;

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

            var pn = new PixelNavigator(l.pixels, l.pitch / l.bpp, l.bpp);
            pn.GoTo(x, y);
            return pn;
        }
Пример #5
0
        public PixelNavigator?GetLayerPixels(int layer, int x, int y)
        {
            if (layer < 0 || layer > 1)
            {
                return(null);
            }

            var l = _layers[layer];

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

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

            pn.GoTo(x, y);
            return(pn);
        }
Пример #6
0
        protected virtual void DrawBits1(Surface surface, int x, int y, BinaryReader src, int drawTop, int width, int height)
        {
            var dst = new PixelNavigator(surface);

            dst.GoTo(x, y);

            byte bits = 0;
            byte col  = Color;
            //int pitch = surface.Pitch - width * surface.BytesPerPixel;
            var dst2 = new PixelNavigator(dst);

            dst2.OffsetY(1);

            for (y = 0; y < height && y + drawTop < surface.Height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    if ((x % 8) == 0)
                    {
                        bits = src.ReadByte();
                    }
                    if ((bits & ScummHelper.RevBitMask(x % 8)) != 0 && y + drawTop >= 0)
                    {
                        if (_shadowMode)
                        {
                            dst.OffsetX(1);
                            dst.Write(_shadowColor);
                            dst2.Write(_shadowColor);
                            dst2.OffsetX(1);
                            dst2.Write(_shadowColor);
                        }
                        dst.Write(col);
                    }
                    dst.OffsetX(1);
                    dst2.OffsetX(1);
                }

                dst.OffsetX(surface.Width - width);
                dst2.OffsetX(surface.Width - width);
            }
        }
Пример #7
0
        public void DrawBomp()
        {
            Rect clip;
            byte skip_y_bits = 0x80;
            byte skip_y_new = 0;
            byte[] bomp_scaling_x = new byte[64];
            byte[] bomp_scaling_y = new byte[64];

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

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

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

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

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

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

            var scalingYPtr = 0;

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

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

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

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

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

            var width = clip.Right - clip.Left;

            if (width <= 0)
                return;

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

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

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

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

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

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

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

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

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

                    // Advance to the next line
                    pos_y++;
                    if (MaskPtr.HasValue)
                    {
                        maskPtr.OffsetY(1);
                    }
                    pn.OffsetY(1);
                }
            }
        }
Пример #8
0
 public PixelNavigator GetMaskBuffer(int x, int y, int i)
 {
     var nav = new PixelNavigator(maskBuffer[i], NumStrips, 1);
     nav.GoTo(x, y);
     return nav;
 }
Пример #9
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++];
            }
        }
Пример #10
0
        protected void GetPixel(int x, int y)
        {
            var vs = FindVirtScreen(y);
            if (vs == null || x > ScreenWidth - 1 || x < 0)
            {
                Push(-1);
                return;
            }

            var nav = new PixelNavigator(vs.Surfaces[0]);
            nav.GoTo(x, y - vs.TopLine);
            var pixel = nav.Read();
            Push(pixel);
        }
Пример #11
0
        public override void PrintChar(int chr, bool ignoreCharsetMask)
        {
            Rect shadow;

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

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

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

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

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

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

            Surface s;

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

            int offsetX = 0;
            int drawTop = Top;

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

            var dst = new PixelNavigator(s);

            dst.GoTo(Left + offsetX, drawTop);

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

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

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

            Left += width;

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

            if (Str.Bottom < shadow.Bottom)
            {
                Str.Bottom = shadow.Bottom;
            }
        }
Пример #12
0
        protected override void DrawBits1(Surface dest, int x, int y, BinaryReader src, int drawTop, int width, int height)
        {
            if (_sjisCurChar != 0)
            {
//                Debug.Assert(Vm._cjkFont);
//                Vm._cjkFont.drawChar(dest, _sjisCurChar, x, y, _color, _shadowColor);
                return;
            }
            bool scale2x = ((dest == Vm.TextSurface) && (Vm.TextSurfaceMultiplier == 2) /*&& !(_sjisCurChar >= 256 && Vm.UseCJKMode)*/);

            byte bits  = 0;
            var  col   = Color;
            var  bpp   = Surface.GetBytesPerPixel(dest.PixelFormat);
            int  pitch = dest.Pitch - width * bpp;
            var  dst   = new PixelNavigator(dest);

            dst.GoTo(x, y);
            var dst2 = new PixelNavigator(dst);

            dst2.OffsetY(1);

            var dst3 = new PixelNavigator(dst2);
            var dst4 = new PixelNavigator(dst2);

            if (scale2x)
            {
                dst3.OffsetY(1);
                dst4.OffsetY(1);
                pitch <<= 1;
            }

            for (y = 0; y < height && y + drawTop < dest.Height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    if ((x % 8) == 0)
                    {
                        bits = src.ReadByte();
                    }
                    if (((bits & ScummHelper.RevBitMask(x % 8)) != 0) && y + drawTop >= 0)
                    {
                        if (bpp == 2)
                        {
                            if (_enableShadow)
                            {
                                dst.WriteUInt16(2, Vm._16BitPalette[_shadowColor]);
                                dst.WriteUInt16(2 + dest.Pitch, Vm._16BitPalette[_shadowColor]);
                            }
                            dst.WriteUInt16(Vm._16BitPalette[Color]);
                        }
                        else
                        {
                            if (_enableShadow)
                            {
                                if (scale2x)
                                {
                                    dst.Write(2, _shadowColor);
                                    dst.Write(3, _shadowColor);
                                    dst2.Write(2, _shadowColor);
                                    dst2.Write(3, _shadowColor);

                                    dst3.Write(0, _shadowColor);
                                    dst3.Write(1, _shadowColor);
                                    dst4.Write(0, _shadowColor);
                                    dst4.Write(0, _shadowColor);
                                }
                                else
                                {
                                    dst2.Write(_shadowColor);
                                    dst.Write(1, _shadowColor);
                                }
                            }
                            dst.Write(col);

                            if (scale2x)
                            {
                                dst.Write(1, col);
                                dst2.Write(0, col);
                                dst2.Write(1, col);
                            }
                        }
                    }
                    dst.OffsetX(1);
                    dst2.OffsetX(1);
                    if (scale2x)
                    {
                        dst.OffsetX(1);
                        dst2.OffsetX(1);
                        dst3.OffsetX(1);
                        dst4.OffsetX(1);
                    }
                }

                dst.OffsetX(pitch / dst.BytesByPixel);
                dst2.OffsetX(pitch / dst2.BytesByPixel);
                dst3.OffsetX(pitch / dst3.BytesByPixel);
                dst4.OffsetX(pitch / dst4.BytesByPixel);
            }
        }
Пример #13
0
        public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn)
        {
            var x = p.X;
            var y = p.Y;

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

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

            int sx = x - vs.XStart / 8;

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

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

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

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

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

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

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

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

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

                DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags);
            }
        }
Пример #14
0
        protected void RestoreBackground(Rect rect, byte backColor = 0)
        {
            VirtScreen vs;

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

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

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

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

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

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

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

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

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

            if (height == 0)
                return;

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

                if (Game.Features.HasFlag(GameFeatures.Is16BitColor))
                    Gdi.Fill(screenBuf, _16BitPalette[backColor], width, height);
                else
                    Gdi.Fill(screenBuf, backColor, width, height);
            }
        }
Пример #15
0
        public void DrawBitmap(ImageData img, VirtScreen vs, Point p, int width, int height, int stripnr, int numstrip, int roomWidth, DrawBitmaps flags, bool isLightOn)
        {
            var x = p.X;
            var y = p.Y;
            if ((_vm.TownsPaletteFlags & 2) != 0)
            {
                int cx = (x - _vm.ScreenStartStrip) << 3;
                Gdi.Fill(_vm.TextSurface, 
                    new Rect(cx * _vm.TextSurfaceMultiplier, y * _vm.TextSurfaceMultiplier, 
                        (cx + width - 1) * _vm.TextSurfaceMultiplier, (y + height - 1) * _vm.TextSurfaceMultiplier), 0);
            }

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

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

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

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

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

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

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

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

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

                DecodeMask(x, y, width, height, stripnr, img.ZPlanes, transpStrip, flags);
            }
        }
Пример #16
0
        void DrawStripEGA(PixelNavigator navDst, BinaryReader src, int height)
        {
            byte color;
            int  run;
            int  x = 0, y = 0;
            int  z;

            navDst = new PixelNavigator(navDst);

            while (x < 8)
            {
                color = src.ReadByte();

                if ((color & 0x80) != 0)
                {
                    run = color & 0x3f;

                    if ((color & 0x40) != 0)
                    {
                        color = src.ReadByte();

                        if (run == 0)
                        {
                            run = src.ReadByte();
                        }
                        for (z = 0; z < run; z++)
                        {
                            navDst.GoTo(x, y);
                            navDst.Write((z & 1) != 0 ? RoomPalette[(color & 0xf) + paletteMod] : RoomPalette[(color >> 4) + paletteMod]);

                            y++;
                            if (y >= height)
                            {
                                y = 0;
                                x++;
                            }
                        }
                    }
                    else
                    {
                        if (run == 0)
                        {
                            run = src.ReadByte();
                        }

                        for (z = 0; z < run; z++)
                        {
                            navDst.GoTo(x - 1, y);
                            var col = navDst.Read();
                            navDst.GoTo(x, y);
                            navDst.Write(col);

                            y++;
                            if (y >= height)
                            {
                                y = 0;
                                x++;
                            }
                        }
                    }
                }
                else
                {
                    run = color >> 4;
                    if (run == 0)
                    {
                        run = src.ReadByte();
                    }

                    for (z = 0; z < run; z++)
                    {
                        navDst.GoTo(x, y);
                        navDst.Write(RoomPalette[(color & 0xf) + paletteMod]);

                        y++;
                        if (y >= height)
                        {
                            y = 0;
                            x++;
                        }
                    }
                }
            }
        }
Пример #17
0
        void DrawFlashlight()
        {
            int i, j, x, y;
            var vs = MainVirtScreen;

            // Remove the flash light first if it was previously drawn
            if (_flashlight.IsDrawn)
            {
                MarkRectAsDirty(MainVirtScreen, _flashlight.X, _flashlight.X + _flashlight.W,
                    _flashlight.Y, _flashlight.Y + _flashlight.H, Gdi.UsageBitDirty);

                if (_flashlight.PixelNavigator.HasValue)
                {
                    Gdi.Fill(_flashlight.PixelNavigator.Value, 0, _flashlight.W, _flashlight.H);
                }
                _flashlight.IsDrawn = false;
            }

            if (_flashlight.XStrips == 0 || _flashlight.YStrips == 0)
                return;

            // Calculate the area of the flashlight
            if (Game.GameId == GameId.Zak || Game.GameId == GameId.Maniac)
            {
                x = _mousePos.X + vs.XStart;
                y = _mousePos.Y - vs.TopLine;
            }
            else
            {
                var a = Actors[Variables[VariableEgo.Value]];
                x = a.Position.X;
                y = a.Position.Y;
            }
            _flashlight.W = _flashlight.XStrips * 8;
            _flashlight.H = _flashlight.YStrips * 8;
            _flashlight.X = x - _flashlight.W / 2 - _screenStartStrip * 8;
            _flashlight.Y = y - _flashlight.H / 2;

            if (Game.GameId == GameId.Loom)
                _flashlight.Y -= 12;

            // Clip the flashlight at the borders
            if (_flashlight.X < 0)
                _flashlight.X = 0;
            else if (_flashlight.X + _flashlight.W > Gdi.NumStrips * 8)
                _flashlight.X = Gdi.NumStrips * 8 - _flashlight.W;
            if (_flashlight.Y < 0)
                _flashlight.Y = 0;
            else if (_flashlight.Y + _flashlight.H > vs.Height)
                _flashlight.Y = vs.Height - _flashlight.H;

            // Redraw any actors "under" the flashlight
            for (i = _flashlight.X / 8; i < (_flashlight.X + _flashlight.W) / 8; i++)
            {
                Debug.Assert(0 <= i && i < Gdi.NumStrips);
                Gdi.SetGfxUsageBit(_screenStartStrip + i, Gdi.UsageBitDirty);
                vs.TDirty[i] = 0;
                vs.BDirty[i] = vs.Height;
            }

            var pn = new PixelNavigator(vs.Surfaces[0]);
            pn.GoTo(_flashlight.X + vs.XStart, _flashlight.Y);
            pn = new PixelNavigator(pn);
            _flashlight.PixelNavigator = pn;
            var bgbak = new PixelNavigator(vs.Surfaces[1]);
            bgbak.GoTo(_flashlight.X + vs.XStart, _flashlight.Y);

            Gdi.Blit(pn, bgbak, _flashlight.W, _flashlight.H);

            // Round the corners. To do so, we simply hard-code a set of nicely
            // rounded corners.
            var corner_data = new [] { 8, 6, 4, 3, 2, 2, 1, 1 };
            int minrow = 0;
            int maxcol = (_flashlight.W - 1);
            int maxrow = (_flashlight.H - 1);

            for (i = 0; i < 8; i++, minrow++, maxrow--)
            {
                int d = corner_data[i];

                for (j = 0; j < d; j++)
                {
                    if (vs.BytesPerPixel == 2)
                    {
                        pn.GoTo(j, minrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(maxcol - j, minrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(j, maxrow);
                        pn.WriteUInt16(0);
                        pn.GoTo(maxcol - j, maxrow);
                        pn.WriteUInt16(0);
                    }
                    else
                    {
                        pn.GoTo(j, minrow);
                        pn.Write(0);
                        pn.GoTo(maxcol - j, minrow);
                        pn.Write(0);
                        pn.GoTo(j, maxrow);
                        pn.Write(0);
                        pn.GoTo(maxcol - j, maxrow);
                        pn.Write(0);
                    }
                }
            }

            _flashlight.IsDrawn = true;
        }
Пример #18
0
        protected override void DrawBits1(Surface dest, int x, int y, BinaryReader src, int drawTop, int width, int height)
        {
            if (_sjisCurChar != 0)
            {
//                Debug.Assert(Vm._cjkFont);
//                Vm._cjkFont.drawChar(dest, _sjisCurChar, x, y, _color, _shadowColor);
                return;
            }
            bool scale2x = ((dest == Vm.TextSurface) && (Vm.TextSurfaceMultiplier == 2) /*&& !(_sjisCurChar >= 256 && Vm.UseCJKMode)*/);

            byte bits = 0;
            var col = Color;
            var bpp = Surface.GetBytesPerPixel(dest.PixelFormat);
            int pitch = dest.Pitch - width * bpp;
            var dst = new PixelNavigator(dest);
            dst.GoTo(x, y);
            var dst2 = new PixelNavigator(dst);
            dst2.OffsetY(1);

            var dst3 = new PixelNavigator(dst2);
            var dst4 = new PixelNavigator(dst2);
            if (scale2x)
            {
                dst3.OffsetY(1);
                dst4.OffsetY(1);
                pitch <<= 1;
            }

            for (y = 0; y < height && y + drawTop < dest.Height; y++)
            {
                for (x = 0; x < width; x++)
                {
                    if ((x % 8) == 0)
                        bits = src.ReadByte();
                    if (((bits & ScummHelper.RevBitMask(x % 8)) != 0) && y + drawTop >= 0)
                    {
                        if (bpp == 2)
                        {
                            if (_enableShadow)
                            {
                                dst.WriteUInt16(2, Vm._16BitPalette[_shadowColor]);
                                dst.WriteUInt16(2 + dest.Pitch, Vm._16BitPalette[_shadowColor]);
                            }
                            dst.WriteUInt16(Vm._16BitPalette[Color]);
                        }
                        else
                        {
                            if (_enableShadow)
                            {
                                if (scale2x)
                                {
                                    dst.Write(2, _shadowColor);
                                    dst.Write(3, _shadowColor);
                                    dst2.Write(2, _shadowColor);
                                    dst2.Write(3, _shadowColor);

                                    dst3.Write(0, _shadowColor);
                                    dst3.Write(1, _shadowColor);
                                    dst4.Write(0, _shadowColor);
                                    dst4.Write(0, _shadowColor);
                                }
                                else
                                {
                                    dst2.Write(_shadowColor);
                                    dst.Write(1, _shadowColor);
                                }
                            }
                            dst.Write(col);

                            if (scale2x)
                            {
                                dst.Write(1, col);
                                dst2.Write(0, col);
                                dst2.Write(1, col);
                            }
                        }
                    }
                    dst.OffsetX(1);
                    dst2.OffsetX(1);
                    if (scale2x)
                    {
                        dst.OffsetX(1);
                        dst2.OffsetX(1);
                        dst3.OffsetX(1);
                        dst4.OffsetX(1);
                    }
                }

                dst.OffsetX(pitch / dst.BytesByPixel);
                dst2.OffsetX(pitch / dst2.BytesByPixel);
                dst3.OffsetX(pitch / dst3.BytesByPixel);
                dst4.OffsetX(pitch / dst4.BytesByPixel);
            }
        }
Пример #19
0
        public void ResetBackground(int top, int bottom, int strip)
        {
            var vs = _vm.MainVirtScreen;

            if (top < 0)
                top = 0;

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

            if (top >= bottom)
                return;

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

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

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

            int numLinesToProcess = bottom - top;
            if (numLinesToProcess > 0)
            {
                var navDest = new PixelNavigator(vs.Surfaces[0]);
                navDest.GoTo(strip * 8 + vs.XStart, top);
                if (_vm.IsLightOn())
                {
                    var bgBakNav = new PixelNavigator(vs.Surfaces[1]);
                    bgBakNav.GoTo(strip * 8 + vs.XStart, top);
                    Copy8Col(navDest, bgBakNav, numLinesToProcess);
                }
                else
                {
                    Clear8Col(navDest, numLinesToProcess);
                }
            }
        }
Пример #20
0
        protected override byte DrawLimb(Actor a, int limb)
        {
            var a0 = (Actor0)a;

            if (limb >= 8)
            {
                return(0);
            }

            if (limb == 0)
            {
                DrawTop    = 200;
                DrawBottom = 0;
            }

            // Invalid current position?
            if (a.Cost.Curpos[limb] == 0xFFFF)
            {
                return(0);
            }

            _loaded.LoadCostume(a.Costume);
            byte frame = _loaded.Data[_loaded.FrameOffsets + a.Cost.Curpos[limb] + a.Cost.Active[limb]];

            // Get the frame ptr
            byte ptrLow      = _loaded.Data[9 + frame];
            byte ptrHigh     = (byte)(ptrLow + _loaded.Data[4]);
            int  frameOffset = (_loaded.Data[9 + ptrHigh] << 8) + _loaded.Data[9 + ptrLow + 2];         // 0x23EF / 0x2400

            var data = 9 + frameOffset;

            // Set up the palette data
            var palette = new byte[4];

            if (_vm.GetCurrentLights().HasFlag(LightModes.ActorUseColors))
            {
                palette[1] = 10;
                palette[2] = CostumeLoader0.actorV0Colors[ActorID];
            }
            else
            {
                palette[2] = 11;
                palette[3] = 11;
            }

            int width   = _loaded.Data[data];
            int height  = _loaded.Data[data + 1];
            int offsetX = _xmove + _loaded.Data[data + 2];
            int offsetY = _ymove + _loaded.Data[data + 3];

            _xmove += (sbyte)_loaded.Data[data + 4];
            _ymove += (sbyte)_loaded.Data[data + 5];
            data   += 6;

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

            int xpos = (int)(ActorX + (a0.LimbFlipped[limb] ? -1 : +1) * (offsetX * 8 - a.Width / 2));
            // +1 as we appear to be 1 pixel away from the original interpreter
            int ypos = ActorY - offsetY + 1;

            var dst = new PixelNavigator(startNav);

            // This code is very similar to procC64()
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    byte color = _loaded.Data[data + y * width + x];

                    int destX = xpos + (a0.LimbFlipped[limb] ? -(x + 1) : x) * 8;
                    int destY = ypos + y;

                    if (destY >= 0 && destY < _h && destX >= 0 && destX < _w)
                    {
                        dst.GoTo(destX, destY);
                        var mask = _vm.GetMaskBuffer(0, destY, ZBuffer);
                        if (a0.LimbFlipped[limb])
                        {
                            LINE(0, 0, color, palette, dst, mask, destX);
                            LINE(2, 2, color, palette, dst, mask, destX);
                            LINE(4, 4, color, palette, dst, mask, destX);
                            LINE(6, 6, color, palette, dst, mask, destX);
                        }
                        else
                        {
                            LINE(6, 0, color, palette, dst, mask, destX);
                            LINE(4, 2, color, palette, dst, mask, destX);
                            LINE(2, 4, color, palette, dst, mask, destX);
                            LINE(0, 6, color, palette, dst, mask, destX);
                        }
                    }
                }
            }

            DrawTop    = Math.Min(DrawTop, ypos);
            DrawBottom = Math.Max(DrawBottom, ypos + height);
            if (a0.LimbFlipped[limb])
            {
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, xpos - (width * 8), xpos, ypos, ypos + height, ActorID);
            }
            else
            {
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, xpos, xpos + (width * 8), ypos, ypos + height, ActorID);
            }
            return(0);
        }
Пример #21
0
        public static void Fill(Surface surface, Rect r, int color)
        {
            r = new Rect(r.Left, r.Top, r.Right, r.Bottom);
            r.Clip(surface.Width, surface.Height);

            if (!r.IsValid)
            {
                return;
            }

            int  width     = r.Width;
            int  lineLen   = width;
            int  height    = r.Height;
            bool useMemset = true;

            var bpp = Surface.GetBytesPerPixel(surface.PixelFormat);

            if (bpp == 2)
            {
                lineLen *= 2;
                if ((ushort)color != ((color & 0xff) | (color & 0xff) << 8))
                {
                    useMemset = false;
                }
            }
            else if (bpp == 4)
            {
                useMemset = false;
            }
            else if (bpp != 1)
            {
                throw new InvalidOperationException("Surface::fillRect: bytesPerPixel must be 1, 2, or 4");
            }

            if (useMemset)
            {
                var pn = new PixelNavigator(surface);
                pn.GoTo(r.Left, r.Top);
                for (int i = 0; i < height; i++)
                {
                    pn.Set((byte)color, lineLen);
                    pn.OffsetY(1);
                }
            }
            else
            {
                if (bpp == 2)
                {
                    var pn = new PixelNavigator(surface);
                    pn.GoTo(r.Left, r.Top);
                    for (int i = 0; i < height; i++)
                    {
                        pn.Set((ushort)color, lineLen);
                        pn.OffsetX(surface.Width);
                    }
                }
                else
                {
                    var pn = new PixelNavigator(surface);
                    pn.GoTo(r.Left, r.Top);
                    for (int i = 0; i < height; i++)
                    {
                        pn.Set((uint)color, lineLen);
                        pn.OffsetX(surface.Width / 2);
                    }
                }
            }
        }
Пример #22
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);
        }
Пример #23
0
        void DrawStripEGA(PixelNavigator navDst, BinaryReader src, int height)
        {
            byte color;
            int run;
            int x = 0, y = 0;
            int z;

            navDst = new PixelNavigator(navDst);

            while (x < 8)
            {
                color = src.ReadByte();

                if ((color & 0x80) != 0)
                {
                    run = color & 0x3f;

                    if ((color & 0x40) != 0)
                    {
                        color = src.ReadByte();

                        if (run == 0)
                        {
                            run = src.ReadByte();
                        }
                        for (z = 0; z < run; z++)
                        {
                            navDst.GoTo(x, y);
                            navDst.Write((z & 1) != 0 ? RoomPalette[(color & 0xf) + paletteMod] : RoomPalette[(color >> 4) + paletteMod]);

                            y++;
                            if (y >= height)
                            {
                                y = 0;
                                x++;
                            }
                        }
                    }
                    else
                    {
                        if (run == 0)
                        {
                            run = src.ReadByte();
                        }

                        for (z = 0; z < run; z++)
                        {
                            navDst.GoTo(x - 1, y);
                            var col = navDst.Read();
                            navDst.GoTo(x, y);
                            navDst.Write(col);

                            y++;
                            if (y >= height)
                            {
                                y = 0;
                                x++;
                            }
                        }
                    }
                }
                else
                {
                    run = color >> 4;
                    if (run == 0)
                    {
                        run = src.ReadByte();
                    }

                    for (z = 0; z < run; z++)
                    {
                        navDst.GoTo(x, y);
                        navDst.Write(RoomPalette[(color & 0xf) + paletteMod]);

                        y++;
                        if (y >= height)
                        {
                            y = 0;
                            x++;
                        }
                    }
                }
            }
        }
Пример #24
0
        protected void TownsDrawStripToScreen(VirtScreen vs, int dstX, int dstY, int srcX, int srcY, int width, int height)
        {
            if (width <= 0 || height <= 0)
                return;

            int m = _textSurfaceMultiplier;

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

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

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

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

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

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

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

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

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

            _townsScreen.AddDirtyRect(dstX * m, dstY * m, width * m, height * m);
        }
Пример #25
0
        void PrintCharIntern(byte[] fontPtr, int charPos, int origWidth, int origHeight, int width, int height, VirtScreen vs, bool ignoreCharsetMask)
        {
            int drawTop = Top - vs.TopLine;

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

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

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

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

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

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

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

                // Blit the image data
                if (w > 0)
                {
                    while (h-- > 0)
                    {
                        for (int i = 0; i < w; i++)
                        {
                            back.Value.Write(dstPtr.Read());
                            back.Value.OffsetX(1);
                            dstPtr.OffsetX(1);
                        }
                        back.Value.Offset(-w, 1);
                        dstPtr.Offset(-w, 1);
                    }
                }
            }
        }
Пример #26
0
        protected override void PrepareDrawBitmap(ImageData img, VirtScreen vs,
                               Point p, int width, int height,
                               int stripnr, int numstrip)
        {
            var ptr = img.Data;
            //
            // Since V3, all graphics data was encoded in strips, which is very efficient
            // for redrawing only parts of the screen. However, V2 is different: here
            // the whole graphics are encoded as one big chunk. That makes it rather
            // difficult to draw only parts of a room/object. We handle the V2 graphics
            // differently from all other (newer) graphic formats for this reason.
            //
            var table = (_objectMode ? null : _roomStrips);
            int left = (stripnr * 8);
            int right = left + (numstrip * 8);
            PixelNavigator navDst;
            var srcOffset = 0;
            byte color, data = 0;
            int run;
            bool dither = false;
            byte[] dither_table = new byte[128];
            var ditherOffset = 0;
            int theX, theY, maxX;

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

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

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

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

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

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

                    if (left <= theX)
                    {
                        mask_ptr.Write(data);
                        mask_ptr.OffsetY(1);
                    }
                    theY++;
                    if (theY >= height)
                    {
                        if (left <= theX)
                        {
                            mask_ptr.Offset(1, -height);
                        }
                        theY = 0;
                        theX += 8;
                        if (theX >= right)
                            break;
                    }
                } while ((--run) != 0);
                run = ptr[srcOffset++];
            }
        }
Пример #27
0
 public override void DrawChar(int chr, Surface s, int x, int y)
 {
     if (!PrepareDraw(chr))
         return;
     var pn = new PixelNavigator(s);
     pn.GoTo(x, y);
     DrawBitsN(s, pn, _fontPtr, _charPos, _fontPtr[_fontPos], y, _width, _height);
 }
Пример #28
0
        public override void PrintChar(int chr, bool ignoreCharsetMask)
        {
            Rect shadow;

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

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

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

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

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

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

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

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

            var dst = new PixelNavigator(s);
            dst.GoTo(Left + offsetX, drawTop);

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

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

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

            Left += width;

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

            if (Str.Bottom < shadow.Bottom)
                Str.Bottom = shadow.Bottom;
        }
Пример #29
0
        protected override void DrawBitsN(Surface s, PixelNavigator dst, IList<byte> src, int srcPos, byte bpp, int drawTop, int width, int height)
        {
//            if (_sjisCurChar)
//            {
//                assert(Vm._cjkFont);
//                Vm._cjkFont.drawChar(Vm._textSurface, _sjisCurChar, _left * Vm._textSurfaceMultiplier, (_top - Vm._screenTop) * Vm._textSurfaceMultiplier, Vm._townsCharsetColorMap[1], _shadowColor);
//                return;
//            }

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

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

            int pitch = Vm.TextSurface.Pitch - width;

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

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

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

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

                    bits <<= bpp;
                    numbits -= bpp;
                    if (numbits == 0)
                    {
                        bits = src[srcPos++];
                        numbits = 8;
                    }
                }
                dst.OffsetX(pitch / dst.BytesByPixel);
                dst2.OffsetX(pitch / dst2.BytesByPixel);
            }
        }
Пример #30
0
        protected override void DrawBitsN(Surface s, PixelNavigator dst, IList <byte> src, int srcPos, byte bpp, int drawTop, int width, int height)
        {
//            if (_sjisCurChar)
//            {
//                assert(Vm._cjkFont);
//                Vm._cjkFont.drawChar(Vm._textSurface, _sjisCurChar, _left * Vm._textSurfaceMultiplier, (_top - Vm._screenTop) * Vm._textSurfaceMultiplier, Vm._townsCharsetColorMap[1], _shadowColor);
//                return;
//            }

            bool scale2x = (Vm.TextSurfaceMultiplier == 2);

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

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

            int pitch = Vm.TextSurface.Pitch - width;

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

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

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

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

                    bits   <<= bpp;
                    numbits -= bpp;
                    if (numbits == 0)
                    {
                        bits    = src[srcPos++];
                        numbits = 8;
                    }
                }
                dst.OffsetX(pitch / dst.BytesByPixel);
                dst2.OffsetX(pitch / dst2.BytesByPixel);
            }
        }
Пример #31
0
        public void DrawBomp()
        {
            Rect clip;
            byte skip_y_bits = 0x80;
            byte skip_y_new  = 0;

            byte[] bomp_scaling_x = new byte[64];
            byte[] bomp_scaling_y = new byte[64];

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

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

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

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

            var src = Src;
            var pn  = new PixelNavigator(Dst);

            pn.GoTo(X + clip.Left, Y);

            var            maskbit = ScummHelper.RevBitMask((X + clip.Left) & 7);
            PixelNavigator maskPtr = new PixelNavigator();

            // Mask against any additionally imposed mask
            if (MaskPtr.HasValue)
            {
                maskPtr = MaskPtr.Value;
                maskPtr.GoTo((X + clip.Left) / 8, Y);
            }

            var scalingYPtr = 0;

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

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

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

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

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

            var width = clip.Right - clip.Left;

            if (width <= 0)
            {
                return;
            }

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

            byte tmp;

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

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

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

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

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

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

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

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

                    // Advance to the next line
                    pos_y++;
                    if (MaskPtr.HasValue)
                    {
                        maskPtr.OffsetY(1);
                    }
                    pn.OffsetY(1);
                }
            }
        }
Пример #32
0
        protected virtual void KernelGetFunctions()
        {
            var vs = MainVirtScreen;

            var args = GetStackList(30);

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

                    Push(GetKeyState(args[1]));
                    break;
                case 212:
                    {
                        var a = Actors[args[1]];
                        // This is used by walk scripts
                        Push(a.Frame);
                    }
                    break;
                case 213:
                    {
                        var slot = GetVerbSlot(args[1], 0);
                        Push(Verbs[slot].CurRect.Left);
                    }
                    break;
                case 214:
                    {
                        var slot = GetVerbSlot(args[1], 0);
                        Push(Verbs[slot].CurRect.Top);
                    }
                    break;
                case 215:
                    if ((_extraBoxFlags[args[1]] & 0x00FF) == 0x00C0)
                    {
                        Push(_extraBoxFlags[args[1]]);
                    }
                    else
                    {
                        Push((int)GetBoxFlags((byte)args[1]));
                    }
                    break;
                default:
                    throw new NotSupportedException(string.Format("KernelGetFunctions: default case {0}", args[0]));
            }
        }
Пример #33
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;
 }
Пример #34
0
        byte Codec16(int xmoveCur, int ymoveCur)
        {
            Debug.Assert(_vm.MainVirtScreen.BytesPerPixel == 1);

            if (ActorHitMode)
            {
//                Console.Error.WriteLine("codec16: _actorHitMode not yet implemented");
                return 0;
            }

            Rect clip;
            if (!_mirror)
            {
                clip.Left = (ActorX - xmoveCur - _width) + 1;
            }
            else
            {
                clip.Left = ActorX + xmoveCur;
            }

            clip.Top = ActorY + ymoveCur;
            clip.Right = clip.Left + _width;
            clip.Bottom = clip.Top + _height;

            var minx = 0;
            var miny = 0;
            var maxw = _vm.MainVirtScreen.Width;
            var maxh = _vm.MainVirtScreen.Height;

            MarkRectAsDirty(clip);

            var skip_x = 0;
            var skip_y = 0;
            var cur_x = _width - 1;
            var cur_y = _height - 1;

            if (clip.Left < minx)
            {
                skip_x = -clip.Left;
                clip.Left = 0;
            }

            if (clip.Right > maxw)
            {
                cur_x -= clip.Right - maxw;
                clip.Right = maxw;
            }

            if (clip.Top < miny)
            {
                skip_y -= clip.Top;
                clip.Top = 0;
            }

            if (clip.Bottom > maxh)
            {
                cur_y -= clip.Bottom - maxh;
                clip.Bottom = maxh;
            }

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

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

            int width_unk;

            var height_unk = clip.Top;
            int dir;

            if (!_mirror)
            {
                dir = -1;

                int tmp_skip_x = skip_x;
                skip_x = _width - 1 - cur_x;
                cur_x = _width - 1 - tmp_skip_x;
                width_unk = clip.Right - 1;
            }
            else
            {
                dir = 1;
                width_unk = clip.Left;
            }

            var out_height = cur_y - skip_y;
            if (out_height < 0)
            {
                out_height = -out_height;
            }
            out_height++;

            cur_x -= skip_x;
            if (cur_x < 0)
            {
                cur_x = -cur_x;
            }
            cur_x++;

            int numskip_before = skip_x + (skip_y * _width);
            int numskip_after = _width - cur_x;

            _pixelsNavigator = new PixelNavigator(_vm.MainVirtScreen.Surfaces[0]);
            _pixelsNavigator.GoTo(width_unk, height_unk);

            Akos16Decompress(_pixelsNavigator, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, 255, clip.Left, clip.Top, ZBuffer);
            return 0;
        }
Пример #35
0
        public static void Fill(Surface surface, Rect r, int color)
        {
            r = new Rect(r.Left, r.Top, r.Right, r.Bottom);
            r.Clip(surface.Width, surface.Height);

            if (!r.IsValid)
                return;

            int width = r.Width;
            int lineLen = width;
            int height = r.Height;
            bool useMemset = true;

            var bpp = Surface.GetBytesPerPixel(surface.PixelFormat);
            if (bpp == 2)
            {
                lineLen *= 2;
                if ((ushort)color != ((color & 0xff) | (color & 0xff) << 8))
                    useMemset = false;
            }
            else if (bpp == 4)
            {
                useMemset = false;
            }
            else if (bpp != 1)
            {
                throw new InvalidOperationException("Surface::fillRect: bytesPerPixel must be 1, 2, or 4");
            }

            if (useMemset)
            {
                var pn = new PixelNavigator(surface);
                pn.GoTo(r.Left, r.Top);
                for (int i = 0; i < height; i++)
                {
                    pn.Set((byte)color, lineLen);
                    pn.OffsetY(1);
                }
            }
            else
            {
                if (bpp == 2)
                {
                    var pn = new PixelNavigator(surface);
                    pn.GoTo(r.Left, r.Top);
                    for (int i = 0; i < height; i++)
                    {
                        pn.Set((ushort)color, lineLen);
                        pn.OffsetX(surface.Width);
                    }
                }
                else
                {
                    var pn = new PixelNavigator(surface);
                    pn.GoTo(r.Left, r.Top);
                    for (int i = 0; i < height; i++)
                    {
                        pn.Set((uint)color, lineLen);
                        pn.OffsetX(surface.Width / 2);
                    }
                }
            }
        }
Пример #36
0
        void PrintCharIntern(byte[] fontPtr, int charPos, int origWidth, int origHeight, int width, int height, VirtScreen vs, bool ignoreCharsetMask)
        {
            int drawTop = Top - vs.TopLine;

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

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

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

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

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

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

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

            }
        }
Пример #37
0
 static void DumpZPlanes(Room room, string name)
 {
     if (room.Image != null)
     {
         for (int i = 0; i < room.Image.ZPlanes.Count; i++)
         {
             var zplane = room.Image.ZPlanes[i];
             var nStrips = zplane.StripOffsets.Count;
             var pixels = new byte[nStrips * room.Header.Height];
             var pn = new PixelNavigator(pixels, nStrips, 1);
             using (var ms = new MemoryStream(zplane.Data))
             {
                 for (int nStrip = 0; nStrip < nStrips; nStrip++)
                 {
                     var offset = zplane.StripOffsets[nStrip];
                     if (offset.HasValue)
                     {
                         ms.Seek(offset.Value, SeekOrigin.Begin);
                         pn.GoTo(nStrip, 0);
                         DecompressMaskImg(pn, ms, room.Header.Height);
                     }
                 }
             }
             using (var bmpZ = new System.Drawing.Bitmap(nStrips * 8, room.Header.Height))
             {
                 for (int j = 0; j < room.Header.Height; j++)
                 {
                     for (int x = 0; x < nStrips; x++)
                     {
                         for (int b = 0; b < 8; b++)
                         {
                             bmpZ.SetPixel(x * 8 + b, j, (pixels[x + j * nStrips] & (0x80 >> b)) != 0 ? System.Drawing.Color.White : System.Drawing.Color.Black);
                         }
                     }
                 }
                 bmpZ.Save(name + "_z" + i + ".png");
             }
         }
     }
 }
Пример #38
0
        protected void RedefineBuiltinCursorFromChar(int index, int chr)
        {
            // Cursor image in both Loom versions are based on images from charset.
            // This function is *only* supported for Loom!
            if (_game.GameId != Scumm.IO.GameId.Loom)
                throw new NotSupportedException("RedefineBuiltinCursorFromChar is *only* supported for Loom!");
            if (index < 0 || index >= 4)
                throw new ArgumentException("index");

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

            var ptr = _cursorImages[index];

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

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

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

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

            //	_charset->setCurID(oldID);
        }
Пример #39
0
 protected virtual void DrawBits1(Surface surface, int x, int y, BinaryReader src, int drawTop, int width, int height)
 {
     var dst = new PixelNavigator(surface);
     dst.GoTo(x, y);
     
     byte bits = 0;
     byte col = Color;
     //int pitch = surface.Pitch - width * surface.BytesPerPixel;
     var dst2 = new PixelNavigator(dst);
     dst2.OffsetY(1);
     
     for (y = 0; y < height && y + drawTop < surface.Height; y++)
     {
         for (x = 0; x < width; x++)
         {
             if ((x % 8) == 0)
                 bits = src.ReadByte();
             if ((bits & ScummHelper.RevBitMask(x % 8)) != 0 && y + drawTop >= 0)
             {
                 if (_shadowMode)
                 {
                     dst.OffsetX(1);
                     dst.Write(_shadowColor);
                     dst2.Write(_shadowColor);
                     dst2.OffsetX(1);
                     dst2.Write(_shadowColor);
                 }
                 dst.Write(col);
             }
             dst.OffsetX(1);
             dst2.OffsetX(1);
         }
     
         dst.OffsetX(surface.Width - width);
         dst2.OffsetX(surface.Width - width);
     }
 }
Пример #40
0
        byte Codec16(int xmoveCur, int ymoveCur)
        {
            Debug.Assert(_vm.MainVirtScreen.BytesPerPixel == 1);

            if (ActorHitMode)
            {
//                Console.Error.WriteLine("codec16: _actorHitMode not yet implemented");
                return(0);
            }

            Rect clip;

            if (!_mirror)
            {
                clip.Left = (ActorX - xmoveCur - _width) + 1;
            }
            else
            {
                clip.Left = ActorX + xmoveCur;
            }

            clip.Top    = ActorY + ymoveCur;
            clip.Right  = clip.Left + _width;
            clip.Bottom = clip.Top + _height;

            var minx = 0;
            var miny = 0;
            var maxw = _vm.MainVirtScreen.Width;
            var maxh = _vm.MainVirtScreen.Height;

            MarkRectAsDirty(clip);

            var skip_x = 0;
            var skip_y = 0;
            var cur_x  = _width - 1;
            var cur_y  = _height - 1;

            if (clip.Left < minx)
            {
                skip_x    = -clip.Left;
                clip.Left = 0;
            }

            if (clip.Right > maxw)
            {
                cur_x     -= clip.Right - maxw;
                clip.Right = maxw;
            }

            if (clip.Top < miny)
            {
                skip_y  -= clip.Top;
                clip.Top = 0;
            }

            if (clip.Bottom > maxh)
            {
                cur_y      -= clip.Bottom - maxh;
                clip.Bottom = maxh;
            }

            if ((clip.Left >= clip.Right) || (clip.Top >= clip.Bottom))
            {
                return(0);
            }

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

            int width_unk;

            var height_unk = clip.Top;
            int dir;

            if (!_mirror)
            {
                dir = -1;

                int tmp_skip_x = skip_x;
                skip_x    = _width - 1 - cur_x;
                cur_x     = _width - 1 - tmp_skip_x;
                width_unk = clip.Right - 1;
            }
            else
            {
                dir       = 1;
                width_unk = clip.Left;
            }

            var out_height = cur_y - skip_y;

            if (out_height < 0)
            {
                out_height = -out_height;
            }
            out_height++;

            cur_x -= skip_x;
            if (cur_x < 0)
            {
                cur_x = -cur_x;
            }
            cur_x++;

            int numskip_before = skip_x + (skip_y * _width);
            int numskip_after  = _width - cur_x;

            _pixelsNavigator = new PixelNavigator(_vm.MainVirtScreen.Surfaces[0]);
            _pixelsNavigator.GoTo(width_unk, height_unk);

            Akos16Decompress(_pixelsNavigator, _srcptr, cur_x, out_height, dir, numskip_before, numskip_after, 255, clip.Left, clip.Top, ZBuffer);
            return(0);
        }
Пример #41
0
        protected void DrawBoxCore(int x, int y, int x2, int y2, int color)
        {
            VirtScreen vs;

            if ((vs = FindVirtScreen(y)) == null)
                return;

            if (x > x2)
                ScummHelper.Swap(ref x, ref x2);

            if (y > y2)
                ScummHelper.Swap(ref y, ref y2);

            x2++;
            y2++;

            // Adjust for the topline of the VirtScreen
            y -= vs.TopLine;
            y2 -= vs.TopLine;

            // Clip the coordinates
            if (x < 0)
                x = 0;
            else if (x >= vs.Width)
                return;

            if (x2 < 0)
                return;
            if (x2 > vs.Width)
                x2 = vs.Width;

            if (y < 0)
                y = 0;
            else if (y > vs.Height)
                return;

            if (y2 < 0)
                return;

            if (y2 > vs.Height)
                y2 = vs.Height;

            int width = x2 - x;
            int height = y2 - y;

            // This will happen in the Sam & Max intro - see bug #1039162 - where
            // it would trigger an assertion in blit().

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

            MarkRectAsDirty(vs, x, x2, y, y2);

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

            // A check for -1 might be wrong in all cases since o5_drawBox() in its current form
            // is definitely not capable of passing a parameter of -1 (color range is 0 - 255).
            // Just to make sure I don't break anything I restrict the code change to FM-Towns
            // version 5 games where this change is necessary to fix certain long standing bugs.
            if (color == -1 || (color >= 254 && Game.Platform == Platform.FMTowns && (Game.GameId == GameId.Monkey2 || Game.GameId == GameId.Indy4)))
            {
                if (_game.Platform == Platform.FMTowns)
                {
                    if (color == 254)
                        TownsSetupPalCycleField(x, y, x2, y2);
                }
                else
                {
                    if (vs != MainVirtScreen)
                        Debug.WriteLine("can only copy bg to main window");

                    var bgbuff = new PixelNavigator(vs.Surfaces[1]);
                    bgbuff.GoTo(vs.XStart + x, y);

                    Gdi.Blit(backbuff, bgbuff, width, height);
                    if (_charset.HasMask)
                    {
                        var mask = new PixelNavigator(_textSurface);
                        mask.GoToIgnoreBytesByPixel(x * _textSurfaceMultiplier, (y - ScreenTop) * _textSurfaceMultiplier);
                        Gdi.Fill(mask, CharsetMaskTransparency, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
                    }
                }
            }
            else
            {
                if (_game.Features.HasFlag(GameFeatures.Is16BitColor))
                {
                    Gdi.Fill(backbuff, _16BitPalette[color], width, height);
                }
                else
                {
                    if (_game.Platform == Platform.FMTowns)
                    {
                        color = ((color & 0x0f) << 4) | (color & 0x0f);
                        var mask = new PixelNavigator(_textSurface);
                        mask.GoTo(x * _textSurfaceMultiplier, (y - ScreenTop + vs.TopLine) * _textSurfaceMultiplier);
                        Gdi.Fill(mask, (byte)color, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);

                        if (Game.GameId == GameId.Monkey2 || Game.GameId == GameId.Indy4 || ((Game.GameId == GameId.Indy3 || Game.GameId == GameId.Zak)
                            && vs != TextVirtScreen) || (_game.GameId == GameId.Loom && vs == MainVirtScreen))
                            return;
                    }

                    Gdi.Fill(backbuff, (byte)color, width, height);
                }
            }
        }
Пример #42
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;
            }
        }
Пример #43
0
        protected override byte DrawLimb(Actor a, int limb)
        {
            var a0 = (Actor0)a;

            if (limb >= 8)
                return 0;

            if (limb == 0)
            {
                DrawTop = 200;
                DrawBottom = 0;
            }

            // Invalid current position?
            if (a.Cost.Curpos[limb] == 0xFFFF)
                return 0;

            _loaded.LoadCostume(a.Costume);
            byte frame = _loaded.Data[_loaded.FrameOffsets + a.Cost.Curpos[limb] + a.Cost.Active[limb]];

            // Get the frame ptr
            byte ptrLow = _loaded.Data[9 + frame];
            byte ptrHigh = (byte)(ptrLow + _loaded.Data[4]);
            int frameOffset = (_loaded.Data[9 + ptrHigh] << 8) + _loaded.Data[9 + ptrLow + 2];          // 0x23EF / 0x2400

            var data = 9 + frameOffset;

            // Set up the palette data
            var palette = new byte[4];
            if (_vm.GetCurrentLights().HasFlag(LightModes.ActorUseColors))
            {
                palette[1] = 10;
                palette[2] = CostumeLoader0.actorV0Colors[ActorID];
            }
            else
            {
                palette[2] = 11;
                palette[3] = 11;
            }

            int width = _loaded.Data[data];
            int height = _loaded.Data[data + 1];
            int offsetX = _xmove + _loaded.Data[data + 2];
            int offsetY = _ymove + _loaded.Data[data + 3];
            _xmove += (sbyte)_loaded.Data[data + 4];
            _ymove += (sbyte)_loaded.Data[data + 5];
            data += 6;

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

            int xpos = (int)(ActorX + (a0.LimbFlipped[limb] ? -1 : +1) * (offsetX * 8 - a.Width / 2));
            // +1 as we appear to be 1 pixel away from the original interpreter
            int ypos = ActorY - offsetY + 1;

            var dst = new PixelNavigator(startNav);
            // This code is very similar to procC64()
            for (int y = 0; y < height; ++y)
            {
                for (int x = 0; x < width; ++x)
                {
                    byte color = _loaded.Data[data + y * width + x];

                    int destX = xpos + (a0.LimbFlipped[limb] ? -(x + 1) : x) * 8;
                    int destY = ypos + y;

                    if (destY >= 0 && destY < _h && destX >= 0 && destX < _w)
                    {
                        dst.GoTo(destX, destY);
                        var mask = _vm.GetMaskBuffer(0, destY, ZBuffer);
                        if (a0.LimbFlipped[limb])
                        {
                            LINE(0, 0, color, palette, dst, mask, destX);
                            LINE(2, 2, color, palette, dst, mask, destX);
                            LINE(4, 4, color, palette, dst, mask, destX);
                            LINE(6, 6, color, palette, dst, mask, destX);
                        }
                        else
                        {
                            LINE(6, 0, color, palette, dst, mask, destX);
                            LINE(4, 2, color, palette, dst, mask, destX);
                            LINE(2, 4, color, palette, dst, mask, destX);
                            LINE(0, 6, color, palette, dst, mask, destX);
                        }
                    }
                }
            }

            DrawTop = Math.Min(DrawTop, ypos);
            DrawBottom = Math.Max(DrawBottom, ypos + height);
            if (a0.LimbFlipped[limb])
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, xpos - (width * 8), xpos, ypos, ypos + height, ActorID);
            else
                _vm.MarkRectAsDirty(_vm.MainVirtScreen, xpos, xpos + (width * 8), ypos, ypos + height, ActorID);
            return 0;
        }