Debugger: Step into, step over, run ppu cycle/scanline/frame (+ call stack fixes)

This commit is contained in:
Sour 2019-03-24 16:42:52 -04:00
parent 75361b4bce
commit 0e26e5317d
13 changed files with 165 additions and 79 deletions

View file

@ -32,9 +32,11 @@ void CallstackManager::Pop(uint32_t destAddress)
return; return;
} }
uint32_t returnAddr = _callstack.back().Return; StackFrameInfo prevFrame = _callstack.back();
_callstack.pop_back(); _callstack.pop_back();
uint32_t returnAddr = prevFrame.Return;
if(!_callstack.empty() && destAddress != returnAddr) { if(!_callstack.empty() && destAddress != returnAddr) {
//Mismatch, pop that stack frame and add the new one //Mismatch, pop that stack frame and add the new one
bool foundMatch = false; bool foundMatch = false;
@ -66,3 +68,12 @@ void CallstackManager::GetCallstack(StackFrameInfo* callstackArray, uint32_t &ca
} }
callstackSize = i; callstackSize = i;
} }
int32_t CallstackManager::GetReturnAddress()
{
DebugBreakHelper helper(_debugger);
if(_callstack.empty()) {
return -1;
}
return _callstack.back().Return;
}

View file

@ -17,4 +17,5 @@ public:
void Pop(uint32_t destAddr); void Pop(uint32_t destAddr);
void GetCallstack(StackFrameInfo* callstackArray, uint32_t &callstackSize); void GetCallstack(StackFrameInfo* callstackArray, uint32_t &callstackSize);
int32_t GetReturnAddress();
}; };

View file

@ -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) void Console::ProcessEvent(EventType type)
{ {
if(_debugger) { if(_debugger) {

View file

@ -127,5 +127,6 @@ public:
void ProcessWorkRamRead(uint32_t addr, uint8_t value); void ProcessWorkRamRead(uint32_t addr, uint8_t value);
void ProcessWorkRamWrite(uint32_t addr, uint8_t value); void ProcessWorkRamWrite(uint32_t addr, uint8_t value);
void ProcessPpuCycle(); void ProcessPpuCycle();
void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi);
void ProcessEvent(EventType type); void ProcessEvent(EventType type);
}; };

View file

@ -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 //Use the state of the IRQ/NMI flags on the previous cycle to determine if an IRQ is processed or not
if(_state.PrevNmiFlag) { if(_state.PrevNmiFlag) {
uint32_t originalPc = GetProgramAddress(_state.PC);
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector); ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyNmiVector : Cpu::NmiVector);
_console->ProcessEvent(EventType::Nmi); _console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), true);
_state.NmiFlag = false; _state.NmiFlag = false;
} else if(_state.PrevIrqSource && !CheckFlag(ProcFlags::IrqDisable)) { } else if(_state.PrevIrqSource && !CheckFlag(ProcFlags::IrqDisable)) {
uint32_t originalPc = GetProgramAddress(_state.PC);
ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector); ProcessInterrupt(_state.EmulationMode ? Cpu::LegacyIrqVector : Cpu::IrqVector);
_console->ProcessEvent(EventType::Irq); _console->ProcessInterrupt(originalPc, GetProgramAddress(_state.PC), false);
} }
} }

View file

@ -205,3 +205,11 @@ struct StackFrameInfo
uint32_t Return; uint32_t Return;
StackFrameFlags Flags; StackFrameFlags Flags;
}; };
enum class StepType
{
CpuStep,
CpuStepOut,
CpuStepOver,
PpuStep,
};

View file

