Commit Graph

24 Commits

Author SHA1 Message Date
Matthew Stanley d110d0a423 Integrate current master for reviewed PR597 and retain canonical BIOS stamp 2026-10-15 00:36:07 -07:00
Matthew Stanley dfd4555d09 Include fixed scaled-charge batching profile in netplay compatibility 2026-10-14 23:51:49 -07:00
Shokunin 43afb3bb16 timing: opt-in batching of the scaled CPU charge
With [timing] guest_cycle_scale active, every one-cycle psx_cyc_charge went
straight to psx_cpu_charge and psx_advance_cycles, bypassing the batch the
scale-1 path uses. [timing] guest_cycle_scale_batch (PSX_GCS_BATCH=0/1)
scales the charge in place, with the same fractional carry and order as
psx_cpu_charge, then batches it like the scale-1 path. It flushes at the same
observation points. Default off.

R4 exactness, frame_fingerprint off vs on, 9000 frames each: headless boot
through intro, title and attract; a 1P Grand Prix race; and a 2P VS race.
cyc, mmio, mc and qc are identical on every frame. sp, wr, pc and ws are
identical at the end. The only differences are single-frame VBlank straddles
of wc/sc (never two frames in a row). 0 dispatch misses.

Speed, release builds, races at 60 Hz:
- M4 (macOS sample): psx_cpu_charge 4.3 % -> 0 % of emulation-thread samples;
  busy 46.0 -> 44.4 % (2 pairs).
- 9800X3D: no measurable change (30.0 vs 30.5 %; one core 44.6 vs 44.2 %).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:26 -07:00
Shokunin 7a4a1a004a idle_skip store counters: only audited sites (idle_skip_store_counter_sites)
The detector cannot prove a loop has no later counter-dependent exit, so
the extension now skips only at block-edge PCs the title lists after an
audit. Unlisted sites are never skipped; an empty list disables it. Docs
record R4's v_wait audit as the reference; tests cover unlisted sites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:25 -07:00
Shokunin f2570a8f76 idle_skip store counters: review fixes, exactness from boot, pinning test
- Last-store tracking: memory.c owns the record and writes it only while
  the extension is on (g_psx_track_last_store); main.cpp hands it and the
  host writer (psx_host_write_word) to psx_cycles.c through
  psx_idle_skip_set_store_tracker / _set_host_writer, so psx_cycles.c no
  longer references memory.c (fixes the tests that link one without the
  other).
- Exact from boot: the device distance is now measured from the current
  cycle (devices report it from their last service, up to a few hundred
  cycles behind), and several edges per pass are accepted only together
  with a counter store. Before this, R4's boot diverged at frame 962 (an
  OpenBIOS multi-edge poll and a late VBlank IRQ after a v_wait skip).
- tests/test_idle_skip_store_counter.c: a v_wait trace skips (whole
  passes, counter lowered by the host writer, never to the timeout, lands
  before the event); an extra store, an MMIO read, a decrement of 2, a
  store to MMIO, the option off and no host writer do not.
- generated/OpenBIOS.emitter.sha re-stamped.

R4 frame_fingerprint off vs on, 9000 frames each: boot through intro and
attract, a 1P race and a 2P VS race: cyc, mmio, mc, sp, sc and qc
identical on every frame, 0 dispatch misses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 14:31:25 -07:00
Shokunin 91cd6db705 guest_cycle_scale: one CPU charge for every tier, declarative gate, rollback
Review of #561. Guest time now has two entry points (psx_cycles.h): the
CPU charge psx_cpu_charge() (instruction base, load fudge/region/completion,
i-cache refills, BIOS HLE costs), which applies [timing] guest_cycle_scale,
and the unscaled device advance psx_advance_cycles() (DMA, idle skips,
mul/div and GTE deadline waits). The emitters' block-mode charges emit
psx_cpu_charge; overlay DLLs accumulate it raw and publish through the
cpu_charge callback (was advance_cycles, same slot) into the same host
function, so nothing is scaled at the DLL boundary. The batched
psx_cyc_charge path, the dirty-RAM interpreter, psx_cyc_readmem, i-cache
refills and bios_hle.c all charge through it. At scale 1 it is exactly
psx_advance_cycles.

