Commit Graph

561 Commits

Author SHA1 Message Date
Shokunin cb1e445e46 Dynamic resolution on the render thread: recorded steps, per-frame render cost, render-thread controller
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:51:55 -07:00
Shokunin 26b0537ff2 Render thread: queue the headless presented-image capture
--headless-opengl captured the presented image into the ring every frame
through gl_renderer_capture_display_hires, a sync point, so a headless
run (fp_identity) held the context for most of every frame. The capture
is now recorded at the same point of the frame (gl_renderer_ring_capture)
and done by the render thread; ring readers already sync first. A rect the
GL surface cannot serve is skipped there rather than resolved through a
CPU readback, and ensure_cpu refuses to run on the render thread at all:
its readback would land in the private upload source and mark the CPU
side current without gpu.c's array seeing the pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:49:53 -07:00
Shokunin af0e6a0472 Frontend: [video] render_thread option, vblank boundary, render_thread command
[video] render_thread (default false; PSX_RENDER_THREAD=0/1 overrides,
PSX_RENDER_THREAD_FRAMES bounds frames in flight, default 2) starts the
OpenGL render thread at the first vblank, after the context and every
startup GL call exist. Each vblank then closes a frame right after its
present and before wall-clock pacing, so the render thread draws while
the guest waits. Netplay, frame interpolation, Vulkan and software keep
the synchronous path.

TCP: render_thread reports records, frames produced/consumed, presents
and stale presents skipped, sync points with their recent reasons,
backpressure and render busy time. Display-ring and present-image-ring
readers sync first (the render thread fills them).

config_loader is a BIOS emitter input: OpenBIOS fingerprint regenerated
(tools/regen_bios.sh --config bios/OpenBIOS.toml; the C is unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:49:42 -07:00
Shokunin 96ee5c0650 Round-trip dynamic resolution through launcher settings 2026-10-07 12:44:59 -07:00
Shokunin ecbbb5eceb Add the opt-in dynamic resolution controller, config and telemetry
A step controller (dynamic_resolution.c) lowers or raises the GL internal scale from frame-time telemetry between a floor and the configured ceiling; off unless a title or the player enables it. Tested by dynamic_resolution_test (synthetic load) and the real-GL gl_scale_invariance_test step modes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 12:44:59 -07:00
Matthew Stanley 3a11aea16d Refresh netplay validation against master retaining audited startup cache and local views 2026-10-07 11:59:16 -07:00
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
Matthew Stanley 62ee64d0a3 Merge reviewed validated warm startup cache (PR555)
# Conflicts:
#	runtime/src/mod_packages.cpp
#	runtime/src/mod_runtime.cpp
#	runtime/tests/test_mod_runtime.cpp
2026-10-07 10:51:41 -07:00
Matthew Stanley a99ad54763 Merge reviewed host launch timing scopes (PR551)
# Conflicts:
#	runtime/src/mod_runtime.cpp
2026-10-07 10:48:55 -07:00
Matthew Stanley c6b089b896 Combine controller stack with validated PGXP fixes and current master; regenerate both BIOS backends 2026-10-07 10:01:37 -07:00
Matthew Stanley c124f6ba52 Wire warm preboot readiness and cover cache invalidation contracts 2026-10-07 09:25:56 -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
Matthew Stanley 8ba237ccf5 Retain host launch and mod commit stage timings for TCP diagnostics 2026-10-06 22:46:05 -07:00
Matthew Stanley 6e154bcf03 Preserve Windows UNC roots when persisting launcher paths
Use native path spelling for settings and BIOS/disc sidecars. Add save/reopen regressions for UNC selections.

Beads: beads-eio.3.286
2026-10-06 21:52:36 -07:00
Shokunin 5f72282fa5 Merge remote-tracking branch 'origin/feat/title-rewind-block' into feat/netplay-input-transform
# Conflicts:
#	generated/OpenBIOS.emitter.sha
#	runtime/src/debug_server.c
2026-10-06 19:37:46 -07:00
Shokunin 6f62f560bf netplay: input transforms stay per player online; rollback rows carry rx/ry
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 19:37:35 -07:00
Shokunin 12c5512218 Merge remote-tracking branch 'origin/feat/pad-transform-stage' into feat/netplay-input-transform 2026-10-06 19:35:45 -07:00
Matthew Stanley d66401751e Integrate controller input stack for review with current command index and both BIOS backends 2026-10-06 19:21:51 -07:00
Matthew Stanley 85d4888352 Merge commit 'refs/review/20261006/pr506' into review/pr502-wave-20261006 2026-10-06 19:04:48 -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 c4215396e3 netplay: present a title-chosen local view for each peer
A title whose netplay mode draws every seat's view into one frame (so all
peers keep identical guest state) can now ask the present path to show only
this peer's rectangle of the display: psx_netplay_present_local_view(x, y,
w, h), usually picked from psx_netplay_local_slot(). The GL dual-raster
present shows it from the internal-resolution surface, the software present
crops its staged frame, both at 4:3, and the headless present-image ring
records the same rectangle. The request is host-only (never serialized or
guest-visible), lapses PSX_NETPLAY_LOCAL_VIEW_HOLD ticks after its last
renewal so menus fall back to the full frame, survives rollback replays
without moving its stamp backwards, and is ignored offline. It wins over
[netplay] local_viewport.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 01:05:14 -07:00
Shokunin 812465df58 Let a title block local Rewind (psx_mod_set_rewind_blocked)
A title calls psx_mod_set_rewind_blocked(1) while it is in a mode that must
not be rewound, such as local split-screen multiplayer, and 0 when it ends.
While blocked, opening Rewind is refused with an OSD note, no history is
captured (the ring keeps what it has; a capture already due is dropped and an
open panel closes unloaded), and a title-allowed direct Rewind shortcut is not
in force: its button is not claimed and reaches the guest pad / title
transform as if Rewind were off. Netplay already refuses Rewind on its own.
The block clears at every mod/session start, so a title that never calls it
is unchanged.

