Commit Graph

115 Commits

Author SHA1 Message Date
Alex Vanderveen 67aaae8a75 buiild with ICE 2026-08-07 03:56:04 -04:00
Alex Vanderveen 480fcad652 new build wizard 2026-08-07 01:43:04 -04:00
Alex Vanderveen 94cb3807a9 Merge origin/master into integrate/game-codegen-hooks-into-rollback
Keep rollback/netplay multiplayer routing, dual-raster GL present, and TOC
fingerprints while taking master's CHD support, mod load acceleration,
adaptive widescreen, and geometry/perspective APIs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 22:50:38 -04:00
Alex Vanderveen 652be7ba02 rollback FMV patches and overlay 2026-08-06 00:52:14 -04:00
Matthew Stanley 084d2d4639 mods: clear the staged catalog before restaging it
copy_directory merges, so a mod package deleted from source survived in the
build output indefinitely -- it kept showing on the Mods page and inflated
the release packagers' catalog assertions (Tomba 2 found 7 manifests where 5
exist). Remove the staged tree first; this runs before the game's own
POST_BUILD copy, so game and framework catalogs both land on a clean slate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 10:48:09 -07:00
Matthew Stanley 25d2798037 mods: ship loading-speed mods with the framework, for every game
Loading acceleration is a property of the emulated hardware, not of any
particular disc, so having each title carry its own copy of the same two
manifests and plugins was duplication waiting to drift.

- target game_id "*" now matches every game. An empty target list still
  matches nothing, so a malformed manifest fails loudly as before.
- mods/builtin/packages ships psx.enhancement.fast-loading and
  psx.enhancement.cd-speed: independent host-pacing and CD-timing mods,
  each a free integer multiplier (1..1024) plus a tickbox that uses
  disabled_by to grey out the field it overrides.
- runtime/src/mod_builtin_speed.c registers both activation plugins.
- runtime.cmake stages mods/builtin into every game's output beside its own
  catalog, before the game's own copy, so a title can still override an id.

Titles adopting these should delete their per-game copies; keeping both
would show two of each mod.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 10:40:07 -07:00
Matthew Stanley 67757efac4 feat(runtime): add CHD discs and mod-owned loading modes 2026-08-03 22:32:17 -07:00
Alex Vanderveen 910b998485 mingw build for toolchain to compile netplay 2026-08-03 15:39:52 -04:00
Alex Vanderveen c19618adc6 BIOS handling 2026-08-03 14:44:17 -04:00
Alex Vanderveen ba276624b9 patch bad merge 2026-08-03 05:26:37 -04:00
Alex Vanderveen 804d3094c0 Merge feat/game-codegen-hooks into feat/rollback-netplay.
Keep rollback netplay/runtime authority (dual-raster, snaps, lobby) while
taking local codegen host/CLI/toolchain packaging from game-codegen-hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 05:13:45 -04:00
Alex Vanderveen 7234d347ea Merge upstream/master into feat/game-codegen-hooks.
Keep local codegen/FMV cutover/zlib host work while taking upstream
tests, FPS telemetry, and mod-provider wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 03:29:32 -04:00
Alex Vanderveen 0392b3ff48 rollback scheduler v1 2026-08-02 12:57:00 -04:00
Alex Vanderveen 4ddd2d01b9 rollback patches 2026-08-01 14:13:58 -04:00
Alex Vanderveen db24f79db5 toolchain patch windows 2026-08-01 14:09:49 -04:00
Matthew Stanley c264a704ec debug: generalize Crash Bash boot write watch
Extract the useful diagnostic from PR #13 into an opt-in, title-agnostic boot
write-range trace with TCP-queryable context.

