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(); } } }
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); } } }
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; }