ImDebugger: add "Run to here, next frame", gated on the flip count

Prototype of the frame-gated run-to-cursor idea. "Run to here" stops at the
first hit, which isn't what you want for an address hit many times per frame -
you end up stepping through the rest of the current frame to reach the state
you actually care about.

Built on machinery that was already there rather than a new stepping mode: the
one-shot breakpoint behind run-to-cursor already takes a condition (step-into
uses it to pin a step to one thread), and a hit that fails the condition leaves
it armed for the next one. So "the next frame" is just a condition that isn't
true yet - here "flipcount > <now>".

Counting presented frames rather than vblanks matters for a game that doesn't
render at the full refresh rate: at 30fps there are two vblanks per frame, so a
vblank-based condition would let you through halfway into the frame you were
trying to skip. The flip side is that the counter only advances when the
framebuffer actually changed, so if the game has stopped drawing - or is wedged
in the loop you're trying to debug - this never trips and the core keeps
running.

Both counters are exposed to the expression parser, next to
threadid/moduleid/usec/ticks, so they're usable in ordinary breakpoint
conditions and cpu.evaluate too, not just from this menu item: "flipcount" for
presented frames and "vcount" for the PSP's own vblank counter, which is what
sceDisplayGetVcount returns and is the one a game's own timing is written
against.

Verified with a headless session: across a second of emulated time flipcount
went 120 -> 172 and vcount 119 -> 172 (a game rendering every vblank, so they
track).

pspautotests 314/314, UnitTest 55/55.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-08-18 10:59:08 +02:00
1 parent 434f1b4e13
commit d8a1808b3d
4 files changed
+63 -6

No files matched your search

+3 -1
View File
@@ -357,7 +357,9 @@ BreakAction BreakpointManager::ExecBreakPoint(u32 addr) {
}
if (tempBreakPoint_.valid && tempBreakPoint_.addr == addr) {
// The condition, when set, restricts the step to one thread - see SetTempBreakPointCond().
// The condition, when set, narrows down which hit counts - to one thread for a step
// ("threadid == ..."), or to a later frame for run-to-cursor ("flipcount > ..."). A hit that
// fails it leaves the breakpoint armed, so the next one gets a chance.
if (!tempBreakPoint_.hasCond || tempBreakPoint_.cond.Evaluate() != 0) {
DEBUG_LOG(Log::Debugger, "Reached temporary breakpoint at %08x", addr);
result |= BREAK_ACTION_PAUSE;