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