From 652663aac6639f3c81f27f19cd5892539e23770d Mon Sep 17 00:00:00 2001 From: James Dansereau <106631954+jkdansereau@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:53:05 -0400 Subject: [PATCH] D75 Bug 2: runtime probe + triage update Adds env-gated GE_D75 probe in title.c sub_GAME_7F007F30 (capped 8 lines). Booted the bare front end through the gun-barrel sequence: - Bond chr model + gun model entirely absent; both Model instances are valid (non-NULL obj, numMatrices 21/1) -> 'model not loaded' ruled out. - chrModelInstance->render_pos is valid and freshly written each frame (== that frame's dynAllocate mtxlist base, clean double-buffer swap, o2p returns it unchanged) -> the 'render_pos = stale dynAllocate arena' hypothesis (D115 #5) is RULED OUT; do NOT land a persistent render_pos buffer. - Zero fast3d DL warnings during the sequence -> not the D144/D146 corrupt-sub-DL family. Failure is downstream in drawjointlist/dotube vtx/node-DL resolution or an off-screen basemtx. Next step: a drawjointlist-level probe. Full write-up in PCPortResearch.md 'D75 Bug 2 - RUNTIME PROBE'. -level_09 nonclear stable (91.66->91.62, D117 pan noise); build green. --- docs/GE-ENV-PROBES.md | 17 +++++++------- docs/PCPortResearch.md | 50 +++++++++++++++++++++++++++++++++++++++++- src/game/title.c | 20 +++++++++++++++++ 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/docs/GE-ENV-PROBES.md b/docs/GE-ENV-PROBES.md index 3407258c..04a86235 100644 --- a/docs/GE-ENV-PROBES.md +++ b/docs/GE-ENV-PROBES.md @@ -33,12 +33,12 @@ Two classes: | Env var | File:line | Finding / what it logged | Status | |---|---|---|---| | `GE_D51` | `port/src/libultra.c:496`, `src/game/model.c:125,244,544` | msgQ 32-slot overflow watch / ModelSlot layout | dead (D51 closed) | -| `GE_D54` | `src/libultra/audio/seqplayer.c:468`, `load.c:369`, `csplayer.c:452` | music seq-table ABI / endianness (`ALMidiHdr`) | dead (D54 closed) | +| `GE_D54` | — (all blocks stripped M-32, commit `49ce620a`) | music seq-table ABI / endianness (`ALMidiHdr`) | dead (D54 closed) — fully removed | | `GE_D56` | `src/game/model.c:227,830` | watch `Model` raw-offset reads | dead (D56 closed) | | `GE_D60` | `port/src/libultra.c:521,735` | gfx frame msgQ delivery trace | dead (D60 closed) | | `GE_D61` | `port/src/libultra.c:795` (`s_d61opened`) | opens a one-shot log file | dead (D61 closed) | | `GE_D62` | `port/src/libultra.c:477` | osRecvMesg trace | dead (D62 closed) | -| `GE_D63` | `src/memp.c:214`, `src/game/bg.c:2525,2880,2908,2953`, `blood_animation.c:237,253`, `dyn.c:103,150`, `front.c:1410,1416,7814,7889,8083,8091,8099,8366`, `image.c:2453`, `language.c:431`, `model.c:4340`, `rsp.c:234,286`, `title.c:607` | gun-barrel sub-DL clobber hunt (D63/D64/D65/D66 — the labels drift within the blocks). **Also `port/fast3d/gfx_pc.cpp` had a D63 branch-trail — stripped M-30, commit `d0789358`.** | dead (D63 closed) — **strip candidate**, see §3 assessment in the session report / PORT-LEARNINGS §E. NB `bg.c:2876/2880` are **not `#ifdef PORT`-guarded** | +| `GE_D63` | remaining: `src/game/bg.c:2525,2908,2953`, `front.c:1410,1416,7814,7889,8083,8091,8099,8366`, `image.c:2453`, `language.c:431`, `model.c:4340`, `title.c:607` | gun-barrel sub-DL clobber hunt (D63/D64/D65/D66 — the labels drift within the blocks). Stripped M-30 (`d0789358`, `gfx_pc.cpp` trail). Stripped M-32 (`49ce620a`): `memp.c`, `bg.c:2880` (incl. the bare non-PORT `d63bgprimarycount` static + entry log), `blood_animation.c`, `dyn.c`, `rsp.c`. **Remaining blocks are all `#ifdef PORT` + getenv-guarded and inert — strip candidates for a later pass.** | dead (D63 closed) — partially removed | | `GE_D69` | `src/game/ob.c:165,227` | stage-load (D69) object trace | dead (D69 closed) | | `GE_D69BB` | `src/game/bg.c:2460,2479,3020` | D69 bg-binary layout trace | dead | | `GE_D69STAN` | `src/game/stan.c:266,276` | D69 stan-tile trace | dead | @@ -47,19 +47,18 @@ Two classes: | `GE_D86` | `src/game/model.c:6295`, `src/game/objecthandler_2.c:143` | D86 model rwdata trace | dead (D86 closed) | | `GE_D87` | `src/game/ramromreplay.c:296,363,381` | D87 `ramromfilestructure` endianness | dead (D87 closed) | | `GE_D88` | `src/game/prop.c:1367`, `src/game/stan.c:3090` | D88 `Usetup*Z` propDef stream | dead (D88 family closed; D88.4 resolved) | -| `GE_D90` | `src/game/bondview_r.c:190,474`, `src/game/bondview2.c:2146`, `src/game/prop.c:1391` | D90 bondview / prop NULL trace | dead (D90 closed) | +| `GE_D90` | remaining: `src/game/bondview2.c:2146`, `src/game/prop.c:1391` (bondview_r.c blocks stripped M-32, `49ce620a`) | D90 bondview / prop NULL trace | dead (D90 closed) — partially removed | | `GE_D96` | `src/game/chrprop.c:436,507` (cached `probe`) | D96 chrprop trace | dead (D96 closed) | | `GE_D104` | `src/game/bg.c:654` (rate-limited, `d104c`) | D104 depth-clear trace | dead (D104 closed) | | `GE_D71LOG` | `port/fast3d/gfx_pc.cpp:645` | D71 fast3d trace | dead (D71 closed) | +| `GE_D75` | `src/game/title.c` `sub_GAME_7F007F30` (capped 8) | D75 Bug 2 gun-barrel model probe: logs `chrModelInstance`/`gunModelInstance` ptr+obj+numMatrices, `render_pos`, `renderData.mtxlist`, `g_GfxMemPos`, `osVirtualToPhysical(render_pos)` | **LIVE** (D75 Bug 2 OPEN — see §F "D75 Bug 2 — RUNTIME PROBE") | ## Notes -- `GE_D63` in `bg.c` at lines 2876 (`static int d63bgprimarycount = 0;`) and - 2880-2881 (`if (getenv("GE_D63") && (d63bgprimarycount++ % 500 == 0))`) is - **outside any `#ifdef PORT`** — it currently compiles into the N64 build - path too. Every other `GE_D63` block is `#ifdef PORT` / `#if defined(PORT)` - wrapped. When these are stripped, that one needs the whole 3-line span - removed, not just an inner block. +- The bare non-`#ifdef PORT` `GE_D63` block in `bgRenderRoomPrimary` + (`d63bgprimarycount` static + entry log, was ~`bg.c:2876/2880`) was + removed M-32 (`49ce620a`). Every remaining `GE_D63` block is + `#ifdef PORT` / `#if defined(PORT)` wrapped and inert. - `[Debug]` ini keys (`Debug.FrameDump`, `Debug.InputLog`) mirror `GE_PCDUMP` / `GE_INPUTLOG` as a fallback (env var wins) — M-26, `port/src/config.c`. diff --git a/docs/PCPortResearch.md b/docs/PCPortResearch.md index 9cc52b24..be702f8a 100644 --- a/docs/PCPortResearch.md +++ b/docs/PCPortResearch.md @@ -802,7 +802,7 @@ covers D24–D69; the log continues in §H (D32 procedure, D70–D121). | D59–D68 | intro render: blood-RLE clobber, DMA validate, OSMesgQueue, HEADS/BODIES sentinels, romCopy width, image_entry, Globalimagetable BE→LE | resolved | | D69 · D78–D84 | stage load (`load_bg_file`): bg/stan offline sidecar (`d69_emit.py`) + StandTile/bg_room_data ABI | resolved | | D70–D74 | intro-logo pixels: C-array bswap, UV path, sinf/cosf `DVAL()`, texture-import truncation | resolved | -| D75 · D77 | front-end 3D model transforms · audio | OPEN (parked). **M-32 triage (see §F "D75 ADDENDUM"): (a) D73-scope-gap RULED OUT (gu tree fully endian-clean). Splits in two: Bug 1 = logo/photo transform = the parked D114/D116 fast3d viewport mirror (not game code). Bug 2 = absent animated models = category (b), lead suspect `render_pos`=transient `dynAllocate` arena (D115 MED #5), in-scope fix candidate.** | +| D75 · D77 | front-end 3D model transforms · audio | OPEN (parked). **M-32 triage (see §F "D75 ADDENDUM"): (a) D73-scope-gap RULED OUT (gu tree fully endian-clean). Splits in two: Bug 1 = logo/photo transform = the parked D114/D116 fast3d viewport mirror (not game code). Bug 2 = absent animated models = category (b). M-32b runtime probe (`GE_D75=1`): `render_pos`/`dynAllocate`-arena hypothesis RULED OUT (render_pos valid + fresh each frame), model instances valid (nMtx 21/1), zero fast3d DL warnings — failure is downstream in `drawjointlist`/`dotube` vtx/node-DL resolution or an off-screen `basemtx`. Needs a drawjointlist-level probe.** | | D76 · D164 | disclaimer/legal screen only draws line 1 — **root-caused (M-31)**: `constructor_menu00_legalscreen` text loop bounds `legal_text_end` on `&legalscreen_MRD`, a linker-adjacency assumption that mingw breaks (`legalscreen_MRD` links 0x60 *before* `legalpage_text_array`) → `do{}while(ptrrender_pos` alternates cleanly + between `0x700a8f10` and `0x700a3f10` (delta `0x5000` = the double-buffer + swap). On each frame `render_pos` == the `renderData.mtxlist` base that + `dynAllocate(21<<6)` returned *that same frame* (`gfxpos 0x700a9490` − + `0x540` chr − `0x40` gun = `0x700a8f10` exactly), i.e. it points at the + freshly-`subcalcmatrices`-written matrices, exactly as on N64. It is a + real low-DRAM (`0x700xxxxx`) address; `osVirtualToPhysical(render_pos)` + returns it **unchanged** (no D131 truncation). Nothing overwrites the + arena between the write and the draw within the frame. +- **fast3d logs ZERO DL warnings** during the whole sequence (no + "ending DL" / unknown-opcode / `fast3d_ptr_ok` / bad-matrix-substitution + lines) — so Bug 2 is **not** the D144/D146 corrupt-front-end-sub-DL + family either. The Bond/gun DL is submitted and consumed silently but + emits no visible geometry. +- Mechanism (3), the `(s32)&ANIM_DATA_bond_eye_fire` truncation, was not + the probe's focus but the model has valid matrices regardless, so a + broken anim would at worst freeze a pose, not delete the model. + +**Where that leaves Bug 2:** the failure is **downstream of matrix setup** +— inside `drawjointlist` / `modelRenderNodeDl` / `dotube` for these +title-screen `Model` instances: either the joint **vertex / node-DL +segmented-pointer resolution** produces no tris, or the model is +transformed off-screen / to zero scale by `renderData.basemtx` +(`= matrix` from `manipulateGunbarrelAndLogoMatrices`, which folds +compiled DL pointers through `OS_K0_TO_PHYSICAL` at `title.c:121/123/138` +— a D58/D84-class `(u32)`-wrap candidate, though the backdrop DLs it +feeds *do* render). **Next probe:** inside `drawjointlist`/`dotube` at the +gun-barrel frame, log the resolved `vtx`/`nodeDl` pointers and whether +`modelRenderNodeDl` emits any `gSPVertex`/`gSP1Triangle`, plus the +composed `basemtx * render_pos` for joint 0 (is it in the view frustum?). +Confidence the cause is joint vtx/DL resolution vs off-screen transform: +**low** — needs the drawjointlist-level probe. The `render_pos`-arena +in-scope fix hypothesised above is **no longer the lead** — do not land a +persistent `render_pos` buffer, it would not change anything. + **D76 (OPEN: 2D graphics — disclaimer/legal screen only partially drawn). ROOT-CAUSED (M-31) → D164.** The image-table/D68 hypothesis is **wrong**: the legal screen (`constructor_menu00_legalscreen`, `front.c:1523`) references **zero** `sImageTableEntry`s — it is 12 lines of `langGet()` font text diff --git a/src/game/title.c b/src/game/title.c index ceefabba..a49ed968 100644 --- a/src/game/title.c +++ b/src/game/title.c @@ -26,6 +26,10 @@ #include "title2.h" #include "title3.h" +#ifdef PORT +#include +#endif + extern signed short sins(unsigned short x); @@ -266,6 +270,22 @@ Gfx *sub_GAME_7F007F30(Gfx *gdl, s32 count, Mtxf *matrix) renderData.zbufferenabled = FALSE; renderData.gdl = gdl; renderData.flags = 1; +#ifdef PORT + { + extern u8 *g_GfxMemPos; + static int s_d75n = 0; + if (getenv("GE_D75") && s_d75n < 8) { + osSyncPrintf("D75 gb#%d chrMI=%p obj=%p nMtx=%d rp=%p | gunMI=%p obj=%p nMtx=%d rp=%p | mtxlist=%p gfxpos=%p o2p(rp_chr)=%08x\n", + s_d75n, chrModelInstance, chrModelInstance->obj, + (int)chrModelInstance->obj->numMatrices, chrModelInstance->render_pos, + gunModelInstance, gunModelInstance->obj, + (int)gunModelInstance->obj->numMatrices, gunModelInstance->render_pos, + renderData.mtxlist, (void *)g_GfxMemPos, + (unsigned)osVirtualToPhysical(chrModelInstance->render_pos)); + s_d75n++; + } + } +#endif drawjointlist(&renderData, entry); renderData.flags = 2;