diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 1037974d..21f30a7f 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -20,6 +20,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index 4d9c4d59..47912be5 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -818,6 +818,7 @@
+
diff --git a/Core/Debugger/Debugger.cpp b/Core/Debugger/Debugger.cpp
index 64c6055a..c5478a5a 100644
--- a/Core/Debugger/Debugger.cpp
+++ b/Core/Debugger/Debugger.cpp
@@ -80,7 +80,6 @@ Debugger::Debugger(Emulator* emu, IConsole* console)
}
_debuggers[(int)type].Evaluator.reset(new ExpressionEvaluator(this, _debuggers[(int)type].Debugger.get(), type));
- _debuggers[(int)type].IgnoreBreakpoints = false;
}
for(CpuType type : _cpuTypes) {
@@ -146,7 +145,8 @@ DebuggerType* Debugger::GetDebugger()
template
void Debugger::ProcessInstruction()
{
- _debuggers[(int)type].IgnoreBreakpoints = false;
+ _debuggers[(int)type].Debugger->IgnoreBreakpoints = false;
+ _debuggers[(int)type].Debugger->AllowChangeProgramCounter = true;
switch(type) {
case CpuType::Snes: GetDebugger()->ProcessInstruction(); break;
@@ -158,6 +158,8 @@ void Debugger::ProcessInstruction()
case CpuType::Gameboy: GetDebugger()->ProcessInstruction(); break;
case CpuType::Nes: GetDebugger()->ProcessInstruction(); break;
}
+
+ _debuggers[(int)type].Debugger->AllowChangeProgramCounter = false;
}
template
@@ -244,7 +246,7 @@ void Debugger::SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOpe
_emu->GetSoundMixer()->StopAudio();
if(_settings->CheckDebuggerFlag(DebuggerFlags::SingleBreakpointPerInstruction)) {
- _debuggers[(int)sourceCpu].IgnoreBreakpoints = true;
+ _debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints = true;
}
//Only trigger code break event if the pause was caused by user action
@@ -255,6 +257,7 @@ void Debugger::SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOpe
if(operation) {
evt.Operation = *operation;
}
+
_waitForBreakResume = true;
_emu->GetNotificationManager()->SendNotification(ConsoleNotificationType::CodeBreak, &evt);
notificationSent = true;
@@ -274,10 +277,10 @@ void Debugger::SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOpe
void Debugger::ProcessBreakConditions(CpuType sourceCpu, StepRequest& step, BreakpointManager* bpManager, MemoryOperationInfo& operation, AddressInfo& addressInfo)
{
int breakpointId = bpManager->CheckBreakpoint(operation, addressInfo, true);
- if(_breakRequestCount || _waitForBreakResume || (step.BreakNeeded && !_debuggers[(int)sourceCpu].IgnoreBreakpoints)) {
+ if(_breakRequestCount || _waitForBreakResume || (step.BreakNeeded && !_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints)) {
SleepUntilResume(sourceCpu, step.Source);
} else {
- if(breakpointId >= 0 && !_debuggers[(int)sourceCpu].IgnoreBreakpoints) {
+ if(breakpointId >= 0 && !_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints) {
SleepUntilResume(sourceCpu, BreakSource::Breakpoint, &operation, breakpointId);
}
}
@@ -285,7 +288,7 @@ void Debugger::ProcessBreakConditions(CpuType sourceCpu, StepRequest& step, Brea
void Debugger::ProcessPredictiveBreakpoint(CpuType sourceCpu, BreakpointManager* bpManager, MemoryOperationInfo& operation, AddressInfo& addressInfo)
{
- if(_debuggers[(int)sourceCpu].IgnoreBreakpoints) {
+ if(_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints) {
return;
}
@@ -548,6 +551,26 @@ void Debugger::GetConsoleState(BaseState& state, ConsoleType consoleType)
_console->GetConsoleState(state, consoleType);
}
+DebuggerFeatures Debugger::GetDebuggerFeatures(CpuType cpuType)
+{
+ if(_debuggers[(int)cpuType].Debugger) {
+ return _debuggers[(int)cpuType].Debugger->GetSupportedFeatures();
+ }
+ return {};
+}
+
+void Debugger::SetProgramCounter(CpuType cpuType, uint32_t addr)
+{
+ if(_debuggers[(int)cpuType].Debugger->AllowChangeProgramCounter) {
+ _debuggers[(int)cpuType].Debugger->SetProgramCounter(addr);
+ }
+}
+
+uint32_t Debugger::GetProgramCounter(CpuType cpuType, bool getInstPc)
+{
+ return _debuggers[(int)cpuType].Debugger->GetProgramCounter(getInstPc);
+}
+
AddressInfo Debugger::GetAbsoluteAddress(AddressInfo relAddress)
{
return _console->GetAbsoluteAddress(relAddress);
diff --git a/Core/Debugger/Debugger.h b/Core/Debugger/Debugger.h
index d0cb2aa2..96cf10a8 100644
--- a/Core/Debugger/Debugger.h
+++ b/Core/Debugger/Debugger.h
@@ -3,6 +3,7 @@
#include "Utilities/SimpleLock.h"
#include "Debugger/DebugUtilities.h"
#include "Debugger/DebugTypes.h"
+#include "Debugger/DebuggerFeatures.h"
#include "Shared/SettingTypes.h"
class IConsole;
@@ -44,7 +45,6 @@ struct CpuInfo
{
unique_ptr Debugger;
unique_ptr Evaluator;
- bool IgnoreBreakpoints;
};
class Debugger
@@ -129,6 +129,10 @@ public:
void GetConsoleState(BaseState& state, ConsoleType consoleType);
+ DebuggerFeatures GetDebuggerFeatures(CpuType cpuType);
+ uint32_t GetProgramCounter(CpuType cpuType, bool forInstStart);
+ void SetProgramCounter(CpuType cpuType, uint32_t addr);
+
AddressInfo GetAbsoluteAddress(AddressInfo relAddress);
AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType);
diff --git a/Core/Debugger/DebuggerFeatures.h b/Core/Debugger/DebuggerFeatures.h
new file mode 100644
index 00000000..6509e973
--- /dev/null
+++ b/Core/Debugger/DebuggerFeatures.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "stdafx.h"
+
+struct DebuggerFeatures
+{
+ bool RunToIrq;
+ bool RunToNmi;
+ bool StepOver;
+ bool StepOut;
+ bool StepBack;
+ bool ChangeProgramCounter;
+ bool CallStack;
+};
diff --git a/Core/Debugger/IDebugger.h b/Core/Debugger/IDebugger.h
index e2155b6e..d461df6f 100644
--- a/Core/Debugger/IDebugger.h
+++ b/Core/Debugger/IDebugger.h
@@ -1,5 +1,6 @@
#pragma once
#include "stdafx.h"
+#include "DebuggerFeatures.h"
enum class StepType;
class BreakpointManager;
@@ -16,6 +17,9 @@ enum class MemoryOperationType;
class IDebugger
{
public:
+ bool IgnoreBreakpoints = false;
+ bool AllowChangeProgramCounter = false;
+
virtual ~IDebugger() = default;
virtual void Step(int32_t stepCount, StepType type) = 0;
@@ -27,6 +31,11 @@ public:
virtual void ProcessInterrupt(uint32_t originalPc, uint32_t currentPc, bool forNmi) {}
+ virtual DebuggerFeatures GetSupportedFeatures() { return {}; }
+
+ virtual uint32_t GetProgramCounter(bool getInstPc) = 0;
+ virtual void SetProgramCounter(uint32_t addr) = 0;
+
virtual BreakpointManager* GetBreakpointManager() = 0;
virtual CallstackManager* GetCallstackManager() = 0;
virtual IAssembler* GetAssembler() = 0;
@@ -38,4 +47,4 @@ public:
virtual BaseState& GetState() = 0;
virtual void GetPpuState(BaseState& state) {};
virtual void SetPpuState(BaseState& state) {};
-};
\ No newline at end of file
+};
diff --git a/Core/Gameboy/Debugger/GbDebugger.cpp b/Core/Gameboy/Debugger/GbDebugger.cpp
index 3cc12fb0..707edf70 100644
--- a/Core/Gameboy/Debugger/GbDebugger.cpp
+++ b/Core/Gameboy/Debugger/GbDebugger.cpp
@@ -83,18 +83,11 @@ void GbDebugger::ProcessInstruction()
uint8_t value = _gameboy->GetMemoryManager()->DebugRead(pc);
MemoryOperationInfo operation(pc, value, MemoryOperationType::ExecOpCode, MemoryType::GameboyMemory);
- if(_traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::GbDebuggerEnabled)) {
- if(addressInfo.Address >= 0) {
- if(addressInfo.Type == MemoryType::GbPrgRom) {
- _codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code);
- }
- _disassembler->BuildCache(addressInfo, 0, CpuType::Gameboy);
- }
-
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, pc, 0, CpuType::Gameboy);
- _traceLogger->Log(state, disInfo, operation);
+ if(addressInfo.Address >= 0) {
+ if(addressInfo.Type == MemoryType::GbPrgRom) {
+ _codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code);
}
+ _disassembler->BuildCache(addressInfo, 0, CpuType::Gameboy);
}
if(GameboyDisUtils::IsJumpToSub(_prevOpCode) && pc != _prevProgramCounter + GameboyDisUtils::GetOpSize(_prevOpCode)) {
@@ -131,7 +124,7 @@ void GbDebugger::ProcessInstruction()
break;
}
}
-
+
_prevOpCode = value;
_prevProgramCounter = pc;
@@ -158,6 +151,10 @@ void GbDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType t
MemoryOperationInfo operation(addr, value, type, MemoryType::GameboyMemory);
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Gameboy);
+ _traceLogger->Log(_cpu->GetState(), disInfo, operation);
+ }
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _emu->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Address >= 0 && addressInfo.Type == MemoryType::GbPrgRom) {
@@ -297,6 +294,30 @@ void GbDebugger::ProcessPpuCycle()
}
}
+DebuggerFeatures GbDebugger::GetSupportedFeatures()
+{
+ DebuggerFeatures features = {};
+ features.RunToIrq = true;
+ features.RunToNmi = false;
+ features.StepOver = true;
+ features.StepOut = true;
+ features.CallStack = true;
+ features.ChangeProgramCounter = AllowChangeProgramCounter;
+ return features;
+}
+
+void GbDebugger::SetProgramCounter(uint32_t addr)
+{
+ _cpu->GetState().PC = (uint16_t)addr;
+ _prevOpCode = _gameboy->GetMemoryManager()->DebugRead((uint16_t)addr);
+ _prevProgramCounter = (uint16_t)addr;
+}
+
+uint32_t GbDebugger::GetProgramCounter(bool getInstPc)
+{
+ return getInstPc ? _prevProgramCounter : _cpu->GetState().PC;
+}
+
BaseEventManager* GbDebugger::GetEventManager()
{
return _eventManager.get();
diff --git a/Core/Gameboy/Debugger/GbDebugger.h b/Core/Gameboy/Debugger/GbDebugger.h
index dca1f841..a8fd443a 100644
--- a/Core/Gameboy/Debugger/GbDebugger.h
+++ b/Core/Gameboy/Debugger/GbDebugger.h
@@ -67,6 +67,11 @@ public:
void SaveRomToDisk(string filename, bool saveAsIps, CdlStripOption stripOption);
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
+ DebuggerFeatures GetSupportedFeatures() override;
+
BaseEventManager* GetEventManager() override;
IAssembler* GetAssembler() override;
CallstackManager* GetCallstackManager() override;
diff --git a/Core/NES/Debugger/NesDebugger.cpp b/Core/NES/Debugger/NesDebugger.cpp
index 378862d6..45e15a61 100644
--- a/Core/NES/Debugger/NesDebugger.cpp
+++ b/Core/NES/Debugger/NesDebugger.cpp
@@ -95,11 +95,6 @@ void NesDebugger::ProcessInstruction()
}
}
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, state.PS, CpuType::Nes);
- _traceLogger->Log(state, disInfo, operation);
- }
-
uint32_t pc = state.PC;
if(_prevOpCode == 0x20) {
//JSR
@@ -156,6 +151,12 @@ void NesDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ NesCpuState& state = _cpu->GetState();
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, state.PS, CpuType::Nes);
+ _traceLogger->Log(state, disInfo, operation);
+ }
+
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _cpu->GetCycleCount());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Type == MemoryType::NesPrgRom && addressInfo.Address >= 0) {
@@ -312,6 +313,30 @@ bool NesDebugger::IsRegister(MemoryOperationInfo& op)
return false;
}
+DebuggerFeatures NesDebugger::GetSupportedFeatures()
+{
+ DebuggerFeatures features = {};
+ features.RunToIrq = true;
+ features.RunToNmi = true;
+ features.StepOver = true;
+ features.StepOut = true;
+ features.CallStack = true;
+ features.ChangeProgramCounter = AllowChangeProgramCounter;
+ return features;
+}
+
+void NesDebugger::SetProgramCounter(uint32_t addr)
+{
+ _cpu->GetState().PC = (uint16_t)addr;
+ _prevOpCode = _memoryManager->DebugRead(addr);
+ _prevProgramCounter = (uint16_t)addr;
+}
+
+uint32_t NesDebugger::GetProgramCounter(bool getInstPc)
+{
+ return getInstPc ? _prevProgramCounter : _cpu->GetState().PC;
+}
+
CallstackManager* NesDebugger::GetCallstackManager()
{
return _callstackManager.get();
diff --git a/Core/NES/Debugger/NesDebugger.h b/Core/NES/Debugger/NesDebugger.h
index 9ec85f0b..f781ad28 100644
--- a/Core/NES/Debugger/NesDebugger.h
+++ b/Core/NES/Debugger/NesDebugger.h
@@ -58,6 +58,7 @@ class NesDebugger final : public IDebugger
bool IsRegister(MemoryOperationInfo& op);
+
public:
NesDebugger(Debugger* debugger);
@@ -74,6 +75,10 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+ DebuggerFeatures GetSupportedFeatures() override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
BreakpointManager* GetBreakpointManager() override;
ITraceLogger* GetTraceLogger() override;
PpuTools* GetPpuTools() override;
diff --git a/Core/SNES/Coprocessors/DSP/NecDsp.cpp b/Core/SNES/Coprocessors/DSP/NecDsp.cpp
index 8148b122..26febd75 100644
--- a/Core/SNES/Coprocessors/DSP/NecDsp.cpp
+++ b/Core/SNES/Coprocessors/DSP/NecDsp.cpp
@@ -148,6 +148,7 @@ void NecDsp::BuildProgramCache()
void NecDsp::ReadOpCode()
{
_opCode = _prgCache[_state.PC & _progMask];
+ _emu->ProcessMemoryRead(_state.PC, _opCode, MemoryOperationType::ExecOpCode);
}
void NecDsp::Run()
@@ -249,7 +250,6 @@ void NecDsp::Write(uint32_t addr, uint8_t value)
uint32_t NecDsp::GetOpCode(uint32_t addr)
{
- //Avoid side effects for now
return _prgCache[addr & _progMask];
}
diff --git a/Core/SNES/Debugger/Cx4Debugger.cpp b/Core/SNES/Debugger/Cx4Debugger.cpp
index b61952f9..420552fa 100644
--- a/Core/SNES/Debugger/Cx4Debugger.cpp
+++ b/Core/SNES/Debugger/Cx4Debugger.cpp
@@ -53,13 +53,8 @@ void Cx4Debugger::ProcessInstruction()
_codeDataLogger->SetFlags(addressInfo.Address + 1, CdlFlags::Code | CdlFlags::Cx4);
}
- if(_traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::Cx4DebuggerEnabled)) {
+ if(_settings->CheckDebuggerFlag(DebuggerFlags::Cx4DebuggerEnabled)) {
_disassembler->BuildCache(addressInfo, 0, CpuType::Cx4);
-
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Cx4);
- _traceLogger->Log(state, disInfo, operation);
- }
}
_prevProgramCounter = addr;
@@ -77,6 +72,11 @@ void Cx4Debugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
MemoryOperationInfo operation(addr, value, type, MemoryType::Cx4Memory);
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Cx4);
+ _traceLogger->Log(state, disInfo, operation);
+ }
+
AddressInfo opCodeHighAddr = _cx4->GetMemoryMappings()->GetAbsoluteAddress(addr + 1);
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
_memoryAccessCounter->ProcessMemoryExec(opCodeHighAddr, _memoryManager->GetMasterClock());
@@ -129,6 +129,17 @@ void Cx4Debugger::Step(int32_t stepCount, StepType type)
_step.reset(new StepRequest(step));
}
+void Cx4Debugger::SetProgramCounter(uint32_t addr)
+{
+ //Not implemented
+}
+
+uint32_t Cx4Debugger::GetProgramCounter(bool getInstPc)
+{
+ Cx4State& state = _cx4->GetState();
+ return getInstPc ? _prevProgramCounter : ((state.Cache.Address[state.Cache.Page] + (state.PC * 2)) & 0xFFFFFF);
+}
+
BreakpointManager* Cx4Debugger::GetBreakpointManager()
{
return _breakpointManager.get();
diff --git a/Core/SNES/Debugger/Cx4Debugger.h b/Core/SNES/Debugger/Cx4Debugger.h
index f69eafec..5cff5ba8 100644
--- a/Core/SNES/Debugger/Cx4Debugger.h
+++ b/Core/SNES/Debugger/Cx4Debugger.h
@@ -44,6 +44,9 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
BreakpointManager* GetBreakpointManager() override;
CallstackManager* GetCallstackManager() override;
IAssembler* GetAssembler() override;
diff --git a/Core/SNES/Debugger/GsuDebugger.cpp b/Core/SNES/Debugger/GsuDebugger.cpp
index 42cad762..f1cd7f54 100644
--- a/Core/SNES/Debugger/GsuDebugger.cpp
+++ b/Core/SNES/Debugger/GsuDebugger.cpp
@@ -51,13 +51,8 @@ void GsuDebugger::ProcessInstruction()
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Code | CdlFlags::Gsu);
}
- if(_traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::GsuDebuggerEnabled)) {
+ if(_settings->CheckDebuggerFlag(DebuggerFlags::GsuDebuggerEnabled)) {
_disassembler->BuildCache(addressInfo, state.SFR.GetFlagsHigh() & 0x13, CpuType::Gsu);
-
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Gsu);
- _traceLogger->Log(state, disInfo, operation);
- }
}
_prevOpCode = state.ProgramReadBuffer;
@@ -72,8 +67,13 @@ void GsuDebugger::ProcessInstruction()
void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo = _gsu->GetMemoryMappings()->GetAbsoluteAddress(addr);
+ MemoryOperationInfo operation(addr, value, type, MemoryType::GsuMemory);
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Gsu);
+ _traceLogger->Log(_gsu->GetState(), disInfo, operation);
+ }
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Type == MemoryType::SnesPrgRom) {
@@ -81,7 +81,6 @@ void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else {
- MemoryOperationInfo operation(addr, value, type, MemoryType::GsuMemory);
if(addressInfo.Type == MemoryType::SnesPrgRom) {
_codeDataLogger->SetFlags(addressInfo.Address, CdlFlags::Data | CdlFlags::Gsu);
@@ -130,6 +129,17 @@ void GsuDebugger::Step(int32_t stepCount, StepType type)
_step.reset(new StepRequest(step));
}
+void GsuDebugger::SetProgramCounter(uint32_t addr)
+{
+ //Not implemented
+}
+
+uint32_t GsuDebugger::GetProgramCounter(bool getInstPc)
+{
+ GsuState& state = _gsu->GetState();
+ return getInstPc ? _prevProgramCounter : ((state.ProgramBank << 16) | state.R[15]);
+}
+
BreakpointManager* GsuDebugger::GetBreakpointManager()
{
return _breakpointManager.get();
diff --git a/Core/SNES/Debugger/GsuDebugger.h b/Core/SNES/Debugger/GsuDebugger.h
index 6571ed51..b46af6c1 100644
--- a/Core/SNES/Debugger/GsuDebugger.h
+++ b/Core/SNES/Debugger/GsuDebugger.h
@@ -44,6 +44,9 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
BreakpointManager* GetBreakpointManager() override;
CallstackManager* GetCallstackManager() override;
IAssembler* GetAssembler() override;
diff --git a/Core/SNES/Debugger/NecDspDebugger.cpp b/Core/SNES/Debugger/NecDspDebugger.cpp
index db24559f..bb632cf8 100644
--- a/Core/SNES/Debugger/NecDspDebugger.cpp
+++ b/Core/SNES/Debugger/NecDspDebugger.cpp
@@ -42,14 +42,7 @@ void NecDspDebugger::ProcessInstruction()
AddressInfo addressInfo = { (int32_t)addr, MemoryType::DspProgramRom };
MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::NecDspMemory);
- if(_traceLogger->IsEnabled() || _settings->CheckDebuggerFlag(DebuggerFlags::NecDspDebuggerEnabled)) {
- _disassembler->BuildCache(addressInfo, 0, CpuType::NecDsp);
-
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::NecDsp);
- _traceLogger->Log(_dsp->GetState(), disInfo, operation);
- }
- }
+ _disassembler->BuildCache(addressInfo, 0, CpuType::NecDsp);
_prevProgramCounter = addr;
_step->ProcessCpuExec();
@@ -58,7 +51,13 @@ void NecDspDebugger::ProcessInstruction()
void NecDspDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type)
{
- //TODO
+ AddressInfo addressInfo = { (int32_t)addr, MemoryType::DspProgramRom };
+ MemoryOperationInfo operation(addr, value, MemoryOperationType::ExecOpCode, MemoryType::NecDspMemory);
+
+ if(_traceLogger->IsEnabled()) {
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::NecDsp);
+ _traceLogger->Log(_dsp->GetState(), disInfo, operation);
+ }
}
void NecDspDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type)
@@ -91,6 +90,24 @@ void NecDspDebugger::Step(int32_t stepCount, StepType type)
_step.reset(new StepRequest(step));
}
+DebuggerFeatures NecDspDebugger::GetSupportedFeatures()
+{
+ DebuggerFeatures features = {};
+ features.ChangeProgramCounter = AllowChangeProgramCounter;
+ return features;
+}
+
+void NecDspDebugger::SetProgramCounter(uint32_t addr)
+{
+ _dsp->GetState().PC = addr / 3;
+ _prevProgramCounter = addr;
+}
+
+uint32_t NecDspDebugger::GetProgramCounter(bool getInstPc)
+{
+ return getInstPc ? _prevProgramCounter : (_dsp->GetState().PC * 3);
+}
+
CallstackManager* NecDspDebugger::GetCallstackManager()
{
return nullptr;
diff --git a/Core/SNES/Debugger/NecDspDebugger.h b/Core/SNES/Debugger/NecDspDebugger.h
index 2eb939c9..7c7ce5ac 100644
--- a/Core/SNES/Debugger/NecDspDebugger.h
+++ b/Core/SNES/Debugger/NecDspDebugger.h
@@ -40,6 +40,10 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+ DebuggerFeatures GetSupportedFeatures() override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
CallstackManager* GetCallstackManager() override;
BreakpointManager* GetBreakpointManager() override;
IAssembler* GetAssembler() override;
diff --git a/Core/SNES/Debugger/SnesDebugger.cpp b/Core/SNES/Debugger/SnesDebugger.cpp
index d950e38d..e9f33e05 100644
--- a/Core/SNES/Debugger/SnesDebugger.cpp
+++ b/Core/SNES/Debugger/SnesDebugger.cpp
@@ -128,11 +128,6 @@ void SnesDebugger::ProcessInstruction()
}
}
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, state.PS, _cpuType);
- _traceLogger->Log(state, disInfo, operation);
- }
-
if(_prevOpCode == 0x20 || _prevOpCode == 0x22 || _prevOpCode == 0xFC) {
//JSR, JSL
uint8_t opSize = DisassemblyInfo::GetOpSize(_prevOpCode, state.PS, _cpuType);
@@ -196,6 +191,10 @@ void SnesDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, state.PS, _cpuType);
+ _traceLogger->Log(state, disInfo, operation);
+ }
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
if(addressInfo.Type == MemoryType::SnesPrgRom && addressInfo.Address >= 0) {
@@ -354,6 +353,32 @@ bool SnesDebugger::IsRegister(uint32_t addr)
return _cpuType == CpuType::Snes && _memoryManager->IsRegister(addr);
}
+DebuggerFeatures SnesDebugger::GetSupportedFeatures()
+{
+ DebuggerFeatures features = {};
+ features.RunToIrq = true;
+ features.RunToNmi = true;
+ features.StepOver = true;
+ features.StepOut = true;
+ features.CallStack = true;
+ features.ChangeProgramCounter = AllowChangeProgramCounter;
+ return features;
+}
+
+void SnesDebugger::SetProgramCounter(uint32_t addr)
+{
+ GetCpuState().PC = (uint16_t)addr;
+ GetCpuState().K = (uint8_t)(addr >> 16);
+
+ _prevOpCode = _memoryManager->Peek(addr);
+ _prevProgramCounter = addr;
+}
+
+uint32_t SnesDebugger::GetProgramCounter(bool getInstPc)
+{
+ return getInstPc ? _prevProgramCounter : ((GetCpuState().K << 16) | GetCpuState().PC);
+}
+
CallstackManager* SnesDebugger::GetCallstackManager()
{
return _callstackManager.get();
diff --git a/Core/SNES/Debugger/SnesDebugger.h b/Core/SNES/Debugger/SnesDebugger.h
index 974f2366..92f9ef3e 100644
--- a/Core/SNES/Debugger/SnesDebugger.h
+++ b/Core/SNES/Debugger/SnesDebugger.h
@@ -91,6 +91,10 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+
+ DebuggerFeatures GetSupportedFeatures() override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
ITraceLogger* GetTraceLogger() override;
BreakpointManager* GetBreakpointManager() override;
diff --git a/Core/SNES/Debugger/SpcDebugger.cpp b/Core/SNES/Debugger/SpcDebugger.cpp
index fbd95f20..df82dd41 100644
--- a/Core/SNES/Debugger/SpcDebugger.cpp
+++ b/Core/SNES/Debugger/SpcDebugger.cpp
@@ -58,11 +58,6 @@ void SpcDebugger::ProcessInstruction()
_disassembler->BuildCache(addressInfo, 0, CpuType::Spc);
- if(_traceLogger->IsEnabled()) {
- DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Spc);
- _traceLogger->Log(state, disInfo, operation);
- }
-
if(_prevOpCode == 0x3F || _prevOpCode == 0x0F) {
//JSR, BRK
uint8_t opSize = DisassemblyInfo::GetOpSize(_prevOpCode, 0, CpuType::Spc);
@@ -115,6 +110,11 @@ void SpcDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
MemoryOperationInfo operation(addr, value, type, MemoryType::SpcMemory);
if(type == MemoryOperationType::ExecOpCode) {
+ if(_traceLogger->IsEnabled()) {
+ SpcState& state = _spc->GetState();
+ DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo, addr, 0, CpuType::Spc);
+ _traceLogger->Log(state, disInfo, operation);
+ }
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
} else if(type == MemoryOperationType::ExecOperand) {
_memoryAccessCounter->ProcessMemoryExec(addressInfo, _memoryManager->GetMasterClock());
@@ -176,6 +176,30 @@ void SpcDebugger::Step(int32_t stepCount, StepType type)
_step.reset(new StepRequest(step));
}
+DebuggerFeatures SpcDebugger::GetSupportedFeatures()
+{
+ DebuggerFeatures features = {};
+ features.RunToIrq = false;
+ features.RunToNmi = false;
+ features.StepOver = true;
+ features.StepOut = true;
+ features.CallStack = true;
+ features.ChangeProgramCounter = AllowChangeProgramCounter;
+ return features;
+}
+
+void SpcDebugger::SetProgramCounter(uint32_t addr)
+{
+ _spc->GetState().PC = (uint16_t)addr;
+ _prevOpCode = _spc->DebugRead(addr);
+ _prevProgramCounter = (uint16_t)addr;
+}
+
+uint32_t SpcDebugger::GetProgramCounter(bool getInstPc)
+{
+ return getInstPc ? _prevProgramCounter : _spc->GetState().PC;
+}
+
CallstackManager* SpcDebugger::GetCallstackManager()
{
return _callstackManager.get();
diff --git a/Core/SNES/Debugger/SpcDebugger.h b/Core/SNES/Debugger/SpcDebugger.h
index e053d214..295d0e3f 100644
--- a/Core/SNES/Debugger/SpcDebugger.h
+++ b/Core/SNES/Debugger/SpcDebugger.h
@@ -51,6 +51,10 @@ public:
void Run() override;
void Step(int32_t stepCount, StepType type) override;
+ DebuggerFeatures GetSupportedFeatures() override;
+ void SetProgramCounter(uint32_t addr) override;
+ uint32_t GetProgramCounter(bool getInstPc) override;
+
CallstackManager* GetCallstackManager() override;
BreakpointManager* GetBreakpointManager() override;
IAssembler* GetAssembler() override;
diff --git a/InteropDLL/DebugApiWrapper.cpp b/InteropDLL/DebugApiWrapper.cpp
index 58aab693..1e798a5c 100644
--- a/InteropDLL/DebugApiWrapper.cpp
+++ b/InteropDLL/DebugApiWrapper.cpp
@@ -102,6 +102,10 @@ extern "C"
DllExport void __stdcall SetCpuState(BaseState& state, CpuType cpuType) { WithDebugger(void, SetCpuState(state, cpuType)); }
DllExport void __stdcall SetPpuState(BaseState& state, CpuType cpuType) { WithDebugger(void, SetPpuState(state, cpuType)); }
+ DllExport uint32_t __stdcall GetProgramCounter(CpuType cpuType, bool getInstPc) { return WithDebugger(uint32_t, GetProgramCounter(cpuType, getInstPc)); }
+ DllExport void __stdcall SetProgramCounter(CpuType cpuType, uint32_t addr) { WithDebugger(void, SetProgramCounter(cpuType, addr)); }
+ DllExport DebuggerFeatures __stdcall GetDebuggerFeatures(CpuType cpuType) { return WithDebugger(DebuggerFeatures, GetDebuggerFeatures(cpuType)); }
+
DllExport const char* __stdcall GetDebuggerLog()
{
_logString = WithDebugger(string, GetLog());
diff --git a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
index b3876be0..abb6a452 100644
--- a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
+++ b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs
@@ -150,7 +150,7 @@ namespace Mesen.Config
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_ViewInMemoryViewer, KeyBinding = new(Key.F1) });
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_AddToWatch, KeyBinding = new() });
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_GoToLocation, KeyBinding = new() });
- Add(new() { Shortcut = DebuggerShortcut.CodeWindow_SetNextStatement, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F10) });
+ Add(new() { Shortcut = DebuggerShortcut.CodeWindow_MoveProgramCounter, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F10) });
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditSelectedCode, KeyBinding = new() });
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditSourceFile, KeyBinding = new(Key.F4) });
Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditLabel, KeyBinding = new(Key.F2) });
@@ -274,7 +274,7 @@ namespace Mesen.Config
BreakOn,
FindOccurrences,
GoToProgramCounter,
- CodeWindow_SetNextStatement,
+ CodeWindow_MoveProgramCounter,
CodeWindow_EditSelectedCode,
CodeWindow_EditSourceFile,
CodeWindow_EditLabel,
diff --git a/NewUI/Debugger/Controls/ActionToolbar.axaml b/NewUI/Debugger/Controls/ActionToolbar.axaml
index 4ae3c039..b49218d7 100644
--- a/NewUI/Debugger/Controls/ActionToolbar.axaml
+++ b/NewUI/Debugger/Controls/ActionToolbar.axaml
@@ -38,7 +38,7 @@
-
+
-