Distilled from Chris Judnich's 'Decompiling a Nintendo 64 Game in 84 Days' (saved under docs/reference/): explicit per-task budgets exposed to the agent, a shared append-only learnings file, file-partitioned parallelism, cheap pre-flight passes, and a standard investigation-subagent brief template. PORT-LEARNINGS.md is a one-screen index of the recurring N64->PC bug classes into PCPortResearch.md §F; AGENTS.md points to both.
6.6 KiB
Agent / subagent workflow for this port
Guidance distilled from Chris Lewis's "Decompiling a Nintendo 64 Game
in 84 Days" (docs/reference/, Snowboard Kids, 2026) — an AI-assisted
N64 decomp run 7× faster than its predecessor — adapted to this project,
which is a PC port on top of a decomp, not a byte-match decomp. The
mechanics differ (we have no permuter / m2c loop; our inner loop is
root-cause → narrow #ifdef PORT fix → visual verify) but the
project-structure lessons transfer directly.
1. Every subagent task gets an explicit budget, stated in the brief
Their key finding: an open-ended tool (the permuter) that "runs until 100% match or manually stopped" wrecks throughput; giving the agent a deadline it can see let it trade tool-time against other problem-solving and judge when to give up on a hard function.
Our open-ended tools are the same shape: rebuild-and-run-the-game cycles, gdb, env-gated probe iteration, staring at PPM dumps. So every subagent brief must state:
- a wall/iteration budget — e.g. "≤ N build→run→inspect cycles" or "~M minutes of investigation"; and
- the fallback on expiry: stop, revert probes, write up what you have with a confidence rating — a good write-up of a half-solved bug is a deliverable, not a failure.
Escalate the budget as the project hardens: early bugs are cheap (one-line truncations, off-by-ones), so cap tight; once those are gone the survivors are structural (matrix handedness, format specs) and deserve more room. Revisit the default each session.
2. A shared, append-only learnings file that briefs point every agent at
They had agents record generalisable IDO quirks in
DECOMPILATION_LEARNINGS.md; later agents read it and got better. "Agents
helped document IDO, and the documentation made subsequent agents better."
Our equivalent already exists but is diffuse: docs/PCPortResearch.md §F
is 200 KB of narrative. The recurring PC-port quirk classes should be
distilled into a short cheat-sheet every subagent brief links and every
subagent is told to append to:
- pointer-width struct growth (32→64) in ROM-serialized / pun-allocated structs — the dominant bug class (D53.2, D56, D79, D98–D102)
- 16-byte PC
Gfx/Vtxvs 8-byte N64 — reservation & copy sizing (D50.6, D58, D85, D95) - big-endian rodata read on LE:
f32word-pairs (D73, D112), header offset tables (D68, D87), packed bitfields (D78, D83) - N64 hardware idioms fast3d doesn't emulate (fill-rect Z clear → D105; LOD/detail tiles → D107; K0 segment address folds → D58, D84)
- offline sidecar converter preferred over runtime fixup for whole formats (D43, D69, D88)
This is docs/PORT-LEARNINGS.md — one screen, an index into §F, not a
replacement. Every investigation-subagent brief links it; every subagent
is told to append any new generalisable quirk before reporting.
3. Parallel work: partition by file, consolidate often
They ran 4 git worktrees sharded by a hash of the candidate list, and found the cost was synchronisation — a match in one worktree stayed invisible to the others until merged, and merging all four took >1 h. Their fix: make the similarity search read all worktrees so a new reference propagates immediately, and merge to main periodically anyway.
For us (parallel investigation subagents, not worktrees yet):
- Partition tracks by the files they will touch so patches don't
collide. This session: Track 1 =
bg.c, Track 2 =chr.c/model*.c, Track 3 =gunfire.c+ a new audit doc — disjoint, merged clean. A brief that can't be file-partitioned shouldn't be parallelised. - Subagents must revert their own probes before reporting (leave only committed, env-gated, capped probes) and must not touch another track's uncommitted edits — call them out in the report instead.
- The integrator (main session) consolidates to
masterper-track with the §F write-up, then the next round of agents starts from a clean tree. Don't let investigation branches drift. - If we move to real worktrees:
data/must be copied, never junctioned (see thedata-dir-junction-hazardmemory —git worktree remove --forcefollows the junction and deletes the real baserom + sidecars).
4. Cheap automated pass before spending agent tokens
They scripted m2c across every unmatched function first (0.93 % hit
rate, but near-free) and told agents to exhaust known SDK
versions / compiler flags / #if paths before writing original code.
Our pre-flight before dispatching an investigation agent:
./build-pc.shgreen +/linkcheckclean- run the existing env-gated probes for the area (
GE_D96,GE_D104,GE_D69*, …) and attach the output to the brief GE_PCDUMP+tools_pc/pixcount.pybaseline capture- grep
docs/PCPortResearch.md§F for a prior instance of the bug class - check
PD_PORT_CHECKOUTfor the PD analogue (already a non-negotiable) — the brief should name the file to look at
Give the agent the results, not just the task. "Give the agent the findings, not just the problem" is the through-line of the whole post.
5. What does not transfer
- Model choice. Their (unscientific) take was Codex > Claude for reproducing IDO codegen. Our task is behavioural correctness, not compiler-output matching — not comparable; ignore.
- The permuter / match-percentage loop. We don't bit-match. Our
"done" bar is: no fault + visually correct vs. N64 footage
(
docs/reference/n64-footage-*), measured withpixcount.py. - "Understanding the function is the easy part." True for decomp, inverted here — our hard part is often what N64 hardware/ABI behaviour the C is silently relying on.
Standard investigation-subagent brief template
Repo: REPO_ROOT (git, master, Windows; PowerShell + Bash).
READ FIRST: docs/HANDOFF.md (top), docs/PORT-LEARNINGS.md,
docs/PCPortResearch.md §F <specific Dxx entries>, AGENTS.md non-negotiables.
TASK: <one bug, one subsystem>.
FILES YOU MAY TOUCH: <disjoint from other running agents>.
KNOWN-GOOD / RULED OUT: <list — do not re-investigate>.
PRE-FLIGHT ATTACHED: <probe output, pixcount baseline, pd_port pointer>.
BUDGET: <N build→run cycles / ~M min>. On expiry: revert probes, write up with confidence.
CONSTRAINTS: no game-logic changes; ABI/layout/format only, #ifdef PORT, documented in §F.
revert your own temp probes; do not touch other agents' uncommitted edits.
REPORT: (a) root cause + file:line evidence (b) fix diff or why-not
(c) probes left in tree (d) confidence. Append any generalisable
quirk to docs/PORT-LEARNINGS.md.