forked from Ports/goldeneye-pc-port
D243 M-189/M-190: fix Bond cutscene root cause, camera tracking, mouse-lock; D236 pass 12 diagnostics
D243/D173/D292 (Bond cutscene family) -- root cause found and fixed: bondview2.c's cutscene body-model buffer layout reserved space using a hardcoded 32-bit sizeof(Model) literal that never accounted for 64-bit pointer widening (real size 232 vs reserved ~188 bytes), so the model's own animation-data buffer overlapped its tail fields (playspeed/animrate/ unkac/unkb0/unkb4), corrupting them on every cutscene body-model creation. Fixed by computing the real sizeof(Model), matching the identical idiom already used one line above for ModelFileHeader. User-confirmed live. Follow-up camera-tracking fix: replaced the old shake-workaround freeze (which also blocked legitimate per-shot tracking) with a write-every-tick scheme plus an instant re-seed of the look-at filter's accumulator at each teleport, eliminating the old catch-up shake without freezing anything. Second bug found in the same review: mouse-look was never gated during scripted/no-control camera states (an already-documented but never implemented safety gate in port/src/input.c's hipDirectCompute). Fixed by adding the missing check, reusing gameScriptedCameraActive() (renamed from D243's d243mCutsceneActive, since it's no longer D243-specific -- also used by model.c's M-183/M-185 clamps, which were separately found to be dead code for real players (gated on the diagnostic env var, not just camera mode) and fixed to be unconditionally active. D236 (Surface tree wall) pass 12: new mechanism found (both competing texture classes are Z_UPD=0 decal-mode draws, so on-screen precedence is decided by draw order, not depth) and a headless capture finally landed on the actual bugged view -- but that view has zero tree-class triangles present, so the mechanism couldn't be tested there. Two new env-gated diagnostic probes (GE_D236ORDER, GE_D236ZFIX) left in tree for the next pass; not a fix, not v0.3.0-blocking. All findings.md summary-table rows touched this session cross-checked against their full entries and corrected where stale (D219/D252/D246/D247 had been fixed in a prior session but their index rows still said OPEN/NOT-A-BUG).
This commit is contained in:
1 parent
643785c2c5
commit
db823d0261
7 files changed
+311
-62
No files matched your search
+48
-8
@@ -459,7 +459,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D216 | **`Game.SkipIntro` — boot straight to the file-select menu (M-83, port + one `#ifdef PORT` game-code line, PD parity, Phase 4 quick win).** — full `## D216` entry at file tail | **LANDED + VERIFIED this session.** Build clean.… |
|
||||
| D217 | **1P weapon viewmodel + 3P Bond model textures garbled — wrong/stale palette on model-DL CI textures (M-84).** Two defects: ① texpool arena misalignment (the green), ② CI texture-cache collision. — full `## D217` entries (M-86→M-97) at file tail | **FIXED + merged** (PR #47 + PR #49); white residual split out as D228. |
|
||||
| D218 | **Wide FOV exposes the per-level draw-distance / fog boundary — "blue artifacting" down long peripheral sightlines (M-84, user QA on the D211 FOV slider).** — full `## D218` entry at file tail | **Logged (M-84), fix proposed + parked.** Plan… |
|
||||
| D219 | **PPK explosions render purple on Dam (M-87, user QA, "not 3D but noting").** — full `## D219` entry at file tail | **RESOLVED (M-115, 2026-09-12)** for the original PPK-purple symptom; note M-157/M-158 logged an adjacent *open* investigation under this label (bullet-spark rainbow, `glass2.c` path — tracked OPEN in D252, non-reproducible as of M-158) —… |
|
||||
| D219 | **PPK explosions render purple on Dam (M-87, user QA, "not 3D but noting").** — full `## D219` entry at file tail | **RESOLVED (M-115, 2026-09-12)** for the original PPK-purple symptom. **The adjacent bullet-spark-rainbow investigation logged under this label (M-157/M-158) is also FIXED (2026-09-18 session)** — `glass2.c`'s `bullet_spark_render` read the spark's RGBA colour via a hardcoded raw byte offset instead of the named `s_bullet_spark` struct fields, landing in the wrong memory on 64-bit PC; fixed by reading the named fields. User live-confirmed. D252's duplicate "lingering particle residue" report closes as the same bug (M-188). |
|
||||
|
||||
**M-111 (2026-09-12, live session, 6 build/relaunch cycles): G_LIGHTING lead RULED OUT; texture-cache-collision lead RULED OUT; ROOT CAUSE FOUND — R/B channel swap in the decoded fire particle texture data itself.** Live-captured 4 rounds against a real user playtest (not scripted) with the user confirming explosions were still blue/purple in every capture:
|
||||
1. **G_LIGHTING probe fired 5000+ times across a full playtest with explosions triggered, 100% `LIGHTING=off`, 0 `D219 SUSPECT` hits.** (First attempt used the original 40-hit cap from the D172 probe, which silently exhausted on ordinary bullet-impact particles before any explosion — fixed to exempt the lit case from the cap and add an always-on periodic counter, confirming the code path really was being hit throughout, not just early. See `port/fast3d/gfx_pc.cpp` `gfx_sp_tri1`'s D172/D219 probe block.) **G_LIGHTING is conclusively not the mechanism.**
|
||||
@@ -539,22 +539,22 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D233 | **All levels (intermittent): indoor level geometry invisible near doors — you can see through walls/floors into rooms you can't see into, while world objects…** — full `## D233` entry at file tail | **FIXED + VISUALLY VERIFIED (M-107 fix, M-108 verify).** See the other D233 row for full detail. |
|
||||
| D234 | **Dam: guard towers along the dam structure invisible except the first one (M-106, user QA report).** — full `## D234` entry at file tail | **VISUALLY VERIFIED FIXED (M-108), mechanism unexplained.** See the other D234 row for detail. |
|
||||
| D235 | **Wrong textures load after dying/restarting a level — not Facility-specific, seen on multiple levels (M-106, user QA report; clarified same session).** — full `## D235` entry at file tail | OPEN — needs: does it repro on a *fresh* level boot (rules out reload-state) vs only after death/restart (confirms it); which surfaces; a screenshot.… |
|
||||
| D236 | **Surface 1: 2D billboard trees render as a wall/sheet of tree texture instead of discrete camera-facing tree sprites (M-106, user QA report).** — full `## D236` entry at file tail | OPEN — tenth pass refuted the "instantiation is nondeterministic" theory (ordinary room-based occlusion, not a bug); original wall-vs-sprites symptom still unresolved; see D276/D280/M-155 |
|
||||
| D236 | **Surface 1: 2D billboard trees render as a wall/sheet of tree texture instead of discrete camera-facing tree sprites (M-106, user QA report).** — full `## D236` entry at file tail | OPEN, twelfth pass (2026-09-18) — new mechanism found (both competing texture classes are Z_UPD=0 decals, so on-screen precedence is draw-order not depth) and headless repro finally reproduced the exact bug visually, but the bugged camera position has zero tree-class triangles present, so the new mechanism can't be tested there; still blocked on live CPU-side tree-instantiation data. Not v0.3.0-blocking, parked again. |
|
||||
| D237 | **QoL ask (M-106, user QA): F10 options overlay — make it scrollable with the mouse wheel, expose more settings into it (e.g. screen-flash / no-hit-flash…** — full `## D237` entry at file tail | OPEN — not designed; port-only |
|
||||
| D238 | **QoL ask (M-106, user QA): mouse sensitivity rework toward normal PC-shooter feel.** — full `## D238` entry at file tail | OPEN — not designed; port-only (`port/src/input.c` + `config.c`) |
|
||||
| D239 | **QoL ask (M-106, user QA): click-to-lock vs always-grab parity.** — full `## D239` entry at file tail | CLOSED — executed in the v0.2.0 prep pass (port-only)… |
|
||||
| D240 | **Player gunshot SFX timing/cadence reportedly does not match the N64 original's rate (M-106, user QA report).** — full `## D240` entry at file tail | **OPEN — not root-caused; static call-site tracing only, no runtime verification possible in this environment.** Confidence LOW-MEDIUM that this is a *new* bug distinct from the D155/D186/D193/D204/D209 timing-keystone family (all of which gate the identical `deltaFrames→speedgraphframes→g_ClockTimer→g_GlobalTimer` chain this SFX trigger consumes).… |
|
||||
| D241 | **Player gunshot SFX goes silent under some conditions — reported on Bunker with the alarm sounding, "or some other factor" — but only for PP7 and AK47, Klobb…** — full `## D241` entry at file tail | **OPEN — not newly root-caused; high confidence this is D207 reproduced, not an independent bug.** Recommend folding this repro into D207 (or closing D241 as a duplicate once D207 is reopened) rather than tracking separately.… |
|
||||
| D242 | **Player-death sequence UX regression vs N64 original: PC requires an LMB click to proceed to the mission-failed/file-select screen; user recalls N64 auto-plays…** — full `## D242` entry at file tail | **NOT A PORT-LOGIC BUG as far as static analysis can tell.** Confidence HIGH that the LMB-click skip path is faithful original behavior (Z_TRIG-mapped, exists unmodified in `bondview2.c`), not a defect to remove.… |
|
||||
| D243 | **Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject): the camera violently shakes/"spazzes" during each of the scripted camera-angle…** — full `## D243` entry at file tail | **PARTIAL FIX (M-170, M-183, M-185):** Camera shake fixed (M-170). Bond's position/animation still broken — rapid advancement (~97 frames/tick) caused by corrupted `playspeed` (388.82 vs expected ~1.0) and `endframe` fields (D100/D140 struct layout/punning family: 32→64-bit pointer widening causes fields to be read from wrong memory locations). Workarounds M-183/M-185 clamp playspeed>10.0 to 1.0 and corrupted endframe values to 100.0 during scripted camera modes, preventing rapid advancement but animation still "repeats" (Bond can't complete his animation). Root cause not yet addressed. |
|
||||
| D243 | **Dam end-of-level cutscene (the abseil/bungee sequence, D148/D160's subject): the camera violently shakes/"spazzes" during each of the scripted camera-angle…** — full `## D243` entry at file tail | **FIXED, live-confirmed by the user (M-189/M-190, 2026-09-18).** Root cause found: `bondview2.c:598-599`'s manual buffer-layout math for Bond's third-person cutscene body model reserved space using a hardcoded 32-bit `sizeof(Model)` literal (`0xfb`) that never accounted for pointer widening — real 64-bit `sizeof(Model)` is 232 bytes, 44 more than reserved, so the animation-data buffer placed right after it overlapped the model's own `playspeed`/`animrate`/`unkac`/`unkb0`/`unkb4` fields, corrupting them (this is what M-183/M-185's clamps were band-aiding). Fixed by computing the real `sizeof(Model)` instead of the stale literal, matching the identical idiom already used one line above for `ModelFileHeader`. **M-190 follow-up:** M-170's camera-shake freeze was replaced with a filter re-seed-on-teleport (camera now tracks Bond continuously within each shot instead of holding a frozen angle), and an unrelated bug in the same review pass — mouse-look never gated during scripted/no-control camera states (D300's own documented-but-unimplemented safety gate) — was found and fixed in `port/src/input.c`. User confirmed both fixes live, full intro-flyover + Dam abseil playthrough: "ok yeah looks good." |
|
||||
| D245 | **IsWater water: two competing patterns with a visible seam that moves as the player looks around (mouse/aim) — "looks almost exactly like skybox" (M-116, user…** — full `## D245` entry at file tail | OPEN — REOPENED, M-142 headless probe found the tc-shift `k` measurably flips during ordinary view rotation (new root-cause evidence); an opt-in `GE_D245_FIXEDSHIFT` candidate is build-verified but needs a live A/B, not shipped as default.… |
|
||||
| D246 | **Tiny pixel strips at the left and right edges of the screen, "like overscan" — look like raw pixels, not 3D graphics (M-116, user QA report).** — full `## D246` entry at file tail | **OPEN — one candidate ruled out (M-116 follow-up), root cause not found.** Step (1) from the original plan is done… |
|
||||
| D247 | **Black bars top and bottom of screen — possible aspect-ratio defect (M-116, user QA report).** — full `## D247` entry at file tail | **NOT A BUG — confirmed faithful, unmodified N64 decomp behaviour, no code change made.** `GE_PCDUMP` captures (both against the pre-existing save and a fresh-EEPROM run, to rule out a stale `Screen` option from earlier test sessions) show the exact same inset on Frigate… |
|
||||
| D246 | **Tiny pixel strips at the left and right edges of the screen, "like overscan" — look like raw pixels, not 3D graphics (M-116, user QA report).** — full `## D246` entry at file tail | **FIXED (2026-09-18 session, port-only, `Video.SafeAreaCrop`).** Measured precisely (exactly 1.0 logical unit missing on both edges, every resolution); underlying clip-precision root cause not isolated, but `gfx_adjust_viewport_or_scissor` now trims a fixed 1-unit margin from both edges — same toggle/mechanism as D247. Live user playtest confirmed clean edges. |
|
||||
| D247 | **Black bars top and bottom of screen — possible aspect-ratio defect (M-116, user QA report).** — full `## D247` entry at file tail | **FIXED (2026-09-18 session, port-only, `Video.SafeAreaCrop`).** Root cause: faithful, unmodified N64 TV-safe-area letterboxing that real CRT overscan used to hide; this port showed the full VI frame. Per user request, given a real fix (not left as "correct original behaviour"): `gfx_adjust_viewport_or_scissor` now remaps against the active gameplay viewport bounds so it fills the window edge-to-edge. New `Video.SafeAreaCrop` toggle (default on). Live user playtest confirmed clean edges. |
|
||||
| D248 | **Port runs a stable 30 FPS instead of 60 FPS game-wide (M-117, user asked to verify FPS after the D209 timing-keystone fixes).** — full `## D248` entry at file tail | **FIXED, root-caused to a genuine pointer-width ABI bug in `src/sched.c` (compiled for the PC build, not excluded).** `osScAddClient()` (`src/sched.c:187-199`) stashes a per-client "present every retrace vs.… |
|
||||
| D249 | **LOD/culling breaks down on large open levels (Streets, Egyptian named specifically) at *default* FOV — far-away geometry has visible culling issues (M-119…** — full `## D249` entry at file tail | OPEN — M-142 static review ruled out the unscaled-far-clip and LOD-multiplier suspects (both already correct); narrowed to the portal/room-visibility BFS, needs a live screenshot+location, not more code reading.… |
|
||||
| D250 | **FPS is inconsistent/low on many levels after 60 Hz shipped (M-119, user QA; D248 follow-on).** — full `## D250` entry at file tail | FIXED — per-call `getenv()` cost was the bottleneck; rock-steady 60-61 fps after, user re-tested 1440p/4K clean. |
|
||||
| D251 | ****F10 options overlay QoL pass:** — full `## D251` entry at file tail | **FIXED (port-only, `port/src/optionsoverlay.c`).** (a) The panel now computes how many rows fit the *actual* current 2D height (`maxVisibleRows()` from `viGetY()`) and scrolls… |
|
||||
| D252 | **Particle effects cycle through a rainbow palette (M-124, user playtest of the v0.2.0-pre candidate).** — full `## D252` entry at file tail | OPEN — root cause genuinely open; M-157 got the first visual capture (bullet-spark path, `glass2.c`) and M-158 found it NOT reproducible in 6 identical dev-box runs — flaky/environment-dependent. GE_D157 probes (D157T/D157I) in tree to capture the full RGBA path on next occurrence (user Deck run with `GE_D157=1`). Cheap repro: bullet-impact sparks. Documented only for v0.2.0-pre per user instruction. |
|
||||
| D252 | **Particle effects cycle through a rainbow palette (M-124, user playtest of the v0.2.0-pre candidate).** — full `## D252` entry at file tail | **CLOSED as a duplicate of D219 (M-188, 2026-09-18)** — the user's actual live-observed symptom ("lingering particle sprites after an explosion") is the same `bullet_spark_render` bug D219 fixed; user-confirmed live on Facility. The *original*, older main-explosion-fireball palette question (`explosion.c`/`import_texture_rgba16`/`G_CC_INTERFERENCE` combiner) is a separate, narrower open thread the user reports was already fixed a while back and hasn't recurred — re-open only if a fresh *fireball* (not residue/embers) rainbow report comes in. |
|
||||
| D253 | **Facility (and any level with a FORCECROUCH/LADDER linked special tile) SIGSEGV on Linux/Steam Deck — `stanCheckLinkedSpecialTile` stores to a garbage…** — full `## D253` entry at file tail | FIXED — Deck-verified: user got past the crouch tile with the re-cut bundle (a *new*, later crash is D255). |
|
||||
| D254 | **Linux crash handler destroyed its own logs: `ge007.crash.log` only ever contained the SIGABRT block, never the original SEGV.** — full `## D254` entry at file tail | FIXED — field-verified. |
|
||||
| D255 | **Facility firefight SIGSEGV on Steam Deck (v0.2.0-pre CI bundle; D253 fix confirmed working).** — full writeup directly below this table (row status was stale; see M-140 update) | **FIXED (M-140)** — D3x-class 32-bit pointer truncation (`vtxstore_fix_refs` read `Model*` through the mistyped `ChrRecord.chrflags` 4-byte-enum alias instead of `ObjectRecord.model`), not the destroy-path race originally suspected. Verified live on real Steam Deck hardware (Facility + Caverns, zero crashes); Windows 21-level sweep clean. |
|
||||
@@ -585,7 +585,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121).
|
||||
| D297 | **v0.3.0 silently wipes ALL pre-fix player saves on first launch (D284 side effect; found during D295/M-148).** — full `## D297` entry at file tail | FIXED (M-150) — migration shim landed: `port/src/legacycrc.c` (isolated, deliberately-wrong pre-D284 PRNG, reviewer-verified bit-exact against `0de99b4d^`) + eeprom-shim read-path hook in `libultra.c` (block 4 only; persists pristine+migrated bytes before the read-time-only AllUnlocked patch). Verified: user's #87 artifact → `D297-migrated 5`, all slots OK, idempotent on relaunch; native post-fix save untouched; corrupt slot left to the game's own wipe path; fresh eep untouched; 21/21 sweep PASS. Block-0 header needed no migration (factory seal, verified). |
|
||||
| D298 | **Full HUD (not just the aim-mode crosshair) missing in a v0.3.0 dev build — user suspects a debug-launch artifact and asked NOT to raise it until seen in a regular release-targeted build; parked** — full `## D298` entry at file tail |s — regression reported 2026-09-16 during v0.3.0 work (build ce8427cf); user says "don't fix, just for context"; not yet investigated** — full `## D298` entry at file tail |
|
||||
| D299 | **Game.SkipIntro crashed selecting any save slot except one — reproduced on a fresh save and on a clean Release rebuild, ruling out stale save data (found + fixed 2026-09-17).** — full `## D299` entry at file tail | FIXED — `fileValidateSaves()` (only called from the skipped legal screen) never ran under `SkipIntro`, leaving `saves[]` all-zero; added the missing call to the `SkipIntro` shortcut (`src/game/lv.c`, `#ifdef PORT`, zero game-logic change). Build-verified both `RelWithDebInfo`/`Release`; live user re-test confirms all 4 slots now selectable with `SkipIntro=1`. Not yet run through a full 21-level sweep. |
|
||||
| D300 | **Hipfire look feels non-uniform (issue #89): mouse px routed through the N64 analog stick's quadratic natural-turn curve, so slow motion is "almost unrecognised" and fast motion saturates at full turn speed by ~13 px/poll.** — full `## D300` entry at file tail | FIXED, user-confirmed live — WI-1 per `docs/dev/GEPD-INPUT-PLAN.md`: new `hipDirectCompute()` (`port/src/input.c`) writes `vv_theta`/`vv_verta` directly, mirroring GEPD's hipfire formula and D194's existing aim-mode direct-write pattern — linear px→degree, FOV-scaled, dt-normalized, bypassing the stick curve entirely. Safety-gated on `bonddead`/`outside_watch_menu`/`pause_state` (GEPD's `!dead && !watch && !pause`, ported from decomp fields since hipfire, unlike aim mode, has no RMB-held natural gate). `Input.MouseDirectLook` (default 1) is the escape hatch back to the legacy stick path. Build/link-verified; user playtested live: "input already feels better." |
|
||||
| D300 | **Hipfire look feels non-uniform (issue #89): mouse px routed through the N64 analog stick's quadratic natural-turn curve, so slow motion is "almost unrecognised" and fast motion saturates at full turn speed by ~13 px/poll.** — full `## D300` entry at file tail | FIXED, user-confirmed live — WI-1 per `docs/dev/GEPD-INPUT-PLAN.md`: new `hipDirectCompute()` (`port/src/input.c`) writes `vv_theta`/`vv_verta` directly, mirroring GEPD's hipfire formula and D194's existing aim-mode direct-write pattern — linear px→degree, FOV-scaled, dt-normalized, bypassing the stick curve entirely. Safety-gated on `bonddead`/`outside_watch_menu`/`pause_state` plus (M-190, 2026-09-18) the scripted-camera-mode check the original safety-gates writeup named but never implemented — mouse could freely move the camera during POSEND/INTRO cutscenes until this session. `Input.MouseDirectLook` (default 1) is the escape hatch back to the legacy stick path. Build/link-verified; user playtested live: "input already feels better," then again post-M-190: "ok yeah looks good." |
|
||||
| D301 | **`fileGetIsCheatUnlocked()` NULL-deref, unguarded on every call site, not just the D299/SkipIntro one (GitHub #87, two reports with an identical crash PC/fault address).** — full `## D301` entry at file tail | FIXED locally on `release/v0.3.0` (not pushed) — NULL-guarded `fileGetIsCheatUnlocked()` itself (`src/game/file2.c`, `#ifdef PORT`) rather than only its one known trigger route; build-verified, crash-free smoke test. Live confirmation against the actual #87 repro still owed — a synthetic `GE_STARTMENU=6` repro attempt did not reproduce the crash even pre-fix, so the exact #87 trigger condition (why the save lookup fails) remains unconfirmed. |
|
||||
|
||||
Phase 2 replaced the Phase-1 demo loop with the real `mainproc()` on real OS
|
||||
@@ -10896,6 +10896,18 @@ proper, not during the opening establishing shot. Correlate against
|
||||
D280's own capture conditions (what level state/position produced 720)
|
||||
if that's recorded anywhere in the D280 write-up above.
|
||||
|
||||
**Pass 12 (2026-09-18, this session): a genuinely new mechanism found and confirmed real, but the exact visually-bugged view still has too little tree-class geometry to test it against — not a fix, narrows the next pass.**
|
||||
|
||||
**New mechanism, not considered by passes 1-11 (all of which reasoned from z/w comparisons):** decoded both classes' full `other_mode_l` words offline — `0xc81049d8` (noise) and `0x0c184b50` (tree cards) are **both `Z_CMP=1`/`Z_UPD=0`/`ZMODE=DEC`** (decal mode, depth-tested but not depth-written). Two non-depth-writing decals never actually depth-test against each other — each tests only against the static background's z-buffer — so on-screen precedence between them is decided by **draw order alone** (whichever is submitted later in the frame wins the color buffer), not by which is geometrically closer. This means the z/w comparisons all 11 prior passes made were measuring something that doesn't determine the visual winner between these two specific classes.
|
||||
|
||||
Built `GE_D236ORDER` (`port/fast3d/gfx_pc.cpp`, `gfx_sp_tri1`, env-gated, zero cost unset) to measure this directly: a per-frame submission-order counter, logging the min/max order index for each class whenever `num_dls` (frame) changes. Also built `GE_D236ZFIX` (same file), a diagnostic-only experiment forcing `depth_update=true` for the tree-card class alone, to test whether giving it real z-write lets it correctly block a later-drawn noise quad — **not proposed as a fix** (decal-mode classes aren't supposed to write depth; this would need its own rule-2 justification if it ever became a real fix candidate).
|
||||
|
||||
**Headless repro finally landed on the actual bug, no live session needed this pass.** `GE_PCDUMP=1300-1700:100` on `-level_36` (a snowy corridor level, not literally "Surface 1/2" by debug number but visually and mechanically the same wall-of-static symptom) captured the exact reported look: a solid black-and-white static-noise "wall" on both sides of a snow corridor, `docs/dev/GRAPHICS-BACKLOG.md`-consistent with the user's screenshots. **`GE_D236ORDER` at this exact captured frame range shows `tree_n=0` throughout** — the discrete tree-card class has **zero triangles present at all** in the view that shows the bug, not merely "in the wrong order." A few hundred frames earlier in the same deterministic run (dl≈609-634), 2 tree triangles ARE present and (in that window) drawn **after** the noise class — the theoretically-correct order for them to win — but 2 triangles is nowhere near enough geometry to visually register against a whole wall of noise texture, and a screenshot at that exact frame (`scratch/ppm_620/frame_000620.png`) confirms it looks identical to the bugged view (no visible trees).
|
||||
|
||||
**Conclusion: the draw-order/decal mechanism is real and worth keeping as a documented candidate, but it isn't provably the active cause of the specific reported visual** — the deterministic boot simply never has enough tree-class geometry present at the bugged camera position to test the theory against, the same wall every pass since D280 has hit. This is unchanged from pass 9-11's own conclusion despite the new mechanism: **the real blocker is still CPU-side tree-prop instantiation/room-streaming at this exact camera position**, not (as far as this pass can tell) a port-side rendering bug. Confidence: HIGH that the decal-mode draw-order mechanism is real and correctly understood; LOW-to-none that it's the dominant cause of the reported symptom, since the necessary competing geometry isn't present to observe it losing or winning.
|
||||
|
||||
**Next pass, concrete (supersedes the "correlate against D280" step above, still valid but now sharper):** a live human session, `GE_D236ORDER=1` set, walking directly toward the tree line from inside the level (not the deterministic boot's opening corridor) is now the single most informative next capture — it would show, in one run: (a) does the tree-card count reach anything near D280's ~720 figure at this camera position, and if so (b) is `GE_D236ORDER`'s per-frame order relationship consistently noise-after-tree (bad) or tree-after-noise (fine) once real geometry is present. That single data point would finally either confirm or rule out the decal draw-order mechanism as the actual fix target, something no headless capture has been able to test in three sessions running. **Not v0.3.0-blocking, per standing user priority** — recommend parking again rather than rushing an unverified fix under release-timeline pressure. `GE_D236ORDER`/`GE_D236ZFIX` left in tree, env-gated, zero behavior change when unset.
|
||||
|
||||
## D237 — QoL ask (M-106, user QA): F10 options overlay — make it scrollable with the mouse wheel, expose more settings into it (e.g. screen-flash / no-hit-flash…
|
||||
|
||||
**QoL ask (M-106, user QA): F10 options overlay — make it scrollable with the mouse wheel, expose more settings into it (e.g. screen-flash / no-hit-flash `Game.NoHitFlash`, and other easily-exposed config keys), and organise rows by category (mouse settings together, video together, etc.).** The overlay (`port/src/optionsoverlay.c`) already renders over the registered `config.c` option list; what's missing is wheel-scroll nav, a broader row set, and grouping headers. Cross-ref `OPTIONS-MENU-PLAN.md` §3 (v1 minimum set) + QOL-INVENTORY "PD has, GE lacks".
|
||||
@@ -11591,7 +11603,9 @@ This is a **perfect, smooth white-hot → yellow → orange → deep-red → fad
|
||||
|
||||
**Live-playtested by the user this session: "input already feels better."** No known issues from that testing. Two unrelated side effects noted (mouse now active during the pre-control intro flying cutscene; no mission-complete screen after Dam) were explicitly deferred by the user for separate investigation — not a regression in this fix itself.
|
||||
|
||||
**Status:** **FIXED, user-confirmed live** — code complete, compiles clean, links, live-playtested with positive feedback. WI-2/WI-3/tank-direct-write remain deferred per the plan's phasing (not blockers for this item).
|
||||
**M-190 (2026-09-18, D243 camera-tracking review session): closed the first deferred side effect above — the missing gate was in this feature's own safety-gate list, not a new bug.** The "mouse now active during the pre-control intro flying cutscene" report, surfaced but deferred at ship time, reproduced again during a live review of the Dam abseil cutscene ("camera angles do not follow bond... on the intro fly in camera... you're not supposed to be able [to move the mouse]... same as the intro flyover cam"). Root cause: this entry's own Safety Gates section above already named the requirement ("hipfire look is always live, so it needs the check explicitly or it would fight the game's own camera control during a death cam or cutscene," mapping to GEPD's `camera==4||0` condition) and `hipDirectCompute()`'s in-code comment stated it explicitly too — but the actual gate list (`bonddead`/`outside_watch_menu`/`pause_state`) never implemented the camera-mode check, only the death/watch/pause ones. Fixed by adding the missing check: `gameScriptedCameraActive()` (`bondview2.c`, renamed from D243's `d243mCutsceneActive()` since it was never D243-specific), gating on `CAMERAMODE_POSEND`/`INTRO`/`SWIRL`/`FADESWIRL`. User confirmed live, full intro-flyover + Dam abseil playthrough: "ok yeah looks good." The second deferred item (no mission-complete screen after Dam) is unrelated and remains open — not touched this pass.
|
||||
|
||||
**Status:** **FIXED, user-confirmed live** — code complete, compiles clean, links, live-playtested with positive feedback, and the one deferred safety-gate gap (mouse-lock during cutscenes) closed in M-190. WI-2/WI-3/tank-direct-write remain deferred per the plan's phasing (not blockers for this item). The "no mission-complete screen after Dam" side effect remains open, untouched.
|
||||
|
||||
## D301 — `fileGetIsCheatUnlocked()` NULL-deref, unguarded on every call site, not just the D299/SkipIntro one (GitHub #87)
|
||||
|
||||
@@ -11641,3 +11655,29 @@ Returns "cheat not unlocked" — the same safe default other cheat-state paths a
|
||||
**D240/D241 — gunshot SFX.** **D241 CONFIRMED (not "likely") duplicate of D207**: identical mechanism — GE's 8-voice SFX cap, with D206's fix correctly making the alarm klaxon a genuine infinite looped voice that legitimately occupies one slot; once 8/8 are held, new one-shot gunshot requests are silently dropped by the preemption scan's refusal to steal an owned LOOPED voice. **Correction to the triage report's "monitoring status" framing:** D207 has **no fix in the tree** — an M-77b last-resort LOOPED-preemption pass was implemented but reverted after its BUNKER1 test harness failed to reproduce starvation (`[D207-DROP]=0`). D241 supplies the repro D207 was missing (alarm active + PP7/AK47 specifically; Klobb unaffected, asymmetry still unexplained — both share `AutomaticFiringRate=0x03` so fire-rate alone doesn't explain it). Recommend: close D241 as a duplicate, fold its repro into D207, re-apply M-77b's preemption pass and retest against D241's specific repro rather than the harness that never triggered it. **D240** (SFX cadence mismatch): low-medium confidence this is a distinct live bug — both plausible tick chains (D209 game-tick side, D204 audio-DAC-rate side) are already fixed/merged; the report may simply predate those merges. Not touched by user's v0.3.0 priority list.
|
||||
|
||||
**D286/D287/D296 — freezes/crash. Deprioritized per user (2026-09-18): "old reports," not v0.3.0 scope.** Recorded for completeness, no further action planned this cycle: **D296 is mislabeled in the triage report** — the actual finding is a *stutter* report ("maybe from the drone guns"), not a crash; it got conflated with D295 (a separate, already-fixed crash that did not reproduce in that same playtest session). `docs/dev/BUG-TRIAGE-REPORT.md` and `findings-index.csv` both need correcting from "crash" to "stutter." **D287**: architecture confirmed (32-slot scheduler completion queue, drained only by the main frame loop), but the evidence file previously believed to show the queue full at freeze-time (`scratch/d287_freeze_gdb.txt`) is actually a normal clean-exit capture with zero hits for the freeze markers — no real freeze-time state has ever been captured; needs a live `GE_D287` heartbeat variant that doesn't cap at 3 reports. **D286**: no new narrowing, asset-streaming-stall remains an untested guess.
|
||||
|
||||
**M-187 (2026-09-18, this session): the "shipped" M-183/M-185 clamps were never actually active for a real player — found and fixed, independent of the still-open root cause.** Both clamps (`model.c` playspeed >10.0 → 1.0, endframe <0/>1000 → 100.0) were gated on `d243mProbeActive()`, which ANDs the scripted-camera-mode test with `getenv("GE_D243M") != NULL` — so despite HANDOFF.md/findings-index describing them as a committed partial fix, they only ever fired during a diagnostic capture (`GE_D243M=1` set), never in a normal playthrough. This is a plausible full or partial explanation for why the user kept seeing the unclamped symptom after M-183/M-185 "shipped." **Fixed:** added `d243mCutsceneActive()` (`bondview2.c`, new, camera-mode test only, no getenv) and re-gated both clamps on it; the `D243M: clamp ...` log lines stay separately gated on `d243mProbeActive()` so diagnostic output is unchanged. Also corrected both clamps' in-code comments, which still cited the M-186-refuted "D100/D140 struct-punning" explanation — replaced with the real, still-open mechanism (`modelSetAnimation2` never resets `unkb0/unkb4/unkac/animrate` on a scripted restart). `#ifdef PORT`, no game-logic change, ABI-neutral (control-flow/gating only). Build clean (`./build-pc.sh ntsc-final`, only pre-existing unrelated warnings); `tools_pc/verify.sh dam` PASS (3 frames, crash-free). **Not yet live-verified against the actual Dam abseil cutscene** — needs the user to play it and confirm whether Bond's animation/positioning now looks correct with a normal launch (no env vars needed, the fix is unconditional-in-cutscene now).
|
||||
|
||||
**Also this session: extended the D243M instrumentation for the still-open root-cause question** (findings.md's own "Not verified" item above), ready for the next live capture: `modelTickAnim`'s existing `D243M: tickstart` probe (`model.c`) now also logs `numticks` (the D193 multi-tick catch-up burst size for that call — the leading candidate for why `unkb0`/`unkb4` could be PC-specifically stale, since N64 never executes more than one tick per frame). New `D243M: animrestart` probe (`chraction.c`, `chrlvPerformAnimationForActor`, right before the `modelSetAnimation()` call) logs `chr=/animID=/startframe=` plus the model's `unkb0/unkb4/unkac/animrate/playspeed` at the exact instant of a scripted animation restart — same `d243mProbeActive()` gate as the rest of the family, zero cost/behavior change when `GE_D243M` is unset. **Next live step (needs the user, per the standing division of labor on this bug):** `GE_D243M=1`, play Dam to the abseil, send the log. Look for the 3rd `D243M: animrestart` line for Bond's `chr=` and check whether `unkb0` is already nonzero going in (confirms the stale-state hypothesis) and whether the preceding `D243M: tickstart` lines show `numticks>1` (confirms the D193-catchup-burst PC-specific trigger) in the ticks immediately before it. If `unkb0` is 0 at that point, the hypothesis is refuted and the search moves to `unka0` (D243 CONSOLIDATED NEXT STEPS' still-untried alternative, `bondtypes.h:1643`).
|
||||
|
||||
### M-189 (2026-09-18, same session): ROOT CAUSE FOUND AND FIXED — live-confirmed by the user; D243/D173/D292's animation/positioning symptom is resolved
|
||||
|
||||
**The user's own live capture (`GE_D243M=1`, full Dam→abseil playthrough) delivered exactly the data M-187/M-188 asked for, and it refuted the `unkb0`-blend-state hypothesis outright — every `D243M: animrestart` line for Bond's cutscene chr (`chr=5037`) showed `unkb0=0.000` at every one of the 4 scripted restarts.** But the same lines carried the real signature: `unkac=6.283`/`12.566` (exact multiples of 2π — a rotation-angle value, not a legitimate animation blend factor) and `animrate=-3111.625` — which is bit-identical (to print precision) to this same chr's own `pos.z` at that moment (`-3111.6`, matching the exact Z value M-160/M-162's captures cycled through repeatedly). Cross-referencing the immediately preceding `D243M: setanimplayspeed`/`CREATE` lines for the same `model=` pointer made the mechanism undeniable: at model-creation time, `playspeed=-14647.539`/`animrate=-2082.015` (read as stale/garbage before being overwritten) were bit-identical to that exact model's own `prop->pos.y`/`pos.z` (`-14647.5`/`-2082.0`).
|
||||
|
||||
**Root cause: a hardcoded 32-bit struct-size literal, stale after 64-bit pointer widening — the actual mechanical bug behind the whole family, distinct from (and more precise than) M-186's "no unfixed punning gap" finding, which only checked ordinary named-field `Model*` access, not this buffer-layout site.** `bondview2.c`'s player third-person body model (used by the `CHR_BOND_CINEMA` cutscene path, the exact model this whole investigation has been chasing) is carved out of a raw scratch buffer with manually-computed offsets: `model = (Model *)(weaponbuf0 + cursor); cursor = ALIGN64_V3(cursor + 0xfb);` (`bondview2.c:598-599`, right after the identical, correctly-written idiom for `ModelFileHeader` one line up: `cursor = ALIGN64_V3(cursor + sizeof(ModelFileHeader) + 0x3f)`, line 591). Decoded: `0xfb == 0xbc + 0x3f` — i.e. this literal IS `sizeof(Model) + 0x3f` for N64's 32-bit `Model` (188 bytes), just pre-computed as a constant instead of written with `sizeof()` like its neighbor. **Confirmed empirically, not just by inspection:** a standalone compile against the real build's exact flags/includes (`scratch/sizeof_model.c`, same defines as `compile_commands.json`'s `bondview2.c` entry) measured `sizeof(Model) == 232` (`0xe8`) on 64-bit PC — pointer-widened fields (`attachedto`, `attachedto_objinst`, `anim`, `anim2`, plus alignment) grew the struct by 44 bytes past the 32-bit original. The stale `0xfb` literal under-reserves by exactly that much, so the very next thing placed in the buffer — the animation-node data array, `animdata = (u32 *)(weaponbuf0 + cursor)` — starts **inside** the tail of the just-allocated `Model`, overlapping precisely `playspeed`/`animrate`/`unkac`/`unkb0`/`unkb4` (`bondtypes.h:1643-1650`, the struct's last 5 real fields before `anim_translation_scale`). Every subsequent write to that overlapping animation-data region corrupts those fields with arbitrary content, and the model's own uninitialized/garbage state before first use reads back as whatever happened to be sitting in adjacent memory (here, the model's own `pos`) — exactly matching every anomalous value captured across M-160 through M-188.
|
||||
|
||||
**This qualifies as the project's standard ABI/pointer-width narrow exception (AGENTS.md rule 2), not a game-logic change:** semantics-preserving, mechanical, and the fix simply completes the pattern the surrounding code already uses. **Fix applied (`#ifdef PORT`, `bondview2.c:598-609`):** replaced the stale `ALIGN64_V3(cursor + 0xfb)` with `ALIGN64_V3(cursor + sizeof(Model) + 0x3f)` — the real `sizeof(Model)` computed at compile time, matching the `ModelFileHeader` idiom one line above exactly. The `#else` branch (N64/original literal) is preserved unmodified for non-PORT builds.
|
||||
|
||||
**Live-verified by the user, full Dam→abseil playthrough, normal launch (no env vars): "Yep fixed and the animations seem to play right."** This closes the actual animation-corruption mechanism for D243/D173/D292's shared family (see D173/D292's own entries — same `Model`-carving-buffer class is worth checking there too, not yet done). Build clean, `tools_pc/verify.sh dam` PASS. M-183/M-185's clamps (now correctly gated per M-187) remain in the tree as a defense-in-depth stopgap — harmless now that the actual corruption source is fixed, since `playspeed`/`endframe` should no longer go out of range in the first place.
|
||||
|
||||
**Remaining open item for this family (not a regression, a distinct piece of work): the Dam end-cutscene camera should now correctly track Bond, but this needs a dedicated review, not just an assumption.** M-170's `field_488.pos` freeze-and-rebaseline-on-teleport-epoch (`bondview2.c:10599-10629`, unconditional, not env-gated) was built as a workaround for camera shake that we now know was itself downstream of this exact M-189 corruption (a corrupted/cycling render-skeleton position feeding the camera's look-at filter). With the real root cause fixed, `field_488.pos` should already be receiving correct, non-cycling data every tick — which may make M-170's freeze either redundant or, worse, actively wrong: freezing between teleports could now be suppressing *legitimate* per-shot camera tracking of Bond's real (correct) motion that the freeze was never designed to distinguish from the old corruption. **Next step:** live-review the Dam abseil cutscene with fresh eyes on whether the camera visibly tracks Bond through each of the 3 scripted shots (per the user's own N64 memory: "stands on the edge and then jumps... camera tracks him as he descends," M-169's note) — if it does, no further work needed; if the camera looks static/wrong-angle for any shot, M-170's freeze is the first thing to loosen or remove now that it's very possibly no longer needed.
|
||||
|
||||
### M-190 (2026-09-18, same session): live camera-tracking review confirmed M-189's prediction — M-170's freeze replaced with a filter re-seed; a second, unrelated mouse-lock bug found and fixed in the same pass
|
||||
|
||||
**User's live review confirmed the M-189 tail's prediction exactly: "the camera angles do not follow bond and dont fully match n64."** M-170's freeze (`bondview2.c:10599-10629`) was skipping every `field_488.pos` write during `CAMERAMODE_POSEND` except the one tick a teleport epoch changed — correct behavior when the input was corrupted garbage (pre-M-189), actively wrong now that it's legitimate per-tick motion, since freezing it means the look-at target never moves within a shot.
|
||||
|
||||
**Fix:** replaced the freeze with a write-every-tick-plus-instant-reseed scheme. `field_488.pos` is now written unconditionally every tick (restoring real per-tick tracking of Bond's motion within a shot). Separately, on the exact tick a teleport epoch changes (a real shot-change, same signal M-170 used), the look-at filter's leaky-integrator accumulator (`field_3B8`, consumed by the unmodified decomp function `bondviewUpdatePlayerCollisionPositionFields`, `bondview2.c:4910-4924`) is re-seeded directly to the new position's *pre-scale* value (`pos / FACTOR_2`, since `field_3C4/8/C = field_3B8 * FACTOR_2` is the filter's actual output) instead of being left to converge over ~20 ticks (M-143's original shake mechanism, confirmed PC-only vs N64 in M-144). `field_3C4/8/C` (what the camera's look-at code actually reads) are also set directly so the correct value is live even before the next filter tick runs. Entirely `#ifdef PORT`, port-layer only — the decomp filter function itself is untouched, this only seeds its accumulator field from the outside at a legitimate, decomp-recognized "reposition" event.
|
||||
|
||||
**Second, unrelated bug found and fixed in the same review pass: mouse-look was never gated during scripted/no-control camera states, letting the player freely move the view during the Dam intro flyover and the abseil-jump cutscene (both meant to be camera-locked).** Root cause: `port/src/input.c`'s `hipDirectCompute()` (the default-active WI-1 direct mouse-to-`vv_theta`/`vv_verta` write path, `mouseDirectLook=1`) had its own doc comment explicitly stating "a frozen or scripted-camera state (POSEND/INTRO cutscenes, death cam, pause) must be checked explicitly or this would fight the game's own camera control during those states" — but the actual gate list (`mouseDirectLook`/`mouseGrabbed`/`bonddead`/`outside_watch_menu`/`pause_state`) never implemented that documented check. `bondviewFrozenMoveBond` (`bondview2.c:7947`) already correctly zeroes stick input during these camera modes, but that gate lives entirely inside the stick-based `MoveBond`-vs-`bondviewFrozenMoveBond` dispatch (`bondview2.c:8268`) — `hipDirectCompute` writes `p->vv_theta`/`vv_verta` directly, bypassing that dispatch and the game's own camera-lock logic entirely. **Fix:** added the missing check, calling the same scripted-camera test D243's clamps already use. Renamed `d243mCutsceneActive()` → `gameScriptedCameraActive()` (`bondview2.c`) since the function was never D243-specific and is now used by two unrelated call sites (`model.c`'s clamps, `port/src/input.c`'s new gate) — behavior-identical rename, all three call sites updated.
|
||||
|
||||
Build clean (`./build-pc.sh ntsc-final`), `tools_pc/verify.sh dam` PASS. **User confirmed both fixes live, full Dam intro-flyover + abseil-jump + abseil-descent playthrough: "ok yeah looks good."**
|
||||
Reference in new issue
Block a user