diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index dbf66d8b..d49b4da7 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -159,7 +159,7 @@ below). | Crash on save slots 1/3/4, plus a host BSOD (fltmgr.sys) | decided | #94 | Needs a repro. Two maintainer retest requests (v0.3.0, v0.4.0) got no reply. Likely D299/D301 (save-slot crash, fixed) and D344 (BSOD on exit, fixed). **Decided 2026-10-01: close as stale when the release ships**, pointing at D299/D301/D344; no GitHub activity before then. | | Authored mip chains not sampled for explicit-LOD textures | post-1.0 | D323 | Distant textures use driver mips instead of Rare's hand-authored chain (heaviest on Statue/Aztec). Parked as a fidelity enhancement. **Decided 2026-10-01:** after 1.0, together with the LOD-fraction approximation as one "real RDP LOD" project. | | Approximations in the software RSP | post-1.0 | `gfx_pc.cpp` `G_CCMUX_LOD_FRACTION`; D323 | The LOD-fraction CC input is an eyeballed approximation, bundled with D323 as one "real RDP LOD" project after 1.0 (2026-09-30 triage). **WrapFix settled 2026-10-02:** the maintainer checked the Depot building ceilings against 1964 with the default `Video.WrapFix = 0` and they look right, so the default stays off (the opt-in knob remains; RC3/D167). | -| Latent 64-bit ABI hazards | partial | D441, #107, #108; AUDIT-M6 `struct player`/`struct hand` raw offsets (porting-notes §A1) | **State (2026-10-03, D441):** complete census (local `scratch/d441/`; many hits are intentional `(s32)&ANIM_DATA_*` offsets, D34); 17 files widened to `uintptr_t` under `#ifdef PORT`; 35 sign-extension sites fixed; CI ratchet `tools_pc/abi_ratchet.py` (baseline 389); arena windows centralised (`port/include/portaddr.h`); tier-1 high-arena build (`GE_HIGHARENA_BASE=0x90000000`) runs the menu and `-level_09` pixel-identical to default. D478: nothing live on the current layout; the rest would bite only on macOS/ARM/ASLR. **Sweep (2026-10-05):** tier-1 all-level sweep done, 21/21 PASS, no fix batches, ratchet unchanged (389), recipe in the D441 entry. **Owed:** tier 2 (above 4 GiB; u32 slots widened); store-to-u32 vs arithmetic-only tag per site (`portHostToN64` under macOS port_addr); `mema.c` widening (D453); `initanitable.c` heap slots; GE_DETERM wall-clock timers (D117 follow-up, blocks using determinism mode for frame gates). **#108:** widening the `sndPlaySfx` bound disables the guard everywhere; prefer a range check. | +| Latent 64-bit ABI hazards | partial | D441, #107, #108; AUDIT-M6 `struct player`/`struct hand` raw offsets (porting-notes §A1) | **State (2026-10-03, D441):** complete census (local `scratch/d441/`; many hits are intentional `(s32)&ANIM_DATA_*` offsets, D34); 17 files widened to `uintptr_t` under `#ifdef PORT`; 35 sign-extension sites fixed; CI ratchet `tools_pc/abi_ratchet.py` (baseline 389); arena windows centralised (`port/include/portaddr.h`); tier-1 high-arena build (`GE_HIGHARENA_BASE=0x90000000`) runs the menu and `-level_09` pixel-identical to default. D478: nothing live on the current layout; the rest would bite only on macOS/ARM/ASLR. **Sweep (2026-10-05):** tier-1 all-level sweep done, 21/21 PASS, no fix batches, ratchet unchanged (389), recipe in the D441 entry. **Owed:** tier 2 (above 4 GiB; u32 slots widened); store-to-u32 vs arithmetic-only tag per site (`portHostToN64` under macOS port_addr); `mema.c` widening (D453); `initanitable.c` heap slots; GE_DETERM wall-clock timers (D117 follow-up, blocks using determinism mode for frame gates). **#108:** widening the `sndPlaySfx` bound disables the guard everywhere; prefer a range check — **done in v0.6.0 as D573** (address-window check). | | Port-memory vertex/pool bounds hardening | post-1.0 (decided; not a v0.5.0 blocker) | D545, D549 | D545 (rockets through floor, fixed) left one residual: ~1 dropped rocket in ~60 spawns (Archives, akimbo), consistent with the room-pool hypothesis (`bgBuildRoomVtxBounds` allocation failing leaves no bounds) but unproven; D549 (same stack-overflow class in grenade/knife/object throws) is fixed. Both shipped. Proposed hardening: a port-memory bounds table validating vtx/pool pointers against the known arena windows. | ## 3. Verification debt (fixed; a live check is owed) @@ -188,7 +188,7 @@ A single campaign pass with these on the checklist would clear most of them. | Item | Status | Refs | Notes | |---|---|---|---| -| macOS (Apple Silicon) / ARM64 Linux | open (target 0.9.0/1.0, maintainer 2026-10-02; **scope 2026-10-08: Apple Silicon only, experimental in v0.6.0**) | PRs #88, #95; #101 | Outside drafts, parked until after 1.0. **Address model decided (2026-09-30): port_addr (#95)**, a `portN64ToHost`/`PORT_N64PTR` chokepoint with a `PORT_ADDR_STRICT` validator. The integration branch is `macos-arm64` (renamed 2026-10-08 from `macos`; local + Forgejo mirror — the stale GitHub `origin/macos` stays until the no-GitHub rule lifts) with #88 (merged), #132 and #95 (open); nothing merges to `main` before the post-1.0 pass. **Scope decision (maintainer 2026-10-08): ship Apple Silicon only** — the x86_64 macOS path (#88) stays in-tree (identity at `PORT_ADDR_BASE==0`) but was **never verified on Intel hardware** and is out of release scope; **arm64 macOS is planned as *experimental* in v0.6.0** (the first release carrying a macOS build; owed before the release: D602 diagnosis, D600/D601 live confirmations, and a release-notes experimental marker on the `macos-arm64` artifact). **Open against `macos`:** #131 (self-hosted sweep scaffold, never run on a Mac; needs #95 first). **Status 2026-10-08:** D590 fixed the deterministic Windows `load_bg_file` SIGSEGV (the D588 bug class on the full-width `bg_addr_t` — plain casts, 5/5 Dam runs clean; the D589 A/B's Win side is unblocked); **D589's rev32 is ROOT-CAUSED as D591**: the decode-time pool is 134/134 byte-identical Mac/Win (the writer side is clean — the “pool holds the rev32” line is retired), and the reversal happens at the *import* — `gfx_tex_source_is_c_array` (`port/fast3d/gfx_pc.cpp`) mixes host-space and N64-raw-space in its range test, so on arm64 macOS (`PORT_ADDR_BASE=16 TiB`) every DRAM/cart texture source mis-classifies as a “C-compiled array” and `gfx_tex_normalize_source` bswaps it (a clean rev32 of the whole wide-pixel pool — the D219/M-114 pink-HUD symptom class). Fix in `9c59cbe7` (compare the host pointer directly; port-layer only, no-op at `PORT_ADDR_BASE==0`); **Windows verified byte-identical (400/400 import `r*.bin` + PPM unchanged), Mac A/B now verified 2026-10-08** (clean arm64 build at `25f92e09`: `GE_TEXN carray=0` on all probe lines, Mac `raw8` matches the Win baseline — the rev32 is gone). **D589 is now RESOLVED: the "second cause" (D592) was CLOSED as a non-issue 2026-10-08.** The "rock striping" that D592 tracked turned out to be a **false positive of a crude vertical-high-frequency (VHF) metric flagging natural rock grain**, *not* a GL-layer artifact: a `GE_TEXSTATE` GL-state probe showed the effective sampler state **and** the NPOT mip level counts are **byte-identical Win/Mac** (the Apple M3/Metal backend builds the full NPOT mip chain; the aniso extension is present on both; the NPOT rock texture gets `min=trilinear, mag=linear, aniso=4` on both sides), a 0-pink scan confirmed **D591 held**, and the **maintainer's live Mac look showed the Dam rendering clean** (no visible striping, ammo counter not pink, F10 menu fine). The NPOT `glGenerateMipmap` guard + companion single-level sampler fix (`9bed5904` / `82dbea9c`) were **reverted as dead weight** (`b80dcd08`, which also strips the `GE_TEXSTATE` probe). The genuine cross-platform symptom (the pink HUD) was **D591 (fixed, `9c59cbe7`)**. **D594 (FIXED): macOS partial input** — `GE_KEYLOG` **disproved** the cross-thread-poll suspect (WASD + LMB reach both the main-thread pump and the scheduler-thread poll); the real gap was the `actHeld` mouse gate on `current_menu == RUN_STAGE` (a forced `-level_NN` start leaves `current_menu == INVALID (-1)`, so the mouse was never read) plus the macOS `reconcileGrab` `windowFocused` gate. Fixed by matching PD's input model (in-stage = RUN_STAGE *or* INVALID; macOS grab = PD's MLOCK_ON, no focus gate) — LMB fire now works on the Mac (trackpad: LMB fire, two-finger = RMB/aim, Shift = ADS). **D595 (FIXED): the arm64-only SIGSEGV that firing then exposed** — `initResolveAnimTable` truncated the live `ptr_animation_table` host pointer to `(s32)`, dropping the 16 TiB `PORT_ADDR_BASE` → every AI hit/stagger `struck_anim` resolved to bogus low memory → crash in `modelSetAnimFrame` on the first AI hit-reaction. Fixed by reading the base at full pointer width (§A1; identity on x86_64). Both are the last input-blockers to a playable arm64 macOS build. (maintainer visual-sanity package: `scratch/d589-dam/ab3-mac/{d591_sbs_win_mac.png,d591_diffmap.png,D591-AB-SUMMARY.txt}`. `tools_pc/abi_ratchet.py` baseline refreshed for the branch. **On the next rebase onto `main`:** take #131's `selfhosted.yml`; drop #95's `crouched_rifle` hunk (our #120/D445 is correct) **and its `D420` finding + 2 `D420` code citations (D420 is #95's only new label; superseded by D445, dropped wholesale)**. **Relabel prep done (2026-10-08): no other relabelling is owed — #95's 9 genuine D-label citations (D290/D293/D294/D295/D297/D299/D406/D407/D408) mean the same things at #95's merge-base as in the current log (no drift); the `D418` hits in #95 are hex addresses in `getfpccsr.s`, not citations.** **§2 ABI-hazard sweep done 2026-10-08:** the macOS (Apple Silicon) full-campaign sweep — 21/21 levels end-to-end, 0 crash logs, 0 flakes (`scratch/d441/macsweep.sh`; record in the D441 entry) — exercised the tier-2 above-4-GiB hazards live (the D595 class) without a single firing; the structural widenings (u32 slots, `mema.c` D453, `initanitable.c` heap slots, #108 range check) stay owed. **Maintainer live pass done 2026-10-08 (Launch E, `MENU-LIVE-CHECKLIST.md`):** mouse / keyboard / pad in-level + F10 / menus all behave as on Win/Linux, **no `ge007.crash.log`** for the session; the `GE_KEYLOG` log shows real LMB events on both the main-thread and scheduler-poll sides — D594/D595 are live-verified (the E1 LMB-fire is the struck-animation ground truth). **Windows identity gate re-enabled 2026-10-08 (D596):** the stale `win/` goldens (pre-D565/D569) were regenerated from `e0a2d4b9` — `verify.sh sweep` 21/21 PASS on the branch tip; the `linux/`/`deck/` sets still need their own re-capture round on those boxes before any new cross-platform number is read. **D598 (RESOLVED by D600, live playtest owed):** the M3 chop on Cradle-class levels was fixed 2026-10-08 by **D600 (display-locked retrace tick)** — the scheduler's tick now paces to the display's refresh instead of assuming 60 Hz vsync (the CPU side was 6–17 ms per 300 frames, so the chop was display/swap pacing, not software-RSP cost); a live Cradle-class playtest confirmation is still owed. **D599–D604 (all 2026-10-08; on `macos-arm64`, pushed to Forgejo 2026-10-08):** D599 FIXED (arm64 SIGBUS on pad connect — `padTabPub` pointer-sized); D601 FIXED (interrupt-guarded sound-list mutation — cyclic list hung Archives stage load, live confirmation owed); D602 OPEN (end-credits SIGBUS — `langGet` rejects impossible slot offsets + one-shot bank diagnostic, needs a natural-flow re-trigger); D603 FIXED (2P `modelSetAnimFrame` SIGSEGV — `playerTick` re-bases the s32-held animation address; the live 2P session exercised it) and D604 FIXED + LIVE-CONFIRMED (2P respawn SIGSEGV — `mp_respawn_handler` stops truncating the pointer-typed `start_stan`; maintainer confirmed Enter/respawn in 2P with keyboard/mouse + 1 controller). **D597 (FIXED 2026-10-08): `GE_INPUTSCRIPT` `MLB`/`MRB`** sustained mouse-button tokens (slot 0) — headless scripted fire; the D595-class regression is now automatable (Mac sweep-fire no-crash run + no-env no-op run verified) and is the standing #131 runtime smoke check. | +| macOS (Apple Silicon) / ARM64 Linux | open (target 0.9.0/1.0, maintainer 2026-10-02; **scope 2026-10-08: Apple Silicon only, experimental in v0.6.0**) | PRs #88, #95; #101 | Outside drafts, parked until after 1.0. **Address model decided (2026-09-30): port_addr (#95)**, a `portN64ToHost`/`PORT_N64PTR` chokepoint with a `PORT_ADDR_STRICT` validator. The integration branch is `macos-arm64` (renamed 2026-10-08 from `macos`; local + Forgejo mirror) with #88 (merged), #132 (merged) and #95 (**merged 2026-10-10** — record merge `903095c9` in the v0.6.0 line + base merge `f87f4bcd`; the stale GitHub `origin/macos` mirror was deleted 2026-10-10, its lineage stays reachable via the record merge); nothing merges to `main` before the post-1.0 pass. **Scope decision (maintainer 2026-10-08): ship Apple Silicon only** — the x86_64 macOS path (#88) stays in-tree (identity at `PORT_ADDR_BASE==0`) but was **never verified on Intel hardware** and is out of release scope; **arm64 macOS is planned as *experimental* in v0.6.0** (the first release carrying a macOS build; owed before the release: D602 diagnosis, D600/D601 live confirmations, and a release-notes experimental marker on the `macos-arm64` artifact). **#131 (self-hosted sweep scaffold) closed 2026-10-10** — its content shipped in the v0.6.0 CI; the fork-friendly rework is parked locally (`park/ci-selfhosted-sweep-131`, `2fb8e52e`) for the v0.7.0 self-hosted runner item. **Status 2026-10-08:** D590 fixed the deterministic Windows `load_bg_file` SIGSEGV (the D588 bug class on the full-width `bg_addr_t` — plain casts, 5/5 Dam runs clean; the D589 A/B's Win side is unblocked); **D589's rev32 is ROOT-CAUSED as D591**: the decode-time pool is 134/134 byte-identical Mac/Win (the writer side is clean — the “pool holds the rev32” line is retired), and the reversal happens at the *import* — `gfx_tex_source_is_c_array` (`port/fast3d/gfx_pc.cpp`) mixes host-space and N64-raw-space in its range test, so on arm64 macOS (`PORT_ADDR_BASE=16 TiB`) every DRAM/cart texture source mis-classifies as a “C-compiled array” and `gfx_tex_normalize_source` bswaps it (a clean rev32 of the whole wide-pixel pool — the D219/M-114 pink-HUD symptom class). Fix in `9c59cbe7` (compare the host pointer directly; port-layer only, no-op at `PORT_ADDR_BASE==0`); **Windows verified byte-identical (400/400 import `r*.bin` + PPM unchanged), Mac A/B now verified 2026-10-08** (clean arm64 build at `25f92e09`: `GE_TEXN carray=0` on all probe lines, Mac `raw8` matches the Win baseline — the rev32 is gone). **D589 is now RESOLVED: the "second cause" (D592) was CLOSED as a non-issue 2026-10-08.** The "rock striping" that D592 tracked turned out to be a **false positive of a crude vertical-high-frequency (VHF) metric flagging natural rock grain**, *not* a GL-layer artifact: a `GE_TEXSTATE` GL-state probe showed the effective sampler state **and** the NPOT mip level counts are **byte-identical Win/Mac** (the Apple M3/Metal backend builds the full NPOT mip chain; the aniso extension is present on both; the NPOT rock texture gets `min=trilinear, mag=linear, aniso=4` on both sides), a 0-pink scan confirmed **D591 held**, and the **maintainer's live Mac look showed the Dam rendering clean** (no visible striping, ammo counter not pink, F10 menu fine). The NPOT `glGenerateMipmap` guard + companion single-level sampler fix (`9bed5904` / `82dbea9c`) were **reverted as dead weight** (`b80dcd08`, which also strips the `GE_TEXSTATE` probe). The genuine cross-platform symptom (the pink HUD) was **D591 (fixed, `9c59cbe7`)**. **D594 (FIXED): macOS partial input** — `GE_KEYLOG` **disproved** the cross-thread-poll suspect (WASD + LMB reach both the main-thread pump and the scheduler-thread poll); the real gap was the `actHeld` mouse gate on `current_menu == RUN_STAGE` (a forced `-level_NN` start leaves `current_menu == INVALID (-1)`, so the mouse was never read) plus the macOS `reconcileGrab` `windowFocused` gate. Fixed by matching PD's input model (in-stage = RUN_STAGE *or* INVALID; macOS grab = PD's MLOCK_ON, no focus gate) — LMB fire now works on the Mac (trackpad: LMB fire, two-finger = RMB/aim, Shift = ADS). **D595 (FIXED): the arm64-only SIGSEGV that firing then exposed** — `initResolveAnimTable` truncated the live `ptr_animation_table` host pointer to `(s32)`, dropping the 16 TiB `PORT_ADDR_BASE` → every AI hit/stagger `struck_anim` resolved to bogus low memory → crash in `modelSetAnimFrame` on the first AI hit-reaction. Fixed by reading the base at full pointer width (§A1; identity on x86_64). Both are the last input-blockers to a playable arm64 macOS build. (maintainer visual-sanity package: `scratch/d589-dam/ab3-mac/{d591_sbs_win_mac.png,d591_diffmap.png,D591-AB-SUMMARY.txt}`. `tools_pc/abi_ratchet.py` baseline refreshed for the branch. **Integration into the v0.6.0 line done (2026-10-10):** #95's `crouched_rifle` hunk and its `D420` label were dropped at integration (our #120/D445 is correct; D420 superseded wholesale); #131's fork-friendly `selfhosted.yml` was NOT taken into v0.6.0 (parked for the v0.7.0 self-hosted runner item). **Relabel prep done (2026-10-08): no other relabelling is owed — #95's 9 genuine D-label citations (D290/D293/D294/D295/D297/D299/D406/D407/D408) mean the same things at #95's merge-base as in the current log (no drift); the `D418` hits in #95 are hex addresses in `getfpccsr.s`, not citations.** **§2 ABI-hazard sweep done 2026-10-08:** the macOS (Apple Silicon) full-campaign sweep — 21/21 levels end-to-end, 0 crash logs, 0 flakes (`scratch/d441/macsweep.sh`; record in the D441 entry) — exercised the tier-2 above-4-GiB hazards live (the D595 class) without a single firing; the structural widenings (u32 slots, `mema.c` D453, `initanitable.c` heap slots, #108 range check) stay owed. **Maintainer live pass done 2026-10-08 (Launch E, `MENU-LIVE-CHECKLIST.md`):** mouse / keyboard / pad in-level + F10 / menus all behave as on Win/Linux, **no `ge007.crash.log`** for the session; the `GE_KEYLOG` log shows real LMB events on both the main-thread and scheduler-poll sides — D594/D595 are live-verified (the E1 LMB-fire is the struck-animation ground truth). **Windows identity gate re-enabled 2026-10-08 (D596):** the stale `win/` goldens (pre-D565/D569) were regenerated from `e0a2d4b9` — `verify.sh sweep` 21/21 PASS on the branch tip; the `linux/`/`deck/` sets still need their own re-capture round on those boxes before any new cross-platform number is read. **D598 (RESOLVED by D600, live playtest owed):** the M3 chop on Cradle-class levels was fixed 2026-10-08 by **D600 (display-locked retrace tick)** — the scheduler's tick now paces to the display's refresh instead of assuming 60 Hz vsync (the CPU side was 6–17 ms per 300 frames, so the chop was display/swap pacing, not software-RSP cost); a live Cradle-class playtest confirmation is still owed. **D599–D604 (all 2026-10-08; on `macos-arm64`, pushed to Forgejo 2026-10-08):** D599 FIXED (arm64 SIGBUS on pad connect — `padTabPub` pointer-sized); D601 FIXED (interrupt-guarded sound-list mutation — cyclic list hung Archives stage load, live confirmation owed); D602 OPEN (end-credits SIGBUS — `langGet` rejects impossible slot offsets + one-shot bank diagnostic, needs a natural-flow re-trigger); D603 FIXED (2P `modelSetAnimFrame` SIGSEGV — `playerTick` re-bases the s32-held animation address; the live 2P session exercised it) and D604 FIXED + LIVE-CONFIRMED (2P respawn SIGSEGV — `mp_respawn_handler` stops truncating the pointer-typed `start_stan`; maintainer confirmed Enter/respawn in 2P with keyboard/mouse + 1 controller). **D597 (FIXED 2026-10-08): `GE_INPUTSCRIPT` `MLB`/`MRB`** sustained mouse-button tokens (slot 0) — headless scripted fire; the D595-class regression is now automatable (Mac sweep-fire no-crash run + no-env no-op run verified) and is the standing #131 runtime smoke check. | | Platform parity gate (Linux co-equal with Windows) | open (v0.7.0, maintainer 2026-10-10) | — | **Decided 2026-09-30:** yes. Every released platform carries the same gate: a 21-level sweep plus a campaign pass. Needs the golden baselines on both platforms first (§7). The last known Linux crash (D190) was closed as not-a-bug. | | Low-end GPUs (~30 fps on Celeron/HD 400) | fixed, verify on N3060 class | D339, D481, D482, #92 | **D481 (2026-10-02):** fast3d ran inline on the scheduler thread, delaying retrace delivery so the tick gate skipped frames; the render worker took a Lenovo X220 (HD 3000) from 44-46 to 60.0 fps. **D482:** Atom/Celeron-class GPUs (HD 400-605, UHD 600/605, software renderers) get DrawDistance/LodDistance 100 and MSAA 1 once, where still at defaults. **D473:** uncached per-batch getenv fixed. Direction: real optimizations, not a preset. **Next only if N3060-class hardware still drops:** one `GE_PERFSTAT=1` run (`gpu=` vs `run=`), then a lighter renderer-keyed default (GPU) or fast3d per-batch cuts (CPU; local `PERF-HOTSPOTS.md`). | | Statue/Cradle hitching (maintainer, 2026-09-30) | parked (not player-visible, 2026-10-02) | `GE_PERFSTAT` spike counters | **Diagnosed (D475, D477, D480):** no sustained load — the ~33 ms frames are the frame limiter skipping a retrace after a late gfx task (`boss.c`, D13-class timing); CPU bursts were CI-palette re-imports (ruled out, D477) and in-play shader compiles (fixed, D480). **Parked 2026-10-02:** a play session with the timeline probe felt no hitching. Reopen only if a visible hitch is reported (lever: pre-warm at level load). | @@ -228,7 +228,7 @@ Background research lives in the maintainer's local notes (gitignored): | Control style Original shows the game's own N64 styles | verify | #139 follow-up, D516, D517 | **Landed 2026-10-04 (D516, merged @ 91595597):** "Controller style" row (Original only; the game's own 1.1-2.4 per seat, saved to the Bond file; front end reads "(in a mission)"); D498 presets hidden in Original. **D517:** hold-repeat on any Bond row dropped fps (EEPROM rewrite per detent); now staged like sliders. Live passes 2026-10-04 (maintainer): single player + split-screen 2P with different styles per seat. **Owed:** the 2.x second-pad pass (real second controller). | | Pad layout preset per player (setting P2's no longer moves P1) | verify | D518, D498 follow-up | **Landed 2026-10-04 (D518):** `Input.PadPreset` kept as seat 1's key + new `Input.PadPreset2/3/4`; the F10/front-end preset row follows the Select-player seat. Headless GE_PADMAPTEST PASS; **live passes 2026-10-04** (P2 change leaves P1 alone; split-screen: each seat ran its own preset). | | Control scheme selectable: Ext / Original control style | verify | #139, D513, D498, D166 | **Landed 2026-10-04 (D513, merged into `release/v0.4.1`).** `Input.ControlScheme` (row "Control style", Ext default / Original) on the Controller page, both UIs. Original leaves the game's own style alone; D498 presets set layout and stick swap only in Original; 2.x runs faithfully; global in v1, per seat with the Select Player work. **Owed:** pad pass in both modes, watch-selected 1.1-1.4, split-screen 2P with different styles, 2.x with a second pad. | -| Outside PRs #107–#109, #122–#124 | decided | #122 hot-plugged pads never reopen, #123 persistent crosshair (`gunfire.c`), #124 compact health/armour bars (`bondview2.c`); #107/#108/#109 (italoarruda) | **Decided 2026-10-01:** **#120/#121/#122** merged locally (#122 = D450); close on push. **#123**: merged 2026-10-06 into v0.5.0 (D436; presets set it off, tip, Rule-2 signed off; by-eye hipfire / sniper zoom / 2P owed). **#124**: deferred (ignores HudScale, overlaps status text, ultrawide anchoring, split-screen untested). **#133**: duplicates D472; close as superseded on push. **#109** (pad rebinding): decline as-is; supersede with our pad presets (§5a), crediting the author (Co-authored-by). **#107**: folded into D441; close on push. **#108**: belongs with `macos`; ask for a range check. | +| Outside PRs #107–#109, #122–#124 | decided | #122 hot-plugged pads never reopen, #123 persistent crosshair (`gunfire.c`), #124 compact health/armour bars (`bondview2.c`); #107/#108/#109 (italoarruda) | **Decided 2026-10-01:** **#120/#121/#122** merged locally (#122 = D450); close on push. **#123**: merged 2026-10-06 into v0.5.0 (D436; presets set it off, tip, Rule-2 signed off; by-eye hipfire / sniper zoom / 2P owed). **#124**: deferred (ignores HudScale, overlaps status text, ultrawide anchoring, split-screen untested) — **tentatively on the v0.7.0 triage list (commented to the author 2026-10-10; blocker is ours: scope + golden re-baseline, so a rebase onto `release/v0.6.0` would make integration cheaper).** **#133**: duplicates D472; close as superseded on push. **#109** (pad rebinding): decline as-is; supersede with our pad presets (§5a), crediting the author (Co-authored-by). **#107**: folded into D441; close on push. **#108**: range check implemented in v0.6.0 as D573 (commented + credited 2026-10-10; superseded, author to close). | | Gamepad presets: duplicate-binding warning, Xbox stick behaviours | open (after v0.5.0; documented in the README) | D469, D498, D518, D394 | D469 (pad action table, Jinx 1.1 default, Custom per-seat bindings), **D498** (Xbox 1.2 Christmas / 1.3 Frost / 1.4 Elektra) and the per-seat preset (**D518**) are done and maintainer-verified with pads. Not done (maintainer 2026-10-04: skip in game for v0.5.0, document only): a warning when two actions share a button; the Xbox "left stick aims the crosshair" and "D-pad copies the left stick" behaviours (D394). | | Pad button names on a Nintendo pad | verify | D471; local note `PAD-MENU-AUDIT.md` | Audit done 2026-10-01 (no controller-only trap; D472 fixed G1-G3). D471 family button names + player LEDs: **PS5 DualSense verified 2026-10-03.** **Owed:** a Nintendo (Switch) pad check; the maintainer has no such pad, so this waits for one or for a user report. | | Mute and auto-pause on focus loss; PNG screenshots to `screenshots/` | parked | D231, PR #56 (closed unmerged), `docs/dev/notes/parked/0001-QoL-*.patch` (local) | Deprioritised by the maintainer on 2026-09-25. F12 today is the dev PPM dump. |