From 422f5ed3e5cb040780d06058828ddf5a15a8ef44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 31 Oct 2026 15:34:50 +0100 Subject: [PATCH] Instance sync: Count milliseconds in emulated time, not cycles The barrier divided the cycle count by the current clock's cycles per millisecond, so a game that changes the CPU clock (Pangya: Fantasy Golf does on its network screens) jumped its count by up to a fifth of everything so far, and from then on ran in lockstep at the wrong ratio: the other instance waited for up to half a minute, then the two ran 266:222 apart in emulated time. Co-Authored-By: Claude Opus 5.5 --- Core/CoreTiming.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index dbb3cec6c4..04aef5f5bd 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -460,9 +460,10 @@ void Advance(MIPSState *mips) { // Keep in step with the other instances. Before the deadline below, so one stopping there has // still told the others it got this far. - const s64 syncTicks = InstanceSyncEnabled() ? usToCycles(1000) : 0; - if (syncTicks && globalTimer / syncTicks != lastInstanceSyncMs) { - lastInstanceSyncMs = globalTimer / syncTicks; + // Counted in time, not cycles: a game can change the CPU clock, and the instances wouldn't agree. + const bool instanceSync = InstanceSyncEnabled(); + if (instanceSync && (s64)(GetGlobalTimeUs() / 1000) != lastInstanceSyncMs) { + lastInstanceSyncMs = (s64)(GetGlobalTimeUs() / 1000); InstanceSyncReached(lastInstanceSyncMs); } @@ -505,8 +506,8 @@ void Advance(MIPSState *mips) { } // Likewise come back at the next millisecond, for the instance sync. - if (syncTicks) { - const s64 remaining = (lastInstanceSyncMs + 1) * syncTicks - globalTimer; + if (instanceSync) { + const s64 remaining = usToCycles((lastInstanceSyncMs + 1) * 1000 - (s64)GetGlobalTimeUs()); if (remaining > 0 && remaining < slicelength) { const int diff = (int)remaining - slicelength; slicelength += diff;