mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
Debugger: Fixed issue that caused forbid breakpoints to prevent "run 1 frame/scanline/etc" from working properly in some scenarios
This commit is contained in:
parent
f675ced226
commit
ecd012c2fe
4 changed files with 69 additions and 29 deletions
|
@ -302,17 +302,19 @@ enum class BreakSource
|
|||
CpuStep,
|
||||
PpuStep,
|
||||
|
||||
Irq,
|
||||
Nmi,
|
||||
|
||||
//Used by DebugBreakHelper, prevents debugger getting focus
|
||||
InternalOperation,
|
||||
|
||||
//Everything after InternalOperation is treated as an "Exception"
|
||||
//Forbid breakpoints can block these, but not the other types above
|
||||
BreakOnBrk,
|
||||
BreakOnCop,
|
||||
BreakOnWdm,
|
||||
BreakOnStp,
|
||||
BreakOnUninitMemoryRead,
|
||||
|
||||
Irq,
|
||||
Nmi,
|
||||
|
||||
GbInvalidOamAccess,
|
||||
GbInvalidVramAccess,
|
||||
|
@ -363,6 +365,14 @@ enum class StepType
|
|||
StepBack
|
||||
};
|
||||
|
||||
enum class BreakType
|
||||
{
|
||||
None = 0,
|
||||
User = 1,
|
||||
Exception = 2,
|
||||
Both = 3
|
||||
};
|
||||
|
||||
struct StepRequest
|
||||
{
|
||||
int64_t BreakAddress = -1;
|
||||
|
@ -374,8 +384,9 @@ struct StepRequest
|
|||
|
||||
bool HasRequest = false;
|
||||
|
||||
bool BreakNeeded = false;
|
||||
BreakType BreakNeeded = BreakType::None;
|
||||
BreakSource Source = BreakSource::Unspecified;
|
||||
BreakSource ExSource = BreakSource::Unspecified;
|
||||
|
||||
StepRequest()
|
||||
{
|
||||
|
@ -397,27 +408,61 @@ struct StepRequest
|
|||
HasRequest = (StepCount != -1 || PpuStepCount != -1 || BreakAddress != -1 || BreakScanline != INT32_MIN || CpuCycleStepCount != -1);
|
||||
}
|
||||
|
||||
__forceinline void SetBreakSource(BreakSource source)
|
||||
void ClearException()
|
||||
{
|
||||
if(Source == BreakSource::Unspecified) {
|
||||
Source = source;
|
||||
ExSource = BreakSource::Unspecified;
|
||||
ClearBreakType(BreakType::Exception);
|
||||
}
|
||||
|
||||
__forceinline void SetBreakSource(BreakSource source, bool breakNeeded)
|
||||
{
|
||||
if(source > BreakSource::InternalOperation) {
|
||||
if(ExSource == BreakSource::Unspecified) {
|
||||
ExSource = source;
|
||||
}
|
||||
|
||||
if(breakNeeded) {
|
||||
SetBreakType(BreakType::Exception);
|
||||
}
|
||||
} else {
|
||||
if(Source == BreakSource::Unspecified) {
|
||||
Source = source;
|
||||
}
|
||||
|
||||
if(breakNeeded) {
|
||||
SetBreakType(BreakType::User);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BreakSource GetBreakSource()
|
||||
{
|
||||
if(ExSource != BreakSource::Unspecified) {
|
||||
return ExSource;
|
||||
}
|
||||
|
||||
if(Source == BreakSource::Unspecified) {
|
||||
if(BreakScanline != INT32_MIN || PpuStepCount >= 0) {
|
||||
return BreakSource::PpuStep;
|
||||
}
|
||||
}
|
||||
|
||||
return Source;
|
||||
}
|
||||
|
||||
__forceinline void SetBreakType(BreakType type)
|
||||
{
|
||||
BreakNeeded = (BreakType)((int)BreakNeeded | (int)type);
|
||||
}
|
||||
|
||||
__forceinline void ClearBreakType(BreakType type)
|
||||
{
|
||||
BreakNeeded = (BreakType)((int)BreakNeeded & ~(int)type);
|
||||
}
|
||||
|
||||
__forceinline void Break(BreakSource src)
|
||||
{
|
||||
BreakNeeded = true;
|
||||
SetBreakSource(src);
|
||||
SetBreakSource(src, true);
|
||||
}
|
||||
|
||||
__forceinline void ProcessCpuExec()
|
||||
|
@ -425,8 +470,7 @@ struct StepRequest
|
|||
if(StepCount > 0) {
|
||||
StepCount--;
|
||||
if(StepCount == 0) {
|
||||
BreakNeeded = true;
|
||||
SetBreakSource(BreakSource::CpuStep);
|
||||
SetBreakSource(BreakSource::CpuStep, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -436,8 +480,7 @@ struct StepRequest
|
|||
if(CpuCycleStepCount > 0) {
|
||||
CpuCycleStepCount--;
|
||||
if(CpuCycleStepCount == 0) {
|
||||
BreakNeeded = true;
|
||||
SetBreakSource(BreakSource::CpuStep);
|
||||
SetBreakSource(BreakSource::CpuStep, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -448,13 +491,11 @@ struct StepRequest
|
|||
{
|
||||
if(forNmi) {
|
||||
if(Type == StepType::RunToNmi) {
|
||||
BreakNeeded = true;
|
||||
SetBreakSource(BreakSource::Nmi);
|
||||
SetBreakSource(BreakSource::Nmi, true);
|
||||
}
|
||||
} else {
|
||||
if(Type == StepType::RunToIrq) {
|
||||
BreakNeeded = true;
|
||||
SetBreakSource(BreakSource::Irq);
|
||||
SetBreakSource(BreakSource::Irq, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ void Debugger::ProcessHaltedCpu()
|
|||
//Process cpu step requests as if each call to ProcessHaltedCpu is an instruction
|
||||
StepRequest* req = dbg->GetStepRequest();
|
||||
req->ProcessCpuExec();
|
||||
if(req->BreakNeeded) {
|
||||
if((int)req->BreakNeeded) {
|
||||
SleepUntilResume(type, req->GetBreakSource());
|
||||
} else {
|
||||
//Also check if a debugger break request is pending
|
||||
|
@ -457,7 +457,7 @@ void Debugger::SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOpe
|
|||
//If SleepUntilResume was called outside of ProcessInstruction, keep running
|
||||
return;
|
||||
} else if(IsBreakpointForbidden(source, sourceCpu, operation)) {
|
||||
ClearPendingBreakRequests();
|
||||
ClearPendingBreakExceptions();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ void Debugger::SleepUntilResume(CpuType sourceCpu, BreakSource source, MemoryOpe
|
|||
|
||||
bool Debugger::IsBreakpointForbidden(BreakSource source, CpuType sourceCpu, MemoryOperationInfo* operation)
|
||||
{
|
||||
if(source != BreakSource::Unspecified && source != BreakSource::CpuStep && source != BreakSource::PpuStep && source != BreakSource::Pause && _breakRequestCount == 0) {
|
||||
if((source > BreakSource::InternalOperation || source == BreakSource::Breakpoint) && _breakRequestCount == 0) {
|
||||
BreakpointManager* bp = _debuggers[(int)sourceCpu].Debugger->GetBreakpointManager();
|
||||
uint32_t pc = GetProgramCounter(sourceCpu, true);
|
||||
AddressInfo relAddr = { (int32_t)pc, DebugUtilities::GetCpuMemoryType(sourceCpu) };
|
||||
|
@ -518,8 +518,8 @@ template<uint8_t accessWidth>
|
|||
void Debugger::ProcessBreakConditions(CpuType sourceCpu, StepRequest& step, BreakpointManager* bpManager, MemoryOperationInfo& operation, AddressInfo& addressInfo)
|
||||
{
|
||||
int breakpointId = bpManager->CheckBreakpoint<accessWidth>(operation, addressInfo, true);
|
||||
if(_breakRequestCount || _waitForBreakResume || (step.BreakNeeded && (!_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints || step.Type == StepType::CpuCycleStep))) {
|
||||
SleepUntilResume(sourceCpu, step.Source);
|
||||
if(_breakRequestCount || _waitForBreakResume || ((int)step.BreakNeeded && (!_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints || step.Type == StepType::CpuCycleStep))) {
|
||||
SleepUntilResume(sourceCpu, step.GetBreakSource());
|
||||
} else {
|
||||
if(breakpointId >= 0 && !_debuggers[(int)sourceCpu].Debugger->IgnoreBreakpoints) {
|
||||
SleepUntilResume(sourceCpu, BreakSource::Breakpoint, &operation, breakpointId);
|
||||
|
@ -656,11 +656,11 @@ void Debugger::Run()
|
|||
_waitForBreakResume = false;
|
||||
}
|
||||
|
||||
void Debugger::ClearPendingBreakRequests()
|
||||
void Debugger::ClearPendingBreakExceptions()
|
||||
{
|
||||
for(int i = 0; i <= (int)DebugUtilities::GetLastCpuType(); i++) {
|
||||
if(_debuggers[i].Debugger) {
|
||||
_debuggers[i].Debugger->Run();
|
||||
_debuggers[i].Debugger->GetStepRequest()->ClearException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -692,7 +692,7 @@ void Debugger::Step(CpuType cpuType, int32_t stepCount, StepType type, BreakSour
|
|||
}
|
||||
|
||||
debugger->Step(stepCount, type);
|
||||
debugger->GetStepRequest()->SetBreakSource(source);
|
||||
debugger->GetStepRequest()->SetBreakSource(source, false);
|
||||
}
|
||||
|
||||
for(int i = 0; i <= (int)DebugUtilities::GetLastCpuType(); i++) {
|
||||
|
|
|
@ -99,7 +99,7 @@ private:
|
|||
bool IsBreakOptionEnabled(BreakSource src);
|
||||
template<CpuType type> void SleepOnBreakRequest();
|
||||
|
||||
void ClearPendingBreakRequests();
|
||||
void ClearPendingBreakExceptions();
|
||||
|
||||
bool IsBreakpointForbidden(BreakSource source, CpuType sourceCpu, MemoryOperationInfo* operation);
|
||||
|
||||
|
|
|
@ -1529,6 +1529,8 @@ namespace Mesen.Interop
|
|||
Pause,
|
||||
CpuStep,
|
||||
PpuStep,
|
||||
Irq,
|
||||
Nmi,
|
||||
InternalOperation,
|
||||
|
||||
BreakOnBrk,
|
||||
|
@ -1537,9 +1539,6 @@ namespace Mesen.Interop
|
|||
BreakOnStp,
|
||||
BreakOnUninitMemoryRead,
|
||||
|
||||
Irq,
|
||||
Nmi,
|
||||
|
||||
GbInvalidOamAccess,
|
||||
GbInvalidVramAccess,
|
||||
GbDisableLcdOutsideVblank,
|
||||
|
|
Loading…
Add table
Reference in a new issue