7.2 KiB
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-LODshifts/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
- 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). - D176(a) black sky — untouched, separate investigation.
- D182 — re-test the file-select round-trip now that
GE_TEXPITCH/GE_TEXRAWexist; the "renders once" half (D182-1) is Family C. - Reassess C/D/E with the user. D174 (blood) is the cheapest — just needs a sidecar regen + BUNKER1 firefight to confirm the D120 fix.