Commit Graph

313 Commits

Author SHA1 Message Date
Alex Vanderveen 1181c9c9e9 fix(runtime): restore missing brace after present-cadence log
The vsync hotfix replaced the closing brace of the non-headless SDL
init else with log_present_cadence(), leaving main.cpp unbalanced.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-16 18:08:58 -04:00
Alex Vanderveen 353da99795 Merge origin/master into feat/vsync_hotfix.
Keep vsync/pacer XOR and skip the full-period wait while manual fast-forward already paces at the turbo multiplier.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-16 14:01:35 -04:00
Alex Vanderveen 0a911fed53 Stop vsync and the wall-clock pacer from double-blocking presents.
Linux compositors wait a full refresh on SwapBuffers even after the pacer has already slept ~16.7 ms, which locked NTSC titles at 30 Hz / 0.50x with the CPU idle. Vsync now owns cadence only on ~60 Hz panels; otherwise the pacer holds 59.94 Hz and swap interval is forced to 0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-16 13:13:02 -04:00
Matthew Stanley ad55fecdcf Gate WipEout local viewport native-wide to split frames 2026-08-15 22:53:24 -07:00
Matthew Stanley bdd7ade6e8 Merge remote-tracking branch 'origin/master' into codex/netplay-local-viewport 2026-08-15 21:40:56 -07:00
Matthew Stanley c18d820fb8 Correct split viewport projection aspect 2026-08-15 21:02:38 -07:00
Matthew Stanley b2eeb0f866 Add opt-in netplay local viewport extraction 2026-08-15 20:51:23 -07:00
Matthew Stanley 7993f412c0 Add opt-in controller device defaults 2026-08-15 20:09:37 -07:00
Matthew Stanley ed9ec01abe pgxp: default tolerance clamp 0.5px (user-validated seam fix)
Interactive isolation on Ape Escape (in-game, live TCP toggles): OFF =
baseline jiggle; geometry ON unclamped = sparse hairline background-bleed
seams along corrected/uncorrected shared edges (both user-reported
artifacts vanished with the toggle off - the THPS2 line class, not wild
vertices); ON with tolerance 0.5 = seams gone, only sub-half-pixel
misalignment remains. Ship 0.5 as the default; negative still disables.

Also documents the screenshot_hires scale-2 windowed readback defect
(tiled/black PNG - row pitch) found during the session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 20:03:08 -07:00
Matthew Stanley 200b5bf003 Add opt-in widescreen culling keep hooks 2026-08-15 19:42:43 -07:00
Matthew Stanley 38bdeeaade pgxp: emit hook macros + dual build targets + flavor-namespaced caches (phase 2)
Emitter side of the value-propagation engine (ENHANCEMENTS.md G1.10):

- recompiler/src/pgxp_hook_emitter.{h,cpp} (new, in the codegen-hash
  surface): ONE hook grammar shared by BOTH emitters, wrapping loads/
  stores/COP2 transfers and precision-carrying ALU ops (moves, add/sub,
  or-merge, shifts, LUI, HI/LO, muldiv) with PGXP_*() macros. Clobberable
  sources are captured into locals before the statement. Precision-
  destroying ops (AND/XOR/SLT/...) are deliberately unhooked - validate-
  on-read drops their stale shadows for free.
- code_generator.cpp: central append in translate_instruction; LWC2/SWC2
  emissions capture the RAW loaded/stored word (a masked GTE register
  write must validate against the word as loaded).
- strict_translator.cpp: translate() wraps translate_impl()'s c_code with
  the shared grammar; deferred load-delay variants hook the psx_ldd temp.
- BIOS regenerated, fingerprints verified CHANGED (SCPH1001 + OpenBIOS;
  42.6k/12.2k macro sites). Base runtime + 33/33 tests green against it.
- Gating: macros expand only under -DPSX_PGXP=1. runtime.cmake grows a
  PGXP option on psxrecomp_add_runtime_target (defines PSX_PGXP=1 +
  PSX_OVERLAY_FLAVOR=2, _pgxp exe suffix) and PSX_PGXP_VARIANT to build
  the sibling target from the same generated tree (framework runtime +
  game wrapper). No ABI version bump needed: the appended PGXPHooks
  table is NULL-tolerant and the flavor half of the ABI tag rejects any
  host/DLL flavor mix.
