export const meta = { name: 'modemwars-finish', description: 'Phase 3: annotate the one code chunk that failed, comment the data files, correct stale claims, verify', phases: [ { title: 'Code', detail: 'redo the fast loader chunk whose agent lost its connection' }, { title: 'Data', detail: 'one agent per pure-data file' }, { title: 'Fix', detail: 'correct claims the data survey disproved' }, { title: 'Verify', detail: 'rebuild, reassemble and compare every unit' }, ], } const RESULT = { type: 'object', properties: { path: { type: 'string' }, linesCommented: { type: 'integer' }, routines: { type: 'integer' }, problems: { type: 'array', items: { type: 'string' } }, }, required: ['path', 'linesCommented', 'routines', 'problems'], } const common = ` You are annotating a reverse-engineered disassembly of "Modem Wars" (Commodore 64, Electronic Arts / Ozark Softscape, Dan Bunten, 1988): a two-player real-time strategy game played over a modem link, with a solo trainer, "game film" record/playback, a console with STATS / REPAIR / MISC panels and a 40x40 battlefield. Work in /home/scott/claude/modemwars. Read first: docs/overview.md and the section of docs/knowledgeBase.md for your unit. disassembly/XREF.txt lists callers/readers/writers per source file (references are grouped under the file they come from - only the ones under your own file are meaningful). survey/*.json holds the raw survey findings, including survey/data_units.json and survey/data_*.json which describe the data blocks in detail. Annotation JSON format (tools/build.py merges every annotations/*.json; everything is unit-scoped): { "chunk": "", "unit": "", "unitLabels": { "": { "XXXX": "camelCaseName" } }, "notes": { "XXXX": { "unit": "", "routine": ["name - what it does", "In: ...", "Out: ...", "Called from: ..."], "block": ["comment block printed before this address"], "line": "end-of-line comment for the instruction or data at this address" } }, "dataTypes": { "XXXX": ["text"|"addr"|"word"|"byte"|"grid"|"bitmap"|"sprite", length, optionalRowWidth] } } "grid" takes a row width and prints that many bytes per line; "bitmap" prints one byte per line as 8 pixels of bit art; "sprite" prints 21 rows of 3 bytes as 24-pixel bit art. Addresses: uppercase hex, 4 digits, no "$". Plain ASCII only. HARD RULES * Write ONLY your own file annotations/30_.json. Never edit disassembly/*.s, tools/*, docs/* or another agent's annotation file. * Do NOT run tools/build.py or disassembly/verify.sh - other agents run in parallel and the build rewrites the whole disassembly directory. A verification agent runs at the end. * dataTypes are keyed by address across the whole program, so only type an address that is data in EVERY file that covers it. $6F00-$87FF and $E000-$EFFF each exist in two different files, and $0200-$04FF in two more: check the sibling file before typing an address in those ranges. * Never invent facts. Mark uncertainty in the comment itself ("probably", "?"). ` phase('Code') const codeChunk = await agent(`${common} YOUR CHUNK: unit "boot/fastLoaderC000", file disassembly/boot/fastLoaderC000.s, addresses $C000-$C3FE. This is the Electronic Arts fast loader: it installs code in the 1541, then pulls the whole game off the disk through a two-bit serial protocol on CIA2 port A while the title picture is displayed. The drive side of the same protocol is disassembly/drive/driveFastLoader.s - read it, the two halves explain each other. Read the whole file first. Its routine headers already exist; the per-instruction comments do not. TASK: write annotations/30_boot_fastLoaderC000_C000.json. 1. A "line" comment on EVERY instruction, explaining intent rather than the mnemonic. Name what each branch tests. Explain every magic number: CIA2 port A bit meanings, the handshake sequence, the raster test that avoids bad lines, VIC register values for the title picture, KERNAL call arguments, DOS command strings. 2. Improve the routine headers where you understand a routine better, and add "Called from:" lines. 3. "block" comments before each logical section. 4. Point out the self-modifying code: which instruction is patched, by whom, with what, and why (the loader rebuilds the stack so its final RTS lands at $0461 instead of returning to its caller). Validate with python3 -c "import json;json.load(open('annotations/30_boot_fastLoaderC000_C000.json'))". Return path, number of line comments, number of routine headers, problems.`, { label: 'annotate:fastLoaderC000', phase: 'Code', schema: RESULT }) phase('Data') const dataChunks = args.dataChunks const dataResults = await pipeline(dataChunks, (c) => agent(`${common} YOUR FILE: unit "${c.unit}", disassembly/${c.file}, addresses $${c.startAddr}-$${c.endAddr}. This file is pure data - there is no code in it. survey/data_units.json and the other survey/data_*.json files already describe much of it; use them, verify what they claim against the bytes, and go further. TASK: write annotations/30_${c.id}.json so that a reader can understand every byte of this file. 1. Give every distinct structure a label and a "block" comment saying exactly what it is: how many entries, how many bytes per entry, what the index means, which code reads it (from XREF.txt, filtered to the right file), and what the values mean. 2. Choose the right dataTypes so the listing renders the structure readably: "grid" with the natural row width for tables (e.g. one screen row, one record, one template row), "bitmap"/"sprite" for graphics so the bit art lines up, "text" for strings, "addr" for pointer tables. Split a block into several dataTypes entries when it contains several structures. 3. Where a table is one half of a split low-byte/high-byte pointer pair, say so and say where the other half is; do NOT type it as "addr". 4. Add "line" comments to individual rows where a row means something specific (a particular glyph, a particular unit, a particular message id). Do not pad every row with a meaningless comment. 5. Say plainly which parts are unused, leftover or unreferenced, and what the evidence is. Validate the JSON parses. Return path, number of comments written (linesCommented), number of structures described (routines), problems.`, { label: `data:${c.id}`, phase: 'Data', schema: RESULT })) phase('Fix') const fixed = await agent(`${common} TASK: the data survey (survey/data_units.json, survey/data_high_FBB8.json) disproved several statements that the earlier survey pass wrote into the listing. Correct them by writing annotations/30_corrections.json (same format, notes only - it loads after the survey notes and overrides them). 1. game/highMemoryFBB8: the listing says $FD70 and $FE24 have "no static reference anywhere in the disassembly" and that $FF90 is "most likely unused leftover memory". All of that is wrong: $FD70 and $FE24 are run-length-encoded sprite streams, unpacked into $0200 by the RLE unpacker at $67CB, which the comcen screens overlay calls from $7596 and $7FF0. Check this yourself in the listings, then write correct block comments for $FD70, $FE24 and $FF90 (say what $FF90 really holds if you can determine it; if you cannot, say that plainly instead of guessing). 2. Search the other listings for any remaining claim that a block is "unreferenced" or "unused" which the data survey contradicts, and correct those too. 3. Do not touch anything you have not verified. Return path, number of corrections (linesCommented), 0 routines, problems.`, { label: 'corrections', phase: 'Fix', schema: RESULT }) phase('Verify') const verified = await agent(`Work in /home/scott/claude/modemwars. You are the only agent running now, so you may run the build. 1. python3 -c "import json,glob;[json.load(open(f)) for f in glob.glob('annotations/*.json')]" - fix invalid JSON. 2. grep -lP '[^\\x00-\\x7F]' annotations/*.json docs/*.md 2>/dev/null - replace any non-ASCII character. 3. python3 tools/build.py 2>&1 | grep -iE "warning|error|traceback" 4. ./disassembly/verify.sh | grep -v "^OK" - all 24 units must reassemble byte-exact. If a unit fails to ASSEMBLE, find the first ca65 error and fix the annotation entry that caused it. If a unit assembles but MISCOMPARES, the cause is a dataTypes entry that changes how many bytes are emitted (for example a typed block that overlaps a label, or a "text"/"sprite" run whose length is wrong): find it with cmp -l disassembly/build/.bin disassembly/build/.orig.bin, locate that address in the listing and fix the annotation. Never edit disassembly/*.s or tools/*. Duplicate-label warnings from build.py are auto-resolved but indicate two annotations claimed the same name: fix the annotation that is wrong. Repeat until verify prints 24 OK and build.py prints no warnings. Finally report the per-file instruction comment coverage using: python3 - <<'PY' import re, glob tot=com=0 for f in sorted(glob.glob("disassembly/*/*.s")): for l in open(f): m=re.match(r"^\\s+[a-z]{3}\\s.*?;\\s[0-9A-F]{4}(.*)$", l) if m: tot+=1 if m.group(1).strip(): com+=1 print(tot, com, round(100*com/tot,1)) PY Return path="disassembly", linesCommented=, routines=, problems=[everything you had to fix].`, { label: 'verify', phase: 'Verify', schema: RESULT }) return { codeChunk, dataResults: dataResults.filter(Boolean), fixed, verified }