#!/usr/bin/env python3 """Reclassify a NES disassembly's code/data split using a Mesen Code Data Logger file. Why this exists --------------- A static trace cannot see code reached through computed dispatch, and it cannot tell inline string data from an instruction that happens to decode from the same bytes. Both failure modes are common (see TODO.md "Gotchas that will bite you"), and both leave the `.byte`/instruction split wrong even though the rebuild is still byte-identical. Mesen's Code Data Logger is the oracle: it marks every PRG byte the CPU *fetched as an opcode* (bit 0 = Code) and every byte it *read as data* (bit 1 = Data), plus bit 2 JumpTarget and bit 3 SubEntryPoint. This tool rewrites prg.s so its split matches the CDL wherever the CDL has an opinion, and leaves bytes the CDL never observed exactly as they were. Only the *representation* changes (instructions <-> .byte/.word); every ROM byte is preserved, so `make` must still print BYTE-IDENTICAL afterwards -- run it. Capture a CDL from the Mesen MCP: mesen_cdl_file(action='save', memoryType='NesPrgRom', filepath='game.cdl') You can also drive the routines the CDL never reached by setting the PC in the debugger -- but note that a routine that returns through a popped address (a `jsr` + `pla`/`rts` dispatcher, very common) will run away when entered that way, marking garbage as Code. Check the newly-marked ranges before trusting such a run; treat a PC-forced capture as unverified and discard it if the CPU ends up somewhere nonsensical. Inputs and defaults ------------------- --dir DIR project directory (default: cwd) --cdl FILE the CDL file (required) --prg FILE PRG image, default /prg.bin (byte-identity oracle, read only) --src FILE assembly, default /prg.s (or main.s where used) --locals FILE zero-page alias file, default /locals.inc; optional --base 0xC000 CPU address the PRG is mapped at --label-template 'Label_{addr:04X}' name given to a *new* label the tool has to define. Labels already defined in the source keep their exact spelling, whatever it is (`SubCxxxx`, semantic names, ...). --override LO-HI:C|D force a range's classification. Use for structure the CDL is silent about but that is provable another way; record the justification in the project's OVERVIEW.md. Repeatable. --apply write the result; without it the tool only reports What it needs from the source format ------------------------------------ * per-emission audit comments `; CPU:$AAAA PRG:AAAA BB BB ...` (the addressing key) * data emitted as `.byte` / `.word` (`.incbin` blocks are left untouched, since they carry no per-byte provenance) * the data-block header `; ---- data $AAAA-$BBBB (N bytes) ----` -- if absent, block expansion is quietly skipped * optionally the routine header `; Routine: