diff --git a/Core/Core.cpp b/Core/Core.cpp index 51e2fcaab4..32db6ab451 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -225,7 +225,7 @@ void Core_RunLoop(GraphicsContext *ctx) { } } - while (!coreState && GetUIState() == UISTATE_INGAME) { + while ((coreState == CORE_RUNNING || coreState == CORE_STEPPING) && GetUIState() == UISTATE_INGAME) { time_update(); UpdateRunLoop(); if (!windowHidden && !Core_IsStepping()) { @@ -264,8 +264,9 @@ void Core_SingleStep() { static inline bool Core_WaitStepping() { std::unique_lock guard(m_hStepMutex); + // We only wait 16ms so that we can still draw UI or react to events. if (!singleStepPending && coreState == CORE_STEPPING) - m_StepCond.wait(guard); + m_StepCond.wait_for(guard, std::chrono::milliseconds(16)); bool result = singleStepPending; singleStepPending = false; @@ -285,9 +286,13 @@ void Core_ProcessStepping() { GPUStepping::SingleStep(); // We're not inside jit now, so it's safe to clear the breakpoints. - CBreakPoints::ClearTemporaryBreakPoints(); - host->UpdateDisassembly(); - host->UpdateMemView(); + static int lastSteppingCounter = -1; + if (lastSteppingCounter != steppingCounter) { + CBreakPoints::ClearTemporaryBreakPoints(); + host->UpdateDisassembly(); + host->UpdateMemView(); + lastSteppingCounter = steppingCounter; + } // Need to check inside the lock to avoid races. bool doStep = Core_WaitStepping(); diff --git a/Core/System.cpp b/Core/System.cpp index b59a365872..bd55510b06 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -442,6 +442,10 @@ void PSP_RunLoopWhileState() { // Run until CORE_NEXTFRAME while (coreState == CORE_RUNNING || coreState == CORE_STEPPING) { PSP_RunLoopFor(blockTicks); + if (coreState == CORE_STEPPING) { + // Keep the UI responsive. + break; + } } } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7dcedfa43d..9d38a4b859 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1230,8 +1230,13 @@ void EmuScreen::render() { // set back to running for the next frame coreState = CORE_RUNNING; } else if (coreState == CORE_STEPPING) { - // If we're stepping, it's convenient not to clear the screen. - thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::DONT_CARE, RPAction::DONT_CARE }); + // If we're stepping, it's convenient not to clear the screen entirely, so we copy display to output. + // This won't work in non-buffered, but that's fine. + thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::DONT_CARE, RPAction::DONT_CARE }); + // Just to make sure. + if (PSP_IsInited()) { + gpu->CopyDisplayToOutput(); + } } else { // Didn't actually reach the end of the frame, ran out of the blockTicks cycles. // In this case we need to bind and wipe the backbuffer, at least.