Gate in psxrecomp: [timing] guest_cycle_scale_gate, RAM predicates judged
at every VBlank edge (deterministic, works online, no mod needed), plus
psx_mod_set_guest_cycle_scale_gate() in mod_plugins.h for custom logic or
to tie the scale to a mod (guest_cycle_scale_gated = true; every mod
session reset shuts it). The carried fraction and both gate states are a
boot_state section (BS_SEC_GCS, written only when the scale is not 1), so
savestates and the netplay rollback snapshot re-simulate the same cycles.
psx_guest_cycle_scale_gate_test pins tier identity, the gates and rollback
re-simulation against the real psx_cycles.c.

OpenBIOS regenerated (emitter stamp); retail SCPH1001 is not.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:41:39 -07:00
Shokunin 1e6e43639a Title timing constant: [timing] guest_cycle_scale (and _gated)
No CPU is emulated: recompiled code charges the guest clock a fixed cost
per instruction. guest_cycle_scale = N charges 1/N of it (instruction,
load, mul/div, GTE latencies, overlay DLL batches) while VBlank, timers,
CD, SPU and DMA keep hardware time, so the game never runs out of frame
time. A title constant in game.toml (1 = faithful, 1..64), never a player
setting; guest_cycle_scale_gated applies it only while the title's mod
opens the gate (psx_guest_cycle_scale_gate_open). PSX_GUEST_CYCLE_SCALE
overrides for testing. A scale other than 1 is folded into the netplay
content fingerprint as a safety net.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 21:41:34 -07:00
Matthew Stanley 2113defcfc Fix overlay Clang exports, PGO, and scaffold cache 2026-09-10 17:23:03 -07:00
Alexandros Mandravillis e9f834da52 cycles: bound idle skip by the SPU sample deadline when IRQ9 is unmasked
The SPU sample event was part of the internal device slicer but not of the
idle-skip observable-event distance, so a poll loop waiting on SPU IRQ9 could
be skipped across several 768-cycle sample boundaries before it could
acknowledge and re-arm. Include the sample deadline in
devices_cycles_to_next_idle_event() when IRQ_SPU is unmasked (mask-gated like
the other sources), expose the distance through
psx_idle_cycles_to_next_observable_event() for tests, and extend
psx_cycle_event_boundaries_test: masked IRQ9 does not bound the skip; unmasked
IRQ9 stops it at the first sample boundary, never across later ones.
2026-08-27 16:26:44 +03:00
Alex Vanderveen 652be7ba02 rollback FMV patches and overlay 2026-08-06 00:52:14 -04:00
Alex Vanderveen ba276624b9 patch bad merge 2026-08-03 05:26:37 -04:00
Matthew Stanley 987c6eeced Revert "Merge pull request #87 from mstan/feat/ui-5p"
This reverts commit e01347cbca, reversing
changes made to 60cb60eee6.
2026-07-31 15:37:57 -07:00
Alex Vanderveen 92efb5c4fd no mods in MP, minor patches 2026-07-29 02:40:50 -04:00
Matthew Stanley e558c971ab runtime: restore native Tomba FMV overlays 2026-07-22 00:35:26 -07:00
Matthew Stanley f1bdefad20 runtime: batch faithful FMV load-cycle charges 2026-07-21 22:23:15 -07:00
Matthew Stanley 0527806ce3 Repair netplay PR rebase for MotK bring-up 2026-07-21 21:38:05 -07:00
Alex Vanderveen 7cf9958135 FMV optimizations 2026-07-21 21:38:04 -07:00
Alex Vanderveen 31015ceab1 feat: launcher polish and recomp-net lobby netplay
Wire MotK-style lobby (recomp-net submodule, WS client, match_caps),
netplay delay-sync, and launcher UX so host sim settings stay aligned
across peers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 21:37:57 -07:00
Matthew Stanley d73dc5f36e runtime: add transactional overlay differential replay 2026-07-19 13:40:03 -07:00
Matthew Stanley fb585541ec opengl: sustain full-rate gameplay and FMV presentation 2026-07-11 14:07:17 -07:00
Matthew Stanley 6da3c34a36 perf(cpu): idle-loop cycle-skip (wait-loop elision)
Detect a side-effect-free poll loop by its repeated same-PC interrupt
checks and, when the window touched no MMIO and issued no stores,
fast-forward guest time to the next internal device event
(vblank/timer/cdrom/dma/sio) in whole loop quanta — bit-exact versus
executing the spins one by one. Off switch: PSX_IDLE_SKIP=0 env or the
idle_skip TCP command; gated off in exception context, precise mode, and
lockstep.

