mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
97 lines
4.2 KiB
C
97 lines
4.2 KiB
C
#ifndef PSX_SELFCHECK_H
|
|
#define PSX_SELFCHECK_H
|
|
|
|
/*
|
|
* Solo rollback resim self-check (PSX_RB_SELFCHECK=1, offline only).
|
|
*
|
|
* Periodically during normal offline play: snapshot the machine at a safe
|
|
* BB edge, keep playing N ticks while recording the per-boundary pad rows
|
|
* the sampler applied to SIO plus the full netplay digest partitions, then
|
|
* rewind to the snapshot and resim the same rows, comparing digests at every
|
|
* boundary. Any live-vs-resim fork is exactly the class of determinism bug
|
|
* that otherwise only surfaces as a doomed netplay episode in a two-peer
|
|
* soak (SIO pace, GTE fold, present-edge PC, v0 restore, ...).
|
|
*
|
|
* Uses the same machinery as netplay rollback: boot_state raw buffer snaps,
|
|
* netplay_state_digest partitions, RB restore recipe (cycle/IRQ resync, SPU
|
|
* CD FIFO reset, NO cdrom_accelerate, light frontend hook). No recomp-net
|
|
* dependency; fully offline, single process.
|
|
*
|
|
* Env:
|
|
* PSX_RB_SELFCHECK=1 enable
|
|
* PSX_RB_SELFCHECK_INTERVAL=N boundaries between windows (default 600)
|
|
* PSX_RB_SELFCHECK_SPAN=N window length in boundaries (default 32)
|
|
* PSX_RB_SELFCHECK_FAULT=1 corrupt one recorded digest per window to
|
|
* prove the comparator/report path
|
|
* PSX_RB_SELFCHECK_PRIME=N throwaway resims before counted passes
|
|
* (default 1, max 4) — clears live-RECORD ambient
|
|
* PSX_RB_SELFCHECK_MASH=1 synthetic fighter-style button spam on live
|
|
* boundaries (IDLE/SAVE_WAIT/RECORD). Recorded
|
|
* rows replay during resim. Headless-safe.
|
|
* PSX_RB_SELFCHECK_MASH_SEED=N xorshift seed (default 0xC0FFEE)
|
|
* PSX_RB_SELFCHECK_MASH_RATE=N % chance to start a new press/release each
|
|
* boundary when not mid-hold (default 75)
|
|
*
|
|
* Verdict = warm resim#2 vs #3 (peer episode path). Cold #1 vs #2 is dig only.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct CPUState;
|
|
|
|
/* Startup bind (after savestate_configure; needs HLE scheduler for the
|
|
* rewind longjmp). Reads env; no-op unless PSX_RB_SELFCHECK=1. */
|
|
void psx_selfcheck_init(struct CPUState *cpu, uint32_t bios_checksum,
|
|
uint32_t entry_pc);
|
|
|
|
int psx_selfcheck_enabled(void);
|
|
|
|
/* 1 while a window is open (record/replay/load). Offline GPU present stays
|
|
* immediate — full BB-edge present-defer skews clk/tim between warm peers. */
|
|
int psx_selfcheck_defer_present(void);
|
|
|
|
/* 1 while the resim replay is running: skip wall pacer / host audio pump /
|
|
* host CD boost exactly like netplay resim. */
|
|
int psx_selfcheck_resim_active(void);
|
|
|
|
/* 1 during replay: main.cpp must skip live pad sampling entirely (the
|
|
* self-check republishes the recorded rows itself). */
|
|
int psx_selfcheck_replay_input(void);
|
|
|
|
/* 1 during record or replay: main.cpp must skip the mid-frame low-latency
|
|
* input re-sample so pads stay boundary-latched (netplay tick semantics). */
|
|
int psx_selfcheck_input_locked(void);
|
|
|
|
/* Offline pad sampler notes what it applied to SIO this boundary (called
|
|
* from apply_pad_slot_to_sio / apply_input_override_to_sio). */
|
|
void psx_selfcheck_note_pad(int slot, uint16_t buttons, uint8_t lx, uint8_t ly,
|
|
uint8_t rx, uint8_t ry, uint8_t analog);
|
|
|
|
/* 1 when mash owns this boundary's P1 pad word (active-low). Latched once
|
|
* per offline vblank so mid-frame resampling sees a stable word. */
|
|
int psx_selfcheck_mash_override(uint16_t *out_buttons);
|
|
|
|
/* Once per offline vblank boundary, after pad sampling (main.cpp present
|
|
* body). defer_window!=0 postpones opening a new window (e.g. multitap
|
|
* arming still pending). */
|
|
void psx_selfcheck_finish_frame(int defer_window);
|
|
|
|
/* Safe BB-edge poll (beside savestate_poll in interrupts.c): performs the
|
|
* deferred snapshot save. Loads only as a fallback when span-end flush did
|
|
* not run (e.g. headless paths that skip present). Near-free when idle. */
|
|
void psx_selfcheck_poll(struct CPUState *cpu, uint32_t resume_pc);
|
|
|
|
/* After present-body C++ RAII: if a window span just ended, rewind+resume
|
|
* immediately at that VBlank boundary (no post-span BB tail). Longjmps. */
|
|
void psx_selfcheck_flush_load(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* PSX_SELFCHECK_H */
|