Co-authored-by: NyperYuhgard <93950153+NyperYuhgard@users.noreply.github.com>
2026-08-01 02:15:34 -07:00
Alex Vanderveen 2f99cca345 migrate more tools into psxrecomp for building 2026-08-01 00:32:10 -04:00
Matthew Stanley 987c6eeced Revert "Merge pull request #87 from mstan/feat/ui-5p"
This reverts commit e01347cbca, reversing
changes made to 60cb60eee6.
2026-07-31 15:37:57 -07:00
Alex Vanderveen 0e6416d5b0 Allow BIOS-free setup hosts; defer BIOS C to local generate.
PSXRECOMP_ALLOW_NO_BIOS links an empty backend registry so CI can ship a
launcher without OpenBIOS/SCPH1001 generated C. First-run generate emits
BIOS backends on the user's machine.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-31 17:51:40 -04:00
Alex Vanderveen fe403e6ce1 rollback patches 2026-07-31 17:14:35 -04:00
Alex Vanderveen 2b35b76a56 rollback engine patch 1 2026-07-29 21:44:44 -04:00
Alex Vanderveen 070fc805c4 Merge origin/master into feat/ui-5p.
Keep 5p/ICE netplay host + lobby client; take master's cycle batching,
SDL3 defaults, and dropped vendored lib/recomp-ui.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 20:17:14 -04:00
Matthew Stanley 224147bb07 runtime: select PSX recomp-ui assets 2026-07-28 13:48:08 -07:00
Matthew Stanley 106e31d6e9 Make SDL3 the default runtime backend 2026-07-28 09:22:28 -07:00
Matthew Stanley e4e2aa7a7d runtime: add per-game radial stick response 2026-07-28 00:20:45 -07:00
Matthew Stanley eb262c4b23 feat(mods): let a trusted plugin read its own option values
The manifest schema already carries typed, validated, launcher-rendered,
persisted options ([[option]] boolean/choice/integer), and the launcher
provider already reads them. A trusted activation plugin could not: the
callback takes no arguments, so a plugin was only ever an on/off switch.

That forced a parameterised feature to be modelled as one feature per
value, and `constraint` only expresses ordered_integer WITHIN a feature, so
those pseudo-features could not even be made mutually exclusive. A game
wanting "Widescreen: 16:9 / 21:9" or "Interpolation: 90/120/144/165/240"
had no way to express it as one entry.

psx_mod_option_value(package, feature, option, out, out_size) closes the
gap against the value the player actually committed. It returns 0 with an
empty string when the plan is not committed or the ids do not resolve, so a
caller applies its own default rather than reading "" as a selection. Ids
are explicit because registration is by plugin id alone and the callback
carries no package/feature context.

Also in this commit, from the same investigation:

* Sustained overlay-autocompile failure is now LOUD. After 3 consecutive
  failed runs the runtime prints once to stdout: what failed, the exit
  code, that overlays are staying interpreted and frame times will be far
  worse than the build is capable of, what to check, and the compiler's own
  output tail. Previously the only trace was a `fails` counter reachable
  over TCP, so a wholly-interpreted title presented as "why is this slow"
  rather than as a message. Threshold is 3, not 1, because isolated
  failures (a shard racing a capture rewrite, a transient lock) are
  ordinary and self-heal. Measured cost of the silent case on Tomba!:
  p50 frame period 105ms, vs 3.1ms once shards existed.

* The autocompile child's working directory is printed at startup beside
  cache and captures. Every relative path in overlay_autocompile_cmd
  resolves against it and it comes from game.toml's detected project root,
  so a game.toml staged outside the real root silently repoints the entire
  compile command with no other symptom.

* A build tree whose cache still carries recomp-ui's OFF for
  RECOMP_UI_ENABLE_MODS now says so at configure time. 610234a's seed only
  fires on a fresh cache, and a stale OFF is indistinguishable from a
  deliberate one, so such trees kept producing Mods-less builds across
  reconfigures - the same "reads as a stale build" failure one level up,
  and invisible. The explicit-OFF contract is deliberate so this does not
  override it; it makes the state audible.

Runtime ctest 16/16. Warning verified to fire on a tree configured with
-DRECOMP_UI_ENABLE_MODS=OFF and to stay silent on a fresh configure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 17:33:44 -07:00
Matthew Stanley 5ec343ab4f fix(bios): make the boot-skip flag mean the same thing on every BIOS
`bios_hle` (default on) is the player-facing "skip the BIOS and go
straight to the game" flag, and it did nothing under the bundled
OpenBIOS: choosing OpenBIOS sat the player in the boot animation while
the identical build on retail SCPH-1001 went straight to the game.

Root cause was ordering, not policy. The tier has two axes with
different per-image requirements:

  * boot-skip     needs only `shell_entry_phys`, works under pure LLE
                  (nothing is synthesized — the shell call just returns
                  immediately), so any image exporting it can skip
  * kernel-call    needs `deliver_event_ret`, the kernel's own
                  DeliverEvent `$ra`, or a delivered callback returns to
                  the wrong PC

