Commit Graph

60 Commits

Author SHA1 Message Date
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 f86087ad94 Remove stale RmlUi launcher remnants 2026-07-23 00:29:22 -07:00
Matthew Stanley 27de42d073 vulkan: fix draw-area batching and enable builds by default 2026-07-22 12:07:32 -07:00
Matthew Stanley e558c971ab runtime: restore native Tomba FMV overlays 2026-07-22 00:35:26 -07:00
Matthew Stanley d482ab67a2 runtime: resume compiled code after patched FMV entries 2026-07-21 22:32:07 -07:00
Matthew Stanley 6c914a763f runtime: quiet high-frequency diagnostics during FMV 2026-07-21 22:24:55 -07:00
Matthew Stanley f1bdefad20 runtime: batch faithful FMV load-cycle charges 2026-07-21 22:23:15 -07:00
Matthew Stanley 9228f32c00 runtime: keep Vulkan opt-in and remove old launcher
Remove the in-tree launcher implementation and its submodules now that game projects use recomp-ui for launcher support.

Keep Vulkan hidden from the launcher unless a game explicitly sets [video] offer_vulkan = true, and clamp stale Vulkan settings back to OpenGL when it is not offered.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 16:31:36 -07:00
Matthew Stanley da64f44e82 launcher: expose the Vulkan renderer
Cycle the renderer selector through Software, OpenGL, and Vulkan while retaining OpenGL-only option gating.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 15:55:16 -07:00
Matthew Stanley f1fd8ec848 vulkan: expose present blocking telemetry
Record queue-wait, acquire, and present durations plus presentation timestamps in the existing vk_perf ring.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 15:55:11 -07:00
Matthew Stanley f5498f796c vulkan: prefer MAILBOX for tear-free presentation
Let the frontend remain the sole frame pacer by requesting MAILBOX for tear-free delivery, with FIFO retained as the required fallback.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 15:55:06 -07:00
Matthew Stanley af9de64951 vulkan: reuse persistently mapped staging buffers
Cache best-fit host-visible staging allocations across queue-idle reclamation points and safely detach long-lived CPU-present buffers during teardown.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 15:54:42 -07:00
Matthew Stanley b5e9f763fe vulkan: batch work into one command buffer
Keep a shared work command buffer open across logical GPU operations and submit it at the existing synchronization boundary.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
2026-07-21 15:54:29 -07:00
Matthew Stanley 92cbb1a327 vulkan: order back-to-back color passes
Add same-layout color attachment barriers before geometry and wide-surface render passes so prior writes are visible to LOAD and blend operations.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:54:17 -07:00
Matthew Stanley 7f9f59a2bb vulkan: wait for acquire before transfer writes
Include the transfer stage in the swapchain acquire wait mask because the present command buffer clears and blits the acquired image with transfer operations.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:54:12 -07:00
Matthew Stanley c25931e3b7 vulkan: align packed upload offsets
Pad each packed R16 upload region to an even texel count so subsequent VkBufferImageCopy offsets retain the required four-byte alignment.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 15:54:07 -07:00
Matthew Stanley d742a62391 fix: default generated games to OpenGL renderer 2026-07-20 17:34:12 -07:00
Matthew Stanley 8f78ddbd89 integrate interpreter hotpath and AOT sharding 2026-07-20 15:58:43 -07:00
Matthew Stanley ae3acc7db6 aot: deduplicate complete shard pairs safely 2026-07-20 14:13:46 -07:00
Matthew Stanley c2f4c8bf4b aot: close cross-variant coverage deterministically 2026-07-20 14:06:26 -07:00
Matthew Stanley 8d0081bca8 runtime: harden overlay candidate capacity 2026-07-20 14:06:25 -07:00
Matthew Stanley c37fc2d60c runtime: harden autocompile polling and result capture 2026-07-20 13:42:06 -07:00
Matthew Stanley 5ded80e61e Merge master (AOT overlay generation) into perf/interpreter-hotpath
Integration branch: the interpreter-perf series (interpreter fallback +
additive shard autocompile + always-on production observability + the
fail-closed alias-body emitter fix) rebased-by-merge onto master's AOT
overlay generation (play-free extraction, bounded indirect discovery,
AOT recall, shadow-diff redesign).

Semantic-union highlights:
- gte.cpp: HEAD's direct-field marshaling fast paths kept; master's
  s_gte_replay_sandbox guards grafted onto every affected site.
- psx_icache.c: HEAD's global tag array + fetch_miss split kept;
  master's transactional shadow record/replay retargeted onto it.
- overlay_capture.c: HEAD's commit/retry/wait-pending pipeline kept;
  master's durable history + autocapture APIs wired into it
  (persist_history_snapshot fed from the immutable .d contribution).
