mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Netplay rb: admit the Live tick a realign resumes into
A Live realign restores the snap at T, sets the session to T+1 and longjmps back into the guest from the admit spin. The resume ran before T+1 was admitted, so that frame latched no inputs and did not advance; the next frame was then counted as T+1 and the realigned seat ran one frame ahead of its tick label from there on (ring saves after a NACK realign carried the next tick's clock, 2x the cycles in the first tick). Only the realigned seat shifted, so it forked from every other seat; with four seats this produced the "resim core diverge" splits and the later hc-fork / hang cascade. flush_resume now admits the tick first on the Live realign path and keeps spinning until it can. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,8 @@ void psx_netplay_rb_poll(struct CPUState *cpu, uint32_t resume_pc);
|
||||
* (same as savestate_poll). No-op when nothing is pending. Never returns on
|
||||
* success. */
|
||||
void psx_netplay_rb_flush_resume(void);
|
||||
/* psx_netplay.c: admit the Live tick a realign resumes into (1 = admitted). */
|
||||
int psx_netplay_live_realign_admit(void);
|
||||
|
||||
/* 1 after flush_resume longjmp until finish_frame / abort — top-level
|
||||
* dispatch has no native call chain under the resume PC. */
|
||||
|
||||
@@ -5016,6 +5016,21 @@ static int np_try_admit_load_barrier_unconfirmed(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* A Live realign restores the snap at T and resumes the guest at the frame
|
||||
* boundary after it, with the session already at T+1. Admit T+1 before the
|
||||
* resume: resuming first ran frame T+1 unadmitted (no inputs latched, no
|
||||
* advance), so the next frame was counted as T+1 and this peer ran one frame
|
||||
* ahead of its tick label (4-seat race: L-saves after a NACK realign carried
|
||||
* the next tick's clock; the realigned seat forked from every other). */
|
||||
int psx_netplay_live_realign_admit(void)
|
||||
{
|
||||
if (!psx_netplay_active() || !g_np.rollback || g_np.xfer != NP_XFER_NONE)
|
||||
return 1;
|
||||
if (g_np.needs_advance)
|
||||
return 1;
|
||||
return np_try_admit_rollback();
|
||||
}
|
||||
|
||||
int psx_netplay_poll_admit(void)
|
||||
{
|
||||
rnet_u32 sim;
|
||||
|
||||
@@ -7117,6 +7117,11 @@ void psx_netplay_rb_flush_resume(void)
|
||||
live_realign_resume = !g_rb || !rnet_rb_is_active(g_rb);
|
||||
if (!live_realign_resume && rnet_rb_get_phase(g_rb) != nRNetRbPhaseReplay)
|
||||
return;
|
||||
/* Live realign: the resumed frame must be an admitted tick, or it runs
|
||||
* uncounted and this seat ends one frame ahead of its label. Stay
|
||||
* spinning until the tick's inputs admit. */
|
||||
if (live_realign_resume && !psx_netplay_live_realign_admit())
|
||||
return;
|
||||
pc = g_pending_resume_pc;
|
||||
if (!rb_resume_pc_ok(pc)) {
|
||||
uint32_t alt = pick_snap_resume_pc(cpu(), pc);
|
||||
|
||||
Reference in New Issue
Block a user