Super Nintendo decomp guide
Recompile the 65816 code with snesrecomp to play fast. A full C rewrite needs a disassembly first.
What this system is like
Super Nintendo games are small. The reviewed ones are 1 to 4 MB. Almost all were written by hand in the 65816 chip's assembly language. So there is no original C code to find. There is also no old compiler to match against.
For Path A, one tool leads on this system: snesrecomp. It turns the game's machine code into C. A shared runtime stands in for the picture, sound and timing chips. Code it cannot prove yet runs in a built-in interpreter. An interpreter runs machine code one step at a time, slowly but safely. So a game can boot on day one and get better step by step.
For Path B, you rewrite each routine in C with Claude. A routine is one small piece of the program. A checker runs the original routine and your C on the same memory. Both must leave every byte the same. One AI-assisted project did all 778 routines of Harvest Moon this way in nine days. A big game like Chrono Trigger has taken months and is not done.
Most of the work runs on plain Windows. You only need WSL for a few Linux-style build scripts.
No C to recover
Most games were written in assembly by hand. So a byte-matching C decomp is not possible. Path B writes new C and proves it acts the same as the original.
The CPU changes size
The 65816 can switch its main registers between 8 and 16 bits. The same bytes then mean different instructions. Tools must track two flags, called M and X, at every point. Wrong widths give garbage code.
Jumps through tables
Many games jump through tables of addresses. A tool cannot always see where those jumps go. Each missed target falls back to the slow interpreter. Finding these targets is most of the Path A grind.
Extra chips in some carts
Some cartridges carry their own chips, such as Super FX, SA-1, Cx4 or DSP-1. snesrecomp supports those four. Only Star Fox has been checked on Super FX so far. S-DD1 is experimental. SPC7110, ExHiROM and DSP-2, DSP-3 and DSP-4 are not supported yet. Check your cart first.
Fan disassemblies exist
Fans have made assembly sources that rebuild the exact ROM for many big games. A disassembly is the game turned back into readable assembly. Starting from one let DKC1 Recomp run on its first day.
Two paths
Get it running on PC
snesrecomp reads the ROM and writes C for each routine it can prove. A shared runtime plays the part of the console chips. Code it cannot prove runs in an interpreter. You then fix jump targets and timing one bug at a time. Eight of the reviewed projects used this path.
Full decomp for porting
SNES games have no original C, so byte-matching C is not possible. Instead you prove a disassembly first. Then you rewrite each routine in C. A checker compares your C with the original routine on the same memory. When all routines pass, the game runs on your C alone.
Path A: Get it running on PC
snesrecomp reads the ROM and writes C for each routine it can prove. A shared runtime plays the part of the console chips. Code it cannot prove runs in an interpreter. You then fix jump targets and timing one bug at a time. Eight of the reviewed projects used this path.
Method: static recompilation
Pick this first for any game on a supported cartridge. It gets you a playable game in weeks.
Pick the game and check the ROM
Choose one game and one exact ROM version. Check that
snesrecompsupports its cartridge type. Look for work that already exists. Write it all inSCOPE.md.- Clone the framework:
git clone --recurse-submodules https://github.com/RetroPortingToolKit/snesrecomp.git. - Probe your dump:
python tools/new_project/probe_rom.py 'D:\ROMs\My Game.sfc'. Look forcoprocessor=noneand a valid checksum. - Read the chip table in the
snesrecompREADME. Plain LoROM and HiROM games are the easy start. - Look for an existing port in the
snesrecompgames list and on RecompLauncher. Joining one may beat starting over. - Search GitHub for a disassembly of your game that rebuilds the exact ROM. Note its link and license.
- Get the hash:
Get-FileHash -Algorithm SHA256 'D:\ROMs\My Game.sfc'. Put it inSCOPE.md.
Prompt for ClaudeGOAL: Write a draft `SCOPE.md` for a `snesrecomp` port of <GAME> (<REGION>, <REVISION>). READ FIRST: `D:/ROMs/<GAME>.sfc` (path only, never copy it), the `snesrecomp` README chip table, its `docs/GETTING_STARTED.md`, and the games list in the README. FENCE: Edit only `SCOPE.md`. Do not generate code or install anything. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `python tools/new_project/probe_rom.py 'D:/ROMs/<GAME>.sfc'` and paste the output. Done means `SCOPE.md` lists: SHA-256, mapping (LoROM or HiROM), coprocessor, existing ports, existing disassemblies with license, the technique, the first milestone and its golden run, and what is out of scope. BUDGET: 30 minutes. Stop after 3 failed tries of any command. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenSelect-String -Path SCOPE.md -Pattern '<SHA-256>','APPROVED:'finds both lines. You add theAPPROVED:line yourself.Proof this works: https://github.com/RetroPortingToolKit/snesrecomp/blob/main/docs/GETTING_STARTED.md, Mega Man X Recomp (refuses the v1.0 ROM; only Rev 1 works), TMNT IV: Turtles in Time PC (one
rom_identity.txtfile)- Clone the framework:
Install the tools on Windows
Install the build tools once. Then make the project folder, the rules file and the ledgers. Keep the ROM outside the repo.
- Install Git for Windows with Git Bash, and Python 3.11 or newer on the PATH.
- Install Visual Studio 2022 with Desktop development with C++ and C++ CMake tools for Windows.
- Install Rust with
rustup-init.exefrom rust-lang.org. The analyzer needs Rust 1.85 or newer. - Open Developer PowerShell for VS 2022. Run
git --version,python --version,cargo --versionandcmake --version. - Keep ROMs in a folder like
D:\ROMs. Add*.sfc,*.smcandsrc/gen/to.gitignore. - Write
CLAUDE.md,PROGRESS.md,notes/parking-lot.mdand one check script,check.ps1.
Prompt for ClaudeGOAL: Set up the repo skeleton and the one check command for the <GAME> port. READ FIRST: `SCOPE.md`, `snesrecomp/docs/GETTING_STARTED.md` section 1. FENCE: Create or edit only `CLAUDE.md`, `PROGRESS.md`, `notes/parking-lot.md`, `.gitignore` and `check.ps1`. Do not install software; tell me if a tool is missing. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `git --version; python --version; cargo --version; cmake --version` and then `./check.ps1`. Done means all four print versions and `check.ps1` runs the build and the golden run (failing is fine for now). BUDGET: 45 minutes. Stop after 3 failed tries. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenAll four version commands print a version, andcheck.ps1runs from start to end.Proof this works: https://github.com/RetroPortingToolKit/snesrecomp/blob/main/docs/GETTING_STARTED.md, https://rust-lang.org/tools/install/, Belthasar (CLAUDE.md, skills and a session-start hook)
Make the project and generate C
The framework has a setup script. It records the ROM's hashes, pulls in the launcher and writes the first C files. Generated C goes in
src/genand is never edited by hand.- From the framework folder:
powershell -File tools\new_project\setup_project.ps1 -Rom 'D:\ROMs\My Game.sfc' -Dir D:\SNESDev -Name 'My First Port' -Yes --players 1 --recomp-ui --no-netplay --no-fetch-boxart --no-github --generate --no-build. - The project folder is the name with spaces removed plus
SNESRecomp, such asD:\SNESDev\MyFirstPortSNESRecomp. - Check that
src\genholds.cfiles and thatrom_identity.txtandCMakeLists.txtexist. - Configure:
cmake -S . -B build -G 'Visual Studio 17 2022' -A x64. - Build:
cmake --build build --config Release --parallel. - Treat any warning during generation as a problem to look into.
Prompt for ClaudeGOAL: Scaffold the <GAME> project with `setup_project.ps1` and get one clean Release build. READ FIRST: `SCOPE.md`, `CLAUDE.md`, `snesrecomp/docs/GETTING_STARTED.md` sections 3 and 4. FENCE: Run commands only. Edit only `PROGRESS.md`. Never edit files in `src/gen`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `cmake --build build --config Release --parallel`. Done means it ends with no errors and `build/Release/<NAME>SNESRecomp.exe` exists. Paste the last 20 lines. BUDGET: 1 hour. Stop after 3 failed builds. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenTest-Path build\Release\<NAME>SNESRecomp.exeprintsTrueafter a build with no errors.Proof this works: https://github.com/RetroPortingToolKit/snesrecomp/blob/main/docs/GETTING_STARTED.md, Super Castlevania IV (scaffolded from snesrecomp), Yoshi's Island Recomp (scaffolded from snesrecomp)
- From the framework folder:
Map the code into the config files
Make a ledger of every routine. Feed known starts, names and jump targets into
recomp/symbols.tomlandrecomp/bank*.cfg. The more the analyzer knows, the less code runs in the slow interpreter.- If a disassembly exists, prove it first. Build it and compare the hash with your ROM. DKC2 did this with Asar 1.91.
- Write a small import script that turns the disassembly's labels into cfg entries. DKC1 and DKC3 each have one (
tools/ingest_dkc1_disasm.py). - List each routine in
recomp/symbols.toml.emit = falsekeeps it interpreted.emit = truecompiles it. - Record each jump-table site and its proven targets in its bank cfg. DKC1 and DKC3 call these dispatch contracts. Copy their syntax only after you check it against your framework version.
- Regenerate after every change:
& 'C:\Program Files\Git\bin\bash.exe' tools/regen.sh --rom 'D:/ROMs/My Game.sfc'. - Keep
notes/routines.csvwith address, name, size, status and the source of each fact.
Prompt for ClaudeGOAL: Import routine starts and names for bank <BANK> into the recompiler config and the ledger. READ FIRST: `SCOPE.md`, `recomp/bank<BANK>.cfg`, `recomp/symbols.toml`, the disassembly at <DISASM_PATH> (labels and pointer tables only). FENCE: Edit only `recomp/bank<BANK>.cfg`, `recomp/symbols.toml`, `notes/routines.csv` and `tools/ingest_disasm.py`. Never edit `src/gen`. Do not guess a jump target: every entry must cite a disassembly label or address. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `& 'C:\Program Files\Git\bin\bash.exe' tools/regen.sh --rom 'D:/ROMs/<GAME>.sfc'` and then `./check.ps1`. Done means regen prints no new warnings and the ledger row count for bank <BANK> matches the import script's count. BUDGET: 1 hour. Stop after 3 failed regens. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whennotes/routines.csvlists every known routine with a status, and regen runs with no new warnings.Proof this works: DKC1 Recomp (1,276 function entries from the Yoshifanatic1 disassembly), DKC3 Recomp (4,716 entries and 353 dispatch contracts), DKC2 Recomp (Asar 1.91 byte check)
Boot to the title screen
This is first light. Drive the game with a script, not by hand. The framework host can run an input script and dump memory to files. Then a script can check any claim about the game, not your eyes.
- Write
routes\boot.txtin the shared script format. One command per line:wait 3600, thendump title, thenquit. - Run it:
$env:SNESRECOMP_DUMP_DIR = 'out\port', then.\build\Release\<NAME>SNESRecomp.exe --no-launcher --script routes\boot.txt 'D:\ROMs\My Game.sfc'. - A good run exits with code 0 and writes
out\port\title.wram.bin,title.vram.binandtitle.fb.bmp. - Prefer
until <addr> == <value>over a fixedwait. If the game never gets there, the run exits with code 3. - Put game-specific frame and interrupt code in
src/game_rtl.c, never insrc/gen. - Run it twice.
Get-FileHash out\port\title.wram.binmust give the same hash both times.
Prompt for ClaudeGOAL: Make the headless golden run reach the <GAME> title screen within <N> frames. READ FIRST: `SCOPE.md`, `CLAUDE.md`, `src/game_rtl.c`, `snesrecomp/docs/FRAME_MODEL_HOSTS.md`, the script grammar in `snesrecomp/tools/snesref/README.md`, the last dumps in `out/port/`. FENCE: Edit only `src/game_rtl.c`, `src/main.c`, `recomp/*.cfg`, `recomp/symbols.toml` and `check.ps1`. Never edit `src/gen` or the `snesrecomp` submodule. Never fake a hardware reply to get further. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `./check.ps1 -Script routes/boot.txt` twice. Done means both runs exit 0 and `title.wram.bin` has the same SHA-256 both times. BUDGET: 2 hours, or 4 failed tries with no new frames reached. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe scripted run exits with code 0, andtitle.wram.binhas the same SHA-256 on two runs.Proof this works: https://github.com/RetroPortingToolKit/snesrecomp/blob/main/tools/snesref/README.md, https://github.com/RetroPortingToolKit/snesrecomp/blob/main/runner/src/host_args.c, DKC1 Recomp (3,600-frame headless boot on day one), DKC3 Recomp (4,801-frame headless boot on day one)
- Write
Fix one divergence at a time
Now grind. Run one route in your port and in a trusted emulator. The same script file drives both. The first dump that differs points at the bug.
- Write each route as a script with
press,untilanddump <tag>lines. Save it inroutes\. - Build
snesref: extractSDL2-devel-2.30.9-VC.ziptotools\snesref\SDL2-2.30.9, thencd tools\snesrefand.\build.bat. PutSDL2.dllbesidesnesref.exe. - Run the reference with
SNESREF_HEADLESS=1,SNESREF_WRAM_FILL=0,SNESREF_SCRIPT=<route>andSNESREF_DUMP_DIR=out\refset. Then run.\snesref.exe C:\cores\snes9x_libretro.dll D:\ROMs\game.sfc. - Run the port on the same script with
SNESRECOMP_DUMP_DIR=out\port. Compare each pair of<tag>.wram.binfiles withGet-FileHash. - Dump on game events with
until, not on frame numbers. DKC2 compared at matched events for this reason. - To find a bad compiled routine, regenerate with
SNESRECOMP_EMIT_AOT_DENY_GATE=1. List routine addresses in a text file named bySNESRECOMP_LLE_INTERP_TARGET_FILE. Those routines then run on the interpreter, with no rebuild. - Regenerate without the deny gate before you package. F-Zero warns about shipping it by mistake.
- After each run, fix unresolved jump targets first. They are the main reason ports drift.
- Promote routines to
emit = trueone at a time. Rerun every route after each one.
Prompt for ClaudeGOAL: Find and fix the first divergence in route `routes/<ROUTE>.txt`. READ FIRST: `CLAUDE.md`, `notes/findings.md`, the route file, the last dumps in `out/ref/<ROUTE>/` and `out/port/<ROUTE>/`. FENCE: Edit only `recomp/*.cfg`, `recomp/symbols.toml`, `src/game_rtl.c` and `notes/findings.md`. Never edit `src/gen`, the submodule, the route file or expected hashes. No game-specific `if` on scene numbers. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `./check.ps1 -Route <ROUTE>`. Done means the first WRAM difference moves past frame <FRAME>, and all older routes still pass. BUDGET: 90 minutes, or 3 fixes that do not move the first divergence. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenFor every route, each<tag>.wram.binfrom the port has the same SHA-256 as the one fromsnesref.Proof this works: https://github.com/RetroPortingToolKit/snesrecomp/blob/main/tools/snesref/README.md, FZeroSNESRecomp (AOT deny gate to bisect a bad routine), Yoshi's Island Recomp (rule: fix unresolved targets first), DKC2 Recomp (Snes9x compare at matched events)
- Write each route as a script with
Build the regression set
A regression is an old bug that comes back. Turn each fixed bug into a replay with pinned hashes. Run them all after every change.
- Save each fixed bug as a route with its expected frame, WRAM, VRAM and audio hashes.
- Run each route three times. All hashes must match byte for byte, as DKC1 requires.
- Run
ctest --test-dir build -C Release --output-on-failureafter every change. - Keep a ROM-free CI build with
-DSNESRECOMP_SETUP_HOST=ON, so tests run with no game data. - Test save states in a fresh process. Load one, then compare the next 180 frames with a reference.
Prompt for ClaudeGOAL: Turn the fixes listed in `PROGRESS.md` into regression routes and wire them into CTest. READ FIRST: `PROGRESS.md`, `notes/findings.md`, `routes/`, `CMakeLists.txt`. FENCE: Edit only `tests/`, `routes/`, `CMakeLists.txt` and `PROGRESS.md`. Do not change game code, and never write an expected hash you did not just measure. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `ctest --test-dir build -C Release --output-on-failure` three times. Done means every route passes all three times with the same hashes. Also break one route on purpose and show that its test fails. BUDGET: 1 hour. Stop after 3 failed tries. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenA clean checkout passes the full check, and every route gives the same hashes on three runs.Proof this works: DKC1 Recomp (three byte-identical replays), TMNT IV: Turtles in Time PC (180-frame save state identity test), Mega Man X Recomp (ROM-free CI setup host)
Add extras and package with no game data
Only add extras after the stock game works. Widescreen and other features go behind switches that start off. Ship your code and tools, never the ROM or code made from it.
- Add one extra at a time. The original 256 by 224 picture must stay pixel-exact with the extra off.
- The scaffold records framework commits in
framework_pins.txt. Keep it current. Keep framework fixes as named files inpatches/. - Package with
scripts/package_release.sh. It refuses to package when it finds ROM data. Make CI fail ifsrc/genfiles appear, as Super Castlevania IV does. - Include
THIRD_PARTY_ATTRIBUTION.mdin every package.snesrecompitself is PolyForm Noncommercial. - Run
git statusbefore each commit. No ROMs, saves, art or generated code may go in.
Prompt for ClaudeGOAL: Add <FEATURE> behind a setting that defaults to off, without changing the stock picture. READ FIRST: `SCOPE.md`, `CLAUDE.md`, `snesrecomp/docs/WIDESCREEN_PATTERNS.md`, `PROGRESS.md`. FENCE: Edit only `src/<FEATURE>_*.c`, `src/game_rtl.c` hook points and the settings file. Never edit `src/gen` or the submodule. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `./check.ps1` with the feature off. Done means every route hash is unchanged. Then run route <ROUTE> with it on and paste the frame dump path. BUDGET: 2 hours. Stop after 3 failed tries. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenscripts/package_release.shsucceeds, and a listing of the zip shows no.sfc,.smcorsrc/genfile.Proof this works: DKC1 Recomp (stock center is a pixel-exact oracle), Super Castlevania IV (setup packs; CI fails on generated C), https://github.com/RetroPortingToolKit/snesrecomp#license, https://github.com/RetroPortingToolKit/snesrecomp/blob/main/docs/GAME_PROJECT_SETUP.md
Path B: Full decomp for porting
SNES games have no original C, so byte-matching C is not possible. Instead you prove a disassembly first. Then you rewrite each routine in C. A checker compares your C with the original routine on the same memory. When all routines pass, the game runs on your C alone.
Method: rebuildable disassembly, then a C rewrite checked routine by routine against the original
Pick this when you want readable code, deep mods or a port to a new system. Finish Path A first, because it becomes your checker.
Scope the rewrite
Decide how far to go. You will write new C that acts the same, not C that rebuilds the same bytes. Find a disassembly first. Without one, add weeks of work.
- Search for a disassembly that rebuilds your exact ROM. Examples:
SMWDisXfor Super Mario World,ebsrcfor EarthBound,HM-Decompfor Harvest Moon. - Read its license. Use names and addresses freely. Copy code only if the license allows it.
- Check whether a C rewrite exists already, such as
snesrev/zelda3orsnesrev/smw. - Write in
SCOPE.mdwhat done means: every routine checked, and the game plays on your C alone.
Prompt for ClaudeGOAL: Draft `SCOPE.md` for a full C rewrite of <GAME> (<REVISION>, SHA-256 <HASH>). READ FIRST: `SCOPE.md` from Path A if it exists, the disassembly README at <DISASM_URL>, and any C rewrite of the same game. FENCE: Edit only `SCOPE.md`. Do not clone or install anything. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means `SCOPE.md` names: the disassembly and its license, how its build is proven to match, the routine count if known, the checker design, the first milestone and what is out of scope. Every claim has a link. BUDGET: 45 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenSelect-String -Path SCOPE.md -Pattern 'disassembly','license','APPROVED:'finds all three. You add theAPPROVED:line yourself.Proof this works: HarvestMoonSnesDecomp (built on the HM-Decomp disassembly), Belthasar (Chrono Trigger; follows the zelda3 method), https://github.com/Herringway/ebsrc
- Search for a disassembly that rebuilds your exact ROM. Examples:
Get a disassembly that rebuilds the ROM
You need assembly source that builds the exact same ROM. That proves every address and label. If none exists, you must make one.
- Asar sources build with
asar.exe [options] <main.asm> <out.sfc>. Getasar191.zipfrom the Asar releases page. - Other disassemblies list their own build steps and helper tools in their README. For example
ebsrcneedsca65v2.19,ebbinex,spcasmand GNUmake. Follow that README exactly. - Compare hashes:
Get-FileHash -Algorithm SHA256 out.sfcmust equal your ROM's hash. - No disassembly? Open the ROM in
DiztinGUIsh. Capture a trace log from its BSNES build while you play. That marks code, data and M/X widths. - Export the
.asmfrom Diz and rebuild it until the hash matches.
Prompt for ClaudeGOAL: Make `tools/rebuild.ps1` build the disassembly and prove it matches the original ROM. READ FIRST: `SCOPE.md`, the disassembly README, its build files. FENCE: Edit only `tools/rebuild.ps1`, `.gitignore` and `PROGRESS.md`. Do not edit the disassembly's `.asm` files in this task. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `./tools/rebuild.ps1`. Done means it prints the built ROM's SHA-256, and it equals `<HASH>` from `SCOPE.md`. Also change one byte in a copy of the source and show the hash check fails. BUDGET: 1 hour. Stop after 3 failed builds. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenOne command rebuilds a ROM whose SHA-256 equals the original's.Proof this works: DKC2 Recomp (H4v0c21 disassembly assembled with Asar 1.91, byte for byte), https://github.com/DizTools/DiztinGUIsh, https://github.com/Herringway/ebsrc
- Asar sources build with
Build Path A first as your oracle
An oracle is a trusted way to get the right answer. You need one that runs each original routine. The Harvest Moon rewrite checked its routines against its sister
snesrecompport. So do Path A steps 1 to 5 first.- Build the recomp port of your game, as in Path A.
- Import the disassembly's names. Harvest Moon renamed
bank_83_8138_M1X0toGetRNG_M1X0with a script. - Name each shared RAM address once, in one header, with a note on its use.
- Make the routine ledger: one row per routine with address, name, size, target file and status.
Prompt for ClaudeGOAL: Build the routine ledger for <GAME> from the disassembly and the recomp port. READ FIRST: `SCOPE.md`, the disassembly labels, `recomp/symbols.toml`, `src/gen` (read only). FENCE: Edit only `notes/routines.csv`, `tools/make_ledger.py` and `src/<GAME>_vars.h`. Never edit `src/gen`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `python tools/make_ledger.py --check`. Done means every routine the analyzer found has one row, the totals match, and no row lacks an address. BUDGET: 1 hour. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenpython tools/make_ledger.py --checkexits 0, and its totals match the analyzer's routine count.Proof this works: HarvestMoonSnesDecomp (DECOMPILATION.md: names imported from HM-Decomp), https://github.com/RetroPortingToolKit/snesrecomp
Build the routine checker
This is the heart of Path B. Save the machine state. Run the original routine. Run your C on a copy. Then compare all 128 KB of work RAM, the CPU registers and the DMA registers.
- Add an in-play mode that checks every call while the game runs. Harvest Moon uses
HM_DECOMP_CHECK=1. - Add a fuzz mode that calls each routine thousands of times with random and edge values. Harvest Moon uses
HM_DECOMP_FUZZ=<frame>:<count>. - Compare the stack bytes too. A routine that pushes or calls leaves bytes below the stack pointer.
- Test the checker: change one number in a rewrite on purpose. It must fail. Then undo it.
- Wrap it in one command that prints PASS or the first byte that differs.
Prompt for ClaudeGOAL: Build the per-routine checker with an in-play mode and a fuzz mode. READ FIRST: `SCOPE.md`, `notes/routines.csv`, the recomp runtime headers, `HarvestMoonSnesDecomp/DECOMPILATION.md` (method only). FENCE: Edit only `src/check/`, `tools/check.sh` and `CMakeLists.txt`. Never edit `src/gen` or the submodule. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: From Git Bash or WSL, run `bash tools/check.sh <FRAMES> <SEEDS>` with one untouched routine, then with one routine broken on purpose. Done means PASS for the first and a reported WRAM or register difference for the second. BUDGET: 3 hours. Stop after 3 failed designs. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe checker fails on a broken rewrite and passes on an untouched routine.Proof this works: HarvestMoonSnesDecomp (WRAM, registers and DMA compared per call), Belthasar (
--sweepmodes run one ROM routine over generated inputs)- Add an in-play mode that checks every call while the game runs. Harvest Moon uses
Rewrite your first routine
Get one small routine to pass end to end. Pick a leaf routine, which is one that calls no others. A random number routine is a good start.
- Pick a leaf routine from the ledger with no calls and no DMA.
- Write it in
src/<system>.cwith plain names and short comments. - Run the in-play check and the fuzz check.
- Mark it verified in the ledger and commit only that file.
Prompt for ClaudeGOAL: Rewrite routine `<NAME>` at `<ADDRESS>` in readable C that passes the checker. READ FIRST: Its rows in `notes/routines.csv`, its disassembly at <DISASM_FILE>:<LINE>, `src/<GAME>_vars.h`. FENCE: Edit only `src/<SYSTEM>.c` and the routine's ledger row. No inline assembly, no copied bytes, no calls back into the original code. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: From Git Bash or WSL, run `bash tools/check.sh 2000 10`. Done means 0 mismatches for `<NAME>` in both modes. BUDGET: 5 tries. Each try must change one idea. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenBoth check modes pass for that routine and the ledger says verified.Proof this works: HarvestMoonSnesDecomp (first commit: 7 routines verified against the original)
Run the routine loop
Now repeat for every routine. Work from the leaves up. Each worker takes one routine in its own git worktree. Only checked routines get merged.
- Pick next the routines whose callees are all verified.
- Give each worker one routine, one file and its own worktree:
claude --worktree <name>. - Merge only work whose checker run passes on the merged branch, not just in the worktree.
- Send routines that fail five tries to a hard job, with notes from each failed try.
- When the original does something odd, copy the oddness. Harvest Moon's
ChangeStaminareads a flag set by its caller. - Track progress with a script, like Harvest Moon's
tools/progress.py.
Prompt for ClaudeGOAL: Rewrite routine `<NAME>` (<SIZE> bytes) in C so the checker passes. READ FIRST: `CLAUDE.md`, its ledger row, its disassembly, the verified C of its callees, `notes/quirks.md`. FENCE: Edit only `src/<SYSTEM>.c` and the ledger row for `<NAME>`. Work in your own worktree. No inline assembly, no calls into original code, no edits to the checker. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: From Git Bash or WSL, run `bash tools/check.sh 2000 10`. Done means 0 mismatches for `<NAME>` and no new mismatches in any verified routine. BUDGET: 5 tries, each with one new idea. Then stop and write what failed in the ledger notes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe ledger shows every routine verified, and the merged branch passes the full checker.Proof this works: HarvestMoonSnesDecomp (778 of 778 routines), https://github.com/RodoLy/HarvestMoonSnesDecomp/blob/main/DECOMPILATION.md
Prove the whole game
A checked routine can still fail in a rare state. So test whole runs too. Give every test a planted bug that must make it fail.
- Replay full routes with the checker on.
zelda3compares RAM with the original code after every frame. - Reach test points from power-on with scripted pad inputs, like Belthasar's
tools/recipes/. - Give each test a mutation, a planted bug that must turn it red. Belthasar has 950 checks, and 931 of them carry mutations.
- Have a fresh session re-run everything and hunt for cheats.
Prompt for ClaudeGOAL: Run every route with the checker on and add a mutation to each regression test. READ FIRST: `PROGRESS.md`, `tests/`, `routes/`, `notes/routines.csv`. FENCE: Edit only `tests/` and `PROGRESS.md`. Do not change game C in this task. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: From Git Bash or WSL, run `bash tools/check.sh --routes all` and `python tools/mutate.py`. Done means 0 mismatches on all routes, and every test fails under its mutation. BUDGET: 2 hours. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenEvery full route runs with zero mismatches, and every test fails under its mutation.Proof this works: https://github.com/snesrev/zelda3, Belthasar (950 checks, 2,205 mutations)
- Replay full routes with the checker on.
Run on your C alone
Now cut the original code out. The game must run on your C plus the hardware chips. The chips here mean the picture and sound parts, kept as a library.
- Make a native target that links your C, not
src/gen. Harvest Moon's lives innative/. - Build it:
cmake -S native -B build/native && cmake --build build/native. - Keep the picture and sound chips behind one small interface. Harvest Moon reused the
snesrecompchips unchanged. - Run the golden routes. RAM hashes and frames must match the checked build.
Prompt for ClaudeGOAL: Make `build/native` run <GAME> on the rewritten C with no recompiled game code linked. READ FIRST: `SCOPE.md`, `CMakeLists.txt`, `native/`, `notes/routines.csv`. FENCE: Edit only `native/` and its CMake files. Do not edit verified routines; report any that break. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run the golden routes on `build/native`. Done means the same hashes as the checked build, and `Select-String -Path native/CMakeLists.txt -Pattern 'src/gen'` finds nothing. BUDGET: 2 hours. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe native build reaches the same points with the same hashes, with no original game code linked.Proof this works: HarvestMoonSnesDecomp (
native/build, chips from snesrecomp)- Make a native target that links your C, not
Port to another system
Now move the game to a new system. Put the window, sound and input behind SDL, a cross-platform library. Then build with the new system's tools.
- Use SDL for window, sound and pads. Harvest Moon uses SDL3. Phase Distorter uses SDL2.
- Build with the target's toolchain. Harvest Moon ships Windows, macOS, Linux and Android builds.
- Build Linux releases in a pinned container so older systems work. Phase Distorter used Debian 12.
- Run the golden routes on the new system before you call it done.
Prompt for ClaudeGOAL: Make the native build compile and pass the golden routes on <TARGET>. READ FIRST: `SCOPE.md`, `native/`, the target toolchain docs at <URL>. FENCE: Edit only `native/platform/<TARGET>/` and build files. Do not change game routines. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run the golden routes on <TARGET>. Done means the same RAM hashes as on Windows. BUDGET: 3 hours. Stop after 3 failed builds and list the errors. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe game runs on the new system and passes the same golden routes.Proof this works: HarvestMoonSnesDecomp (Windows, macOS, Linux, Android), Phase Distorter (Debian 12 container), Star Fox Enhanced (many targets)
Tools you need
| Tool | What it does | How to get it | How we know |
|---|---|---|---|
| snesrecomp Required both | Turns 65816 machine code into C and builds it with a shared SNES runtime. Code it cannot prove runs in its interpreter. It also ships the snesref and co-sim debug tools.Path A Path B | git clone --recurse-submodules https://github.com/RetroPortingToolKit/snesrecomp.git | README, docs/GETTING_STARTED.md and AGENTS.md (read 2026-11-13); release v0.4.5-alpha dated 2026-11-11 holds only a separate code-generation CLI zip, not the scaffold; used by 8 reviewed projects |
| Visual Studio 2022 (C++ workload with CMake tools) Required Windows | The Windows compiler and build tools that the snesrecomp guide uses.Path A Path B | Install Visual Studio 2022 with 'Desktop development with C++', the Windows SDK and 'C++ CMake tools for Windows' | snesrecomp docs/GETTING_STARTED.md section 1 (read 2026-11-13); used by DKC1, DKC3, TMNT IV and Belthasar |
| Git for Windows (Git Bash) Required Windows | Clones the repos. Its Bash runs the regen.sh scripts on Windows.Path A Path B | Download and run the installer from https://git-scm.com/downloads/win | snesrecomp docs/GETTING_STARTED.md (read 2026-11-13) |
| Python 3.11+ Required both | Runs the probe, setup and import scripts. Most projects keep their tools in Python. Path A Path B | Install from https://www.python.org/downloads/windows/ and tick 'Add to PATH'. In WSL: sudo apt install python3 | snesrecomp docs/GETTING_STARTED.md asks for 3.11 or newer (read 2026-11-13) |
| Rust (rustup) Required both | Builds the fast native analyzer inside snesrecomp. You do not write any Rust.Path A Path B | Windows: run rustup-init.exe from rust-lang.org. WSL: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh | rust-lang.org install page (read 2026-11-13); the snesrecomp guide needs Rust 1.85+; DKC2 measured 25.3 s with the Rust analyzer vs 401 s with Python |
| CMake and Ninja Required both | Set up and run the build. CMake comes with the Visual Studio tools. Ninja is used on Linux and in CI. Path A Path B | Windows: included with Visual Studio's C++ CMake tools. WSL: sudo apt install cmake ninja-build | build steps in the DKC2, DKC3, Mega Man X, F-Zero and Phase Distorter cards; ninja repo (read 2026-11-13) |
| SDL2 development package (for snesref) Helpful Windows | The window and input library that the snesref reference tool builds against.Path A Path B | Download SDL2-devel-2.30.9-VC.zip from the SDL release-2.30.9 page and extract it to tools\snesref\SDL2-2.30.9 | snesrecomp tools/snesref/README.md build steps and the SDL release-2.30.9 asset list (read 2026-11-13) |
| Snes9x (libretro core) Helpful both | A trusted SNES emulator. Load its libretro core into snesref to compare your port frame by frame.Path A Path B | Download snes9x-1.63-libretro-x64.zip from the Snes9x Releases page (non-commercial license) | Snes9x release 1.63 assets (read 2026-11-13); snesrecomp README and snesref README (Snes9x has a non-commercial license); used by DKC2 and Super Castlevania IV |
| bsnes Helpful both | An accurate SNES emulator. Its libretro core also works with snesref as a second reference.Path A Path B | Supply your own `bsnes_libretro.dll` core (GPLv3). The `bsnes-windows.zip` nightly is the stand-alone emulator. | snesrecomp and snesref READMEs name a bsnes libretro core (read 2026-11-13). Which download holds a Windows bsnes_libretro.dll was NOT confirmed. |
| Mesen (Community Edition) Helpful both | A multi-system emulator with SNES debug tools. Use it to watch memory and step through code by hand. Path A Path B | Download Mesen_2.2.1_Windows.zip from the MesenCE Releases page | MesenCE README and release 2.2.1 (read 2026-11-13); the older SourMesen/Mesen2 repo is archived and points here. No reviewed card names it |
| Asar Helpful both | An SNES assembler for 65c816, SPC700 and Super FX code. Many fan disassemblies build with it. You need it when yours does.Path A Path B | Download asar191.zip from the Asar Releases page. Usage: asar.exe [options] {asm_file} [rom_file] | Asar README and manual (read 2026-11-13); DKC2 used Asar 1.91 to prove its disassembly byte for byte |
| cc65 (ca65 assembler) Helpful both | The assembler and linker used by ebsrc and other ca65-based disassemblies.Path B | Windows: cc65-snapshot-win64.zip, linked from the cc65 README. ebsrc pins ca65 v2.19 | cc65 README downloads section and ebsrc README (read 2026-11-13); the README links a snapshot zip, while the V2.19 tag has no zip, so check the version ebsrc asks for; Phase Distorter builds ebsrc banks with ca65 and ld65 |
| DiztinGUIsh Helpful Windows | An SNES disassembler that learns which bytes are code or data from a live trace. It exports .asm that builds back into the ROM.Path B | Download the latest zip (v2.5.1.0) from the DiztinGUIsh Releases page | README and release v2.5.1.0 (read 2026-11-13); no reviewed card names it directly |
| LakeSnes Helpful both | A small SNES emulator in C. smw, zelda3 and Belthasar run it inside their test tools as the oracle. Path B | git clone https://github.com/angelo-wf/LakeSnes (MIT; archived, so pin the commit) | gh api repo data (read 2026-11-13); used by snesrev/smw, snesrev/zelda3 and Belthasar; the snesrecomp runner derives from it |
| SingleStepTests 65816 Helpful both | JSON tests for every 65816 instruction, 20,000 per opcode. Use them if you change or write a CPU core.Path B | git clone https://github.com/SingleStepTests/65816 | README (read 2026-11-13); DKC2's interpreter passed 5,080,000 of these state checks |
Skills and add-ons
Read any skill before you install it. A skill is a set of instructions that Claude will follow. See Tools and Skills for the full list and safety notes.
verification-before-completion
Claude may not say done without fresh proof. Here that means pasted hashes from a headless run, not 'the title showed up'.
npx skills add obra/superpowers --skill verification-before-completion -a claude-code
systematic-debugging
No fix before the cause is found. It fits the hunt for the first differing frame.
npx skills add obra/superpowers --skill systematic-debugging -a claude-code
using-git-worktrees
Keeps each worker in its own copy of the repo. DKC3 got mixed-up commits when two sessions shared one folder.
npx skills add obra/superpowers --skill using-git-worktrees -a claude-code
handoff
Writes a short note so a fresh session can carry on. Tell it to save inside the repo, not the temp folder.
npx skills add mattpocock/skills --skill handoff -a claude-code
static-recomp-scope-plan
Makes you write the exact ROM, the test scenes and the pass numbers before work starts. That becomes your SCOPE.md.
npx skills add bgyss/switchrecomp --skill static-recomp-scope-plan -a claude-code
static-recomp-av-compare
Scores your port's video and sound against your own recordings with ffmpeg. Fix its script paths first, since it was written for Codex.
npx skills add bgyss/switchrecomp --skill static-recomp-av-compare -a claude-code
gamedecomp-library
Searches a list of about 790 decomp projects. Use it once at the start to find a disassembly. Treat hits as hints. Do not run the repo's install.sh.
npx skills add madpai/game-decomp-compendium --skill gamedecomp-library -a claude-code
PreToolUse hook that blocks generated files
Turns the top rule from DKC1, F-Zero and Yoshi's Island into a hard block. Claude cannot hand-edit generated C or the pinned framework.
Ask Claude: 'Write a PreToolUse hook in .claude/settings.json that blocks edits to src/gen/, snesrecomp/ and rom_identity.txt, exits with code 2 and says what to do instead.'
snes-regen-check (project skill)
Every session uses the same tools the same way. It stops Claude from building a new debug tool each time.
Make .claude/skills/snes-regen-check/SKILL.md. List where each kind of fix belongs (recomp/*.cfg, symbols.toml, src/game_rtl.c, patches/), the regen command, the headless run, the route list, and the rule 'paste hashes or it is not done'. Model it on DKC1's dkc1-tools skill.
snes-re-derive (project skill)
Forces proof from the ROM before any code change. Belthasar used this to stop invented fixes.
Make .claude/skills/snes-re-derive/SKILL.md. Steps: reproduce on the oracle, find the RAM that changes and the instruction that writes it, read it with the right M/X widths, then write a note in notes/re/ with ROM addresses and open questions. Model it on Belthasar's re-derive skill.
Claude setup for this system
Path A's unit is one divergence: the first frame where a route stops matching. Path B's unit is one routine, judged by the routine checker. Each unit gets one session, one task card and one check. Keep framework changes apart from game changes, since one engine fix can break other games. Write every finding in a file, never only in chat.
Which model and effort for each job
The model and effort names come from one shared table, so they stay the same on every guide. See Claude Setup for the reasons.
| Job | What it means on this system | Max 20x (now called Ultra) | Max 5x (now called Max) |
|---|---|---|---|
| Plan the project | Pick the ROM revision, check the chip table, and find ports and disassemblies. Write SCOPE.md. | Fable 5.2 effort highOne session. This choice shapes months of work. | Opus 5.5 effort highUse Fable 5.2 for this one session if you have weekly room. |
| Set up the project | Install the tools, run setup_project.ps1, and write check.ps1, the hooks and CLAUDE.md. | Opus 5.5 effort medium | Sonnet 5.5 effort medium |
| Study the game file | Import disassembly labels into recomp/*.cfg and symbols.toml. Find jump-table targets and M/X widths. Build the routine ledger. | Opus 5.5 effort high | Opus 5.5 effort mediumRaise to high for function edges and data layouts. A mistake there spreads. |
| Bulk units | Path A: promote routines to emit = true one by one. Path B: rewrite leaf routines that pass the checker. | Sonnet 5.5 effort mediumHaiku 5.5 for the plainest units. | Sonnet 5.5 effort mediumFewer workers at once. Haiku 5.5 for the plainest units. |
| Hard units | Routines with stack tricks, NMI loops or task switching, and rewrites that failed five tries. Mega Man X's task scheduler is one such case. | Fable 5.2 effort highGo to xhigh only after a failed try at high. | Opus 5.5 effort highSend only the last few that still fail to Fable 5.2. |
| Build the runtime | Host code in src/game_rtl.c, save states, widescreen, and the native build for Path B. | Opus 5.5 effort high | Opus 5.5 effort mediumRaise to high for timing and graphics bugs. |
| Find a bug | Find the first differing frame with snesref or snes_cosim.py. Then prove the cause from the ROM. | Opus 5.5 effort highAfter two failed tries with full evidence, move to Fable 5.2. | Opus 5.5 effort highOne bug at a time. |
| Check the work | A fresh session re-runs every route and the checker. It hunts for edited hashes, scene gates and faked hardware replies. | Opus 5.5 effort mediumAlways a new session, never the one that did the work. | Sonnet 5.5 effort highAlways a new session, never the one that did the work. |
| Keep the records | Update PROGRESS.md, the routine ledger, notes/findings.md and the dated bring-up log. | Haiku 5.5 effort medium | Haiku 5.5 effort medium |
How many sessions at once
Max 20x (now called Ultra)
Run one lead session plus three or four workers. The snesrecomp owner allows up to three agents at once on framework work, one item each, in separate worktrees. Give each worker its own worktree, one route or one routine, and its own build folder. Only one worker may drive a live game run at a time.
Max 5x (now called Max)
Run one lead and one or two workers. Spend your limit on debug and hard jobs. Queue bulk rewrites for overnight runs with claude -p.
Lines for this project's CLAUDE.md
- Read `SCOPE.md`, `PROGRESS.md` and `notes/findings.md` before any change. - The one check is `./check.ps1`. A task is done only when its output is pasted in the report. - Never edit `src/gen/` or `recomp/funcs.h`. Fix `recomp/*.cfg`, `recomp/symbols.toml` or host code, then run `tools/regen.sh`. - Never edit the `snesrecomp/` submodule in place. Framework changes go in `patches/` as named patch files. - The ROM is the only source of truth. If you cannot show it from the disassembly, a trace or the reference emulator, write UNKNOWN and stop. - Never fake a hardware reply, write an expected result into game RAM, or add an `if` on a scene number to get further. - Never change expected hashes, route files or `rom_identity.txt` to make a check pass. - Never commit ROMs, saves, extracted art, audio or generated C. Run `git status` before each commit. - Fix unresolved jump targets before any other bug after each run. - Write each finding in `notes/findings.md` with the ROM address, the evidence command and the result. Write dead ends too. - In a worktree, use absolute paths and your own build folder. Do not touch other worktrees. - Report unverified work as unverified. Start every report with DONE, PARTIAL or BLOCKED.
Keep the context small
- Give Claude a ROM address and a ledger row, not pages of disassembly. Let it open the lines it needs.
- Keep generated C out of the chat. DKC3's first run made 61 MB of C.
- Use a subagent to read long traces. It should report only the first differing frame and address.
- Run
/clearbetween units. Facts live innotes/findings.md, so nothing is lost. - Do not trust a summary from an older session. Check the fact again with a dump before you build on it.
More prompts for this system
Each step above has its own prompt. These extra prompts cover the rest of the work. Fill in the parts in <ANGLE_BRACKETS>.
Scope and feasibility
Before any work, to learn if your game can be done and how.
GOAL: Tell me if <GAME> (<REGION>, <REVISION>) can be ported with `snesrecomp`, and if a full C rewrite is realistic. End with a draft `SCOPE.md`. READ FIRST: `D:/ROMs/<GAME>.sfc` (path only), the `snesrecomp` README (Games and ROM compatibility tables), the RecompLauncher page for <GAME>, GitHub search results for '<GAME> disassembly'. FENCE: Edit only `SCOPE.md`. Do not clone, build or install anything. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `python tools/new_project/probe_rom.py 'D:/ROMs/<GAME>.sfc'`. Done means `SCOPE.md` lists mapping, coprocessor, chip support status, existing ports, disassemblies with license and match proof, the chosen path and a first milestone with a golden run. Every claim has a link or command output. BUDGET: 45 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: DONE, then the probe output. It names the chip status in plain words, such as 'Super FX: supported'. It lists real links. It says plainly if the cart is not supported.
Map the binary
After setup, to build the routine ledger and the config inputs for one bank.
GOAL: Build `notes/routines.csv` rows for bank <BANK>: address, name, size, M/X entry widths, emit status and the source of each fact. READ FIRST: `recomp/bank<BANK>.cfg`, `recomp/symbols.toml`, the disassembly labels for bank <BANK>, the analyzer manifest from the last regen. FENCE: Edit only `notes/routines.csv` and `recomp/symbols.toml`. Never edit `src/gen`. Do not guess widths or targets. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `& 'C:\Program Files\Git\bin\bash.exe' tools/regen.sh --rom 'D:/ROMs/<GAME>.sfc'`. Done means no new warnings, and every row has an address and a cited source. BUDGET: 1 hour. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: DONE with the row count and the regen output. Routines with an UNKNOWN width or target are listed, each with the reason.
Path A unit: one divergence
For each bug in the Path A grind.
GOAL: Make route `<ROUTE>` match the reference past frame <FRAME>. READ FIRST: `CLAUDE.md`, `notes/findings.md`, `routes/<ROUTE>.txt`, the `snesref` and port dumps in `out/ref/<ROUTE>/` and `out/port/<ROUTE>/`. FENCE: Edit only `recomp/*.cfg`, `recomp/symbols.toml`, `src/game_rtl.c` and `notes/findings.md`. Never edit `src/gen`, the submodule, routes or hashes. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `./check.ps1 -Route <ROUTE>`. Done means the first WRAM difference is past frame <FRAME> and every other route still passes. BUDGET: 90 minutes, or 3 changes that do not move the first difference. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: DONE or PARTIAL with the old and new first-difference frame, the ROM address of the cause, and the cfg line that fixed it.
Path B unit: one routine
For each routine in the Path B loop.
GOAL: Rewrite `<NAME>` at `<ADDRESS>` as readable C that passes the routine checker. READ FIRST: Its ledger row, its disassembly lines, the C of its callees, `notes/quirks.md`. FENCE: Edit only `src/<SYSTEM>.c` and the ledger row. No inline assembly, no copied ROM bytes, no calls to original code, no checker edits. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `bash tools/check.sh 2000 10`. Done means 0 mismatches for `<NAME>` in play and fuzz modes, and no new mismatch anywhere else. BUDGET: 5 tries, each with one new idea. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: DONE with the checker summary line. Any odd original behavior that was copied is named in notes/quirks.md.
Batch dispatch
In the lead session, to hand out the next set of units.
GOAL: Pick the next <N> units and start one worker per unit, each in its own worktree. READ FIRST: `notes/routines.csv` (or `routes/` for Path A), `PROGRESS.md`, `notes/parking-lot.md`. FENCE: Edit only `PROGRESS.md`. Workers follow the unit card. Never give two workers the same file or the live game run. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means each worker report starts with DONE, PARTIAL or BLOCKED and holds pasted check output. Re-run the check on the merged branch after each merge. BUDGET: Stop after <N> units, or when two merges fail the merged-branch check. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A table of unit, worker, outcome and merged-branch check. Failed units go back to the queue with notes.
Debug with evidence
When something crashes, freezes or draws wrong and the cause is not known.
GOAL: Find the cause of <SYMPTOM> in route `<ROUTE>`. Do not fix it yet. READ FIRST: `notes/findings.md`, the route file, the last logs, `snesrecomp/docs/TRIPWIRES.md`. FENCE: Edit only `notes/findings.md`. You may add temporary trace switches that default to off. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Prove the cause with a trace or memory dump from both the port and the reference. Done means one cause, one ROM address and one command that shows it. BUDGET: 1 hour, or 3 theories ruled out. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A short cause statement with the frame, the address and both traces. It lists the theories ruled out.
Verify and hunt for cheating
After each batch, in a fresh session with no memory of the work.
GOAL: Check that the work in commits <RANGE> is real. READ FIRST: `CLAUDE.md`, `git diff <RANGE>`, `PROGRESS.md`. FENCE: Read only. Edit only `notes/verify-<DATE>.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Re-run `./check.ps1` and `ctest --test-dir build -C Release --output-on-failure`. Look for edits in `src/gen` or `snesrecomp/`, changed hashes or routes, scene-number `if`s, faked hardware replies, values written into game RAM, disabled tests and files outside the fence. Done means a list of findings with file and line. BUDGET: 1 hour. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: PASS or FAIL per rule, with file and line for each problem, and the pasted check output.
Status report
Once a week, or before you plan the next block of work.
GOAL: Give me a status report from the ledger files only. READ FIRST: `PROGRESS.md`, `notes/routines.csv`, `routes/`, the last check output. FENCE: Read only. Do not run long jobs. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means numbers: routines compiled vs interpreted (Path A) or verified (Path B), routes passing, open bugs, and the next three units. BUDGET: 15 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A short table with counts and dates. No praise words. Unknown numbers are marked unknown.
Session handoff
At the end of a session, so a fresh one can pick up.
GOAL: Write what the next session needs into the ledger files. READ FIRST: `PROGRESS.md`, `notes/findings.md`, `git status`, this session's check outputs. FENCE: Edit only `PROGRESS.md`, `notes/findings.md` and `notes/parking-lot.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means `PROGRESS.md` holds what works with proof, what is half done, dead ends, the exact next unit card, and the branch and worktree in use. BUDGET: 15 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A short update where every claim points to a command or file. A fresh session could start from it alone.
Blocked or cannot deliver
When a unit keeps failing, or a chip or feature may be out of reach.
GOAL: Tell me plainly whether <GOAL> can be done with the current tools, and what the options are. READ FIRST: `SCOPE.md`, `notes/findings.md`, the `snesrecomp` ROM compatibility table, the failed attempts in `PROGRESS.md`. FENCE: Read only. Edit only `notes/blocked-<TOPIC>.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means one answer, CAN, CANNOT or UNKNOWN, with the evidence, what was tried, and two or three options with their cost in time. BUDGET: 30 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A one-word answer first, then evidence. It never says 'should work'. It names the missing chip, tool or fact.
Scope change request
When Claude finds that a fix needs files outside its fence, such as the framework.
GOAL: Ask me before you leave the fence for <TASK>. READ FIRST: `SCOPE.md`, the current task card, `notes/findings.md`. FENCE: Edit nothing until I answer. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means a request that names the files to change, why, the risk to other games or routes, and how you will check it. BUDGET: 10 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what blocked you, what you tried, and what you need from me. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
A good answer: A short request that waits for a yes or no. Framework changes come as a patch file in patches/.
Keep Claude on task
These are the detours Claude tends to take on this system, and the rule that stops each one. The full method is on Stay on Task.
| The detour | The rule to give Claude |
|---|---|
Claude patches the generated C in src/gen to fix a bug fast. The next regen wipes the fix out. | Never edit src/gen/ or recomp/funcs.h. Fix the cfg, symbols.toml or host code, then regenerate. A hook blocks the edit. |
| Claude fakes a hardware reply or a game event so the boot gets one screen further. | Never replace missing hardware with a guessed success. Report it as unverified and stop. DKC2's rules say the same. |
Claude adds an if for one scene, or a guess that looks right, instead of the real mechanism. | No scene-number gates and no tuning by eye. Find the ROM flag or routine that does it, and cite its address. Belthasar lists real cases. |
| Claude turns a red test green by changing its expected value or making a timeout longer. | Never re-pin a hash, route or timeout to pass. Only a change you approved, backed by the oracle, may update a baseline. |
| Claude widens a jump-table contract to raise the compiled-code count. | Never add a jump target or function bound without disassembly proof. The interpreter stays the judge of what is correct. |
| Claude builds on a fact from an old summary or memory note that was wrong. | A memory note is not evidence. Check the fact again with a dump before you use it. DKC3 lost time to a wrong summary. |
| Claude writes the expected result into game RAM so a test passes. | Never write test outcomes into guest RAM. F-Zero's plan names this as forbidden. |
Claude edits the pinned snesrecomp submodule directly, and other games break. | Framework changes go in patches/ as named patch files, tested on more than one game, and only after you approve. |
| Claude fills the disk with trace logs and test captures. | Keep scratch data in one folder with a size budget. Star Fox Enhanced set 1 GiB and a 20 GiB free-space floor. |
Problems other projects hit
Code reached through tables of addresses was missing from the config. It ran on the interpreter. In DKC2 it hit the step cap and ran at 1 to 3 frames per second.
Fix: After every run, list unresolved jump targets first. Add each one to the bank cfg with proof, then regenerate.
Seen in: DKC2Recomp, DKC1 Recomp, Super Castlevania IV, Super Mario World 2: Yoshi's Island
A plain disassembler turned 16-bit code into garbage. It did not know the M and X widths, or the direct page base.
Fix: Always pass the M and X widths. Take them from a trace or from a disassembly that rebuilds the ROM.
Seen in: Belthasar, DKC1 Recomp
Some games run their logic inside the NMI handler, a routine the console calls each frame. The interpreter spun or froze there. A WAI wait did not halt as it should.
Fix: Support nested NMI waits and a real WAI halt in the framework. Keep each fix as a named patch with a note on the game behavior.
Seen in: Super Castlevania IV, Super Mario World 2: Yoshi's Island, DKC2Recomp
Save states kept memory but not the CPU's place or the picture chip's latches. Loading one ran the wrong code or broke graphics.
Fix: Save the CPU resume point and all PPU port state. Test by loading in a fresh process and comparing 180 frames.
Seen in: Super Castlevania IV, Super Mario World 2: Yoshi's Island, TMNT IV: Turtles in Time PC
Checks passed while the game was wrong. A soak passed with a garbled last frame. A test enforced the wrong value. Exit codes said OK on a mismatch.
Fix: Check printed results, not exit codes. Give each test a planted bug that must make it fail. Compare every frame, not every 12th.
Seen in: FZeroSNESRecomp, Star Fox Enhanced, Belthasar, DKC3Recomp
HiROM games broke LoROM rules in the framework, such as interrupt vectors and save RAM windows. A patched ROM read the wrong bytes.
Fix: Confirm the mapping from the ROM header first. Test each mapping with its own route.
Seen in: DKC2Recomp, DKC1 Recomp
The wrong ROM revision gave different code, or a copied launcher still held another game's hash.
Fix: Keep one rom_identity.txt that the build, regen and launcher all read. Refuse any other dump.
Seen in: Mega Man X Recomp, DKC3Recomp, Super Castlevania IV
Widescreen showed more than the game expected. Objects vanished, popped in or ran early, because the game only builds what is near the screen.
Fix: Keep the original 256-pixel center exact. Add the wide view as an extra pass, and test each level with its own route.
Seen in: Super Mario All-Stars PC Port, Phase Distorter, DKC1 Recomp
Picture timing bugs: the renderer used the newest tiles for every line, and HDMA splits landed one line late.
Fix: Log VRAM, palette and sprite writes per scanline. Compare register traces, not just pictures.
Seen in: Super Mario World 2: Yoshi's Island, Super Castlevania IV, FZeroSNESRecomp
On Windows, deep build folders went past the 260-character path limit.
Fix: Clone into a short path such as D:\SNESDev.
Seen in: Belthasar
How long it takes
| Max 20x (now called Ultra) | Max 5x (now called Max) | One person, no AI | How sure | |
|---|---|---|---|---|
| Path A: running on PC | 2 to 8 weeks | 5 to 20 weeks | 6 to 18 months | medium confidence |
| Path B: full decomp | 3 to 9 months | 7 to 22 months | 2 to 5 years | low confidence |
Read this first
All ranges assume one medium-sized game and one person giving 10 to 15 hours a week. Path A numbers come from many dated AI-assisted SNES recomps. But most were made by the framework's own authors, or with a ready disassembly, so a newcomer should expect the upper end. Few of them claim a fully checked game. Path B rests on only two AI-assisted projects of very different sizes, so its confidence is low. A small game took nine days, with a disassembly and a recomp port ready. A large one is still unfinished after five months. The no-AI numbers come from snesrev projects and a PS1 recomp, because no SNES recomp predates agents. Treat every number as a rough guide.
What makes it faster or slower
- Whether a disassembly that rebuilds the ROM exists. DKC1 ran on day one because it had one.
- Whether a sister game is already ported. DKC1 and DKC3 reused DKC2's layout and tools.
- The cartridge chip. Plain LoROM or HiROM is quick. Unsupported chips may block the port.
- How many jump tables and odd stack tricks the game uses. Each one needs proof.
- Game size for Path B. Harvest Moon has 778 routines. A big RPG has many more.
- How strict your checks are. Hash-based replays find bugs early. Checks by eye find them late.
The facts behind these numbers
| Project | What happened | Link |
|---|---|---|
| DKC1 Recomp | First commit 2026-08-15. Bring-up log says the game ran the same day. First release 2026-08-27. One contributor. Agent files present. | source |
| DKC3Recomp | Repo created 2026-09-03 and booted in a headless run that day. First release 2026-09-04. At first generation 3,034 of 4,757 variants were compiled; the rest ran on the interpreter. | source |
| DKC2Recomp | First commit 2026-07-15. Version 0.0.1 on 2026-07-19. Public release 2026-08-31. Three contributors. Still alpha on 2026-09-13. | source |
| Mega Man X Recomp | First commit 2026-05-22. First release 2026-10-06. 825 commits, 5 contributors. The framework grew during the same months. | source |
| Super Castlevania IV and Yoshi's Island (mpolizel) | Each released version 0.1.0 on the day of its first commit (2026-11-02 and 2026-11-03). Both now play their first stage. Most code still runs on the interpreter. Developer notes say Claude was used. | source |
| HarvestMoonSnesDecomp | First commit 2026-10-20 with 7 routines verified. The 100% commit (778 of 778 routines) and the first release are both dated 2026-10-29. 244 commits, 2 contributors, made with AI help. | source |
| Belthasar (Chrono Trigger) | Work began 2026-06-04 in private. Public first commit 2026-10-11, release 2026-11-13. Still not verified playable start to finish. Written with Claude Code. | source |
| snesrev/zelda3 | First public commit 2022-08-11, release 2023-08-17. No AI stated. About 70k to 80k lines of C. Work before the first commit is unknown. | source |
| snesrecomp author (PS1 and SNES recomps) | Writes that a first game can take weeks to months, and later games days to weeks, on the same framework. | source |
Projects reviewed (17)
RecompLauncher lists 84 projects for 61 games. We took the top-starred project for each of the top 12 games. We added three where the developer says AI was used. Two more show Path B. snesrev/zelda3 comes from outside the list. HarvestMoonSnesDecomp is the only finished AI-assisted C rewrite we found.
What each project teaches
zelda3
The Legend of Zelda: A Link to the Past
Started: 2022-08. First release: 2023-08. Code: C.
AI: none stated
Lesson: A full C version of an SNES game, checked against the original code each frame. Most later SNES work copies this method.
Super Mario World (snesrev)
Super Mario World
Started: 2023-05. First release: 2023-08. Code: C.
AI: none stated
Lesson: Run the original code beside your C and compare RAM every frame. A mismatch then points at the exact frame.
Zelda 3 Launcher
The Legend of Zelda: A Link to the Past
Started: 2023-02. First release: 2023-02. Code: C#.
AI: none stated
Lesson: A launcher can script a port's own build. Check the ROM hash first and log every command to one file.
Super Mario All-Stars PC Port
Super Mario All-Stars
Started: 2026-11. First release: 2026-11. Code: C++.
AI: none stated
Lesson: A port can keep the original code on an emulated CPU. A headless test tool made each widescreen fix checkable.
DKC1 Recomp
Donkey Kong Country
Started: 2026-08. First release: 2026-08. Code: C, C++ and Python.
AI: yes: AGENTS.md for Codex and other agents, plus a Claude Code skill (dkc1-tools) Agent files: AGENTS.md, .claude/skills/dkc1-tools/SKILL.md, .claude/skills/dkc1-tools/TOOLS.md.
Lesson: Starting from a disassembly that rebuilds the ROM gave every function start. The game ran on day one.
Mega Man X Recomp
Mega Man X
Started: 2026-05. First release: 2026-10. Code: C, C++ and Python.
AI: yes: catalog flag; docs mention agents, Codex temp paths and a Claude memory folder
Lesson: Keep the interpreter as the floor of truth. Compiled code must give byte-identical snapshots.
Super Metroid Launcher
Super Metroid
Started: 2023-03. First release: 2023-03. Code: C#.
AI: none stated
Lesson: Sister ports with the same build recipe let one launcher be reused fast.
DKC2Recomp
Donkey Kong Country 2: Diddy's Kong Quest
Started: 2026-07. First release: 2026-08. Code: C and Python.
AI: yes: AGENTS.md; early commits carried 'Codex' placeholder authorship Agent files: AGENTS.md.
Lesson: Prove the disassembly matches your ROM before you trust its addresses.
DKC3Recomp
Donkey Kong Country 3: Dixie Kong's Double Trouble!
Started: 2026-09. First release: 2026-09. Code: C and Python.
AI: yes: AGENTS.md; docs written as an agent work log Agent files: AGENTS.md.
Lesson: Compile what can be proven and interpret the rest. The game booted with only 64% of variants compiled.
Phase Distorter
EarthBound
Started: 2026-09. First release: 2026-09. Code: C++.
AI: none stated
Lesson: With a full source disassembly you can translate from source lines, and keep a dated record of what was tested.
Star Fox Enhanced
Star Fox
Started: 2026-08. First release: 2026-09. Code: C++.
AI: yes: README says it was ported and coded by AI (Codex) Agent files: AGENTS.md.
Lesson: Compare game state at each logic tick, not screenshots. A passing test once enforced the wrong value.
FZeroSNESRecomp
F-Zero
Started: 2026-08. First release: 2026-08. Code: C and Python.
AI: yes: catalog flag; docs written as agent hand-offs
Lesson: Bisect a bad routine by forcing it back to the interpreter from a text list, with no rebuild. The repo is now named F-ZeroForever.
Belthasar
Chrono Trigger (SNES)
Started: 2026-10. First release: 2026-11. Code: C and Python.
AI: yes: README says much of it was written with Claude Code Agent files: CLAUDE.md, .claude/no-invention-mandate.md, .claude/settings.json, .claude/hooks/session-start.sh.
Lesson: A strict 'no invention' rule plus an emulator oracle keeps agents honest. A big RPG still takes many months: private work began 2026-06.
Harvest Moon Decomp
Harvest Moon
Started: 2026-10. First release: 2026-10. Code: C.
AI: yes: README says it was made with the help of AI
Lesson: Every routine in C, each checked against the original on the same memory. A small game reached 100% in nine days.
Super Mario World 2: Yoshi's Island
Super Mario World 2: Yoshi's Island
Started: 2026-11. First release: 2026-11. Code: C.
AI: yes: README says AI-assisted reverse engineering; developer note names Claude
Lesson: Keep each framework fix as a named patch with a note on the symptom and cause.
TMNT IV: Turtles in Time PC
Teenage Mutant Ninja Turtles IV: Turtles in Time
Started: 2026-10. First release: 2026-10. Code: C.
AI: yes: developer note says ChatGPT helped
Lesson: Keep the ROM identity in one file, and prove save states by loading them in a fresh process.
Super Castlevania IV
Super Castlevania IV
Started: 2026-11. First release: 2026-11. Code: C.
AI: yes: README says AI-assisted reverse engineering; developer note names Claude
Lesson: Count how many test frames match Snes9x and report that number each release.
What we could not check
- How much of EarthBound was written in C. The ebsrc to-do list names a VUCC compiler, but the share and version are unknown.
- Whether any other SNES game used a C compiler. The sources read say most games were hand-written assembly.
- Script names in the prompts, such as
tools/make_ledger.py,tools/mutate.pyandcheck.ps1, are scripts you write. Only Harvest Moon'stools/check.shexists in a reviewed repo. - HarvestMoonSnesDecomp's own check scripts were not run here. Its 100% figure is the README's claim.
- The time ranges for a newcomer. All dated SNES recomps were made by experienced people or with ready disassemblies.
- The shared HLE rules repo linked from the snesrecomp AGENTS.md returned 404, so it could not be read.
- The framework fork used by the TMNT IV port is private. Its build could not be checked.
- Mesen was not used by any reviewed project. It is listed only as a hand debugging aid.
- No reviewed SNES project used an MCP server, so none is listed.
- The
snesrecompscaffold steps were read, not run, on this machine. No ROM was used. - Linux builds of Path A in WSL were not tested here. Several cards document them.
- The CPU clock speed was not confirmed in the pages read, so it is left out.
- The scripted boot and route runs (
--script,SNESRECOMP_DUMP_DIR) were read in the framework source, not run here. - Whether port dumps and
snesrefdumps match byte for byte at the sameuntilpoint was not tested. Timing may differ by a frame. - Which download holds a Windows
bsnes_libretro.dllcore was not confirmed. - The AOT deny gate variables were found in the framework code and the F-Zero card. They were not tried on a new scaffold.
- The co-sim tool
tools/snes_cosim.pyneeds a game-specific co-sim build. A new scaffold may not have one, so the guide does not rely on it. - The
ebsrchelper tools (ebbinex,spcasm) were not installed or tried.
Sources
- snesrecomp README (RetroPortingToolKit)
- snesrecomp: Your first SNESRecomp port
- snesrecomp AGENTS.md
- snesrev/zelda3 README
- HarvestMoonSnesDecomp README
- HarvestMoonSnesDecomp DECOMPILATION.md (method)
- ebsrc README
- Asar README
- Asar manual (command line usage)
- DiztinGUIsh README
- MesenCE README
- SingleStepTests 65816
- LakeSnes
- Snes9x releases
- cc65 README
- ghidra-snes-loader (unmaintained)
- SNESdev Wiki: ROM header
- SNESdev Wiki: Memory map
- SNESdev Wiki: MMIO registers
- SNESdev Wiki: 65C816
- SNESdev Wiki: S-SMP
- SNESdev Wiki: Backgrounds
- Rust install page
- MSYS2
- DKC1Recomp bring-up log
- DKC3Recomp bring-up log
- snesref README (reference frontend and script format)
- snesrecomp: Setting up a game project
- snesrecomp host options (host_args.c)
- SDL release 2.30.9