mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
docs(D172): withdraw 0xB9 root cause — it's G_SETOTHERMODE_L, already handled
0xB9 == G_SETOTHERMODE_L in this non-F3DEX2 build (G_IMMFIRST-6); fast3d handles it as gsDPSetRenderMode. -level_09 sustained-fire run: zero D146 aborts, zero warnings. Re-scoped to the 2-cycle/cycletype hypothesis (records never set G_MDSFT_CYCLETYPE -> use_2cyc==0 on PC -> TEXEL1 garbage -> magenta/cyan).
This commit is contained in:
1 parent
90641f6305
commit
809560ca1e
2 files changed
+53
-35
No files matched your search
@@ -45,50 +45,65 @@ bit layout:
|
||||
- The generated GLSL combiner implements the RDP formula with the usual special cases;
|
||||
`SHADER_COMBINED` correctly resolves to the previous cycle's running value.
|
||||
|
||||
## 4. Root-cause candidate: the 0xB9 word aborts the sub-DL (D146 path)
|
||||
## 4. The 0xB9 root-cause candidate is WITHDRAWN (M-82, 2026-09-08)
|
||||
|
||||
fast3d's SP walker has **no case for opcode 0xB9** (full case list audited: MTX/MOVEMEM/
|
||||
VTX/DL/COL/syncs/all DP immediates/EXT commands — nothing in the 0x80–0xBF group). Its
|
||||
`default:` (`gfx_pc.cpp:2920`, the D146 guard) **ends the whole (sub-)display list** on an
|
||||
unknown opcode.
|
||||
The earlier audit claimed fast3d has "no case for opcode 0xB9" and that the D146
|
||||
`default:` guard therefore aborts every particle sub-DL. **That is wrong.**
|
||||
|
||||
Consequence for every particle record replay:
|
||||
This build does **not** define `F3DEX_GBI_2` (verified: no `-DF3DEX_GBI_2` in
|
||||
`CMakeLists.txt`, no `#define` in `include/PR/gbi.h` or anywhere in tree). In the
|
||||
non-F3DEX2 branch of `gbi.h`, `G_SETOTHERMODE_L = G_IMMFIRST-6 = -71`, and
|
||||
`(uint8_t)(-71) == 0xB9`. So `gfx_pc.cpp:2731` `case (uint8_t)G_SETOTHERMODE_L:`
|
||||
**is** `case 0xB9:`.
|
||||
|
||||
```
|
||||
RDPPIPESYNC -> ok (no-op)
|
||||
0xB9 -> D146 default -> RETURN (sub-DL dead)
|
||||
G_SETCOMBINE -> never applied
|
||||
G_SETTIMG -> never applied
|
||||
<particles> -> drawn with STALE combine mode + stale tile/timg state
|
||||
```
|
||||
Decode of the record word `w0 = 0xB900031D`, `w1 = <varies>`:
|
||||
`gfx_sp_set_other_mode(C0(8,8)=3, C0(0,8)=29, w1)` → sets `other_mode_l` bits
|
||||
3..31. `sft=3 == G_MDSFT_RENDERMODE`, `len=29` — this is exactly
|
||||
`gsDPSetRenderMode(w1)`. `w1` values (`0x0C184B50`, `0x00504B50`, …) are
|
||||
render-mode / blender words. fast3d applies it correctly.
|
||||
|
||||
Stale CC/tile state = arbitrary colors = the magenta/cyan symptom. On N64, gmain.s
|
||||
obviously handles 0xB9 (the game works there), so this is a fast3d gap, not a ROM quirk.
|
||||
So the particle sub-DL runs to completion on PC: `E7` RDPPIPESYNC (handled),
|
||||
`B9` SetRenderMode (handled), `FC` SETCOMBINE (handled), `FD` SETTIMG (handled).
|
||||
**No D146 abort. No stale-state fallthrough.** The wrong-colour bug is elsewhere.
|
||||
|
||||
Secondary (only matters if 0xB9 turns out to be a no-op): particle 2-cycle rendering
|
||||
requires `G_CYC_2CYCLE` in other_mode_h (`gfx_pc.cpp:1523`); the records never set
|
||||
other-modes, so particles inherit ambient state — same on N64, but worth confirming if
|
||||
the primary fix doesn't resolve it.
|
||||
## 5. Where the bug actually is — re-scoped (M-82)
|
||||
|
||||
## 5. Verification (cheap, in-game)
|
||||
The dominant combine (14/17 records, §2) is a **2-cycle** mode
|
||||
(`cycle 1 RGB: (COMBINED - 0)·SHADE + COMB_A`). But the records set render mode
|
||||
(`0xB9`) and **never set the cycle-type** field (`G_MDSFT_CYCLETYPE`, in
|
||||
`other_mode_h`). On N64 the ambient `other_mode_h` at particle-draw time is
|
||||
2-cycle (set by whatever DL ran before); fast3d's ambient `other_mode_h` at that
|
||||
point is very likely **1-cycle**, so `use_2cyc` (`gfx_pc.cpp:1521`) is false and
|
||||
fast3d renders only cycle-0 of the combine:
|
||||
`(TEXEL0 - 0)·TEXEL1 + COMBINED_A`. With no second tile loaded, **TEXEL1 is
|
||||
garbage** → arbitrary colour → the magenta/cyan symptom. This is the "secondary"
|
||||
note from the old §4, now promoted to the primary hypothesis.
|
||||
|
||||
The D146 guard logs `D146: unknown GBI opcode 0x%02x ...` rate-limited to **20** messages.
|
||||
Run any level, shoot things / trigger flares, watch console output at startup for
|
||||
`unknown GBI opcode 0xb9`. If present → root cause confirmed. (The budget fills in the
|
||||
first frame or two of particles, so check early output.)
|
||||
### Verification
|
||||
|
||||
1. **DONE (M-82).** `-level_09` (bunker1), `GE_INPUTSCRIPT` sustained-fire,
|
||||
~3600 frames, `d172_probe.log`: **zero `D146: unknown GBI opcode` lines,
|
||||
zero ERROR/WARN of any kind.** The particle sub-DL does not abort on 0xB9.
|
||||
§4 root cause is dead. (Headless, so this does not by itself confirm the
|
||||
§5 2-cycle hypothesis — that still needs the probe below.)
|
||||
2. Add an env-gated probe at `gfx_sp_tri*` when `rdp.combine_mode` matches a
|
||||
particle record's key: log `use_2cyc`, `other_mode_h & CYCLETYPE`, the CC
|
||||
key. Expect `use_2cyc == 0`.
|
||||
|
||||
## 6. Fix path (next session)
|
||||
|
||||
1. **Decode 0xB9's semantics.** `ginit.s` (dispatch-table init) is *not in this repo*
|
||||
(`gmain.s:10` includes it; file absent). Options: (a) locate ginit.s in the original
|
||||
source / another checkout; (b) trace gmain.s's 0x80–0xBF group handler by hand;
|
||||
(c) infer from data — w0 is constant `B900031D` across all records, w1 varies
|
||||
(`0C184B50`, `00504B50`, …); if it's an other-modes/cycle-type setter, w1 bits should
|
||||
match G_MDSFT_* fields.
|
||||
2. Implement the handler in fast3d (port-only). Re-run: blood/flares should go dark red;
|
||||
D146 spam for 0xb9 stops.
|
||||
3. If colors still wrong after that: log `use_2cyc` + combine key on particle triangles
|
||||
(env-gated) and check ambient G_CYC_2CYCLE (§4 secondary).
|
||||
1. Run the §5 verification. If `use_2cyc == 0` on particle tris is confirmed:
|
||||
2. **Port-only fix, `src/game/explosion.c` under `#ifdef PORT`** (same
|
||||
hardware-idiom exception class as the existing `G_TRI4` / dynamic-light
|
||||
`#ifdef PORT`s): emit an explicit `gsDPSetCycleType(G_CYC_2CYCLE)` (or the
|
||||
raw `G_SETOTHERMODE_H` immediate) into / ahead of the particle record replay
|
||||
so PC does not depend on ambient cycle-type. `#else` = N64 stream verbatim.
|
||||
Alternative (pure port): in `gfx_pc.cpp`, when a SETCOMBINE carries a
|
||||
2-cycle-only combine (cycle-1 slots non-trivial) force `use_2cyc` — riskier,
|
||||
broader blast radius.
|
||||
3. If colour still wrong after 2-cycle is forced: check `texSelect` actually
|
||||
binds TEXEL1's tile for these records, and re-decode the combine (the §2
|
||||
decode was not re-verified this pass).
|
||||
|
||||
## Files
|
||||
|
||||
@@ -98,3 +113,6 @@ first frame or two of particles, so check early output.)
|
||||
SETCOMBINE decode (2786), combine store (2270), cc generation (312+), 2CYCLE flag (1523)
|
||||
- `rsp/graphics/gmain.s` — N64 ucode ground truth for 0xB9 (dispatch table at dmem 0xbc;
|
||||
ginit.s missing from repo)
|
||||
|
||||
Note (M-82): 0xB9 is `G_SETOTHERMODE_L` in this non-F3DEX2 build and is already
|
||||
handled by fast3d — `gmain.s` / `ginit.s` are NOT needed to resolve D172.
|
||||
@@ -18,7 +18,7 @@ once the game is playable start-to-finish without crashes.
|
||||
| **D149** | Front-end MISSION COMPLETE / mode-select 3D models (dossier, wallets) render as garbled full-screen geometry or not at all — one of the compiled sub-DLs (seg5+0x9ee4) is malformed, D146 now skips it instead of aborting. | D75 family. §F D146. |
|
||||
| **D170** | Named-NPC "flee" scripted behavior 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. **M-49 full playthrough: escalated — Cradle (`-level_51`) is "bugged out completely" from Trevelyan's behavior; the final level's scripted progression breaks. Now folded into / superseded by §F D193 (NPC AI locomotion too slow).** | **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). | **Root-cause candidate found, static research done** (`docs/dev/D172-PARTICLE-COLOR-RESEARCH.md`). Particles get CC/tile state from 15 ROM records replayed via `gSPDisplayList` (`explosion.c:894`); each record contains an opcode **0xB9** that fast3d does not handle → the D146 unknown-opcode guard kills the sub-DL before the record's `G_SETCOMBINE`+`G_SETTIMG` apply → particles draw with stale state = magenta/cyan. SETCOMBINE decode itself verified correct. Verify in-game: watch console for `D146: unknown GBI opcode 0xb9` while shooting (rate-limited to 20). Fix: decode 0xB9 semantics (ginit.s missing from repo — trace gmain.s 0x80–0xBF group or infer from data) + implement in fast3d. |
|
||||
| **D172** | Bullet-impact / blood particle spray renders magenta or cyan instead of dark red (visible on guards hit at close range on Silo). | **M-82: 0xB9 root cause WITHDRAWN** (`docs/dev/D172-PARTICLE-COLOR-RESEARCH.md` §4). 0xB9 = `G_SETOTHERMODE_L` in this non-F3DEX2 build (`= G_IMMFIRST-6`), already handled by fast3d as `gsDPSetRenderMode`; `-level_09` sustained-fire run logged **zero D146 aborts**. New primary hypothesis: the dominant particle combine is **2-cycle** but the records never set `G_MDSFT_CYCLETYPE`, so on PC `use_2cyc==0` → only cycle-0 runs → TEXEL1 garbage → magenta/cyan. Next: env-gated `use_2cyc`/CC-key probe on particle tris; fix = emit explicit `gsDPSetCycleType(G_CYC_2CYCLE)` in `explosion.c` under `#ifdef PORT`. |
|
||||
| **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: **M-36 partial (findings.md "D176(a)").** Env data is correct (`Sky.Clouds=1`, `CloudRGB=240,120,30`, `SkyImageId=0`); `skyRender` runs the cloud path and classifies corners correctly (switch case 12), but `skyRenderTri`/`skyRenderFull` emit nothing — not even the `env->RGB` fill shows. Not root-caused: next is probing `sub_GAME_7F097388` projected coords, verifying `skywaterimages[0]` resolves on PC (`image_bank.c` GIMG offset `0xFB4`), and a fast3d sky-tri trace. `GE_D176=1` probe shipped. **M-37: ROOT-CAUSED** — `skyRenderTri`/`skyRenderFull` build geometry *exclusively* as `G_RDPHALF_*` immediates, which `gfx_pc.cpp` deliberately no-ops (identical no-op in the PD port); fix = decode the RDPHALF tri-raster stream in fast3d (~1 session, genuine new code). **M-42: `-level_22` (Statue) confirmed a clean headless repro** — bare boot, frame ~360, upper half pure black; use it to verify the decoder. **M-47 + read-only consolidation:** Path B draft exists (`scratchpad/sky.patch`, `skyPortRenderPoly` PORT hook — geometry+texture reach GL, two unit defects open) and the full RDPHALF wire format is now decoded (S15.1 half-packing, 8-component perspective-interpolated vertex vectors); next session is mechanical per `docs/dev/D176a-SKY-NOTES.md`. `-level_36`/`-43` intro cams face down (not a sky test without `GE_INPUTSCRIPT`). **M-82: PR #18 rebased onto main + Defect-1 fix applied** — cloud tile is `s_skywaterimages[0]` = 64×64 IA8; the patch's `tc = S·32` scale is correct (matches GE's `width<<5` idiom, `glass2.c:678`), the bug was `(s16)` overflow on the ±20k-texel horizon S/T; fix = per-primitive phase-fold to the 64-texel period (`sky.c` `skyPortRenderPoly`, `#ifdef PORT`). Builds clean, no crash (bunker1/statue/surface1 verify PASS). **Unverified visually** — owed: one `-level_22` screenshot (see `D176a-SKY-NOTES.md` "verification ask"). Defect 2 (horizon-band coverage / straddling tris) still open → adaptive tessellation. **(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). |
|
||||
|
||||
Reference in new issue
Block a user