From 9c071bf45e6eed6f41cf7f05ce93b60370e255db Mon Sep 17 00:00:00 2001 From: goyuken Date: Sat, 15 Feb 2014 16:55:55 +0000 Subject: [PATCH] NES: add CHR ROM tile view to the PPU viewer. i'm not sure how generally useful this is, but it's something i wanted, so there. --- BizHawk.Client.Common/config/Config.cs | 1 + .../tools/NES/NESPPU.Designer.cs | 108 +++++++++++--- BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs | 135 +++++++++++++----- 3 files changed, 185 insertions(+), 59 deletions(-) diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs index 028abd337f..e56921051f 100644 --- a/BizHawk.Client.Common/config/Config.cs +++ b/BizHawk.Client.Common/config/Config.cs @@ -348,6 +348,7 @@ namespace BizHawk.Client.Common public ToolDialogSettings NesPPUSettings = new ToolDialogSettings(); public bool AutoLoadNESPPU = false; public int NESPPURefreshRate = 4; + public bool NESPPUChrRomView = false; // NESDebuger Settings public bool AutoLoadNESDebugger = false; diff --git a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.Designer.cs b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.Designer.cs index 1568d2bab3..35fd3a4b41 100644 --- a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.Designer.cs +++ b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.Designer.cs @@ -104,6 +104,11 @@ this.NesPPUStatusBar = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.Messagetimer = new System.Windows.Forms.Timer(this.components); + this.CHRROMGroup = new System.Windows.Forms.GroupBox(); + this.CHRROMView = new BizHawk.Client.EmuHawk.PatternViewer(); + this.numericUpDownCHRROMBank = new System.Windows.Forms.NumericUpDown(); + this.label5 = new System.Windows.Forms.Label(); + this.cHRROMTileViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.PatternGroup.SuspendLayout(); this.PatternContext.SuspendLayout(); this.PalettesGroup.SuspendLayout(); @@ -117,6 +122,8 @@ ((System.ComponentModel.ISupportInitialize)(this.RefreshRate)).BeginInit(); this.NesPPUMenu.SuspendLayout(); this.NesPPUStatusBar.SuspendLayout(); + this.CHRROMGroup.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownCHRROMBank)).BeginInit(); this.SuspendLayout(); // // PatternGroup @@ -471,7 +478,7 @@ this.SettingsSubMenu}); this.NesPPUMenu.Location = new System.Drawing.Point(0, 0); this.NesPPUMenu.Name = "NesPPUMenu"; - this.NesPPUMenu.Size = new System.Drawing.Size(574, 24); + this.NesPPUMenu.Size = new System.Drawing.Size(854, 24); this.NesPPUMenu.TabIndex = 10; this.NesPPUMenu.Text = "menuStrip1"; // @@ -488,65 +495,65 @@ this.toolStripSeparator2, this.ExitMenuItem}); this.FileSubMenu.Name = "FileSubMenu"; - this.FileSubMenu.Size = new System.Drawing.Size(37, 20); + this.FileSubMenu.Size = new System.Drawing.Size(35, 20); this.FileSubMenu.Text = "&File"; // // SavePaletteScreenshotMenuItem // this.SavePaletteScreenshotMenuItem.Name = "SavePaletteScreenshotMenuItem"; - this.SavePaletteScreenshotMenuItem.Size = new System.Drawing.Size(212, 22); + this.SavePaletteScreenshotMenuItem.Size = new System.Drawing.Size(206, 22); this.SavePaletteScreenshotMenuItem.Text = "Save Palette Screenshot..."; this.SavePaletteScreenshotMenuItem.Click += new System.EventHandler(this.SavePaletteScreenshotMenuItem_Click); // // SavePatternScreenshotMenuItem // this.SavePatternScreenshotMenuItem.Name = "SavePatternScreenshotMenuItem"; - this.SavePatternScreenshotMenuItem.Size = new System.Drawing.Size(212, 22); + this.SavePatternScreenshotMenuItem.Size = new System.Drawing.Size(206, 22); this.SavePatternScreenshotMenuItem.Text = "Save Pattern Screenshot..."; this.SavePatternScreenshotMenuItem.Click += new System.EventHandler(this.SavePatternScreenshotMenuItem_Click); // // SaveSpriteScreenshotMenuItem // this.SaveSpriteScreenshotMenuItem.Name = "SaveSpriteScreenshotMenuItem"; - this.SaveSpriteScreenshotMenuItem.Size = new System.Drawing.Size(212, 22); + this.SaveSpriteScreenshotMenuItem.Size = new System.Drawing.Size(206, 22); this.SaveSpriteScreenshotMenuItem.Text = "Save Sprite Screenshot..."; this.SaveSpriteScreenshotMenuItem.Click += new System.EventHandler(this.SaveSpriteScreenshotMenuItem_Click); // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(209, 6); + this.toolStripSeparator1.Size = new System.Drawing.Size(203, 6); // // CopyPaletteToClipboardMenuItem // this.CopyPaletteToClipboardMenuItem.Name = "CopyPaletteToClipboardMenuItem"; - this.CopyPaletteToClipboardMenuItem.Size = new System.Drawing.Size(212, 22); + this.CopyPaletteToClipboardMenuItem.Size = new System.Drawing.Size(206, 22); this.CopyPaletteToClipboardMenuItem.Text = "Copy Palette to Clipboard"; this.CopyPaletteToClipboardMenuItem.Click += new System.EventHandler(this.CopyPaletteToClipboardMenuItem_Click); // // CopyPatternToClipboardMenuItem // this.CopyPatternToClipboardMenuItem.Name = "CopyPatternToClipboardMenuItem"; - this.CopyPatternToClipboardMenuItem.Size = new System.Drawing.Size(212, 22); + this.CopyPatternToClipboardMenuItem.Size = new System.Drawing.Size(206, 22); this.CopyPatternToClipboardMenuItem.Text = "Copy Pattern to Clipboard"; this.CopyPatternToClipboardMenuItem.Click += new System.EventHandler(this.CopyPatternToClipboardMenuItem_Click); // // CopySpriteToClipboardMenuItem // this.CopySpriteToClipboardMenuItem.Name = "CopySpriteToClipboardMenuItem"; - this.CopySpriteToClipboardMenuItem.Size = new System.Drawing.Size(212, 22); + this.CopySpriteToClipboardMenuItem.Size = new System.Drawing.Size(206, 22); this.CopySpriteToClipboardMenuItem.Text = "Copy Sprite to Clipboard"; this.CopySpriteToClipboardMenuItem.Click += new System.EventHandler(this.CopySpriteToClipboardMenuItem_Click); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(209, 6); + this.toolStripSeparator2.Size = new System.Drawing.Size(203, 6); // // ExitMenuItem // this.ExitMenuItem.Name = "ExitMenuItem"; - this.ExitMenuItem.Size = new System.Drawing.Size(212, 22); + this.ExitMenuItem.Size = new System.Drawing.Size(206, 22); this.ExitMenuItem.Text = "E&xit"; this.ExitMenuItem.Click += new System.EventHandler(this.ExitMenuItem_Click); // @@ -556,7 +563,7 @@ this.Table0PaletteSubMenu, this.Table1PaletteSubMenu}); this.PatternSubMenu.Name = "PatternSubMenu"; - this.PatternSubMenu.Size = new System.Drawing.Size(57, 20); + this.PatternSubMenu.Size = new System.Drawing.Size(55, 20); this.PatternSubMenu.Text = "&Pattern"; // // Table0PaletteSubMenu @@ -571,7 +578,7 @@ this.Table0P6MenuItem, this.Table0P7MenuItem}); this.Table0PaletteSubMenu.Name = "Table0PaletteSubMenu"; - this.Table0PaletteSubMenu.Size = new System.Drawing.Size(151, 22); + this.Table0PaletteSubMenu.Size = new System.Drawing.Size(152, 22); this.Table0PaletteSubMenu.Text = "Table 0 Palette"; this.Table0PaletteSubMenu.DropDownOpened += new System.EventHandler(this.Table0PaletteSubMenu_DropDownOpened); // @@ -643,7 +650,7 @@ this.Table1P6MenuItem, this.Table1P7MenuItem}); this.Table1PaletteSubMenu.Name = "Table1PaletteSubMenu"; - this.Table1PaletteSubMenu.Size = new System.Drawing.Size(151, 22); + this.Table1PaletteSubMenu.Size = new System.Drawing.Size(152, 22); this.Table1PaletteSubMenu.Text = "Table 1 Palette"; this.Table1PaletteSubMenu.DropDownOpened += new System.EventHandler(this.Table1PaletteSubMenu_DropDownOpened); // @@ -709,37 +716,38 @@ this.AutoLoadMenuItem, this.SaveWindowPositionMenuItem, this.AlwaysOnTopMenuItem, - this.FloatingWindowMenuItem}); + this.FloatingWindowMenuItem, + this.cHRROMTileViewerToolStripMenuItem}); this.SettingsSubMenu.Name = "SettingsSubMenu"; - this.SettingsSubMenu.Size = new System.Drawing.Size(61, 20); + this.SettingsSubMenu.Size = new System.Drawing.Size(58, 20); this.SettingsSubMenu.Text = "&Settings"; this.SettingsSubMenu.DropDownOpened += new System.EventHandler(this.SettingsSubMenu_DropDownOpened); // // AutoLoadMenuItem // this.AutoLoadMenuItem.Name = "AutoLoadMenuItem"; - this.AutoLoadMenuItem.Size = new System.Drawing.Size(191, 22); + this.AutoLoadMenuItem.Size = new System.Drawing.Size(179, 22); this.AutoLoadMenuItem.Text = "Autoload"; this.AutoLoadMenuItem.Click += new System.EventHandler(this.AutoloadMenuItem_Click); // // SaveWindowPositionMenuItem // this.SaveWindowPositionMenuItem.Name = "SaveWindowPositionMenuItem"; - this.SaveWindowPositionMenuItem.Size = new System.Drawing.Size(191, 22); + this.SaveWindowPositionMenuItem.Size = new System.Drawing.Size(179, 22); this.SaveWindowPositionMenuItem.Text = "Save Window Position"; this.SaveWindowPositionMenuItem.Click += new System.EventHandler(this.SaveWindowPositionMenuItem_Click); // // AlwaysOnTopMenuItem // this.AlwaysOnTopMenuItem.Name = "AlwaysOnTopMenuItem"; - this.AlwaysOnTopMenuItem.Size = new System.Drawing.Size(191, 22); + this.AlwaysOnTopMenuItem.Size = new System.Drawing.Size(179, 22); this.AlwaysOnTopMenuItem.Text = "Always On Top"; this.AlwaysOnTopMenuItem.Click += new System.EventHandler(this.AlwaysOnTopMenuItem_Click); // // FloatingWindowMenuItem // this.FloatingWindowMenuItem.Name = "FloatingWindowMenuItem"; - this.FloatingWindowMenuItem.Size = new System.Drawing.Size(191, 22); + this.FloatingWindowMenuItem.Size = new System.Drawing.Size(179, 22); this.FloatingWindowMenuItem.Text = "Floating Window"; this.FloatingWindowMenuItem.Click += new System.EventHandler(this.FloatingWindowMenuItem_Click); // @@ -749,7 +757,7 @@ this.toolStripStatusLabel1}); this.NesPPUStatusBar.Location = new System.Drawing.Point(0, 349); this.NesPPUStatusBar.Name = "NesPPUStatusBar"; - this.NesPPUStatusBar.Size = new System.Drawing.Size(574, 22); + this.NesPPUStatusBar.Size = new System.Drawing.Size(854, 22); this.NesPPUStatusBar.SizingGrip = false; this.NesPPUStatusBar.TabIndex = 11; this.NesPPUStatusBar.Text = "statusStrip1"; @@ -757,7 +765,7 @@ // toolStripStatusLabel1 // this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; - this.toolStripStatusLabel1.Size = new System.Drawing.Size(348, 17); + this.toolStripStatusLabel1.Size = new System.Drawing.Size(319, 17); this.toolStripStatusLabel1.Text = "Use CTRL+C to copy the pane under the mouse to the clipboard."; // // Messagetimer @@ -765,11 +773,57 @@ this.Messagetimer.Interval = 5000; this.Messagetimer.Tick += new System.EventHandler(this.MessageTimer_Tick); // + // CHRROMGroup + // + this.CHRROMGroup.Controls.Add(this.label5); + this.CHRROMGroup.Controls.Add(this.numericUpDownCHRROMBank); + this.CHRROMGroup.Controls.Add(this.CHRROMView); + this.CHRROMGroup.Location = new System.Drawing.Point(574, 37); + this.CHRROMGroup.Name = "CHRROMGroup"; + this.CHRROMGroup.Size = new System.Drawing.Size(272, 299); + this.CHRROMGroup.TabIndex = 12; + this.CHRROMGroup.TabStop = false; + this.CHRROMGroup.Text = "CHR ROM Tiles"; + // + // CHRROMView + // + this.CHRROMView.BackColor = System.Drawing.Color.Transparent; + this.CHRROMView.Location = new System.Drawing.Point(7, 20); + this.CHRROMView.Name = "CHRROMView"; + this.CHRROMView.Size = new System.Drawing.Size(256, 128); + this.CHRROMView.TabIndex = 0; + this.CHRROMView.Text = "patternViewer1"; + // + // numericUpDownCHRROMBank + // + this.numericUpDownCHRROMBank.Location = new System.Drawing.Point(47, 154); + this.numericUpDownCHRROMBank.Name = "numericUpDownCHRROMBank"; + this.numericUpDownCHRROMBank.Size = new System.Drawing.Size(120, 20); + this.numericUpDownCHRROMBank.TabIndex = 1; + this.numericUpDownCHRROMBank.ValueChanged += new System.EventHandler(this.numericUpDownCHRROMBank_ValueChanged); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(6, 156); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.TabIndex = 2; + this.label5.Text = "Bank:"; + // + // cHRROMTileViewerToolStripMenuItem + // + this.cHRROMTileViewerToolStripMenuItem.Name = "cHRROMTileViewerToolStripMenuItem"; + this.cHRROMTileViewerToolStripMenuItem.Size = new System.Drawing.Size(179, 22); + this.cHRROMTileViewerToolStripMenuItem.Text = "CHR ROM Tile Viewer"; + this.cHRROMTileViewerToolStripMenuItem.Click += new System.EventHandler(this.cHRROMTileViewerToolStripMenuItem_Click); + // // NesPPU // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(574, 371); + this.ClientSize = new System.Drawing.Size(854, 371); + this.Controls.Add(this.CHRROMGroup); this.Controls.Add(this.NesPPUStatusBar); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); @@ -809,6 +863,9 @@ this.NesPPUMenu.PerformLayout(); this.NesPPUStatusBar.ResumeLayout(false); this.NesPPUStatusBar.PerformLayout(); + this.CHRROMGroup.ResumeLayout(false); + this.CHRROMGroup.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.numericUpDownCHRROMBank)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -890,5 +947,10 @@ private System.Windows.Forms.Timer Messagetimer; private System.Windows.Forms.ToolStripMenuItem AlwaysOnTopMenuItem; private System.Windows.Forms.ToolStripMenuItem FloatingWindowMenuItem; + private System.Windows.Forms.GroupBox CHRROMGroup; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.NumericUpDown numericUpDownCHRROMBank; + private PatternViewer CHRROMView; + private System.Windows.Forms.ToolStripMenuItem cHRROMTileViewerToolStripMenuItem; } } \ No newline at end of file diff --git a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs index 708b6e4fe4..3b6868f345 100644 --- a/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs +++ b/BizHawk.Client.EmuHawk/tools/NES/NESPPU.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Windows.Forms; using BizHawk.Client.Common; using BizHawk.Emulation.Cores.Nintendo.NES; +using BizHawk.Emulation.Common; namespace BizHawk.Client.EmuHawk { @@ -36,6 +37,7 @@ namespace BizHawk.Client.EmuHawk }; TopMost = Global.Config.NesPPUSettings.TopMost; _callback.Callback = () => Generate(); + CalculateFormSize(); } private void NesPPU_Load(object sender, EventArgs e) @@ -45,6 +47,7 @@ namespace BizHawk.Client.EmuHawk ClearDetails(); RefreshRate.Value = Global.Config.NESPPURefreshRate; Generate(true); + CHRROMViewReload(); } #region Public API @@ -70,6 +73,7 @@ namespace BizHawk.Client.EmuHawk { _nes = Global.Emulator as NES; Generate(true); + CHRROMViewReload(); } else { @@ -123,6 +127,50 @@ namespace BizHawk.Client.EmuHawk return changed; } + private unsafe void DrawPatternView(PatternViewer dest, byte[] src) + { + int b0; + int b1; + byte value; + int cvalue; + + var bmpdata = dest.pattern.LockBits( + new Rectangle(new Point(0, 0), dest.pattern.Size), + ImageLockMode.WriteOnly, + PixelFormat.Format32bppArgb); + + var framebuf = (int*)bmpdata.Scan0.ToPointer(); + for (int z = 0; z < 2; z++) + { + int pal; + pal = z == 0 ? PatternView.Pal0 : PatternView.Pal1; // change? + + for (int i = 0; i < 16; i++) + { + for (int j = 0; j < 16; j++) + { + for (int x = 0; x < 8; x++) + { + for (int y = 0; y < 8; y++) + { + int address = (z << 12) + (i << 8) + (j << 4) + y; + b0 = (byte)((src[address] >> (7 - x)) & 1); + b1 = (byte)((src[address + 8] >> (7 - x)) & 1); + + value = (byte)(b0 + (b1 << 1)); + cvalue = _nes.LookupColor(_nes.ppu.PALRAM[value + (pal << 2)]); + int adr = (x + (j << 3)) + (y + (i << 3)) * (bmpdata.Stride >> 2); + framebuf[adr + (z << 7)] = cvalue; + } + } + } + } + } + + dest.pattern.UnlockBits(bmpdata); + dest.Refresh(); + } + private unsafe void Generate(bool now = false) { if (!IsHandleCreated || IsDisposed) @@ -155,42 +203,7 @@ namespace BizHawk.Client.EmuHawk PaletteView.Refresh(); } - var bmpdata = PatternView.pattern.LockBits( - new Rectangle(new Point(0, 0), PatternView.pattern.Size), - ImageLockMode.WriteOnly, - PixelFormat.Format32bppArgb - ); - - var framebuf = (int*)bmpdata.Scan0.ToPointer(); - for (int z = 0; z < 2; z++) - { - int pal; - pal = z == 0 ? PatternView.Pal0 : PatternView.Pal1; - - for (int i = 0; i < 16; i++) - { - for (int j = 0; j < 16; j++) - { - for (int x = 0; x < 8; x++) - { - for (int y = 0; y < 8; y++) - { - int address = (z << 12) + (i << 8) + (j << 4) + y; - b0 = (byte)((_ppuBus[address] >> (7 - x)) & 1); - b1 = (byte)((_ppuBus[address + 8] >> (7 - x)) & 1); - - value = (byte)(b0 + (b1 << 1)); - cvalue = _nes.LookupColor(_nes.ppu.PALRAM[value + (pal << 2)]); - int adr = (x + (j << 3)) + (y + (i << 3)) * (bmpdata.Stride >> 2); - framebuf[adr + (z << 7)] = cvalue; - } - } - } - } - } - - PatternView.pattern.UnlockBits(bmpdata); - PatternView.Refresh(); + DrawPatternView(PatternView, _ppuBus); } var bmpdata2 = SpriteView.sprites.LockBits(new Rectangle(new Point(0, 0), SpriteView.sprites.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); @@ -461,6 +474,7 @@ namespace BizHawk.Client.EmuHawk SaveWindowPositionMenuItem.Checked = Global.Config.NesPPUSettings.SaveWindowPosition; AlwaysOnTopMenuItem.Checked = Global.Config.NesPPUSettings.TopMost; FloatingWindowMenuItem.Checked = Global.Config.NesPPUSettings.FloatingWindow; + cHRROMTileViewerToolStripMenuItem.Checked = Global.Config.NESPPUChrRomView; } private void AutoloadMenuItem_Click(object sender, EventArgs e) @@ -794,6 +808,55 @@ namespace BizHawk.Client.EmuHawk #endregion + MemoryDomain CHRROM; + byte[] chrromcache = new byte[8192]; + + private void cHRROMTileViewerToolStripMenuItem_Click(object sender, EventArgs e) + { + Global.Config.NESPPUChrRomView ^= true; + CalculateFormSize(); + } + + private void CalculateFormSize() + { + Width = Global.Config.NESPPUChrRomView ? 861 : 580; + } + + private void CHRROMViewReload() + { + CHRROM = _nes.MemoryDomains["CHR VROM"]; + if (CHRROM == null) + { + numericUpDownCHRROMBank.Enabled = false; + Array.Clear(chrromcache, 0, 8192); + } + else + { + numericUpDownCHRROMBank.Enabled = true; + numericUpDownCHRROMBank.Minimum = 0; + numericUpDownCHRROMBank.Maximum = CHRROM.Size / 8192 - 1; + numericUpDownCHRROMBank.Value = Math.Min(numericUpDownCHRROMBank.Value, numericUpDownCHRROMBank.Maximum); + } + CHRROMViewRefresh(); + } + + private void CHRROMViewRefresh() + { + if (CHRROM != null) + { + int offs = 8192 * (int)numericUpDownCHRROMBank.Value; + for (int i = 0; i < 8192; i++) + chrromcache[i] = CHRROM.PeekByte(offs + i); + + DrawPatternView(CHRROMView, chrromcache); + } + } + #endregion + + private void numericUpDownCHRROMBank_ValueChanged(object sender, EventArgs e) + { + CHRROMViewRefresh(); + } } }