WebSocket debugger: runUntilTime that's already there, and across loads

A target time that had already passed, relativeUs 0 for one, failed
without a stop event, so a client waiting for cpu.stepping waited until
its own timeout. Now it doesn't run, and reports the stop right away.

A savestate loaded during the run kept the deadline's absolute time,
which belongs to the timeline the load replaced: a state from later in
the game stopped the run at once, one from earlier ran it for as long
as the gap. Now the deadline keeps the time it had left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-29 00:21:49 +01:00
1 parent df72f3be81
commit 93b7dacc1e
5 files changed
+35 -9

No files matched your search

@@ -293,6 +293,9 @@ void WebSocketSteppingState::RunUntil(DebuggerRequest &req) {
// - us: emulated time right now.
// A cpu.stepping event follows once it gets there. Note that anything else that stops the CPU
// first - a breakpoint, an exception - cancels the deadline, same as it cancels a step.
// A time that has already passed (relativeUs 0, say) doesn't run at all: the response and the
// cpu.stepping event come right away. A savestate loaded during the run moves the deadline along
// with the clock, so it still runs for the time that was left.
void WebSocketSteppingState::RunUntilTime(DebuggerRequest &req) {
if (!currentDebugMIPS->isAlive()) {
return req.Fail("CPU not started");
@@ -318,15 +321,14 @@ void WebSocketSteppingState::RunUntilTime(DebuggerRequest &req) {
const u64 nowUs = CoreTiming::GetGlobalTimeUs();
const u64 targetUs = absolute ? (u64)requested : nowUs + (u64)requested;
if (targetUs <= nowUs) {
req.Fail("Target time has already passed");
return;
// Already there. A client waiting for the stop would otherwise never get one.
Core_ReportBreakWithoutRunning(BreakReason::RunUntilTime, currentMIPS->pc);
} else {
CoreTiming::SetBreakDeadlineUs(targetUs);
PrepareResume();
Core_Resume();
}
CoreTiming::SetBreakDeadlineUs(targetUs);
PrepareResume();
Core_Resume();
JsonWriter &json = req.Respond();
json.writeFloat("targetUs", (double)targetUs);
json.writeFloat("us", (double)nowUs);