示例#1
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);
        }
示例#2
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);
        }
示例#3
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);
        }
示例#4
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);
        }
示例#5
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);
        }
示例#6
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]));
            }
        }