From 7159fff544373205d9b12e129e50bf14769acfaa Mon Sep 17 00:00:00 2001 From: James Dansereau <106631954+jkdansereau@users.noreply.github.com> Date: Sat, 29 Aug 2026 20:27:20 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20M-17=20session=20=E2=80=94=20D126/D127/?= =?UTF-8?q?D128/D129,=2013->18/21=20levels=20pass?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LEVEL-STATUS: Bunker2/Depot/Surface2 (D126), Surface1 (D127), Control (D128) now PASS. Only C2/C2-GDL remains (Runway intermittent, Facility, Jungle). Cuba loads+renders but bare-boot end-credits path still faults (D76/D129). HANDOFF next task = C2-GDL model relocation (own session). PORT-LEARNINGS: D126 corollary (trailing runtime list ptr in ROM record), D128 (raw hardcoded N64 struct stride bites the same as Gfx/Vtx sizing). --- docs/HANDOFF.md | 70 ++++++++++++++++++++++++++++-------------- docs/LEVEL-STATUS.md | 40 ++++++++++++++---------- docs/PORT-LEARNINGS.md | 9 ++++++ 3 files changed, 79 insertions(+), 40 deletions(-) diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 70afb78d..175ae7c8 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -78,33 +78,57 @@ Full workstream breakdown (WS1–WS6) in `docs/PLAN-linear-level-sweep.md`. `HANDOFF.md`, `AGENTS.md`, `CLAUDE.md`): the D121 + D122 entries in `docs/PCPortResearch.md` §F/§H and this file's edits. Commit or fold in. -## Next task — converter write-audit (C3r / C4 / C5 / C6) +## Done this session (M-17) — 4 commits, 13→18/21 PASS -**D125 is LANDED (M-16b).** `tools_pc/d88_emit.py:374` now writes 8 NUL -bytes; all 21 `Usetup*Z` sidecars regen'd; **Aztec `-level_28` PASSES** -(was C3 crash), Bunker1/Silo unregressed, `d125_check.py` 21/21 MATCH. -M-16 probes reverted, scratch deleted, `d125_check.py` kept. Sweep 12 → -13/21. Full write-up: §H D125 M-16b. +- **D126** (`e851e2ab`) — objective sub-records `criteria_picture` (30), + `criteria_roomentered` (32), `criteria_deposit` (33), + `setup_objective_text` (35) each end in a `T *next` list pointer that + `set_parent_cur_obj_*` / `setup_briefing_text_entry_parent` write while + walking the setup stream. Widens 4→8B and 8-aligns at offset 16 on PC → + struct is 24B/6w (N64 16/20); the old N64-sized emit meant the runtime + 8-byte `->next` store clobbered the *next* propdef record's header → + walk desync → command indices drifted ~100 → `setupDoor` `linkedDoor` + resolution landed on the wrong record. Fixed `d88_propdefs.py` + (`PROPDEF_PC_BYTES[30/32/33/35]=24` + typed handler) + + `loadobjectmodel.c` `sizepropdef` PORT returns 6. **Cleared C3r Bunker2 + + C4 Depot + C6 Surface2** in one change. +- **D127** (`1129f63d`) — `sndPlaySfx` guards a bogus `ALSound*` (the + converted libaudio bank has fewer/rearranged `soundArray` slots than + N64; audio is Phase-3 parked). **Cleared C7 Surface1.** +- **D128** (`749feb9f`) — `sub_GAME_7F0B37EC` special-portal marker used + the hardcoded N64 8-byte `bg_portal_data_entry` stride / `controlbytes1@6`; + on PC the struct is 16B with `controlbytes1@10`, so `|= 2` scribbled + into the middle of a portal's `offset_portal` pointer → `bg.c:5723` + crash on any level with a `specialportalarray` entry. `#ifdef PORT` + uses the struct accessor. **Cleared C5 Control.** +- **D129** (``) — `langGet` bounds-checks the slot id and + resolved bank pointer. Bare `-level_XX` boots that reach the + cast/credits text path (Cuba, `bondviewRenderCredits`, D76 area) + reference banks the menu flow never loaded. Reduces the Cuba bare-boot + end-credits crash; **Cuba itself loads + renders 300+ frames fine** and + the credits work through the real front-end flow. -The last 3 sessions' converter bugs are one family — width/endianness/ -stride errors in `tools_pc/d*_emit.py` (D112 `put_f32`, D120 opcode-0x18, -D125 slice width). Pi audited every `out[` write in `d88_emit.py`; -`d43_emit.py` + the BG sidecar emitters never got that pass, and the open -crashes line up with exactly those files: +## Next task — C2 / C2-GDL model-GDL relocation (Runway + Facility + Jungle) -- **C3r** Bunker2 — DOOR-tail `linkedDoorOffset`/`linkedDoor` layout in - `d88_propdefs.py` vs compiled PC `DoorRecord` (`offsetof`/`sizeof` - cross-check; D123 read-before-write-id pattern). -- **C6** Surface2 — `PitemZ_entries[modelid]` (D122/D123 cont., - `d43_emit.py` / `d88_propdefs.py`). -- **C4** Depot — BG tile/room table (`prop.c:902`). -- **C5** Control — BG portal `offset_portal` unresolved/BE (`bg.c:5723`). +The last 3 crashes are **one class**: the model / prop GDL relocation +(`texLoadFromGdl` / `sub_GAME_7F0762E0`, `objecthandler_2.c`) writes +non-16-aligned `dst` because it mixes N64 8-byte `Gfx` and PC 16-byte +stride in the `replacementgdl` / `name` offset math → garbage `G_SETTIMG` +w1 → `import_texture_i8` fault (Runway, Facility). Jungle renders ~300 +frames then hits a related explosion-DL `G_MTX` (`gfx_sp_matrix`). +**Brief: `docs/BRIEF-C2gdl-model-reloc.md` — its own focused session** +(D80/D82/D83 area). Files: `src/game/objecthandler_2.c`, `src/game/tex.c` +(`texLoadFromGdl`), `src/game/model.c` (`modelNodeReplaceGdl`), +possibly `tools_pc/d43_emit.py` model texture-blob offsets. -Audit `d43_emit.py` + BG sidecar emit paths for slice-width mismatches, -un-byteswapped fields, N64-vs-PC stride math. Then the structural piece: -**C2-GDL** (Runway + Facility) — `docs/BRIEF-C2gdl-model-reloc.md`, its -own focused session. Defer C2m Jungle (matrix), C7 Surface1 (add a narrow -`#ifdef PORT` `sndSetupSound` load guard only — audio is Phase 3). +Everything else: hand `docs/LEVEL-PLAYTEST.md` to the user for the WS6 +completion pass (real input, per-level objective checklist). + +**Regen gotcha:** `d69_emit.py` rewrites `data/pccg-/pccg.bin` from +scratch with only the 52 bg/stan rows — you MUST follow it with +`d88_emit.py --regen` to re-add the 21 `Usetup*Z` rows, or every level +falls back to the raw N64 setup and crashes identically in +`proplvreset2`. Always run the full `d43 && d69 && d88 --regen` chain. Sweep note: `level_sweep.sh` was flaky this session (spurious NO-FRAMES on known-good levels under machine load / the 24 s watchdog + D117 diff --git a/docs/LEVEL-STATUS.md b/docs/LEVEL-STATUS.md index 8df3c26b..6360513d 100644 --- a/docs/LEVEL-STATUS.md +++ b/docs/LEVEL-STATUS.md @@ -18,29 +18,33 @@ Build = `f2beae4b` + `tools_pc/d88_propdefs.py` (D123) + `port/src/gimgfixup.c` | Train | 25 | **PASS** 87.0% | — | — | | Caverns | 39 | **PASS** 91.6% | — | — | | Egypt | 32 | **PASS** 90.9% | — | — | -| Cuba | 54 | **PASS** 92.5% | — | — | +| Cuba | 54 | **PASS** 92.5% (loads+renders 300+ frames; bare-boot end-credits path `bondviewRenderCredits` still faults intermittently — D76/D129, not a real-flow blocker) | — | — | | Dam | 33 | **PASS** 83.3% | — (C1 fixed, D123) | — | | Frigate | 26 | **PASS** 90.4% | — (C1 fixed, D123) | — | | Statue | 22 | **PASS** 80.1% | — (C1 fixed, D123) | — | | Streets | 29 | **PASS** 91.6% | — (C1 fixed, D123; no C2 crash this run — timing) | — | | Cradle | 41 | **PASS** 55.4% (low — partial render, no crash) | — (C1 fixed, D123) | — | -| Runway | 35 | CRASH | `import_texture_i8` gfx_pc.cpp:821 (fault 0x721b8ee8) — same as Facility | **C2** | +| Runway | 35 | CRASH (intermittent, ~3/4 runs; `0x1400d1d83`) | `import_texture_i8` — same as Facility | **C2** | | Facility | 34 | CRASH | `import_texture_i8` gfx_pc.cpp:821 (fault 0x72181ee8) — model-GDL relocation align bug, D124, NOT fixed | **C2** | | Jungle | 37 | CRASH | `gfx_sp_matrix` gfx_pc.cpp:1046 (fault 0x401c68e0) — C2 texture crash fixed (D124), now explosion-DL `G_MTX` (D75/matrix family) | **C2m** | | Aztec | 28 | **PASS** 90.8% | — (C3 fixed, D125) | — | | Bunker2 | 27 | **PASS** 91.5% | — (C3r fixed, D126) | — | | Depot | 30 | **PASS** 79.8% | — (C4 fixed, D126) | — | -| Control | 23 | CRASH | `sub_GAME_7F0BA2D4` bg.c:5723 (`portal_pts->numPoints`, via chrprop.c:62) | **C5** | +| Control | 23 | **PASS** 90.8% | — (C5 fixed, D128) | — | | Surface2 | 43 | **PASS** 70.4% | — (C6 fixed, D126) | — | -| Surface1 | 36 | CRASH | `sndSetupSound` snd.c:653 (fault 0x56220001…, ascii-ish) | **C7** | +| Surface1 | 36 | **PASS** 77.5% | — (C7 guarded, D127) | — | -**16 / 21 PASS.** D123 cleared C1 on all 6. D124 cleared Jungle's texture +**18 / 21 PASS.** D123 cleared C1 on all 6. D124 cleared Jungle's texture crash (now hits an explosion-DL matrix crash). D125 cleared C3-Aztec. **D126** (objective sub-record `->next` pointer widens 4→8B → 8-byte store clobbers the next propdef record's header → walk desync → wrong command indices) cleared **C3r Bunker2 + C4 Depot + C6 Surface2** in one fix -(`d88_propdefs.py` types 30/32/33/35 → 24B/6w). 5 crashes remain in 4 -classes: C2 Runway+Facility, C2m Jungle, C5 Control, C7 Surface1. +(`d88_propdefs.py` types 30/32/33/35 → 24B/6w). **D127** guarded a bogus +ALSound* in the parked audio path → **C7 Surface1**. **D128** fixed a +hardcoded-N64-stride portal-flag write → **C5 Control**. **3 crashes +remain, all one class:** C2 Runway + Facility + C2m Jungle — the model / +prop GDL relocation misaligns on the 8→16B `Gfx` stride +(`docs/BRIEF-C2gdl-model-reloc.md`). Notes: Streets passed this run but the C1 agent saw a `gfx_sp_matrix` crash — likely the same explosion-DL `G_MTX` (C2m) as Jungle, timing- @@ -163,16 +167,18 @@ id from a propDef record). Fault addr 0x0. Files: `tools_pc/d88_propdefs.py`, crash on load, not silence. May be dodge-able with a narrow guard until audio lands. Files: `src/snd.c`, `port/src/` audio stubs. -## Next (5 crashes, 4 classes — priority order) -1. **C2** Runway + Facility — model-GDL relocation align bug in - `objecthandler_2.c`/`texLoadFromGdl` (D80/D82/D83 area). Shared infra, - 2 levels + likely helps Jungle. Biggest win. -2. **C2m** Jungle — explosion-DL `G_MTX` (`gfx_sp_matrix`), D75/matrix - family. -3. **C5** Control — BG portal `g_BgPortals[].offset_portal` unresolved/BE, - `bg.c:5723` via `chrprop.c:62`. BG sidecar (`d69_emit.py`). -4. **C7** Surface1 — `sndSetupSound` `snd.c:653`; parked-audio, may just - need a narrow load guard until Phase 3. +## Next (3 crashes, 1 class) +1. **C2 / C2-GDL** Runway + Facility — model/prop GDL relocation writes + non-16-aligned `dst` (N64 8B `Gfx` vs PC 16B stride) in the + `texLoadFromGdl` / `sub_GAME_7F0762E0` path → garbage `G_SETTIMG` w1 → + `import_texture_i8` fault. `docs/BRIEF-C2gdl-model-reloc.md` — its own + focused session (D80/D82/D83 area). +2. **C2m** Jungle — renders ~300 frames then an explosion-DL `G_MTX` + (`gfx_sp_matrix`), D75/matrix family. May be downstream of the same + GDL-reloc infra. + +Everything else loads + renders + survives the no-input window. +Hand `docs/LEVEL-PLAYTEST.md` to the user for the WS6 completion pass. Re-run `tools_pc/level_sweep.sh` after each class fix; keep `-level_09`/`-level_20` green (`tools_pc/framediff.py`). diff --git a/docs/PORT-LEARNINGS.md b/docs/PORT-LEARNINGS.md index 68f93a29..ae77c058 100644 --- a/docs/PORT-LEARNINGS.md +++ b/docs/PORT-LEARNINGS.md @@ -48,6 +48,15 @@ expressed in N64 `Gfx`/`Vtx` units is **half-size** on PC. - Instances: D50.6 (texCopyGdls copied only w0 of each 16-byte slot), D58 (DL reserve 0x100→0x200), D85 (`bgWidenRoomGdl` 8→16 + bswap), D95 (2× master-DL buffer + raised mempool ceiling). +- **Also bites RAW hardcoded struct-stride writes, not just Gfx/Vtx.** + D128: `sub_GAME_7F0B37EC` did `((u8*)g_BgPortals)[(portal<<3)+6] |= 2` + — the N64 `bg_portal_data_entry` is 8B (`ptr@0, cr1@4..cb2@7`); on PC + the widened `offset_portal` ptr makes it 16B (`cr1@8..cb2@11`), so the + write landed in the middle of another portal's pointer. Fix = use the + struct accessor under `#ifdef PORT` (every other site already does: + `g_BgPortals[portal].controlbytes1 |= PORTALFLAG_SPECIAL`). Grep for + `<< 3` / `* 8` / `+ 6` style raw offsets into any struct that gained a + pointer field. ## C. Big-endian rodata / ROM data read on little-endian PC