diff --git a/Core/Debugger/DebugTypes.h b/Core/Debugger/DebugTypes.h index 408f0a4a..f532c7fd 100644 --- a/Core/Debugger/DebugTypes.h +++ b/Core/Debugger/DebugTypes.h @@ -290,6 +290,7 @@ enum class BreakSource { Unspecified = -1, Breakpoint = 0, + Pause, CpuStep, PpuStep, BreakOnBrk, @@ -374,10 +375,27 @@ struct StepRequest HasRequest = (StepCount != -1 || PpuStepCount != -1 || BreakAddress != -1 || BreakScanline != INT32_MIN || CpuCycleStepCount != -1); } + __forceinline void SetBreakSource(BreakSource source) + { + if(Source == BreakSource::Unspecified) { + Source = source; + } + } + + BreakSource GetBreakSource() + { + if(Source == BreakSource::Unspecified) { + if(BreakScanline != INT32_MIN || PpuStepCount >= 0) { + return BreakSource::PpuStep; + } + } + return Source; + } + __forceinline void Break(BreakSource src) { BreakNeeded = true; - Source = src; + SetBreakSource(src); } __forceinline void ProcessCpuExec() @@ -386,7 +404,7 @@ struct StepRequest StepCount--; if(StepCount == 0) { BreakNeeded = true; - Source = BreakSource::CpuStep; + SetBreakSource(BreakSource::CpuStep); } } } @@ -397,7 +415,7 @@ struct StepRequest CpuCycleStepCount--; if(CpuCycleStepCount == 0) { BreakNeeded = true; - Source = BreakSource::CpuStep; + SetBreakSource(BreakSource::CpuStep); return true; } } @@ -409,12 +427,12 @@ struct StepRequest if(forNmi) { if(Type == StepType::RunToNmi) { BreakNeeded = true; - Source = BreakSource::Nmi; + SetBreakSource(BreakSource::Nmi); } } else { if(Type == StepType::RunToIrq) { BreakNeeded = true; - Source = BreakSource::Irq; + SetBreakSource(BreakSource::Irq); } } } diff --git a/Core/Debugger/Debugger.cpp b/Core/Debugger/Debugger.cpp index 559520fa..76385b8b 100644 --- a/Core/Debugger/Debugger.cpp +++ b/Core/Debugger/Debugger.cpp @@ -481,13 +481,25 @@ void Debugger::Run() _waitForBreakResume = false; } -void Debugger::Step(CpuType cpuType, int32_t stepCount, StepType type) +void Debugger::PauseOnNextFrame() +{ + //Use BreakSource::PpuStep to prevent "Run single frame" from triggering the "bring to front on pause" feature + switch(_mainCpuType) { + case CpuType::Snes: Step(CpuType::Snes, 240, StepType::SpecificScanline, BreakSource::PpuStep); break; + case CpuType::Gameboy: Step(CpuType::Gameboy, 144, StepType::SpecificScanline, BreakSource::PpuStep); break; + case CpuType::Nes: Step(CpuType::Nes, 240, StepType::SpecificScanline, BreakSource::PpuStep); break; + case CpuType::Pce: Step(CpuType::Pce, 243, StepType::SpecificScanline, BreakSource::PpuStep); break; + } +} + +void Debugger::Step(CpuType cpuType, int32_t stepCount, StepType type, BreakSource source) { DebugBreakHelper helper(this); IDebugger* debugger = _debuggers[(int)cpuType].Debugger.get(); if(debugger) { debugger->Step(stepCount, type); + debugger->GetStepRequest()->SetBreakSource(source); } for(int i = 0; i <= (int)DebugUtilities::GetLastCpuType(); i++) { diff --git a/Core/Debugger/Debugger.h b/Core/Debugger/Debugger.h index cca34380..5877eb6a 100644 --- a/Core/Debugger/Debugger.h +++ b/Core/Debugger/Debugger.h @@ -119,7 +119,8 @@ public: int32_t EvaluateExpression(string expression, CpuType cpuType, EvalResultType &resultType, bool useCache); void Run(); - void Step(CpuType cpuType, int32_t stepCount, StepType type); + void PauseOnNextFrame(); + void Step(CpuType cpuType, int32_t stepCount, StepType type, BreakSource source = BreakSource::Unspecified); bool IsPaused(); bool IsExecutionStopped(); diff --git a/Core/Debugger/IDebugger.h b/Core/Debugger/IDebugger.h index 99f653ca..4cba12ca 100644 --- a/Core/Debugger/IDebugger.h +++ b/Core/Debugger/IDebugger.h @@ -17,6 +17,9 @@ enum class MemoryOperationType; class IDebugger { +protected: + unique_ptr _step; + public: bool IgnoreBreakpoints = false; bool AllowChangeProgramCounter = false; @@ -24,6 +27,8 @@ public: virtual ~IDebugger() = default; + StepRequest* GetStepRequest() { return _step.get(); } + virtual void Step(int32_t stepCount, StepType type) = 0; virtual void Reset() = 0; virtual void Run() = 0; diff --git a/Core/Gameboy/Debugger/GbDebugger.cpp b/Core/Gameboy/Debugger/GbDebugger.cpp index b25b1f1f..47b7ef34 100644 --- a/Core/Gameboy/Debugger/GbDebugger.cpp +++ b/Core/Gameboy/Debugger/GbDebugger.cpp @@ -309,11 +309,11 @@ void GbDebugger::ProcessPpuCycle() if(_step->HasRequest) { if(_step->HasScanlineBreakRequest() && _ppu->GetCycle() == 0 && _ppu->GetScanline() == _step->BreakScanline) { - _debugger->SleepUntilResume(CpuType::Gameboy, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Gameboy, _step->GetBreakSource()); } else if(_step->PpuStepCount > 0) { _step->PpuStepCount--; if(_step->PpuStepCount == 0) { - _debugger->SleepUntilResume(CpuType::Gameboy, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Gameboy, _step->GetBreakSource()); } } } diff --git a/Core/Gameboy/Debugger/GbDebugger.h b/Core/Gameboy/Debugger/GbDebugger.h index e6107b5e..29b11ce0 100644 --- a/Core/Gameboy/Debugger/GbDebugger.h +++ b/Core/Gameboy/Debugger/GbDebugger.h @@ -38,7 +38,6 @@ class GbDebugger final : public IDebugger unique_ptr _callstackManager; unique_ptr _codeDataLogger; unique_ptr _breakpointManager; - unique_ptr _step; unique_ptr _assembler; unique_ptr _traceLogger; unique_ptr _ppuTools; diff --git a/Core/NES/Debugger/NesDebugger.cpp b/Core/NES/Debugger/NesDebugger.cpp index 68a296cd..5410b5bf 100644 --- a/Core/NES/Debugger/NesDebugger.cpp +++ b/Core/NES/Debugger/NesDebugger.cpp @@ -347,11 +347,11 @@ void NesDebugger::ProcessPpuCycle() if(_step->HasRequest) { if(_step->HasScanlineBreakRequest() && _ppu->GetCurrentCycle() == 0 && _ppu->GetCurrentScanline() == _step->BreakScanline) { - _debugger->SleepUntilResume(CpuType::Nes, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Nes, _step->GetBreakSource()); } else if(_step->PpuStepCount > 0) { _step->PpuStepCount--; if(_step->PpuStepCount == 0) { - _debugger->SleepUntilResume(CpuType::Nes, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Nes, _step->GetBreakSource()); } } } diff --git a/Core/NES/Debugger/NesDebugger.h b/Core/NES/Debugger/NesDebugger.h index 5822f2a6..2df95b47 100644 --- a/Core/NES/Debugger/NesDebugger.h +++ b/Core/NES/Debugger/NesDebugger.h @@ -47,7 +47,6 @@ class NesDebugger final : public IDebugger unique_ptr _callstackManager; unique_ptr _breakpointManager; unique_ptr _traceLogger; - unique_ptr _step; unique_ptr _ppuTools; bool _enableBreakOnUninitRead = false; diff --git a/Core/PCE/Debugger/PceDebugger.cpp b/Core/PCE/Debugger/PceDebugger.cpp index d20e0c24..f612e932 100644 --- a/Core/PCE/Debugger/PceDebugger.cpp +++ b/Core/PCE/Debugger/PceDebugger.cpp @@ -317,12 +317,12 @@ void PceDebugger::ProcessPpuCycle() if(_step->HasRequest) { if(_step->HasScanlineBreakRequest() && _vdc->GetHClock() == 0 && _vdc->GetScanline() == _step->BreakScanline) { - _debugger->SleepUntilResume(CpuType::Pce, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Pce, _step->GetBreakSource()); } else if(_step->PpuStepCount > 0) { _step->PpuStepCount -= 3; if(_step->PpuStepCount <= 0) { _step->PpuStepCount = 0; - _debugger->SleepUntilResume(CpuType::Pce, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Pce, _step->GetBreakSource()); } } } diff --git a/Core/PCE/Debugger/PceDebugger.h b/Core/PCE/Debugger/PceDebugger.h index 1d428874..26d1a252 100644 --- a/Core/PCE/Debugger/PceDebugger.h +++ b/Core/PCE/Debugger/PceDebugger.h @@ -48,7 +48,6 @@ class PceDebugger final : public IDebugger unique_ptr _callstackManager; unique_ptr _breakpointManager; unique_ptr _traceLogger; - unique_ptr _step; unique_ptr _ppuTools; bool _enableBreakOnUninitRead = false; diff --git a/Core/SNES/Debugger/Cx4Debugger.h b/Core/SNES/Debugger/Cx4Debugger.h index bb77f40b..efba07ef 100644 --- a/Core/SNES/Debugger/Cx4Debugger.h +++ b/Core/SNES/Debugger/Cx4Debugger.h @@ -28,7 +28,6 @@ class Cx4Debugger final : public IDebugger unique_ptr _breakpointManager; unique_ptr _callstackManager; - unique_ptr _step; unique_ptr _traceLogger; uint32_t _prevProgramCounter = 0; diff --git a/Core/SNES/Debugger/GsuDebugger.h b/Core/SNES/Debugger/GsuDebugger.h index 70934dde..959e3c11 100644 --- a/Core/SNES/Debugger/GsuDebugger.h +++ b/Core/SNES/Debugger/GsuDebugger.h @@ -26,7 +26,6 @@ class GsuDebugger final : public IDebugger EmuSettings* _settings; unique_ptr _breakpointManager; - unique_ptr _step; unique_ptr _traceLogger; uint8_t _prevOpCode = 0xFF; diff --git a/Core/SNES/Debugger/NecDspDebugger.h b/Core/SNES/Debugger/NecDspDebugger.h index df1d1bba..8199a6a6 100644 --- a/Core/SNES/Debugger/NecDspDebugger.h +++ b/Core/SNES/Debugger/NecDspDebugger.h @@ -23,7 +23,6 @@ class NecDspDebugger final : public IDebugger EmuSettings* _settings; unique_ptr _breakpointManager; - unique_ptr _step; unique_ptr _traceLogger; unique_ptr _callstackManager; diff --git a/Core/SNES/Debugger/SnesDebugger.cpp b/Core/SNES/Debugger/SnesDebugger.cpp index 8f53324f..314e16ea 100644 --- a/Core/SNES/Debugger/SnesDebugger.cpp +++ b/Core/SNES/Debugger/SnesDebugger.cpp @@ -377,11 +377,11 @@ void SnesDebugger::ProcessPpuCycle() if(_step->HasRequest) { if(_step->HasScanlineBreakRequest() && _ppu->GetScanline() == _step->BreakScanline && _memoryManager->GetHClock() == 0) { - _debugger->SleepUntilResume(CpuType::Snes, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Snes, _step->GetBreakSource()); } else if(_step->PpuStepCount > 0) { _step->PpuStepCount--; if(_step->PpuStepCount == 0) { - _debugger->SleepUntilResume(CpuType::Snes, BreakSource::PpuStep); + _debugger->SleepUntilResume(CpuType::Snes, _step->GetBreakSource()); } } } diff --git a/Core/SNES/Debugger/SnesDebugger.h b/Core/SNES/Debugger/SnesDebugger.h index bc9a18c9..89945e6f 100644 --- a/Core/SNES/Debugger/SnesDebugger.h +++ b/Core/SNES/Debugger/SnesDebugger.h @@ -51,7 +51,6 @@ class SnesDebugger final : public IDebugger unique_ptr _assembler; unique_ptr _callstackManager; unique_ptr _breakpointManager; - unique_ptr _step; unique_ptr _traceLogger; unique_ptr _ppuTools; unique_ptr _dummyCpu; diff --git a/Core/SNES/Debugger/SpcDebugger.h b/Core/SNES/Debugger/SpcDebugger.h index f44f4d90..f9c65cf3 100644 --- a/Core/SNES/Debugger/SpcDebugger.h +++ b/Core/SNES/Debugger/SpcDebugger.h @@ -28,7 +28,6 @@ class SpcDebugger final : public IDebugger unique_ptr _callstackManager; unique_ptr _breakpointManager; unique_ptr _traceLogger; - unique_ptr _step; unique_ptr _dummyCpu; uint8_t _prevOpCode = 0xFF; diff --git a/Core/Shared/Emulator.cpp b/Core/Shared/Emulator.cpp index fa9b8af0..355fff73 100644 --- a/Core/Shared/Emulator.cpp +++ b/Core/Shared/Emulator.cpp @@ -665,27 +665,10 @@ double Emulator::GetFrameDelay() void Emulator::PauseOnNextFrame() { + //Used by "Run single frame" shortcut shared_ptr debugger = _debugger.lock(); if(debugger) { - //TODO move this logic to console classes? - switch(GetConsoleType()) { - case ConsoleType::Snes: - debugger->Step(CpuType::Snes, 240, StepType::SpecificScanline); - break; - - case ConsoleType::Gameboy: - case ConsoleType::GameboyColor: - debugger->Step(CpuType::Gameboy, 144, StepType::SpecificScanline); - break; - - case ConsoleType::Nes: - debugger->Step(CpuType::Nes, 240, StepType::SpecificScanline); - break; - - case ConsoleType::PcEngine: - debugger->Step(CpuType::Pce, 243, StepType::SpecificScanline); - break; - } + debugger->PauseOnNextFrame(); } else { _pauseOnNextFrame = true; _paused = false; @@ -696,7 +679,7 @@ void Emulator::Pause() { shared_ptr debugger = _debugger.lock(); if(debugger) { - debugger->Step(GetCpuTypes()[0], 1, StepType::Step); + debugger->Step(GetCpuTypes()[0], 1, StepType::Step, BreakSource::Pause); } else { _paused = true; } diff --git a/NewUI/Config/Debugger/DebuggerConfig.cs b/NewUI/Config/Debugger/DebuggerConfig.cs index 9711685d..4efdc408 100644 --- a/NewUI/Config/Debugger/DebuggerConfig.cs +++ b/NewUI/Config/Debugger/DebuggerConfig.cs @@ -49,6 +49,7 @@ namespace Mesen.Config [Reactive] public bool RefreshWhileRunning { get; set; } = false; [Reactive] public bool BringToFrontOnBreak { get; set; } = true; + [Reactive] public bool BringToFrontOnPause { get; set; } = false; [Reactive] public CodeDisplayMode UnidentifiedBlockDisplay { get; set; } = CodeDisplayMode.Hide; [Reactive] public CodeDisplayMode VerifiedDataDisplay { get; set; } = CodeDisplayMode.Hide; diff --git a/NewUI/Debugger/Views/DebuggerOptionsView.axaml b/NewUI/Debugger/Views/DebuggerOptionsView.axaml index d8f917fd..28d7795c 100644 --- a/NewUI/Debugger/Views/DebuggerOptionsView.axaml +++ b/NewUI/Debugger/Views/DebuggerOptionsView.axaml @@ -175,7 +175,12 @@ IsChecked="{CompiledBinding Config.BringToFrontOnBreak}" Content="{l:Translate chkBringToFrontOnBreak}" /> - + + + (e.Parameter); Dispatcher.UIThread.Post(() => { _model.UpdateDebugger(true, evt); - if(!_suppressBringToFront && _model.Config.BringToFrontOnBreak && evt.SourceCpu == _model.CpuType && evt.Source != BreakSource.PpuStep) { - Activate(); + if(!_suppressBringToFront) { + bool isPause = evt.Source == BreakSource.Pause; + if(isPause && _model.Config.BringToFrontOnPause && evt.SourceCpu == _model.CpuType) { + Activate(); + } else if(!isPause && _model.Config.BringToFrontOnBreak && evt.SourceCpu == _model.CpuType && evt.Source != BreakSource.PpuStep) { + Activate(); + } } _suppressBringToFront = false; }); diff --git a/NewUI/Interop/DebugApi.cs b/NewUI/Interop/DebugApi.cs index 792a3a2c..2039fe71 100644 --- a/NewUI/Interop/DebugApi.cs +++ b/NewUI/Interop/DebugApi.cs @@ -1207,6 +1207,7 @@ namespace Mesen.Interop { Unspecified = -1, Breakpoint = 0, + Pause, CpuStep, PpuStep, BreakOnBrk, diff --git a/NewUI/Localization/resources.en.xml b/NewUI/Localization/resources.en.xml index f758daf1..ea0a94a8 100644 --- a/NewUI/Localization/resources.en.xml +++ b/NewUI/Localization/resources.en.xml @@ -1073,6 +1073,7 @@ Misc. settings Bring to front on break + Bring to front on pause Refresh while running Draw partial frame Use predictive breakpoints @@ -2424,6 +2425,7 @@ Text (Active only) + Pause Breakpoint CPU Step PPU Step