mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
SPU: anchor the restored sample phase to the restored clock at load
The SPU's guest-clock phase was applied lazily at the next catch-up, after the guest had run on, so the phase was taken against a later clock and lost; a rollback replay rendered SPU samples at other guest cycles than the live run (voice / SPU RAM split with an identical CPU path, PSX_RB_DET_SELFTEST). boot_state writes CLOCK before SPU, so the load anchors it immediately. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+14
-3
@@ -2028,9 +2028,20 @@ int spu_snapshot_read(const uint8_t *p, uint32_t len) {
|
||||
}
|
||||
uint32_t phase = 0;
|
||||
if (len == spu_snapshot_bytes() && !pst_r_u32(&r, &phase)) return 0;
|
||||
/* Applied at the next catch-up, once the guest clock is restored too. */
|
||||
s_clock_carry = phase % SPU_CYCLES_PER_SAMPLE;
|
||||
s_clock_valid = 0;
|
||||
/* Anchor the SPU's sample phase to the restored clock NOW. boot_state
|
||||
* writes CLOCK before SPU, so the clock is already restored here. It used
|
||||
* to be applied lazily at the next catch-up -- after the guest had run on,
|
||||
* so the phase was taken against a later clock and lost: a rollback
|
||||
* replay rendered SPU samples at other guest cycles than the live run
|
||||
* (voice state / SPU RAM split with identical CPU paths,
|
||||
* PSX_RB_DET_SELFTEST). */
|
||||
{
|
||||
const uint64_t now = psx_get_cycle_count();
|
||||
const uint32_t carry = phase % SPU_CYCLES_PER_SAMPLE;
|
||||
s_clock = now >= carry ? now - carry : now;
|
||||
s_clock_carry = 0;
|
||||
s_clock_valid = 1;
|
||||
}
|
||||
spu_output_flush();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user