Commit Graph

1851 Commits

Author SHA1 Message Date
Alexandros Mandravillis 6fcfb8adbd Preserve field masks in wide flat overlay geometry 2026-09-06 14:16:53 +03:00
Alexandros Mandravillis 5aee9c831a Preserve Vulkan wide overlay row clipping 2026-09-06 13:58:00 +03:00
Alexandros Mandravillis 7c4b03000e Bound interlaced precise triangle row submissions 2026-09-06 13:54:52 +03:00
Alexandros Mandravillis 439097184f Count perspective triangles once across interlaced row submissions 2026-09-06 13:34:03 +03:00
Alexandros Mandravillis 0661ce7773 Preserve active display field during interlaced raster drawing 2026-09-06 13:13:03 +03:00
Alex Vanderveen 155e269ba5 tools: DirectWrite/Direct2D/WIC are system DLLs, not payload
recomp-ui's Win32 emoji and font path imports DWrite.dll, d2d1.dll and the
WIC/D3D family. None was in the system list, so the bundler went looking
for them in the MinGW sysroot, did not find them (they only exist on
Windows) and failed the packaging step — measured on the SNES side, where
the same recomp-ui pulled the same imports and killed the release job.

Brings the list to parity with snesrecomp's bundle_runtime_libs.sh, whose
entries this one was missing as well (KERNELBASE, GDIPLUS, SHCORE, DWMAPI,
UXTHEME, HID, XINPUT*, AVRT, MF*, EXT-MS-*, and the rest).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DYwgPRbwbXz8FhpVzDM7tA
2026-09-06 04:04:37 -04:00
Alex Vanderveen e9038af4cd lobby: log the title presented at hello
The per-game scope failing silently is what made an empty title hard to
find; the client now says which one it announced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1dT6h1ZshMVUUVKTPxsCD
2026-09-06 03:37:26 -04:00
Alex Vanderveen 0f1fd021a8 patch lobby chat 2026-09-06 03:31:56 -04:00
Alex Vanderveen ecc121ade6 lobby browser: spectator column, players online, gallery latency
- lobby_list rows carry allow_spectators / max_spectators / spectator_count
  (browser shows "No" or "1/4"), and every lobby_list carries a players
  array: everyone on the hub with country, room and a short connection tag
  so a client can pick out its own row without publishing whole ids.
- Spectator latency: the round-trip table was keyed by seat and bounds-
  checked against its size, so gallery seats (numbered from 64) were always
  dropped. Seats now map to table cells, player seats first.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1dT6h1ZshMVUUVKTPxsCD
2026-09-06 03:31:38 -04:00
Alex Vanderveen 3d9930c5d3 release: Authenticode-sign Windows binaries when a certificate secret exists
Smart App Control blocks unsigned executables outright. The packager now
runs tools/ci/sign_windows.sh over the staged tree (host exe, DLLs,
emitters) with SHA-256 + RFC 3161 timestamp; no certificate in the
environment means a notice and an unsigned package as before, while a
configured certificate that fails to sign is fatal. The workflow template
passes WINDOWS_SIGN_PFX_BASE64 / WINDOWS_SIGN_PFX_PASSWORD to the package
step. Docs cover the secrets and the limit: the game exe the player builds
locally after Generate is unsigned by nature.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1dT6h1ZshMVUUVKTPxsCD
2026-09-06 03:31:38 -04:00
Alex Vanderveen 5e1b7d3332 netplay: host from the gallery, seat swaps across tables, LAN seat self-service, keybind fixes
- Host may sit in a spectator seat: session slot 0 stays the sim authority
  with a muted pad and no port; slot->port map keeps players on the port of
  their lobby seat (host first). Rematch path copies the same plan.
- Seat self-service on LAN (MOTK5 SEATMOVE / SWAPASK / SWAPANS / SWAPRES)
  relayed by the host; online swap requests accept a gallery seat as target.
- Lobby chat ring + join/leave lines; country codes from the server.
- Keybinds: a key drives one input per player (binding S to Cross unbinds it
  from Circle), and keybinds.ini is re-read after the rematch launcher too.
