Commit Graph

1032 Commits

Author SHA1 Message Date
Matthew Stanley 72622466f8 Allow audited titles to opt into worker-safe launcher preparation 2026-10-06 23:32:26 -07:00
Matthew Stanley bceadc6124 Add DuckStation-compatible texture pack mod and gameplay dumping
Load modern texpage/texupload PNG replacements independently of DuckStation source. Integrate pack folders and options with mods, preserve native VRAM, and validate GL rendering, format matching, dump safety, and upload invalidation.
2026-10-06 23:24:47 -07:00
Matthew Stanley e4b6ddc99a Require measured host credit before admitting render replay 2026-10-06 23:03:48 -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 20b0ea04bc Honor explicit HUD anchors in projection rendering 2026-10-06 21:49:56 -07:00
Matthew Stanley 8f95b59999 Support checkpointed relocation of packet precision metadata 2026-10-06 20:37:31 -07:00
Matthew Stanley 1d201aa39f Accelerate exact startup file hashing with native host crypto 2026-10-06 20:00:55 -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 04f871f014 Preserve exact packet precision across guarded draw replay 2026-10-06 19:21:43 -07:00
Matthew Stanley 8873093790 Abort render replay before uncheckpointed device reads 2026-10-06 19:19:09 -07:00
Matthew Stanley 8f126c595b Integrate PR 513 retaining current COP2 hooks and regenerate both BIOS backends 2026-10-06 19:13:37 -07:00
Matthew Stanley 85d4888352 Merge commit 'refs/review/20261006/pr506' into review/pr502-wave-20261006 2026-10-06 19:04:48 -07:00
Matthew Stanley b0bb115dd0 Honor HOLD when presenting native replay generations 2026-10-06 18:36:52 -07:00
Matthew Stanley 16d3672526 Add build-selected execution contracts and stateless HLE GTE service 2026-10-06 18:30:50 -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
Matthew Stanley f9c7bb0a1c PGXP: carry precision through GTE-as-multiplier arithmetic and lwl/lwr word copies
Fixes Ape Escape terrain seams: CPU-built subdivision midpoints and lwl/lwr-copied
grid corners drew native next to precise neighbours. Adds pgxp_tri_ring/pgxp_store_ring.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 13:35:43 -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
Matt Stanley d95eed86c2 Merge pull request #541 from RetroPortingToolKit/feat/mod-uncharged-guest-call
Add uncharged guest calls: run a guest function in zero guest time
2026-10-06 11:13:08 -07:00
Matthew Stanley 49fe052a3e Add uncharged guest calls: run a guest function in zero guest time
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-06 09:53:08 -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 3654593e16 Add a rewind_status debug command
Reports whether local Rewind is enabled and open, the title block
(psx_mod_set_rewind_blocked) and the snapshots held, so scripted headless runs
can check that a blocked title captures no history and refuses to open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:49:55 -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 96b2c05c27 Drain queued world batches before wide overlays, bound forced replay spans, sequence presented images
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 23:33:30 -07:00
Matthew Stanley ddd903014f Keep resident packs in memory when the cache is unwritable and record adapter requests in an always-on ring
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 22:52:52 -07:00
Matthew Stanley a734cd9034 Record GPU list CPU holds, per-source exception cycles and recent C0 readbacks in always-on rings
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 22:52:52 -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 ca82734bb8 sio: add the NeGcon (0x23) controller type
SIO_PAD_NEGCON = 3 presents a Namco NeGcon (NPC-101): poll ID 0x23 with
buttons, twist (left X), then analog I, II and L (Mednafen negcon.cpp).
sio_set_pad_negcon() supplies I/II/L per frame like the sticks. The device
has no config mode: any command but 0x42 gets the ID byte with no ACK, and
game bytes in a poll drive no motors. Multitap seats stay digital unless the
analog-on-tap hack is armed; the bulk status block carries the NeGcon frame.

