Commit Graph

109 Commits

Author SHA1 Message Date
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 4073e2311c rollback + fmv + connectivity 2026-08-06 20:34:50 -04:00
Alex Vanderveen 652be7ba02 rollback FMV patches and overlay 2026-08-06 00:52:14 -04:00
Matthew Stanley c8b692eda2 feat(video): opt-in sub-pixel vertex precision + perspective-correct textures
Makes the parked projection/perspective work reachable and gets it into the
renderers people actually use. Addresses issue #92 (PGXP-style geometry and
texture correction).

The GTE side cache, SWC2 RAM provenance, GP0 triangle preparation and the
software-renderer consumption path already landed in 2ceaf5a ("park projection
and perspective correction", from kem0x PR #14), but were unreachable: the
generic setters gte_geometry_correction_set() / gpu_texture_correction_set()
had no production caller, and the corrected vertices went straight to
sw_set_precise_triangle(), bypassing the renderer vtable — while the default
renderer is OpenGL.

This adds:

- [video] geometry_correction and [video] perspective_texturing, in game.toml
  and settings.toml, both defaulting false. Independent knobs; the launcher
  seed marks them present so a save round-trips a hand-edited key instead of
  dropping it. Startup names the active pair, and notes when geometry
  correction is on below supersampling 2 (where it cannot be seen).
- gr_set_precise_triangle() / gr_set_perspective_triangle() on the
  GpuRenderBackend vtable, so gpu.c hands the correction to whichever backend
  is live rather than to the software rasterizer directly. NULL entries no-op.
- OpenGL and Vulkan consumption. Positions are already float end-to-end, so
  sub-pixel vertices drop in; the readback dirty rect widens by one pixel to
  cover them. Perspective UVs use a per-vertex a_q weight and clip coordinates
  pre-multiplied by w = 1/q, letting the hardware's own perspective divide
  interpolate a smooth UV varying beside the affine noperspective one. a_q == 0
  — the default, and what every prim gets with the feature off — makes w
  exactly 1.0 and selects the affine varying, so the faithful path is the
  pre-feature pipeline unchanged.

The PS1-visible GTE SXY FIFO stays integer either way: guest-side screen-bounds
culling and SXY readback are untouched, and this remains visual-only.

Also fixes a pre-existing concurrent-build race found while validating: every
runtime target runs embed_spirv.py over the same shaders, and each wrote
"<shader>.spv" next to the source, so under -j N one process deleted the file
another had just written (FileNotFoundError on a shader that compiled fine).
The intermediates now go to a per-invocation temp dir.

Parked-work provenance retained; see ENHANCEMENTS.md G1.

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 14:02:58 -07:00
Matthew Stanley 1dcab6a2ff Merge remote-tracking branch 'origin/master' into codex/debug-input-route-20260803 2026-08-03 23:31:59 -07:00
Matthew Stanley 3e89dbc6c2 widescreen: support MMX4 background refill layout 2026-08-03 23:31:52 -07:00
Matthew Stanley bc6b277c94 feat(mods): add GPU DMA enhancement memory 2026-08-03 15:55:47 -07:00
Matthew Stanley b2af4e89c9 feat(mods): add trusted game enhancement hooks 2026-08-03 15:17:39 -07: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 4ddd2d01b9 rollback patches 2026-08-01 14:13:58 -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 fe403e6ce1 rollback patches 2026-07-31 17:14:35 -04:00
Alex Vanderveen b3d99b05ff rollback patching 2026-07-30 17:24:20 -04:00
Alex Vanderveen 92efb5c4fd no mods in MP, minor patches 2026-07-29 02:40:50 -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 a292a7c136 Add activation-only widescreen cull margin 2026-07-28 11:08:03 -07:00
Matthew Stanley c1eb052ca3 runtime: remove dead MMX6 host-side reveal 2026-07-27 19:30:48 -07:00
Matthew Stanley 63d8f88dc5 runtime: group front-layer UI for widescreen 2026-07-27 15:54:23 -07:00
Matthew Stanley 49b57f4178 docs(gpu): correct the MMX6 widescreen comments; record what is safe to delete
Comment-only. No compiled code changes -- the sole non-comment diff line moves
a trailing comment off the g_mmx6_hostside declaration into a block above it;
the declaration itself is byte-identical.

A survey of the mmx6-named widescreen symbols found the existing comments
misleading in a way that invites a dangerous cleanup, so the findings are
recorded in the source next to the code they describe.

1. "Compatibility entry points for already-generated MMX6 sources" (gpu.h) was
   wrong. These are not MMX6 compat shims and are not safe to delete. They are
   the widescreen-2D entry points the recompiler emits for ANY title with a
   [widescreen.bg2d] block, and live generated code in several non-MMX6 repos
   links them today:
     cols/startcol/startx/stream_left/stream_right
         -> CrashBash, MegaManX5, Tsumu (+ -release)
     undercap
         -> Ape, CrashBash, MMX4, MMX5, Tsumu, Vigilante8, THPS2
   Each forwards to its psx_ws_bg2d_* twin, which is the real implementation.
   Only the name is historical. Renaming is not runtime-only: the names come
   from code_generator.cpp, which is in codegen_hash_sources.cmake, so it rolls
   the overlay cache tag and forces regen + reshard of every title.

2. Host-side reveal (g_mmx6_hostside) is dead in every shipping build, which
   the previous "kept inert pending removal" note understated. Nothing sets it
   but the mmx6_reveal debug command, PSX_DEBUG_TOOLS is OFF for Release, and
   no generated source anywhere references a host-side symbol. Noted that
   removing it is the last step decoupling the generic psx_ws_bg2d_* API from
   MMX6 -- mmx6_hostside_active() is currently embedded in the ternaries of
   psx_ws_bg2d_cols/startcol/startx -- and listed the symbols that go with it.

3. BG buffer relocation is a parked FEATURE behind a load-bearing SYMBOL, a
   distinction the old comment did not draw. With g_mmx6_reloc == 0 both hooks
   return their argument unchanged, but MegaManX6Recomp/game.toml names the
   bufbase/cap instruction sites, so the emitter writes calls into generated
   code and psx_ws_mmx6_bg_bufbase is genuinely called by MMX6's generated C.
   The supportable cleanup is to gut the bodies to identity and keep the
   symbols, not to delete the functions.

Removal of (2) and (3) is deliberately deferred: it touches the renderer and
wants its own session with MMX6 revalidation.

Verified: gcc -fsyntax-only on gpu.c exits clean (an earlier draft embedded
"*/" inside a block comment and broke the parse -- caught before commit);
ctest 29/29 green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 11:49:31 -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 fa408aae50 Merge trusted mod plugin support 2026-07-26 21:05:03 -07:00
Matthew Stanley a4afb828ac feat(mods): add trusted static vblank plugins 2026-07-26 18:59:10 -07:00
Matthew Stanley 436fe14101 widescreen: support guarded object participation overrides 2026-07-25 23:24:41 -07:00
Rick G 2715b7483a gpu: union native-wide host reject with guest draw area (#79)
Preserve wider guest staging and composition regions while extending framebuffer draw bounds for native-wide margins. Regression-tested in 16:9 on Tomba and Mega Man X6 with bundled OpenBIOS.
2026-07-25 19:42:30 -07:00
OpokXeno 0a8f8ac98c widescreen: stretch backdrop X-stores about screen centre in native-wide mode (#78)
Stretch explicitly configured backdrop X-store sites across the native-wide surface while leaving 4:3, FMV, menu, and unconfigured games unchanged.\n\nValidated by the contributor on Xenogears Battle Mountain and regression-tested on Tomba's Watch Tower flower backdrop with bundled OpenBIOS.
2026-07-25 19:15:30 -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
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 c34c1460e0 Merge remote-tracking branch 'refs/remotes/origin/master' 2026-07-23 01:27:44 -04:00
Alex Vanderveen 1347e49dfc patch FMV playback, fix artifact flicker on cutover to new video 2026-07-23 01:22:11 -04:00
Matthew Stanley cece00296a feat: add adaptive native widescreen
Add a resize-driven aspect option, keep native-wide culling and spawning hooks engaged across live aspect changes, and widen host GP0 draw-area pruning only for the active wide framebuffer.

Credit OpokXeno's independently discovered draw-area pruning fix documented in PR #73.

Co-authored-by: Opok <novelasevilliousesp@gmail.com>
2026-07-22 21:59:31 -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
Opok 4412bc7a7d widescreen: add per-primitive X-reject bound-load cull sites
Add opt-in [widescreen.cull] xclip_load_sites: a configured `lw rt,off(rs)`
loading a per-primitive X-reject bound (sltu-compared against ANDI-masked
u16 screen X) routes through psx_ws_xclip_bound() - INT32_MAX while the
margins are revealed (reject disabled; the wide-surface scissor clips the
overflow, wrapped off-left u16 coords pass), vanilla value at 4:3. Matched
native codegen emit and interpreter hook; overlay ABI v18 forwarder (NULL
preserves the vanilla loaded value); codegen ver 8. Parser, codegen and
overlay-mismatch regression coverage.

Split from #49: replaces the xclip_globals RAM poke with a recompile-time
instruction transform so native shards and the interpreter behave identically.
2026-07-21 15:02:20 -07:00
Opok a5fdf1ad9a widescreen: add side frustum-plane normal-X cull sites
Add opt-in [widescreen.cull] plane_nx_sites: a configured `lw rt,off(rs)`
loading the X component of a side frustum-plane normal (sign-tested per
corner, dot = nx*px + nz*pz) routes through psx_ws_plane_nx() — scaled by
the inverse aspect factor (4*den)/(3*num) while the margins are revealed,
widening the plane cone by exactly atan((3*num)/(4*den)*tan(theta));
identity at 4:3. Matched native codegen emit and interpreter hook; overlay
ABI v17 forwarder (NULL preserves the vanilla normal); codegen ver 7.
Parser, codegen and overlay-mismatch regression coverage.

Split from #49: replaces the plane sign-test RAM pokes with a
recompile-time instruction transform so native shards and the interpreter
behave identically.
2026-07-21 14:38:55 -07:00
Matthew Stanley e38daa3415 fix: mirror widescreen range sites in interpreter
Register configured range_sites with the dirty-RAM interpreter so overlay-resident classifiers use the same two-margin widening already emitted by native codegen.

Co-authored-by: Opok <novelasevilliousesp@gmail.com>
2026-07-20 19:39:36 -07:00
Matthew Stanley fa626bdb4c feat: add aspect-scaled depth cull sites
Add opt-in slti/sltiu far-bound scaling with matched native and interpreter semantics, correct immediate sign extension, and an overlay ABI forwarder for live aspect state.

Co-authored-by: Opok <novelasevilliousesp@gmail.com>
2026-07-20 12:14:18 -07:00
Matthew Stanley 288926111f feat: add masked-u16 widescreen cull sites
Add a shared native/interpreter helper for sltiu classifiers operating on ANDI-masked 16-bit screen X values, preserving MIPS immediate sign extension and overlay linkage.

Co-authored-by: Opok <novelasevilliousesp@gmail.com>
2026-07-20 12:11:58 -07:00
Matthew Stanley bdeb106e5c feat: add negsub widescreen cull sites
Add an opt-in horizontal low-edge transform for subu rd,zero,rt classifiers, with matching native and dirty-RAM interpreter behavior and guarded overlay variants.

Co-authored-by: Opok <novelasevilliousesp@gmail.com>
2026-07-19 23:25:03 -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 2ceaf5abee feat: park projection and perspective correction
Adapted from https://github.com/mstan/psxrecomp/commit/ec889d6e5956fc4f34acfee41d87f30b24123b7f

Co-authored-by: Kareem Olim <kareemolim@gmail.com>
2026-07-14 23:06:38 -07:00
douglasjv 28165d6421 Expand Einhander player bounds for native widescreen 2026-07-14 23:06:05 -07:00
douglasjv 9a8cdb6772 Add typed native-wide textured edge expansion 2026-07-14 23:04:55 -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 35684c5385 gpu: recognize shaded-polyline terminators in either phase
Adapted from NyperYuhgard's PR #13.

Co-authored-by: NyperYuhgard <93950153+NyperYuhgard@users.noreply.github.com>
2026-07-14 18:34:14 -07:00
Matthew Stanley fb585541ec opengl: sustain full-rate gameplay and FMV presentation 2026-07-11 14:07:17 -07:00
Matthew Stanley a0818de0b4 Merge feat/ws-2d-scene-pillarbox: 2D-only scenes pillarbox in native-wide; present ring; full-pad input injection
Tomba 16:9: rooms, sky falls, and task-card sequences presented stretched
because native-wide's 2D-backdrop stretch fires wholesale in scenes whose
background phase never ends. Such scenes now present native 4:3 from the
faithful canonical buffer, keyed on DEEP UNTAGGED POLYGON OVERHANG (>=24px
past the canonical window, >=4 polys, sustained 2 frames) — the only world
signal that survived adversarial scenes (shaded prims, GTE volume, any-poly
and shallow overhang all falsified by census evidence; lineage in gpu.c).
Scoped to sprite-tag titles; full_2d (MMX6) and gte_game_mode (Ape) paths
unchanged. Plus: native-wide never stretches a canonical-width game frame
(fallback pillarboxes); always-on present-classification ring (TCP
present_ring) across all backends; debug input injection drives the full
pad model (hybrid d-pad drop + stick axes); savestate TCP honesty; census
tagged column + ws_hud_mode A/B (HUD-corners deferred: ENHANCEMENTS.md W2).
USER-VALIDATED on Tomba (SCUS-94236).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 15:41:52 -07:00
Matthew Stanley d57ce7a121 widescreen: census tagged column + ws_hud_mode A/B; defer HUD-corners for tag titles (ENHANCEMENTS W2)
The Tomba nw_hud_corners experiment surfaced two blockers, both documented
in ENHANCEMENTS.md W2 with census evidence: composite dialog boxes spanning
zone boundaries tear (end caps pulled to opposite edges), and the AP counter
renders through the TAGGED sprite funnel so the untagged-only gate skips it.
Groundwork kept for the next attempt:
- WsCensusEntry gains a `tagged` column (ws_census CSV) so funnel membership
  is measurable per prim.
- TCP ws_hud_mode {"tag_rects":0|1} live-A/Bs the tagged-rect gate.
Tomba's game.toml reverts nw_hud_corners to false (its own repo).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 15:37:59 -07:00