[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>
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>
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.
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>
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>
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>
[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>
Reconciled with #470 (PGXP): gpu.c precise vertices take PGXP only under geometry correction and count it, then native-wide edge recovery; the PGXP triangle stat stays PGXP-only. Stubs and tests from both kept; stamps recomputed.
Master moved the textured-dot test stubs into gpu_exec_stubs.inc; the PGXP stubs move there too. pgxp_note_rect_bypass stub takes (int). Stamps recomputed.
1982e7dc included recomp_net/host_relay.h unguarded, so PSX_NETPLAY=OFF builds fail to compile (optional_netplay_auth caught it).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Hook every GPR-writing ALU op; rebase onto the 11-bit GP0 field. Spider-Man ORs clip flags into SXY2 before storing it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A renderer that keeps a screen X as SX << 16 tests the right edge against
a lui-held W << 16 and the left edge with bltz on the shifted value. No
explicit [widescreen.cull] kind fits either: bltz_sites compares the whole
register with -margin, and a lui at a screen_x site was a build error.
screen_x_sites now also takes
lui rt, W -> rt = (W + margin) << 16
bltz x, outside -> taken while SX < -margin (x = SX << 16)
Both are the identity at 4:3. The helpers are defined for native code and
for overlay shards; their math is in ws_cull_edge.h. The two prototypes are
written only for a config that lists screen_x_sites, so the generated code
of every other title is unchanged.
A failed start printed "built without recomp-net, or bind/peer invalid" for every cause. A player whose system held the UDP port read first that the build had no netplay.
The library answers a refused bind, a listen address it cannot read and a peer address it cannot use with the same -1. main.cpp now does those steps again (it reads the listen address as the library does, looks up a name, binds without address reuse) and reports the system's answer. The sentence names a cause only when the system does: address in use, access denied (a port range Windows keeps for Hyper-V or WSL, a port below 1024 elsewhere), address not available. Any other error gets the number and the system's text. The peer address is named only when the listen address opened and the peer address cannot be read. The build is named only when it has no netplay.
The sentences are in netplay_exit_reason.c with unit cases; a source guard checks the wiring in main.cpp.