Entering or leaving NeGcon is a device swap, not the DualShock analog
button: a deferred request applies even while the game holds the 0x44 mode
lock, and the swap clears the lock, config latch and motor map. Requests
raised mid-config still wait for config exit.

0x44 now selects the analog mode of the device in the port: a JogCon the
game set to digital returns as a JogCon instead of becoming a DualShock.
The mode lock and that device are guest state, so they join the snapshot
as an appended section (older snapshots still load, unlocked).
pad_status reports negcon and mode_locked per slot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:25:38 -07:00
Shokunin 5abf703694 Drop PGXP shadows on DMA and host stores
A DMA or host store (psx_host_write_*) has no instruction hook, and
validation on read only rejects a shadow whose word changed. A writer
that stores the identical word left the old shadow believed, although
two projections that round to the same integer X/Y carry different
fractions and depth. memory.c now drops the shadow of every RAM or
scratchpad word a DMA or host store touches (pgxp_invalidate_word); the
drop is journaled, so a render pass rolls it back with its other writes.

pgxp_untracked_store_test drives the real memory.c store paths against
the real engine (fails 9 checks without the fix).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:15:50 -07:00
Shokunin 1a90c04c27 Hook coprocessor reads into GPRs in the PGXP shadow
MFC0 and CFC2 overwrite a GPR, but the recompiled code did not hook them
(and neither interpreter hooked MFC0/CFC0), so the register kept the
shadow of whatever vertex it held before. Validation by value cannot
prove provenance when the new word equals the old one. Emit PGXP_ALU
after MFC0 and PGXP_COP2 after CFC2, matching the interpreters' CFC2
hook, and hook MFC0/CFC0 in both interpreters. OpenBIOS regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:15:44 -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
Shokunin a2bbf961ec netplay: expose published seat pads and seat count; unconfirmed load barrier in both modes
- psx_netplay_seat_count() and psx_netplay_sim_pad(seat, out): the pad row
  last published to SIO for each seat at the current simulation tick,
  following delay-sync publication and rollback's sealed overrides, for a
  game hook whose title reads more players than its SIO protocol exposes
  (R4 Link Battle). Host-only cache, never serialized; republished on
  every admitted or replayed tick.
- Load barrier: while a slower peer is still applying a save, neither
  mode waits for confirmation from an already-frozen peer (rollback did
  this already); after mutual ready, both modes resume on a confirmed
  first tick instead of rollback inventing it, so peers cannot run
  different inputs from the identical restored state.

From the R4 Link Battle branch; its headless input probe is dropped
because master already honours debug input on headless peers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:17:22 -07:00
Shokunin 7c6419cbcb mods: game-owned netplay function hooks and filters
Trusted game code can register entry hooks and consuming filters that run
only in a netplay session (psx_game_register_netplay_function_entry /
_filter). They live outside the mod package plan, which every online
match clears, so a title's netplay support survives it. Offline they are
inert unless PSX_GAME_FILTER_OFFLINE_PROBE=1. Reimplemented on master's
entry-filter path from the R4 Link Battle branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:15:09 -07:00
Shokunin 74cb83930a Fix duplicate mixed-hash netplay load apply
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:12:45 -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 9f13dd0bbc openxr: suspend presentation interpolation while a session runs; glDeleteProgram optional
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 13:41:02 -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 19f009600c Merge remote-tracking branch 'origin/master' into landtmp/505
# Conflicts:
#	runtime/tests/test_gte_register_access.cpp
2026-10-05 13:25:10 -07:00
Matthew Stanley b31c40c2ae Merge remote-tracking branch 'origin/master' into landtmp/460 2026-10-05 13:24:39 -07:00
Matthew Stanley 9c88657abc Merge remote-tracking branch 'origin/master' into landtmp/496
# Conflicts:
#	docs/TCP_COMMANDS.md
#	runtime/runtime.cmake
2026-10-05 13:24:20 -07:00