Files
goldeneye-pc-port/docs/dev/M-36-TRIAGE.md
T

95 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# M-36 — graphics / QA bug triage sweep
Branch `qol/native-pc-input-menu` (local). Goal: sort the open
`GRAPHICS-BACKLOG.md` + QA-report bugs into **root-cause families** so a
fix hits several at once, and correct one mis-attribution.
Method: headless `GE_PCDUMP` captures (`-level_36` Surface, `GE_STARTMENU=10`
briefing) + static read of the implicated port code. Frames in
`scratchpad/` this session; not committed (auto window size = 1957×1468,
can't framediff — visual only).
---
## Headline findings
### 1. The "comb interlacing" is NOT the D159 family
`GRAPHICS-BACKLOG.md` attributes D176(b) and D182(2) to `texSwapAltRowBytes`
"recurring on re-import". **That function is a full `#ifdef PORT` no-op** —
`src/game/image.c:2199` `return;` before any work. It cannot be the cause of
anything. The mis-attribution is now corrected in the backlog.
The real defect: `port/fast3d/gfx_pc.cpp` `import_texture_*` assume
`full_image_line_size_bytes == line_size_bytes` (explicit `SUPPORT_CHECK`
on rgba32/ia4/ia8/ia16/…; the rgba16 one is commented out with
*"this trips in some places with a garbage size in
full_image_line_size_bytes"*, `gfx_pc.cpp:658`). When a tile's `line`
(SETTILE pitch) differs from the source image row width — non-power-of-two
textures, or a sub-rect tile load — the importer does a flat linear read and
every row walks off by a few bytes → **diagonal shear that reads as grey
static**. Matches the Surface cliff/tree walls (`-level_36` frame 300–900:
structured rock texture tiling but each tile sheared to noise) and the
file-select spiral after re-entry.
Open question: why does D182 only scramble **after** navigating away and
back? Either the first import happens to have `line == width` and the
re-import doesn't, or the tile descriptor is stale on the second visit.
### 2. Briefing objectives are BLANK, not wrong
`GE_STARTMENU=10` briefing (Dam): header renders perfectly ("OHMSS / Agent:
James Bond / Mission 1: Arkangelsk / Part i: Dam / PRIMARY OBJECTIVES:").
Under it: just the bullet letter **"a."** with **no objective text**, and no
b/c/d lines. So D178 is the **D143/D151 blank-text family** (`langGet()`
returns NULL for the objective string slot → text silently blank), *not* a
propDef walk-desync or difficulty-decode problem. Fix = find which lang bank
the front-end briefing flow fails to load/map.
Caveat: this repro used the synthetic `GE_STARTMENU` boot (skips real
save/unlock state). The user's D178 report is from a live playthrough, and
D143 independently documents blank briefing text, so it is a real defect —
but re-confirm the exact "a." + blank shape in a real briefing.
---
## Family table
| Family | Bugs | Root cause (hypothesis) | Files | ROI |
|---|---|---|---|---|
| **A — fast3d texture line/pitch shear** | D176(b) Surface walls; D182(2) file-select bg | **HYPOTHESIS DISPROVEN (D183, `4b71435d`).** 0/166 texture loads on `-level_36` are strided; the wall texture is a 32×32 IA8 whose ROM bytes are genuinely a noise field, decoded correctly. A golden-safe de-stride + `GE_TEXRAW`/`GE_DTEX` diagnostics landed anyway (latent hardening). **D176(b)/D182(2) still OPEN** — next: ROM ground-truth decode of the wall texnum (`TEXTURE-GLITCH-ANALYSIS.md` §7) → likely a tiling-density / UV-scale / `shifts`/`shiftt`-LOD issue (RC3/D167 family) or a wrong-texture bind, not a decode bug. | `port/fast3d/gfx_pc.cpp` | was HIGH, **now needs re-scoping** |
| **B — front-end string bank not loaded** | D178 briefing objectives blank; D143 briefing text blank | **FIXED (D178, `cd1ed574`).** Not a bank-load problem — the `Ubrief*Z` segment is a raw 48-byte BE ROM image loaded with no converter; all 24 `u16` (string ids + difficulty gates) read byte-swapped on LE → `langGet()` NULL → blank, and `>=` difficulty gate always-false → objectives vanish. `romdataFixupBriefing()` swaps in place. Verified: all 4 Dam objectives render at 00 Agent with correct gating. **D143 was a symptom of this** — annotate it superseded. D151 (watch objective text) still owed a re-verify. | `port/src/romdata.c`, `src/game/front.c` (`#ifdef PORT`) | **DONE** |
| **C — D75 front-end / cutscene 3D models** | D75 Nintendo logo; D148 Dam rappel cutscene; D149 MISSION COMPLETE / mode-select models; D182(1) file-select Bond image "renders once"; D173 3rd-person Bond floats; 1P weapon viewmodel absent | mixed: compiled sub-DL corruption (D144/D146), model transform/geometry, `render_pos` arena lifetime, constructor-runs-once | `port/fast3d/gfx_pc.cpp`, `title.c`, `bondview*.c`, model path | **LOW** per fix, deep. **DEFER** (agreed COA). |
| **D — blood / particle** | D172 spray magenta/cyan; D174 no blood decals | D172: CC-mode / texture-format decode in the fast3d sprite path. D174: likely D120 `PointUsage[]` — **only takes effect after a full sidecar regen** (`d43 && d69 && d88 --regen`); verify that first. | `blood_animation.c`, fast3d sprite path; `tools_pc/d43_emit.py` | **MEDIUM**. D174 may already be fixed — regen + BUNKER1 firefight to confirm before touching code. |
| **E — transient hang / anim speed / clip** | D175 door-open stutter (Runway/Surface); D170 NPC flee runs not walks; D171 Silo grey-triangle sweep | D175: matches D155/D156/D134/D147 known classes (benign texture-import spike most likely). D170: D155/D156 wall-clock `deltaFrames` anim speed-up, or just scripted. D171: near-plane clip fan (D106 family). | frametiming clamp, `chrTick`/AI, portal near-plane | **LOW–MED** — needs interactive repro + N64 reference footage. **DEFER**. |
| **F — misc cosmetic** | D74 dead wrap-block (latent, harmless); D76 disclaimer partial (D164 fix owed an eyeball); D77 audio (Phase 3); **D176(a) black sky** | D176(a): sky DL not emitting / wrong transform — **separate from D176(b)**, own investigation (could be C-family or a sky-pass issue). | various | **LOW**, opportunistic. |
---
## Results (2 subagents, integrated + verified on branch HEAD)
- **Family B → FIXED** (`cd1ed574`). Byte-swapped raw briefing segment. Also
explains D143. High confidence.
- **Family A → hypothesis disproven** (`4b71435d`, D183). D176(b) is not a
texture decode bug. Golden-safe de-stride + diagnostics shipped for the
latent case. **D176(b) / D182(2) remain open and need re-scoping** — start
from the ROM ground-truth decode of the wall texnum; suspect
tiling-density / UV / per-LOD `shifts`/`shiftt` (RC3/D167 family) or a
wrong-texture bind.
Harness note: both agent worktrees were created from `def0e0ac` (the M-35
branch point, ~5 commits stale — the M-31 stale-worktree bug again). No harm
this round: the integrator re-applied both patches onto branch HEAD and
verified there. Check `git worktree list` HEADs on the next burst.
## Next
1. **D176(b) re-scope** — offline decode the Surface wall texnum from ROM
(`TEXTURE-GLITCH-ANALYSIS.md` §7). Structured rock in ROM → wrong bind or
UV/tiling; noise in ROM → not our bug (or a shift-LOD density issue).
2. **D176(a)** black sky — untouched, separate investigation.
3. **D182** — re-test the file-select round-trip now that `GE_TEXPITCH` /
`GE_TEXRAW` exist; the "renders once" half (D182-1) is Family C.
4. Reassess C/D/E with the user. D174 (blood) is the cheapest — just needs a
sidecar regen + BUNKER1 firefight to confirm the D120 fix.