- LAN registry file anchored to the exe directory.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1dT6h1ZshMVUUVKTPxsCD
2026-09-06 03:31:38 -04:00
Matt Stanley b213858c4c Merge pull request #323 from Alexbeav/codex/sbi-setup
Preserve SBI companions and validate them before launch
2026-09-05 22:45:15 -07:00
Matt Stanley d485a751d8 Merge pull request #325 from kerokline/fix/static-fragments-per-variant
compile_overlays --static: isolated fragments per (entry, image), pooled, memoized
2026-09-05 22:42:16 -07:00
Matt Stanley 87c06376fb Merge pull request #324 from kerokline/feat/dirty-pc-enrichment
dirty_ram per_pc: stamp resident-occupant CRC and caller RA on external entries
2026-09-05 22:40:28 -07:00
Matt Stanley b0e7c157f3 Merge pull request #322 from Alexbeav/codex/fix-exit-critical-section
runtime: preserve registers in ExitCriticalSection
2026-09-05 22:38:27 -07:00
Matt Stanley 12c40a5b12 Merge pull request #321 from kerokline/fix/starvation-watchdog-wrap
runtime: fix starvation watchdog cross-thread wrap; label watchdog and console exits
2026-09-05 22:36:37 -07:00
Alex Vanderveen f3e9a3f8eb tests: cover the lobby chat ring
psxrecomp's chat was already complete -- client, callbacks, and a host-relayed
LAN path snesrecomp does not have -- but nothing tested it. The SNES side got
this coverage when its chat was written; this brings psx level, against the
same properties, so the two cannot drift apart silently.

Covers what the ring actually promises: room order and both ends, local vs
peer vs system identity (decided by player id, not by who called send, because
the server echoes our own line back and that echo is the copy we keep),
monotonic seq, out-of-range reads refused, wrap-around dropping the OLDEST --
a chat that discards what was just said is worse than no chat -- empty lines
ignored, seq surviving a clear so a UI tracking "newest seen" does not skip
the first line of a new room, and an over-long line clipped to the field
rather than past it.

Links the REAL recomp_net and WS helpers rather than a wall of stubs: nothing
here reaches a socket, so fakes would buy nothing and could drift from what
the runtime links. Only psx_host_mono_ms is supplied, because it lives in the
runtime's own main TU.

Verified to discriminate: making the ring refuse new lines at capacity instead
of evicting the oldest fails two assertions.

ctest with -DPSX_NETPLAY=ON: 67/67 pass (2 disabled).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DYwgPRbwbXz8FhpVzDM7tA
2026-09-05 21:47:18 -04:00
Alex Vanderveen 8f266efe27 netplay: bring-your-own memory card, lobby chat, and the fullscreen lobby glue
Seat 1 (P2) can bring its LOCAL slot-1 card to a match: it uploads the card
to the host at launch over the new recomp-net MEMCARD op, the host installs
it as the match's slot-2 card, and the usual card broadcast carries it to
everyone. The host's real slot-2 file is rebound to netplay/guest_card2.mcd
for the session and restored on shutdown; guests already sandbox both slots.
Lobby side: a per-seat memcard_offer on set_ready (has_card, share), a host
allow flag in match_caps, and guest_memcard_active settled ONCE by the host
at start and shipped with the launch, so a toggle racing the start cannot
split the room. LAN carries the same over MOTK5 UPDATE / MEMCARD / JOIN
tail / a trailing START line. PSX_NET_GUEST_MEMCARD=1 for CLI sessions;
a host waiting on a card that never comes stalls at a named phase
(mc_guest_wait), not a silent "ok".

Two latent guest-sandbox bugs fixed on the way: a disabled slot 2 had no
bound path, so a host blob carrying a card for it failed to import and the
guest stalled forever; and leaving the sandbox re-bound a disabled slot to
the sandbox file. Both slots are now bound in the sandbox and restored per
slot (memcard_rebind_path, which can also unbind).

Lobby chat: the client keeps a ring fed by the server's echo (op:chat);
LAN rooms relay through the host (MOTK5 CHATREQ guest->host, MOTK5 CHAT
host->everyone). Wired to the launcher's chat_send/chat_count/chat_get.

