forked from Ports/goldeneye-pc-port
docs: M-36 triage sweep — bug families, correct the D159 mis-attribution
Headless GE_PCDUMP (-level_36, GE_STARTMENU=10) + static read of the
implicated port code. Two headline findings:
- The "comb interlacing" (D176b, D182-2) is NOT the D159 family.
texSwapAltRowBytes is a full #ifdef PORT no-op (image.c:2199) and
cannot cause anything. Real cause: gfx_pc.cpp import_texture_* assume
line_size_bytes == full_image_line_size_bytes and shear non-PoT /
sub-rect tiles into diagonal noise. New "Family A". Backlog D176/D182
corrected.
- D178 briefing objectives are BLANK, not wrong-listed: header renders,
then just "a." with no objective text. That is the D143/D151
langGet-NULL blank-text family ("Family B"), not a propDef walk desync.
docs/dev/M-36-TRIAGE.md: full family table (A fast3d texture pitch,
B string bank, C D75 models [defer], D blood/particle, E transient
hang [defer], F misc). Recommends Families A and B as the two
high-ROI targets, disjoint enough for two subagents.
Claude-Session: https://claude.ai/code/session_01GULf6knbsqfsnW39tMr9WT
This commit is contained in:
1 parent
ef10985343
commit
9a69d57afd
2 files changed
+86
-3
No files matched your search
@@ -19,12 +19,12 @@ once the game is playable start-to-finish without crashes.
|
||||
| **D170** | Named-NPC "flee" scripted behaviour looks wrong on PC: on Silo, Ourumov breaks into a full run the instant he alerts ("Ourumov: Kill him!") rather than the N64 walk/retreat; developer reports Trevelyan behaves the same way on Cradle. | **Observed, not investigated** (M-34, from a Silo playtest capture; user bug report — no fix wanted yet). Could be a genuine ailist / `chrTick` divergence, OR the D155/D156 wall-clock `deltaFrames` locomotion-anim speed-up (a catch-up spike playing the walk cycle at 2–3×). **Verify first:** capture the same beat against N64 reference footage before assuming it diverges — Ourumov may be scripted to flee. If it's real, suspect the frametiming clamp (§F D155/D156) or the Cradle-family AI path (§F D123). |
|
||||
| **D171** | Silo missile-shaft: a large translucent grey triangle sweeps across the lower frame while panning down the shaft (~3 s of the capture). Looks like a stray poly / near-plane clip fan, same family as D106 (portal near-plane min>max). | **Observed, not investigated** (M-34, Silo capture). Cosmetic, intermittent, tied to camera angle in the open vertical shaft. |
|
||||
| **D172** | Bullet-impact / blood particle spray renders magenta or cyan instead of dark red (visible on guards hit at close range on Silo). | **Observed, not investigated** (M-34, Silo capture). A channel-order / CC-mode error in the particle-sprite path (magenta = R+B, cyan = G+B) — not the D64/D120 blood-decal family (those are crash/hang + missing decals, not colour). Likely a texture-format or env-colour decode in `blood_animation.c` / the fast3d sprite path. |
|
||||
| **D178** | Objectives not listed correctly on the pre-mission briefing screen (the mission overview shown before starting a level). | **Observed, not investigated** (user QA report). "Not correctly" unspecified — wrong set of objectives, wrong order, or garbled/blank lines. Close relatives: D151 (watch objective text blank — type-35/23 `text` slot u16→u32 fix, M-28; interactive re-verify was still pending), D143 (briefing/objective text blank via `langGet` NULL), D157 (objective difficulty byte offset — could make difficulty-gated objectives appear/disappear wrongly). The pre-start briefing is a *different surface* from the in-level watch, so D151's fix may not cover it. **Next:** ask user which level + what exactly shows vs expected; compare against `docs/dev/LEVEL-OBJECTIVES.md` (regenerated post-D157); if lines are blank → D143/D151 family (`langGet` NULL guard = silent blank), if wrong objectives listed → propDef type-23 record walk / difficulty decode. |
|
||||
| **D178** | Objectives not listed correctly on the pre-mission briefing screen (the mission overview shown before starting a level). | **M-36 triage: the objective lines are BLANK, not wrong.** `GE_STARTMENU=10` Dam briefing renders the header fine ("OHMSS / Agent: James Bond / Mission 1: Arkangelsk / Part i: Dam / PRIMARY OBJECTIVES:") then just the bullet "a." with no text and no b/c/d. → **D143/D151 blank-text family** (`langGet()` → NULL → silent blank), *not* a propDef walk / difficulty decode. **Family B** in `docs/dev/M-36-TRIAGE.md` — find which lang bank the front-end briefing flow fails to load. Re-confirm the exact shape in a *real* briefing (the `GE_STARTMENU` boot skips real save state). Close relatives: D151 (watch objective text blank — type-35/23 `text` slot u16→u32 fix, M-28; interactive re-verify was still pending), D143 (briefing/objective text blank via `langGet` NULL), D157 (objective difficulty byte offset — could make difficulty-gated objectives appear/disappear wrongly). The pre-start briefing is a *different surface* from the in-level watch, so D151's fix may not cover it. **Next:** ask user which level + what exactly shows vs expected; compare against `docs/dev/LEVEL-OBJECTIVES.md` (regenerated post-D157); if lines are blank → D143/D151 family (`langGet` NULL guard = silent blank), if wrong objectives listed → propDef type-23 record walk / difficulty decode. |
|
||||
| **D175** | In-game stutter / brief hang during normal play — observed opening a door on Runway (mission 3, `-level_35`) and also on Surface. No backtrace captured (gdb attach missed the window; it self-recovered). | **Observed, not investigated** (user QA report). Matches known transient-hang classes rather than looking new: D155 (post-slow-load catch-up spiral — clamped), D156 (anim NaN loop — guarded, prints one-shot stderr diag if it fires), D134 (SP/DP task-done event swallowed — fixed M-22, Runway was an original victim), D147/D152 (audio `s_imLock` steal = ~2 s hiccup). Door-open specifically = new room first visible → one-off texture-import/frame spike (likely benign). **Next:** reproduce under `tools_pc/debug.ps1` with the box idle; check console for the D156 stderr diag; if it recurs, attach gdb mid-hang and pattern-match `bt` (import_texture = benign slow frame; model.c:3131 spin = D156; pthread_mutex_lock on s_imLock = D147/D152). |
|
||||
| **D176** | Surface exterior renders wrong (two co-located defects). **(a)** Sky is solid **black** — the skybox / sky gradient does not draw at all (reference: warm sunset cloud gradient). **(b)** The perimeter **tree-line backdrop renders as grey TV-static / comb interlacing** instead of snow-laden pines — the geometry is present and roughly the right silhouette but every tree texture is scrambled noise. Ground, tunnel and the dish/bunker building draw fine. | **Observed, screenshots committed** (M-35, user QA; `docs/img/bugs/d176-surface-exterior-our-build.png` vs `-reference.png`). Level is the shared Surface exterior — user reached it Dam→Surface on Agent so this is **Surface (i) `-level_36`** (confirm it also affects `-level_43`). **(a)** black sky: sky DL not emitting / wrong transform (D75 `logoinst` family) or sky tiles failing import — `GE_PCDUMP` + `GE_DTEX` on the sky pass. **(b)** tree static: the comb/interlace pattern is the **D159 family** (`texSwapAltRowBytes` odd-row byte-swap for the RDP TMEM XOR fast3d doesn't emulate) — D159 added an `#ifdef PORT` skip but these tree textures (likely a specific CI/IA format or non-PoT size) still hit a swap/decode path. Same visual as D182 below. Compare `GE_TEXDUMP` of one tree tile against the ROM texture. |
|
||||
| **D176** | Surface exterior renders wrong (two co-located defects). **(a)** Sky is solid **black** — the skybox / sky gradient does not draw at all (reference: warm sunset cloud gradient). **(b)** The perimeter **tree-line backdrop renders as grey TV-static / comb interlacing** instead of snow-laden pines — the geometry is present and roughly the right silhouette but every tree texture is scrambled noise. Ground, tunnel and the dish/bunker building draw fine. | **Observed, screenshots committed** (M-35, user QA; `docs/img/bugs/d176-surface-exterior-our-build.png` vs `-reference.png`). Level is the shared Surface exterior — user reached it Dam→Surface on Agent so this is **Surface (i) `-level_36`** (confirm it also affects `-level_43`). **(a)** black sky: sky DL not emitting / wrong transform (D75 `logoinst` family) or sky tiles failing import — `GE_PCDUMP` + `GE_DTEX` on the sky pass. **(b)** tree/rock static: **M-36 triage — NOT the D159 family.** `texSwapAltRowBytes` is a full `#ifdef PORT` no-op (`image.c:2199`), it cannot cause this. Real cause: `port/fast3d/gfx_pc.cpp` `import_texture_*` assume `line_size_bytes == full_image_line_size_bytes` (`SUPPORT_CHECK`; rgba16's is commented out *"trips ... with a garbage size"* `:658`) → non-PoT / sub-rect tiles get a flat linear read → diagonal row shear = grey static. **Family A** in `docs/dev/M-36-TRIAGE.md`. Fix: honour `line_size_bytes` as the real source pitch. Same defect as D182(2). |
|
||||
| **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 colour, 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 colour"). 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. | **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" behaviour). **(2)** interlacing = **D159 family** (`texSwapAltRowBytes` odd-row byte-swap) reappearing on the spiral texture once it's re-imported on the second visit — suggests the D159 `#ifdef PORT` skip is keyed on something that only holds on the first import (e.g. a cached tile-format flag), or a different texture takes the swap path on re-load. 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" behaviour). **(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). |
|
||||
| **1P weapon viewmodel** | In-level first-person weapon models don't draw at all (no gun visible while playing). | Already documented — **AUDIT-M6 #5** (`docs/dev/AUDIT-M6-player-offsets.md`, "prime suspect") + §F D115 "still open (MED)"; M-8 handoff listed it NOT STARTED with a plan: instrument `gunfire.c:600-661` setup + `field_87F` gating first, then check `weaponModel.render_pos` arena lifetime and `weaponRwPool[192]` sizing. Note M-32b's "render_pos/dynAllocate RULED OUT" probe was the **front-end gun-barrel** path (`title.c`), not this in-level path — candidate #5 still stands. Distinct from the watch-page "dark/faint weapon model" (D75, D141 note). |
|
||||
|
||||
## Resolved (for reference)
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# 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; possibly faint briefing-paper noise | importers assume `line == full_image_line`; shear on non-PoT / sub-rect tiles. **Not D159.** | `port/fast3d/gfx_pc.cpp` `import_texture_*` | **HIGH** — one fix, several visible bugs. Medium difficulty. |
|
||||
| **B — front-end string bank not loaded** | D178 briefing objectives blank (confirmed); D143 briefing text blank; D151 watch objective text (re-verify) | `langGet()` → NULL; the bank the PC briefing flow needs isn't loaded/mapped | `src/game/textrelated.c`, lang bank load in the front-end flow (`lv.c` `langClearBank`/`langGetLangBankIndexFromStagenum`) | **HIGH** — every mission briefing. Medium difficulty (trace the bank). |
|
||||
| **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. |
|
||||
|
||||
---
|
||||
|
||||
## Recommended next steps (per agreed COA — fix families, not bugs)
|
||||
|
||||
1. **Family A** — teach the `import_texture_*` path to honour `line_size_bytes`
|
||||
independently of `full_image_line_size_bytes` (copy row-by-row with the
|
||||
real source pitch). Verify: Surface `-level_36` walls, file-select
|
||||
round-trip, and the golden `-level_09` framediff (must stay 3/3). Likely
|
||||
clears D176(b) + D182(2) together.
|
||||
2. **Family B** — trace the briefing objective string: which `langGet(slot)`
|
||||
returns NULL, which bank owns that slot, why the front-end flow hasn't
|
||||
loaded it. One bank load likely clears D178 + D143 + the D151 re-verify.
|
||||
3. Then reassess C/D/E with the user.
|
||||
|
||||
These two are good candidates for two disjoint subagents (Family A =
|
||||
`port/fast3d/gfx_pc.cpp`; Family B = `src/game/textrelated.c` + lang load) —
|
||||
see `docs/dev-process.md` for the brief template.
|
||||
Reference in new issue
Block a user