using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Emulation.Cores.Consoles.Sega.gpgx; using System.Drawing.Imaging; using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk { public partial class GenVDPViewer : Form, IToolFormAutoConfig { [RequiredService] private GPGX Emu { get; set; } private LibGPGX.VDPView View = new LibGPGX.VDPView(); int palindex = 0; public GenVDPViewer() { InitializeComponent(); bmpViewTiles.ChangeBitmapSize(512, 256); bmpViewPal.ChangeBitmapSize(16, 4); } unsafe static void DrawTile(int* dest, int pitch, byte* src, int* pal) { for (int j = 0; j < 8; j++) { *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; *dest++ = pal[*src++]; dest += pitch - 8; } } unsafe static void DrawNameTable(LibGPGX.VDPNameTable NT, ushort* vram, byte* tiles, int* pal, BmpView bv) { ushort* nametable = vram + NT.Baseaddr / 2; int tilew = NT.Width; int tileh = NT.Height; Size pixsize = new Size(tilew * 8, tileh * 8); bv.Size = pixsize; bv.ChangeBitmapSize(pixsize); var lockdata = bv.bmp.LockBits(new Rectangle(Point.Empty, pixsize), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int pitch = lockdata.Stride / sizeof(int); int* dest = (int*)lockdata.Scan0; for (int tiley = 0; tiley < tileh; tiley++) { for (int tilex = 0; tilex < tilew; tilex++) { ushort bgent = *nametable++; int palidx = bgent >> 9 & 0x30; int tileent = bgent & 0x1fff; // h and v flip are stored separately in cache DrawTile(dest, pitch, tiles + tileent * 64, pal + palidx); dest += 8; } dest -= 8 * tilew; dest += 8 * pitch; } bv.bmp.UnlockBits(lockdata); bv.Refresh(); } unsafe void DrawPalettes(int *pal) { var lockdata = bmpViewPal.bmp.LockBits(new Rectangle(0, 0, 16, 4), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int pitch = lockdata.Stride / sizeof(int); int* dest = (int*)lockdata.Scan0; for (int j = 0; j < 4; j++) { for (int i = 0; i < 16; i++) *dest++ = *pal++; dest += pitch - 16; } bmpViewPal.bmp.UnlockBits(lockdata); bmpViewPal.Refresh(); } unsafe void DrawTiles() { var lockdata = bmpViewTiles.bmp.LockBits(new Rectangle(0, 0, 512, 256), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); int pitch = lockdata.Stride / sizeof(int); int* dest = (int*)lockdata.Scan0; byte* src = (byte*)View.PatternCache; int* pal = 0x10 * palindex + (int*)View.ColorCache; for (int tile = 0; tile < 2048;) { DrawTile(dest, pitch, src, pal); dest += 8; src += 64; tile++; if ((tile & 63) == 0) dest += 8 * pitch - 512; } bmpViewTiles.bmp.UnlockBits(lockdata); bmpViewTiles.Refresh(); } public void UpdateValues() { if (Emu == null) return; Emu.UpdateVDPViewContext(View); unsafe { int* pal = (int*)View.ColorCache; //for (int i = 0; i < 0x40; i++) // pal[i] |= unchecked((int)0xff000000); DrawPalettes(pal); DrawTiles(); ushort *VRAMNT = (ushort*)View.VRAM; byte *tiles = (byte*)View.PatternCache; DrawNameTable(View.NTA, VRAMNT, tiles, pal, bmpViewNTA); DrawNameTable(View.NTB, VRAMNT, tiles, pal, bmpViewNTB); DrawNameTable(View.NTW, VRAMNT, tiles, pal, bmpViewNTW); } } public void FastUpdate() { // Do nothing } public void Restart() { UpdateValues(); } public bool AskSaveChanges() { return true; } public bool UpdateBefore { get { return true; } } private void bmpViewPal_MouseClick(object sender, MouseEventArgs e) { int idx = e.Y / 16; idx = Math.Min(3, Math.Max(idx, 0)); palindex = idx; DrawTiles(); } private void VDPViewer_KeyDown(object sender, KeyEventArgs e) { if (ModifierKeys.HasFlag(Keys.Control) && e.KeyCode == Keys.C) { // find the control under the mouse Point m = Cursor.Position; Control top = this; Control found; do { found = top.GetChildAtPoint(top.PointToClient(m)); top = found; } while (found != null && found.HasChildren); if (found is BmpView) { var bv = found as BmpView; Clipboard.SetImage(bv.bmp); } } } private void saveBGAScreenshotToolStripMenuItem_Click(object sender, EventArgs e) { bmpViewNTA.SaveFile(); } private void saveBGBScreenshotToolStripMenuItem_Click(object sender, EventArgs e) { bmpViewNTB.SaveFile(); } private void saveTilesScreenshotToolStripMenuItem_Click(object sender, EventArgs e) { bmpViewTiles.SaveFile(); } private void saveWindowScreenshotToolStripMenuItem_Click(object sender, EventArgs e) { bmpViewNTW.SaveFile(); } private void savePaletteScreenshotToolStripMenuItem_Click(object sender, EventArgs e) { bmpViewPal.SaveFile(); } private void closeToolStripMenuItem_Click(object sender, EventArgs e) { Close(); } private void GenVDPViewer_Load(object sender, EventArgs e) { } } }