@ -109,6 +109,8 @@ void Debugger::ProcessCpuRead(uint32_t addr, uint8_t value, MemoryOperationType
_callstackManager->Pop(pc); _callstackManager->Pop(pc);
} }
ProcessStepConditions(_prevOpCode, pc);
_prevOpCode = value; _prevOpCode = value;
_prevProgramCounter = pc; _prevProgramCounter = pc;
@ -187,6 +189,35 @@ void Debugger::ProcessPpuCycle()
uint16_t scanline = _ppu->GetState().Scanline; uint16_t scanline = _ppu->GetState().Scanline;
uint16_t cycle = _ppu->GetState().Cycle; uint16_t cycle = _ppu->GetState().Cycle;
_ppuTools->UpdateViewers(scanline, 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<int, std::milli>(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) void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo)
@ -196,31 +227,19 @@ void Debugger::ProcessBreakConditions(MemoryOperationInfo &operation, AddressInf
} }
if(_cpuStepCount == 0 || _breakRequestCount) { if(_cpuStepCount == 0 || _breakRequestCount) {
_console->GetSoundMixer()->StopAudio(); SleepUntilResume();
_disassembler->Disassemble();
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak);
_executionStopped = true;
while(_cpuStepCount == 0 || _breakRequestCount) {
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
}
_executionStopped = false;
} }
} }
void Debugger::ProcessInterrupt(bool forNmi) void Debugger::ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi)
{ {
CpuState state = _cpu->GetState(); _callstackManager->Push(_prevProgramCounter, currentPc, originalPc, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq);
_callstackManager->Push(_prevProgramCounter, (state.K << 16) | state.PC, _prevProgramCounter, forNmi ? StackFrameFlags::Nmi : StackFrameFlags::Irq);
_eventManager->AddEvent(forNmi ? DebugEventType::Nmi : DebugEventType::Irq); _eventManager->AddEvent(forNmi ? DebugEventType::Nmi : DebugEventType::Irq);
} }
void Debugger::ProcessEvent(EventType type) void Debugger::ProcessEvent(EventType type)
{ {
switch(type) { switch(type) {
case EventType::Nmi: ProcessInterrupt(true); break;
case EventType::Irq: ProcessInterrupt(false); break;
case EventType::StartFrame: case EventType::StartFrame:
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::EventViewerRefresh); _console->GetNotificationManager()->SendNotification(ConsoleNotificationType::EventViewerRefresh);
_eventManager->ClearFrameEvents(); _eventManager->ClearFrameEvents();
@ -244,11 +263,45 @@ int32_t Debugger::EvaluateExpression(string expression, EvalResultType &resultTy
void Debugger::Run() void Debugger::Run()
{ {
_cpuStepCount = -1; _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() bool Debugger::IsExecutionStopped()

View file

@ -2,6 +2,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "CpuTypes.h" #include "CpuTypes.h"
#include "PpuTypes.h" #include "PpuTypes.h"
#include "DebugTypes.h"
class Console; class Console;
class Cpu; class Cpu;
@ -20,15 +21,8 @@ class EventManager;
class CallstackManager; class CallstackManager;
enum class EventType; enum class EventType;
enum class SnesMemoryType;
enum class MemoryOperationType;
enum class BreakpointCategory;
enum class EvalResultType : int32_t; enum class EvalResultType : int32_t;
struct DebugState;
struct MemoryOperationInfo;
struct AddressInfo;
class Debugger class Debugger
{ {
private: private:
@ -53,12 +47,15 @@ private:
atomic<uint32_t> _breakRequestCount; atomic<uint32_t> _breakRequestCount;
atomic<int32_t> _cpuStepCount; atomic<int32_t> _cpuStepCount;
atomic<int32_t> _ppuStepCount;
atomic<int32_t> _breakAddress;
uint8_t _prevOpCode = 0; uint8_t _prevOpCode = 0;
uint32_t _prevProgramCounter = 0; uint32_t _prevProgramCounter = 0;
void SleepUntilResume();
void ProcessStepConditions(uint8_t opCode, uint32_t currentPc);
void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo); void ProcessBreakConditions(MemoryOperationInfo &operation, AddressInfo &addressInfo);
void ProcessInterrupt(bool forNmi);
public: public:
Debugger(shared_ptr<Console> console); Debugger(shared_ptr<Console> console);
@ -75,12 +72,13 @@ public:
void ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType); void ProcessPpuWrite(uint16_t addr, uint8_t value, SnesMemoryType memoryType);
void ProcessPpuCycle(); void ProcessPpuCycle();
void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi);
void ProcessEvent(EventType type); void ProcessEvent(EventType type);
int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache); int32_t EvaluateExpression(string expression, EvalResultType &resultType, bool useCache);
void Run(); void Run();
void Step(int32_t stepCount); void Step(int32_t stepCount, StepType type = StepType::CpuStep);
bool IsExecutionStopped(); bool IsExecutionStopped();
void BreakRequest(bool release); void BreakRequest(bool release);

View file

@ -38,7 +38,7 @@ extern "C"
DllExport bool __stdcall IsExecutionStopped() { return GetDebugger()->IsExecutionStopped(); } DllExport bool __stdcall IsExecutionStopped() { return GetDebugger()->IsExecutionStopped(); }
DllExport void __stdcall ResumeExecution() { if(IsDebuggerRunning()) GetDebugger()->Run(); } 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 void __stdcall GetDisassemblyLineData(uint32_t lineIndex, CodeLineData &data) { GetDebugger()->GetDisassembler()->GetLineData(lineIndex, data); }
DllExport uint32_t __stdcall GetDisassemblyLineCount() { return GetDebugger()->GetDisassembler()->GetLineCount(); } DllExport uint32_t __stdcall GetDisassemblyLineCount() { return GetDebugger()->GetDisassembler()->GetLineCount(); }

View file

@ -304,6 +304,12 @@ namespace Mesen.GUI.Debugger.Controls
} else if(keyData == ConfigManager.Config.Debug.Shortcuts.Find) { } else if(keyData == ConfigManager.Config.Debug.Shortcuts.Find) {
this.OpenSearchBox(true); this.OpenSearchBox(true);
return 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)) { if(keyData == (Keys.Control | Keys.F)) {

View file

@ -49,7 +49,7 @@
this.mnuDisableEnableBreakpoint = new System.Windows.Forms.ToolStripMenuItem(); this.mnuDisableEnableBreakpoint = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRunCpuCycle = new System.Windows.Forms.ToolStripMenuItem(); 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.mnuRunPpuCycle = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRunScanline = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunScanline = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem(); this.mnuRunOneFrame = new System.Windows.Forms.ToolStripMenuItem();
@ -113,7 +113,7 @@
this.mnuDisableEnableBreakpoint, this.mnuDisableEnableBreakpoint,
this.toolStripMenuItem2, this.toolStripMenuItem2,
this.mnuRunCpuCycle, this.mnuRunCpuCycle,
this.mnuRun1000Cycles, this.mnuRun1000Instructions,
this.mnuRunPpuCycle, this.mnuRunPpuCycle,
this.mnuRunScanline, this.mnuRunScanline,
this.mnuRunOneFrame, this.mnuRunOneFrame,
@ -128,9 +128,8 @@
// //
this.mnuContinue.Image = global::Mesen.GUI.Properties.Resources.MediaPlay; this.mnuContinue.Image = global::Mesen.GUI.Properties.Resources.MediaPlay;
this.mnuContinue.Name = "mnuContinue"; 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.Text = "Continue";
this.mnuContinue.Click += new System.EventHandler(this.mnuContinue_Click);
// //
// mnuBreak // mnuBreak
// //
@ -138,136 +137,134 @@
this.mnuBreak.Image = global::Mesen.GUI.Properties.Resources.MediaPause; this.mnuBreak.Image = global::Mesen.GUI.Properties.Resources.MediaPause;
this.mnuBreak.Name = "mnuBreak"; this.mnuBreak.Name = "mnuBreak";
this.mnuBreak.ShortcutKeyDisplayString = ""; 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"; this.mnuBreak.Text = "Break";
// //
// toolStripMenuItem3 // toolStripMenuItem3
// //
this.toolStripMenuItem3.Name = "toolStripMenuItem3"; this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(209, 6); this.toolStripMenuItem3.Size = new System.Drawing.Size(210, 6);
// //
// mnuStepInto // mnuStepInto
// //
this.mnuStepInto.Image = global::Mesen.GUI.Properties.Resources.StepInto; this.mnuStepInto.Image = global::Mesen.GUI.Properties.Resources.StepInto;
this.mnuStepInto.Name = "mnuStepInto"; 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.Text = "Step Into";
this.mnuStepInto.Click += new System.EventHandler(this.mnuStepInto_Click);
// //
// mnuStepOver // mnuStepOver
// //
this.mnuStepOver.Image = global::Mesen.GUI.Properties.Resources.StepOver; this.mnuStepOver.Image = global::Mesen.GUI.Properties.Resources.StepOver;
this.mnuStepOver.Name = "mnuStepOver"; 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"; this.mnuStepOver.Text = "Step Over";
// //
// mnuStepOut // mnuStepOut
// //
this.mnuStepOut.Image = global::Mesen.GUI.Properties.Resources.StepOut; this.mnuStepOut.Image = global::Mesen.GUI.Properties.Resources.StepOut;
this.mnuStepOut.Name = "mnuStepOut"; 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"; this.mnuStepOut.Text = "Step Out";
// //
// mnuStepBack // mnuStepBack
// //
this.mnuStepBack.Image = global::Mesen.GUI.Properties.Resources.StepBack; this.mnuStepBack.Image = global::Mesen.GUI.Properties.Resources.StepBack;
this.mnuStepBack.Name = "mnuStepBack"; 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"; this.mnuStepBack.Text = "Step Back";
// //
// toolStripMenuItem1 // toolStripMenuItem1
// //
this.toolStripMenuItem1.Name = "toolStripMenuItem1"; this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(209, 6); this.toolStripMenuItem1.Size = new System.Drawing.Size(210, 6);
// //
// mnuReset // mnuReset
// //
this.mnuReset.Image = global::Mesen.GUI.Properties.Resources.Refresh; this.mnuReset.Image = global::Mesen.GUI.Properties.Resources.Refresh;
this.mnuReset.Name = "mnuReset"; 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"; this.mnuReset.Text = "Reset";
// //
// mnuPowerCycle // mnuPowerCycle
// //
this.mnuPowerCycle.Image = global::Mesen.GUI.Properties.Resources.PowerCycle; this.mnuPowerCycle.Image = global::Mesen.GUI.Properties.Resources.PowerCycle;
this.mnuPowerCycle.Name = "mnuPowerCycle"; 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"; this.mnuPowerCycle.Text = "Power Cycle";
// //
// toolStripMenuItem24 // toolStripMenuItem24
// //
this.toolStripMenuItem24.Name = "toolStripMenuItem24"; this.toolStripMenuItem24.Name = "toolStripMenuItem24";
this.toolStripMenuItem24.Size = new System.Drawing.Size(209, 6); this.toolStripMenuItem24.Size = new System.Drawing.Size(210, 6);
// //
// mnuToggleBreakpoint // mnuToggleBreakpoint
// //
this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint; this.mnuToggleBreakpoint.Image = global::Mesen.GUI.Properties.Resources.Breakpoint;
this.mnuToggleBreakpoint.Name = "mnuToggleBreakpoint"; 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"; this.mnuToggleBreakpoint.Text = "Toggle Breakpoint";
// //
// mnuDisableEnableBreakpoint // mnuDisableEnableBreakpoint
// //
this.mnuDisableEnableBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointDisabled; this.mnuDisableEnableBreakpoint.Image = global::Mesen.GUI.Properties.Resources.BreakpointDisabled;
this.mnuDisableEnableBreakpoint.Name = "mnuDisableEnableBreakpoint"; 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"; this.mnuDisableEnableBreakpoint.Text = "Disable/Enable Breakpoint";
// //
// toolStripMenuItem2 // toolStripMenuItem2
// //
this.toolStripMenuItem2.Name = "toolStripMenuItem2"; this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(209, 6); this.toolStripMenuItem2.Size = new System.Drawing.Size(210, 6);
// //
// mnuRunCpuCycle // mnuRunCpuCycle
// //
this.mnuRunCpuCycle.Image = global::Mesen.GUI.Properties.Resources.JumpTarget; this.mnuRunCpuCycle.Image = global::Mesen.GUI.Properties.Resources.JumpTarget;
this.mnuRunCpuCycle.Name = "mnuRunCpuCycle"; 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"; this.mnuRunCpuCycle.Text = "Run one CPU cycle";
// //
// mnuRun1000Cycles // mnuRun1000Instructions
// //
this.mnuRun1000Cycles.Name = "mnuRun1000Cycles"; this.mnuRun1000Instructions.Name = "mnuRun1000Instructions";
this.mnuRun1000Cycles.Size = new System.Drawing.Size(212, 22); this.mnuRun1000Instructions.Size = new System.Drawing.Size(213, 22);
this.mnuRun1000Cycles.Text = "Run 1000 CPU cycles"; this.mnuRun1000Instructions.Text = "Run 1000 CPU instructions";
this.mnuRun1000Cycles.Click += new System.EventHandler(this.mnuRun1000Cycles_Click);
// //
// mnuRunPpuCycle // mnuRunPpuCycle
// //
this.mnuRunPpuCycle.Image = global::Mesen.GUI.Properties.Resources.RunPpuCycle; this.mnuRunPpuCycle.Image = global::Mesen.GUI.Properties.Resources.RunPpuCycle;
this.mnuRunPpuCycle.Name = "mnuRunPpuCycle"; 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"; this.mnuRunPpuCycle.Text = "Run one PPU cycle";
// //
// mnuRunScanline // mnuRunScanline
// //
this.mnuRunScanline.Image = global::Mesen.GUI.Properties.Resources.RunPpuScanline; this.mnuRunScanline.Image = global::Mesen.GUI.Properties.Resources.RunPpuScanline;
this.mnuRunScanline.Name = "mnuRunScanline"; 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"; this.mnuRunScanline.Text = "Run one scanline";
// //
// mnuRunOneFrame // mnuRunOneFrame
// //
this.mnuRunOneFrame.Image = global::Mesen.GUI.Properties.Resources.RunPpuFrame; this.mnuRunOneFrame.Image = global::Mesen.GUI.Properties.Resources.RunPpuFrame;
this.mnuRunOneFrame.Name = "mnuRunOneFrame"; 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"; this.mnuRunOneFrame.Text = "Run one frame";
// //
// toolStripMenuItem8 // toolStripMenuItem8
// //
this.toolStripMenuItem8.Name = "toolStripMenuItem8"; this.toolStripMenuItem8.Name = "toolStripMenuItem8";
this.toolStripMenuItem8.Size = new System.Drawing.Size(209, 6); this.toolStripMenuItem8.Size = new System.Drawing.Size(210, 6);
// //
// mnuBreakIn // mnuBreakIn
// //
this.mnuBreakIn.Name = "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..."; this.mnuBreakIn.Text = "Break in...";
// //
// mnuBreakOn // mnuBreakOn
// //
this.mnuBreakOn.Name = "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..."; this.mnuBreakOn.Text = "Break on...";
// //
// ctrlSplitContainer // ctrlSplitContainer
@ -440,7 +437,7 @@
private System.Windows.Forms.GroupBox grpBreakpoints; private System.Windows.Forms.GroupBox grpBreakpoints;
private Controls.ctrlBreakpoints ctrlBreakpoints; private Controls.ctrlBreakpoints ctrlBreakpoints;
private Controls.ctrlConsoleStatus ctrlStatus; private Controls.ctrlConsoleStatus ctrlStatus;
private System.Windows.Forms.ToolStripMenuItem mnuRun1000Cycles; private System.Windows.Forms.ToolStripMenuItem mnuRun1000Instructions;
private GUI.Controls.ctrlMesenToolStrip tsToolbar; private GUI.Controls.ctrlMesenToolStrip tsToolbar;
private System.Windows.Forms.GroupBox grpCallstack; private System.Windows.Forms.GroupBox grpCallstack;
private Controls.ctrlCallstack ctrlCallstack; private Controls.ctrlCallstack ctrlCallstack;

View file

@ -66,6 +66,15 @@ namespace Mesen.GUI.Debugger
mnuRunPpuCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuCycle)); mnuRunPpuCycle.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuCycle));
mnuRunScanline.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuScanline)); mnuRunScanline.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuScanline));
mnuRunOneFrame.InitShortcut(this, nameof(DebuggerShortcutsConfig.RunPpuFrame)); 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() 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) private void ctrlCallstack_FunctionSelected(uint address)
{ {
ctrlDisassemblyView.ScrollToAddress(address); ctrlDisassemblyView.ScrollToAddress(address);

View file

@ -20,7 +20,7 @@ namespace Mesen.GUI
[DllImport(DllPath)] public static extern void ReleaseDebugger(); [DllImport(DllPath)] public static extern void ReleaseDebugger();
[DllImport(DllPath)] public static extern void ResumeExecution(); [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 StartTraceLogger([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filename);
[DllImport(DllPath)] public static extern void StopTraceLogger(); [DllImport(DllPath)] public static extern void StopTraceLogger();
@ -375,4 +375,12 @@ namespace Mesen.GUI
Nmi = 1, Nmi = 1,
Irq = 2 Irq = 2
} }
public enum StepType
{
CpuStep,
CpuStepOut,
CpuStepOver,
PpuStep,
}
} }