diff --git a/Core/CallstackManager.cpp b/Core/CallstackManager.cpp index df2da50..ae6522f 100644 --- a/Core/CallstackManager.cpp +++ b/Core/CallstackManager.cpp @@ -32,9 +32,11 @@ void CallstackManager::Pop(uint32_t destAddress) return; } - uint32_t returnAddr = _callstack.back().Return; + StackFrameInfo prevFrame = _callstack.back(); _callstack.pop_back(); + uint32_t returnAddr = prevFrame.Return; + if(!_callstack.empty() && destAddress != returnAddr) { //Mismatch, pop that stack frame and add the new one bool foundMatch = false; @@ -65,4 +67,13 @@ void CallstackManager::GetCallstack(StackFrameInfo* callstackArray, uint32_t &ca i++; } callstackSize = i; -} \ No newline at end of file +} + +int32_t CallstackManager::GetReturnAddress() +{ + DebugBreakHelper helper(_debugger); + if(_callstack.empty()) { + return -1; + } + return _callstack.back().Return; +} diff --git a/Core/CallstackManager.h b/Core/CallstackManager.h index 9afc6e3..eb5ff8d 100644 --- a/Core/CallstackManager.h +++ b/Core/CallstackManager.h @@ -17,4 +17,5 @@ public: void Pop(uint32_t destAddr); void GetCallstack(StackFrameInfo* callstackArray, uint32_t &callstackSize); + int32_t GetReturnAddress(); }; \ No newline at end of file diff --git a/Core/Console.cpp b/Core/Console.cpp index d0918e0..ec9cbba 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -593,6 +593,13 @@ void Console::ProcessPpuCycle() } } +void Console::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi) +{ + if(_debugger) { + _debugger->ProcessInterrupt(originalPc, currentPc, forNmi); + } +} + void Console::ProcessEvent(EventType type) { if(_debugger) { diff --git a/Core/Console.h b/Core/Console.h index 076df91..06eabf3 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -127,5 +127,6 @@ public: void ProcessWorkRamRead(uint32_t addr, uint8_t value); void ProcessWorkRamWrite(uint32_t addr, uint8_t value); void ProcessPpuCycle(); + void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi); void ProcessEvent(EventType type); }; \ No newline at end of file diff --git a/Core/Cpu.cpp b/Core/Cpu.cpp index b1345ac..199a9bd 100644 --- a/Core/Cpu.cpp +++ b/Core/Cpu.cpp @@ -73,12 +73,14 @@ void Cpu::Exec() //Use the state of the IRQ/NMI flags on the previous cycle to determine if an IRQ is processed or not if(_state.PrevNmiFlag) { + uint32_t originalPc = GetProgramAddress(_state.PC); ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector); - _console->ProcessEvent(EventType::Nmi); + _console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), true); _state.NmiFlag = false; } else if(_state.PrevIrqSource && !CheckFlag(ProcFlags::IrqDisable)) { + uint32_t originalPc = GetProgramAddress(_state.PC); ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector); - _console->ProcessEvent(EventType::Irq); + _console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), false); } } diff --git a/Core/DebugTypes.h b/Core/DebugTypes.h index 24c94fa..249795c 100644 --- a/Core/DebugTypes.h +++ b/Core/DebugTypes.h @@ -204,4 +204,12 @@ struct StackFrameInfo uint32_t Target; uint32_t Return; StackFrameFlags Flags; -}; \ No newline at end of file +}; + +enum class StepType +{ + CpuStep, + CpuStepOut, + CpuStepOver, + PpuStep, +}; diff --git a/Core/Debugger.cpp b/Core/Debugger.cpp index 6758670..a24e4c0 100644 --- a/Core/Debugger.cpp +++ b/Core/Debugger.cpp @@ -109,6 +109,8 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType _callstackManager->Pop(pc); } + ProcessStepConditions(_prevOpCode, pc); + _prevOpCode = value; _prevProgramCounter = pc; @@ -187,6 +189,35 @@ void Debugger::ProcessPpuCycle() uint16_t scanline = _ppu->GetState().Scanline; uint16_t cycle = _ppu->GetState().Cycle; _ppuTools->UpdateViewers(scanline, cycle); + + if(_ppuStepCount > 0) { + _ppuStepCount--; + if(_ppuStepCount == 0) { + _cpuStepCount = 0; + SleepUntilResume(); + } + } +} + +void Debugger::SleepUntilResume() +{ + _console->GetSoundMixer()->StopAudio(); + _disassembler->Disassemble(); + + _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak); + _executionStopped = true; + while(_cpuStepCount == 0 || _breakRequestCount) { + std::this_thread::sleep_for(std::chrono::duration(10)); + } + _executionStopped = false; +} + +void Debugger::ProcessStepConditions(uint8_t opCode, uint32_t currentPc) +{ + if(_breakAddress == currentPc && (opCode == 0x60 || opCode == 0x40 || opCode == 0x6B || opCode == 0x44 || opCode == 0x54)) { + //RTS/RTL/RTI found, if we're on the expected return address, break immediately (for step over/step out) + _cpuStepCount = 0; + } } void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo) @@ -196,31 +227,19 @@ void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInf } if(_cpuStepCount == 0 || _breakRequestCount) { - _console->GetSoundMixer()->StopAudio(); - _disassembler->Disassemble(); - - _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak); - _executionStopped = true; - while(_cpuStepCount == 0 || _breakRequestCount) { - std::this_thread::sleep_for(std::chrono::duration(10)); - } - _executionStopped = false; + SleepUntilResume(); } } -void Debugger::ProcessInterrupt(bool forNmi) +void Debugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi) { - CpuState state = _cpu->GetState(); - _callstackManager->Push(_prevProgramCounter, (state.K << 16) | state.PC, _prevProgramCounter, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq); + _callstackManager->Push(_prevProgramCounter, currentPc, originalPc, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq); _eventManager->AddEvent(forNmi ? DebugEventType::Nmi : DebugEventType::Irq); } void Debugger::ProcessEvent(EventType type) { switch(type) { - case EventType::Nmi: ProcessInterrupt(true); break; - case EventType::Irq: ProcessInterrupt(false); break; - case EventType::StartFrame: _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::EventViewerRefresh); _eventManager->ClearFrameEvents(); @@ -244,11 +263,45 @@ int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultTy void Debugger::Run() { _cpuStepCount = -1; + _breakAddress = -1; + _ppuStepCount = -1; } -void Debugger::Step(int32_t stepCount) +void Debugger::Step(int32_t stepCount, StepType type) { - _cpuStepCount = stepCount; + switch(type) { + case StepType::CpuStep: + _cpuStepCount = stepCount; + _breakAddress = -1; + _ppuStepCount = -1; + break; + + case StepType::CpuStepOut: + _breakAddress = _callstackManager->GetReturnAddress(); + _cpuStepCount = -1; + _ppuStepCount = -1; + break; + + case StepType::CpuStepOver: + if(_prevOpCode == 0x20 || _prevOpCode == 0x22 || _prevOpCode == 0xFC || _prevOpCode == 0x00 || _prevOpCode == 0x02 || _prevOpCode == 0x44 || _prevOpCode == 0x54) { + //JSR, JSL, BRK, COP, MVP, MVN + _breakAddress = (_prevProgramCounter & 0xFF0000) | (((_prevProgramCounter & 0xFFFF) + DisassemblyInfo::GetOperandSize(_prevOpCode, 0) + 1) & 0xFFFF); + _cpuStepCount = -1; + _ppuStepCount = -1; + } else { + //For any other instruction, step over is the same as step into + _cpuStepCount = 1; + _breakAddress = -1; + _ppuStepCount = -1; + } + break; + + case StepType::PpuStep: + _ppuStepCount = stepCount; + _cpuStepCount = -1; + _breakAddress = -1; + break; + } } bool Debugger::IsExecutionStopped() diff --git a/Core/Debugger.h b/Core/Debugger.h index 3516ad8..e37430c 100644 --- a/Core/Debugger.h +++ b/Core/Debugger.h @@ -2,6 +2,7 @@ #include "stdafx.h" #include "CpuTypes.h" #include "PpuTypes.h" +#include "DebugTypes.h" class Console; class Cpu; @@ -20,15 +21,8 @@ class EventManager; class CallstackManager; enum class EventType; -enum class SnesMemoryType; -enum class MemoryOperationType; -enum class BreakpointCategory; enum class EvalResultType : int32_t; -struct DebugState; -struct MemoryOperationInfo; -struct AddressInfo; - class Debugger { private: @@ -53,12 +47,15 @@ private: atomic _breakRequestCount; atomic _cpuStepCount; + atomic _ppuStepCount; + atomic _breakAddress; uint8_t _prevOpCode = 0; uint32_t _prevProgramCounter = 0; + void SleepUntilResume(); + void ProcessStepConditions(uint8_t opCode, uint32_t currentPc); void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo); - void ProcessInterrupt(bool forNmi); public: Debugger(shared_ptr console); @@ -75,12 +72,13 @@ public: void ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType); void ProcessPpuCycle(); + void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi); void ProcessEvent(EventType type); int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache); void Run(); - void Step(int32_t stepCount); + void Step(int32_t stepCount, StepType type = StepType::CpuStep); bool IsExecutionStopped(); void BreakRequest(bool release); diff --git a/InteropDLL/DebugApiWrapper.cpp b/InteropDLL/DebugApiWrapper.cpp index 0be0591..920d72d 100644 --- a/InteropDLL/DebugApiWrapper.cpp +++ b/InteropDLL/DebugApiWrapper.cpp @@ -38,7 +38,7 @@ extern "C" DllExport bool __stdcall IsExecutionStopped() { return GetDebugger()->IsExecutionStopped(); } DllExport void __stdcall ResumeExecution() { if(IsDebuggerRunning()) GetDebugger()->Run(); } - DllExport void __stdcall Step(uint32_t count) { GetDebugger()->Step(count); } + DllExport void __stdcall Step(uint32_t count, StepType type) { GetDebugger()->Step(count, type); } DllExport void __stdcall GetDisassemblyLineData(uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(lineIndex, data); } DllExport uint32_t __stdcall GetDisassemblyLineCount() { return GetDebugger()->GetDisassembler()->GetLineCount(); } diff --git a/UI/Debugger/Controls/ctrlScrollableTextbox.cs b/UI/Debugger/Controls/ctrlScrollableTextbox.cs index b8d23ef..453dd5c 100644 --- a/UI/Debugger/Controls/ctrlScrollableTextbox.cs +++ b/UI/Debugger/Controls/ctrlScrollableTextbox.cs @@ -304,6 +304,12 @@ namespace Mesen.GUI.Debugger.Controls } else if(keyData == ConfigManager.Config.Debug.Shortcuts.Find) { this.OpenSearchBox(true); return true; + } else if(keyData == ConfigManager.Config.Debug.Shortcuts.FindNext) { + this.FindNext(); + return true; + } else if(keyData == ConfigManager.Config.Debug.Shortcuts.FindPrev) { + this.FindPrevious(); + return true; } if(keyData == (Keys.Control | Keys.F)) { diff --git a/UI/Debugger/frmDebugger.Designer.cs b/UI/Debugger/frmDebugger.Designer.cs index caadf7a..31f3da0 100644 --- a/UI/Debugger/frmDebugger.Designer.cs +++ b/UI/Debugger/frmDebugger.Designer.cs @@ -49,7 +49,7 @@ this.mnuDisableEnableBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); this.mnuRunCpuCycle = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuRun1000Cycles = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRun1000Instructions = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunPpuCycle = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunScanline = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem(); @@ -113,7 +113,7 @@ this.mnuDisableEnableBreakpoint, this.toolStripMenuItem2, this.mnuRunCpuCycle, - this.mnuRun1000Cycles, + this.mnuRun1000Instructions, this.mnuRunPpuCycle, this.mnuRunScanline, this.mnuRunOneFrame, @@ -128,9 +128,8 @@ // this.mnuContinue.Image = global::Mesen.GUI.Properties.Resources.MediaPlay; this.mnuContinue.Name = "mnuContinue"; - this.mnuContinue.Size = new System.Drawing.Size(212, 22); + this.mnuContinue.Size = new System.Drawing.Size(213, 22); this.mnuContinue.Text = "Continue"; - this.mnuContinue.Click += new System.EventHandler(this.mnuContinue_Click); // // mnuBreak // @@ -138,136 +137,134 @@ this.mnuBreak.Image = global::Mesen.GUI.Properties.Resources.MediaPause; this.mnuBreak.Name = "mnuBreak"; this.mnuBreak.ShortcutKeyDisplayString = ""; - this.mnuBreak.Size = new System.Drawing.Size(212, 22); + this.mnuBreak.Size = new System.Drawing.Size(213, 22); this.mnuBreak.Text = "Break"; // // toolStripMenuItem3 // this.toolStripMenuItem3.Name = "toolStripMenuItem3"; - this.toolStripMenuItem3.Size = new System.Drawing.Size(209, 6); + this.toolStripMenuItem3.Size = new System.Drawing.Size(210, 6); // // mnuStepInto // this.mnuStepInto.Image = global::Mesen.GUI.Properties.Resources.StepInto; this.mnuStepInto.Name = "mnuStepInto"; - this.mnuStepInto.Size = new System.Drawing.Size(212, 22); + this.mnuStepInto.Size = new System.Drawing.Size(213, 22); this.mnuStepInto.Text = "Step Into"; - this.mnuStepInto.Click += new System.EventHandler(this.mnuStepInto_Click); // // mnuStepOver // this.mnuStepOver.Image = global::Mesen.GUI.Properties.Resources.StepOver; this.mnuStepOver.Name = "mnuStepOver"; - this.mnuStepOver.Size = new System.Drawing.Size(212, 22); + this.mnuStepOver.Size = new System.Drawing.Size(213, 22); this.mnuStepOver.Text = "Step Over"; // // mnuStepOut // this.mnuStepOut.Image = global::Mesen.GUI.Properties.Resources.StepOut; this.mnuStepOut.Name = "mnuStepOut"; - this.mnuStepOut.Size = new System.Drawing.Size(212, 22); + this.mnuStepOut.Size = new System.Drawing.Size(213, 22); this.mnuStepOut.Text = "Step Out"; // // mnuStepBack // this.mnuStepBack.Image = global::Mesen.GUI.Properties.Resources.StepBack; this.mnuStepBack.Name = "mnuStepBack"; - this.mnuStepBack.Size = new System.Drawing.Size(212, 22); + this.mnuStepBack.Size = new System.Drawing.Size(213, 22); this.mnuStepBack.Text = "Step Back"; // // toolStripMenuItem1 // this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - this.toolStripMenuItem1.Size = new System.Drawing.Size(209, 6); + this.toolStripMenuItem1.Size = new System.Drawing.Size(210, 6); // // mnuReset // this.mnuReset.Image = global::Mesen.GUI.Properties.Resources.Refresh; this.mnuReset.Name = "mnuReset"; - this.mnuReset.Size = new System.Drawing.Size(212, 22); + this.mnuReset.Size = new System.Drawing.Size(213, 22); this.mnuReset.Text = "Reset"; // // mnuPowerCycle // this.mnuPowerCycle.Image = global::Mesen.GUI.Properties.Resources.PowerCycle; this.mnuPowerCycle.Name = "mnuPowerCycle"; - this.mnuPowerCycle.Size = new System.Drawing.Size(212, 22); + this.mnuPowerCycle.Size = new System.Drawing.Size(213, 22); this.mnuPowerCycle.Text = "Power Cycle"; // // toolStripMenuItem24 // this.toolStripMenuItem24.Name = "toolStripMenuItem24"; - this.toolStripMenuItem24.Size = new System.Drawing.Size(209, 6); + this.toolStripMenuItem24.Size = new System.Drawing.Size(210, 6); // // mnuToggleBreakpoint // this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint; this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint"; - this.mnuToggleBreakpoint.Size = new System.Drawing.Size(212, 22); + this.mnuToggleBreakpoint.Size = new System.Drawing.Size(213, 22); this.mnuToggleBreakpoint.Text = "Toggle Breakpoint"; // // mnuDisableEnableBreakpoint // this.mnuDisableEnableBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointDisabled; this.mnuDisableEnableBreakpoint.Name = "mnuDisableEnableBreakpoint"; - this.mnuDisableEnableBreakpoint.Size = new System.Drawing.Size(212, 22); + this.mnuDisableEnableBreakpoint.Size = new System.Drawing.Size(213, 22); this.mnuDisableEnableBreakpoint.Text = "Disable/Enable Breakpoint"; // // toolStripMenuItem2 // this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(209, 6); + this.toolStripMenuItem2.Size = new System.Drawing.Size(210, 6); // // mnuRunCpuCycle // this.mnuRunCpuCycle.Image = global::Mesen.GUI.Properties.Resources.JumpTarget; this.mnuRunCpuCycle.Name = "mnuRunCpuCycle"; - this.mnuRunCpuCycle.Size = new System.Drawing.Size(212, 22); + this.mnuRunCpuCycle.Size = new System.Drawing.Size(213, 22); this.mnuRunCpuCycle.Text = "Run one CPU cycle"; // - // mnuRun1000Cycles + // mnuRun1000Instructions // - this.mnuRun1000Cycles.Name = "mnuRun1000Cycles"; - this.mnuRun1000Cycles.Size = new System.Drawing.Size(212, 22); - this.mnuRun1000Cycles.Text = "Run 1000 CPU cycles"; - this.mnuRun1000Cycles.Click += new System.EventHandler(this.mnuRun1000Cycles_Click); + this.mnuRun1000Instructions.Name = "mnuRun1000Instructions"; + this.mnuRun1000Instructions.Size = new System.Drawing.Size(213, 22); + this.mnuRun1000Instructions.Text = "Run 1000 CPU instructions"; // // mnuRunPpuCycle // this.mnuRunPpuCycle.Image = global::Mesen.GUI.Properties.Resources.RunPpuCycle; this.mnuRunPpuCycle.Name = "mnuRunPpuCycle"; - this.mnuRunPpuCycle.Size = new System.Drawing.Size(212, 22); + this.mnuRunPpuCycle.Size = new System.Drawing.Size(213, 22); this.mnuRunPpuCycle.Text = "Run one PPU cycle"; // // mnuRunScanline // this.mnuRunScanline.Image = global::Mesen.GUI.Properties.Resources.RunPpuScanline; this.mnuRunScanline.Name = "mnuRunScanline"; - this.mnuRunScanline.Size = new System.Drawing.Size(212, 22); + this.mnuRunScanline.Size = new System.Drawing.Size(213, 22); this.mnuRunScanline.Text = "Run one scanline"; // // mnuRunOneFrame // this.mnuRunOneFrame.Image = global::Mesen.GUI.Properties.Resources.RunPpuFrame; this.mnuRunOneFrame.Name = "mnuRunOneFrame"; - this.mnuRunOneFrame.Size = new System.Drawing.Size(212, 22); + this.mnuRunOneFrame.Size = new System.Drawing.Size(213, 22); this.mnuRunOneFrame.Text = "Run one frame"; // // toolStripMenuItem8 // this.toolStripMenuItem8.Name = "toolStripMenuItem8"; - this.toolStripMenuItem8.Size = new System.Drawing.Size(209, 6); + this.toolStripMenuItem8.Size = new System.Drawing.Size(210, 6); // // mnuBreakIn // this.mnuBreakIn.Name = "mnuBreakIn"; - this.mnuBreakIn.Size = new System.Drawing.Size(212, 22); + this.mnuBreakIn.Size = new System.Drawing.Size(213, 22); this.mnuBreakIn.Text = "Break in..."; // // mnuBreakOn // this.mnuBreakOn.Name = "mnuBreakOn"; - this.mnuBreakOn.Size = new System.Drawing.Size(212, 22); + this.mnuBreakOn.Size = new System.Drawing.Size(213, 22); this.mnuBreakOn.Text = "Break on..."; // // ctrlSplitContainer @@ -440,7 +437,7 @@ private System.Windows.Forms.GroupBox grpBreakpoints; private Controls.ctrlBreakpoints ctrlBreakpoints; private Controls.ctrlConsoleStatus ctrlStatus; - private System.Windows.Forms.ToolStripMenuItem mnuRun1000Cycles; + private System.Windows.Forms.ToolStripMenuItem mnuRun1000Instructions; private GUI.Controls.ctrlMesenToolStrip tsToolbar; private System.Windows.Forms.GroupBox grpCallstack; private Controls.ctrlCallstack ctrlCallstack; diff --git a/UI/Debugger/frmDebugger.cs b/UI/Debugger/frmDebugger.cs index 274a9d6..c6e89b7 100644 --- a/UI/Debugger/frmDebugger.cs +++ b/UI/Debugger/frmDebugger.cs @@ -66,6 +66,15 @@ namespace Mesen.GUI.Debugger mnuRunPpuCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuCycle)); mnuRunScanline.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuScanline)); mnuRunOneFrame.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuFrame)); + + mnuStepInto.Click += (s, e) => { DebugApi.Step(1); }; + mnuStepOver.Click += (s, e) => { DebugApi.Step(1, StepType.CpuStepOver); }; + mnuStepOut.Click += (s, e) => { DebugApi.Step(1, StepType.CpuStepOut); }; + mnuRun1000Instructions.Click += (s, e) => { DebugApi.Step(1000); }; + mnuRunPpuCycle.Click += (s, e) => { DebugApi.Step(1, StepType.PpuStep); }; + mnuRunScanline.Click += (s, e) => { DebugApi.Step(341, StepType.PpuStep); }; + mnuRunOneFrame.Click += (s, e) => { DebugApi.Step(341*262, StepType.PpuStep); }; //TODO ntsc/pal + mnuContinue.Click += (s, e) => { DebugApi.ResumeExecution(); }; } private void InitToolbar() @@ -97,21 +106,6 @@ namespace Mesen.GUI.Debugger } } - private void mnuStepInto_Click(object sender, EventArgs e) - { - DebugApi.Step(1); - } - - private void mnuContinue_Click(object sender, EventArgs e) - { - DebugApi.ResumeExecution(); - } - - private void mnuRun1000Cycles_Click(object sender, EventArgs e) - { - DebugApi.Step(1000); - } - private void ctrlCallstack_FunctionSelected(uint address) { ctrlDisassemblyView.ScrollToAddress(address); diff --git a/UI/Interop/DebugApi.cs b/UI/Interop/DebugApi.cs index 07a48d5..36f655b 100644 --- a/UI/Interop/DebugApi.cs +++ b/UI/Interop/DebugApi.cs @@ -20,7 +20,7 @@ namespace Mesen.GUI [DllImport(DllPath)] public static extern void ReleaseDebugger(); [DllImport(DllPath)] public static extern void ResumeExecution(); - [DllImport(DllPath)] public static extern void Step(Int32 instructionCount); + [DllImport(DllPath)] public static extern void Step(Int32 instructionCount, StepType type = StepType.CpuStep); [DllImport(DllPath)] public static extern void StartTraceLogger([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename); [DllImport(DllPath)] public static extern void StopTraceLogger(); @@ -375,4 +375,12 @@ namespace Mesen.GUI Nmi = 1, Irq = 2 } + + public enum StepType + { + CpuStep, + CpuStepOut, + CpuStepOver, + PpuStep, + } }