Skip to the page
It's Decomplicated
Nintendo, 1990

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

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.

Go to the steps

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.

Go to the steps

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.

  1. Pick the game and check the ROM

    Choose one game and one exact ROM version. Check that snesrecomp supports its cartridge type. Look for work that already exists. Write it all in SCOPE.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 for coprocessor=none and a valid checksum.
    • Read the chip table in the snesrecomp README. Plain LoROM and HiROM games are the easy start.
    • Look for an existing port in the snesrecomp games 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 in SCOPE.md.
    Prompt for Claude
    GOAL: 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 the APPROVED: 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.txt file)

  2. 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.exe from rust-lang.org. The analyzer needs Rust 1.85 or newer.
    • Open Developer PowerShell for VS 2022. Run git --version, python --version, cargo --version and cmake --version.
    • Keep ROMs in a folder like D:\ROMs. Add *.sfc, *.smc and src/gen/ to .gitignore.
    • Write CLAUDE.md, PROGRESS.md, notes/parking-lot.md and one check script, check.ps1.
    Prompt for Claude
    GOAL: 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, and check.ps1 runs 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)

  3. 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/gen and 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 as D:\SNESDev\MyFirstPortSNESRecomp.
    • Check that src\gen holds .c files and that rom_identity.txt and CMakeLists.txt exist.
    • 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 Claude
    GOAL: 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.exe prints True after 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)

  4. Map the code into the config files

    Make a ledger of every routine. Feed known starts, names and jump targets into recomp/symbols.toml and recomp/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 = false keeps it interpreted. emit = true compiles 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.csv with address, name, size, status and the source of each fact.
    Prompt for Claude
    GOAL: 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.csv lists 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)

  5. 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.txt in the shared script format. One command per line: wait 3600, then dump title, then quit.
    • 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.bin and title.fb.bmp.
    • Prefer until <addr> == <value> over a fixed wait. 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 in src/gen.
    • Run it twice. Get-FileHash out\port\title.wram.bin must give the same hash both times.
    Prompt for Claude
    GOAL: 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, and title.wram.bin has 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)

  6. 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, until and dump <tag> lines. Save it in routes\.
    • Build snesref: extract SDL2-devel-2.30.9-VC.zip to tools\snesref\SDL2-2.30.9, then cd tools\snesref and .\build.bat. Put SDL2.dll beside snesref.exe.
    • Run the reference with SNESREF_HEADLESS=1, SNESREF_WRAM_FILL=0, SNESREF_SCRIPT=<route> and SNESREF_DUMP_DIR=out\ref set. 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.bin files with Get-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 by SNESRECOMP_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 = true one at a time. Rerun every route after each one.
    Prompt for Claude
    GOAL: 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.bin from the port has the same SHA-256 as the one from snesref.

    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)

  7. 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-failure after 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 Claude
    GOAL: 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)

  8. 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 in patches/.
    • Package with scripts/package_release.sh. It refuses to package when it finds ROM data. Make CI fail if src/gen files appear, as Super Castlevania IV does.
    • Include THIRD_PARTY_ATTRIBUTION.md in every package. snesrecomp itself is PolyForm Noncommercial.
    • Run git status before each commit. No ROMs, saves, art or generated code may go in.
    Prompt for Claude
    GOAL: 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.sh succeeds, and a listing of the zip shows no .sfc, .smc or src/gen file.

    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.

  1. 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: SMWDisX for Super Mario World, ebsrc for EarthBound, HM-Decomp for 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/zelda3 or snesrev/smw.
    • Write in SCOPE.md what done means: every routine checked, and the game plays on your C alone.
    Prompt for Claude
    GOAL: 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 the APPROVED: line yourself.

    Proof this works: HarvestMoonSnesDecomp (built on the HM-Decomp disassembly), Belthasar (Chrono Trigger; follows the zelda3 method), https://github.com/Herringway/ebsrc

  2. 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>. Get asar191.zip from the Asar releases page.
    • Other disassemblies list their own build steps and helper tools in their README. For example ebsrc needs ca65 v2.19, ebbinex, spcasm and GNU make. Follow that README exactly.
    • Compare hashes: Get-FileHash -Algorithm SHA256 out.sfc must 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 .asm from Diz and rebuild it until the hash matches.
    Prompt for Claude
    GOAL: 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

  3. 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 snesrecomp port. 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_M1X0 to GetRNG_M1X0 with 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 Claude
    GOAL: 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 --check exits 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

  4. 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 Claude
    GOAL: 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 (--sweep modes run one ROM routine over generated inputs)

  5. 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>.c with 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 Claude
    GOAL: 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)

  6. 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 ChangeStamina reads a flag set by its caller.
    • Track progress with a script, like Harvest Moon's tools/progress.py.
    Prompt for Claude
    GOAL: 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

  7. 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. zelda3 compares 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 Claude
    GOAL: 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)

  8. 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 in native/.
    • 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 snesrecomp chips unchanged.
    • Run the golden routes. RAM hashes and frames must match the checked build.
    Prompt for Claude
    GOAL: 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)

  9. 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 Claude
    GOAL: 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

