Files
psxrecomp/runtime/include/psx_netplay_sched.h
T
Alex Vanderveen b5ef7b86d9 netplay: take the scheduler, input history and hash-confirm from recomp-net
recomp-net now carries the peer-facing rollback modules that used to live in
retcomm-rbengine (RetroPortingToolKit/recomp-net#14). Switch the MotK shims and
psx_netplay_sched.c from rbe_sched_* / rbe_ih_* / rbe_hc_* /
rbe_rb_peer_post_tip_ok to their rnet_* names and recomp_net/ headers, and bump
lib/recomp-net to c2338c6.

The netplay_* / np_sched_* surface the rest of the runtime calls is unchanged.
The snap ring and rbe_mono_ms still come from retcomm-rbengine, which stays at
a7b9850 for now; the three moved-module unit tests link recomp_net directly
instead of reaching it through rbengine. RBE_RB_* env knobs keep their names.

Checked with PSX_NETPLAY=ON: psx-runtime links and the netplay tests pass
against both the current rbengine and the split one (rbengine
refactor/launcher-core), and the binary's 33 scheduler / history /
hash-confirm functions now resolve to rnet_* where they were rbe_*.
lobby_chat_ring_test does not compile on master either (chat_push arity) and
is untouched here.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-24 22:06:27 -04:00

113 lines
4.8 KiB
C

/* psx_netplay_sched.h — MotK facade over recomp-net (rnet_sched_*).
*
* Policy lives in lib/recomp-net. This header keeps the historical
* np_sched_* / PsxNpSchedBridge surface; MotK dig0/FMV/RTT enter through
* gates in psx_netplay_sched.c.
*
* Env knobs: RBE_RB_* (preferred) with MotK PSX_RB_* fallback in recomp-net.
*
* The scheduler's job (design contract, 2026-08-02):
* - keep both peers at the same simulation time (mispredict-driven pacing,
* pcap freeze);
* - keep the delay cushion FULL (consume at wire = sim, produce at
* wire = sim + D — see np_sched_wire_for_sim; prediction is an emergency
* brake, not a steady state);
* - spend prediction only on genuine runway starvation, and recover back
* to zero prediction afterwards (cushion rebuild);
* - resolve D from measured link latency (np_sched auto-delay) instead of
* paying for phase error with prediction.
*/
#ifndef PSX_NETPLAY_SCHED_H
#define PSX_NETPLAY_SCHED_H
#include <stdint.h>
/* Full session types only when recomp-net is linked. Stub builds keep opaque
* pointers so this header stays includable with PSX_NETPLAY=OFF. */
#if defined(PSX_HAS_RECOMP_NET)
#include "recomp_net/session.h"
#else
typedef struct RNetSession RNetSession;
typedef struct RNetSessionStats RNetSessionStats;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Live pointers into psx_netplay.c state (session may repoint on restart). */
typedef struct PsxNpSchedBridge {
RNetSession **session;
int *input_delay; /* committed D, ticks */
int *input_prediction; /* P cap, ticks */
int *local_slot;
/* Sticky for the session (from launch cfg / PSX_NET_FORCE_TURN). */
int force_turn; /* 1 = ICE relay-only — auto-delay floor applies */
} PsxNpSchedBridge;
void np_sched_bind(const PsxNpSchedBridge *bridge);
/* Clear session-scoped pacing/invent state (cushion rebuild, pcap freeze,
* timesync debt, tip cadence). Soft-return rematch reuses the process; without
* this, a mid-match episode can leave cushion_rebuild/debt armed and freeze
* the next session after lockstep armed. Called from np_sched_bind. */
void np_sched_reset_session(void);
/* sim→wire CONSUMPTION mapping. §44 real delay (default): guest tick T plays
* the wire row T; the local sample taken at admit(T) is stored at wire T+D
* (rnet_session_prepare_local_tip), so a press surfaces D ticks later and the
* peer's row for T arrived ~D ticks minus transit before it is needed — a
* real cushion. PSX_RB_ZERO_DELAY=1 restores the legacy mapping (T plays
* wire T+D, the sample taken the same admit: zero local latency, zero
* cushion, permanent pred_depth 1 — the pre-§44 behavior). */
uint32_t np_sched_wire_for_sim(uint32_t sim_tick);
int np_sched_real_delay_enabled(void);
/* Mid-session DELAY_SYNC commit → mirror into *input_delay. */
void np_sched_sync_delay_from_session(void);
/* Pre-admit gate, in original np_try_admit_rollback order: tip cadence
* tracking, timesync throttle (live only), lead sampling, runway/phase logs,
* cushion-rebuild clearing, auto-delay resolution. Returns 1 = stall this
* admit (pacing debt), 0 = proceed. */
int np_sched_pre_admit(uint32_t sim, uint32_t wire, const RNetSessionStats *st);
/* Remote row missing at `wire` for `slot`. Returns 1 = stall the admit
* (grace/freeze/cushion wait), 0 = invent hold-last now (*reason_out set,
* telemetry already recorded). */
int np_sched_on_remote_miss(int slot, uint32_t sim, uint32_t wire,
const RNetSessionStats *st, int pred,
const char **reason_out);
/* Remote row present at the consumption wire (gap1 grace paid off). */
void np_sched_note_remote_hit(void);
/* End of a successful admit: leave pcap freeze, flush periodic stats. */
void np_sched_post_admit(int any_invent);
/* MotK-side admit stall tag for barrier logs. Rollback never calls
* rnet_session_try_admit, so rnet last_stall stays "ok" while MotK invent /
* FMV lockstep / wire-hole stalls. Cleared on successful admit. */
void np_sched_set_admit_stall(const char *tag);
void np_sched_clear_admit_stall(void);
const char *np_sched_admit_stall_tag(void); /* "" if none */
/* Reconcile caught a genuine mispredict (published != wire) that rode `age`
* ticks before being caught — feeds the pacing debt of the ahead peer. */
void np_sched_note_mispredict(uint32_t age);
/* Episode boundary (commit/abort): clear the pegged-streak off-guard and arm
* cushion rebuild. (Public alias: psx_netplay_timesync_on_episode_boundary.) */
void np_sched_note_episode_boundary(void);
/* §83 C: after baseline-abort Live realign, allow invent despite absurd
* remote_lead for a short window so recovery can catch up (soak: lead=500
* refuse invent → crawl). Tip-hold ring-age absurd leads stay blocked. */
void np_sched_arm_absurd_invent_catchup(void);
#ifdef __cplusplus
}
#endif
#endif /* PSX_NETPLAY_SCHED_H */