- overlay_loader.c: master's interp-record/native-replay shadow-diff
  redesign kept as base with HEAD's scheduler-bail hardening grafted
  (new SHDIFF_SCHED divergence kind); strict manifest v2 parsing keeps
  master's P pair-id lines; always-on native-call ring preserved.
- main.cpp shutdown calls BOTH overlay_autocapture_shutdown() and
  overlay_capture_wait_pending() (the latter drains the preserve-write
  FIFO the former does not).
- recompiler: master's generate_alias_group refactor retains the
  fail-closed alias-body re-entry defaults from c85f1d1.

Validated on this tree: recompiler + runtime + tests build; all six
runtime unit tests PASS; interpreter perf guards PASS; recompiler
patch/structural tests PASS (l1 decoder oracle noise = 376 pre-existing
on both parents).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:43:41 -07:00
Matthew Stanley b3bfdd9330 Fix in-handler RFE contract gaps that livelock the boot splash (Tomba 2 frame 1385)
Three-layer faithful-core fix for the exception-return contract, root-caused
live over TCP on a deterministic dbg-build repro (vblank authority vetoed
forever while the guest spun in the kernel idle loop, in_exception stuck 1):

1. Interpreter RFE backend parity: dirty-RAM RFE now calls
   psx_rfe_mark_escape() exactly like the recompiled opcode and every
   overlay shard (ABI v12), and dirty_ram_dispatch_inner takes a pending
   escape at the committed transfer before local dirty flow can keep
   interpreting the resumed code inside psx_check_interrupts' window.
2. Legacy-sentinel deliveries arm the escape too: the old blanket decline
   assumed a sentinel delivery always resumes AT the sentinel, but guest
   TCBs never hold the sentinel (Fix B anti-leak), so a kernel
   ReturnFromException restore resumes at an approximate real PC with no
   exit path armed. The take site preserves the legacy contract: a resume
   landing ON the sentinel still exits through the sentinel detector.
3. Same-thread completion of a sentinel delivery via explicit RFE /
   ReturnFromException converts to the legacy exit (restore interrupted
   GPRs, pc=0, continue the live host chain) keyed on the structural
   entry_tcb == exit_tcb test - otherwise the approximate TCB PC surfaces
   up the trampoline, severs the live chain, and the run dies one hop
   later on an un-re-enterable mid-function PC ("execution completed").

Validated: production build passes the previously-fatal splash transition
(frames 4717+ at 60fps, was deterministic death at 1385 x3 runs); dbg build
advances past the wedge (was frozen at exactly 1385); all runtime tests +
structural guards pass (guards extended to pin the interp RFE contract).
Known follow-up: the PSX_DEBUG_TOOLS build still loses one kernel CD event
through a third timing path at the same site - tracked as an open
foundation item; production config unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:00:29 -07:00
Matthew Stanley e02b7b3455 Close publication lifecycle: shutdown join, prepare retry, loud caps, canonical paths
Audit fixes for the async shard-publication pipeline (45a2dda):

- autocompile_shutdown(): stops the pipeline, kills the compiler tree via a
  kill-on-close job object (assigned while the child is SUSPENDED so cmd.exe
  cannot spawn grandchildren outside it), and JOINS the watcher + preparer —
  never abandoning a thread inside the Windows loader lock at ExitProcess.
  Wired first into shutdown_runtime(). Crash exits reap the tree via the job.
- Failed off-thread prepares retry (3 attempts, 100 ms) on the worker before
  the artifact silently reverts to a synchronous emu-thread first-map; retry
  and giveup counters exposed in autocompile_status_json.
- Capacity caps fail closed and LOUD: cand_register shouts once at CAND_CAP;
  load_one_dll_prepared refuses at MAX_LOADED_DLLS before registering, so
  dll_already_loaded can never lose track and double-register on rescan.
- Publication confinement is filesystem-resolved: published_path_valid
  canonicalizes the cache root and the pipe path (GetFinalPathNameByHandle /
  realpath), prefix-checks canonical forms, and the worker maps the canonical
  string while holding a no-delete-share guard handle (TOCTOU). `..`/junction
  spellings that passed the lexical check are now rejected — proven by the
  new overlay_path_canon_test boundary test.
- test_autocompile_publication gains a shutdown-mid-run scenario asserting
  prepared == committed + discarded with nothing queued; perf guards updated
  to require validate -> guard-handle -> canonical first-map ordering.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:19:57 -07:00
