Commit Graph

17 Commits

Author SHA1 Message Date
Matthew Stanley 9a1bfdcee2 Merge PR 554 for local netplay validation; clear new peer state on rematch 2026-10-07 11:21:55 -07:00
Matthew Stanley 7d0a18ebc6 Integrate netplay pad and own-view stack without dropping current-master behavior
Preserve negotiated content and dual-raster pass gates. Retain both fixture assertion sets and HD-off seams. Regenerate both BIOS with actual native emitter. Fix type-only rollback corrections and exclude extra-pad changes from digital-only promote gates.
2026-10-07 11:06:57 -07:00
Shokunin 465f926ecf netplay: confirm against every peer, shed the own view when behind, progress-based stall timeout
Four-peer rollback desynced under load (R4, host behind): the guests
predicted the slow host's pad, hash-confirmed the tick among themselves
through the one shared peer ring, then promoted the host's real pad into
history only (hc-silent promote) while the host simulated it. The host
stayed forked; its recovery episode was then refused as a "zombie load"
behind the guests' (wrongly) agreed tip.

- Hash confirm is a quorum over every occupied peer seat
  (rnet_hc_set_peer_mask / note_peer_from, recomp-net) for three or more
  seats; two seats keep the one-peer chain.
- A peer more than 4 ticks behind the others' inputs sheds its own view
  (psx_mod_render_local_view status FAST_FORWARD, held 60 ticks), so the
  presentation-only pass goes before the simulation slips.
  PSX_NET_LOCAL_VIEW_SHED=0 keeps it.
- The admit-stall watchdog counts time without progress: a remote input tip
  that advances restarts it, so a slow peer is waited for.
  PSX_NET_ADMIT_STALL_MS (20000) and PSX_NET_LIVENESS_MS (1500) configure it.
- Pins recomp-net fix/rollback-span-stall.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 06:59:03 -07:00
Shokunin 33b842e97f netplay: per-player own-view mods, widescreen only inside the local view
A [[plugin]] may declare netplay = "local_view": it only changes what one
player sees. A netplay session now keeps the player's own features whose every
contribution is such a plugin (no writes, overlays or derived discs) instead of
clearing them, without saving state.toml. They activate as usual, but their
hooks run only inside psx_mod_render_local_view (psx_mod_local_view_scope) and
their vblank/savestate callbacks not at all. With such a plan the widescreen
cull margin is the stock 0 in the shared game and this peer's own margin only
inside the sandboxed own-view draw; squash is not used. The canonical frame,
snapshots and digests stay identical on every peer whatever each player chose,
so nothing is negotiated, and each keeps their own aspect.