Also carries the spectator-seat work that was in the tree alongside this
(spectator seats in the lobby client, spectator_wire_slot in the launch).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V1dT6h1ZshMVUUVKTPxsCD
2026-09-05 21:18:20 -04:00
Alex Vanderveen 953381b12e Merge remote-tracking branch 'origin/master' 2026-09-05 21:05:32 -04:00
Alex Vanderveen d371d74421 tools: generate_ci -- the release workflow for an existing project, and nothing else
sh psxrecomp/tools/generate_ci.sh            # in the project
    powershell -File psxrecomp\tools\generate_ci.ps1
    ... [root] [--check] [--force] [--dry-run] [--zip-prefix X] [--title X]

Project Studio already knows how to emit the setup-host release workflow
(emit_ci_workflow, behind `apply` and `git install-ci`), but reaching it
meant a migration plan or a commit-and-push. This is the single-purpose
face of that operation: it resolves the template from the project's own
psxrecomp submodule, takes the zip prefix from
scripts/package_setup_release.sh so CI uploads the zips the packager
built, writes .github/workflows/release.yml, and stops.

--check reports missing / placeholder / stale (step names the template
has and the file lacks) with exit 1, so a fleet can be audited without
writing anything; only --force overwrites. The .sh and .ps1 are thin
launchers over the one Python implementation.

Verified read-only against two ports: ApeEscapeRecomp reports stale
(four emitter/ccache steps missing), TombaRecomp reports current.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0173EhspvAdRQc9DZdDr97Hg
2026-09-05 18:53:24 -04:00
Kevin 2fa3472a78 compile_overlays --static: isolated fragments per (entry, image), pooled, memoized
The static isolated-fragment pass resolved demands by bare entry address across
every capture: once any part had a variant at an address, that address counted
as served for every other capture of the band, and static_entry_sources kept
only the last capture's bytes. The dispatcher validates each variant against
the exact bytes it was compiled from, so in a band with N occupants exactly one
occupant ever received fragments (BoF3: BOSS055 35/35, PLP678 19/19, SCENA19
20/20; the 128-occupant and 181-occupant bands got none). 23,728 (entry, image)
demands were unserved; at the title screen the resident SCENA16 ran every
observed entry on the interpreter while every spanning piece came from
SCENA19/04/06.

- Demands are keyed (entry, image crc); parts carry image_crc;
  select_static_fragment_demands / served_static_variant_keys are the pure
  helpers (unit-tested).
- Fragment compiles run on the --jobs pool; the image table is sent once per
  worker (initializer) instead of once per demand; results merge in demand
  order and duplicates already served by an earlier-merged part are dropped,
  so the output equals the sequential loop's.
- generate_interior_fragment_static returns (part, reason). Deterministic
  verdicts on the bytes (generated-C audit, requested-entry audit, and a walk
  that runs off the image, which the recompiler reports by throwing) are
  memoized in <out-dir>/interior_fail_memo.txt and counted as skipped, never
  as shard failures; --force-interior retries an entry. Only a
  non-deterministic recompiler failure is a shard failure.
- Fragment parts are grouped one translation unit per image (BoF3: 779 units
  instead of 20,635 files).

BoF3 full run: 20,250 fragments built, 3,570 memoized rejections, 238 s cold,
nothing lost from the previous dispatcher (99,778 -> 138,148 served keys).
Title screen: 12 interpreted SCENARIO-band entries -> 2, both unharvested PCs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 18:35:16 -04:00
Kevin 6e760748c2 dirty_ram per_pc: stamp resident-occupant CRC and caller RA on external entries
Make a bare interpreted PC explainable from the session-long per_pc snapshot
alone. DirtyRamPcEntry gains occ_crc / occ_ok (the static overlay variant whose
code ranges span the PC, via a per-PC scan of the static-match cache, and
whether it validated at that moment) and last_ext_ra (gpr[31] at the most
recent external entry, i.e. the caller that reached this interior). Both are
stamped only on external entries -- arrivals from native dispatch, not interp
block chaining -- and emitted per row in dirty_ram_stats.per_pc as occ_crc,
occ_ok and ext_ra.

Reading the pair: occ_ok=1 is an interior gap inside live native code (an
alias seed fixes it); occ_ok=0 with a CRC means the spanning piece is resident
but CRC-missing, so it was compiled from another section's bytes or rewritten
at run time and no seed helps; 0 means nothing compiled spans the PC.