The direct-allowance decision (allowed, and for Rewind: enabled and not
blocked) is now one pure helper, psx_hotkey_direct_active, used for both the
claim and the shortcut press, so an unclaimed Rewind button is never a
one-button shortcut (with Rewind off it falls back to Select + button rather
than popping the "Rewind is off" note on every press).

Tests: psx_hotkey_pad_test covers the allowance and a block taking effect
mid-press; rewind_toggle_combo_test guards the capture/open gates and reset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:44:18 -07:00
Matthew Stanley 66482a7cd8 Add opt-in netplay content negotiation with a backward-compatible LAN protocol
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 22:52:52 -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
Shokunin 91d780bc0a Let a title claim a direct host shortcut; add a debug host-pad layer
psx_mod_allow_direct_shortcut(PSX_MOD_SHORTCUT_*) lets a host shortcut
bound to one controller button act on that button alone. Without it a
one-button binding means Select + button, like the legacy encoding, so a
title can default to a one-button binding safely whether or not its mod is
enabled. While allowed (Rewind: while Rewind is enabled) the runtime claims
the host button: it never reaches P1's guest pad, and a claim made while it
is held lasts until release. Allowances clear at every mod session start.
Multi-button bindings behave as before.

game.toml [controller] direct_shortcut / direct_shortcut_button lets the
title default that shortcut to one button and tells the launcher to capture
it as one button (RECOMP_LAUNCHER_HAS_DIRECT_ASSIST_BIND). No title id is
checked anywhere.

Debug: set_input {"layer":"host", buttons, lx..ry, lt, rt} arms a
virtual P1 gamepad that feeds stage 1 of the offline input path (so sources,
title transforms and trigger values see it) and shortcut polling. A plain
set_input override still wins. Headless runs with the layer armed resolve
P1 through the same path and poll Rewind and the fast-forward latch; the
Rewind pause loop keeps the debug endpoint live and runs without a window.