ToolWhat it doesHow to get itHow 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.gitREADME, 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/winsnesrecomp 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 python3snesrecomp 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 | shrust-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-buildbuild 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.9snesrecomp 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 pageMesenCE 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.19cc65 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 pageREADME 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/65816README (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

skills.sh

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

skills.sh

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

skills.sh

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

skills.sh

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

skills.sh

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

skills.sh

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

skills.sh

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

built-in

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)

write-your-own

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)

write-your-own

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.

JobWhat it means on this systemMax 20x (now called Ultra)Max 5x (now called Max)
Plan the projectPick the ROM revision, check the chip table, and find ports and disassemblies. Write SCOPE.md.Fable 5.2
effort high
One session. This choice shapes months of work.
Opus 5.5
effort high
Use Fable 5.2 for this one session if you have weekly room.
Set up the projectInstall 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 fileImport 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 medium
Raise to high for function edges and data layouts. A mistake there spreads.
Bulk unitsPath A: promote routines to emit = true one by one. Path B: rewrite leaf routines that pass the checker.Sonnet 5.5
effort medium
Haiku 5.5 for the plainest units.
Sonnet 5.5
effort medium
Fewer workers at once. Haiku 5.5 for the plainest units.
Hard unitsRoutines 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 high
Go to xhigh only after a failed try at high.
Opus 5.5
effort high
Send only the last few that still fail to Fable 5.2.
Build the runtimeHost 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 medium
Raise to high for timing and graphics bugs.
Find a bugFind the first differing frame with snesref or snes_cosim.py. Then prove the cause from the ROM.Opus 5.5
effort high
After two failed tries with full evidence, move to Fable 5.2.
Opus 5.5
effort high
One bug at a time.
Check the workA fresh session re-runs every route and the checker. It hunts for edited hashes, scene gates and faked hardware replies.Opus 5.5
effort medium
Always a new session, never the one that did the work.
Sonnet 5.5
effort high
Always a new session, never the one that did the work.
Keep the recordsUpdate 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

Add to 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 /clear between units. Facts live in notes/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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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.

Prompt for Claude
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 detourThe 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 AIHow sure
Path A: running on PC2 to 8 weeks5 to 20 weeks6 to 18 monthsmedium confidence
Path B: full decomp3 to 9 months7 to 22 months2 to 5 yearslow 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

ProjectWhat happenedLink
DKC1 RecompFirst 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
DKC3RecompRepo 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
DKC2RecompFirst 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 RecompFirst 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
HarvestMoonSnesDecompFirst 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/zelda3First 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

From outside RecompLauncherreimplementationplayable
LakeSnesSDL2TCCPython

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

Top rated on RecompLauncherreimplementationplayable
LakeSnesSDL2TCCmake

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

Top rated on RecompLauncherothercomplete
C#.NET Windows FormsTCCSDL2

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

Top rated on RecompLauncheremulator-basedplayable
own SNES coreCMakeMSVCDirect3D 11

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

Top rated on RecompLauncherstatic recompplayable
snesrecompIDAasarMSVCCMakeSDL2

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

Top rated on RecompLauncherstatic recompplayable
snesrecompCMakeNinjaSDL3

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

Top rated on RecompLauncherothercomplete
C#.NET Windows FormsTCCSDL2

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

Top rated on RecompLauncherstatic recompplayable
snesrecompAsar 1.91Snes9xCMakeSDL2

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!

Top rated on RecompLauncherstatic recompin progress
snesrecompCMakeMSVCSDL2

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

Top rated on RecompLauncherstatic recompplayable
ebsrcca65ld65CMakeSDL2

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

Top rated on RecompLauncherport of a decompplayable
UltraStarFoxretro_cpusnes_spcSDL3CMake

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

Top rated on RecompLauncherstatic recompplayable
snesrecomprecomp-uiCMakeNinjaCTest

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)

Top rated on RecompLauncherreimplementationin progress
LakeSnesown disassemblerCMakeMSVCSDL2

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

Added: real decomp workreimplementationplayable
HM-DecompsnesrecompCMakeSDL3

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

Added: developer used AIstatic recompin progress
snesrecomprecomp-uiCMakeclang

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

Added: developer used AIstatic recompplayable
SNESRecomp (private fork)CMakeMSVCSDL3Inno Setup

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

Added: developer used AIstatic recompin progress
snesrecomprecomp-uiCMakeclang

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.py and check.ps1, are scripts you write. Only Harvest Moon's tools/check.sh exists 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 snesrecomp scaffold 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 snesref dumps match byte for byte at the same until point was not tested. Timing may differ by a frame.
  • Which download holds a Windows bsnes_libretro.dll core 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.py needs a game-specific co-sim build. A new scaffold may not have one, so the guide does not rely on it.
  • The ebsrc helper tools (ebbinex, spcasm) were not installed or tried.

Sources