diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 48434d74..b7112ee0 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -7,6 +7,7 @@ #include "Console.h" #include "BaseMapper.h" #include "Disassembler.h" +#include "VideoDecoder.h" #include "APU.h" Debugger* Debugger::Instance = nullptr; @@ -304,4 +305,134 @@ uint32_t Debugger::GetMemoryState(DebugMemoryType type, uint8_t *buffer) return _mapper->GetChrSize(); } return 0; +} + +void Debugger::GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData) +{ + uint16_t *screenBuffer = new uint16_t[256 * 240]; + uint16_t bgAddr = _ppu->GetState().ControlFlags.BackgroundPatternAddr; + uint16_t baseAddr = 0x2000 + nametableIndex * 0x400; + uint16_t baseAttributeAddr = baseAddr + 960; + for(int y = 0; y < 30; y++) { + for(int x = 0; x < 32; x++) { + uint8_t tileIndex = _mapper->ReadVRAM(baseAddr + (y << 5) + x); + uint8_t attribute = _mapper->ReadVRAM(baseAttributeAddr + ((y & 0xFC) << 1) + (x >> 2)); + tileData[y * 30 + x] = tileIndex; + paletteData[y * 30 + x] = attribute; + uint8_t shift = (x & 0x02) | ((y & 0x02) << 1); + + uint8_t paletteBaseAddr = ((attribute >> shift) & 0x03) << 2; + uint16_t tileAddr = bgAddr + (tileIndex << 4); + for(int i = 0; i < 8; i++) { + uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i); + uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8); + for(int j = 0; j < 8; j++) { + uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1); + screenBuffer[(y<<11)+(x<<3)+(i<<8)+j] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(paletteBaseAddr + color); + } + } + } + } + + VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 256*240); + + delete[] screenBuffer; +} + +void Debugger::GetChrBank(int bankIndex, uint32_t* frameBuffer, uint8_t palette) +{ + uint16_t *screenBuffer = new uint16_t[128 * 128]; + uint16_t bgAddr = bankIndex == 0 ? 0x0000 : 0x1000; + for(int y = 0; y < 16; y++) { + for(int x = 0; x < 16; x++) { + uint8_t tileIndex = y * 16 + x; + uint8_t paletteBaseAddr = palette << 2; + uint16_t tileAddr = bgAddr + (tileIndex << 4); + for(int i = 0; i < 8; i++) { + uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i); + uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8); + for(int j = 0; j < 8; j++) { + uint8_t color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1); + screenBuffer[(y<<10)+(x<<3)+(i<<7)+j] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(paletteBaseAddr + color); + } + } + } + } + + VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 128*128); + + delete[] screenBuffer; +} + +void Debugger::GetSprites(uint32_t* frameBuffer) +{ + uint16_t *screenBuffer = new uint16_t[64 * 128]; + memset(screenBuffer, 0, 64*128*sizeof(uint16_t)); + uint8_t *spriteRam = _ppu->GetSpriteRam(); + + uint16_t spriteAddr = _ppu->GetState().ControlFlags.SpritePatternAddr; + bool largeSprites = _ppu->GetState().ControlFlags.LargeSprites; + + for(int y = 0; y < 8; y++) { + for(int x = 0; x < 8; x++) { + uint8_t ramAddr = ((y << 3) + x) << 2; + uint8_t spriteY = spriteRam[ramAddr]; + uint8_t tileIndex = spriteRam[ramAddr + 1]; + uint8_t attributes = spriteRam[ramAddr + 2]; + uint8_t spriteX = spriteRam[ramAddr + 3]; + + bool verticalMirror = (attributes & 0x80) == 0x80; + bool horizontalMirror = (attributes & 0x40) == 0x40; + + uint16_t tileAddr; + if(largeSprites) { + tileAddr = (tileIndex & 0x01 ? 0x1000 : 0x0000) + ((tileIndex & 0xFE) << 4); + } else { + tileAddr = spriteAddr + (tileIndex << 4); + } + + uint8_t palette = 0x10 + ((attributes & 0x03) << 2); + + for(int i = 0, iMax = largeSprites ? 16 : 8; i < iMax; i++) { + if(i == 8) { + //Move to next tile for 2nd tile of 8x16 sprites + tileAddr += 8; + } + + uint8_t lowByte = _mapper->ReadVRAM(tileAddr + i); + uint8_t highByte = _mapper->ReadVRAM(tileAddr + i + 8); + for(int j = 0; j < 8; j++) { + uint8_t color; + if(horizontalMirror) { + color = ((lowByte >> j) & 0x01) | (((highByte >> j) & 0x01) << 1); + } else { + color = ((lowByte >> (7 - j)) & 0x01) | (((highByte >> (7 - j)) & 0x01) << 1); + } + + uint16_t destAddr; + if(verticalMirror) { + destAddr = (y << 10) + (x << 3) + (((largeSprites ? 15 : 7) - i) << 6) + j; + } else { + destAddr = (y << 10) + (x << 3) + (i << 6) + j; + } + + screenBuffer[destAddr] = color == 0 ? _ppu->ReadPaletteRAM(0) : _ppu->ReadPaletteRAM(palette + color); + } + } + } + } + + VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 64*128); + + delete[] screenBuffer; +} + +void Debugger::GetPalette(uint32_t* frameBuffer) +{ + uint16_t *screenBuffer = new uint16_t[4*8]; + for(int i = 0; i < 32; i++) { + screenBuffer[i] = _ppu->ReadPaletteRAM(i); + } + VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 4*8); + delete[] screenBuffer; } \ No newline at end of file diff --git a/Core/Debugger.h b/Core/Debugger.h index 3c680ad7..5467dbeb 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -70,6 +70,10 @@ public: vector GetExecBreakpointAddresses(); uint32_t GetMemoryState(DebugMemoryType type, uint8_t *buffer); + void GetNametable(int nametableIndex, uint32_t* frameBuffer, uint8_t* tileData, uint8_t* paletteData); + void GetChrBank(int bankIndex, uint32_t* frameBuffer, uint8_t palette); + void GetSprites(uint32_t* frameBuffer); + void GetPalette(uint32_t* frameBuffer); void GetState(DebugState *state); diff --git a/Core/INotificationListener.h b/Core/INotificationListener.h index 2b8f3afd..f48d236f 100644 --- a/Core/INotificationListener.h +++ b/Core/INotificationListener.h @@ -11,7 +11,8 @@ enum class ConsoleNotificationType GameStopped = 5, CodeBreak = 6, CheatAdded = 7, - CheatRemoved = 8 + CheatRemoved = 8, + PpuFrameDone = 9 }; class INotificationListener diff --git a/Core/MessageManager.cpp b/Core/MessageManager.cpp index 652d47c8..645781aa 100644 --- a/Core/MessageManager.cpp +++ b/Core/MessageManager.cpp @@ -3,7 +3,7 @@ #include "MessageManager.h" IMessageManager* MessageManager::_messageManager = nullptr; -list MessageManager::_notificationListeners; +vector MessageManager::_notificationListeners; void MessageManager::RegisterMessageManager(IMessageManager* messageManager) { @@ -26,20 +26,32 @@ void MessageManager::DisplayToast(string title, string message, uint8_t* iconDat void MessageManager::RegisterNotificationListener(INotificationListener* notificationListener) { MessageManager::_notificationListeners.push_back(notificationListener); - MessageManager::_notificationListeners.unique(); } void MessageManager::UnregisterNotificationListener(INotificationListener* notificationListener) { - MessageManager::_notificationListeners.remove(notificationListener); + MessageManager::_notificationListeners.erase(std::remove(MessageManager::_notificationListeners.begin(), MessageManager::_notificationListeners.end(), notificationListener), MessageManager::_notificationListeners.end()); } void MessageManager::SendNotification(ConsoleNotificationType type) { - list listeners = MessageManager::_notificationListeners; - //Iterate on a copy to prevent issues if a notification causes a listener to unregister itself - for(INotificationListener* notificationListener : listeners) { - notificationListener->ProcessNotification(type); + vector listeners = MessageManager::_notificationListeners; + vector processedListeners; + + for(size_t i = 0, len = listeners.size(); i < len; i++) { + INotificationListener* notificationListener = listeners[i]; + if(std::find(processedListeners.begin(), processedListeners.end(), notificationListener) == processedListeners.end()) { + //Only send notification if it hasn't been processed already + notificationListener->ProcessNotification(type); + } + processedListeners.push_back(notificationListener); + + if(len != MessageManager::_notificationListeners.size()) { + //Vector changed, start from the beginning again (can occur when sending a notification caused listeners to unregister themselves) + i = 0; + len = MessageManager::_notificationListeners.size(); + listeners = MessageManager::_notificationListeners; + } } } \ No newline at end of file diff --git a/Core/MessageManager.h b/Core/MessageManager.h index bfbd35cd..41ea9d6d 100644 --- a/Core/MessageManager.h +++ b/Core/MessageManager.h @@ -9,7 +9,7 @@ class MessageManager { private: static IMessageManager* _messageManager; - static list _notificationListeners; + static vector _notificationListeners; public: static void RegisterMessageManager(IMessageManager* messageManager); diff --git a/Core/VideoDecoder.cpp b/Core/VideoDecoder.cpp index 9589aa63..e58233be 100644 --- a/Core/VideoDecoder.cpp +++ b/Core/VideoDecoder.cpp @@ -90,6 +90,8 @@ void VideoDecoder::UpdateBufferSize() uint32_t* VideoDecoder::DecodeFrame(uint16_t* inputBuffer) { + MessageManager::SendNotification(ConsoleNotificationType::PpuFrameDone); + _frameLock.Acquire(); UpdateBufferSize(); uint32_t* outputBuffer = _frameBuffer; @@ -100,10 +102,17 @@ uint32_t* VideoDecoder::DecodeFrame(uint16_t* inputBuffer) } } _frameLock.Release(); - + return _frameBuffer; } +void VideoDecoder::DebugDecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer, uint32_t length) +{ + for(uint32_t i = 0; i < length; i++) { + outputBuffer[i] = PPU_PALETTE_ARGB[inputBuffer[i] & 0x3F]; + } +} + void VideoDecoder::TakeScreenshot(string romFilename) { uint32_t bufferSize = _overscan.GetPixelCount() * 4; diff --git a/Core/VideoDecoder.h b/Core/VideoDecoder.h index b068f317..e28bd192 100644 --- a/Core/VideoDecoder.h +++ b/Core/VideoDecoder.h @@ -21,4 +21,6 @@ public: uint32_t* DecodeFrame(uint16_t* inputBuffer); void TakeScreenshot(string romFilename); + + void DebugDecodeFrame(uint16_t* inputBuffer, uint32_t* outputBuffer, uint32_t length); }; \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlChrViewer.Designer.cs b/GUI.NET/Debugger/Controls/ctrlChrViewer.Designer.cs new file mode 100644 index 00000000..7ef4b2be --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlChrViewer.Designer.cs @@ -0,0 +1,265 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlChrViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.grpTileInfo = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.txtTileAddress = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.txtTileIndex = new System.Windows.Forms.TextBox(); + this.picTile = new System.Windows.Forms.PictureBox(); + this.picChrBank1 = new System.Windows.Forms.PictureBox(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + this.lblPalette = new System.Windows.Forms.Label(); + this.cboPalette = new System.Windows.Forms.ComboBox(); + this.picChrBank2 = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel3.SuspendLayout(); + this.grpTileInfo.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).BeginInit(); + this.flowLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 3; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Controls.Add(this.grpTileInfo, 1, 1); + this.tableLayoutPanel3.Controls.Add(this.picChrBank1, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.flowLayoutPanel1, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.picChrBank2, 0, 2); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 3; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(446, 522); + this.tableLayoutPanel3.TabIndex = 3; + // + // grpTileInfo + // + this.grpTileInfo.Controls.Add(this.tableLayoutPanel4); + this.grpTileInfo.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpTileInfo.Location = new System.Drawing.Point(263, 31); + this.grpTileInfo.Name = "grpTileInfo"; + this.tableLayoutPanel3.SetRowSpan(this.grpTileInfo, 2); + this.grpTileInfo.Size = new System.Drawing.Size(180, 488); + this.grpTileInfo.TabIndex = 4; + this.grpTileInfo.TabStop = false; + this.grpTileInfo.Text = "Tile Info"; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 2; + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.Controls.Add(this.txtTileAddress, 1, 1); + this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.label2, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.label6, 0, 2); + this.tableLayoutPanel4.Controls.Add(this.txtTileIndex, 1, 0); + this.tableLayoutPanel4.Controls.Add(this.picTile, 1, 2); + this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 4; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.Size = new System.Drawing.Size(174, 469); + this.tableLayoutPanel4.TabIndex = 0; + // + // txtTileAddress + // + this.txtTileAddress.Location = new System.Drawing.Point(77, 29); + this.txtTileAddress.Name = "txtTileAddress"; + this.txtTileAddress.ReadOnly = true; + this.txtTileAddress.Size = new System.Drawing.Size(42, 20); + this.txtTileAddress.TabIndex = 8; + // + // label1 + // + this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 6); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(56, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Tile Index:"; + // + // label2 + // + this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 32); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(68, 13); + this.label2.TabIndex = 1; + this.label2.Text = "Tile Address:"; + // + // label6 + // + this.label6.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(3, 81); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(27, 13); + this.label6.TabIndex = 6; + this.label6.Text = "Tile:"; + // + // txtTileIndex + // + this.txtTileIndex.Location = new System.Drawing.Point(77, 3); + this.txtTileIndex.Name = "txtTileIndex"; + this.txtTileIndex.ReadOnly = true; + this.txtTileIndex.Size = new System.Drawing.Size(26, 20); + this.txtTileIndex.TabIndex = 7; + // + // picTile + // + this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picTile.Location = new System.Drawing.Point(77, 55); + this.picTile.Name = "picTile"; + this.picTile.Size = new System.Drawing.Size(66, 66); + this.picTile.TabIndex = 12; + this.picTile.TabStop = false; + // + // picChrBank1 + // + this.picChrBank1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picChrBank1.Location = new System.Drawing.Point(1, 1); + this.picChrBank1.Margin = new System.Windows.Forms.Padding(1); + this.picChrBank1.Name = "picChrBank1"; + this.tableLayoutPanel3.SetRowSpan(this.picChrBank1, 2); + this.picChrBank1.Size = new System.Drawing.Size(258, 258); + this.picChrBank1.TabIndex = 0; + this.picChrBank1.TabStop = false; + this.picChrBank1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picChrBank_MouseMove); + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.Controls.Add(this.lblPalette); + this.flowLayoutPanel1.Controls.Add(this.cboPalette); + this.flowLayoutPanel1.Location = new System.Drawing.Point(260, 0); + this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(166, 28); + this.flowLayoutPanel1.TabIndex = 5; + // + // lblPalette + // + this.lblPalette.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPalette.AutoSize = true; + this.lblPalette.Location = new System.Drawing.Point(3, 7); + this.lblPalette.Name = "lblPalette"; + this.lblPalette.Size = new System.Drawing.Size(43, 13); + this.lblPalette.TabIndex = 0; + this.lblPalette.Text = "Palette:"; + // + // cboPalette + // + this.cboPalette.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboPalette.FormattingEnabled = true; + this.cboPalette.Items.AddRange(new object[] { + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7"}); + this.cboPalette.Location = new System.Drawing.Point(52, 3); + this.cboPalette.Name = "cboPalette"; + this.cboPalette.Size = new System.Drawing.Size(45, 21); + this.cboPalette.TabIndex = 1; + this.cboPalette.SelectedIndexChanged += new System.EventHandler(this.cboPalette_SelectedIndexChanged); + // + // picChrBank2 + // + this.picChrBank2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picChrBank2.Location = new System.Drawing.Point(1, 261); + this.picChrBank2.Margin = new System.Windows.Forms.Padding(1); + this.picChrBank2.Name = "picChrBank2"; + this.picChrBank2.Size = new System.Drawing.Size(258, 258); + this.picChrBank2.TabIndex = 1; + this.picChrBank2.TabStop = false; + this.picChrBank2.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picChrBank_MouseMove); + // + // ctrlChrViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel3); + this.Name = "ctrlChrViewer"; + this.Size = new System.Drawing.Size(446, 522); + this.tableLayoutPanel3.ResumeLayout(false); + this.grpTileInfo.ResumeLayout(false); + this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picChrBank1)).EndInit(); + this.flowLayoutPanel1.ResumeLayout(false); + this.flowLayoutPanel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picChrBank2)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.PictureBox picChrBank2; + private System.Windows.Forms.PictureBox picChrBank1; + private System.Windows.Forms.GroupBox grpTileInfo; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private System.Windows.Forms.TextBox txtTileAddress; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.TextBox txtTileIndex; + private System.Windows.Forms.PictureBox picTile; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + private System.Windows.Forms.Label lblPalette; + private System.Windows.Forms.ComboBox cboPalette; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlChrViewer.cs b/GUI.NET/Debugger/Controls/ctrlChrViewer.cs new file mode 100644 index 00000000..c785fb1c --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlChrViewer.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlChrViewer : UserControl + { + public ctrlChrViewer() + { + InitializeComponent(); + } + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if(!this.DesignMode) { + this.cboPalette.SelectedIndex = 0; + } + } + + public void RefreshViewer() + { + PictureBox[] chrBanks = new PictureBox[] { this.picChrBank1, this.picChrBank2 }; + + for(int i = 0; i < 2; i++) { + byte[] pixelData = InteropEmu.DebugGetChrBank(i, this.cboPalette.SelectedIndex); + + GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(128, 128, 4*128, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + Bitmap target = new Bitmap(256, 256); + + using(Graphics g = Graphics.FromImage(target)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(source, new Rectangle(0, 0, 256, 256), new Rectangle(0, 0, 128, 128), GraphicsUnit.Pixel); + } + chrBanks[i].Image = target; + } finally { + handle.Free(); + } + } + } + + private void cboPalette_SelectedIndexChanged(object sender, EventArgs e) + { + this.RefreshViewer(); + } + + private void picChrBank_MouseMove(object sender, MouseEventArgs e) + { + List chrBanks = new List() { this.picChrBank1, this.picChrBank2 }; + int bankIndex = chrBanks.IndexOf((PictureBox)sender); + int baseAddress = bankIndex == 0 ? 0x0000 : 0x1000; + + int tileX = Math.Min(e.X / 16, 15); + int tileY = Math.Min(e.Y / 16, 15); + + int tileIndex = tileY * 16 + tileX; + + this.txtTileIndex.Text = tileIndex.ToString("X2"); + this.txtTileAddress.Text = (baseAddress + tileIndex * 16).ToString("X4"); + + Bitmap tile = new Bitmap(64, 64); + using(Graphics g = Graphics.FromImage(tile)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*16, tileY*16, 16, 16), GraphicsUnit.Pixel); + } + this.picTile.Image = tile; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlChrViewer.resx b/GUI.NET/Debugger/Controls/ctrlChrViewer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlChrViewer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlNametableViewer.Designer.cs b/GUI.NET/Debugger/Controls/ctrlNametableViewer.Designer.cs new file mode 100644 index 00000000..8b76037d --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlNametableViewer.Designer.cs @@ -0,0 +1,318 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlNametableViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.grpTileInfo = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.txtPaletteAddress = new System.Windows.Forms.TextBox(); + this.txtAttributeAddress = new System.Windows.Forms.TextBox(); + this.txtAttributeData = new System.Windows.Forms.TextBox(); + this.txtTileAddress = new System.Windows.Forms.TextBox(); + this.lblTileIndex = new System.Windows.Forms.Label(); + this.lblTileAddress = new System.Windows.Forms.Label(); + this.lblAttributeData = new System.Windows.Forms.Label(); + this.lblAttributeAddress = new System.Windows.Forms.Label(); + this.lblPaletteAddress = new System.Windows.Forms.Label(); + this.lblTile = new System.Windows.Forms.Label(); + this.txtTileIndex = new System.Windows.Forms.TextBox(); + this.picNametable4 = new System.Windows.Forms.PictureBox(); + this.picNametable3 = new System.Windows.Forms.PictureBox(); + this.picNametable2 = new System.Windows.Forms.PictureBox(); + this.picNametable1 = new System.Windows.Forms.PictureBox(); + this.picTile = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel1.SuspendLayout(); + this.grpTileInfo.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable4)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 3; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.picNametable4, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.picNametable3, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.picNametable2, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.picNametable1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.grpTileInfo, 2, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 3; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(697, 488); + this.tableLayoutPanel1.TabIndex = 2; + // + // grpTileInfo + // + this.grpTileInfo.Controls.Add(this.tableLayoutPanel2); + this.grpTileInfo.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpTileInfo.Location = new System.Drawing.Point(523, 3); + this.grpTileInfo.Name = "grpTileInfo"; + this.tableLayoutPanel1.SetRowSpan(this.grpTileInfo, 2); + this.grpTileInfo.Size = new System.Drawing.Size(171, 482); + this.grpTileInfo.TabIndex = 4; + this.grpTileInfo.TabStop = false; + this.grpTileInfo.Text = "Tile Info"; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 2; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Controls.Add(this.txtPaletteAddress, 1, 4); + this.tableLayoutPanel2.Controls.Add(this.txtAttributeAddress, 1, 3); + this.tableLayoutPanel2.Controls.Add(this.txtAttributeData, 1, 2); + this.tableLayoutPanel2.Controls.Add(this.txtTileAddress, 1, 1); + this.tableLayoutPanel2.Controls.Add(this.lblTileIndex, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.lblTileAddress, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.lblAttributeData, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.lblAttributeAddress, 0, 3); + this.tableLayoutPanel2.Controls.Add(this.lblPaletteAddress, 0, 4); + this.tableLayoutPanel2.Controls.Add(this.lblTile, 0, 5); + this.tableLayoutPanel2.Controls.Add(this.txtTileIndex, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.picTile, 1, 5); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 7; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(165, 463); + this.tableLayoutPanel2.TabIndex = 0; + // + // txtPaletteAddress + // + this.txtPaletteAddress.Location = new System.Drawing.Point(99, 107); + this.txtPaletteAddress.Name = "txtPaletteAddress"; + this.txtPaletteAddress.ReadOnly = true; + this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20); + this.txtPaletteAddress.TabIndex = 11; + // + // txtAttributeAddress + // + this.txtAttributeAddress.Location = new System.Drawing.Point(99, 81); + this.txtAttributeAddress.Name = "txtAttributeAddress"; + this.txtAttributeAddress.ReadOnly = true; + this.txtAttributeAddress.Size = new System.Drawing.Size(42, 20); + this.txtAttributeAddress.TabIndex = 10; + // + // txtAttributeData + // + this.txtAttributeData.Location = new System.Drawing.Point(99, 55); + this.txtAttributeData.Name = "txtAttributeData"; + this.txtAttributeData.ReadOnly = true; + this.txtAttributeData.Size = new System.Drawing.Size(26, 20); + this.txtAttributeData.TabIndex = 9; + // + // txtTileAddress + // + this.txtTileAddress.Location = new System.Drawing.Point(99, 29); + this.txtTileAddress.Name = "txtTileAddress"; + this.txtTileAddress.ReadOnly = true; + this.txtTileAddress.Size = new System.Drawing.Size(42, 20); + this.txtTileAddress.TabIndex = 8; + // + // lblTileIndex + // + this.lblTileIndex.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblTileIndex.AutoSize = true; + this.lblTileIndex.Location = new System.Drawing.Point(3, 6); + this.lblTileIndex.Name = "lblTileIndex"; + this.lblTileIndex.Size = new System.Drawing.Size(56, 13); + this.lblTileIndex.TabIndex = 0; + this.lblTileIndex.Text = "Tile Index:"; + // + // lblTileAddress + // + this.lblTileAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblTileAddress.AutoSize = true; + this.lblTileAddress.Location = new System.Drawing.Point(3, 32); + this.lblTileAddress.Name = "lblTileAddress"; + this.lblTileAddress.Size = new System.Drawing.Size(68, 13); + this.lblTileAddress.TabIndex = 1; + this.lblTileAddress.Text = "Tile Address:"; + // + // lblAttributeData + // + this.lblAttributeData.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblAttributeData.AutoSize = true; + this.lblAttributeData.Location = new System.Drawing.Point(3, 58); + this.lblAttributeData.Name = "lblAttributeData"; + this.lblAttributeData.Size = new System.Drawing.Size(75, 13); + this.lblAttributeData.TabIndex = 2; + this.lblAttributeData.Text = "Attribute Data:"; + // + // lblAttributeAddress + // + this.lblAttributeAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblAttributeAddress.AutoSize = true; + this.lblAttributeAddress.Location = new System.Drawing.Point(3, 84); + this.lblAttributeAddress.Name = "lblAttributeAddress"; + this.lblAttributeAddress.Size = new System.Drawing.Size(90, 13); + this.lblAttributeAddress.TabIndex = 3; + this.lblAttributeAddress.Text = "Attribute Address:"; + // + // lblPaletteAddress + // + this.lblPaletteAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPaletteAddress.AutoSize = true; + this.lblPaletteAddress.Location = new System.Drawing.Point(3, 110); + this.lblPaletteAddress.Name = "lblPaletteAddress"; + this.lblPaletteAddress.Size = new System.Drawing.Size(84, 13); + this.lblPaletteAddress.TabIndex = 4; + this.lblPaletteAddress.Text = "Palette Address:"; + // + // lblTile + // + this.lblTile.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblTile.AutoSize = true; + this.lblTile.Location = new System.Drawing.Point(3, 159); + this.lblTile.Name = "lblTile"; + this.lblTile.Size = new System.Drawing.Size(27, 13); + this.lblTile.TabIndex = 6; + this.lblTile.Text = "Tile:"; + // + // txtTileIndex + // + this.txtTileIndex.Location = new System.Drawing.Point(99, 3); + this.txtTileIndex.Name = "txtTileIndex"; + this.txtTileIndex.ReadOnly = true; + this.txtTileIndex.Size = new System.Drawing.Size(26, 20); + this.txtTileIndex.TabIndex = 7; + // + // picNametable4 + // + this.picNametable4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picNametable4.Location = new System.Drawing.Point(261, 245); + this.picNametable4.Margin = new System.Windows.Forms.Padding(1); + this.picNametable4.Name = "picNametable4"; + this.picNametable4.Size = new System.Drawing.Size(258, 242); + this.picNametable4.TabIndex = 3; + this.picNametable4.TabStop = false; + this.picNametable4.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove); + // + // picNametable3 + // + this.picNametable3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picNametable3.Location = new System.Drawing.Point(1, 245); + this.picNametable3.Margin = new System.Windows.Forms.Padding(1); + this.picNametable3.Name = "picNametable3"; + this.picNametable3.Size = new System.Drawing.Size(258, 242); + this.picNametable3.TabIndex = 2; + this.picNametable3.TabStop = false; + this.picNametable3.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove); + // + // picNametable2 + // + this.picNametable2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picNametable2.Location = new System.Drawing.Point(261, 1); + this.picNametable2.Margin = new System.Windows.Forms.Padding(1); + this.picNametable2.Name = "picNametable2"; + this.picNametable2.Size = new System.Drawing.Size(258, 242); + this.picNametable2.TabIndex = 1; + this.picNametable2.TabStop = false; + this.picNametable2.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove); + // + // picNametable1 + // + this.picNametable1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picNametable1.Location = new System.Drawing.Point(1, 1); + this.picNametable1.Margin = new System.Windows.Forms.Padding(1); + this.picNametable1.Name = "picNametable1"; + this.picNametable1.Size = new System.Drawing.Size(258, 242); + this.picNametable1.TabIndex = 0; + this.picNametable1.TabStop = false; + this.picNametable1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picNametable_MouseMove); + // + // picTile + // + this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picTile.Location = new System.Drawing.Point(99, 133); + this.picTile.Name = "picTile"; + this.picTile.Size = new System.Drawing.Size(63, 66); + this.picTile.TabIndex = 12; + this.picTile.TabStop = false; + // + // ctrlNametableViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "ctrlNametableViewer"; + this.Size = new System.Drawing.Size(697, 488); + this.tableLayoutPanel1.ResumeLayout(false); + this.grpTileInfo.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable4)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picNametable1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.PictureBox picNametable4; + private System.Windows.Forms.PictureBox picNametable3; + private System.Windows.Forms.PictureBox picNametable2; + private System.Windows.Forms.PictureBox picNametable1; + private System.Windows.Forms.GroupBox grpTileInfo; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.TextBox txtPaletteAddress; + private System.Windows.Forms.TextBox txtAttributeAddress; + private System.Windows.Forms.TextBox txtAttributeData; + private System.Windows.Forms.TextBox txtTileAddress; + private System.Windows.Forms.Label lblTileIndex; + private System.Windows.Forms.Label lblTileAddress; + private System.Windows.Forms.Label lblAttributeData; + private System.Windows.Forms.Label lblAttributeAddress; + private System.Windows.Forms.Label lblPaletteAddress; + private System.Windows.Forms.Label lblTile; + private System.Windows.Forms.TextBox txtTileIndex; + private System.Windows.Forms.PictureBox picTile; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlNametableViewer.cs b/GUI.NET/Debugger/Controls/ctrlNametableViewer.cs new file mode 100644 index 00000000..d69c057b --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlNametableViewer.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlNametableViewer : UserControl + { + private List _tileData = new List() { null, null, null, null }; + private List _attributeData = new List() { null, null, null, null }; + + public ctrlNametableViewer() + { + InitializeComponent(); + } + + public void RefreshViewer() + { + PictureBox[] nametables = new PictureBox[] { this.picNametable1, this.picNametable2, this.picNametable3, this.picNametable4 }; + + for(int i = 0; i < 4; i++) { + byte[] nametablePixelData, tileData, attributeData; + InteropEmu.DebugGetNametable(i, out nametablePixelData, out tileData, out attributeData); + _tileData[i] = tileData; + _attributeData[i] = attributeData; + + GCHandle handle = GCHandle.Alloc(nametablePixelData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(256, 240, 4*256, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + Bitmap target = new Bitmap(256, 240); + using(Graphics g = Graphics.FromImage(target)) { + g.DrawImage(source, new Rectangle(0, 0, 256, 240), new Rectangle(0, 0, 256, 240), GraphicsUnit.Pixel); + } + nametables[i].Image = target; + } finally { + handle.Free(); + } + } + } + + private void picNametable_MouseMove(object sender, MouseEventArgs e) + { + List nametables = new List() { this.picNametable1, this.picNametable2, this.picNametable3, this.picNametable4 }; + int nametableIndex = nametables.IndexOf((PictureBox)sender); + + int baseAddress = 0x2000 + nametableIndex * 0x400; + + DebugState state = new DebugState(); + InteropEmu.DebugGetState(ref state); + int bgAddr = state.PPU.ControlFlags.BackgroundPatternAddr; + + int tileX = Math.Min(e.X / 8, 31); + int tileY = Math.Min(e.Y / 8, 29); + int shift = (tileX & 0x02) | ((tileY & 0x02) << 1); + + int tileIndex = _tileData[nametableIndex][tileY*32+tileX]; + int attributeData = _attributeData[nametableIndex][tileY*32+tileX]; + int attributeAddr = baseAddress + 960 + ((tileY & 0xFC) << 1) + (tileX >> 2); + int paletteBaseAddr = ((attributeData >> shift) & 0x03) << 2; + + this.txtTileIndex.Text = tileIndex.ToString("X2"); + this.txtTileAddress.Text = (bgAddr + tileIndex * 16).ToString("X4"); + this.txtAttributeData.Text = attributeData.ToString("X2"); + this.txtAttributeAddress.Text = attributeAddr.ToString("X4"); + this.txtPaletteAddress.Text = (0x3F00 + paletteBaseAddr).ToString("X4"); + + Bitmap tile = new Bitmap(64, 64); + using(Graphics g = Graphics.FromImage(tile)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*8, tileY*8, 8, 8), GraphicsUnit.Pixel); + } + this.picTile.Image = tile; + } + + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlNametableViewer.resx b/GUI.NET/Debugger/Controls/ctrlNametableViewer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlNametableViewer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlPaletteViewer.Designer.cs b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.Designer.cs new file mode 100644 index 00000000..2dda9dbc --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.Designer.cs @@ -0,0 +1,198 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlPaletteViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.grpColorInfo = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.txtPaletteAddress = new System.Windows.Forms.TextBox(); + this.lblColor = new System.Windows.Forms.Label(); + this.lblPaletteAddress = new System.Windows.Forms.Label(); + this.lblColorTile = new System.Windows.Forms.Label(); + this.txtColor = new System.Windows.Forms.TextBox(); + this.picColor = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.picPalette = new System.Windows.Forms.PictureBox(); + this.grpColorInfo.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picColor)).BeginInit(); + this.tableLayoutPanel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picPalette)).BeginInit(); + this.SuspendLayout(); + // + // grpColorInfo + // + this.grpColorInfo.Controls.Add(this.tableLayoutPanel4); + this.grpColorInfo.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpColorInfo.Location = new System.Drawing.Point(135, 3); + this.grpColorInfo.Name = "grpColorInfo"; + this.grpColorInfo.Size = new System.Drawing.Size(544, 254); + this.grpColorInfo.TabIndex = 4; + this.grpColorInfo.TabStop = false; + this.grpColorInfo.Text = "Color Info"; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 2; + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.Controls.Add(this.txtPaletteAddress, 1, 1); + this.tableLayoutPanel4.Controls.Add(this.lblColor, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.lblPaletteAddress, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.lblColorTile, 0, 2); + this.tableLayoutPanel4.Controls.Add(this.txtColor, 1, 0); + this.tableLayoutPanel4.Controls.Add(this.picColor, 1, 2); + this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 4; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel4.Size = new System.Drawing.Size(538, 235); + this.tableLayoutPanel4.TabIndex = 0; + // + // txtPaletteAddress + // + this.txtPaletteAddress.Location = new System.Drawing.Point(93, 29); + this.txtPaletteAddress.Name = "txtPaletteAddress"; + this.txtPaletteAddress.ReadOnly = true; + this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20); + this.txtPaletteAddress.TabIndex = 8; + // + // lblColor + // + this.lblColor.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblColor.AutoSize = true; + this.lblColor.Location = new System.Drawing.Point(3, 6); + this.lblColor.Name = "lblColor"; + this.lblColor.Size = new System.Drawing.Size(34, 13); + this.lblColor.TabIndex = 0; + this.lblColor.Text = "Color:"; + // + // lblPaletteAddress + // + this.lblPaletteAddress.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPaletteAddress.AutoSize = true; + this.lblPaletteAddress.Location = new System.Drawing.Point(3, 32); + this.lblPaletteAddress.Name = "lblPaletteAddress"; + this.lblPaletteAddress.Size = new System.Drawing.Size(84, 13); + this.lblPaletteAddress.TabIndex = 1; + this.lblPaletteAddress.Text = "Palette Address:"; + // + // lblColorTile + // + this.lblColorTile.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblColorTile.AutoSize = true; + this.lblColorTile.Location = new System.Drawing.Point(3, 81); + this.lblColorTile.Name = "lblColorTile"; + this.lblColorTile.Size = new System.Drawing.Size(48, 13); + this.lblColorTile.TabIndex = 6; + this.lblColorTile.Text = "Preview:"; + // + // txtColor + // + this.txtColor.Location = new System.Drawing.Point(93, 3); + this.txtColor.Name = "txtColor"; + this.txtColor.ReadOnly = true; + this.txtColor.Size = new System.Drawing.Size(26, 20); + this.txtColor.TabIndex = 7; + // + // picColor + // + this.picColor.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picColor.Location = new System.Drawing.Point(93, 55); + this.picColor.Name = "picColor"; + this.picColor.Size = new System.Drawing.Size(66, 66); + this.picColor.TabIndex = 12; + this.picColor.TabStop = false; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 3; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Controls.Add(this.grpColorInfo, 2, 1); + this.tableLayoutPanel3.Controls.Add(this.picPalette, 0, 1); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 2; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(682, 260); + this.tableLayoutPanel3.TabIndex = 3; + // + // picPalette + // + this.picPalette.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picPalette.Location = new System.Drawing.Point(1, 1); + this.picPalette.Margin = new System.Windows.Forms.Padding(1); + this.picPalette.Name = "picPalette"; + this.picPalette.Size = new System.Drawing.Size(130, 258); + this.picPalette.TabIndex = 0; + this.picPalette.TabStop = false; + this.picPalette.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picPalette_MouseMove); + // + // ctrlPaletteViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel3); + this.Name = "ctrlPaletteViewer"; + this.Size = new System.Drawing.Size(682, 260); + this.grpColorInfo.ResumeLayout(false); + this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picColor)).EndInit(); + this.tableLayoutPanel3.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.picPalette)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox picPalette; + private System.Windows.Forms.GroupBox grpColorInfo; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private System.Windows.Forms.TextBox txtPaletteAddress; + private System.Windows.Forms.Label lblColor; + private System.Windows.Forms.Label lblPaletteAddress; + private System.Windows.Forms.Label lblColorTile; + private System.Windows.Forms.TextBox txtColor; + private System.Windows.Forms.PictureBox picColor; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlPaletteViewer.cs b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.cs new file mode 100644 index 00000000..d80a28e5 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlPaletteViewer : UserControl + { + private byte[] _paletteRam; + + public ctrlPaletteViewer() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + + public void RefreshViewer() + { + this._paletteRam = InteropEmu.DebugGetMemoryState(DebugMemoryType.PaletteMemory); + byte[] pixelData = InteropEmu.DebugGetPalette(); + + GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(4, 8, 4*4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + Bitmap target = new Bitmap(128, 256); + + using(Graphics g = Graphics.FromImage(target)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(source, new Rectangle(0, 0, 128, 256), new Rectangle(0, 0, 4, 8), GraphicsUnit.Pixel); + } + this.picPalette.Image = target; + } finally { + handle.Free(); + } + } + + private void picPalette_MouseMove(object sender, MouseEventArgs e) + { + int tileX = Math.Min(e.X / 32, 31); + int tileY = Math.Min(e.Y / 32, 31); + int tileIndex = tileY * 4 + tileX; + + this.txtColor.Text = _paletteRam[tileIndex].ToString("X2"); + this.txtPaletteAddress.Text = (0x3F00 + tileIndex).ToString("X4"); + + Bitmap tile = new Bitmap(64, 64); + using(Graphics g = Graphics.FromImage(tile)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(picPalette.Image, new Rectangle(0, 0, 64, 64), new Rectangle(tileX*32, tileY*32, 32, 32), GraphicsUnit.Pixel); + } + this.picColor.Image = tile; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlPaletteViewer.resx b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlPaletteViewer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/Controls/ctrlSpriteViewer.Designer.cs b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.Designer.cs new file mode 100644 index 00000000..d2dca1f1 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.Designer.cs @@ -0,0 +1,273 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlSpriteViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.grpSpriteInfo = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.txtPosition = new System.Windows.Forms.TextBox(); + this.txtPaletteAddress = new System.Windows.Forms.TextBox(); + this.txtTileAddress = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.lblTile = new System.Windows.Forms.Label(); + this.txtTileIndex = new System.Windows.Forms.TextBox(); + this.chkVerticalMirroring = new System.Windows.Forms.CheckBox(); + this.chkHorizontalMirroring = new System.Windows.Forms.CheckBox(); + this.lblPaletteAddr = new System.Windows.Forms.Label(); + this.lblPosition = new System.Windows.Forms.Label(); + this.picTile = new System.Windows.Forms.PictureBox(); + this.picSprites = new System.Windows.Forms.PictureBox(); + this.tableLayoutPanel3.SuspendLayout(); + this.grpSpriteInfo.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picSprites)).BeginInit(); + this.SuspendLayout(); + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 2; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.Controls.Add(this.grpSpriteInfo, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.picSprites, 0, 0); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 1; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel3.Size = new System.Drawing.Size(682, 516); + this.tableLayoutPanel3.TabIndex = 3; + // + // grpSpriteInfo + // + this.grpSpriteInfo.Controls.Add(this.tableLayoutPanel4); + this.grpSpriteInfo.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpSpriteInfo.Location = new System.Drawing.Point(263, 3); + this.grpSpriteInfo.Name = "grpSpriteInfo"; + this.grpSpriteInfo.Size = new System.Drawing.Size(416, 510); + this.grpSpriteInfo.TabIndex = 4; + this.grpSpriteInfo.TabStop = false; + this.grpSpriteInfo.Text = "Sprite Info"; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 2; + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.Controls.Add(this.txtPosition, 1, 3); + this.tableLayoutPanel4.Controls.Add(this.txtPaletteAddress, 1, 2); + this.tableLayoutPanel4.Controls.Add(this.txtTileAddress, 1, 1); + this.tableLayoutPanel4.Controls.Add(this.label1, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.label2, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.lblTile, 0, 6); + this.tableLayoutPanel4.Controls.Add(this.txtTileIndex, 1, 0); + this.tableLayoutPanel4.Controls.Add(this.picTile, 1, 6); + this.tableLayoutPanel4.Controls.Add(this.chkVerticalMirroring, 0, 5); + this.tableLayoutPanel4.Controls.Add(this.chkHorizontalMirroring, 0, 4); + this.tableLayoutPanel4.Controls.Add(this.lblPaletteAddr, 0, 2); + this.tableLayoutPanel4.Controls.Add(this.lblPosition, 0, 3); + this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 16); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 8; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel4.Size = new System.Drawing.Size(410, 491); + this.tableLayoutPanel4.TabIndex = 0; + // + // txtPosition + // + this.txtPosition.Location = new System.Drawing.Point(93, 81); + this.txtPosition.Name = "txtPosition"; + this.txtPosition.ReadOnly = true; + this.txtPosition.Size = new System.Drawing.Size(42, 20); + this.txtPosition.TabIndex = 18; + // + // txtPaletteAddress + // + this.txtPaletteAddress.Location = new System.Drawing.Point(93, 55); + this.txtPaletteAddress.Name = "txtPaletteAddress"; + this.txtPaletteAddress.ReadOnly = true; + this.txtPaletteAddress.Size = new System.Drawing.Size(42, 20); + this.txtPaletteAddress.TabIndex = 17; + // + // txtTileAddress + // + this.txtTileAddress.Location = new System.Drawing.Point(93, 29); + this.txtTileAddress.Name = "txtTileAddress"; + this.txtTileAddress.ReadOnly = true; + this.txtTileAddress.Size = new System.Drawing.Size(42, 20); + this.txtTileAddress.TabIndex = 8; + // + // label1 + // + this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 6); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(56, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Tile Index:"; + // + // label2 + // + this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 32); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(68, 13); + this.label2.TabIndex = 1; + this.label2.Text = "Tile Address:"; + // + // lblTile + // + this.lblTile.AutoSize = true; + this.lblTile.Location = new System.Drawing.Point(3, 155); + this.lblTile.Margin = new System.Windows.Forms.Padding(3, 5, 3, 0); + this.lblTile.Name = "lblTile"; + this.lblTile.Size = new System.Drawing.Size(27, 13); + this.lblTile.TabIndex = 6; + this.lblTile.Text = "Tile:"; + // + // txtTileIndex + // + this.txtTileIndex.Location = new System.Drawing.Point(93, 3); + this.txtTileIndex.Name = "txtTileIndex"; + this.txtTileIndex.ReadOnly = true; + this.txtTileIndex.Size = new System.Drawing.Size(26, 20); + this.txtTileIndex.TabIndex = 7; + // + // chkVerticalMirroring + // + this.chkVerticalMirroring.AutoSize = true; + this.tableLayoutPanel4.SetColumnSpan(this.chkVerticalMirroring, 2); + this.chkVerticalMirroring.Location = new System.Drawing.Point(3, 130); + this.chkVerticalMirroring.Name = "chkVerticalMirroring"; + this.chkVerticalMirroring.Size = new System.Drawing.Size(77, 17); + this.chkVerticalMirroring.TabIndex = 14; + this.chkVerticalMirroring.Text = "Vertical flip"; + this.chkVerticalMirroring.UseVisualStyleBackColor = true; + // + // chkHorizontalMirroring + // + this.chkHorizontalMirroring.AutoSize = true; + this.tableLayoutPanel4.SetColumnSpan(this.chkHorizontalMirroring, 2); + this.chkHorizontalMirroring.Location = new System.Drawing.Point(3, 107); + this.chkHorizontalMirroring.Name = "chkHorizontalMirroring"; + this.chkHorizontalMirroring.Size = new System.Drawing.Size(89, 17); + this.chkHorizontalMirroring.TabIndex = 13; + this.chkHorizontalMirroring.Text = "Horizontal flip"; + this.chkHorizontalMirroring.UseVisualStyleBackColor = true; + // + // lblPaletteAddr + // + this.lblPaletteAddr.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPaletteAddr.AutoSize = true; + this.lblPaletteAddr.Location = new System.Drawing.Point(3, 58); + this.lblPaletteAddr.Name = "lblPaletteAddr"; + this.lblPaletteAddr.Size = new System.Drawing.Size(84, 13); + this.lblPaletteAddr.TabIndex = 15; + this.lblPaletteAddr.Text = "Palette Address:"; + // + // lblPosition + // + this.lblPosition.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.lblPosition.AutoSize = true; + this.lblPosition.Location = new System.Drawing.Point(3, 84); + this.lblPosition.Name = "lblPosition"; + this.lblPosition.Size = new System.Drawing.Size(70, 13); + this.lblPosition.TabIndex = 16; + this.lblPosition.Text = "Position (X,Y)"; + // + // picTile + // + this.picTile.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.picTile.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picTile.Location = new System.Drawing.Point(93, 153); + this.picTile.Name = "picTile"; + this.picTile.Size = new System.Drawing.Size(66, 130); + this.picTile.TabIndex = 12; + this.picTile.TabStop = false; + // + // picSprites + // + this.picSprites.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.picSprites.Location = new System.Drawing.Point(1, 1); + this.picSprites.Margin = new System.Windows.Forms.Padding(1); + this.picSprites.Name = "picSprites"; + this.picSprites.Size = new System.Drawing.Size(258, 514); + this.picSprites.TabIndex = 0; + this.picSprites.TabStop = false; + this.picSprites.MouseMove += new System.Windows.Forms.MouseEventHandler(this.picSprites_MouseMove); + // + // ctrlSpriteViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tableLayoutPanel3); + this.Name = "ctrlSpriteViewer"; + this.Size = new System.Drawing.Size(682, 516); + this.tableLayoutPanel3.ResumeLayout(false); + this.grpSpriteInfo.ResumeLayout(false); + this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel4.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.picTile)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picSprites)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.PictureBox picSprites; + private System.Windows.Forms.GroupBox grpSpriteInfo; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private System.Windows.Forms.TextBox txtTileAddress; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label lblTile; + private System.Windows.Forms.TextBox txtTileIndex; + private System.Windows.Forms.PictureBox picTile; + private System.Windows.Forms.TextBox txtPosition; + private System.Windows.Forms.TextBox txtPaletteAddress; + private System.Windows.Forms.CheckBox chkVerticalMirroring; + private System.Windows.Forms.CheckBox chkHorizontalMirroring; + private System.Windows.Forms.Label lblPaletteAddr; + private System.Windows.Forms.Label lblPosition; + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlSpriteViewer.cs b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.cs new file mode 100644 index 00000000..66498f53 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlSpriteViewer : UserControl + { + private byte[] _spriteRam; + + public ctrlSpriteViewer() + { + InitializeComponent(); + } + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + + public void RefreshViewer() + { + _spriteRam = InteropEmu.DebugGetMemoryState(DebugMemoryType.SpriteMemory); + + byte[] pixelData = InteropEmu.DebugGetSprites(); + + GCHandle handle = GCHandle.Alloc(pixelData, GCHandleType.Pinned); + try { + Bitmap source = new Bitmap(64, 128, 4*64, System.Drawing.Imaging.PixelFormat.Format32bppArgb, handle.AddrOfPinnedObject()); + Bitmap target = new Bitmap(256, 512); + + using(Graphics g = Graphics.FromImage(target)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(source, new Rectangle(0, 0, 256, 512), new Rectangle(0, 0, 64, 128), GraphicsUnit.Pixel); + } + picSprites.Image = target; + } finally { + handle.Free(); + } + } + + private void picSprites_MouseMove(object sender, MouseEventArgs e) + { + int tileX = Math.Min(e.X / 32, 31); + int tileY = Math.Min(e.Y / 64, 63); + + int ramAddr = ((tileY << 3) + tileX) << 2; + int spriteY = _spriteRam[ramAddr]; + int tileIndex = _spriteRam[ramAddr + 1]; + int attributes = _spriteRam[ramAddr + 2]; + int spriteX = _spriteRam[ramAddr + 3]; + + DebugState state = new DebugState(); + InteropEmu.DebugGetState(ref state); + + int tileAddr; + if(state.PPU.ControlFlags.LargeSprites != 0) { + tileAddr = ((tileIndex & 0x01) == 0x01 ? 0x1000 : 0x0000) + ((tileIndex & 0xFE) << 4); + } else { + tileAddr = state.PPU.ControlFlags.SpritePatternAddr + (tileIndex << 4); + } + + int paletteAddr = 0x3F10 + ((attributes & 0x03) << 2); + bool verticalMirror = (attributes & 0x80) == 0x80; + bool horizontalMirror = (attributes & 0x40) == 0x40; + + this.txtTileIndex.Text = tileIndex.ToString("X2"); + this.txtTileAddress.Text = tileAddr.ToString("X4"); + this.txtPosition.Text = spriteX.ToString() + ", " + spriteY.ToString(); + this.txtPaletteAddress.Text = paletteAddr.ToString("X4"); + this.chkVerticalMirroring.Checked = verticalMirror; + this.chkHorizontalMirroring.Checked = horizontalMirror; + + Bitmap tile = new Bitmap(64, 128); + using(Graphics g = Graphics.FromImage(tile)) { + g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; + g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; + g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half; + g.DrawImage(((PictureBox)sender).Image, new Rectangle(0, 0, 64, 128), new Rectangle(tileX*32, tileY*64, 32, 64), GraphicsUnit.Pixel); + } + this.picTile.Image = tile; + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlSpriteViewer.resx b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlSpriteViewer.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.Designer.cs b/GUI.NET/Debugger/frmDebugger.Designer.cs index 8b502f0f..3f699c39 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -34,12 +34,17 @@ this.components = new System.ComponentModel.Container(); this.splitContainer = new System.Windows.Forms.SplitContainer(); this.tlpTop = new System.Windows.Forms.TableLayoutPanel(); + this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode(); this.contextMenuCode = new System.Windows.Forms.ContextMenuStrip(this.components); this.mnuShowNextStatement = new System.Windows.Forms.ToolStripMenuItem(); this.mnuSetNextStatement = new System.Windows.Forms.ToolStripMenuItem(); + this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus(); + this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode(); this.tableLayoutPanel10 = new System.Windows.Forms.TableLayoutPanel(); this.grpBreakpoints = new System.Windows.Forms.GroupBox(); + this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints(); this.grpWatch = new System.Windows.Forms.GroupBox(); + this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch(); this.menuStrip = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); @@ -65,15 +70,8 @@ this.mnuFindPrev = new System.Windows.Forms.ToolStripMenuItem(); this.mnuGoTo = new System.Windows.Forms.ToolStripMenuItem(); this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.nametableViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.cHRViewerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem(); - this.ctrlDebuggerCode = new Mesen.GUI.Debugger.ctrlDebuggerCode(); - this.ctrlConsoleStatus = new Mesen.GUI.Debugger.ctrlConsoleStatus(); - this.ctrlDebuggerCodeSplit = new Mesen.GUI.Debugger.ctrlDebuggerCode(); - this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints(); - this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); @@ -124,6 +122,18 @@ this.tlpTop.Size = new System.Drawing.Size(984, 422); this.tlpTop.TabIndex = 2; // + // ctrlDebuggerCode + // + this.ctrlDebuggerCode.Code = null; + this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode; + this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3); + this.ctrlDebuggerCode.Name = "ctrlDebuggerCode"; + this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 416); + this.ctrlDebuggerCode.TabIndex = 2; + this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded); + this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter); + // // contextMenuCode // this.contextMenuCode.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -148,6 +158,27 @@ this.mnuSetNextStatement.Size = new System.Drawing.Size(258, 22); this.mnuSetNextStatement.Text = "Set Next Statement"; // + // ctrlConsoleStatus + // + this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top; + this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0); + this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0); + this.ctrlConsoleStatus.Name = "ctrlConsoleStatus"; + this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362); + this.ctrlConsoleStatus.TabIndex = 3; + // + // ctrlDebuggerCodeSplit + // + this.ctrlDebuggerCodeSplit.Code = null; + this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3); + this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit"; + this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 416); + this.ctrlDebuggerCodeSplit.TabIndex = 4; + this.ctrlDebuggerCodeSplit.Visible = false; + this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded); + this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter); + // // tableLayoutPanel10 // this.tableLayoutPanel10.ColumnCount = 2; @@ -178,6 +209,15 @@ this.grpBreakpoints.TabStop = false; this.grpBreakpoints.Text = "Breakpoints"; // + // ctrlBreakpoints + // + this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16); + this.ctrlBreakpoints.Name = "ctrlBreakpoints"; + this.ctrlBreakpoints.Size = new System.Drawing.Size(480, 137); + this.ctrlBreakpoints.TabIndex = 0; + this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged); + // // grpWatch // this.grpWatch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) @@ -191,6 +231,14 @@ this.grpWatch.TabStop = false; this.grpWatch.Text = "Watch"; // + // ctrlWatch + // + this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlWatch.Location = new System.Drawing.Point(3, 16); + this.ctrlWatch.Name = "ctrlWatch"; + this.ctrlWatch.Size = new System.Drawing.Size(480, 137); + this.ctrlWatch.TabIndex = 0; + // // menuStrip // this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -216,7 +264,7 @@ // mnuClose // this.mnuClose.Name = "mnuClose"; - this.mnuClose.Size = new System.Drawing.Size(152, 22); + this.mnuClose.Size = new System.Drawing.Size(103, 22); this.mnuClose.Text = "Close"; this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click); // @@ -404,88 +452,26 @@ // toolsToolStripMenuItem // this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.nametableViewerToolStripMenuItem, - this.cHRViewerToolStripMenuItem, - this.toolStripMenuItem3, + this.mnuPpuViewer, this.mnuMemoryViewer}); this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20); this.toolsToolStripMenuItem.Text = "Tools"; // - // nametableViewerToolStripMenuItem + // mnuPpuViewer // - this.nametableViewerToolStripMenuItem.Name = "nametableViewerToolStripMenuItem"; - this.nametableViewerToolStripMenuItem.Size = new System.Drawing.Size(170, 22); - this.nametableViewerToolStripMenuItem.Text = "Nametable Viewer"; - // - // cHRViewerToolStripMenuItem - // - this.cHRViewerToolStripMenuItem.Name = "cHRViewerToolStripMenuItem"; - this.cHRViewerToolStripMenuItem.Size = new System.Drawing.Size(170, 22); - this.cHRViewerToolStripMenuItem.Text = "CHR Viewer"; - // - // toolStripMenuItem3 - // - this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(167, 6); + this.mnuPpuViewer.Name = "mnuPpuViewer"; + this.mnuPpuViewer.Size = new System.Drawing.Size(157, 22); + this.mnuPpuViewer.Text = "PPU Viewer"; + this.mnuPpuViewer.Click += new System.EventHandler(this.mnuNametableViewer_Click); // // mnuMemoryViewer // this.mnuMemoryViewer.Name = "mnuMemoryViewer"; - this.mnuMemoryViewer.Size = new System.Drawing.Size(170, 22); + this.mnuMemoryViewer.Size = new System.Drawing.Size(157, 22); this.mnuMemoryViewer.Text = "Memory Viewer"; this.mnuMemoryViewer.Click += new System.EventHandler(this.mnuMemoryViewer_Click); // - // ctrlDebuggerCode - // - this.ctrlDebuggerCode.Code = null; - this.ctrlDebuggerCode.ContextMenuStrip = this.contextMenuCode; - this.ctrlDebuggerCode.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlDebuggerCode.Location = new System.Drawing.Point(3, 3); - this.ctrlDebuggerCode.Name = "ctrlDebuggerCode"; - this.ctrlDebuggerCode.Size = new System.Drawing.Size(546, 416); - this.ctrlDebuggerCode.TabIndex = 2; - this.ctrlDebuggerCode.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded); - this.ctrlDebuggerCode.Enter += new System.EventHandler(this.ctrlDebuggerCode_Enter); - // - // ctrlConsoleStatus - // - this.ctrlConsoleStatus.Dock = System.Windows.Forms.DockStyle.Top; - this.ctrlConsoleStatus.Location = new System.Drawing.Point(552, 0); - this.ctrlConsoleStatus.Margin = new System.Windows.Forms.Padding(0); - this.ctrlConsoleStatus.Name = "ctrlConsoleStatus"; - this.ctrlConsoleStatus.Size = new System.Drawing.Size(432, 362); - this.ctrlConsoleStatus.TabIndex = 3; - // - // ctrlDebuggerCodeSplit - // - this.ctrlDebuggerCodeSplit.Code = null; - this.ctrlDebuggerCodeSplit.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlDebuggerCodeSplit.Location = new System.Drawing.Point(555, 3); - this.ctrlDebuggerCodeSplit.Name = "ctrlDebuggerCodeSplit"; - this.ctrlDebuggerCodeSplit.Size = new System.Drawing.Size(1, 416); - this.ctrlDebuggerCodeSplit.TabIndex = 4; - this.ctrlDebuggerCodeSplit.Visible = false; - this.ctrlDebuggerCodeSplit.OnWatchAdded += new Mesen.GUI.Debugger.ctrlDebuggerCode.WatchAddedEventHandler(this.ctrlDebuggerCode_OnWatchAdded); - this.ctrlDebuggerCodeSplit.Enter += new System.EventHandler(this.ctrlDebuggerCodeSplit_Enter); - // - // ctrlBreakpoints - // - this.ctrlBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlBreakpoints.Location = new System.Drawing.Point(3, 16); - this.ctrlBreakpoints.Name = "ctrlBreakpoints"; - this.ctrlBreakpoints.Size = new System.Drawing.Size(480, 137); - this.ctrlBreakpoints.TabIndex = 0; - this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged); - // - // ctrlWatch - // - this.ctrlWatch.Dock = System.Windows.Forms.DockStyle.Fill; - this.ctrlWatch.Location = new System.Drawing.Point(3, 16); - this.ctrlWatch.Name = "ctrlWatch"; - this.ctrlWatch.Size = new System.Drawing.Size(480, 137); - this.ctrlWatch.TabIndex = 0; - // // frmDebugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -548,9 +534,7 @@ private System.Windows.Forms.ToolStripMenuItem mnuView; private System.Windows.Forms.ToolStripMenuItem mnuSplitView; private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem nametableViewerToolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem cHRViewerToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem3; + private System.Windows.Forms.ToolStripMenuItem mnuPpuViewer; private System.Windows.Forms.ToolStripMenuItem mnuMemoryViewer; private Controls.ctrlBreakpoints ctrlBreakpoints; private System.Windows.Forms.ToolStripMenuItem mnuGoTo; diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index 5eff7f51..8c9a7867 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -14,7 +14,7 @@ namespace Mesen.GUI.Debugger { public partial class frmDebugger : Form { - private List _memoryViewers = new List(); + private List
_childForms = new List(); private InteropEmu.NotificationListener _notifListener; private ctrlDebuggerCode _lastCodeWindow; @@ -42,10 +42,13 @@ namespace Mesen.GUI.Debugger InteropEmu.DebugStep(100000); } - void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) + private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) { if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) { this.BeginInvoke((MethodInvoker)(() => UpdateDebugger())); + } else if(e.NotificationType == InteropEmu.ConsoleNotificationType.GameLoaded) { + InteropEmu.DebugRelease(); + InteropEmu.DebugInitialize(); } } @@ -107,6 +110,15 @@ namespace Mesen.GUI.Debugger ctrlDebuggerCode.HighlightBreakpoints(ctrlBreakpoints.GetBreakpoints()); } + private void OpenChildForm(Form frm) + { + this._childForms.Add(frm); + frm.FormClosed += (obj, args) => { + this._childForms.Remove((Form)obj); + }; + frm.Show(); + } + private void mnuContinue_Click(object sender, EventArgs e) { ClearActiveStatement(); @@ -175,12 +187,7 @@ namespace Mesen.GUI.Debugger private void mnuMemoryViewer_Click(object sender, EventArgs e) { - frmMemoryViewer frm = new frmMemoryViewer(); - this._memoryViewers.Add(frm); - frm.FormClosed += (obj, args) => { - this._memoryViewers.Remove((frmMemoryViewer)obj); - }; - frm.Show(); + OpenChildForm(new frmMemoryViewer()); } private void ctrlBreakpoints_BreakpointChanged(object sender, EventArgs e) @@ -225,10 +232,15 @@ namespace Mesen.GUI.Debugger protected override void OnFormClosed(FormClosedEventArgs e) { - foreach(frmMemoryViewer frm in this._memoryViewers.ToArray()) { + foreach(Form frm in this._childForms.ToArray()) { frm.Close(); } base.OnFormClosed(e); } + + private void mnuNametableViewer_Click(object sender, EventArgs e) + { + OpenChildForm(new frmPpuViewer()); + } } } diff --git a/GUI.NET/Debugger/frmPpuViewer.Designer.cs b/GUI.NET/Debugger/frmPpuViewer.Designer.cs new file mode 100644 index 00000000..7c57a8d6 --- /dev/null +++ b/GUI.NET/Debugger/frmPpuViewer.Designer.cs @@ -0,0 +1,245 @@ +namespace Mesen.GUI.Debugger +{ + partial class frmPpuViewer + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if(disposing && (components != null)) { + components.Dispose(); + } + if(this._notifListener != null) { + this._notifListener.Dispose(); + this._notifListener = null; + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); + this.viewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem(); + this.tabMain = new System.Windows.Forms.TabControl(); + this.tpgNametableViewer = new System.Windows.Forms.TabPage(); + this.ctrlNametableViewer = new Mesen.GUI.Debugger.Controls.ctrlNametableViewer(); + this.tpgChrViewer = new System.Windows.Forms.TabPage(); + this.ctrlChrViewer = new Mesen.GUI.Debugger.Controls.ctrlChrViewer(); + this.tpgSpriteViewer = new System.Windows.Forms.TabPage(); + this.ctrlSpriteViewer = new Mesen.GUI.Debugger.Controls.ctrlSpriteViewer(); + this.tpgPaletteViewer = new System.Windows.Forms.TabPage(); + this.ctrlPaletteViewer = new Mesen.GUI.Debugger.Controls.ctrlPaletteViewer(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.menuStrip1.SuspendLayout(); + this.tabMain.SuspendLayout(); + this.tpgNametableViewer.SuspendLayout(); + this.tpgChrViewer.SuspendLayout(); + this.tpgSpriteViewer.SuspendLayout(); + this.tpgPaletteViewer.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.viewToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(709, 24); + this.menuStrip1.TabIndex = 2; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuClose}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // mnuClose + // + this.mnuClose.Name = "mnuClose"; + this.mnuClose.Size = new System.Drawing.Size(103, 22); + this.mnuClose.Text = "Close"; + this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click); + // + // viewToolStripMenuItem + // + this.viewToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuRefresh, + this.toolStripMenuItem1, + this.mnuAutoRefresh}); + this.viewToolStripMenuItem.Name = "viewToolStripMenuItem"; + this.viewToolStripMenuItem.Size = new System.Drawing.Size(44, 20); + this.viewToolStripMenuItem.Text = "View"; + // + // mnuRefresh + // + this.mnuRefresh.Name = "mnuRefresh"; + this.mnuRefresh.ShortcutKeys = System.Windows.Forms.Keys.F5; + this.mnuRefresh.Size = new System.Drawing.Size(152, 22); + this.mnuRefresh.Text = "Refresh"; + this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click); + // + // mnuAutoRefresh + // + this.mnuAutoRefresh.Checked = true; + this.mnuAutoRefresh.CheckOnClick = true; + this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked; + this.mnuAutoRefresh.Name = "mnuAutoRefresh"; + this.mnuAutoRefresh.Size = new System.Drawing.Size(152, 22); + this.mnuAutoRefresh.Text = "Auto-refresh"; + // + // tabMain + // + this.tabMain.Controls.Add(this.tpgNametableViewer); + this.tabMain.Controls.Add(this.tpgChrViewer); + this.tabMain.Controls.Add(this.tpgSpriteViewer); + this.tabMain.Controls.Add(this.tpgPaletteViewer); + this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabMain.Location = new System.Drawing.Point(0, 24); + this.tabMain.Name = "tabMain"; + this.tabMain.SelectedIndex = 0; + this.tabMain.Size = new System.Drawing.Size(709, 545); + this.tabMain.TabIndex = 3; + // + // tpgNametableViewer + // + this.tpgNametableViewer.Controls.Add(this.ctrlNametableViewer); + this.tpgNametableViewer.Location = new System.Drawing.Point(4, 22); + this.tpgNametableViewer.Name = "tpgNametableViewer"; + this.tpgNametableViewer.Padding = new System.Windows.Forms.Padding(3); + this.tpgNametableViewer.Size = new System.Drawing.Size(701, 519); + this.tpgNametableViewer.TabIndex = 0; + this.tpgNametableViewer.Text = "Nametable Viewer"; + this.tpgNametableViewer.UseVisualStyleBackColor = true; + // + // ctrlNametableViewer + // + this.ctrlNametableViewer.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlNametableViewer.Location = new System.Drawing.Point(3, 3); + this.ctrlNametableViewer.Name = "ctrlNametableViewer"; + this.ctrlNametableViewer.Size = new System.Drawing.Size(695, 513); + this.ctrlNametableViewer.TabIndex = 0; + // + // tpgChrViewer + // + this.tpgChrViewer.Controls.Add(this.ctrlChrViewer); + this.tpgChrViewer.Location = new System.Drawing.Point(4, 22); + this.tpgChrViewer.Name = "tpgChrViewer"; + this.tpgChrViewer.Padding = new System.Windows.Forms.Padding(3); + this.tpgChrViewer.Size = new System.Drawing.Size(701, 519); + this.tpgChrViewer.TabIndex = 1; + this.tpgChrViewer.Text = "CHR Viewer"; + this.tpgChrViewer.UseVisualStyleBackColor = true; + // + // ctrlChrViewer + // + this.ctrlChrViewer.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlChrViewer.Location = new System.Drawing.Point(3, 3); + this.ctrlChrViewer.Name = "ctrlChrViewer"; + this.ctrlChrViewer.Size = new System.Drawing.Size(695, 513); + this.ctrlChrViewer.TabIndex = 2; + // + // tpgSpriteViewer + // + this.tpgSpriteViewer.Controls.Add(this.ctrlSpriteViewer); + this.tpgSpriteViewer.Location = new System.Drawing.Point(4, 22); + this.tpgSpriteViewer.Name = "tpgSpriteViewer"; + this.tpgSpriteViewer.Size = new System.Drawing.Size(701, 519); + this.tpgSpriteViewer.TabIndex = 2; + this.tpgSpriteViewer.Text = "Sprite Viewer"; + this.tpgSpriteViewer.UseVisualStyleBackColor = true; + // + // ctrlSpriteViewer + // + this.ctrlSpriteViewer.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlSpriteViewer.Location = new System.Drawing.Point(0, 0); + this.ctrlSpriteViewer.Name = "ctrlSpriteViewer"; + this.ctrlSpriteViewer.Size = new System.Drawing.Size(701, 519); + this.ctrlSpriteViewer.TabIndex = 0; + // + // tpgPaletteViewer + // + this.tpgPaletteViewer.Controls.Add(this.ctrlPaletteViewer); + this.tpgPaletteViewer.Location = new System.Drawing.Point(4, 22); + this.tpgPaletteViewer.Name = "tpgPaletteViewer"; + this.tpgPaletteViewer.Size = new System.Drawing.Size(701, 519); + this.tpgPaletteViewer.TabIndex = 3; + this.tpgPaletteViewer.Text = "Palette Viewer"; + this.tpgPaletteViewer.UseVisualStyleBackColor = true; + // + // ctrlPaletteViewer + // + this.ctrlPaletteViewer.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlPaletteViewer.Location = new System.Drawing.Point(0, 0); + this.ctrlPaletteViewer.Name = "ctrlPaletteViewer"; + this.ctrlPaletteViewer.Size = new System.Drawing.Size(701, 519); + this.ctrlPaletteViewer.TabIndex = 0; + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + this.toolStripMenuItem1.Size = new System.Drawing.Size(149, 6); + // + // frmPpuViewer + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(709, 569); + this.Controls.Add(this.tabMain); + this.Controls.Add(this.menuStrip1); + this.MainMenuStrip = this.menuStrip1; + this.MinimumSize = new System.Drawing.Size(725, 607); + this.Name = "frmPpuViewer"; + this.Text = "PPU Viewer"; + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.tabMain.ResumeLayout(false); + this.tpgNametableViewer.ResumeLayout(false); + this.tpgChrViewer.ResumeLayout(false); + this.tpgSpriteViewer.ResumeLayout(false); + this.tpgPaletteViewer.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuClose; + private System.Windows.Forms.ToolStripMenuItem viewToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem mnuRefresh; + private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh; + private System.Windows.Forms.TabControl tabMain; + private System.Windows.Forms.TabPage tpgNametableViewer; + private System.Windows.Forms.TabPage tpgChrViewer; + private System.Windows.Forms.TabPage tpgSpriteViewer; + private Controls.ctrlNametableViewer ctrlNametableViewer; + private Controls.ctrlChrViewer ctrlChrViewer; + private Controls.ctrlSpriteViewer ctrlSpriteViewer; + private System.Windows.Forms.TabPage tpgPaletteViewer; + private Controls.ctrlPaletteViewer ctrlPaletteViewer; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + } +} \ No newline at end of file diff --git a/GUI.NET/Debugger/frmPpuViewer.cs b/GUI.NET/Debugger/frmPpuViewer.cs new file mode 100644 index 00000000..416d022a --- /dev/null +++ b/GUI.NET/Debugger/frmPpuViewer.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using Mesen.GUI.Forms; + +namespace Mesen.GUI.Debugger +{ + public partial class frmPpuViewer : BaseForm + { + private InteropEmu.NotificationListener _notifListener; + + public frmPpuViewer() + { + InitializeComponent(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + if(!this.DesignMode) { + this._notifListener = new InteropEmu.NotificationListener(); + this._notifListener.OnNotification += this._notifListener_OnNotification; + + this.ctrlNametableViewer.RefreshViewer(); + this.ctrlChrViewer.RefreshViewer(); + this.ctrlSpriteViewer.RefreshViewer(); + this.ctrlPaletteViewer.RefreshViewer(); + } + } + + private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) + { + if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) { + this.BeginInvoke((MethodInvoker)(() => this.RefreshViewers())); + } else if(e.NotificationType == InteropEmu.ConsoleNotificationType.PpuFrameDone) { + this.BeginInvoke((MethodInvoker)(() => this.AutoRefresh())); + } + } + + private void RefreshViewers() + { + if(this.tabMain.SelectedTab == this.tpgNametableViewer) { + this.ctrlNametableViewer.RefreshViewer(); + } else if(this.tabMain.SelectedTab == this.tpgChrViewer) { + this.ctrlChrViewer.RefreshViewer(); + } else if(this.tabMain.SelectedTab == this.tpgSpriteViewer) { + this.ctrlSpriteViewer.RefreshViewer(); + } else if(this.tabMain.SelectedTab == this.tpgPaletteViewer) { + this.ctrlPaletteViewer.RefreshViewer(); + } + } + + private void AutoRefresh() + { + if(mnuAutoRefresh.Checked) { + this.RefreshViewers(); + } + } + + private void mnuRefresh_Click(object sender, EventArgs e) + { + this.RefreshViewers(); + } + + private void mnuClose_Click(object sender, EventArgs e) + { + this.Close(); + } + } +} diff --git a/GUI.NET/Debugger/frmPpuViewer.resx b/GUI.NET/Debugger/frmPpuViewer.resx new file mode 100644 index 00000000..d5494e30 --- /dev/null +++ b/GUI.NET/Debugger/frmPpuViewer.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/GUI.NET/Forms/frmMain.Designer.cs b/GUI.NET/Forms/frmMain.Designer.cs index cda20401..f5e8f2f5 100644 --- a/GUI.NET/Forms/frmMain.Designer.cs +++ b/GUI.NET/Forms/frmMain.Designer.cs @@ -20,6 +20,9 @@ _notifListener.Dispose(); _notifListener = null; } + if(_debugger != null) { + _debugger.Close(); + } StopEmu(); InteropEmu.Release(); base.Dispose(disposing); diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index a061f474..e390c3e2 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -109,6 +109,24 @@ ctrlBreakpoints.cs + + UserControl + + + ctrlPaletteViewer.cs + + + UserControl + + + ctrlSpriteViewer.cs + + + UserControl + + + ctrlChrViewer.cs + UserControl @@ -127,6 +145,12 @@ ctrlHexViewer.cs + + UserControl + + + ctrlNametableViewer.cs + UserControl @@ -169,6 +193,12 @@ frmMemoryViewer.cs + + Form + + + frmPpuViewer.cs + BaseConfigForm.cs @@ -259,6 +289,15 @@ ctrlBreakpoints.cs + + ctrlPaletteViewer.cs + + + ctrlSpriteViewer.cs + + + ctrlChrViewer.cs + ctrlConsoleStatus.cs @@ -268,6 +307,9 @@ ctrlHexViewer.cs + + ctrlNametableViewer.cs + ctrlScrollableTextbox.cs @@ -286,6 +328,9 @@ frmMemoryViewer.cs + + frmPpuViewer.cs + BaseConfigForm.cs diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index c7fc1aee..885cf78b 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -83,6 +83,10 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern Byte DebugGetMemoryValue(UInt32 addr); [DllImport(DLLPath)] public static extern UInt32 DebugGetRelativeAddress(UInt32 addr); [DllImport(DLLPath, EntryPoint="DebugGetMemoryState")] private static extern UInt32 DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer); + [DllImport(DLLPath, EntryPoint="DebugGetNametable")] private static extern void DebugGetNametableWrapper(UInt32 nametableIndex, IntPtr frameBuffer, IntPtr tileData, IntPtr attributeData); + [DllImport(DLLPath, EntryPoint="DebugGetChrBank")] private static extern void DebugGetChrBankWrapper(UInt32 bankIndex, IntPtr frameBuffer, Byte palette); + [DllImport(DLLPath, EntryPoint="DebugGetSprites")] private static extern void DebugGetSpritesWrapper(IntPtr frameBuffer); + [DllImport(DLLPath, EntryPoint="DebugGetPalette")] private static extern void DebugGetPaletteWrapper(IntPtr frameBuffer); public static byte[] DebugGetMemoryState(DebugMemoryType type) { @@ -97,6 +101,66 @@ namespace Mesen.GUI return buffer; } + public static void DebugGetNametable(int nametableIndex, out byte[] frameData, out byte[] tileData, out byte[] attributeData) + { + frameData = new byte[256*240*4]; + tileData = new byte[32*30]; + attributeData = new byte[32*30]; + + GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned); + GCHandle hTileData = GCHandle.Alloc(tileData, GCHandleType.Pinned); + GCHandle hAttributeData = GCHandle.Alloc(attributeData, GCHandleType.Pinned); + try { + InteropEmu.DebugGetNametableWrapper((UInt32)nametableIndex, hFrameData.AddrOfPinnedObject(), hTileData.AddrOfPinnedObject(), hAttributeData.AddrOfPinnedObject()); + } finally { + hFrameData.Free(); + hTileData.Free(); + hAttributeData.Free(); + } + } + + public static byte[] DebugGetChrBank(int bankIndex, int palette) + { + byte[] frameData = new byte[128*128*4]; + + GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned); + try { + InteropEmu.DebugGetChrBankWrapper((UInt32)bankIndex, hFrameData.AddrOfPinnedObject(), (Byte)palette); + } finally { + hFrameData.Free(); + } + + return frameData; + } + + public static byte[] DebugGetSprites() + { + byte[] frameData = new byte[64*128*4]; + + GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned); + try { + InteropEmu.DebugGetSpritesWrapper(hFrameData.AddrOfPinnedObject()); + } finally { + hFrameData.Free(); + } + + return frameData; + } + + public static byte[] DebugGetPalette() + { + byte[] frameData = new byte[4*8*4]; + + GCHandle hFrameData = GCHandle.Alloc(frameData, GCHandleType.Pinned); + try { + InteropEmu.DebugGetPaletteWrapper(hFrameData.AddrOfPinnedObject()); + } finally { + hFrameData.Free(); + } + + return frameData; + } + public static string GetROMPath() { return PtrToStringUtf8(InteropEmu.GetROMPathWrapper()); } public static string GetKeyName(UInt32 key) { return PtrToStringUtf8(InteropEmu.GetKeyNameWrapper(key)); } @@ -129,6 +193,9 @@ namespace Mesen.GUI GameResumed = 4, GameStopped = 5, CodeBreak = 6, + CheatAdded = 7, + CheatRemoved = 8, + PpuFrameDone = 9, } public struct KeyMapping diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index 497845c8..28ae7144 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -34,6 +34,10 @@ extern "C" DllExport const char* __stdcall DebugGetCode() { return _debugger->GetCode()->c_str(); } DllExport uint32_t __stdcall DebugGetMemoryState(uint32_t type, uint8_t *buffer) { return _debugger->GetMemoryState((DebugMemoryType)type, buffer); } + DllExport void __stdcall DebugGetNametable(uint32_t nametableIndex, uint32_t *frameBuffer, uint8_t *tileData, uint8_t *attributeData) { _debugger->GetNametable(nametableIndex, frameBuffer, tileData, attributeData); } + DllExport void __stdcall DebugGetChrBank(uint32_t bankIndex, uint32_t *frameBuffer, uint8_t palette) { _debugger->GetChrBank(bankIndex, frameBuffer, palette); } + DllExport void __stdcall DebugGetSprites(uint32_t *frameBuffer) { _debugger->GetSprites(frameBuffer); } + DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { _debugger->GetPalette(frameBuffer); } DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return _debugger->GetMemoryValue(addr); } DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return _debugger->GetRelativeAddress(addr); }