示例#1
0
        void RestoreCharsetBg()
        {
            _nextLeft = _string[0].Position.X;
            _nextTop  = _string[0].Position.Y + ScreenTop;

            if (_charset.HasMask)
            {
                _charset.HasMask  = false;
                _charset.Str.Left = -1;
                _charset.Left     = -1;

                // Restore background on the whole text area. This code is based on
                // restoreBackground(), but was changed to only restore those parts which are
                // currently covered by the charset mask.

                var vs = _charset.TextScreen;
                if (vs.Height == 0)
                {
                    return;
                }

                MarkRectAsDirty(vs, 0, vs.Width, 0, vs.Height, Gdi.UsageBitRestored);

                if (vs.HasTwoBuffers && _currentRoom != 0 && IsLightOn())
                {
                    if (vs != MainVirtScreen)
                    {
                        // Restore from back buffer
                        var screenBufNav = new PixelNavigator(vs.Surfaces[0]);
                        screenBufNav.OffsetX(vs.XStart);
                        var backNav = new PixelNavigator(vs.Surfaces[1]);
                        backNav.OffsetX(vs.XStart);
                        Gdi.Blit(screenBufNav, backNav, vs.Width, vs.Height);
                    }
                }
                else
                {
                    // Clear area
                    var screenBuf = vs.Surfaces[0].Pixels;
                    Array.Clear(screenBuf, 0, screenBuf.Length);
                }

                if (vs.HasTwoBuffers)
                {
                    // Clean out the charset mask
                    ClearTextSurface();
                }
            }
        }
示例#2
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);
                }
            }
        }
示例#3
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;
        }