Binding semantics and the claim latch are pure (psx_hotkey_pad.h) and
covered by psx_hotkey_pad_test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:25:17 -07:00
Shokunin 82bc90dff2 Give a title pad transform the host pad of a digital-presented player
A digital presentation folds the sticks onto the D-pad and centres them,
so a transform on a digital player (the default for many titles) never
saw the stick. The transform decides what the guest sees, so for a
digital stage-1 pad with no controller source its frame is now the host
pad: real sticks and buttons without the stick->D-pad fold, type still
DIGITAL (new PadExtHooks.host_pad, capture_pad_slot_view). The output is
pre-filled with the stock pad and a decline delivers it, so pass-through
stays the stock folded digital bytes (mod_pad_transform_run takes the
stock pad). Analog pads, sources and guarded frames are unchanged.

Tests: pad_external_input_test (digital player: frame has the real lx and
unfolded buttons, decline and pass-through deliver the stock digital
bytes, no host-pad query for analog / guarded / source ports),
mod_pad_transform_test (decline returns the stock pad, output pre-filled
from it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:24:54 -07:00
Matthew Stanley d247ce8b88 Add opt-in netplay local viewport width sites, fixed aspect and native-wide per-camera views
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 20:20:18 -07:00
Shokunin a4d1f31487 Add a title pad transform stage to external offline input
psx_mod_set_pad_transform(player, &PSXModPadTransform) registers stage 2b
of pad_external_input: after the physical pad and any controller source,
before the mouse policy. The transform sees the resolved pad plus the
port's host extras (gamepad present, LT/RT 0..255 from SDL, unthresholded)
and may rewrite buttons, sticks and the presented controller type, e.g. a
NeGcon whose I/II come from the triggers. Output is pre-filled as a
pass-through, validated (struct size, ranges, type within allowed_types)
and replaced by neutral when invalid; detaching or a mod/session reset
owes one neutral release frame. initial_type sets the boot/hotplug type.

The resolver stays pure: host extras arrive through a new capture hook and
the transform through another, both covered in pad_external_input_test.
Under the input guard the transform runs on zero triggers and its output
is neutralized. A NeGcon result resets the mouse policy rather than letting
it overwrite the I/II bytes. Offline only: netplay, resim, selfcheck replay
and plain debug overrides never reach it.

With no transform registered every pad is bit-identical to before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:36:34 -07:00
Shokunin 514cf5deda Carry the NeGcon type through PsxNetPad and one shared SIO apply
PsxNetPad type 3 is NeGcon, packed lx = twist, rx = I, ry = II, ly = L
(the rollback row's stick view carries twist and L). Every decoder accepts
up to PSX_NETPAD_TYPE_MAX instead of clamping at JogCon, and normalization
keeps NeGcon pressures exact (only twist gets the centre deadzone).

psx_pad_apply_to_sio() is now the one PsxNetPad -> SIO path for offline
sampling, netplay delay/rollback apply and selfcheck replay, so a type
added once reaches the guest the same way everywhere. Selfcheck replay now
matches offline sampling on multitap seats with the analog-on-tap hack.
psx_netplay_normalize_pad moves to a pure TU so tests link the real one
instead of a mirror. Pins recomp-net to the branch that keeps type 3.

Other titles: pads never carry type 3, so SIO bytes are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:28:13 -07:00
Shokunin 1db61e768b config: a title default for the offline multitap
[controller] multitap = false in game.toml keeps offline play at two
standalone pads for a title whose game has no multitap support but whose
netplay seats more players (players still sets the netplay seat count).
settings.toml [controller] multitap and the launcher toggle still
override it. Without the key nothing changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:19:47 -07:00
Shokunin 2388a5ff7f Merge remote-tracking branch 'origin/master' into feat/jogcon-controller
# Conflicts:
#	runtime/src/main.cpp
2026-10-05 14:51:54 -07:00
Shokunin 775fb3b646 Merge remote-tracking branch 'origin/master' into feat/mod-local-pad-sticks
# Conflicts:
#	runtime/src/main.cpp
2026-10-05 14:50:46 -07:00
Matthew Stanley 6f9bdd94f2 Resolve controller source and mouse policy in one ordered external-input layer
Mouse policy now folds onto the resolved pad (source included) instead of a discarded capture; no-policy path does no mouse polling.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 13:49:35 -07:00
Beman b5566c7b25 Support optional held mouse input policies for local P1
(cherry picked from commit 00ee1f40b6)
2026-10-05 13:49:35 -07:00
Matthew Stanley 78da432f1e Merge origin/master into pr497
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:39:19 -07:00
Matthew Stanley a6674e6629 Merge remote-tracking branch 'origin/master' into landtmp/495
# Conflicts:
#	runtime/CMakeLists.txt
#	runtime/src/main.cpp
2026-10-05 13:24:03 -07:00
Shokunin f3801ba10b mods: read local host sticks for presentation-only plugins
psx_mod_read_local_pad_sticks(player, out[4]) returns the mapped local
stick axes (lx, ly, rx, ry; 0..255, centre 128) without touching the
SIO sample, so a presentation plugin (a look-around camera) can read the
right stick even when the game selected a digital pad. It returns 0 and
centred axes for an invalid or disconnected player, in netplay, and
during rollback resimulation; peer input is never presentation input.
The debug-server axis override feeds it for deterministic tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 13:11:51 -07:00
Shokunin b44c72349d Test JogCon steering, hotplug and live input 2026-10-05 12:57:31 -07:00
Shokunin 3df760f524 Add JogCon input selection and hotplug handling 2026-10-05 12:57:31 -07:00
Shokunin 52c6d758a6 Add JogCon SIO controller support 2026-10-05 12:57:10 -07:00
Matthew Stanley 3733764362 Merge origin/master into land/pr495 2026-10-05 10:11:51 -07:00
Matthew Stanley 029629ff89 Merge origin/master into land/pr494 2026-10-05 10:11:43 -07:00
Matthew Stanley fe42da2744 Merge release/native-rendering-20261003 into master
Keeps both lines: master's PGXP session, draw-distance clamps, masked rejects
and saturated-winding NCLIP; the release's render-pass kit additions, verified
media/disc extents, timeline/present rings, cull-scale sites. Overlay ABI v30.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 19:27:02 -07:00
Matthew Stanley 64cab80377 openxr: PSX_OPENXR_ENABLE env var, log the 4.6 context switch; document threading and loss
Bare PSX_OPENXR env still works but is deprecated (collides with the CMake option name).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 11:11:21 -07:00
Matthew Stanley f0b920dd65 Merge branch 'review/pr495-fix' into review/pr497-fix
# Conflicts:
#	runtime/CMakeLists.txt
#	runtime/include/mod_controller_source.h
#	runtime/include/mod_plugins.h
#	runtime/runtime.cmake
#	runtime/src/main.cpp
#	runtime/src/mod_controller_source.c
#	runtime/tests/test_mod_controller_source.c
2026-10-04 11:03:38 -07:00
Matthew Stanley b1899a2f51 Merge branch 'review/pr496-fix' into review/pr497-fix
# Conflicts:
#	runtime/src/debug_server.c
2026-10-04 11:03:22 -07:00
Matthew Stanley a407f7af89 fov_scale: honour settings.toml [video] (game.toml < settings.toml < env), round-trip on save
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:55:58 -07:00
Matthew Stanley 2cc8dcb317 mod controller source: neutral release on reset, once-per-frame sample, policy-routed type
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-04 10:46:04 -07:00
Matthew Stanley b6a659ca4a Merge origin/master into review/pr494-fix
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:43:41 -07:00