Matthew Stanley 45a2dda040 Checkpoint asynchronous overlay shard publication 2026-07-19 15:30:25 -07:00
Matthew Stanley a73a4055d1 Retry additive overlay capture and compile requests 2026-07-19 15:07:33 -07:00
Matthew Stanley 4f4e6e467c Speed up interpreter dependency decoding 2026-07-19 14:54:30 -07:00
Matthew Stanley d13bade9ae Speed up exact GTE command marshaling 2026-07-19 14:44:22 -07:00
Matthew Stanley 05f6ef3e02 Optimize GTE fallback and isolate interpreter perf runs 2026-07-19 14:23:36 -07:00
Matthew Stanley ffda40934b runtime: preserve causality at device deadlines 2026-07-19 13:40:25 -07:00
Matthew Stanley 7376e6b042 Harden additive overlay shards and speed interpreter fetch 2026-07-19 12:11:56 -07:00
Matthew Stanley 3949854981 Optimize interpreter fallback and additive overlay autocompile 2026-07-18 08:32:42 -07:00
Matthew Stanley a544809edf aot: persist overlay capture history atomically 2026-07-17 23:56:58 -07:00
Matthew Stanley 5b7e69b441 Remove the sljit Tier-2 in-process JIT backend
The tier mis-compiled and has been hard-gated off since 2026-06-25; overlay
gaps fall to gcc/tcc shards and the dirty-RAM interpreter, unchanged.

Re-do on master of the removal validated on the stale branch (6da8c02),
reconciled with everything master grew since the fork:

- Delete overlay_sljit.{c,h}, overlay_compile_worker.{c,h}, lib/sljit,
  runtime/tests/sljit_*.c, and the runtime.cmake sources/include-dirs.
- Strip the sljit provider/backend from code_provider.{c,h},
  overlay_backend.{c,h} ("sljit" in overlay_backend/PSX_OVERLAY_BACKEND now
  degrades to auto so stale configs still boot), main.cpp, debug_server.c
  (sljit_status/sljit_async/sljit_try TCP commands), overlay_loader.{c,h}
  (live policy, JIT-on-miss, persisted-shard cache, async worker glue,
  psx_sljit_call/cop2/memx host helpers — reachable only via the removed
  cpu->sljit_helpers table), and cpu_state.h (SLJIT_HLP_* enum + the
  sljit_helpers[] member; CPUState layout change reshards via the cg tag).
- Master-only entanglement resolved before deletion: 28165d6's Einhander WS
  player-X bound emit existed in three paths (gcc code_generator, sljit,
  dirty_ram_interp). The gcc shard link contract now forwards
  psx_ws_player_x_bound (ABI v13, previous commit), so deleting the sljit
  emit path loses no widescreen behavior; ffc6688's game-dispatch block
  inside the dead psx_sljit_call helper goes with it.
- Reword comments that described sljit as a live backend (gpu.{c,h},
  ws_*_detect.h, cosim_state.c, dirty_ram_interp.c, autocompile.h,
  boot_state.h, config_loader.h, compile_overlays.py, and the CPS marker
  comments the recompiler emits).

recompiler psxrecomp-game builds clean; game runtimes rebuilt + boot-verified
separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 22:22:38 -07:00
Matthew Stanley 0e5c38d558 feat: add generic CD-DA playback and CUE pregaps
Adapted from https://github.com/mstan/psxrecomp/commit/0e9df70ca2da6ec67c8e7a1f3e5aaa025fddc369

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
2026-07-14 20:03:02 -07:00
Matthew Stanley 7ae052534a spu: add hardware Gaussian interpolation
Port the reusable Gaussian interpolation slice from PR #16 while keeping its reverb engine on a separate branch.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:56:51 -07:00
Matthew Stanley 19e526d57d gpu: reject oversized hardware primitives
Apply the PS1 1023x511 size rule to every polygon triangle, line, and polyline continuation before widescreen transforms while preserving textured-command state latching.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:35:07 -07:00
Matthew Stanley 928085d5fb gpu: use exclusive PS1 software-raster edges
Adapt PR #14's biased 32.32 triangle edge DDA and half-open bottom/right coverage across the software raster paths, with a focused pure edge-math regression test.

Source: https://github.com/mstan/psxrecomp/pull/14

Source-commit: https://github.com/mstan/psxrecomp/commit/91a654f61dff18806f3eea43f72a30cb34430695

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
2026-07-14 18:34:32 -07:00
Matthew Stanley c2b9d467e5 runtime: discover decodable unmarked overlay code
Admit post-EXE RAM to the dirty interpreter only after a real control transfer and an existing MIPS decodability check. Keep the already-merged overlay initialization guard out of this focused change.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 18:12:08 -07:00
Matthew Stanley e247155cd6 overlay: use platform-native shared-library suffixes
Adapted from NyperYuhgard's PR #13 POSIX overlay work.

