mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
D86 (resolved): modelInitRwData crashed on a bad ModelNode pointer during room-triggered gameplay init. Root cause: initplayergaitobject.c did `player_gait_object_header.RootNode = (int)&player_gait_hdr;` -- a same-width pointer<->int round trip that's a no-op on N64 but truncates a real 64-bit pointer on PC, dropping the executable's load-base high bits. Fixed under #ifdef PORT by assigning the real pointer directly. Only exercised once real gameplay starts (past the intro), which is why it was never hit before D69 let the game reach stage load. D87 (resolved): once D86 stopped blocking progress, an idle (no-input) run reaches the front end's genuine attract-mode demo playback and crashes in ramrom_replay_handler. Root cause: ramromfilestructure is a real ROM-compiled asset (big-endian) loaded via romCopyAligned's raw byte copy (D66) with no byteswap, so every multi-byte field reads scrambled and drives wild pointer arithmetic in the block-buffer consumers. Fixed with a #ifdef PORT ramromFixupEndian() called once after the load (D54 cseq-fixup pattern). Both root-caused with new env-gated TEMP probes (GE_D86, GE_D87), left in place per the existing convention. D88 (per-level "Usetup*Z" stage-setup file: zero PC porting done, struct-width + endian bugs stacked) is the new next blocker, root-caused but intentionally not patched inline -- it's D69-scale format-conversion work, logged as an open finding instead. Also documents a fast, deterministic BUNKER1 repro (-level_09 command-line arg, bypasses the front end/attract-mode entirely) and a correction to the gdb guidance: attach mode (vs. launch-only) works well for watching a global's write on an already-running process. Docs: docs/PCPortResearch.md §F (D86/D87 resolved, D88 new), docs/HANDOFF.md (session K), AGENTS.md summary line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C3xib6jjMV8o2iE4JfixAo
14 KiB
14 KiB
AGENTS.md — GoldenEye 007 PC Port
What this is
n64decomp/007: WIP decompilation of GoldenEye 007 (N64), byte-matches US/EU/JP ROMs.- Active work: PC port modelled on the Perfect Dark PC port (same Rare "Indy" engine family).
- Read
docs/PCPortResearch.mdfirst — architecture, GE-specific RSP deltas, phased plan, and review findings (A1–D33 in §11; current handoff + plan in §H). - Starting a fresh session? Read
docs/HANDOFF.md— the paste-ready brief with the immediate task, standing procedure, and environment gotchas.
Non-negotiables
- N64 build untouched.
Makefile,tools/,rsp/,ld/belong to the N64 build. Never modify them for the PC port. - Game logic is unmodified. The decomp's control flow and behavior are ground truth for 1:1 fidelity — never change them. All N64 hardware dependencies are satisfied by the
port/layer; if a game file seems to need a behavioral change, stop — the fix belongs inport/. Narrow exception (ABI/layout only): the 32→64-bit transition forces a small class of mechanical, semantics-preserving edits that cannot be isolated inport/— chiefly pointer-width reconciliation in ROM-serialized structs (a struct with a 32-bit-pointer field misaligns when read as 64-bit). These follow the PD ground-truth pattern (store the embedded address asu32, cast to a real pointer at the use site), change no logic or behavior, and are each documented indocs/PCPortResearch.md§F/D3x. No other game-code edits are permitted. - Region macros mirror the Makefile.
CMakeLists.txtREGION_DEFSmust match the N64 Makefile's per-region macro set exactly (finding A1). Divergence = silent branch divergence + link failures. src/libultrare/Makefile.libultrareis ground truth for original-vs-Rare libultra files (finding B3). The PC build compiles:libultra/audio,libultrare/audio(drvrNew/env/reverb),libultra/gu, andlibultrare/io/vitbl.conly. All otherio/+os/files are excluded and shimmed inport/src/libultra.c.rsp/graphics/gmain.sis the RSP ground truth — the authoritative reference for which GBI commands GE emits (modified fast3d, 1545 lines). We do not run it on PC;port/fast3d/replaces it. Use it to validate the software RSP's command decoding and the custom CC/RM modes.
Critical files
| File | Role |
|---|---|
docs/PCPortResearch.md |
Research + plan + findings (A1–C2). Read first. |
CMakeLists.txt |
PC build (parallel to the N64 Makefile). Source list + REGION_DEFS live here. |
port/src/ |
Shims: libultra.c (OS API), gesched.c (scheduler), n64stubs.c (boot/TLB/FPU/rmon), random.c (PRNG ported verbatim from random.s), ucode.c (microcode segment markers), main.c, video.c, … |
port/fast3d/ |
Software RSP (adapted from the PD port). The main Phase 2 work. |
rsp/graphics/gmain.s |
GE's RSP ucode — ground truth for GBI/CC/RM. |
PD_PORT_CHECKOUT |
Perfect Dark PC port checkout — standing reference for this project: consult it whenever a remaining work item has a PD analogue (same Rare engine family). Port-layer ground truth (port/fast3d/, crash/system/video), plus copy candidates: port/src/preprocess/ (N64→PC asset conversion at load; filemodel.c is the D43 near-analogue, same vma 0x5000000) and mixer.c/input.c/fs.c (Phase 3/4 — our stubs were scaffolded to be replaced by these). Caveats: port-layer files only; same family ≠ identical format — validate per field. Full audit: docs/PCPortResearch.md §2.4. |
Build
./build-pc.sh ntsc-final # or pal-final / jpn-final
Needs CMake + SDL2 + zlib + OpenGL (MSYS2 packages: see build-pc.sh header). ROM goes in ./data/ (not distributed).
Verification ritual (after any build-affecting change)
- Undefined symbols. Every symbol referenced by the compiled set (see
CMakeLists.txt:SRC_GAME,SRC_ENGINE,SRC_LIBAUDIO,SRC_LIBULTRARE_AUDIO,SRC_LIBULTRARE_DATA,SRC_GU,SRC_PORT*) must be defined exactly once in the compiled set or inport/. Symbols that live in EXCLUDED files (libultra/io/*,libultrare/io/*exceptvitbl.c,libultra/os/*,libultrare/os/*,sched.c,rmon.c,vi.c,src/*.s) must be provided byport/src/libultra.c,gesched.c,n64stubs.c,random.c, orucode.c. - Duplicates. No symbol defined twice across the compiled set (watch
sp_*stacks,rmon*,os*shims, segment markers). - Syntax. Every touched file must parse; once the toolchain is installed,
./build-pc.shis the final word.
Run /linkcheck for this sweep. Record new findings in docs/PCPortResearch.md §11 style (next label after the last used).
Phase status
- Phase 0 (scaffolding): done, committed.
- Compile+link milestone: all ~235 TUs compile and
ge007.x86_64.exelinks clean (ninja ge007 -k 0, 236/236). Findings D7–D17 indocs/PCPortResearch.md§11; asset stubs inport/src/assetstubs.c, fast3d no-ops inport/src/gfxstub.c(delete when real fast3d lands). - Phase 1 (boot to window): done — ROM loads/validates/maps at cart base 0x10000000 (
romdata.c), SDL2 window + GL clear loop (video.c), absolute asset symbols fromscripts/gen_romassets.py→port/src/romassets_<r>.s(findings D18–D23). - Phase 1.5 (boot to first frame): DONE — boot chain complete AND real frames render (
[NOTE] frame N rendered in … us). D34–D42 closed the blockers on top of D31–D33: ANIM_DATA lvalues, music seq-table ABI+endianness, music-heap sizing, libaudio bank-tree re-layout, implicit-declaration prototype shim (D38), Globalimagetable rebasing + true segment size (D39), ModelHitEntry pool sizing (D40), cross-thread GL context release (D41), rsp task-settings toggle (D42). ROM dump verified against the No-Intro good dump (byte-identical, header CRCs re-checked —tools_pc/romverify.c). - Phase 2 (rendering): IN PROGRESS — fast3d integrated + real frames render. Plan B EXECUTED (D50, committed): all 512 NTSC model files converted offline by
tools_pc/d43_emit.py→data/pcmodels-ntsc-final/pcmodels.bin+ manifest.csv (single concatenated RZ image; regenerate per region with the script — sidecars are gitignored), served through the existing load path via a port-layer table patch (port/src/pcmodels.c, romdata cart-extension, one-shotpcmodelsPatchTable()+ poolRemaining reset hook inload_object_fill_header); runtime C fixups for language-bank BE offset tables + font re-layout (D50.3/D50.4); legal-screen UB seed (D50.5); D50.6 fixed the first model-render crash —texCopyGdlscopied only w0 of each 16-byte Gfx slot on PC (the union's trailinglong longis 8 bytes), leaving stale mempool w1s in the compacted GDLs; byte-proven against PlegalpageZ, fixed with a full-slot copy under #ifdef PORT. Model GDLs now execute to completion (PlegalpageZ sub-DLs). D51 RESOLVED (fontpixeldatafixup wrote the pointer at the wrong offsets — frame-5import_texture_i8crash gone; GE opcode space decoded along the way, G_TEXRECT=0xE4/0xE5 non-F3DEX numbering), D52 RESOLVED (osGetCountnow advances at the N64 RSP counter rate ≈ 46.5525 ticks/µs — fixed the non-deterministic post-frame-2 hang), D53 RESOLVED (model RW-data pool addressing: D53.1Model.datasword-stride →u32 *under PORT + casts; D53.2 ModelSlot/AnimModelSlot re-laid on top of the PC struct Model — in-use@0x10 / pool@0x20, slot size = sizeof(Model) = 0xE8 — plus PORT-guarded heap-fallback bumps in model.c), D54 RESOLVED (cseq ALCMidiHdr BE header: port-layerromdataFixupCseqbswap32 of the first 17 u32s, called from music.c after each decompress), D54b RESOLVED (synth param slots sized for ALStartParamAlt = 0x28 in synthesizer.c alSynInit under PORT), D55 RESOLVED (RLE folder-menu background BE w/h header: bswap32 of the first word at(u32 *)&unknown2at cart-map time in romdataInit, guarded). Build GREEN; game boots, plays intro music, renders through logo/gun-barrel, instantiates Brosnan, and executes the gun-barrel hole DL clean to ENDDL. D56 RESOLVED (watch Model/RW-pool raw offsets: field-name Model access + static 0xC8-byte pool under PORT in bondview2.c), D57 RESOLVED (pointer-grown rwdata records overflowed N64-sized spare pools — Brosnan PC numRecords 153 > 140: capacities grown in initunk_005520.c + dynamic slot+pool fallback in model.c), D58 RESOLVED (gun-barrel DL: vertex-pointer K0 idiom rebuilt viaOS_K0_TO_PHYSICAL(…) | 0x80000000in title.c + DL reserve 0x100→0x200 becausesizeof(Gfx)is 16 on PC). D59–D68 RESOLVED (committed): the "GL DLL" crash was D64's unbounded blood-RLE write (sentinel section-adjacency lost on PC) clobbering the gun-barrel sub-DL; then D60–D62 (DMA target validation, OSMesgQueue layout), D65/D65b (HEADS/BODIES enum signed sentinels under PORT), D66 (romCopyAligned + ramrom replay 64-bit pointer width), D67 (struct image_entry N64 layout), D68 (Globalimagetable BE→LE fixup —port/src/gimgfixup.cbswaps IMAGESEG Gfx w1 words + sImageTableEntry.index after texReset's romCopy; compiled globalDL shadows synced for explosion.c). The game now renders the entire intro (logo → gun barrel w/ Brosnan → cast; ~frame 2100, ≈2 min wall-clock at the current ~20 fps clean-run rate). D69 RESOLVED (committed):load_bg_fileno longer faults on stage load. BG-file headers/records are N64 big-endian segment-0x0F offsets with internal self-relative offsets; fixed via offline sidecar conversion (tools_pc/d69_emit.py→data/pccg-<region>/pccg.bin+ manifest, same Plan-B pattern as D43/pcmodels, port-layer wiring inport/src/pccg.c) plus four ABI layout fixes surfaced along the way: D78 (StandTileid/room bitfield packing), D79 (bg_room_datapointer-width), D83 (StandTileHeaderMid/Tailbitfield packing — same class as D78, caused an infinite loop instanBuildRoomDatauntil fixed), D84 (hand-inlinedBG_SEG_TO_PTR-style folds in room-DL loaders needed the same(u32)-cast 32-bit wrap the macro already has). D85 OPEN, D86/D87 RESOLVED, D88 OPEN (current blocker) — found during/after D69 verification: D85 — room primary/secondary DL binaries decompress correctly buttexLoadFromGdl(the already-working model-GDL runtime converter) produces garbage from their content, not yet root-caused; safety-netted (bounds-checked inbgBuildRoomVtxBoundsso it can't segfault, but geometry is wrong/empty). D86 (RESOLVED) —modelInitRwDatacrash was a single(int)-truncated pointer ininitplayergaitobject.c's embedded player gait-model init; fixed under#ifdef PORT. D87 (RESOLVED) — the front end's genuine attract-mode demo playback crashed on an unswapped big-endianramromfilestructure; fixed with a#ifdef PORTbyteswap fixup inramromreplay.c(D54-cseq pattern). D88 (OPEN, current blocker) — the per-levelUsetup*Z"stage setup" file (prop.c/struct stagesetup) has zero PC porting work: it's raw ROM bytes read directly through a pointer-widened, still-big-endian C struct (D79-class width bug + D87-class endian bug, stacked); crashes inproplvreset2(prop.c:1306), reproducible in seconds via-level_09(bypasses the front end, no attract-mode wait). Needs D69-scale format-conversion work (byte-accurate spec + offline converter or careful runtime fixup), not a quick inline patch — logged as an open finding per AGENTS.md's "stop and write up" guidance. Seedocs/HANDOFF.mdanddocs/PCPortResearch.md§F/D86-D88 for full detail and next steps. D70–D74 (intro-logo pixels, RESOLVED): D70 env-gated PPM frame capture (GE_PCDUMP→./ppm/, gitignored — kept as permanent dev tooling); D71 C-array texture sources (the four rarewarelogo.c RGBA16 images) byte-swapped on LE PC → port-layer per-source bswap inimport_texture; D72 the UV path (GE always uses authoredtc[]UVs;lookat_enableddefaults false); D73 = root cause of old D72.3 — sinf/cosfdudouble constants are big-endian word pairs, garbage on LE PC → guMtxF2L emitted −32768 for every sin/cos entry → logo triangles projected off-screen; fixed with the PORT-onlyDVAL()macro insrc/libultra/gu/guint.h(sinf.c/cosf.c.dreads replaced; N64 build untouched); D74 texture import fallback no longer truncates valid gDPLoadBlock data (was dropping letter mip chains + reducing D_02005FF0 to 32×3),TextureCacheKeygainedsize_bytes, and the VBO path wraps UVs by tile size for WRAP sub-tiles (N64 semantics). The Rareware logo now renders its four gold letters on the dark-blue plate (PPM-verified ~frame 555; final pixel-perfect check vs N64 footage optional). D69 is resolved; D88 is the current blocker to a rendered stage frame, with D85 next after it (see above). Committed through D87. Recurring sub-task: ABI/layout fixes per the D32 procedure (§H) as more asset types are first touched (PD'spreprocess/module already solves most of them; prefer the offline pattern for format work — D48; full-struct Gfx copies on PC — D50.6; audit struct type-puns after pointer-width changes — D53.2; raw byte offsets into pointer-containing structs shift on PC — D56; N64-sized reservations must be re-checked against 16-byte Gfx/Vtx widths — D58). Open this session (tracked in §F as D75–D77, lower priority than D69): D75 3D rendering still wrong (Nintendo logo misplacement + intro player models absent); D76 2D disclaimer screen only partially drawn; D77 no audible music on PC. Prioritization: rendering over audio unless a shared root cause is found (Q1). - Phase 3 (audio + input): libaudio → SDL — largely copy-and-adapt from PD (
mixer.c722 lines vs our 31-line stub;input.cSDL_GameController backend; §2.4); decide the ASP strategy (C2:aspMain*dummies inucode.c). - Phase 4 (saves + polish): file-backed EEPROM — build on PD's
fs.c(file-backed save dir); PFS/motor already no-op stubs.