Commit Graph

1480 Commits

Author SHA1 Message Date
Matthew Stanley a423f74f7c tests: pgxp_session builds on MinGW (no POSIX setenv/unsetenv)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 19:36:57 -07:00
Matthew Stanley 40af8a428c Merge master into feat/pgxp
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.
2026-10-02 19:30:59 -07:00
Matthew Stanley 30a4072c25 Merge master into feat/max-detail
Stamps recomputed with tools/bios_emitter_fingerprint.cmake after #480's restamp.
2026-10-02 19:22:24 -07:00
Matt Stanley bb5284bf78 Merge pull request #459 from Alexbeav/up/interp-refused-game-text-2
interp: keep interpreting through game text that dispatch refuses
2026-10-02 19:21:42 -07:00
Matthew Stanley 54826826a6 tests: define the draw-distance clamp flag in the refused-game-text fixture
#459's fixture predates #468; fixture_link stubs the undefined data symbol as a function, which reads non-zero and aborts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 19:21:09 -07:00
Matt Stanley 921d0b021d Merge pull request #467 from RetroPortingToolKit/feat/vs-split
GL: texture window per vertex; opt-in batching across texture windows
2026-10-02 19:20:52 -07:00
Matt Stanley adf2b8a01c Merge pull request #461 from Alexbeav/up/launcher-quit-keeps-settings
launcher: keep settings changed and dismissed with quit
2026-10-02 19:20:48 -07:00
Matt Stanley 0347edd577 Merge pull request #455 from Alexbeav/up/settings-paths-relative
runtime: keep a portable game folder portable (relative settings paths)
2026-10-02 19:20:44 -07:00
Matt Stanley a1a755c7d6 Merge pull request #453 from Alexbeav/up/interp-cop0-before-charge
interp: read cop0 before the instruction's own cycle charge
2026-10-02 19:20:39 -07:00
Matt Stanley fa7105db9f Merge pull request #481 from RetroPortingToolKit/fix/mdec-never-decoded-snapshot
mdec: keep "never decoded" never across a snapshot load
2026-10-02 18:45:50 -07:00
Matt Stanley 6b9a2d49ac Merge pull request #482 from RetroPortingToolKit/fix/bundle-tinycc-license
release: ship TinyCC's LGPL-2.1 notice with the bundled tcc
2026-10-02 18:30:02 -07:00
Matt Stanley 32464ef6f0 Merge pull request #458 from Alexbeav/up/dma-gpu-list-cpu-hold
dma: hold the cpu while a kicked gpu linked-list walk runs
2026-10-02 18:25:35 -07:00
Matthew Stanley 04375fd453 release: ship TinyCC's LGPL-2.1 notice with the bundled tcc
Closes #474. The win64 binary zip carries no license file; stage the notice beside tcc.exe and in licenses/, and make the zip verifier require both.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:49:13 -07:00
Matthew Stanley 439423af03 mdec: keep "never decoded" never across a snapshot load
Fixes the false FMV flag after every snapshot load made before the first video (#475 cause 1); v1 payloads still load. Drops the unread host-frame stamp.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 15:44:09 -07:00
Matt Stanley 973d93a907 Merge pull request #456 from Alexbeav/up/bios-scph5500-5501-2
bios: add the SCPH-5500 and SCPH-5501 profiles
2026-10-02 15:35:49 -07:00
Matt Stanley 7f72d7ed7b Merge pull request #452 from Alexbeav/up/changethread-self-clears-pc
traps: clear pc after a same-thread changethread
2026-10-02 15:35:45 -07:00
Matt Stanley eff6000d18 Merge pull request #454 from Alexbeav/up/cmake-ccache-windows-only
cmake: only look for ccache.exe on windows hosts
2026-10-02 15:35:38 -07:00
Matt Stanley 00121e5def Merge pull request #463 from Alexbeav/up/sdl-main-guard-standalone-test
tests: let the sdl_main guard skip the stand-alone fullscreen test
2026-10-02 15:35:34 -07:00
Matt Stanley 641537be82 Merge pull request #473 from RetroPortingToolKit/fix/unsplit-shared-hud
Netplay: show complete shared timers in both unsplit views
2026-10-01 16:44:43 -07:00
Matthew Stanley 5e413cbd84 netplay: duplicate shared HUD counters into both unsplit views 2026-10-01 16:43:56 -07:00
Alex Vanderveen 1982e7dcb5 netplay: host relay for online rooms (amends §108 "online is always SFU")
An online room this build hosts asks the lobby server for transport "host"
(match_caps.relay): the host carries the match on its own UDP port and
guests dial it; the server's relay (SFU) is the fallback when a guest's
probe fails (recomp-net-server WS_LOBBY.md "Host relay"). The mechanics are
recomp-net's recomp_net/host_relay.h, pinned here (lib/recomp-net b0751b7);
this engine's own lobby-client copy gets the same glue as rnet_lobby_client:
the cap (emitted only when asked), the launch's transport ->
PsxLobbyJoinInfo.transport_host (force_input_relay 0; the host accepts
first / hubs instead of dialling the guest's LAN address), each seat's
published path / path_fresh, host_relay_step() from psx_lobby_pump, and
unmap on leave / disconnect.

psx_netplay: transport_host takes the LAN / hub path instead of the "MotK
online needs the SFU" rule. main.cpp: relay_host_get/set + relay_status
for recomp-ui (Network Settings / MATCH SETTINGS / ROOM "Match Relay"),
transport_host on the launch and into PsxNetplayConfig, and the
host==guest-advertise SFU inference skipped on a host launch; all under
RECOMP_LAUNCHER_HAS_HOST_RELAY so older recomp-ui pins still build.

Compile-checked against workspace recomp-ui 58604b0 (MOTK scratch
configure: full build and link).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 19:10:30 -04:00
Alex Vanderveen 35d604ab80 netplay: matches the Retro hub negotiates -- ingest_launch and --netplay-query
The hub holds the lobby seat; the game settles everything itself
(retcomm-launcher docs/NETPLAY_HANDOFF.md):
- psx_lobby_ingest_record replays the hub's seat/room/launch messages
  through handle_server_json, so fill_launch answers as in-game.
- --netplay-query answers what this build's lobby would send: disc_fp,
  set_ready (BIOS offer), start (default caps; settled from a room).
- set_ready/start builders and the host start-caps settle are factored out
  unchanged and shared by in-game PLAY and the query.
- A handed-off match ends the process (the hub holds the room).

Two CTR processes from records, local relay: all 80 live digests equal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 19:10:30 -04:00
Matthew Stanley 2163035e9a netplay local viewport: projection renderer, hi-res half present, state gate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 16:02:08 -07:00
Matthew Stanley 881c94a869 widescreen: netplay local viewport keeps the display's pixel aspect
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:30:39 -07:00
Matthew Stanley 3b41a81365 netplay: debug-server input override drives headless peers
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:07:43 -07:00
Matthew Stanley fa74d5aa72 widescreen: auto_ui_squash admits small HUD pieces stacked on the front rank
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 12:22:05 -07:00
Shokunin dd5fdec6bb Add opt-in draw-distance clamps ([[draw_distance.clamp]])
Many PS1 renderers drop a primitive whose depth index falls past the end
of their ordering table. Raising that limit can write past the table, so
a title can now list such guards in game.toml with the register that
carries the index and the last safe value. While a trusted mod has called
psx_mod_set_draw_distance_clamp(1), generated main-EXE code clamps that
register before the guard runs, so far geometry is kept in the farthest
slot instead of popping in later.

- Off by default and reset at every session start, so netplay and every
  title that lists no sites run unchanged; with no sites the generated
  code and declarations are byte-identical.
- Main executable only: the full instruction word is the guard,
  generation fails on a mismatch or a load-delay hazard, captured
  overlay code keeps its own code (the sites are not part of the overlay
  config identity), and the dirty-RAM interpreter applies the clamp
  where the game's text image holds the listed word.
- Compatibility: code_generator.cpp is a codegen-hash input, so the
  codegen hash and the overlay-cache tag change for every title, sites
  or not. Savestates from earlier builds are refused, and overlay shards
  rebuild once on first visit. Generated code and behaviour are
  unchanged for a title without sites or with the switch off.
- Tests: draw_distance_codegen_test (config rules, emission, guards,
  declarations, overlay identity) and draw_distance_interp_test (store,
  switch, interpreted guards); the session-reset guard covers the switch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:36:48 -07:00
Matthew Stanley acb2e2c05e widescreen: auto_ui_squash admits backing panels enclosing front-rank HUD
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 11:23:44 -07:00
Matthew Stanley 4ddb7b3ca9 widescreen: auto_ui_squash corrects untextured HUD quads with their frames
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 11:19:45 -07:00
Matthew Stanley 85c88d269c widescreen: auto_ui_anchor = "in_place" squashes each HUD run about its own centre
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 11:13:30 -07:00
Shokunin 8630d3a6f8 PGXP: precise culling as a mod option; the mod as a title's one switch
With every drawn vertex precise, a title can still show cracks where the game
culled a face on its integer winding. R4's road emitter runs NCLIP on each
far row and skips rows whose native height rounds to 0. Natively their
neighbours meet at the same integer y. With PGXP they sit at their exact y,
and the skipped row becomes a strip of sky across the road beyond the start
gantry, at 4K and in 2P. tri_mixed cannot see this: the missing face draws
no triangle.

Precise culling (DuckStation's "PGXP culling", minimal footprint):
- While geometry correction is armed, gte_nclip computes the exact
  determinant of the three SXY register shadows (pgxp_gte_nclip_precise:
  live, current words, the GPU's own truncation agreement and tolerance).
  When its sign is nonzero and differs from the integer MAC0's, MAC0 takes
  that sign, with the rounded exact doubled area (at least 1) as magnitude.
  FLAG keeps the integer overflow bits.
- It changes guest-visible MAC0, so it is a `culling` option of
  psx.enhancement.pgxp, false in the builtin, with no [video] key, so netplay
  (which clears every mod) never runs it. It needs geometry correction.
  It is held off in every pass compared against another execution: the
  speculative and replay passes, and the whole overlay shadow diff
  (psx_overlay_shadow_diff_active), interpreter pass included.
- Counters whenever geometry correction is armed: nclip_precise,
  nclip_disagree (exact sign differs: the culled-face crack exposure),
  nclip_corrected. TCP pgxp {"culling":0|1}; env PSX_PGXP_CULLING.

Session arming in one place (src/pgxp_session.cpp, psx_pgxp_session_arm):
main.cpp's renderer setup now calls the same code the test drives. The arming
takes the mod request (reads and clears it), so a session with an empty plan
cannot inherit an earlier session's request even if the reset were skipped.
pgxp_session_test now links the real mod runtime, the builtin plugin and the
builtin manifest, and covers:
- a default-on override;
- a netplay clear, with and without the reset;
- the off switch;
- the options;
- env overrides;
- pgxp_mod_only.

[video] pgxp_mod_only (game.toml, default false): for a title that ships
PGXP through the mod, the mod is the one switch. The [video]
geometry_correction / perspective_texturing / pgxp_cpu_mode values are not
applied, from game.toml or the player's settings.toml. The launcher also
hides its Perspective textures row (has_geometry_precision = 0). That row
showed "off" while a default-on mod corrected textures, and it could keep
texture correction on after the player switched the mod off.

geom_correction also reports texture_correction and the culling switch.

R4, Helter Skelter: 28.7% of NCLIPs disagree in sign. With culling, the
ladder is gone in same-frame 4K captures (1P straight and crest, 2P VS), and
the game emits about 24% more triangles. Its packet buffers peak at 60%.
fp_identity over 12000 frames: stock, PGXP off, and PGXP on with culling off
are IDENTICAL; with culling on, the RAM writes differ from the attract race
on, while cyc/mmio/mc agree throughout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 06:02:52 -07:00
Shokunin 5970e30ddf PGXP: keep rectangles and out-of-window projections precise, not mixed
Two cases that could still draw a triangle with precise and native corners:

- The rectangle shortcut bypass now needs all four vertices of an
  axis-aligned textured quad to be dataflow-precise. A quad with only some
  precise corners, such as a CPU-built sprite with one corner copied from
  SXY, keeps the shortcut and counts as rect_partial; two triangles would
  have mixed precise and native corners. R4's facade quads are fully
  precise (rect_partial 0 in every R4 run).
- Under preserve-projection, RTPS now applies the GPU's truncation window
  itself (pgxp_ppp_accept): an exact projection outside it is not
  shadowed, the vertex keeps the IR path's shadow, which always agrees, and
  it draws precise instead of being rejected to native at the GPU
  (ppp_window_fallback counts these). The exact math is skipped while the
  hooks record nothing (pgxp_active(): speculative passes).

Also:
- The prepare_precise_triangle comment no longer claims a native neighbour
  can only disagree by the sub-pixel fraction. Under preserve-projection it
  can disagree by up to the window.
- gpu_textured_dot_nw_shift_exec_test links with -dead_strip on Darwin,
  as isc_store_test does. GNU --gc-sections kept it from linking on macOS,
  so the rectangle cases never ran there. The test now covers no, one and
  all four precise corners.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 06:02:26 -07:00
Shokunin a8a75cd353 PGXP: draw precise axis-aligned textured quads as triangles
A textured quad whose four packet vertices form an axis-aligned rectangle in
integer screen space and in UV takes the 2D rectangle shortcut
(gr_draw_textured_rect), which draws the native integer position with no
perspective. That is right for a CPU-built sprite, but a GTE-projected world
quad can land on such a rectangle too: a facade seen straight on. Its
neighbours are drawn precise, so at a high internal resolution the shortcut
left a background-coloured seam along the shared edges. On R4's Helter
Skelter start straight it showed as an L-shaped sky line along a building
panel at 4K, with tolerance off, both with and without preserve projection.

When geometry or texture correction is on and any of the quad's vertices
resolves to a dataflow-precise position (pgxp_probe_precise_vertex: the same
decision as pgxp_get_precise_vertex, not counted), the quad is drawn as its
two triangles like any other world quad. A CPU-built sprite has no dataflow
shadow and keeps the shortcut. With PGXP off nothing changes. geom_correction
counts the bypassed quads (rect_bypass).

Tests: gpu_textured_dot_nw_shift_exec_test gains the quad case (PGXP off,
on without a precise vertex, on with one); pgxp_test checks that the probe
does not count; gpu_gp0_history_guard_test's gpu.c stubs gain the two new
pgxp entry points.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 04:24:54 -07:00
Shokunin dd867215af PGXP: dataflow-only geometry and preserve-projection precision
Two opt-in [video] keys for titles whose build carries the PGXP hooks, both
live-tunable through the TCP pgxp verb. Defaults keep today's behaviour.

pgxp_position_fallback (default true). false skips the position-cache tier
in pgxp_get_precise_vertex and stops gte.cpp filling it. At hook-build
coverage the cache only hands unrelated 3D fractions to CPU-built 2D
polygons (a HUD needle, menus). Beetle and DuckStation leave their vertex
cache off by default.

pgxp_preserve_projection (default false). true makes RTPS/RTPT shadow the
exact projection, from the unshifted MACs and a true divide
(pgxp_project_precise), instead of the GTE's integer-IR one. That removes
the residual wobble of near geometry. Guest SXY, MAC0 and FLAG are
untouched. Only sf=1 vertices with no IR, SZ3 or divide saturation qualify,
and the rest keep the IR path. The exact position can sit a little below the
guest integer or more than a pixel above it, so truncation agreement becomes
the window -4 < precise - native < 5 px, a sanity bound over the IR path's
own error (on R4 every on-screen vertex falls within -1.9 .. +2.6 px). A
packet half at or beyond the GTE saturation limit must still agree exactly.
The tolerance clamp now measures the offset both ways. [widescreen]
precise_nclip reads the same shadows, so in a title that sets both, its
branch sign follows the exact projection too.

Observability: geom_correction reports both switches, ppp_produced, and
geometry-corrected triangles split into all-precise, mixed and native. The
mixed share is the mesh-cracking exposure of G1.1.

Tests: pgxp_test (fallback off, window edges, saturation, two-sided
tolerance, the exact projection and its qualifiers, triangle census);
gte_register_access_test (RTPS/RTPT guest state equals the oracle with the
mode on, and the shadow is the exact projection); video settings test
(defaults, parsing, type check). gpu_gp0_history_guard_test's gpu.c stubs
gain pgxp_note_triangle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 04:24:54 -07:00
Shokunin 67da069f9c GL: texture window per vertex; opt-in texture-window batching
The OpenGL textured program read the GP0(E2h) texture window from a
uniform, so every window change ended the open textured batch (batch
reason 5). Titles that tile far textures with per-primitive windows pay
for that in draws: Ridge Racer Type 4's split screen changes the window
about 515 times a game frame and drew about 180 batches, against 17 with
batching on. On the native-wide path every batch that reaches the margins
is drawn again into the wide surface; under heavy load on an M4, 2P with
widescreen at Match display ran at 39-43 guest VBlanks/s and 1P at 50,
against 50-58 and 57 with batching on.

The window now rides in each textured vertex (a_twin, the E2h low 20 bits
as one float) like texpage and CLUT already do, and the shader decodes it
there; the uniform and the window-replay queue's copy of it are gone.
With the default unchanged, batches still split at every window change,
so every vertex carries the batch's window and the image is the same as
before: the new test's oracle passes on the unmodified renderer too, with
the same digests at 1x, 4x, 9x and in the windowed 9x/18x mode.

[video] texture_window_batching = true (game.toml only, default off) lets
primitives with different windows share a batch. The image is the same:
an opaque batch draws its colour in one painter-ordered pass and
semi-transparent primitives are still drawn one per batch. While mask
checking is on the window stays a batch key, because an opaque batch
fixes the stencil for its STP=1 texels after its colour pass.
PSX_GL_TEXWIN_BATCH=0|1 overrides it for a run and the TCP command
gl_texwin_batch switches it live. Software and Vulkan are unchanged.

Tests: gl_scale_invariance_test gains mode "twin" (alternating windows
over opaque, semi-transparent, set-mask, mask-check and bilinear prims,
into the native-wide margins): off and on give the same native VRAM,
frame at S and wide surface, on draws 17 batches instead of 46 and flushes
only for the 5 mask-check window changes. Each run also checks an oracle
that does not depend on the renderer: raw rects through all four windows
into a 4-bit and a 15-bit page must give, pixel for pixel in the native
VRAM and at the centre of each pixel at S, the texel the PS1 window rule
picks from the VRAM as read back. A decode or packing error both settings
share fails it (checked with (v_twin >> 11) and with off_y left out of the
packed window). video_enhancement_settings_test checks the key's default
and opt-in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 04:15:01 -07:00
Shokunin 2ddb2e0ec4 Let a title build its one runtime as the PGXP hook flavor
psxrecomp_add_game_runtime gains a PGXP option and forwards it to
psxrecomp_add_runtime_target, which already supports a PGXP primary
(-DPSX_PGXP=1, overlay flavor 2, published flavor file, no _pgxp suffix and no
clone). Until now a title could only get the hook flavor through
PSX_PGXP_VARIANT's side-by-side clone, or by leaving a bare PGXP in the
forwarded tail, where an earlier multi-value argument such as
CODEGEN_SETUP_SOURCES or GEN_FULL_GLOB swallowed it as a file name.

The generated C already carries the PGXP_*() hook sites, so a title's
committed generated/ does not change. Default unchanged: titles that do not
pass PGXP build the base flavor as before.

game_runtime_pgxp_test runs the real function body under cmake -P with the
runtime target stubbed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 02:56:05 -07:00
Shokunin 6d905e81bd Keep the PGXP mod's activation through renderer setup
psx.enhancement.pgxp did nothing at boot. Its activation armed geometry and
texture correction, then main.cpp's renderer setup, which runs after
activation, applied the [video] baseline and switched both back off. Only the
[video] keys could turn PGXP on.

The activation now records a request (pgxp_mod_request), cleared at every
session start in reset_mod_owned_presentation(). The renderer setup arms PGXP
from the [video] baseline OR the request (pgxp_session.h); the validation env
overrides (PSX_GEOMETRY_CORRECTION, PSX_PERSPECTIVE_TEXTURING,
PSX_PGXP_CPU_MODE) still win. The g_video_* values stay the player's
settings, so the mod never leaks into a launcher seed, and a netplay session,
whose plan is cleared, keeps the [video] keys alone, as before.

No change for a title whose mod is off. pgxp_session_test drives the real
builtin activation and the resolver in main.cpp's order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 02:55:14 -07:00
Alexandros Mandravillis bf5995a427 tests: let the sdl_main guard skip the stand-alone fullscreen test
test_window_fullscreen.cpp is a separate test program with its own main(). It includes SDL_main.h and is built with SDL_MAIN_HANDLED. The single-owner guard sdl3_main_single_include counts every file under runtime/tests, so it has failed since that test was added.

Name the file as a stand-alone program. Every other file under runtime/src, runtime/include and runtime/tests is still held to the one-owner rule.
2026-10-01 11:36:35 +03:00
Alexandros Mandravillis 67e9b4cf42 interp: keep interpreting through game text that dispatch refuses
When straight-line interpretation reaches a clean page, the interpreter
hands the PC back to static dispatch. If that PC is game text whose live
bytes differ from the boot EXE, dispatch refuses the compiled code and
enters the interpreter again, which hands back one instruction later. A
page of such text cost about a thousand dispatch round trips.

This happens during the retail BIOS intro on profiles whose shell runs
interpreted in RAM (the SCPH5552 profile has no shell seeds). In a game
whose boot EXE later owns that RAM, every shell instruction took the
round trip; on one PAL title the intro ran at 17 fields/s on the host
instead of 42.

Straight-line flow now keeps interpreting while the next PC is game text
that psx_game_text_native_ok() refuses, and re-tests every instruction,
so it hands back at the first PC dispatch accepts.

interp_refused_game_text links the production interpreter into a fixture:
from a dirty page into refused text, it hands back once and dispatch runs
the compiled code at the first accepted page. Before this change the
interpreter returned at the first clean page. A control checks that a
clean page outside game text is still handed back at once.
2026-10-01 09:39:57 +03:00
Alexandros Mandravillis 5a787e56a2 interp: say what compiled code defers in the cop0 sample comment
Compiled code defers its base charge to the block boundary (GCC/Clang
builds). The comment said it batches all its charges to the boundary,
which is broader than what the code does. Comment only.
2026-10-01 09:34:16 +03:00
Matthew Stanley 53521866b4 SDL3: separate Windows desktop borderless and exclusive fullscreen 2026-09-30 23:30:28 -07:00
Alexandros Mandravillis ff4be21c90 bios: add the SCPH-5500 and SCPH-5501 profiles
The v3.0 Japanese (SCPH-5500, 09/09/96) and US (SCPH-5501, 11/18/96)
retail BIOS images join SCPH-1001, SCPH-101 and SCPH-5552, so every v3.0
region (J, A, E) has a profile.

Both images match SCPH-1001 v2.2 byte for byte in the kernel,
ROM [0x80, 0x18000). SCPH-5501's reset vector is identical too; SCPH-5500's
differs in 24 bytes. The shell differs in both. So each profile is
SCPH1001.toml with its own identity (name, id, rom, sha256 pin, stem): the
copy windows and install slots are kernel properties and carry over
unchanged. The shell runs through the dirty-RAM interpreter, as for
SCPH5552.

Each image gets its own seed list, derived by the same rule as
phase2_ghidra_seeds_SCPH5552.json: the SCPH-1001 corpus filtered to seeds
whose 64-byte ROM window is identical in both images (534 kept, 569
dropped), plus the two architectural vectors and 6 A0/B0/C0 kernel-table
targets. The files carry only addresses, labels and rationales, plus the
SHA-256 of both ROMs.

- psx_bios_known_images.h: CRC-32 FF3EEB8C (SCPH-5500) and 8D8CB7E4
  (SCPH-5501), both 512 KiB. A build that does not link these backends
  builds one from the player's own dump as a loadable module, like
  SCPH-5552, and the netplay lobby can name the image.
- main_cli.cpp: map SCPH5500 / SCPH5501 dumps to their profiles.
- build_cli.py: package both profiles with the CLI framework.
- docs/BIOS_SELECTION.md: list them among the module-built images.
2026-10-01 09:28:13 +03:00
Matthew Stanley 757790debe Keep large screen-space composites anchored as one group 2026-09-30 21:38:17 -07:00
Matthew Stanley 7c7133fbb4 Integrate MMX6 adaptive renderer with current framework master
Preserve current segmented dispatch, active-plan mod hooks and software scale limits. Extend function filters through the active plan, retain the last-store pointer with overlay ABI 25, and keep default config fingerprints stable. Refresh BIOS emitter stamps after byte-identical regeneration and reconcile regression fixtures.
2026-09-30 20:23:16 -07:00
Alex Vanderveen efcb48fbcb bios fingerprint: compute it with cmake -P, not a bash found on PATH
The windows-2022 release job accepted the committed backends in the step
shell (Git Bash) and refused them at configure: runtime.cmake ran the bash
fingerprint through whichever bash find_program() located, and that
environment hashed a byte-identical tree differently. The fingerprint is now
tools/bios_emitter_fingerprint.cmake, run with the configuring cmake itself
on every platform; the shell script is a thin wrapper around it. Same digest
shape as before, so existing stamps stay valid (verified on an LF tree and
an autocrlf clone).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 20:49:23 -04:00
Alex Vanderveen f180a32ec1 bios: commit the OpenBIOS and SCPH-1001 backends; releases link both
Decision (Alex, 2026-09-30): the recompiled BIOS carries the same risk as
the recompiled game, which titles already commit, so the retail backend is
compiled in rather than built on the player's machine. The retail image is
still never shipped: the runtime needs its data at run time and accepts only
the exact image the backend was built from, so the player supplies their
own dump as before.

- generated/{OpenBIOS,SCPH1001}_{full,dispatch}.c and their .emitter.sha
  stamps are tracked (.gitignore un-ignores exactly those); regenerated with
  the current emitter.
- bios_emitter_fingerprint.sh no longer hashes the ROM image: the profile's
  SHA-256 pin stands for it and the emitter refuses any other image, and CI
  has no dump, so hashing it made every CI configure read "stale".
- runtime.cmake: the staleness check covers every LINKED stem and
  -DPSXRECOMP_BIOS_STALE_FATAL=ON makes a stale stamp fail configure.
- game-release.yml: no CI-side OpenBIOS emission (generate_openbios.sh is
  gone); configure with BIOS_STALE_FATAL and assert both backends linked.
  check_generated.sh asserts the submodule carries both backends tracked
  and no dump is tracked anywhere.
- The player-side module build stays for a known image a build does not
  link (SCPH-5552).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 20:27:41 -04:00
Matthew Stanley ca14a118f0 fix(runtime): grow software present buffers for adaptive widths 2026-09-30 17:11:39 -07:00
Alex Vanderveen 170370a440 launcher: prepare a retail BIOS from the wizard with progress, not at Play
A buildable dump used to verify as usable and then block at Play behind a
modal while the module compiled. Now:

- ae_bios_verify reports a buildable, not-yet-cached dump as needs_regen,
  and the runtime wires recomp-ui's new bios_prepare_with_progress job
  (ae_bios_prepare) whenever the toolchain is present and no Generate host
  is: the launcher runs the build as a progress job from the wizard's
  "Prepare BIOS" button or the Play prompt, re-verifies, and resumes the
  wizard. Generate & rebuild is never offered for a BIOS in a bundled build.
- psx_bios_module.c gains a progress sink fed from the builder's output
  lines (dump / emit / compile / self-check / published map to stage
  percentages with readable messages); run_command streams lines on both
  platforms.
- The launch-time build stays as the fallback for --bios / --no-launcher.

Requires recomp-ui 9f86c49 (GameInfo.bios_prepare_with_progress).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 20:10:57 -04:00
Alex Vanderveen 60919f5a87 bios: build a retail backend from the player's own dump as a loadable module
Bundled releases link OpenBIOS only; retail-BIOS-derived C never ships.
"Bring your own BIOS" now works without it: when a dump matching a shipped
profile (psx_bios_known_images.h) is selected, the runtime builds that
backend on the player's machine with the overlay toolchain the release
already carries, caches it, and loads it as one more registered backend.

- runtime/include/psx_bios_module.h: the module contract. An overlay-style
  self-contained shared library (no imports from the executable) exporting
  psx_bios_module_{abi,codegen_hash,init,backend}; reaches the runtime only
  through OverlayCallbacks plus a new PsxBiosModuleCallbacks table (traps,
  dirty-RAM/kernel-bless probes, fntrace, log_probe) and pointer aliases of
  the globals the generated dispatcher touches. Its #defines rewrite the
  emitter's own extern lines, so the generated C compiles unchanged.
- runtime/include/psx_bios_module_glue.c.inc: module-side forwarders and the
  four exports, compiled after overlay_dispatch_preamble.c.inc.
- runtime/src/psx_bios_module.c: host side. Cache path
  <exe>/cache/bios/<os-arch>/bm<abi>_<codegen hash>_f<flavor>/<STEM>_<crc>,
  ABI + codegen-hash gated load, callback fill, and a blocking build via
  overlay_toolchain/bios_module_build.py (gcc via compiler.txt or PATH,
  else tcc), then psx_bios_register().
- psx_bios_backend.c: the registry is now a mutable table seeded from the
  CMake-generated psx_bios_builtin_registry by a constructor, with
  psx_bios_register(); every existing walker keeps working.
- main.cpp: validate_bios_for_launch acquires a module (announcing a first
  build) before declaring a mismatch; discovery accepts a buildable dump;
  the launcher verify reports it usable ("ready" / "compiled on first
  launch") with no Generate & rebuild; the BIOS row shows whenever the
  toolchain is present; bundled_only respects module support.
- emitter: the CPS-marker constructor is not emitted in a module build.
- overlay_api.h: OverlayCallbacks gains a struct tag;
  overlay_loader_callbacks() exposes the host table before loader init.
- tools/bios_module_build.py (ships in the toolchain): identity + profile
  SHA-256 gate, staged emitter tree, emit, three-TU compile, ctypes
  self-check, atomic publish. release_stage.py stages psxrecomp-bios, every
  bios/*.toml, the seeds and the builder into overlay_toolchain/.
- Tests: runtime/tests/test_bios_module_host.c against three fake modules
  (good / wrong ABI / wrong hash) on real dlopen; recompiler/tests/
  test_bios_module_build.py builds the bundled OpenBIOS end to end and reads
  the descriptor back; guards extended.

Verified on Twisted Metal 4 (bundled build + staged toolchain, headless):
first launch with --bios SCPH1001.BIN builds and loads the module and boots
on image=SCPH-1001; the second launch loads it from cache.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 19:26:29 -04:00
Matthew Stanley 9fc5b50d19 Merge remote-tracking branch 'origin/master' into test/netplay-bios-wire-20260930 2026-09-30 15:21:24 -07:00