- Shard caches: flavor folded into the cache tag (cg<V>_<hash>_gc<hash>
  _f<flavor>) in overlay_loader.c + compile_overlays.py so base and pgxp
  caches never share a directory; compile_overlays.py passes
  -DPSX_PGXP=1 when flavor bit 2 is set; overlay preamble forwards
  psx_pgxp_* through the table. PSX_OVERLAY_CODEGEN_VER 9 -> 10.
- Env overrides PSX_GEOMETRY_CORRECTION / PSX_PERSPECTIVE_TEXTURING /
  PSX_PGXP_CPU_MODE (validation path: free-running headless boots arm
  from the first vertex); census grew produced/swc2_stores and the pgxp
  verb reports suppress/active gate state.

Validated: PSXRecomp_pgxp.exe boots the recompiled BIOS with hooks armed
(engine active, per-vertex lookups flowing; the BIOS shell has no RTPS
content so produced=0 there is correct - coverage measurement moves to a
3D title in phase 3).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 19:03:36 -07:00
Matthew Stanley 2ba74f3b4b pgxp: land clean-room value-propagation engine (phases 0+1, issue #92)
The G1.2/G1.3 mechanism: per-word RAM/scratchpad + per-GPR + per-GTE-reg
shadows carrying sub-pixel projections BY PROVENANCE, validated against
the actual guest word on every read (never guessed from rounded position
- the measured 93.1%-ambiguous G1.4 dead end). Clean-room from psx-spx +
public design docs; vendored duckstation (CC BY-NC-ND) and beetle-psx
(GPL) trees remain black-box oracles only - no code ported.

- runtime/src/pgxp.cpp + pgxp.h: engine, per-vertex GetPreciseVertex
  (dataflow -> ambiguity-gated position cache -> native) with truncation
  agreement + tolerance safeguards; stats; test accessors.
- pgxp_hooks.h: 5-entry hook funnel; PGXP_*() macros no-op unless
  -DPSX_PGXP=1 (codegen-time gate over ONE generated tree); appended
  PGXPHooks* table member in OverlayCallbacks (ABI bump ships with the
  Phase-2 emitter change).
- Both interpreters wired: loads/stores/COP2 + precision-carrying
  arithmetic (moves, add/sub, or-merge, 16-bit shifts, LUI, HI/LO).
- gte.cpp: RTPS feeds the GTE reg shadows; retired s_precise_sxy FIFO,
  hashed s_precision_store, and plain-store invalidation (redundant
  under validate-on-read; store hot path gets 3 calls back).
- gpu.c: prepare_precise_triangle rewritten per-vertex; perspective UVs
  share the same provenance and compose per triangle.
- [video] pgxp_cpu_mode / pgxp_tolerance keys; TCP pgxp verb live-
  toggles geometry/texture/cpu_mode/tolerance; geom_correction census
  grew the pgxp dataflow counters (G1.9 gate metric).
- tests: new pgxp_test (registered); gte_register_access_test updated
  to precise invalidation contract. 33/33 enabled tests green.

Also fixed while landing (both broke a fresh master tree):
- runtime.cmake: once-only psx_game_version.txt stamp (multi-target
  file(GENERATE) collision broke every fresh single-config configure).
- test_overlay_capture_retry: SDL3 rot (SDL_SetMainReady gone, inverted
  SDL_Init check) -> psx_sdl_init.

Tracked as beads-eio.3.48; postmortem + this landing: ENHANCEMENTS.md
G1-G1.10.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-15 18:34:47 -07:00
Alexandros Mandravillis 992f5b0bf0 build: keep SDL3 main implementation in one translation unit 2026-08-15 12:19:16 +03:00
Matthew Stanley 32c6b34986 fix(runtime): clarify PSX overlay controls 2026-08-14 19:12:37 -07:00
Matthew Stanley cab7d00f9a Fix PSX launcher hotkeys and audio persistence 2026-08-14 15:22:29 -07:00
Alex Vanderveen a9a61b4d47 Merge origin/master into feat/rbengine.
Keep recomp-net at occupied_mask (d65918f); master's pin was an ancestor.
Brings in rewind/save-state controls from master.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-14 02:57:25 -04:00
Alex Vanderveen 94cd223249 FMV Heal patch and build optimizations for launcher 2026-08-13 12:55:41 -04:00
Alex Vanderveen 9253f229a1 fmv heal patch + appicon 2026-08-13 10:37:18 -04:00
Alex Vanderveen 9482615b29 Pass lobby occupied_mask into recomp-net for sparse seats.
Bumps recomp-net so empty lobby seats no longer block READY/admit; launch
builds the mask from seated members (online + LAN).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-12 22:37:08 -04:00
Matthew Stanley cee9b97239 Add PSX rewind and save-state controls 2026-08-12 11:12:24 -07:00
Alex Vanderveen a42dd63b61 overlay rewind 2026-08-12 04:34:41 -04:00
Alex Vanderveen 554476457f rewind support 2026-08-12 03:51:50 -04:00
Alex Vanderveen 1c070dfe40 chore: bump recomp-net + retcomm-rbengine 2026-08-12 03:25:31 -04:00
Alex Vanderveen a73a5c1093 rewind feature 2026-08-12 02:42:30 -04:00
Alex Vanderveen 48a2a4dd7a hotfix 2026-08-11 20:34:19 -04:00
Alex Vanderveen 581d4e927c Merge origin/master into feat/legendofmanaetc
Resolve main.cpp by keeping ae_fill/rematch netplay bring-up and taking
master's mod-safe turbo_loads/skip_fmv apply (no pre-activation clobber).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 19:28:20 -04:00
Alex Vanderveen 12f4e3281e lobby rematch & bios hotswap stability 2026-08-11 18:59:19 -04:00
Alex Vanderveen 599d326dd0 default multitap and multitap hack, and savestate optimizations 2026-08-11 14:20:26 -04:00
Alex Vanderveen 49f7a7f668 hardening connectivity 2026-08-11 11:57:44 -04:00
Alex Vanderveen 4e8900e6fe bios netplay patch 2026-08-10 23:20:30 -04:00
Alex Vanderveen 91d683d87d bios hotfix 2026-08-10 22:53:17 -04:00
Alex Vanderveen 71adcfa2c0 BIOS pathing 2026-08-10 22:17:30 -04:00
Matthew Stanley f0cfa92afa config: retire the legacy generic turbo_loads switch — load acceleration is mod-only
Load acceleration moved to the Mods catalog in 125d84d
(psx.enhancement.fast-loading "Fast Loading (host pacing)" and
psx.enhancement.cd-speed, both `game_id = "*"` so they ship with every
title, both default-off), and recomp-ui deliberately stopped drawing a
generic Turbo loads row. But the legacy switch was left live here with
`offer_turbo_loads` defaulting TRUE, so any title that had not explicitly
migrated still got turbo forced on — with no UI to turn it back off.

That shipped to players. MegaManX6Recomp v1.0.4 and v1.0.5 both carry
`[runtime] turbo_loads = true` in the game.toml inside the release zip
(verified by extracting the artifacts). Two paths forced it on:

  * game.toml [runtime] turbo_loads set g_turbo_loads_enabled directly;
  * a stale [video] turbo_loads in settings.toml was restored, and the
    seed write persisted it — so one run latched the value permanently
    and no later game.toml change could undo it.

Reported as MegaManX6Recomp#14: the WARNING screen self-advances and load
spinners run fast, with Turbo confirmed off in Mods. Tomba 2 hit the same
defect (fixed per-title), and MMX5 is also unmigrated. Third occurrence of
one config default, so fix the class instead of the titles.

Both keys are still PARSED, so existing configs load without error, but
neither is honoured:

  * offer_turbo_loads defaults false and turbo_loads_offered becomes a
    constexpr false, matching how ws_offered / skip_fmv_offered /
    frame_interpolation_offered already model mod-owned features. No title
    can offer the generic switch, so forgetting to migrate is no longer
    punished.
  * game.toml turbo_loads logs a deprecation line naming the Fast Loading
    mod and enables nothing.
  * settings.toml [video] turbo_loads is neither restored nor written back
    out, so the stale row is dropped on the first save — same write-only
    latch reasoning already documented for fast_boot, which bit harder here
    because there was no UI control at all.

Also fixes a related hole found while auditing: the in-game Settings apply
path wrote both g_turbo_loads_enabled and g_auto_skip_fmv from a launcher
snapshot taken BEFORE mod_runtime_activate_plugins() ran, so the first
in-game Apply silently turned a player's enabled Fast Loading or Tweaks FMV
feature back off. Both are now gated on their offered flags.

The supported surfaces are unchanged: the Fast Loading / CD Speed mod
plugins still enable acceleration (verified: "mod selected 8x load
acceleration"), and the `turbo_loads` TCP debug command still toggles it
for development.

Verified against MMX6 built on this framework: with game.toml
`turbo_loads = true` AND `offer_turbo_loads = true` AND a stale
settings.toml `turbo_loads = true`, both deprecation lines fire and the
debug server reports enabled=0, turbo_frames=0. With the keys removed and
no mods enabled, it boots silently with enabled=0.

test_mod_load_acceleration.py is updated to pin the new contract; it also
had a stale assertion on the old 2..16 multiplier range, which is now
pinned to the symbolic PSX_MOD_LOAD_ACCEL_MAX bound. The guard-test suite
goes from 9 pre-existing failures to 8 (no new failures; this one fixed).

Refs: beads-eio.3.26, MegaManX6Recomp#14

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 18:52:16 -07:00
Alex Vanderveen 61279a9d01 bios select and rematch pathing fix 2026-08-10 20:44:18 -04:00
Matt Stanley 52d6a5440d Merge pull request #127 from mstan/hotfix/windows-installations
Fix Windows setup installs: require_generated cmdline + BIOS picker.
2026-08-09 21:22:51 -07:00
Matthew Stanley 41658ce997 launcher: ignore hidden stale BIOS paths 2026-08-09 20:44:26 -07:00
Matthew Stanley 4af7025f3d launcher: gate disc netplay diagnostics by capability 2026-08-09 20:03:10 -07:00
Alex Vanderveen 6c0d343077 Fix Windows setup installs: require_generated cmdline + BIOS picker.
Pass generated shard paths via a SOURCES_FILE so cmake -P is not killed by
CreateProcess's ~8191-char limit, and keep has_bios on for OpenBIOS-only
setup SDKs so the first-run wizard still offers SCPH1001.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-09 22:57:18 -04:00
Matthew Stanley e102688227 launcher: make PSX display enhancements mod-only 2026-08-09 19:41:44 -07:00
Alex Vanderveen 2918a4ef0c Merge branch 'master' of https://github.com/mstan/psxrecomp 2026-08-09 22:25:24 -04:00
Alex Vanderveen 47d1bf147b stomp mods in netplay 2026-08-09 22:24:48 -04:00
Matthew Stanley 0179d941ef input: keep keyboard/mouse binds live alongside a routed gamepad
Routing a player to a controller silently discarded every keybinds.ini and
mouse bind, which defeats the pad-in-hand plus mouse-for-aiming combination
those binds exist for.

This is the same behaviour change as the original commit in PR #107, but
applied through pad_sources_for() rather than to the button merge alone. That
distinction is the point: every consumer of the source set - the button merge,
the HYBRID auto-switch detectors and the analog stick fold - now learns about
the keyboard in the same instant.

Widening only the button merge (the original shape) let a keyboard D-pad press
assert the D-pad bits while hybrid_dpad_active never saw them, so a mod-driven
hybrid pad would report D-pad input while still presenting ANALOG - the exact
failure the hybrid logic exists to prevent, and silent. Commit 3ba40b02 had
previously removed a keyboard-always-P1 behaviour for related reasons.

The PSX pad word is active-low and the merge is an AND, so an unpressed source
is a no-op and pad-only players are unaffected.

NEEDS HANDS-ON VALIDATION: Tomba's hybrid controller mod is the only consumer
of HYBRID mode. It should be exercised with a controller routed AND keyboard
binds live, confirming the pad still auto-switches. If the two cannot coexist,
the agreed fallback is for the mod to disable keyboard/mouse dual binding while
active, documented in the mod.

Co-Authored-By: Alexandros Mandravillis <Alexbeav@live.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 19:07:55 -07:00
Matthew Stanley 20a8f4ad08 input: make Hybrid a mod-only mode, not a selectable one
Hybrid kept reappearing in titles that never meant to ship it, because it was
the ZERO value of PadMode and therefore the default everywhere: PlayerInput,
p1_mode/p2_mode, ctrl_locked_*, and default_p1/p2_mode all initialised to it.
A game then had to opt OUT with [controller] allow_hybrid = false, and every
shipping title did exactly that or pinned a mode - so no title actually ran it.

Hybrid now has exactly one route: a trusted game plugin calling
psx_mod_set_controller_mode_override(), which is how Tomba's hybrid controller
mod already requests it. Everything that made it reachable by accident is gone:

  - defaults are ANALOG (PlayerInput, p1/p2, ctrl_locked_*, default_p1/p2)
  - [controller] allow_hybrid is removed, along with the startup clamp that
    existed only to undo the bad default
  - game.toml default_mode/p1_mode/p2_mode = hybrid now THROWS, naming the
    mod API as the only route, rather than being silently coerced
  - a stale settings.toml hybrid migrates to analog via
    pad_mode_from_settings_string(); a user should not fail to launch over a
    value they never typed
  - pad_mode_to_string() never writes hybrid back

Deliberately KEPT, because the mod runs on it: PAD_MODE_HYBRID,
PSX_MOD_CONTROLLER_HYBRID, psx_mod_set_controller_mode_override(),
hybrid_stick_active/hybrid_dpad_active, PlayerInput::hybrid_analog and
psx_keybinds_dpad_active.

Paired with the recomp-ui change that drops the Hybrid segment and the
allow_hybrid field from RecompLauncherCGameInfo - the two must land together.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 19:06:13 -07:00
Matthew Stanley fc5b07f677 input: derive every pad source from one predicate (pad_sources_for)
The runtime decided which sources may drive a pad slot in three independent
places - the button merge in capture_pad_slot, the HYBRID analog/digital
auto-switch (hybrid_stick_active / hybrid_dpad_active), and the analog stick
fold. Nothing kept them in step.

That is a live hazard rather than a tidiness issue. If the button merge is
widened without widening the hybrid detectors, a source can assert the D-pad
while the hybrid state machine never sees it, so the pad reports D-pad presses
while still presenting ANALOG and never falls back to digital - the exact
failure the hybrid logic exists to prevent, and silent when it happens.
Commit 3ba40b02 previously removed a keyboard-always-P1 behaviour for related
reasons; the hybrid gates were written assuming it stayed removed.

pad_sources_for(p, dev_here) now returns the source set once (device,
keybinds, all_pads) and all three consumers read it. Input-routing POLICY
becomes a change to that one function instead of three conditions that must
be edited together.

Pure refactor - behaviour is unchanged:
  device   == (p.kind != 0), as before
  keybinds == (p.kind == 1 || dev_here), the same expression the hybrid
              D-pad detector already used
  all_pads == dev_here, as before
dev_here implies slot 0, so the previously hardcoded player 1 in
pad_from_keyboard(1) and psx_keybinds_sticks(keys, 1, ...) is the same value
as `player`. Where a consumer is now reached that was not before (kind==1 in
analog mode re-entering psx_keybinds_sticks), the call is idempotent: it only
sets fixed extremes on held binds, and pad_sticks_for already applied it with
the same player.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 19:04:12 -07:00
Matthew Stanley 6042e82613 fix(cdrom): restore the "disc could not be mounted" check PR #110 dropped
cdrom_init() is deliberately non-fatal -- BIOS-only targets run with an empty
drive on purpose -- so when a disc IS requested and nothing mounts, the game
boots into an empty drive and renders nothing. That is the "black screen on a
.cue that works as a .bin" symptom.

The earlier validate_disc_for_launch() pass cannot catch it: identify_disc()
reads the data-track FILE directly, so a cue whose sheet the mounting reader
rejects still earns a green "Disc verified" badge and the player is left
staring at black with no explanation.

Master reports the actual failure and names the likely cause; PR #110 dropped
the check while keeping every part it depends on -- cdrom_has_disc() in
cdrom.h, resolve_disc_path()/DiscPathResolution in disc_path.h, and
launcher_warning() -- so only the call site and the disc_path.h include were
missing. Block restored verbatim from origin/master.

Verified no false positive: Tomba boots past cdrom_init into gameplay with a
good disc (PSX_NO_LAUNCHER=1, reaches the in-game window). The negative case (a
cue that verifies but will not mount) was not synthesised.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 16:49:43 -07:00
Matthew Stanley e8441c6a3d fix(bios_hle): decide call-HLE and boot-skip via psx_bios_hle_plan again
PR #110 replaced master's plan() call with an inline
"(bios_hle && !keep_intro) || fast_boot" boot-skip decision that passes
bios_hle straight through as the call-HLE axis. That conflates two axes with
DIFFERENT per-image requirements, which is exactly the bug bios_hle_plan.c was
written to fix: call-HLE needs a DeliverEvent anchor (deliver_event_ret), the
boot-skip needs only shell_entry_phys.

On an image exporting no DeliverEvent anchor -- OpenBIOS, which is bundled and
default for several titles, and bios_hle defaults ON -- the inline form turns
call-HLE on anyway, servicing B0 events with mismatched semantics. That is the
OpenBIOS bring-up wedge: the shell menu hangs in a CD-event wait under HLE and
boots fine under LLE.

Restores the plan() call and both denial notices, so an unavailable axis is
reported rather than silently taken (or silently cancelling the other).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 15:51:57 -07:00
Matthew Stanley b98633734f fix(bios,input): restore master call sites PR #110 dropped from main.cpp
BIOS
  - resolve_bios_path() now consults PSXRecompV4::resolve_bios_rom() again, so
    either filename convention resolves: a dump folder holding
    "US-PSX-SCPH1001.BIN" satisfies a request for "SCPH1001.BIN". Restored at
    both rungs (direct hit and the exe-dir upward walk).
  - gi.has_bios = psx_bios_has_selectable() restores the launcher BIOS row.
    It asks the registry rather than psx_bios_image, which is not populated
    until a backend activates.

Input
  - anti_deadzone was gone entirely: PR #110 inlined the stick maths into
    axes_to_pad_pair() and implemented only the deadzone half, so [controller]
    anti_deadzone in game.toml was parsed and silently ignored. axes_to_pad_pair
    now calls the shared psx_stick_to_dualshock() (runtime/src/psx_stick.c),
    keeping PR's per-player deadzone and restoring master's anti-deadzone.
  - Launcher device<->source mapping used raw string compares, so a hand-edited
    "Keyboard" or " none " was misclassified as a gamepad. Both read sites and
    both writeback sites now use launcher_source_from_device(), which trims and
    lowercases first. PR's N-player loop and GUID preservation are kept -- they
    supersede master's 2-player launcher_device_from_source pair.

Shutdown
  - autocompile_shutdown() restored ahead of capture teardown, so closing the
    window no longer leaves cmd/python/gcc running against cache and capture
    files while the main thread does synchronous shutdown work (the window
    appears frozen until that process tree exits).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 15:50:50 -07:00
Matthew Stanley 32047212b7 fix(widescreen): restore the five gpu_ws_set_* call sites PR #110 lost
PR #110 keeps the widescreen engine and most of its configuration (full_2d,
bg2d, clear_reveal, cull_guard_pixels, explicit/slti/negsub/vxrange/depth/
plane_nx/xclip cull sites, dome sites) but drops five setters that master
calls from the same [widescreen] config block:

  - gpu_ws_set_auto_ui_squash
  - gpu_ws_set_activation_guard_pixels
  - gpu_ws_set_cull_keep_sites
  - gpu_ws_set_angle_sites
  - gpu_ws_set_aspect_cone

All five still have live config fields in recompiler/src/config_loader.h and
live implementations in runtime/src/gpu.c -- only the main.cpp call sites were
missing, so every game.toml that configures them was silently ignored and the
funnel-cull / aspect-cone quality work never engaged.

Blocks are taken verbatim from origin/master and inserted at the same points
in the config block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 15:28:37 -07:00
Matthew Stanley 7e4c01d529 fix(mods): restore the four mod_runtime hooks PR #110 lost from main.cpp
PR #110 keeps almost the whole mods integration - mod_plugins.h, every
psx_mod_set_* callback, mod_runtime_commit, mod_runtime_activate_plugins -
but four call sites present on master are absent, which leaves the entire
feature inert:

  - mod_runtime_initialize          scan <exe_dir>/mods + load persisted state
  - mod_runtime_launcher_provider   gi.mods, the launcher Mods tab
  - mod_runtime_effective_disc_path mount a mod's private patched image
  - mod_runtime_enable_disc_patches apply exe/overlay patches after the guard

Without initialize() nothing else can fire, so a build stages all of a
title's mod packages next to the exe and then never reads them: Tomba showed
an empty Mods tab and fell back to the legacy Display "View mode" row instead
of the widescreen mod.

gi.mods is set at both launcher GameInfo sites so the tab appears on either
path. Blocks are taken verbatim from origin/master.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 15:26:39 -07:00
Alex Vanderveen ceee034d59 Merge origin/CTR-Netplay into integrate/game-codegen-hooks-into-rollback
Keep both psx_bss.h (BSS rings) and nd_intro_ot.h from CTR-Netplay.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-08 22:53:34 -04:00