main.cpp correctly refused the call axis on an image without
`deliver_event_ret` by assigning `bios_hle = false` — and then derived
`boot_skip` from that already-mutated flag. OpenBIOS omits
`deliver_event_ret` (B0 semantics unvalidated) but DOES export
`shell_entry_phys`, so an available skip was cancelled by an unrelated
refusal, and one flag meant two things depending on a BIOS detail no
player can see.

Both axes are now decided by one pure, dependency-free function,
`psx_bios_hle_plan()` (runtime/src/bios_hle_plan.c): the boot decision
reads the REQUESTED `bios_hle`, each axis is gated on only the anchor it
needs, and refusals are reported at startup instead of downgrading
silently. `psx_bios_hle_configure()` clamps `boot_skip` to
`shell_entry_phys != 0` as a backstop so the banner and `hle_dump`
cannot overstate what can fire. The main.cpp local is renamed
`bios_hle_requested` and is no longer written back from the plan — the
`session_reboot` path re-enters that block, so folding a refusal into
the request would have made a netplay rematch differ from first launch.

Also in this pass:

* A BIOS profile's `[runtime]` block was parsed into
  `BiosConfig::runtime` and read by NOTHING, and bios/OpenBIOS.toml
  carried an inert `bios_hle = false` there that read as the reason HLE
  was off on OpenBIOS. It was not. `load_bios_config` now REJECTS
  `[runtime]` in a BIOS profile: a profile states facts about an image,
  never preferences.
* `psx_icache_fastpath_test` had been unbuildable ("redefinition of
  `psx_advance_cycles`" — the test's counting stub vs the header's
  `static inline`), which blocked every runtime test registered after
  it. It now builds with `PSX_OVERLAY_DLL_BUILD=1`, the seam
  psx_cycles.h already provides for a TU supplying its own advance.

Tests: new `bios_hle_plan_test` pins the matrix, including a 64-case
sweep asserting the boot decision is independent of
`deliver_event_ret` and the call decision independent of
`shell_entry_phys`. Runtime ctest 15/15, recompiler ctest 30/30.