Co-authored-by: NyperYuhgard <93950153+NyperYuhgard@users.noreply.github.com>
2026-07-14 15:58:34 -07:00
Matt Stanley f88828327e Merge pull request #18 from mstan/fix/posix-overlay-export-scan-douglas
Load cached overlay exports on POSIX
2026-07-14 00:03:48 -07:00
Matt Stanley a03350fb68 Merge pull request #23 from mstan/fix/overlay-init-guard-shaneomac
Guard overlay entry points before initialization
2026-07-14 00:03:41 -07:00
Matt Stanley 23edb88b68 Merge pull request #20 from mstan/fix/cdrom-encoded-interrupts-kem0x
Fix encoded CD-ROM interrupt mask matching
2026-07-14 00:03:38 -07:00
Matthew Stanley c0fa9b1e89 overlay: load cached exports on POSIX
Port Douglas Vanderveer's manifest-driven macOS/Linux overlay discovery onto the current cache index and exact-dispatch loader. Validate both filename key fields, preserve ABI cleanup and rescan idempotence, and cover the POSIX primitives with a real shared-library fixture.

Co-authored-by: douglasjv <vanderveerdouglas@gmail.com>
2026-07-13 21:52:25 -07:00
Matthew Stanley 5b8098a9d9 runtime: guard overlay loader before initialization
Adapt only the fail-closed overlay lifecycle checks from mstan/psxrecomp#16 commit e6809ccf7d. Add a focused structural regression test and record the excluded dirty-interpreter and game/runtime work.

Co-authored-by: Martin Penkava <mpenkava1337@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 21:48:39 -07:00
Matthew Stanley 76ddcc008a test(spu): pin END-only voice mute semantics
Document the overlap with kem0x PR #14 and explicitly record the game-specific and unrelated changes excluded from this branch.

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
2026-07-13 21:40:11 -07:00
Matthew Stanley 52eb8e8a24 Fix encoded CD-ROM interrupt mask matching
Adapt the CD interrupt mask/status comparison from kem0x PR #14 and centralize it in a tested helper. The HC05 exposes numeric INT1..INT5 reasons but gates the line with a direct mask/status AND, so the common 0x07 mask must also pass INT4 and INT5.

Source: https://github.com/mstan/psxrecomp/pull/14

Source-commit: https://github.com/mstan/psxrecomp/commit/dd9e5c65073dd41fbac2d965d2f945a866ec59e2

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
2026-07-13 21:38:58 -07:00
Matthew Stanley 9b54441a8a repo cleanup: drop 16 stale handoff/overnight/resolved-bug docs; untrack scratch scripts + test binaries
Deleted dated session-scratch (HANDOFF*, OVERNIGHT*, SUMMARY*) and resolved-bug
writeups (memcard audit, Tomba2 attract/FMV/Whoopee, codex analysis, load4 wedge
superseded). KEPT docs still cited by canonical docs/source (RECURSION_BUG,
WEDGE_load4, CASE_A_AOT_GAP) and all current subsystem-design docs.
Untracked (gitignored, kept on disk): tools/_options_session/ (80 scratch scripts
w/ hardcoded paths) + runtime/tests/*.exe (build artifacts; .c sources stay).
Genericized sibling-project absolute paths in bios_hle.h + crash_trace.c; fixed
README link CURRENT_STATE->FAITHFUL_TIMING_PLAN.
2026-07-06 11:34:35 -07:00
Matthew Stanley 01b4d91e8a WIP: forward-port Ape Escape framework (dev/ape-escape) onto master
Comprehensive 3-way merge of the dev/ape-escape branch into master for
the isolated wt/ape-escape worktree. Brought in every complementary ape
change automatically (dma.c, memory.c interrupt byte/half lanes,
function_analysis discovery, main_bios vector seeds, iso_reader
iso_sector_count, config_loader, crash-trace fields, headers). Resolved
the 13 conflicts by rule:

  - CPS dispatch / recompiler (code_generator, full_function_emitter,
    dirty_ram_interp, traps, main_psx) -> KEEP MASTER (evolved system).
  - CD model (cdrom.c) -> take ape (the model that booted Ape).
  - interrupts.c/.h -> reverted to MASTER (ape's interrupt-delivery is
    dispatch-coupled; the merged Frankenstein stormed).
  - sio/debug_server/freeze_heartbeat/main.cpp -> keep master (evolved).
  - crash_trace.c -> master (ape freeze-dump fns omitted to avoid the
    debug-ring cascade).

STATUS: does NOT boot yet. ape-cdrom + master-interrupts derails to
PC=0 at frame ~2092 (insta-close); ape-cdrom + ape-interrupts storms
(297M exception re-entries) at frame 2077. Root finding: ape's CD
anti-storm is coupled to ape's interrupt-delivery + call-depth + EPC
model, which master replaced with CPS continuation-passing, so the CD
subsystem does not forward-port as pure hardware simulation. Preserved
as the reference state for a design consult on bridging the two models.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 15:55:23 -07:00