diff --git a/.gitignore b/.gitignore index b00d74a3..4804737c 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,6 @@ build-pyinst/ # from repo root / scratch on 2026-09-18; never commit. /local/ build-pc-cmd.bat + +# v0.4.0 modern-options wave: per-landing sweep capture dirs (capture.sh output) +tools_pc/sweep-captures/capture-*/ diff --git a/README.md b/README.md index 99c8ba4d..eaccbc72 100644 --- a/README.md +++ b/README.md @@ -128,10 +128,13 @@ filtering, FOV, sensitivity); Windows and Linux, including Steam Deck. - Gunshot SFX can sound off during sustained/rapid fire: cadence can drift from the N64 original's rate, and PP7/AK47 fire can occasionally go silent under heavy automatic fire near another looping sound (D240/D241). -- **`All unlocked` is highly experimental — don't enable it until you have - at least one save written** (complete a level normally first, e.g. Dam on - Agent). Enabling it on a brand-new install with no prior save can still - cause silent audio and odd right-mouse-aim behavior (D257/D259/D281). +- **`All unlocked` is experimental: back up `data/ge007.eep` before enabling + it.** Any save while ON, even a profile-settings change, can permanently + write artificial cheat unlocks and completion times into the EEPROM; + switching OFF does not undo them (D387). In the v0.3.0 release, turning it + on before a real save exists can also cause silent audio and missing + aim/HUD settings (D257/D259/D281). Do not use it on a save whose original + progression you need to preserve. - Assorted further cosmetic defects are tracked in [`docs/dev/GRAPHICS-BACKLOG.md`](docs/dev/GRAPHICS-BACKLOG.md). - No macOS or ARM support; no controller rebinding UI. @@ -318,18 +321,30 @@ lives in `ge007.eep`. Launch with `-fresh` to wipe both before starting |---------------------|--------------------------|---------------| | Move / strafe | `W` `A` `S` `D` / arrows | Left stick (or D-pad) | | Aim / look | Mouse | Right stick | -| Fire (Z) | Left mouse / `LCtrl` | Right trigger | -| Aim mode (R) | Right mouse / `LShift` | Left trigger | -| Use / accept (A) | `Space` / `E` / `X` | A / X | -| Reload / cancel (B) | `R` / `F` | B / Y | -| Next weapon | Mouse wheel up | RB | -| Previous weapon | Mouse wheel down | LB | +| Fire | Left mouse | Right trigger | +| Aim mode | Right mouse / `LShift` | Left trigger / LB | +| Use / interact | `E` | A | +| Reload | `R` | X | +| Crouch | `LCtrl` | Left or right stick click | +| Cycle owned gadgets | Watch inventory | B | +| Next weapon | Mouse wheel down / `Q` | Y | +| Previous weapon | Mouse wheel up | — | | Start | `Enter` / `Tab` | Start | -| Options overlay | `F10` | Select (D-pad/stick + A/B navigate, Start closes) | +| Options overlay | `F10` | Back (A selects/toggles; B backs; D-pad/stick left/right adjusts sliders; Start closes) | -The controller layout follows the modern dual-stick scheme used by the -console re-releases (left stick move, right stick look, triggers fire/aim, -shoulders cycle weapons). +Gameplay follows the Xbox **1.1 Jinx** button roles in the user-provided +[StrategyWiki control table](https://strategywiki.org/wiki/GoldenEye_007/Controls): +A use, X reload, B gadget cycle, Y weapon cycle, either stick click crouch, +LB/LT aim and RT fire. The PC gadget cycle selects the next owned gadget in +the N64 inventory; the user has confirmed the gameplay buttons on a physical +pad, but exact gadget-category parity remains unaudited. In menus A +accepts and B cancels. RB's *updated graphics* toggle cannot be provided by +the original N64 port (no remastered assets); it is reserved. Back opens PC +options rather than Xbox's *view scores*; exact menu parity is not claimed. +The other Xbox schemes (1.2 Christmas, 1.3 Frost, 1.4 Elektra) are planned, +not yet selectable. Input → Bindings → Movement/Actions edits **keyboard/mouse +only**; a controller can navigate those pages and use B to go back, but +controller-button rebinding is not supported yet. Mouse sensitivity, Y-inversion and the aim/turn split are tunable in the `[Input]` section of `ge007.ini`. diff --git a/docs/dev/GRAPHICS-BACKLOG.md b/docs/dev/GRAPHICS-BACKLOG.md index 4a148060..0694416c 100644 --- a/docs/dev/GRAPHICS-BACKLOG.md +++ b/docs/dev/GRAPHICS-BACKLOG.md @@ -10,6 +10,7 @@ once the game is playable start-to-finish without crashes. |----|---------|----------------| | ~~**D114/D116**~~ | ~~HUD text + ammo digits render each glyph individually X-mirrored~~ | **CLOSED — NOT A BUG (M-33, §F D168).** The `GE_PCDUMP` PPM writer never reversed `glReadPixels` rows, so every capture was upside-down; "mirrored" was a misread of inverted asymmetric content. The game renders correctly on hardware (developer-confirmed). Writer fixed (`gfx_opengl.cpp`). "Every stage verified non-mirrored" was correct — there was no mirror. | | ~~**D74 wrap-block**~~ | ~~`gfx_pc.cpp:1546/1551` PORT block is dead code (guard `cms & G_TX_WRAP` always false; indexes per-texunit arrays with the vertex index → OOB if reached).~~ | **RESOLVED (M-30, RC3/D167).** The in-vertex-loop wrap block was reworked and hoisted to a per-texunit pre-wrap window (`gfx_pc.cpp` ~1574, now `cms`-correct and indexed by texunit not vertex), behind the `Video.WrapFix` knob (default OFF). No longer dead code or OOB. See §F "RC3 · D167". | +| **D392** | In the opening attract-mode Train demo, a soldier consistently looks more hunched on PC than in 1964/GEPD; his hand intersects his body at the wrong position. User comparison: `docs/img/animation-glitch-pc-port.png` and `docs/img/animation-glitch-1964gepd.png`. | **FIXED — user visually verified (D392).** Train's normal opening (`-level_25`) has a central firing guard (`chr=5`) whose torso/shoulder aim offsets reached `aimupback=-0.855`, `shoulder=-0.606,+0.868` radians by tick 100. `chrlvUpdateAimendbackShoulders` used N64 `((f32*)arg1)[12/13/16/17]` offsets into a firing table whose first member widens from a 4-byte to an 8-byte pointer union on PC; it read *other* floats and bent the torso/arms to wrong angles. `#ifdef PORT` now reads `max_up/max_down/free_arm_frac_up/free_arm_frac_down` by name; with the same short Train intro probe the torso offset stays 0, shoulders ~0.028/+0.014 at tick 100. User's original comparison: `docs/img/animation-glitch-pc-port.png` vs `docs/img/animation-glitch-1964gepd.png`. The user subsequently confirmed the soldier's pose looked fixed in-game; this session's image tool itself cannot display PNGs. No ramrom demo override needed; ordinary `-level_25` reproduces. | | **D75** | ~~Nintendo logo mispositioned; gun-barrel Bond model absent~~; cast-roll character models — status unknown. (Rareware logo OK.) | **Nintendo logo + GoldenEye logo + legal page FIXED (M-197, user-confirmed live 2026-09-21).** Root cause: the D50 sidecar converter (`tools_pc/d43_emit.py`) reserved + remapped the model's embedded texture-blob span but never copied the pixel bytes into the emitted RZ image → TEXEL0 sampled a zeroed buffer → the texture-modulate logo rendered black (M-195/M-196 had proven emission/transform/combiner all correct). Same latent bug hit `PgoldeneyelogoZ` + `PlegalpageZ`. Fix = tooling-only (blob raw-copy + round-trip check); ntsc sidecars regenerated; logo window now renders 23k px (7.59%) vs 0–33 pre-fix. Gun-barrel Bond renders correctly (M-33). Cast roll still unverified — recheck with `GE_PCDUMP="1400-2200:25"`. `findings.md` §F D75 (M-195/M-196/M-197 updates) + M-197 at file tail. | | **D76** | 2D disclaimer screen only partially drawn. | §F D76. | | ~~**D77**~~ | ~~No audible music on PC.~~ | **RESOLVED (M-104, PR #42) — in-level music now plays.** Root cause was a D6-class missing `return` in `sub_GAME_7F0C0BF0` (`mp_music.c`) that zeroed the seqp volume on the only in-level trigger path; menu/intro music bypassed it and was always fine. The remaining audio-*quality* gap (wrong-sounding instruments on some tracks — elevator named specifically — plus occasional garbling) is tracked as **D230**. §F D77/D230. | @@ -30,7 +31,7 @@ once the game is playable start-to-finish without crashes. | **D217** | 1P weapon viewmodel + character-model CI textures render with a wrong palette on many levels / multiple weapons — PP7 grip + hand render flat green on Facility & Depot, "weird or missing" gun textures elsewhere; Bond's watch face too. Surfaced by D215 (viewmodel now draws). Clean on Bunker1. | **Defect ① FIXED (M-90), pending human playtest eyeball — full detail in `findings.md` §H "D217 — M-90" and §F D217.** Root cause: weapon texpool arena bases land %8==4 on PC (memp bump drift from pointer bloat); `texAlignIndices` absolute 8-byte row padding then shifts every palette 4 bytes early while model-DL `G_LOADTLUT` reads the N64 offset (grip count=1 load lands on next tenant's header slot → `0x1A00` green; larger loads read a 2-entry zero pad — the M-86 tell). Fix: `texInitPool` rounds the base up to 8 under `#ifdef PORT` (no-op on N64); 21/21 sweep PASS. Two defects: ① **visible green = misaligned texpool arena** (fixed as above). ② **CI texture-cache collision** (no palette-content key) — proven, **fix landed on branch `fix/d217-model-texture-palette` `f6fc0399`** (palette FNV-1a hash in the CI cache key), owes a 21-level `verify.sh sweep`; does not fix ①. | | **D174** | "No blood effect" — user reports no visible blood when shooting guards / into surfaces. | **User QA report; likely D120, unverified.** Decals: the D120 `PointUsage[]` converter fix (M-30) was never interactively verified and only takes effect after a full sidecar regen (`d43 && d69 && d88 --regen`) — check whether the playtest build had regenerated sidecars before concluding the fix failed. Spray: D172 observed the particle spray *drawing* (wrong color, magenta/cyan) on Silo — if the user sees no spray either, that's new info (different weapon/range, or the D172 decode is worse than "wrong color"). First step: BUNKER1 firefight with regenerated sidecars; if decals still absent, instrument the `chr.c:3328` decal walk. | | **D173** | Third-person Bond model (the player-representing figure shown at level start) spawns too high — floats well above the ground "a lot of the time" while the actual player spawn is correct. Same symptom on the Cuba end credits: JB stands ~6 ft in the air above Natalya. | **Confirmed still present across the full 21-level playthrough (M-49).** **Observed, not investigated** (user QA report). D75 animated-model family but a *position* defect, not absence — M-33 confirmed the gun-barrel Bond renders fine upright. Suspects: (a) intro/credits puppet chr spawn position vs the model's base transform; (b) anim root-motion accumulation (`modelSetAnimFrame2WithChrStuff`, D156 area) offsetting the rendered joints above the body origin; (c) a `coord3d`/packed-float decode in the intro camera/model setup. "Player spawning is OK" localises it to the render-side model, not `g_CurrentPlayer` state. | -| **D182** | SELECT FILE screen degrades after navigating away and back (main menu → file select, or backing out of file select and re-entering). On the fresh screen the 007 gun-barrel spiral / Bond silhouette renders behind the file boxes; after a round-trip **the Bond image stops drawing entirely** and the whole background gains the **comb / interlacing** artifact (horizontal line scramble). File boxes, text and the Copy/Erase icons still draw. | **Observed, screenshot committed** (M-35, user QA; `docs/img/bugs/d182-file-select-backout-20260902.png`). Two symptoms, likely linked: **(1)** background 3D image stops rendering after re-entry → a front-end model/DL whose `render_pos` / segment binding is only valid on first construction (D149 / D75 `constructor_menuXX` family — the dossier/wallet models have the same "renders once" behavior). **(2)** interlacing = **M-36 triage: Family A**, the `import_texture_*` `line` vs `full_image_line` shear (see D176(b) / `docs/dev/M-36-TRIAGE.md`) — **not** the D159 `texSwapAltRowBytes` path (that is a full PORT no-op). Open question: why only *after* a round-trip — first import may land `line == width`, re-import may not, or the tile descriptor is stale on re-entry. Repro: `GE_STARTMENU` to file-select, back out with ESC/B, re-enter; `GE_DTEX` on the spiral texture across both visits. Shares defect (2) with D176(b). | +| **D182** | SELECT FILE screen degrades after navigating away and back (main menu → file select, or backing out of file select and re-entering). On the fresh screen the 007 gun-barrel spiral / Bond silhouette renders behind the file boxes; after a round-trip **the Bond image stops drawing entirely** and the whole background gains the **comb / interlacing** artifact (horizontal line scramble). File boxes, text and the Copy/Erase icons still draw. | **Observed, screenshot committed** (M-35, user QA; `docs/img/bugs/d182-file-select-backout-20260902.png`). Two symptoms, likely linked: **(1)** background 3D image stops rendering after re-entry → a front-end model/DL whose `render_pos` / segment binding is only valid on first construction (D149 / D75 `constructor_menuXX` family — the dossier/wallet models have the same "renders once" behavior). **(2)** interlacing = **M-36 triage: Family A**, the `import_texture_*` `line` vs `full_image_line` shear (see D176(b) / `docs/dev/M-36-TRIAGE.md`) — **not** the D159 `texSwapAltRowBytes` path (that is a full PORT no-op). Open question: why only *after* a round-trip — first import may land `line == width`, re-import may not, or the tile descriptor is stale on re-entry. Repro: `GE_STARTMENU` to file-select, back out with ESC/B, re-enter; `GE_DTEX` on the spiral texture across both visits. Shares defect (2) with D176(b). **2026-09-27 (D397):** user re-reported the comb/interlace on the file-select background AND on the **intro gun-barrel** — the latter is a *first-time* render, so the defect is persistent (not only after a round-trip), refuting the "stale descriptor on re-entry" hypothesis. D159 (odd-row swap) is no-op'd and D183 pitch shear is disproven for level_36 + a no-op for the 299×440×1 row-strip. Next step is a live `GE_PCDUMP` capture + ROM ground-truth decode of the gun-barrel RLE image to separate ground-truth dithered content from a GL sampling/texture-cache artifact. See findings.md D397. | | **D197** | Character face/head textures wrap wrong — the face texture repeats around the side of the head "and continues weird" instead of clamping to the front. Seen on **Silo** (M-49 playtest), intermittent ("sometimes"). Reads as **`G_TX_CLAMP` not honoured** for the character-skin tile in fast3d (→ `GL_REPEAT`, so the face UV region tiles around the skull), or wrong `shifts`/`shiftt` / LOD-tile selection on the head texture, or the D167 non-PoT wrap-period issue (head textures are often non-PoT) hitting skinned models. | **Observed, not investigated** (M-49, user bug report — needs a capture + which chr/level). Distinct from D176(b)/D182(2) (those are *bg wall* pitch shear). Related: RC3/D167 (`Video.WrapFix`, non-PoT wrap period) + the `texWriteTileLods` `shifts=shiftt=lod` note in findings §F "D176(b) → 4. candidate 2". First checks: does `gfx_pc.cpp` map N64 `cms/cmt` `G_TX_CLAMP` → `GL_CLAMP_TO_EDGE` for character DLs; is the head tile getting the base tile vs an LOD tile (D107); try `Video.WrapFix=1` on a repro. | | **D195** | Transparency / alpha-blended surfaces render wrong — reported on **Control** (Severnaya bunker basement — Natalya's console room; heavy on glass partitions and the translucent projected/holographic wall displays). Exact failure mode not yet pinned by the reporter (M-49 playtest): candidates are alpha-blended geometry drawing fully opaque, translucent panels drawing invisible, or draw-order/sort so translucent surfaces occlude what's behind. | **Observed, not investigated** (M-49, user bug report — needs a `GE_PCDUMP` capture + which surfaces). fast3d render-mode / combiner path. Same neighborhood as D161 (CI8 tile + `G_TT_NONE` → garbage), D172 (particle-sprite channel order), D176(b) (texture pitch shear) — but this is a *blend/alpha* defect, not a texture-decode one. Note D128 already touched Control's `specialportalarray` (portal struct stride) — check whether the affected surfaces are portal-adjacent. First checks: does `gfx_pc.cpp` honour `G_RM_*` XLU render modes + `G_AC_THRESHOLD`/`G_CC` alpha for these DLs; is `gDPSetRenderMode` `w1` being parsed (cf. findings §F "zbuf-clear w1 scribble"); is Z-write-vs-blend ordering right for XLU surfaces. Get the reporter to say: opaque-where-should-be-clear, invisible, or wrong edges? | | **D252** | Particle effects cycle through a rainbow palette — bullet-impact sparks and lingering smoke/explosion residue drift through the full hue wheel over time (~10 shots to sweep it) instead of holding their intended grey/orange palette (M-124, user playtest). Full mechanism + suspect in findings §F **D252**: colour comes from 15 distinct `IMAGE_SMOKE_N`×`IMAGE_FIRE_N` (RGBA16) pairs the particles age through; prime suspect is `import_texture_rgba16` deriving width/height from the tile line size (32×7 instead of 16×14 for the fire tiles), scrambling each stage's sprite into a different wrong hue. | **Documented only — not fixed for v0.2.0-pre** (user instruction). Confirm with one dumped fire tile vs raw `IMAGE_FIRE_N` bytes, then derive width/height from the LOADBLOCK dtx/dlh. D172/M-82 lineage. | diff --git a/docs/dev/V0.4.0-PLAN.md b/docs/dev/V0.4.0-PLAN.md index d2c70557..135ac554 100644 --- a/docs/dev/V0.4.0-PLAN.md +++ b/docs/dev/V0.4.0-PLAN.md @@ -1,5 +1,26 @@ # v0.4.0 Plan — local working document (NOT pushed; update as items move) +**2026-09-27 user release decision:** defer M7 / AllUnlocked save-safety work +for v0.4.0 (D387); do not ask for a live-save test or treat the feature as +safe. Before shipping, hide/disable the unsafe toggle or explicitly agree +on a release limitation — default OFF alone does not prevent a user from +turning it ON. The user will do a full campaign playtest *instead of* the +21-level automated sweep; record the campaign result as the release gate, +not as a sweep PASS. **Playtest interruption D393/D394:** physical-pad +A use / X reload / Y weapon cycle was user-tested. After the user supplied +the StrategyWiki Xbox 1.1 Jinx mapping, D394 moved crouch to either stick +click, LB to aim, B to a port-side owned-gadget cycle, and retired LB/RB +weapon cycling. Build linked; user physically confirmed the new button roles work, including +stick-click crouch, LB aim, RB no weapon cycling and B gadget cycling (the +N64 port has no separate gadget HUD icon). **D395:** both controller-accessible +binding menus now refuse pad-initiated keyboard/mouse capture and allow B to +cancel an active modal, pending pad-only retest; this is not gamepad rebinding. +**D396:** F10 B now backs/closes, A selects/toggles without changing sliders; +left/right adjusts sliders. NTSC linked; physical pad retest owed. Inspect B's item category/order during campaign play if multiple mission +items are owned: the current ID-range filter includes some mission objects. +RB's remastered-graphics toggle cannot be replicated with N64 assets, and +Back remains the PC options shortcut. + Created 2026-09-21 from a fresh triage of `findings-index.csv`, `GRAPHICS-BACKLOG.md`, `docs/BACKLOG.md`, `ROADMAP-1.0.md` (M-139 phase order), `QOL-INVENTORY.md`, and the 2026-09-20 HANDOFF. @@ -73,13 +94,11 @@ Sequencing follows M-139's R → Q → F order, split into four phases below. | D314/D315 | F10 flicker (user-deprioritized) + main-vs-in-game menu scaling | D315 deferred from v0.3.0; bigger design question — lands naturally with the overlay work. | | D238 | Mouse sensitivity rework (master sens, RMB aim sens, Y-gain parity) | Partly superseded: aim modes folded (D337, N64 default via PD integration; Centred (PC) opt-in), Aim range PC/N64 (D338). Remaining: sensitivity feel tuning. | | D239 | Click-to-lock parity: delete always-grab mode 0 + config key | Small; closes D192 by deletion. | -| GEPD controls preset | New opt-in key-layout option ("Controls: FPS (default) / GEPD") reproducing the 1964 GEPD scheme: Q=A (accept/next-weapon), E=Use (B), **R=dedicated reload**, **Ctrl=crouch** (hold or toggle mode); M1=fire / M2=aim / wheel=weapon-cycle / arrows=stick all already exist. Implementation = D214 bind-string presets (`Input.Layout` enum writing preset strings into `g_bindStr`, per-user ini override preserved) + two new port-layer actions (IA_RELOAD emits **B** — reload is the B button in GE: `lv.c:796` `bond_pressed_reload_activate()` → `attempt_reload_item_in_hand()`, so a dedicated key needs no ROM hack and zero game-code changes; IA_CROUCH emits B held — crouch is B, same as the pad layout `input.c:1477–1481` — or a latched toggle). **Wrinkle (decided 2026-09-27): the preset leaves LeanLeft unbound** (its default `Q`, `input.c:885`, would otherwise make GEPD's Q=Action emit A+L; 1964 has no lean key, so the faithful layout drops it — rebindable via per-key override; FPS layout keeps Q). Small, `input.c` + overlay row, OFF default. See `GEPORT-REFERENCE-DEEPDIVE.md` §7 and `MODERN-OPTIONS-PLAN.md` (M3). | -| Modern options wave (parity set, 2026-09-27) | One opt-in "Modern" section in the F10/PC options page (`GE.` ini namespace, unknown keys ignored, all rows **default-off / N64-original**): (a) **crosshair on/off + color** (N64 default: always-on white; tint/hide at the HUD draw site); (b) **low-end perf preset** (FpsCap 30 / AA off / render-scale — the D339/#92 follow-up); (c) **GE+ gameplay toggles, clean subset**: disable knockback, disable - hitstun, damage sound, endless death cam (damage flash already shipped - as D232 `Game.NoHitFlash`) — each a small `#ifdef PORT` hook point; - rule-2 flag per feature, port-side default OFF; see `GEPORT-REFERENCE-DEEPDIVE.md` - §2.1 for the full upstream list); (d) **AllUnlocked preservation proof**: verify untoggling keeps progress (D257 read-time patch design should already guarantee it — evidence, not code). (F12 screenshot → PNG dropped from this wave 2026-09-27 — the dev PPM dump stays, the PNG upgrade is parked.) Total ≈ 2 sessions; lands in Phase 3 as one wave. | +| GEPD controls (M3) | **IMPLEMENTED, targeted playtest owed (D378/D380/D383–D386).** One effective keyboard/mouse layout, no `Input.Layout` selector: Ctrl crouches without aim; E interacts without reloading; R reloads without interacting. Input → Bindings → Movement/Actions edits two Primary/Secondary keyboard-or-Mouse 1–5 slots in both UIs (D388). Mouse 3 (right) is Aim default; wheel still cycles weapons. Menu arrows/Enter/Escape and mouse clicks remain fixed. See `MODERN-OPTIONS-PLAN.md` M3; earlier preset/B-button text there is historical. | +| Modern controller presets (D394) | **1.1 Jinx button roles physically confirmed; precise gadget category still open**: A action, X reload, B cycle owned gadgets, Y cycle weapons, L3/R3 crouch, RT fire, LT/LB aim, D-pad movement, Start pause. RB updated-graphics and Back scores are XBLA remaster-specific: no HD assets/score view in the N64 port; reserve RB, keep Back→PC options. **Planned** named selector: 1.1 Jinx (L move+strafe, R look+turn), 1.2 Christmas (L move+turn, R look+strafe), 1.3 Frost (L look+strafe, R move+turn), 1.4 Elektra (L look+turn, R move+strafe). Face/trigger roles remain fixed across schemes. Add an `Input.ControllerPreset` enum with default 1.1, F10/front-options selector, preserve per-pad inversion/deadzone, separate keyboard `NaturalPitch` from the pad selector, adapt both stick axes and D-pad per scheme, and verify in watch/menu/tank and physical controller before labeling each selectable. Do not treat these four presets as already implemented. | +| Modern options wave (parity set, 2026-09-27) | **In progress, not a single opt-in Modern page (D388).** M1: Input → Bindings and Gameplay → HUD, shared by F10/front; M2: Original red crosshair plus White/custom RGB, style, size and visibility implemented (D379/D381/D382); M3: single effective layout and rebinding (above). **M5: redundant Low-end toggle removed (D388); Frame rate cap and Anti-aliasing remain independently adjustable, stored values preserved on migration.** M4 GE+ knockback/hitstun/damage-sound/death-cam toggles parked for v0.5.0, not v0.4.0 blockers. **M7 BLOCKED (D387):** AllUnlocked ON can persist synthetic cheats/times after any profile-settings save; OFF does not remove them. Do not run on live saves; a safe design and multi-profile fixture tests are owed. PNG screenshot upgrade dropped from this wave; dev PPM dump remains. The M1–M7 detailed notes retain their historical design record in `MODERN-OPTIONS-PLAN.md`. | | D226 | Player-adjustable HUD scale (ammo counter, pickup text, dialogue) | **DONE 2026-09-24 (`30720354`)**: Game.HudScale 75–150% (user-verified), fast3d rect scaling about anchors, dialogue/bottom width-capped. | +| Controller rebinding UI (D395) | **Not implemented.** The two Input → Bindings → Movement/Actions pages edit keyboard/mouse slots only. Pad-only users could previously enter a capture modal and get stuck; pad-triggered capture is now disabled in both UIs and B cancels a capture started by keyboard/mouse (NTSC build linked; physical pad-only retest owed). Controller presets (D394) are separate from arbitrary pad rebinding; design an explicit controller-actions page, persistence/migration and capture/cancel semantics before enabling pad capture. | Post-v0.4 scope decision; no promise that keyboard binding slots can hold pad buttons. | | Rumble (D224) | Wire `osMotor*` → `SDL_GameControllerRumble` (PD precedent exists) | Deprioritized M-87; pick up if gamepad support is in scope for v0.4.0 — user call. | | Per-pad tuning / hot-plug | PD incremental hot-plug + remembered seats; deadzone/scale/rumble per pad | Medium; real-controller users. | | Window polish | HiDpi, center window, maximize/default-fullscreen | Small P-class wins. | @@ -204,17 +223,18 @@ Order by user-visible value (2026-09-27 refresh — several rows since DONE, mar 4. ~~**D226 HUD scale**~~ — **DONE 2026-09-24**. 5. Unlocked FPS: re-measure Phase 0 against the post-D248/D250 baseline and decide whether v0.4.0 or v0.5.0. -6. **Modern options wave** (Bucket C "parity set": crosshair on/off+color, - low-end perf preset, GE+ gameplay toggles subset, AllUnlocked - preservation proof, GEPD key-layout preset — F12 screenshot dropped - 2026-09-27) — one opt-in - section, all rows default-off/N64-original. ≈ 2 sessions total (damage - flash was already D232; F12 screenshot dropped 2026-09-27); the - user-facing answer to "does it have the modern options". Per-item - hook points, effort, and rule-2 sign-off list: local - `MODERN-OPTIONS-PLAN.md` (M1–M7, M6 parked; zero sign-off: M1/M3/M5/M7, - one each: M2 + M4's four toggles — M4.3 is the shipped D232 NoHitFlash — - batched review). +6. **Modern options wave — substantially implemented, NOT release-complete** + (D377–D389). Five functional roots; Input → Bindings → Movement/Actions + and Gameplay → HUD work in both menus. One effective PC layout with + dedicated E/R/Ctrl; two bind slots including Mouse 1–5; crosshair + visibility, Original/White/colour, style and size. Redundant Low-end + preset retired, but FPS cap/MSAA remain. M4 GE+ toggles deferred to + v0.5.0, M6 PNG screenshot removed from this release. **M7 blocked by + persisted fake save progress (D387); do not test with a live save**. + Physical acceptance, M7 release decision, 21-level visual gate and + documentation/commit reconciliation are still open. Earlier "one + opt-in section/default-off/preservation proof" estimates were superseded; + the original research remains in `MODERN-OPTIONS-PLAN.md`. ### Phase 4 — Release ritual 1. `./build-pc.sh ntsc-final` clean; `/linkcheck`; full 21-level @@ -239,8 +259,12 @@ Both were investigated 2026-09-22 against the Perfect Dark PC port fork `perfect-dark-dabs-mod-dabs-mod` (**MIT**, Ryan Dwyer — same license as this tree; `AGENTS.md` already names the PD port a standing reference, so code may be adapted with attribution). Fuller sequencing notes live in the local -`docs/dev/notes/MODERN-PORT-FEATURES-BACKLOG.md` §5/§6, which is gitignored — the -durable record is `docs/dev/findings.md` and the summary here. +`docs/dev/notes/MODERN-PORT-FEATURES-BACKLOG.md` §5/§6, which is +gitignored — the +durable record is `docs/dev/findings.md` and the summary here. The +drop-in mod support design itself is expanded in the local +`docs/dev/notes/MOD-LOADER-PLAN.md` (2026-09-27: C1–C4 components, v1 +scope, acceptance bar). **Mod support (ROM patches) — viable, medium–large.** Findings **D325–D328**. - Community mods *repack* the ROM, so vanilla offsets are useless: Goldfinger 64 @@ -473,12 +497,13 @@ Checklist beyond the normal play: you see it, then share the `D303:` log lines from around that moment — each line carries the RDP state of a candidate quad and will identify the spurious draw call's source. -18. **AllUnlocked preservation (M7)**: with the new tree — enable - AllUnlocked, play two missions, toggle it OFF in the Watch options, - continue a third mission: objectives/saves must persist (D257 - read-time patch design; evidence for the findings entry — failure is - its own D3xx). Also the modern-toggles A/Bs when M2/M4 land (see - `MODERN-OPTIONS-PLAN.md` per-item verification). +18. **AllUnlocked preservation (M7) BLOCKED — D387.** Do not run this + against a real save: even changing a profile setting while ON persists + synthetic cheats and 0x3FF completion times; OFF requires a restart and + does not undo already-written fakes. First define safe earned-progress + semantics, fix in `port/`, and verify on private copies with settings + writes, mission completion, OFF restart and multi-slot CRC checks. + M4 modern toggles are parked to v0.5.0. ## Conventions reminder - One findings entry per investigation; the index tail moves constantly — diff --git a/docs/porting-notes.md b/docs/porting-notes.md index 0c789f96..d47234d3 100644 --- a/docs/porting-notes.md +++ b/docs/porting-notes.md @@ -107,6 +107,15 @@ for hardcoded indices into any `padding[]`/`u8[]` union arm. through the correctly-typed sibling field (`ObjectRecord.model`) instead, `#ifdef PORT`, N64 line/cast kept verbatim under `#else`. §F **D255** (M-140). +- **D392** (the firing-guard pose variant): `chrlvUpdateAimendbackShoulders` + reads `((f32*)arg1)[12/13/16/17]` into a + `weapon_firing_animation_table` whose *first* member is a union of a + `s32` and a `ModelAnimation *`. N64's 4-byte union places those slots at + `max_up/max_down/free_arm_frac_up/free_arm_frac_down`; on PC the 8-byte + union shifts the floats, so the raw indices read `aim_end_frame/max_up/ + max_right/free_arm_frac_up`. The wrong aim clamp bends the torso ~49° and + pushes the hands through it. Under `#ifdef PORT`, use the four named + fields; retain the raw indices for N64. §F D392. **Lesson.** When a value reads as a clean constant (0, 1, NULL) rather than garbage, a pointer byte is a prime suspect; the high bytes of a @@ -588,6 +597,14 @@ through a converter or a runtime bswap fixup reads scrambled. (exact for hold-to-aim; a toggle scheme needs `g_CurrentPlayer-> insightaimmode`). GE's native pitch is **inverted** (C-up → look down); hide it so mouse-down looks down; `MouseInvertY` flips (D118, M-24). +- **N64 A/B bit names are not modern pad A/B semantics (D393).** GE's + gameplay `GE_CONT_A` cycles weapons and `GE_CONT_B` contextually uses or + reloads. Assigning Xbox A/X both to native A and B/Y both to independent + crouch leaves *no* use button. For modern controls, map A to a dedicated + use edge, X to a dedicated reload edge, B to crouch, Y to a weapon-cycle + edge; preserve native accept/cancel bits in front menus/watch/tank. Track + held buttons across UI transitions so closing F10 does not trigger an + unexpected use/reload/cycle. - `osContGetReadData(pad)` must fill **one OSContPad per channel** (`MAXCONTROLLERS`-long array), not just controller 0; joy.c passes the whole `samples[i].pads` array (D118).