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 @@ - + -