Tests: netplay_view_mods_test (flag, plan filter, parked hooks, no vblank,
state.toml untouched), ws_local_view_margin_test (margin scope), render-pass
sandbox asserts the scope around a local view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:17:26 -07:00
Shokunin f379771c93 netplay: let a title present its own sandboxed local view
psx_mod_render_local_view() runs a title's draw code in the render-pass
sandbox on a forward netplay frame and keeps the drawn display rect in the
OpenGL presenter's surface only. The authoritative CPU VRAM, guest RAM,
rollback snapshots and digests keep the canonical frame; the presenter shows
this peer's own image. A committed image cancels any local-view crop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:24:17 -07:00
Matthew Stanley d7fb33eb85 Add opt-in CD-DA playlists, media preparers, netplay render passes, hidden OpenGL headless and netplay_status
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 22:52:51 -07:00
Matthew Stanley 8403bdf9a5 Merge branch 'review/pr493-fix' into review/pr496-fix
# Conflicts:
#	runtime/include/mod_plugins.h
#	runtime/src/main.cpp
#	runtime/src/render_pass.c
#	runtime/tests/test_gl_readback_region.c
#	runtime/tests/test_gte_register_access.cpp
#	runtime/tests/test_render_pass_sandbox.c
2026-10-04 10:57:48 -07:00
Matthew Stanley 95aa6e68b6 Merge review/pr492-fix into review/pr493-fix
# Conflicts:
#	runtime/src/debug_server.c
#	runtime/src/render_pass.c
#	runtime/tests/test_render_pass_abort.c
2026-10-04 10:45:21 -07:00
Matthew Stanley 40c2d6c82f render passes: a refusal always records a non-null reason
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:44:08 -07:00
Matthew Stanley 0ae34cd0de Merge remote-tracking branch 'origin/master' into review/pr492-fix
# Conflicts:
#	runtime/include/gpu_gl_renderer.h
#	runtime/src/debug_server.c
#	runtime/src/render_pass.c
#	runtime/tests/test_render_pass_abort.c
#	runtime/tests/test_render_pass_sandbox.c
2026-10-04 10:41:19 -07:00
Matthew Stanley d2c8f03e76 Add guarded native draw replay, motion interpolation and stable world filtering 2026-10-03 23:46:25 -07:00
Yves 305b5485b9 render passes: add atomic stereo pairs and scoped camera views
Adapted from the original feature commits, retaining their author credit:
[0a955971](https://github.com/FractalEngineer/psxrecomp/commit/0a95597129cc2ee6d70397a8da9511831575eae4)
[0a4cf21f](https://github.com/FractalEngineer/psxrecomp/commit/0a4cf21fac88ef425ba0edd25871d7dd20ee0903)
[22bdc9e9](https://github.com/FractalEngineer/psxrecomp/commit/22bdc9e90d14f7a04b79c83b77611c4eb980fef4)
[734977c9](https://github.com/FractalEngineer/psxrecomp/commit/734977c93e80789e9210a262daa35a88f41c40d4)

Source scope and current-master validation: docs/internal/upstream/atomic-stereo-render-views.md

Co-authored-by: Yves <calibratedbeats@gmail.com>
2026-10-04 05:54:05 +08:00
Yves b491a3597f render passes: restore mod callback context after watchdog aborts
Adapted from the original feature commits, retaining their author credit:
[6d44e21d](https://github.com/FractalEngineer/psxrecomp/commit/6d44e21df7ccedd1acbfa31844a53bf8bd8b316e)
[35b209d4](https://github.com/FractalEngineer/psxrecomp/commit/35b209d406c168e14f51bb8bbd549742473c7388)

Source scope and current-master validation: docs/internal/upstream/render-pass-mod-callback-rollback.md

Co-authored-by: Yves <calibratedbeats@gmail.com>
2026-10-04 05:54:03 +08:00
Yves dedbe47c97 render passes: expose refusal and framebuffer failure details over TCP
Adapted from the original feature commits, retaining their author credit:
[257a88b0](https://github.com/FractalEngineer/psxrecomp/commit/257a88b06d26bb99a9e6066b89f839af41090118)

Source scope and current-master validation: docs/internal/upstream/render-pass-refusal-diagnostics.md

Co-authored-by: Yves <calibratedbeats@gmail.com>
2026-10-04 05:54:03 +08:00
Shokunin 825a89a9c5 runtime: keep host stores out of IsC, as DMA is
Only CPU stores are cache-isolated. Mods, the FMV skip, debug pokes, the
bg2d ring fill and the exception sentinel write guest memory from the host;
they now go through psx_host_write_*, which bypasses isc_store the way DMA
does, so a host store inside a FlushCache window reaches memory instead of
rewriting an I-cache tag. The render-pass checkpoint restores the new depth
counter like the DMA depth. isc_store_test covers it (a lane-0 host store in
tag-test mode would otherwise mark a cold line valid).

Docs: the SCPH-1001 residual starts at kernel init 0x598, and without #429
the fix removes 113 of the 126 OpenBIOS flush cycles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:55:26 -07:00
Shokunin d300319b7e Render passes: follow the live 2/8 MiB RAM geometry
Upstream now has one live main-RAM geometry: retail 2 MiB mirrored four
times across the 8 MiB decode window, or 8 MiB unique with the opt-in
8 MB RAM mod (psx_memory.h). memory.c's RAM array is sized for the
largest geometry, so the pass store policy was handed 8 MiB even on a
retail boot, and a store to a mirror (0x80200000..) would have landed in
the unused upper backing bytes instead of folding onto RAM. With the
8 MB map live, the checkpoint copied and restored only the low 2 MiB.

- memory.c passes the store policy psx_ram_live_bytes(), so pass stores
  fold exactly as psx_ram_map_write does outside a pass.
- render_pass.c checkpoints, restores and (PSX_RENDER_PASS_VERIFY)
  hashes memory_get_ram_bytes() bytes; the copy grows if a later session
  boots with the larger map.
- render_pass_sandbox_test: policy and a real pass with 8 MiB live
  (unique addresses up to 0x7FFFFF, all 8 MiB restored), then a retail
  pass folding mirrors again. Restoring a fixed 2 MiB fails it twice;
  folding with the backing size fails it twice. render_pass_guards pins
  the live size in memory.c and in the checkpoint, restore and hash.
- psx_ram_runtime_map_test (upstream's 2/8 MiB test over the real
  memory.c and dma.c) links those files with section GC. The pass paths
  make six more symbols reachable there (the pass flag and store policy,
  the synchronous GPU linked-list walk); its stubs double them, trapping
  if a pass path ever runs. With the macOS-only link gaps stubbed as well,
  the test passes on this branch as on master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:02:48 -07:00
Shokunin 3e262c128d Render passes: unit-test the sandbox (store drops, frozen devices, journal)
The store policy and the CPU side of the out-of-rect VRAM journal move into
render_pass_plan.c as pure functions (render_pass_store_to,
render_pass_vram_policy, render_pass_journal_add/_rollback); memory.c and
gpu_gl_renderer.c only wire them to their arrays and GL copies. Behaviour is
unchanged.

render_pass_sandbox_test covers what the plan's U5a list asked for:
- every device class a pass may not reach (SPU key-on and control, CD,
  timer, other DMA channels, GP1, SIO, memory control, MDEC, expansion,
  KSEG2) is dropped under its class and never delivered, while GP0,
  GP1 DMA mode/info, I_STAT/I_MASK, GPU/OTC DMA and DPCR reach the device;
- a real pass (render_pass.c, psx_cycles.c, timers.c) that makes those
  stores, acknowledges and masks every interrupt, runs 10^6 cycles while
  timer 2 is armed to interrupt every 1000, and changes a timer behind the
  store policy's back: drops counted per class, no device advanced, no
  interrupt raised, RAM, scratchpad, I_STAT/I_MASK, timers and clock
  restored, and the timer interrupts again once time is live;
- fast-forward and backend status refuse the pass without running it;
- VRAM writes inside the rect are allowed, outside ones journaled once
  (covered writes not twice, clipped to VRAM) and rolled back exactly,
  newest first; a full journal or a mode that cannot journal refuses.

Mutations it catches: SPU or CD mis-classed, device service not frozen,
rollback order or entry skipped, I_STAT, timer, RAM or scratchpad restore
removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:02:48 -07:00