Debugger: Added "bring to front on pause" option

This commit is contained in:
Sour 2022-08-26 18:20:34 -04:00
parent 89a2a46392
commit 7b394aa686
22 changed files with 71 additions and 46 deletions

View file

@ -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);
}
}
}

View file

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

View file

@ -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();

View file

@ -17,6 +17,9 @@ enum class MemoryOperationType;
class IDebugger
{
protected:
unique_ptr<StepRequest> _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;

View file

@ -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());
}
}
}

View file

@ -38,7 +38,6 @@ class GbDebugger final : public IDebugger
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<CodeDataLogger> _codeDataLogger;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
unique_ptr<GbAssembler> _assembler;
unique_ptr<GbTraceLogger> _traceLogger;
unique_ptr<GbPpuTools> _ppuTools;

View file

@ -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());
}
}
}

View file

@ -47,7 +47,6 @@ class NesDebugger final : public IDebugger
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<NesTraceLogger> _traceLogger;
unique_ptr<StepRequest> _step;
unique_ptr<NesPpuTools> _ppuTools;
bool _enableBreakOnUninitRead = false;

View file

@ -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());
}
}
}

View file

@ -48,7 +48,6 @@ class PceDebugger final : public IDebugger
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<PceTraceLogger> _traceLogger;
unique_ptr<StepRequest> _step;
unique_ptr<PceVdcTools> _ppuTools;
bool _enableBreakOnUninitRead = false;

View file

@ -28,7 +28,6 @@ class Cx4Debugger final : public IDebugger
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<StepRequest> _step;
unique_ptr<Cx4TraceLogger> _traceLogger;
uint32_t _prevProgramCounter = 0;

View file

@ -26,7 +26,6 @@ class GsuDebugger final : public IDebugger
EmuSettings* _settings;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
unique_ptr<GsuTraceLogger> _traceLogger;
uint8_t _prevOpCode = 0xFF;

View file

@ -23,7 +23,6 @@ class NecDspDebugger final : public IDebugger
EmuSettings* _settings;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
unique_ptr<NecDspTraceLogger> _traceLogger;
unique_ptr<CallstackManager> _callstackManager;

View file

@ -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());
}
}
}

View file

@ -51,7 +51,6 @@ class SnesDebugger final : public IDebugger
unique_ptr<SnesAssembler> _assembler;
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<StepRequest> _step;
unique_ptr<SnesCpuTraceLogger> _traceLogger;
unique_ptr<SnesPpuTools> _ppuTools;
unique_ptr<DummySnesCpu> _dummyCpu;

View file

@ -28,7 +28,6 @@ class SpcDebugger final : public IDebugger
unique_ptr<CallstackManager> _callstackManager;
unique_ptr<BreakpointManager> _breakpointManager;
unique_ptr<SpcTraceLogger> _traceLogger;
unique_ptr<StepRequest> _step;
unique_ptr<DummySpc> _dummyCpu;
uint8_t _prevOpCode = 0xFF;

View file

@ -665,27 +665,10 @@ double Emulator::GetFrameDelay()
void Emulator::PauseOnNextFrame()
{
//Used by "Run single frame" shortcut
shared_ptr<Debugger> 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 = _debugger.lock();
if(debugger) {
debugger->Step(GetCpuTypes()[0], 1, StepType::Step);
debugger->Step(GetCpuTypes()[0], 1, StepType::Step, BreakSource::Pause);
} else {
_paused = true;
}

View file

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

View file

@ -175,7 +175,12 @@
IsChecked="{CompiledBinding Config.BringToFrontOnBreak}"
Content="{l:Translate chkBringToFrontOnBreak}"
/>
<CheckBox
IsChecked="{CompiledBinding Config.BringToFrontOnPause}"
Content="{l:Translate chkBringToFrontOnPause}"
/>
<CheckBox
IsChecked="{CompiledBinding Config.RefreshWhileRunning}"
Content="{l:Translate chkRefreshWhileRunning}"

View file

@ -135,8 +135,13 @@ namespace Mesen.Debugger.Windows
BreakEvent evt = Marshal.PtrToStructure<BreakEvent>(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;
});

View file

@ -1207,6 +1207,7 @@ namespace Mesen.Interop
{
Unspecified = -1,
Breakpoint = 0,
Pause,
CpuStep,
PpuStep,
BreakOnBrk,

View file

@ -1073,6 +1073,7 @@
<Control ID="lblMiscSettings">Misc. settings</Control>
<Control ID="chkBringToFrontOnBreak">Bring to front on break</Control>
<Control ID="chkBringToFrontOnPause">Bring to front on pause</Control>
<Control ID="chkRefreshWhileRunning">Refresh while running</Control>
<Control ID="chkDrawPartialFrame">Draw partial frame</Control>
<Control ID="chkUsePredictiveBreakpoints">Use predictive breakpoints</Control>
@ -2424,6 +2425,7 @@
<Value ID="CompactText">Text (Active only)</Value>
</Enum>
<Enum ID="BreakSource">
<Value ID="Pause">Pause</Value>
<Value ID="Breakpoint">Breakpoint</Value>
<Value ID="CpuStep">CPU Step</Value>
<Value ID="PpuStep">PPU Step</Value>