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); }
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); }
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); }
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); }
/// <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); }
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])); } }