mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
netplay fmv patch again
This commit is contained in:
@@ -4978,3 +4978,41 @@ Cachy `GAP1_LEGACY` / `RUNWAY_EMPTY` invents. Soft fork @1480 sat **before**
|
||||
ahead-of-tip seat; fewer `GAP1_LEGACY` / `RUNWAY_EMPTY` before tip+1.
|
||||
Accuracy (§112 arm) still required for matched fin cyc at tip+1.
|
||||
|
||||
|
||||
## 114. Platform tip+1 apply-only heal + KF stream (2026-08-13)
|
||||
|
||||
**Problem:** matched-baseline tip+1 after post-FMV loading is Win↔Linux
|
||||
platform nondeterminism (cpu/clk/tim/ram diverge with matched dirty). Verify
|
||||
span past load always aborted; empty tip KF rematched tip and stormed.
|
||||
|
||||
**What landed (§114):**
|
||||
|
||||
1. Apply-only MEDIA_KF heal (`target=load`) — no tip+1 resim.
|
||||
2. Heal Live → invent off + `g_post_fmv_platform_nondet` + initiator KF stream
|
||||
every 16 sim ticks (dense snaps).
|
||||
3. Heal loop CAP → same keep-live stream instead of hard DESYNC abort.
|
||||
|
||||
**Gap:** stream always rewound to HC's stuck tip+1 fork (`resolved+1`), so
|
||||
`choose_load` re-pinned keep forever → loading-screen livelock (no DESYNC).
|
||||
|
||||
## 115. Platform KF stream escape / host-tip ride (2026-08-13)
|
||||
|
||||
**Soak (MotK Win↔CachyOS after §114):** `FIRST CORE DIVERGE sim=1112`, heal
|
||||
pin `1111` / `pc=0x800768e8`, then hundreds of `§114 KF stream begin
|
||||
fork=1112` + `heal KF CAP →1111` with `invent off until rematch`. No DESYNC;
|
||||
loading never advanced. HC `peek_mismatch` stays at tip+1 while
|
||||
`resolved_through=keep`.
|
||||
|
||||
**What landed (§115):**
|
||||
|
||||
1. **Host-tip ride** — when HC fork is the known platform tip+1 and
|
||||
`sim > fork`, stream `begin_rewind(sim)` so MEDIA-KF pins near host tip.
|
||||
2. **Accept on advance** — heal Live/tip-hold with `tip > keep` primes HC
|
||||
past the soft fork, clears invent-hold/stream, sets
|
||||
`g_platform_accepted_fork` (hc-fork / begin refuse re-heal).
|
||||
3. **Stream CAP** (`RB_FMV_PLATFORM_KF_STREAM_LIMIT=6`) — same stale fork
|
||||
without escape → force accept.
|
||||
|
||||
**Re-soak watch:** after first post-FMV tip+1 diverge, logs
|
||||
`§115 KF stream ride host tip` and/or `§115 platform fork accepted`; sim
|
||||
advances past keep; no endless `snap applied tick=<keep>`; loading completes.
|
||||
|
||||
@@ -114,6 +114,10 @@ int psx_netplay_rb_post_fmv_heal_eligible(void);
|
||||
/* §111: 1 while heal sticky window is live (invent hold may be tip-lead only). */
|
||||
int psx_netplay_rb_post_fmv_heal_sticky(void);
|
||||
|
||||
/* §115: 1 if this tip+1 fork was accepted (HC primed past it) — hc-fork /
|
||||
* begin must not re-open apply-only heal for it. */
|
||||
int psx_netplay_rb_platform_fork_accepted(uint32_t fork_tick);
|
||||
|
||||
/* §93: 1 if tick sits in the last FMV media bout / settle tail (or DESYNC
|
||||
* hold). Begin/follow/hc-fork must not open episodes that load there.
|
||||
* §97 MEDIA_KF (default on): returns 0 for media-range — episodes allowed. */
|
||||
|
||||
@@ -693,6 +693,9 @@ static void np_try_hc_fork_recovery(uint32_t fork_tick)
|
||||
return;
|
||||
if (g_np.local_slot != 0)
|
||||
return; /* initiator side only */
|
||||
/* §115: tip+1 soft fork already accepted — stay Live. */
|
||||
if (psx_netplay_rb_platform_fork_accepted(fork_tick))
|
||||
return;
|
||||
/* §64: do not bookkeep persist while an episode / tip-hold / load is
|
||||
* in flight. Previously fork_tick advances during tip-extend rereplay
|
||||
* started the persist clock, so tip-extend abandon → Live opened a
|
||||
|
||||
+139
-15
@@ -216,6 +216,8 @@ static void rb_clear_post_fmv_heal_sticky(const char *why);
|
||||
static void rb_post_fmv_platform_nondet_enter(uint32_t keep_tick, uint32_t fork_tick,
|
||||
uint32_t live_sim, const char *why);
|
||||
static void rb_clear_post_fmv_platform_nondet(const char *why);
|
||||
static void rb_post_fmv_platform_accept(uint32_t through, uint32_t fork,
|
||||
const char *why);
|
||||
static int rb_post_fmv_heal_eligible(void);
|
||||
static int rb_fmv_media_active(void); /* §96 — used by ownership budget during FMV */
|
||||
|
||||
@@ -452,6 +454,10 @@ static uint32_t g_post_fmv_heal_loop_count;
|
||||
static int g_post_fmv_platform_nondet;
|
||||
static uint32_t g_post_fmv_platform_keep_tick;
|
||||
static uint32_t g_platform_kf_next_sim;
|
||||
/* §115: KF stream opens while still pinned at keep_tick (livelock counter). */
|
||||
static uint32_t g_platform_kf_stream_count;
|
||||
/* §115: tip+1 fork accepted (HC primed past it) — refuse re-heal/stream. */
|
||||
static uint32_t g_platform_accepted_fork;
|
||||
|
||||
/* §100: recent FMV media snap CRCs — prefer choose_load ticks we already
|
||||
* sealed, and let probe_match confirm without a ring edge-case miss. */
|
||||
@@ -579,6 +585,9 @@ static uint32_t g_last_begin_mismatch = 0xffffffffu;
|
||||
* MEDIA_KF this often (sim ticks) so both peers ride the host timeline
|
||||
* through loading instead of Live-walking a forked tip+1. */
|
||||
#define RB_FMV_PLATFORM_KF_IV 16u
|
||||
/* §115: same keep_tick re-stream limit — beyond this, prime HC past the
|
||||
* tip+1 fork and clear invent-hold (Win↔Linux loading-screen livelock). */
|
||||
#define RB_FMV_PLATFORM_KF_STREAM_LIMIT 6u
|
||||
/* MotK TipHold: quiet window so press→release→D-pad coalesce in one episode.
|
||||
* §27: seal slack uses library default (2) so Live may invent tip+1..tip+2
|
||||
* during tip-hold — FORCE0 parked presentation at the tip (mini delay-sync).
|
||||
@@ -936,18 +945,24 @@ static void ownership_exit_to_live(uint32_t tip, uint32_t frontier,
|
||||
"psxrecomp: rb ownership Live tip=%u frontier=%u (%s) — no TipHold\n",
|
||||
(unsigned)tip, (unsigned)frontier, why ? why : "?");
|
||||
fflush(stderr);
|
||||
/* §109/§114: apply-only heal converged — keep invent OFF (all leads) and
|
||||
* stream KF through tip+1. §111 sticky alone only holds when lead>0, so
|
||||
* the tip-starved peer invents into platform nondet (Win↔Linux soak).
|
||||
* Do not lockstep RELEASE here. */
|
||||
/* §109/§114/§115: apply-only heal converged. First pin at the soft-fork
|
||||
* keep → invent OFF + KF stream. Once a later host-tip KF advances past
|
||||
* the keep/fork, accept the timeline (§115) instead of re-pinning forever. */
|
||||
if (g_post_fmv_heal_kf) {
|
||||
uint32_t fork = g_last_begin_mismatch;
|
||||
if (fork == 0xffffffffu)
|
||||
fork = g_post_fmv_heal_fork_tick;
|
||||
g_post_fmv_heal_kf = 0;
|
||||
g_fmv_core_match_streak = 0; /* need fresh CONFIRM after Live walk */
|
||||
rb_post_fmv_platform_nondet_enter(tip, fork, tip,
|
||||
"post-FMV heal KF Live");
|
||||
if (g_post_fmv_platform_nondet &&
|
||||
g_post_fmv_platform_keep_tick > 0u &&
|
||||
tip > g_post_fmv_platform_keep_tick) {
|
||||
rb_post_fmv_platform_accept(tip, fork,
|
||||
"heal Live past platform keep");
|
||||
} else {
|
||||
rb_post_fmv_platform_nondet_enter(tip, fork, tip,
|
||||
"post-FMV heal KF Live");
|
||||
}
|
||||
}
|
||||
if (g_stash_begin_valid && g_rb &&
|
||||
g_stash_begin_epoch == rnet_rb_get_epoch_id(g_rb)) {
|
||||
@@ -1873,6 +1888,44 @@ static void rb_clear_post_fmv_platform_nondet(const char *why)
|
||||
g_post_fmv_platform_nondet = 0;
|
||||
g_post_fmv_platform_keep_tick = 0u;
|
||||
g_platform_kf_next_sim = 0u;
|
||||
g_platform_kf_stream_count = 0u;
|
||||
}
|
||||
|
||||
/* §115: accept a tip+1 platform fork — prime HC past it, drop invent-hold /
|
||||
* KF stream, and refuse re-heal for that fork tick. */
|
||||
static void rb_post_fmv_platform_accept(uint32_t through, uint32_t fork,
|
||||
const char *why)
|
||||
{
|
||||
uint32_t prime = through;
|
||||
if (fork > prime)
|
||||
prime = fork;
|
||||
if (g_b.hc && prime > 0u)
|
||||
netplay_hc_prime_after(g_b.hc, prime);
|
||||
if (fork > 0u)
|
||||
g_platform_accepted_fork = fork;
|
||||
else if (through > 0u)
|
||||
g_platform_accepted_fork = through;
|
||||
g_request_post_fmv_heal = 0;
|
||||
g_post_fmv_heal_kf = 0;
|
||||
g_platform_kf_stream_count = 0u;
|
||||
rb_clear_post_fmv_platform_nondet(why ? why : "§115 platform accept");
|
||||
rb_clear_post_fmv_heal_sticky(why ? why : "§115 platform accept");
|
||||
if (g_fmv_unmatched_desync)
|
||||
rb_clear_fmv_desync_hold(why ? why : "§115 platform accept");
|
||||
psx_netplay_hc_fork_recovery_clear();
|
||||
fprintf(stderr,
|
||||
"psxrecomp: rb §115 platform fork accepted through=%u fork=%u "
|
||||
"(%s) — invent unlocked; no re-heal for this tip+1\n",
|
||||
(unsigned)through, (unsigned)fork, why ? why : "?");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
int psx_netplay_rb_platform_fork_accepted(uint32_t fork_tick)
|
||||
{
|
||||
return (g_platform_accepted_fork != 0u &&
|
||||
fork_tick == g_platform_accepted_fork)
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
|
||||
/* §109/§97: arm host keyframe for media-range OR requested post-FMV heal. */
|
||||
@@ -5246,15 +5299,23 @@ static void ownership_on_post_match(uint32_t tip)
|
||||
fflush(stderr);
|
||||
ownership_clear_chain_budget();
|
||||
/* §109/§114: heal KF reached tip with no confirmed ahead — still
|
||||
* converged; keep invent off + KF stream (do not RELEASE). */
|
||||
* converged; keep invent off + KF stream (do not RELEASE). §115: if the
|
||||
* pin already advanced past the original keep, accept instead. */
|
||||
if (g_post_fmv_heal_kf) {
|
||||
uint32_t fork = g_last_begin_mismatch;
|
||||
if (fork == 0xffffffffu)
|
||||
fork = g_post_fmv_heal_fork_tick;
|
||||
g_post_fmv_heal_kf = 0;
|
||||
g_fmv_core_match_streak = 0;
|
||||
rb_post_fmv_platform_nondet_enter(tip, fork, tip,
|
||||
"post-FMV heal KF tip-hold");
|
||||
if (g_post_fmv_platform_nondet &&
|
||||
g_post_fmv_platform_keep_tick > 0u &&
|
||||
tip > g_post_fmv_platform_keep_tick) {
|
||||
rb_post_fmv_platform_accept(tip, fork,
|
||||
"heal tip-hold past platform keep");
|
||||
} else {
|
||||
rb_post_fmv_platform_nondet_enter(tip, fork, tip,
|
||||
"post-FMV heal KF tip-hold");
|
||||
}
|
||||
}
|
||||
/* §61: discard any stashed BEGIN for this episode (rexmit) so Live does
|
||||
* not reopen it. */
|
||||
@@ -6248,6 +6309,8 @@ void psx_netplay_rb_cold_reset(void)
|
||||
g_post_fmv_platform_nondet = 0;
|
||||
g_post_fmv_platform_keep_tick = 0u;
|
||||
g_platform_kf_next_sim = 0u;
|
||||
g_platform_kf_stream_count = 0u;
|
||||
g_platform_accepted_fork = 0u;
|
||||
g_last_good_bb_pc = 0;
|
||||
}
|
||||
|
||||
@@ -7456,6 +7519,21 @@ int psx_netplay_rb_begin_rewind(uint32_t mismatch_tick, int slot)
|
||||
|
||||
if (!g_rb || !s)
|
||||
return 0;
|
||||
/* §115: tip+1 platform fork already accepted — do not re-heal it. */
|
||||
if (g_platform_accepted_fork != 0u &&
|
||||
mismatch_tick == g_platform_accepted_fork) {
|
||||
static uint32_t s_accept_refuse_log;
|
||||
if (s_accept_refuse_log != mismatch_tick) {
|
||||
fprintf(stderr,
|
||||
"psxrecomp: rb begin REFUSED mismatch=%u — §115 platform "
|
||||
"fork already accepted\n",
|
||||
(unsigned)mismatch_tick);
|
||||
fflush(stderr);
|
||||
s_accept_refuse_log = mismatch_tick;
|
||||
}
|
||||
g_request_post_fmv_heal = 0;
|
||||
return 0;
|
||||
}
|
||||
/* Prefer tip-extend over refusing while an episode is already open.
|
||||
* Span-cap TipHold commit leaves the session inactive — fall through to
|
||||
* open a fresh episode for this mismatch (symmetric with peer). */
|
||||
@@ -8563,16 +8641,19 @@ static void begin_follower(uint32_t epoch, uint32_t mismatch, uint32_t load, uin
|
||||
}
|
||||
}
|
||||
|
||||
/* §114: initiator re-opens apply-only MEDIA_KF while platform nondet is
|
||||
* armed and cores still disagree — keeps peers on the host timeline. */
|
||||
/* §114/§115: initiator re-opens apply-only MEDIA_KF while platform nondet is
|
||||
* armed and cores still disagree. Prefer host *current* tip when HC is stuck
|
||||
* on the known tip+1 fork so the pin advances; cap same-keep streams. */
|
||||
static void rb_post_fmv_platform_kf_stream_poll(void)
|
||||
{
|
||||
RNetSession *s = sess();
|
||||
uint32_t sim;
|
||||
uint32_t fork = 0u;
|
||||
uint32_t stream_mm;
|
||||
int local;
|
||||
int remote;
|
||||
int n;
|
||||
int stale_platform_fork;
|
||||
|
||||
if (!g_post_fmv_platform_nondet && !g_fmv_unmatched_desync)
|
||||
return;
|
||||
@@ -8595,6 +8676,48 @@ static void rb_post_fmv_platform_kf_stream_poll(void)
|
||||
}
|
||||
if (fork == 0u)
|
||||
fork = (sim > 0u) ? sim : 1u;
|
||||
if (g_platform_accepted_fork != 0u && fork == g_platform_accepted_fork) {
|
||||
g_platform_kf_next_sim = sim + RB_FMV_PLATFORM_KF_IV;
|
||||
return;
|
||||
}
|
||||
|
||||
stale_platform_fork =
|
||||
(g_post_fmv_heal_fork_tick != 0u && fork == g_post_fmv_heal_fork_tick) ||
|
||||
(g_post_fmv_platform_keep_tick != 0u &&
|
||||
fork == g_post_fmv_platform_keep_tick + 1u);
|
||||
|
||||
/* §115: HC stays stuck at tip+1 forever (resolved=keep). Streaming that
|
||||
* fork only re-applies keep. Ride host sim so choose_load pins near tip. */
|
||||
stream_mm = fork;
|
||||
if (stale_platform_fork && sim > fork) {
|
||||
stream_mm = sim;
|
||||
fprintf(stderr,
|
||||
"psxrecomp: rb §115 KF stream ride host tip fork=%u→%u "
|
||||
"sim=%u (stale tip+1)\n",
|
||||
(unsigned)fork, (unsigned)stream_mm, (unsigned)sim);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
if (stale_platform_fork) {
|
||||
g_platform_kf_stream_count++;
|
||||
if (g_platform_kf_stream_count > RB_FMV_PLATFORM_KF_STREAM_LIMIT) {
|
||||
uint32_t through = g_post_fmv_platform_keep_tick;
|
||||
if (sim > through)
|
||||
through = (sim > 0u) ? (sim - 1u) : fork;
|
||||
fprintf(stderr,
|
||||
"psxrecomp: rb §115 KF stream CAP fork=%u count=%u "
|
||||
"sim=%u — accept platform tip+1\n",
|
||||
(unsigned)fork, (unsigned)g_platform_kf_stream_count,
|
||||
(unsigned)sim);
|
||||
fflush(stderr);
|
||||
rb_post_fmv_platform_accept(through, fork,
|
||||
"KF stream limit at stale tip+1");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
g_platform_kf_stream_count = 0u;
|
||||
}
|
||||
|
||||
n = g_b.slot_count ? *g_b.slot_count : 0;
|
||||
remote = (local == 0) ? 1 : 0;
|
||||
if (n < 2)
|
||||
@@ -8603,11 +8726,12 @@ static void rb_post_fmv_platform_kf_stream_poll(void)
|
||||
g_post_fmv_heal_loop_count = 0u;
|
||||
g_platform_kf_next_sim = sim + RB_FMV_PLATFORM_KF_IV;
|
||||
fprintf(stderr,
|
||||
"psxrecomp: rb §114 KF stream begin fork=%u sim=%u "
|
||||
"(platform nondet)\n",
|
||||
(unsigned)fork, (unsigned)sim);
|
||||
"psxrecomp: rb §114 KF stream begin fork=%u stream_mm=%u sim=%u "
|
||||
"(platform nondet; stream=%u)\n",
|
||||
(unsigned)fork, (unsigned)stream_mm, (unsigned)sim,
|
||||
(unsigned)g_platform_kf_stream_count);
|
||||
fflush(stderr);
|
||||
(void)psx_netplay_rb_begin_rewind(fork, remote);
|
||||
(void)psx_netplay_rb_begin_rewind(stream_mm, remote);
|
||||
}
|
||||
|
||||
void psx_netplay_rb_pump(void)
|
||||
|
||||
Reference in New Issue
Block a user