From cb8ec83408053bf07c999544c0d8908092443b7f Mon Sep 17 00:00:00 2001 From: Souryo Date: Sun, 9 Aug 2015 14:47:27 -0400 Subject: [PATCH] Debugger - Added callstack --- Core/BaseMapper.h | 13 +- Core/Debugger.cpp | 34 +++++ Core/Debugger.h | 6 + .../BaseScrollableTextboxUserControl.cs | 5 + .../Controls/ctrlCallstack.Designer.cs | 71 +++++++++++ GUI.NET/Debugger/Controls/ctrlCallstack.cs | 74 +++++++++++ GUI.NET/Debugger/Controls/ctrlCallstack.resx | 120 ++++++++++++++++++ GUI.NET/Debugger/frmDebugger.Designer.cs | 96 ++++++++------ GUI.NET/Debugger/frmDebugger.cs | 6 + GUI.NET/GUI.NET.csproj | 9 ++ GUI.NET/InteropEmu.cs | 26 +++- InteropDLL/DebugWrapper.cpp | 2 + 12 files changed, 414 insertions(+), 48 deletions(-) create mode 100644 GUI.NET/Debugger/Controls/ctrlCallstack.Designer.cs create mode 100644 GUI.NET/Debugger/Controls/ctrlCallstack.cs create mode 100644 GUI.NET/Debugger/Controls/ctrlCallstack.resx diff --git a/Core/BaseMapper.h b/Core/BaseMapper.h index 79a40f84..fb1f0b26 100644 --- a/Core/BaseMapper.h +++ b/Core/BaseMapper.h @@ -474,14 +474,15 @@ class BaseMapper : public IMemoryHandler, public Snapshotable, public INotificat int32_t FromAbsoluteAddress(uint32_t addr) { - /*uint32_t page = addr / GetPRGPageSize(); - for(int i = 0, len = GetPRGSlotCount(); i < len; i++) { - if((_prgSlotPages[i] % GetPRGPageCount()) == page) { - uint32_t offset = addr - (page * GetPRGPageSize()); - return GetPRGPageSize() * i + offset + 0x8000; + uint8_t* ptrAddress = _prgRom + addr; + + for(int i = 0; i < 256; i++) { + uint8_t* pageAddress = _prgPages[i]; + if(pageAddress != nullptr && ptrAddress >= pageAddress && ptrAddress <= pageAddress + 0xFF) { + return (i << 8) + (ptrAddress - pageAddress); } } - */ + //Address is currently not mapped return -1; } diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index b7112ee0..e72ada69 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -112,6 +112,24 @@ void Debugger::PrivateCheckBreakpoint(BreakpointType type, uint32_t addr) bool breakDone = false; if(type == BreakpointType::Execute) { _lastInstruction = _memoryManager->DebugRead(addr); + + //Update callstack + if(_lastInstruction == 0x60 && !_callstackRelative.empty()) { + //RTS + _callstackRelative.pop_back(); + _callstackRelative.pop_back(); + _callstackAbsolute.pop_back(); + _callstackAbsolute.pop_back(); + } else if(_lastInstruction == 0x20 && _callstackRelative.size() < 1022) { + //JSR + uint16_t targetAddr = _memoryManager->DebugRead(addr + 1) | (_memoryManager->DebugRead(addr + 2) << 8); + _callstackRelative.push_back(addr); + _callstackRelative.push_back(targetAddr); + + _callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(addr)); + _callstackAbsolute.push_back(_mapper->ToAbsoluteAddress(targetAddr)); + } + if(_stepOut && _lastInstruction == 0x60) { //RTS found, set StepCount to 2 to break on the following instruction Step(2); @@ -435,4 +453,20 @@ void Debugger::GetPalette(uint32_t* frameBuffer) } VideoDecoder::GetInstance()->DebugDecodeFrame(screenBuffer, frameBuffer, 4*8); delete[] screenBuffer; +} + +void Debugger::GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelative) +{ + for(size_t i = 0, len = _callstackRelative.size(); i < len; i++) { + callstackAbsolute[i] = _callstackAbsolute[i]; + + int32_t relativeAddr = _callstackRelative[i]; + if(_mapper->FromAbsoluteAddress(_callstackAbsolute[i]) == -1) { + //Mark address as an unmapped memory addr + relativeAddr |= 0x10000; + } + callstackRelative[i] = relativeAddr; + } + callstackAbsolute[_callstackRelative.size()] = -2; + callstackRelative[_callstackRelative.size()] = -2; } \ No newline at end of file diff --git a/Core/Debugger.h b/Core/Debugger.h index 5467dbeb..c1984e1d 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -2,7 +2,9 @@ #include "stdafx.h" #include +#include using std::atomic; +using std::deque; #include "CPU.h" #include "PPU.h" @@ -44,6 +46,8 @@ private: vector> _readBreakpoints; vector> _writeBreakpoints; vector> _execBreakpoints; + deque _callstackAbsolute; + deque _callstackRelative; SimpleLock _bpLock; SimpleLock _breakLock; @@ -75,6 +79,8 @@ public: void GetSprites(uint32_t* frameBuffer); void GetPalette(uint32_t* frameBuffer); + void GetCallstack(int32_t* callstackAbsolute, int32_t* callstackRelative); + void GetState(DebugState *state); void Step(uint32_t count = 1); diff --git a/GUI.NET/Debugger/Controls/BaseScrollableTextboxUserControl.cs b/GUI.NET/Debugger/Controls/BaseScrollableTextboxUserControl.cs index 2402f126..79e8fd31 100644 --- a/GUI.NET/Debugger/Controls/BaseScrollableTextboxUserControl.cs +++ b/GUI.NET/Debugger/Controls/BaseScrollableTextboxUserControl.cs @@ -43,6 +43,11 @@ namespace Mesen.GUI.Debugger.Controls this.ScrollableTextbox.GoToAddress(); } + public void ScrollToLineNumber(int lineNumber) + { + this.ScrollableTextbox.ScrollToLineNumber(lineNumber); + } + public int GetCurrentLine() { return this.ScrollableTextbox.CurrentLine; diff --git a/GUI.NET/Debugger/Controls/ctrlCallstack.Designer.cs b/GUI.NET/Debugger/Controls/ctrlCallstack.Designer.cs new file mode 100644 index 00000000..5a9862d6 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCallstack.Designer.cs @@ -0,0 +1,71 @@ +namespace Mesen.GUI.Debugger.Controls +{ + partial class ctrlCallstack + { + /// + /// 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.lstCallstack = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.SuspendLayout(); + // + // lstCallstack + // + this.lstCallstack.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1}); + this.lstCallstack.Dock = System.Windows.Forms.DockStyle.Fill; + this.lstCallstack.Font = new System.Drawing.Font("Consolas", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.lstCallstack.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None; + this.lstCallstack.Location = new System.Drawing.Point(0, 0); + this.lstCallstack.MultiSelect = false; + this.lstCallstack.Name = "lstCallstack"; + this.lstCallstack.Size = new System.Drawing.Size(324, 125); + this.lstCallstack.TabIndex = 1; + this.lstCallstack.UseCompatibleStateImageBehavior = false; + this.lstCallstack.View = System.Windows.Forms.View.Details; + this.lstCallstack.DoubleClick += new System.EventHandler(this.lstCallstack_DoubleClick); + // + // columnHeader1 + // + this.columnHeader1.Width = 256; + // + // ctrlCallstack + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.lstCallstack); + this.Name = "ctrlCallstack"; + this.Size = new System.Drawing.Size(324, 125); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListView lstCallstack; + private System.Windows.Forms.ColumnHeader columnHeader1; + + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCallstack.cs b/GUI.NET/Debugger/Controls/ctrlCallstack.cs new file mode 100644 index 00000000..a456f133 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCallstack.cs @@ -0,0 +1,74 @@ +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; + +namespace Mesen.GUI.Debugger.Controls +{ + public partial class ctrlCallstack : UserControl + { + public event EventHandler FunctionSelected; + + private Int32[] _absoluteCallstack; + private Int32[] _relativeCallstack; + private Int32 _programCounter; + + public ctrlCallstack() + { + InitializeComponent(); + } + + public void UpdateCallstack() + { + InteropEmu.DebugGetCallstack(out _absoluteCallstack, out _relativeCallstack); + DebugState state = new DebugState(); + InteropEmu.DebugGetState(ref state); + _programCounter = state.CPU.DebugPC; + + this.lstCallstack.Items.Clear(); + int subStartAddr = -1; + for(int i = 0, len = _relativeCallstack.Length; i < len; i+=2) { + int jsrAddr = _relativeCallstack[i]; + bool unmappedAddress = false; + if(subStartAddr >= 0) { + unmappedAddress = ((subStartAddr & 0x10000) == 0x10000); + if(unmappedAddress) { + subStartAddr &= 0xFFFF; + jsrAddr &= 0xFFFF; + } + } + + string startAddr = subStartAddr >= 0 ? subStartAddr.ToString("X4") : "----"; + if(_relativeCallstack[i] == -2) { + break; + } + subStartAddr = _relativeCallstack[i+1]; + ListViewItem item = this.lstCallstack.Items.Insert(0, "$" + startAddr + " @ $" + jsrAddr.ToString("X4") + " [$" + _absoluteCallstack[i].ToString("X4") + "]"); + if(unmappedAddress) { + item.ForeColor = Color.Gray; + item.Font = new Font(item.Font, FontStyle.Italic); + } + } + this.lstCallstack.Items.Insert(0, "$" + subStartAddr.ToString("X4") + " @ $" + _programCounter.ToString("X4")); + } + + private void lstCallstack_DoubleClick(object sender, EventArgs e) + { + if(this.lstCallstack.SelectedIndices.Count > 0) { + if(this.lstCallstack.SelectedIndices[0] == 0) { + this.FunctionSelected(_programCounter, null); + } else { + Int32 address = _relativeCallstack[(this.lstCallstack.Items.Count - 1 - this.lstCallstack.SelectedIndices[0]) * 2]; + if(this.FunctionSelected != null) { + this.FunctionSelected(address, null); + } + } + } + } + } +} diff --git a/GUI.NET/Debugger/Controls/ctrlCallstack.resx b/GUI.NET/Debugger/Controls/ctrlCallstack.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/GUI.NET/Debugger/Controls/ctrlCallstack.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 3f699c39..d365bcd2 100644 --- a/GUI.NET/Debugger/frmDebugger.Designer.cs +++ b/GUI.NET/Debugger/frmDebugger.Designer.cs @@ -41,10 +41,11 @@ 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.grpBreakpoints = new System.Windows.Forms.GroupBox(); + this.ctrlBreakpoints = new Mesen.GUI.Debugger.Controls.ctrlBreakpoints(); + this.grpCallstack = new System.Windows.Forms.GroupBox(); this.menuStrip = new System.Windows.Forms.MenuStrip(); this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mnuClose = new System.Windows.Forms.ToolStripMenuItem(); @@ -72,6 +73,7 @@ this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.mnuPpuViewer = new System.Windows.Forms.ToolStripMenuItem(); this.mnuMemoryViewer = new System.Windows.Forms.ToolStripMenuItem(); + this.ctrlCallstack = new Mesen.GUI.Debugger.Controls.ctrlCallstack(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); @@ -79,8 +81,9 @@ this.tlpTop.SuspendLayout(); this.contextMenuCode.SuspendLayout(); this.tableLayoutPanel10.SuspendLayout(); - this.grpBreakpoints.SuspendLayout(); this.grpWatch.SuspendLayout(); + this.grpBreakpoints.SuspendLayout(); + this.grpCallstack.SuspendLayout(); this.menuStrip.SuspendLayout(); this.SuspendLayout(); // @@ -181,52 +184,28 @@ // // tableLayoutPanel10 // - this.tableLayoutPanel10.ColumnCount = 2; - this.tableLayoutPanel10.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel10.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel10.Controls.Add(this.grpBreakpoints, 0, 0); + this.tableLayoutPanel10.ColumnCount = 3; + this.tableLayoutPanel10.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel10.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel10.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); this.tableLayoutPanel10.Controls.Add(this.grpWatch, 0, 0); + this.tableLayoutPanel10.Controls.Add(this.grpBreakpoints, 1, 0); + this.tableLayoutPanel10.Controls.Add(this.grpCallstack, 2, 0); this.tableLayoutPanel10.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel10.Location = new System.Drawing.Point(0, 0); this.tableLayoutPanel10.Name = "tableLayoutPanel10"; this.tableLayoutPanel10.RowCount = 1; this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 162F)); - this.tableLayoutPanel10.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 162F)); this.tableLayoutPanel10.Size = new System.Drawing.Size(984, 162); this.tableLayoutPanel10.TabIndex = 0; // - // grpBreakpoints - // - this.grpBreakpoints.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints); - this.grpBreakpoints.Location = new System.Drawing.Point(495, 3); - this.grpBreakpoints.Name = "grpBreakpoints"; - this.grpBreakpoints.Size = new System.Drawing.Size(486, 156); - this.grpBreakpoints.TabIndex = 3; - 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) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); this.grpWatch.Controls.Add(this.ctrlWatch); + this.grpWatch.Dock = System.Windows.Forms.DockStyle.Fill; this.grpWatch.Location = new System.Drawing.Point(3, 3); this.grpWatch.Name = "grpWatch"; - this.grpWatch.Size = new System.Drawing.Size(486, 156); + this.grpWatch.Size = new System.Drawing.Size(322, 156); this.grpWatch.TabIndex = 2; this.grpWatch.TabStop = false; this.grpWatch.Text = "Watch"; @@ -236,9 +215,40 @@ 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.Size = new System.Drawing.Size(316, 137); this.ctrlWatch.TabIndex = 0; // + // grpBreakpoints + // + this.grpBreakpoints.Controls.Add(this.ctrlBreakpoints); + this.grpBreakpoints.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpBreakpoints.Location = new System.Drawing.Point(331, 3); + this.grpBreakpoints.Name = "grpBreakpoints"; + this.grpBreakpoints.Size = new System.Drawing.Size(322, 156); + this.grpBreakpoints.TabIndex = 3; + 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(316, 137); + this.ctrlBreakpoints.TabIndex = 0; + this.ctrlBreakpoints.BreakpointChanged += new System.EventHandler(this.ctrlBreakpoints_BreakpointChanged); + // + // grpCallstack + // + this.grpCallstack.Controls.Add(this.ctrlCallstack); + this.grpCallstack.Dock = System.Windows.Forms.DockStyle.Fill; + this.grpCallstack.Location = new System.Drawing.Point(659, 3); + this.grpCallstack.Name = "grpCallstack"; + this.grpCallstack.Size = new System.Drawing.Size(322, 156); + this.grpCallstack.TabIndex = 4; + this.grpCallstack.TabStop = false; + this.grpCallstack.Text = "Callstack"; + // // menuStrip // this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -472,6 +482,15 @@ this.mnuMemoryViewer.Text = "Memory Viewer"; this.mnuMemoryViewer.Click += new System.EventHandler(this.mnuMemoryViewer_Click); // + // ctrlCallstack + // + this.ctrlCallstack.Dock = System.Windows.Forms.DockStyle.Fill; + this.ctrlCallstack.Location = new System.Drawing.Point(3, 16); + this.ctrlCallstack.Name = "ctrlCallstack"; + this.ctrlCallstack.Size = new System.Drawing.Size(316, 137); + this.ctrlCallstack.TabIndex = 0; + this.ctrlCallstack.FunctionSelected += new System.EventHandler(this.ctrlCallstack_FunctionSelected); + // // frmDebugger // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -491,8 +510,9 @@ this.tlpTop.ResumeLayout(false); this.contextMenuCode.ResumeLayout(false); this.tableLayoutPanel10.ResumeLayout(false); - this.grpBreakpoints.ResumeLayout(false); this.grpWatch.ResumeLayout(false); + this.grpBreakpoints.ResumeLayout(false); + this.grpCallstack.ResumeLayout(false); this.menuStrip.ResumeLayout(false); this.menuStrip.PerformLayout(); this.ResumeLayout(false); @@ -542,5 +562,7 @@ private System.Windows.Forms.ToolStripMenuItem mnuIncreaseFontSize; private System.Windows.Forms.ToolStripMenuItem mnuDecreaseFontSize; private System.Windows.Forms.ToolStripMenuItem mnuResetFontSize; + private System.Windows.Forms.GroupBox grpCallstack; + private Controls.ctrlCallstack ctrlCallstack; } } \ No newline at end of file diff --git a/GUI.NET/Debugger/frmDebugger.cs b/GUI.NET/Debugger/frmDebugger.cs index 8c9a7867..d4567a41 100644 --- a/GUI.NET/Debugger/frmDebugger.cs +++ b/GUI.NET/Debugger/frmDebugger.cs @@ -91,6 +91,7 @@ namespace Mesen.GUI.Debugger ctrlConsoleStatus.UpdateStatus(ref state); ctrlWatch.UpdateWatch(); + ctrlCallstack.UpdateCallstack(); } private void ClearActiveStatement() @@ -242,5 +243,10 @@ namespace Mesen.GUI.Debugger { OpenChildForm(new frmPpuViewer()); } + + private void ctrlCallstack_FunctionSelected(object sender, EventArgs e) + { + _lastCodeWindow.ScrollToLineNumber((int)sender); + } } } diff --git a/GUI.NET/GUI.NET.csproj b/GUI.NET/GUI.NET.csproj index e390c3e2..451ac864 100644 --- a/GUI.NET/GUI.NET.csproj +++ b/GUI.NET/GUI.NET.csproj @@ -109,6 +109,12 @@ ctrlBreakpoints.cs + + UserControl + + + ctrlCallstack.cs + UserControl @@ -289,6 +295,9 @@ ctrlBreakpoints.cs + + ctrlCallstack.cs + ctrlPaletteViewer.cs diff --git a/GUI.NET/InteropEmu.cs b/GUI.NET/InteropEmu.cs index 885cf78b..64308c65 100644 --- a/GUI.NET/InteropEmu.cs +++ b/GUI.NET/InteropEmu.cs @@ -82,12 +82,8 @@ namespace Mesen.GUI [DllImport(DLLPath)] public static extern IntPtr DebugGetCode(); [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); + [DllImport(DLLPath, EntryPoint="DebugGetMemoryState")] private static extern UInt32 DebugGetMemoryStateWrapper(DebugMemoryType type, IntPtr buffer); public static byte[] DebugGetMemoryState(DebugMemoryType type) { byte[] buffer = new byte[10485760]; //10mb buffer @@ -101,6 +97,7 @@ namespace Mesen.GUI return buffer; } + [DllImport(DLLPath, EntryPoint="DebugGetNametable")] private static extern void DebugGetNametableWrapper(UInt32 nametableIndex, IntPtr frameBuffer, IntPtr tileData, IntPtr attributeData); public static void DebugGetNametable(int nametableIndex, out byte[] frameData, out byte[] tileData, out byte[] attributeData) { frameData = new byte[256*240*4]; @@ -119,6 +116,7 @@ namespace Mesen.GUI } } + [DllImport(DLLPath, EntryPoint="DebugGetChrBank")] private static extern void DebugGetChrBankWrapper(UInt32 bankIndex, IntPtr frameBuffer, Byte palette); public static byte[] DebugGetChrBank(int bankIndex, int palette) { byte[] frameData = new byte[128*128*4]; @@ -133,6 +131,7 @@ namespace Mesen.GUI return frameData; } + [DllImport(DLLPath, EntryPoint="DebugGetSprites")] private static extern void DebugGetSpritesWrapper(IntPtr frameBuffer); public static byte[] DebugGetSprites() { byte[] frameData = new byte[64*128*4]; @@ -147,6 +146,7 @@ namespace Mesen.GUI return frameData; } + [DllImport(DLLPath, EntryPoint="DebugGetPalette")] private static extern void DebugGetPaletteWrapper(IntPtr frameBuffer); public static byte[] DebugGetPalette() { byte[] frameData = new byte[4*8*4]; @@ -161,6 +161,22 @@ namespace Mesen.GUI return frameData; } + [DllImport(DLLPath, EntryPoint="DebugGetCallstack")] private static extern void DebugGetCallstackWrapper(IntPtr callstackAbsolute, IntPtr callstackRelative); + public static void DebugGetCallstack(out Int32[] callstackAbsolute, out Int32[] callstackRelative) + { + callstackAbsolute = new Int32[1024]; + callstackRelative = new Int32[1024]; + + GCHandle hAbsolute = GCHandle.Alloc(callstackAbsolute, GCHandleType.Pinned); + GCHandle hRelative = GCHandle.Alloc(callstackRelative, GCHandleType.Pinned); + try { + InteropEmu.DebugGetCallstackWrapper(hAbsolute.AddrOfPinnedObject(), hRelative.AddrOfPinnedObject()); + } finally { + hAbsolute.Free(); + hRelative.Free(); + } + } + public static string GetROMPath() { return PtrToStringUtf8(InteropEmu.GetROMPathWrapper()); } public static string GetKeyName(UInt32 key) { return PtrToStringUtf8(InteropEmu.GetKeyNameWrapper(key)); } diff --git a/InteropDLL/DebugWrapper.cpp b/InteropDLL/DebugWrapper.cpp index 28ae7144..05c6ec40 100644 --- a/InteropDLL/DebugWrapper.cpp +++ b/InteropDLL/DebugWrapper.cpp @@ -39,6 +39,8 @@ extern "C" DllExport void __stdcall DebugGetSprites(uint32_t *frameBuffer) { _debugger->GetSprites(frameBuffer); } DllExport void __stdcall DebugGetPalette(uint32_t *frameBuffer) { _debugger->GetPalette(frameBuffer); } + DllExport void __stdcall DebugGetCallstack(int32_t *callstackAbsolute, int32_t *callstackRelative) { _debugger->GetCallstack(callstackAbsolute, callstackRelative); } + DllExport uint8_t __stdcall DebugGetMemoryValue(uint32_t addr) { return _debugger->GetMemoryValue(addr); } DllExport uint32_t __stdcall DebugGetRelativeAddress(uint32_t addr) { return _debugger->GetRelativeAddress(addr); } };