Validated on Ape Escape (SCUS-94423) built against this framework with
both backends linked, headless, all four cases:

  OpenBIOS default   bios_boot=skip to game; route=2 fire at vec 0x30000
                     ra=0xBFC06EA8 (the continuation OpenBIOS.toml
                     documents); in-game on screen
  retail default     bios_boot=skip to game; route=2 at vec 0x30000
                     ra=0xBFC0702C; in-game on screen; differs only in
                     bios_backend=HLE (LLE fallback)
  PSX_BIOS_HLE=0     bios_boot=real intro; ring empty (no hook)
  KEEP_INTRO=1       bios_boot=real intro; ring empty

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 16:36:48 -07:00
Matthew Stanley 63d8f88dc5 runtime: group front-layer UI for widescreen 2026-07-27 15:54:23 -07:00
Matthew Stanley 610234a907 fix(launcher): opt in to the recomp-ui Mods view by default
recomp-ui f6395d6 (upstream commit 39a6e4e, 'mods: make launcher integration
opt-in') gates the Mods view behind RECOMP_UI_ENABLE_MODS, which defaults OFF.
That is the right default for a cross-console launcher -- a console with no mod
system should not show an empty Mods tab -- but it is the wrong default here.

psxrecomp ships mod packages as a first-class documented feature
(docs/MOD_PACKAGES.md); Tomba! ships three catalogs and Ape Escape two. With
the option off, a title that already shipped a working Mods panel silently
loses it on its next rebuild: the panel is compiled in, the catalog is staged
beside the exe, and the view simply never appears. It reads as a stale build
rather than a missing flag, which is how it was found.

Opt in from the framework rather than in each game's CMakeLists, so every
title inherits it instead of six repos each needing the same line. Set before
including recomp_ui.cmake so its option() honours the value, and only when the
caller has not already decided, so -DRECOMP_UI_ENABLE_MODS=OFF still wins.

Verified on ApeEscapeRecomp: a clean configure with no extra flags now yields
RECOMP_UI_ENABLE_MODS:BOOL=ON and the compile definition on every launcher TU;
configuring with -DRECOMP_UI_ENABLE_MODS=OFF still produces none. runtime.cmake
is not in codegen_hash_sources.cmake, so the overlay cache tag is unaffected.
2026-07-27 15:24:52 -07:00
Matthew Stanley da093d4374 fix(build): link a BIOS backend only when its generated C provides one
PSXRECOMP_BIOS_STEMS defaults to "OpenBIOS;SCPH1001", so every game link
required a SCPH1001 backend. That backend is compiled from generated C which is
a derivative of a copyrighted Sony BIOS, so it is gitignored and only exists
after a developer regenerates it from their own dump. A checkout that has only
the bundled MIT OpenBIOS -- the documented default, and what a fresh clone gets
-- configured fine and then failed at link with:

    undefined reference to `SCPH1001_psx_bios_backend'

Hit while building Tomba 1, Tomba 2 and MMX6 to validate an unrelated branch;
all three needed -DPSXRECOMP_BIOS_STEMS=OpenBIOS as a workaround.

Filter the stem list to those that actually supply a backend, rather than
flipping the default. Flipping it would silently drop SCPH1001 for developers
who HAVE regenerated it; filtering keeps it fully supported when present and
simply absent when not.

Presence of the files is not a sufficient test. A generated/ tree produced
before the backend-descriptor mechanism existed has both <stem>_full.c and
<stem>_dispatch.c yet defines no descriptor -- exactly the local state that
produced the error above. The check therefore probes for the descriptor symbol
itself, in <stem>_dispatch.c (~1MB, where the emitter puts it) rather than the
multi-megabyte <stem>_full.c, so configure stays fast.

Also report what happened instead of leaving it implicit:
  - STATUS line naming the linked backends
  - STATUS line naming skipped stems with the regen command to fix them
  - FATAL_ERROR, with the OpenBIOS regen command, if no backend resolves at all
    (previously an empty registry would have surfaced as a confusing link error)

Verified: with default flags and a stale local SCPH1001 tree, Tomba 2 now
reports "BIOS backends skipped ... SCPH1001" / "BIOS backends linked: OpenBIOS",
links, and boots.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 12:32:30 -07:00
Matthew Stanley 2696c391b8 feat: add aspect-aware world participation 2026-07-27 10:48:41 -07:00
Alex Vanderveen fbad0be1b9 launcher performance, load state performance, game launch performance
it stops checking the entire PSX disc for full hash check every time the launcher runs, assuming the user's hash checked it when selecting the disc the first time and saving it to settings, so it just validates the file name and size instead, then it shares lifecycle with the launcher and the game to load the game faster, and several optimizations were made to loadstate paths which I think in the end relied on reanchoring host timings to the restored clock that came with the state
2026-07-27 11:03:10 -04:00
Matthew Stanley 6c1bd61a1f feat: derive modded discs from verified stock images 2026-07-25 21:14:27 -07:00
Matthew Stanley 316eaa44a7 feat: add versioned runtime mod packages 2026-07-25 21:14:27 -07:00
Matthew Stanley 4bf868da4f feat(bios): ship OpenBIOS as a runtime dependency 2026-07-25 18:11:57 -07:00
Matthew Stanley 986d8be94c Merge remote-tracking branch 'origin/master' into integrate/openbios-bundle
# Conflicts:
#	recompiler/src/full_function_emitter.cpp
#	recompiler/src/full_function_emitter.h
#	recompiler/src/main_bios.cpp
#	runtime/runtime.cmake
#	runtime/src/main.cpp
2026-07-25 12:31:05 -07:00
Matthew Stanley b0f514c57e feat(bios): pick the BIOS at runtime — OpenBIOS unless the player chose one
Implements docs/BIOS_SELECTION.md on top of the backend ABI. One build
now carries both images and decides at startup, so the per-BIOS build
flavour (and its three uncross-checked restatements) is gone.

  - runtime.cmake takes PSXRECOMP_BIOS_STEMS (default "OpenBIOS;SCPH1001")
    and generates psx_bios_registry.c from it, so the stem list is the
    single source of truth for what a build carries.
  - [runtime] openbios (default true) records whether a title may use the
    bundled image. Not exposed to settings.toml: it is a developer's
    compatibility finding, not a player preference.
  - Selection: an explicit choice that matches a linked image wins;
    otherwise the bundled image; otherwise prompt. A mismatched explicit
    choice is explained and falls back to OpenBIOS when the title allows
    it, instead of dead-ending.
  - validate_bios_for_launch now ASKS WHICH backend an image is, rather
    than checking against one hardcoded identity, and activates it.

Crucially, "no BIOS" means "the player chose none" — not "no BIOS file
was discoverable". The compile-time DEFAULT_BIOS_PATH is no longer
treated as a choice: it made a stray file near the executable produce a
BIOS Mismatch dialog before the bundled image was considered.

Also fixed while wiring this: the settings.toml BIOS-adoption check read
psx_bios_image.image_bundled, which now runs before any backend is
active (all-zero), so it asks the registry instead.

Verified on Tomba! with ONE binary, both paths:
  no --bios          -> OPENBIOS, no dialog, boots to in-game save
  --bios SCPH1001.BIN-> SCPH-1001 (crc 37157331, bundled=0)
and the per-image state follows the selection, not just the label:
kernel-bless window 0x500-0x4BA0 vs 0x500-0x8500, deliver_event_ret
0x0 vs 0x80001720.

Still outstanding: savestates must record the active BIOS and refuse to
load under another (kernel RAM layout differs); a player-facing way to
clear a remembered choice; retiring PSXRECOMP_BIOS_STEM/_PROFILE, which
now only feed the staleness stamp.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 12:12:33 -07:00
Matthew Stanley 46f06a5d46 build: make netplay opt-in instead of opt-out
PSX_NETPLAY defaulted ON and auto-discovered a recomp-net checkout from
four candidate paths, so every build linked the delay-sync library. The
lobby WebSocket client was worse: gated on nothing but its source files
existing, i.e. always compiled.

These are single-player titles. Neither belongs in their binaries.

Default PSX_NETPLAY to OFF and gate the lobby client on it too. A
multiplayer title opts in with -DPSX_NETPLAY=ON, which still links
recomp-net and the lobby client exactly as before (verified both
directions on Tomba).

ws2_32 stays unconditional: the TCP debug server needs sockets
regardless of netplay.

psx_netplay.c / psx_lobby_client.c still compile as their existing
no-op stubs rather than being #ifdef'd out — main.cpp has 74 call sites
and they are already written to stub cleanly, so guarding every one of
them would be a large, riskier change for a small object-size win.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25 11:11:56 -07:00
Matthew Stanley 68667cd58b disc+bios: either file the user picks resolves, mounts, and verifies
Two path-resolution defects where the runtime silently accepted only one of
two equally-valid spellings of the same input.

1. Disc: picking the .cue threw away the disc's TOC.

normalize_disc_path_for_launch() swapped any .cue for its same-named .bin
unconditionally, and every disc entry point (game.toml, --disc, the cached
disc.cfg, the launcher's Change Disc, the first-run dialog) went through it.
That discarded the cue's table of contents -- every CD-DA track and pregap
with it -- even though iso_reader.cpp has full multi-FILE cue support that
the swap defeated before it was ever reached. In the other direction,
picking a redump audio-track bin mounted that track as the whole disc, which
cannot boot.

resolve_disc_path() (runtime/include/disc_path.h) now canonicalizes any pick:

  .cue that resolves            -> mount the cue (TOC intact)
  .cue with a missing bin       -> the payload it still names, else a
                                   stem-matched sibling image
  .bin/.iso/.img owned by a cue -> mount that cue
  bare image, no cue            -> mount it

identify_disc() resolves through the same code, so the header/serial/CRC32
verdict is read from the data track no matter which member was picked.

While here: the mount path and the verify path had two divergent private cue
parsers (quoted-only + case-sensitive vs quoted-or-bare + case-insensitive),
so they could disagree about the same file. Both now use one parser
(runtime/include/cue_sheet.h), which additionally handles CRLF, backslash
paths, and case-insensitive payload lookup for case-sensitive filesystems.

2. BIOS: the multi-BIOS rename made configs and dump folders incompatible.

SCPH*.toml name "US-PSX-SCPH1001.BIN" while every pre-existing dump folder,
bios.cfg and tools/regen_bios.sh default name "SCPH1001.BIN". Either
combination fataled with "cannot open BIOS file" despite the right ROM being
present. resolve_bios_rom() (recompiler/include/bios_rom_alias.h) matches on
the model token -- the last '-'-separated component of the stem -- so both
conventions resolve in both directions without a hardcoded alias table.
Applied at the config loader, the positional psxrecomp-bios CLI, and each
rung of the runtime's BIOS search.

The positional CLI also derived out_stem from the raw filename, so a
region-qualified ROM would have emitted US-PSX-SCPH1001_full.c -- a name
runtime.cmake cannot link. It now derives the model token.

Also fixes SCPH5552.toml, whose rom field omitted the bios/ directory that
its two siblings have.

Tests: test_disc_path_resolve (36 checks, five dump layouts) and
test_bios_rom_alias (15 checks, both directions + negative cases), both
registered in runtime/CMakeLists.txt. Registered the pre-existing
test_iso_reader_cdda, which was wired into no build.

Verified on real dumps: Ape Escape .cue and .bin both give
SCUS-94423 / NTSC-U / crc=C6F455BC; Tomba 2's multi-track dump gives
crc=1FB8C151 and a 2-track TOC from the .cue, the data bin, and the CD-DA
bin alike.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 22:17:52 -07:00
Matthew Stanley bfa760f43b build: fail early with a clear message when recompiled game C is missing
The runtime links generated/<serial>_{full,dispatch}.c, produced by a separate
recompiler step run before the build. Those paths are marked GENERATED so cmake
configure succeeds before that step has run — which meant skipping generation
surfaced only as a raw "cc1: fatal error: <file>: No such file or directory"
deep in the build, with no hint that a step was skipped or what produces the file
(exactly the trap a from-source builder on a fresh checkout hits).

Add runtime/check_generated_sources.cmake and wire it into
psxrecomp_add_runtime_target as a build-time dependency of the runtime target:
a missing game source now aborts at build start with the files named and the
exact fix (build recompiler -> extract EXE -> generate -> rebuild), and configure
emits an early non-fatal warning. Framework-wide, so every game inherits it.

Also fix the docs/BUILDING.md "build and run a game" recompiler invocation (the
framework is a submodule at psxrecomp/, not ../psxrecomp/) and add the
recompiler-build step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 09:36:14 -07:00
NyperYuhgard 2ebb2b1a6b Multi-Bios (seeds required) 2026-07-24 01:38:56 -05:00
Henrique Guedes 6749b826d4 feat: OpenBIOS support — profile-driven BIOS recompilation
Adds PCSX-Redux's MIT-licensed OpenBIOS as a second BIOS the framework can
statically recompile, next to retail SCPH1001. Because OpenBIOS is
redistributable, a game verified against it ships its BIOS with the build —
players supply only a disc, and the launcher BIOS picker disappears.

The mechanism is general, not OpenBIOS-specific: every BIOS image gets a
bios/<STEM>.toml profile that is the single source of truth for its identity
and layout.

Recompiler
- bios/<STEM>.toml profiles: [program.image] (sha256 pin, redistributable
  flag), [recompiler.address_model] (boot-time ROM->RAM copy windows,
  kernel-bless window), install_slots, and [recompiler.runtime_exports]
  HLE anchors (0 = feature structurally unavailable on that BIOS).
- BiosAddressModel (new): validated model built from the profile, replacing
  ~9 hardcoded SCPH1001 window constants that had drifted apart across the
  emitter / discovery / game codegen. The emitted C normalize() derives
  from the same table. from_config rejects overlapping/misaligned windows
  and orderings where sequential folding != first-match. A CTest-registered
  equivalence test sweeps every RAM/ROM address against verbatim copies of
  the old helpers.
- Orphaned delay slots (the OpenBIOS-critical emitter fixes): jr/jalr
  slots are inlined before the jump resolves — previously their side
  effect was silently LOST (e.g. a case-return fragment's addiu $sp pop,
  which unwound a shifted frame and walked the exception handler's IntRP
  cursor into a wild dispatch). Orphaned branches resume at ds+4 on
  not-taken instead of re-executing the slot (a read-modify-write slot
  doubling twice broke OpenBIOS readPad). Jump targets latch pre-slot.
- MIPS-I load-delay modeling for dependent load pairs: the successor sees
  the pre-load value (OpenBIOS's cardfasttrack.s relies on it on purpose —
  "gotta break those bad emulators"). Unmodeled shapes warn at build time.
- Discovery hardening: branch-target dispatchability closure to fixpoint;
  jump tables placed at jr+8 no longer walked as code; cross-function
  continuations routed by an instruction->owner map.
- Signed MULT support (unreachable from the retail seed set; modern-GCC
  OpenBIOS emits it freely), latency-modeled like MULTU.
- Seeds from ELF symbol tables + data-section code-pointer harvest
  (tools/gen_bios_seeds_from_elf.py) — a source-built BIOS needs no
  disassembly pass. 646 OpenBIOS seeds, incl. 5 empirical dispatch-miss
  seeds.
- Stemmed outputs (<out_stem>_full.c / _dispatch.c) so two BIOSes coexist
  in one out_dir. tools/regen_bios.sh is profile-driven (--config).

Runtime
- psx_bios_image: the generated dispatch now self-describes the BIOS it
  was compiled from (identity: size/CRC32/SHA-256/wordsum; kernel-bless
  window; HLE anchors; bundled flag). Runtime SCPH1001 hardcodes removed.
- Launch check is a hard identity gate (a mismatched image under
  statically recompiled code is a guaranteed wild jump). Bundled builds
  hide the BIOS picker and treat a missing/tampered bundled image as an
  installation defect.
- Faithfulness fixes surfaced by OpenBIOS's tighter timing loops (all
  global, argued in code comments, regression-tested against SCPH1001):
  - SIO pad RX is cycle-paced like the memcard path (RX_RDY at
    shift-complete, ACK +170); total ack-IRQ latency unchanged.
    PSX_SIO_PAD_SYNC_RX=1 restores the legacy synchronous path for A/B.
  - SPUSTAT derived from SPUCNT instead of permanently-asserted busy.
  - GPUSTAT.13 (interlace field) alternates per vblank while interlaced,
    pinned 0 in progressive.
  - CD Init(0x0A) completes in ~3.9 ms instead of borrowing Beetle's
    34 ms Reset figure (OpenBIOS's short bounded retry loop livelocked).
  - Exception EPC guard accepts ROM-window block leaders, not just RAM.
- New TCP debug commands (documented in TCP_COMMANDS.md): bios_info,
  s3_smear_watch, callret_watch; write-trace ring gains $s0-$s5.

bios/openbios.bin is vendored (MIT — notice in bios/OpenBIOS.LICENSE,
attribution in THIRD_PARTY_ATTRIBUTION.md, source pin + build recipe in
bios/OpenBIOS.toml). The emitter fingerprint digest is now content-only:
existing generated/*.emitter.sha will read STALE once; re-run
tools/regen_bios.sh.
2026-07-23 17:10:23 -03:00
Alex Vanderveen 626a7d613e build: drop lib/recomp-ui; games vendor UI at repo root
Discover recomp-ui from CMAKE_SOURCE_DIR/recomp-ui (or RECOMP_UI_ROOT).
Keep lib/recomp-net in the engine.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 00:27:15 -04:00
Alex Vanderveen 8a362a36ad build: drop lib/recomp-ui; games vendor UI at repo root
Discover recomp-ui from CMAKE_SOURCE_DIR/recomp-ui (or RECOMP_UI_ROOT).
Keep lib/recomp-net in the engine.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 00:27:15 -04:00
Alex Vanderveen 65d254cc9b Add MAX_PLAYERS build flag, multitap, and N-slot netplay wiring.
Games pass MAX_PLAYERS (2..5, default 2) to bake PSX_MAX_PLAYERS. SCPH-1070
multitap maps pads 0–3 on port 1 and pad 4 on port 2. Lobby max_slots and
recomp-net slot_count follow the game player count; MotK stays at 2.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 23:09:00 -04:00
Matthew Stanley 27de42d073 vulkan: fix draw-area batching and enable builds by default 2026-07-22 12:07:32 -07:00
Alex Vanderveen 3d6b0f3a86 launcher: enumerate LAN IPs for host advertise dropdown
Implement list_lan_ips (GetAdaptersAddresses / getifaddrs), bump
recomp-ui for the Host Lobby LAN IP combo, and keep UDP bind on 0.0.0.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 13:17:03 -04:00
Matthew Stanley 87491cb035 launcher: integrate recomp-ui netplay flow 2026-07-21 21:39:28 -07:00
Alex Vanderveen 0b890cdc13 lobby game version control 2026-07-21 21:38:04 -07:00
Alex Vanderveen 31015ceab1 feat: launcher polish and recomp-net lobby netplay
Wire MotK-style lobby (recomp-net submodule, WS client, match_caps),
netplay delay-sync, and launcher UX so host sim settings stay aligned
across peers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 21:37:57 -07:00