memory.c adds the two always-on gates the skip requires: g_guest_store_count
(bumped at every raw store chokepoint) and g_mmio_access_count (bumped on
every device-page read/write). Any store or MMIO touch in the window
disqualifies it as a pure poll loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 19:38:48 -07:00
Matthew Stanley 496d1dbbc8 runtime: HLE tier wiring + carried instrumentation from the card-load hunt
HLE tier wiring (completes the previous commit — HEAD builds again):
- main.cpp: [runtime] bios_hle/keep_intro consume + settings.toml layer +
  PSX_BIOS_HLE / PSX_BIOS_HLE_KEEP_INTRO env resolution + backend banner;
  boot-turbo window ORed into the turbo predicate; the fast_boot snapshot
  restore/capture path and s_fast_boot_active are removed (deprecated by
  the HLE boot shell-skip); psx_hle_scheduler_set_default call.
- traps.c: psx_hle_scheduler_enabled default now flows from config
  ([runtime] hle_scheduler) with the PSX_HLE_SCHEDULER env winning.
- debug_server.c: hle_dump command (always-on HLE ring query).

Carried instrumentation/state from the MMX6 card-load sessions (kept
deliberately; documented in memory + handoff):
- dirty_ram_interp.c: XOP_RES interp JAL call-resolution probe + xprobe
  watched dump section (emitted first), watch targets.
- overlay_loader.c: probed wrapper around dispatch_call + psx_sljit_call.
- debug_server.c: card_mgr_trace range widen, TestEvent spin-body
  collapse, 64MB response cap.
- interrupts.c: PSX_SAME_THREAD_RESTORE selector (0/1/2; TCB-equality
  hardening candidate).
- memory.c: PSX_POLL_PROOF temp gate (remove when card work resumes).
- savestate.c/.h (new): user save states (F1-F12), HLE-scheduler-gated
  load via psx_scheduler_resume_at; load-crash known, do not use for
  repros yet.
- psx_cycles/autocompile/cycle_testrom: timing-fastpath + exe-path
  session state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:27:57 -07:00
Matthew Stanley 6f7fcdc89b Remove all psxrecomp-v4 naming — rename to psxrecomp throughout
The "v4" suffix was a holdover from iterative project restarts.
There is now one psxrecomp; all identifiers, include guards, cmake
variables, function names, log strings, schema tags, and tool paths
drop the v4 suffix.

Changes:
- PSXRECOMP_V4_ROOT → PSXRECOMP_ROOT (cmake)
- PSXRECOMP_V4_RUNTIME_SOURCES/_INCLUDE_DIRS/_BIOS_GENERATED → no V4
- psxrecomp_v4_add_runtime_target → psxrecomp_add_runtime_target
- PSXRECOMP_V4_*_H include guards → PSXRECOMP_*_H
- "psxrecomp-v4" log/window strings → "psxrecomp"
- Schema version strings in recompiler JSON output
- Tool script hardcoded absolute paths updated

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 21:14:30 -07:00
Matthew Stanley 5d4d4bd30b phase1.0e-a: psx_cycle_count scaffold + cycle-timing arch doc
Scaffold for guest-cycle-driven peripheral timing per
docs/CYCLE_TIMING_ARCH.md. The counter is defined and exposed via
freeze_check, but psx_advance_cycles has no callers yet — counter
stays 0. Validation: zero behavior change.

Files:
- runtime/include/psx_cycles.h: extern uint64_t psx_cycle_count;
  void psx_advance_cycles(uint32_t cycles); uint64_t psx_get_cycle_count(void);
- runtime/src/psx_cycles.c: scaffold body; peripheral hooks empty
  (1.0e-b will add sio_advance, 1.0e-c will add gpu_advance, etc.)
- runtime/CMakeLists.txt: psx_cycles.c added to PSX_SHARED_SOURCES
- runtime/src/debug_server.c: freeze_check exposes psx_cycle_count
- docs/CYCLE_TIMING_ARCH.md: design doc — single cycle clock,
  generic per-block emit (no card-specific paths), MMIO-split codegen
  per explicit user direction, IRQ-pending-vs-CPU-entry separation,
  five-step migration plan (1.0e-a..e)

Validation against 0d15e2b baseline:
- t=20s/30s tx_writes match (1160/5480)
- 4x CROSS succeeds; card txn distribution unchanged (10 reach READ_DATA)
- "MC" bytes still flow at txn 0 bytes 10-11
- psx_cycle_count = 0 throughout (no callers in this slice)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 19:04:11 -07:00