psx_overlay_resident_crc_at() records each static-match cache entry's code
span (lo_min/hi_max) so the scan is a range test; DLL-path titles fall back to
the loader's last residency hash. The debug-server reply buffer grows 32 -> 64
KiB for the wider rows; the tail reserve still cuts between rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 18:11:13 -04:00
Alexandros Mandravillis 10eb22b775 Keep native SBI test assertions enabled in release builds 2026-09-05 21:47:40 +03:00
Alexandros Mandravillis 83ba647b6e Register SBI setup tests with CTest 2026-09-05 21:38:40 +03:00
Alexandros Mandravillis 2d92d67592 Validate and import SBI companions in the native launcher 2026-09-05 21:34:14 +03:00
Alexandros Mandravillis 1c60d340dc Preserve and verify SBI companions during disc setup 2026-09-05 20:51:14 +03:00
Alexandros Mandravillis 49d5f6233c Report unsupported syscall test toolchains explicitly 2026-09-05 20:09:57 +03:00
Alexandros Mandravillis f3229541a1 Preserve registers in ExitCriticalSection 2026-09-05 19:53:03 +03:00
Kevin 430c93b8a4 runtime: fix starvation watchdog cross-thread wrap; label watchdog and console exits
starvation_watchdog_check() sampled the clock before loading the heartbeat,
but the heartbeat is also stamped by the debug-server IO thread on every
send() chunk. A stamp landing between the two reads made last > now, the
uint64 subtraction wrapped past any threshold, and a healthy runtime exited
with code 2 (BoF3 2026-09-02: 402 us of real staleness tripped the 4 s
watchdog within ~2 min whenever the area poller was attached).

- Load the heartbeat first, decide through the new pure helper
  starvation_watchdog_stale(), which refuses a negative gap by construction
  (same shape as the frame_pacing_sleep_ms fix).
- Make s_last_heartbeat_us _Atomic with relaxed store/load.
- Tag the exit origin: "starvation_watchdog" on the trip, console_close /
  console_ctrl_break / console_ctrl_c in the Win32 console handler, and
  signal_sigint / signal_sigterm in the soft-exit handler. These all used
  to reach psx_atexit_handler as atexit/unknown, indistinguishable from an
  SDL window close.
- Add starvation_watchdog_test (ctest) pinning the decision function.

Verified on BoF3 build-dbg: 10 min soak with the poller polling at 1 s and
the watchdog enabled at its 4 s default, no dump, process alive; forced
trip with PSX_STARVATION_TIMEOUT_US=1000 fires and the run report reads
exit_origin "starvation_watchdog".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-05 12:17:16 -04:00
Matt Stanley 17f49ad3b2 Merge pull request #320 from mstan/fix/keymap-label-explicit-unbind
host_keymap: hide labels for explicit unbinds
2026-09-04 23:33:43 -07:00
Matthew Stanley 08ec6fc84a host_keymap: hide labels for explicit unbinds 2026-09-04 23:32:45 -07:00
Matt Stanley df3bc1bc2b Merge pull request #319 from kerokline/feat/keymap-explicit-unbind
host_keymap: honour an explicit None/empty [KeyMap] line as unbound (Backspace-to-clear companion)
2026-09-04 23:29:58 -07:00
Kevin 975f6646ef host_keymap: a present-but-empty / "None" [KeyMap] line is an explicit unbind
host_keymap_load zeroed an action's binds when its line was present and then
apply_defaults() put the built-in key straight back, so "Turbo = None" (or
an empty value) silently re-armed Tab. Track explicit_unbound per action:
set when the line is present but yields no binds, and honoured by
apply_defaults through want_default(). A missing line still receives the
default, so existing config.ini files are unaffected.

Pairs with the launcher's Backspace-to-clear (recomp-ui
feat/additional-ui-functionality), which writes "None" for that reason.
README documents the rule; test_rewind_toggle_combo.py guards it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 07:33:08 -04:00
Matt Stanley 15822694c6 Merge pull request #318 from kerokline/feat/fast-forward-toggle
runtime: fast-forward toggle shortcut (TurboToggle / fast_forward_toggle_pad) + document the implicit Select chord
2026-09-03 19:01:48 -07:00
Alex Vanderveen 9d26330bc0 Update README with setup and project structure details
Added sections on source code requirements, project scaffolding, and folder structure.
2026-09-03 21:19:48 -04:00
Kevin 3b8b98fa29 runtime: fast-forward toggle shortcut + document the implicit Select chord
Turbo (Tab / [hotkeys] fast_forward_pad) is hold-to-run only. Add a
press-to-latch twin that feeds the same manual fast-forward block:

- host_keymap: HOST_KEYMAP_TURBO_TOGGLE, [KeyMap] TurboToggle, default F9.
- main.cpp: g_manual_turbo_latched flipped by the key edge or by a fourth
  host shortcut, PSX_ASSIST_BIND_FAST_FORWARD_TOGGLE ("Fast-forward
  toggle", [hotkeys] fast_forward_toggle_pad, unbound by default), polled
  next to Rewind / Save states through hotkey_pad_binding_down(). OSD shows
  "Fast forward: Nx (locked)" / "Fast forward: off". Threaded through every
  settings hop (settings.toml -> globals -> launcher seed -> LauncherSettings
  -> back), mirroring fast_forward_pad.
- config_loader: [hotkeys] fast_forward_toggle_pad read/write.
- README: describe the toggle and state that a single-button / trigger host
  shortcut is an implicit chord with Select (hotkey_pad_binding_down), which
  the launcher now labels as "select + ..." (recomp-ui companion change).
- test_rewind_toggle_combo.py guards the new sites.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 21:00:59 -04:00
Alex Vanderveen cda971dd35 build deps 2026-09-03 20:55:45 -04:00
Alex Vanderveen b1d1e3dd70 CI release and build toolchain deps readme 2026-09-03 20:34:10 -04:00
Alex Vanderveen 6419e5d2a9 bumprecomp-net and update README 2026-09-03 19:54:19 -04:00
Matt Stanley 6732d7694c Merge pull request #317 from mstan/fix/dma2-ot-observability
dma: expose GPU linked-list observability
2026-09-03 16:48:00 -07:00
Matthew Stanley 471ee0d34b dma: expose GPU linked-list observability
Add passive DMA2 ordering-table counters to dma_state so long or aborted linked-list walks are visible without relying on screenshots. The counters track starts, duplicate starts dropped while a walk is active, completions, cancels, last/max walk size and cycle cost, CHCR poll counts, the initiator PC, and the last eight cancel records.

This intentionally does not port PR #302's superseded walker changes or the PSX_GPU_LL_SYNC diagnostic lever; PR #304 remains the timing implementation.

Co-authored-by: Kevin Kline <9866117+kerokline@users.noreply.github.com>
2026-09-03 16:47:19 -07:00
Matt Stanley 2da25c18d9 Merge pull request #316 from mstan/integrate/303-312
Integrate overlay guard bounds and XA EOF fixes
v0.3.3-alpha
2026-09-03 11:42:09 -07:00
Matthew Stanley 240cff542e Merge remote-tracking branch 'origin/pr/312' into integrate/303-312
# Conflicts:
#	tools/compile_overlays.py
2026-09-03 11:41:22 -07:00
Matthew Stanley 254a14f3d7 Merge remote-tracking branch 'origin/pr/303' into integrate/303-312
# Conflicts:
#	tools/compile_overlays.py
2026-09-03 11:37:13 -07:00
Matt Stanley d1f776d497 Merge pull request #313 from kerokline/fix/gpu-polyline-terminator
gpu: polyline terminator never in the first two vertices
2026-09-03 11:35:31 -07:00
Matt Stanley 1d414fc7b1 Merge pull request #314 from mstan/chore/repo-cleanup
chore: repo hygiene — purge dead scratch tooling, relocate root docs/fixtures/BIOS profiles
2026-09-03 11:30:32 -07:00
Matt Stanley 71f3c8c360 Merge pull request #304 from Alexbeav/pr/gpu-dma2-correctness-ff7
dma: preserve live linked-list reads with word-cost timing
2026-09-03 11:24:02 -07:00
Matt Stanley 9113540bea Merge pull request #315 from mstan/review/pr293-vulkan-stage-idempotent
Vulkan header staging and netplay diagnostic
2026-09-03 11:23:20 -07:00
Matthew Stanley 772a3a956b Merge remote-tracking branch 'origin/master' into pr293-vulkan-stage-idempotent 2026-09-03 11:21:11 -07:00
Matthew Stanley bcd048f184 CMake: make Vulkan header staging idempotent 2026-09-03 11:21:10 -07:00