Game Boy Advance decomp guide
A shared recompiler runs many games on PC, and finished matching decomps show the way.
What this system is like
The Game Boy Advance is one of the friendliest systems for this work. Its chip is a simple ARM CPU. Its games are small, from 4 to 16 MB. One free framework, gbarecomp, already runs more than a dozen games on PC.
For Path A you use gbarecomp. It turns the game's machine code into C++ and adds a stand-in for the console. Most of your work is telling it about code the game copies into RAM. Then you prove that a test route runs with no gaps.
For Path B you write C that the old compiler, agbcc, turns back into the same bytes. Many GBA decomps are done or close, so check first. The port then compiles that C for PC with a small console layer, as Project Picori and ReKHCoM did.
Path A runs on Windows. Path B needs WSL for the matching build. Nine of the fourteen projects reviewed here say they used AI. The other five have only a store flag.
One shared recompiler
Nine of the fourteen reviewed projects use gbarecomp. Each game repo is tiny: a game.toml file, a ROM hash file, a few source files and a script. The engine does the hard part.
Code that hides in RAM
GBA games copy some code from the cartridge into fast RAM at boot. A plain scan of the ROM never sees it. You must list each copied block in game.toml as [[code_copy]], or the game falls back to slow code or a black screen.
The BIOS matters
The BIOS is the small built-in program that starts the console. gbarecomp recompiles your own BIOS dump too. Interrupts enter the BIOS and return into the middle of game functions. Those return points need their own entries.
Finished decomps exist
Pokemon Emerald, FireRed, Minish Cap and Chain of Memories all have matching decomps. Recomps use them for function names only. Ports compile their C directly. Always look for one before you start.
Two compilers in one ROM
Most game code was built with agbcc. The SDK sound driver often used an older build, old_agbcc. A matching project must use the right one for each file.
Two paths
Get it running on PC
You feed your own ROM and BIOS to gbarecomp. It writes C++ for every function it can find. A shared runtime acts as the console: graphics, sound, timers, saves and input. You add a small host program and a game.toml that describes your game. Code it cannot find runs slowly through an interpreter, and the log tells you where to look.
Full decomp for porting
You split the ROM into one assembly file per function. Then you replace each one with C that agbcc turns into the same bytes. make compare rebuilds the whole ROM and checks its SHA-1. When every function is C, you build the same source for PC with a small layer for graphics, sound and input.
Path A: Get it running on PC
You feed your own ROM and BIOS to gbarecomp. It writes C++ for every function it can find. A shared runtime acts as the console: graphics, sound, timers, saves and input. You add a small host program and a game.toml that describes your game. Code it cannot find runs slowly through an interpreter, and the log tells you where to look.
Method: static recompilation
Pick this first for almost every GBA game. It is the fastest way to a native PC build, and the framework is free and active. Pick Path B only if you want readable source or a port to new hardware.
Pick the game and check for prior work
You choose one game and one exact ROM version. A hash is a short fingerprint of a file. It proves which version you have. Then you look for an existing port or decomp, and you write
SCOPE.md.- Hash your own dump in PowerShell:
Get-FileHash -Algorithm SHA1 <ROM>. - Run
luvdis info <ROM>to see if the dump is a known good copy. - Check the game list in the
gbarecompREADME and on RecompLauncher. Many games already have a port. - Search GitHub for a decomp or disassembly of your game, such as
pret/pokeemerald,zeldaret/tmcorPheenoh/khcom. A decomp gives you function names for free. - Write
SCOPE.md. Give the ROM SHA-1, the technique (gbarecomp) and the first milestone (a strict-static boot route). List what is out of scope (widescreen, netplay) and what Claude must never edit.
Prompt for ClaudeGOAL: Decide if <GAME> can be brought up on gbarecomp, and draft SCOPE.md. READ FIRST: the gbarecomp README game list, docs/GETTING_STARTED.md, and my ROM hash <SHA1>. FENCE: Edit only `SCOPE.md` and `notes/prior-work.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. Do not download any ROM, BIOS or game data. CHECK: `SCOPE.md` must name the SHA-1, the region and revision, the technique, the first milestone and its check, the out-of-scope list and the never-edit list. Done means every one of those fields is filled with a fact and its source. BUDGET: Stop after 45 minutes or 20 web lookups. 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: list each existing port, decomp or disassembly you found, with its URL and the ROM hash it targets. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenSCOPE.mdnames the ROM SHA-1, the technique and the first milestone, and you have approved it.Proof this works: https://github.com/mstan/gbarecomp/blob/main/docs/GETTING_STARTED.md, Dragon Ball Z: Buu's Fury Recomp (baserom.md records size, CRC32, MD5, SHA-1 and SHA-256)
- Hash your own dump in PowerShell:
Install the Windows tools and build the recompiler
You set up a C++ toolchain on Windows and build
gba_recompile, the tool that writes the C++. You also make the game repo, with the engine and launcher as git submodules. A submodule is another repo pinned inside yours at one exact version.- Install MSYS2 from msys2.org. In the MSYS2 MINGW64 shell run
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2. - Add
C:\msys64\mingw64\binto your PATH. Run all builds from PowerShell, not from Claude's Bash shell. - The game scripts run with
pwsh, which is PowerShell 7. Windows 11 ships only the older PowerShell 5.1. Install it withwinget install --id Microsoft.PowerShell --source winget. - Make the repo, then run
git submodule add https://github.com/mstan/gbarecomp.git gbarecompandgit submodule add https://github.com/RetroPortingToolKit/recomp-ui.git recomp-ui. - Run
git submodule update --init --recursive. Thegbarecomprepo has submodules of its own, and they must be there too. - Build the recompiler:
cmake -S gbarecomp -B gbarecomp/build -G Ninja, thencmake --build gbarecomp/build --target gba_recompile. - Put your ROM in
roms/and your own BIOS dump atgbarecomp/bios/gba_bios.bin. Addroms/,generated/, saves and the BIOS to.gitignore. - Write
tools/regen.ps1. It hashes the ROM and the BIOS, stops on a mismatch, then runsgba_recompilefor the BIOS and for the ROM.
Prompt for ClaudeGOAL: Make the repo build `gba_recompile` and give it a hash-gated `tools/regen.ps1`. READ FIRST: `SCOPE.md`, `gbarecomp/README.md`, `gbarecomp/CLAUDE.md`, and `tools/regen.ps1` from https://github.com/mstan/SuperMarioAdvance4Recomp as a pattern. FENCE: Edit only `CMakeLists.txt`, `tools/`, `.gitignore`, `baserom.md` and `CLAUDE.md`. `gbarecomp/` and `recomp-ui/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. Never copy the ROM or BIOS into Git. CHECK: Run `cmake --build gbarecomp/build --target gba_recompile` from PowerShell. Then run `pwsh tools/regen.ps1 -Rom <A_WRONG_FILE>`. Done means the first prints a built `gba_recompile.exe` and the second stops with a hash error. BUDGET: Stop after 3 failed builds with the same error. 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 last lines of both commands. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whengba_recompile.exeexists, andpwsh tools/regen.ps1refuses a file whose SHA-1 is wrong.Proof this works: Super Mario Advance 4 Recomp (regen.ps1 checks ROM and BIOS SHA-1), EmeraldRecomp (CLAUDE.md: build from PowerShell, the Bash shell breaks
cc1plus), Dragon Ball Z: Buu's Fury Recomp (CLAUDE.md: initialize both submodules before building), https://www.msys2.org/, https://learn.microsoft.com/en-us/powershell/scripting/install/install-powershell-on-windows- Install MSYS2 from msys2.org. In the MSYS2 MINGW64 shell run
Map the code and write game.toml
The recompiler must know where functions start. A decomp's symbol list is the best seed. Code the game copies into RAM is invisible to a ROM scan, so you list it by hand. You also start a ledger: a file that tracks each item and its status.
- Start
game.tomlfrom a game with similar hardware, such as Super Mario Advance 4. Set the ROM identity,aot_scan_start,aot_scan_end, the save type andcodegen_shards. Keepstatic_resume_all = true, which is the default. - If a decomp exists, build it in WSL at a pinned commit. Check that it rebuilds your exact ROM hash. Then import names with
gbarecomp/tools/symbol_import/import_decomp_symbols.py. - Keep importer output in its own overlay file. Keep
game.tomlas the hand-written base that wins conflicts. - With no decomp, run
luvdis <ROM> -o rom.s -co functions.cfg. The-cofile lists the functionsluvdisguessed. Or load the ROM in Ghidra with the GBA loader. - List each block the game copies into IWRAM as
[[code_copy]]plus[[extra_func]], with a note on how you checked it. - Start
notes/coverage.mdwith one row per seed: address, mode (ARM or Thumb), source, status.
Prompt for ClaudeGOAL: Write a first `game.toml` and an imported symbol overlay for <GAME>. READ FIRST: `SCOPE.md`, `game.toml` of https://github.com/mstan/SuperMarioAdvance4Recomp, `gbarecomp/PRINCIPLES.md`, and <DECOMP_URL_OR_NONE>. FENCE: Edit only `game.toml`, `symbols/` and `notes/coverage.md`. `gbarecomp/` and `generated/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. Import only names, addresses, sizes and ARM or Thumb mode from the decomp, never its C source. CHECK: Run `pwsh tools/regen.ps1`. Done means it finishes with no errors and `notes/coverage.md` lists every `[[code_copy]]` and `[[extra_func]]` with its source. BUDGET: Stop after 3 failed regen runs, or after 60 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 last 20 lines of regen output and the count of seeds. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenpwsh tools/regen.ps1finishes, and every hand entry ingame.tomlhas a matching row innotes/coverage.md.Proof this works: EmeraldRecomp (symbols from pret/pokeemerald, import gated on the ROM SHA-1), Mother 3 Recomp (
[[code_copy]]for IRQ handler, sound driver and sprite sort), FireRedLeafGreenRecomp (flash helper copied to the stack, black screen until declared)- Start
Generate the code and boot to the title
You build the generated C++ with a small host program. The host is your
main.cppplus launcher glue. This is the first-light test: the game should reach its title screen.- Copy
src/main.cppand the launcher boot code from agbarecompgame with similar save hardware. Change only the names and paths. - Run
pwsh tools/regen.ps1, thencmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release, thencmake --build build --target <GAME>Recomp. - Run the game with the interpreter bridge on. Watch the console for the first-miss notice.
- Run it with no window and save a picture:
build\<GAME>Recomp.exe --bios gbarecomp\bios\gba_bios.bin --rom <ROM> --frames 600 --no-window --dump-png build\title.png game.toml. These flags come from the SMA4 host code you copied. - Compare
build\title.pngwith the same moment in mGBA.
Prompt for ClaudeGOAL: Build <GAME>Recomp and reach the title screen. READ FIRST: `SCOPE.md`, `CLAUDE.md`, `src/main.cpp`, `CMakeLists.txt` and `tools/test-attract-fuzz.ps1` of https://github.com/mstan/SuperMarioAdvance4Recomp, `gbarecomp/docs/GETTING_STARTED.md`, `gbarecomp/docs/WINDOWS_GAME_SETUP.md`. FENCE: Edit only `src/`, `CMakeLists.txt` and `notes/`. `generated/`, `gbarecomp/` and `recomp-ui/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `cmake --build build --target <GAME>Recomp`. Then run `build\<GAME>Recomp.exe --bios gbarecomp\bios\gba_bios.bin --rom <ROM> --frames <N> --no-window --dump-png build\title.png game.toml`. Done means the exit code is 0 and `build\title.png` is not empty. I will look at the picture myself. Also report the dispatch miss count from the log. BUDGET: Stop after 3 failed builds with the same error, or 90 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: the exit code, the PNG path and its size, and the coverage lines from the log. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenThe headless run exits with code 0 and writes a non-emptybuild\title.pngthat shows the title screen.Proof this works: Dragon Ball Z: Buu's Fury Recomp (build steps), Super Mario Advance 2 Recomp (no symbols needed for first bring-up), Super Mario Advance 4 Recomp (
tools/test-attract-fuzz.ps1runs the exe with--frames,--no-windowand--dump-png)- Copy
Close the dispatch misses
A dispatch miss is a jump to code the static pass did not translate. The runtime logs each one. You fix the config, regenerate and run again. You never edit the generated code.
- Record a fixed route: the attract demo plus a short input file in
tests/. - Set
$env:GBARECOMP_STRICT_STATIC=1,$env:GBARECOMP_SELFHEAL_RECOMPILE=0and$env:GBARECOMP_INPUT_REPLAYto the input file. Then run the exe with--frames <N> --no-window. In strict mode the first miss stops the run. - Read
dispatch_misses.logand the proposal file,recomp_seed_proposals.toml. Check each address in mGBA or Ghidra before it goes intogame.toml. - Check that
static_resume_allis stilltrue. It lets an interrupt return at any instruction. Add other missing entry points as reviewed[[extra_func]]seeds. - Regenerate and rebuild after every config change. Old generated code does not pick up new config.
Prompt for ClaudeGOAL: Make the route `<ROUTE>` pass in strict-static mode with zero dispatch misses. READ FIRST: `CLAUDE.md`, `notes/coverage.md`, `gbarecomp/PRINCIPLES.md` (coverage honesty), the latest `dispatch_misses.log`. FENCE: Edit only `game.toml`, `symbols/*reviewed*` and `notes/coverage.md`. `generated/` and `gbarecomp/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. Never add an address you have not checked against the ROM or mGBA. CHECK: Run `pwsh tools/regen.ps1`, rebuild, then run the route with `GBARECOMP_STRICT_STATIC=1` and `GBARECOMP_SELFHEAL_RECOMPILE=0`. Done means the log holds `self_heal_coverage=FULLY_STATIC dispatch_misses=0 interpreted_insns=0` and `ppu_frames=<N>`. BUDGET: Stop after 5 regen cycles with no fewer misses. 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 coverage line. 3) Files changed, with one line per new seed and its evidence. 4) What is left. 5) New parking-lot items.
Done whenThe strict-static route log showsself_heal_coverage=FULLY_STATIC dispatch_misses=0 interpreted_insns=0.Proof this works: Super Mario Advance 4 Recomp (
tools/test-attract-fuzz.ps1, two 12000-frame routes), Super Mario Advance 2 Recomp (tools/coverage-attract.ps1), Fire Emblem: The Sacred Stones Recomp (missing entry at0x08000380, fixed by regenerating withstatic_resume_all), https://github.com/mstan/gbarecomp/blob/main/docs/TOML_SCHEMA.md (static_resume_alldefaults totrue)- Record a fixed route: the attract demo plus a short input file in
Fix wrong behavior against mGBA
Full coverage does not mean correct output. mGBA is the reference emulator, or oracle. When your build and mGBA differ, mGBA is right. You find the first frame that differs and fix the cause in the runtime or the config.
- Build the mGBA oracle. It is a separate program that wraps mGBA. Follow
gbarecomp/oracle/README.md: build mGBA 0.10.5 inthird_party/mgba/build/, then configure with-DGBARECOMP_BUILD_ORACLE=ON. - Turn on the TCP debug server: put a
debug.inifile next to your exe. Each game picks its port withGBARECOMP_DEFAULT_DEBUG_PORTinCMakeLists.txt. The oracle listens one port higher. - Replay the same input in both. The scripts in
gbarecomp/oracle/, such asfind_first_diverge.py, compare the two. - Walk the frame ring backwards to the first frame where memory differs. Later differences are only effects.
- Name the layer: code generation, hardware model or game config. Fix it there, then regenerate.
- Test saves early: save, quit, reload and compare the save file hash.
- Write each finding in
notes/findings.md: symptom, first bad frame, cause, fix, test.
Prompt for ClaudeGOAL: Find the cause of <BUG> and fix it at its source. READ FIRST: `CLAUDE.md`, `gbarecomp/DEBUG.md`, `gbarecomp/TCP.md`, `gbarecomp/oracle/README.md`, `notes/findings.md`, the input file `<INPUT>`. FENCE: Edit only <FILES_I_NAME> after I approve the cause. Until then everything is read-only. `generated/` is always read-only. Do not add features, refactors, tools or cleanups I did not ask for. No per-game special cases inside `gbarecomp/src/gba/`. CHECK: First prove the cause: name the first divergent frame and the first wrong write, with TCP output from both builds. After the fix, replay `<INPUT>`. Done means native and mGBA agree at that frame and the strict-static route still passes. BUDGET: Stop after 2 fix attempts that fail, or 90 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: the divergence evidence and the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenYour build and mGBA agree at the first divergent frame, and a route that hit the bug now passes.Proof this works: Mario Kart: Super Circuit Recompiled (saves broken until the flash chip reported the right ID), EmeraldRecomp (CLAUDE.md: mGBA is the oracle), https://github.com/mstan/gbarecomp/blob/main/DEBUG.md, https://github.com/mstan/gbarecomp/blob/main/TCP.md (
debug.ini, native port, oracle port)- Build the mGBA oracle. It is a separate program that wraps mGBA. Follow
Build a regression set and package
A regression set is a group of tests that keeps old fixes fixed. You replay recorded routes and check save hashes after every change. The release script runs those tests on the packaged files, not just on your build folder.
- Add more routes in
tests/*.input: menus, a save, a load, a boss, a scene change. - For each route, check the exact frame count, zero misses and the final save hash.
- Add CTest unit tests for your own host code, such as widescreen math.
- Make
tools/make_release.ps1run the routes on the staged files. Make it scan the package for ROM data. Never shipgenerated/. - After each
gbarecompsubmodule update, rerun every route before you commit.
Prompt for ClaudeGOAL: Add a regression suite and make the release script run it. READ FIRST: `CLAUDE.md`, `tests/`, `tools/make_release.ps1`, and `docs/SAVE_VALIDATION.md` of https://github.com/mstan/MarioKartSuperCircuitRecomp as a pattern. FENCE: Edit only `tests/`, `tools/` and `notes/`. `generated/`, `gbarecomp/` and `src/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: From a fresh clone, run regen, build, then `pwsh tools/make_release.ps1 -Version <X.Y.Z>`. Done means every route passes with zero misses, every save hash matches `tests/expected_saves.txt`, and the ROM scan finds nothing. BUDGET: Stop after 3 failed full runs. 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 summary of each route. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenOn a fresh clone, regen, build and every route pass, and the package holds no ROM-derived files.Proof this works: Mario Kart: Super Circuit Recompiled (9,839-frame save route, same save SHA-256 on Windows and Linux), Fire Emblem: The Sacred Stones Recomp (release tests on staged files), GSRecomp (
scripts/release_rom_scan.py)- Add more routes in
Add extras behind a switch
Widescreen, filters and netplay come last. Each one is an optional mod. With it off, the picture must stay exactly as before. Many scenes cannot widen, because the game never loads the extra map data.
- Ship each extra as a mod package with a
manifest.tomlinmods/preloaded/. - Patch only what the renderer reads. Do not move the camera or actors.
- Use the game's own level data for the extra columns. Do not repeat the hardware tilemap into the margins.
- Test every level or course, not just one. Keep the native 240x160 route in the regression set.
Prompt for ClaudeGOAL: Add an optional widescreen mod for <SCENE_LIST>. READ FIRST: `CLAUDE.md`, `gbarecomp/docs/MOD_PACKAGES.md`, and `CLAUDE.md` of https://github.com/mstan/DragonBallZBuusFuryRecomp. FENCE: Edit only `src/mods/`, `mods/preloaded/` and `tests/`. `generated/` and `gbarecomp/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. Never write guest RAM, camera state or actor positions. CHECK: Run the regression suite with the mod off and on. Done means every route passes with the mod off and the native picture hash is unchanged, and each scene in <SCENE_LIST> has a screenshot with the mod on. BUDGET: Stop after 3 failed tries on one scene. Leave that scene at native width. 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: test output and screenshot paths. 3) Files changed. 4) Scenes left at native width. 5) New parking-lot items.
Done whenWith the mod off, every route passes and the native picture hash is unchanged.Proof this works: Dragon Ball Z: Buu's Fury Recomp (CLAUDE.md widescreen rules), Mario Kart: Super Circuit Recompiled (first policy pillarboxed 33 of 40 courses)
- Ship each extra as a mod package with a
Path B: Full decomp for porting
You split the ROM into one assembly file per function. Then you replace each one with C that agbcc turns into the same bytes. make compare rebuilds the whole ROM and checks its SHA-1. When every function is C, you build the same source for PC with a small layer for graphics, sound and input.
Method: matching decompilation
Pick this if you want readable source or a port to phones, browsers or other consoles. First check if a decomp exists. If one does, skip to the port steps.
Look for an existing decomp and plan
Many GBA games already have a full or partial decomp. Starting a second one wastes months. You check, count the work, and write
SCOPE.md.- Search GitHub and the pret, zeldaret and decomp.dev pages for your game.
- If a matching decomp exists, read its README and progress. Plan only the port (the last two steps).
- If none exists, count functions with
luvdisor Ghidra. Note the ROM size and the save type. - Find which files use
old_agbcc. The m4a sound driver usually does. - Write
SCOPE.mdwith the SHA-1, the technique, the first milestone (one function matched) and the never-edit list.
Prompt for ClaudeGOAL: Find all prior decomp work for <GAME> and draft SCOPE.md for a matching decomp. READ FIRST: my ROM SHA-1 <SHA1>, https://github.com/pret, https://github.com/zeldaret, https://github.com/Dream-Atelier/kl-eod-decomp README. FENCE: Edit only `SCOPE.md` and `notes/prior-work.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. Do not download any ROM, BIOS or game data. CHECK: Done means `notes/prior-work.md` lists each project found with URL, ROM hash, progress figure and its source, and `SCOPE.md` says either 'port only' or 'new decomp' with the reason. BUDGET: Stop after 45 minutes or 20 web lookups. 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: the list of projects with URLs. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenSCOPE.mdsays 'port only' or 'new decomp', with the evidence, and you approved it.Proof this works: https://github.com/Pheenoh/khcom (matching decomp used by ReKHCoM), https://github.com/zeldaret/tmc (used by Project Picori)
Set up the matching build in WSL
You install the original-style compiler and the ARM assembler in Ubuntu. Then you make a build that turns plain assembly back into the ROM. Its hash check is the one check for this whole path.
- Run Claude Code inside WSL for this whole path. Install it from the WSL terminal, so
make compareruns in Claude's own shell. - In WSL Ubuntu:
sudo apt install build-essential binutils-arm-none-eabi git libpng-dev python3. - Keep the repo inside the WSL file system, such as
~/decomp/<game>. On WSL 2, the Windows 11 default, builds on/mnt/cpaths are slow. - Clone
agbccnext to your game folder:git clone https://github.com/pret/agbcc, thencd agbcc && ./build.sh && ./install.sh ../<game>. It buildsagbcc,old_agbccandagbcc_arm. - Copy the layout of
kl-eod-decomporkhcom:Makefileorconfigure.py, a linker script,asm/,src/,include/, a.sha1file andbaserom.gbain.gitignore. - Make
make compareprint<game>.gba: OKwith everything still in assembly. - The Klonoa decomp builds with its own
agbccfork that adds flags. Start with plainpret/agbcc. Change the compiler only after you approve it as a scope change.
Prompt for ClaudeGOAL: Make `make compare` rebuild <GAME> from assembly and print OK. READ FIRST: `SCOPE.md`, the README and Makefile of https://github.com/Dream-Atelier/kl-eod-decomp, the pokeemerald INSTALL.md section on agbcc. FENCE: Edit only `Makefile`, `ldscript.txt`, `scripts/`, `asm/macros*`, `.gitignore` and `CLAUDE.md`. `baserom.gba` and the `.sha1` file are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `make compare` in WSL. Done means it prints `<GAME>.gba: OK`. Then change one byte in a copy of an asm file and confirm `make compare` fails; undo it. BUDGET: Stop after 3 failed builds with the same error. 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 OK line and the failing line from the broken test. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenmake compareprints<game>.gba: OK, and a deliberately broken file makes it fail.Proof this works: https://github.com/pret/pokeemerald/blob/master/INSTALL.md, https://github.com/Dream-Atelier/kl-eod-decomp, EmeraldRecomp (decomp build on a Windows-mounted path was slow), https://code.claude.com/docs/en/setup (install and run Claude Code inside WSL), https://github.com/pret/agbcc (build.sh builds agbcc, old_agbcc and agbcc_arm)
- Run Claude Code inside WSL for this whole path. Install it from the WSL terminal, so
Split the ROM and map the functions
You cut the ROM into one assembly file per function. You find code, data and SDK library code. Library code should come from other decomps, not from fresh work. The map goes into a ledger with a status column.
- Run
luvdis <ROM> -o rom.s -co functions.cfgfor a first list. Later runs read the list back with-c functions.cfg. Add more functions from Ghidra with the GBA loader. - Have Claude merge the lists and drop false hits. Mark data that was decoded as code.
- Give each function an
INCLUDE_ASM(...)line in asrc/*.cmodule. - Mark SDK code: m4a sound,
libagbsyscallandlibgcc. Copy matched C for these frompokeemeraldortmcand test it. - Write
notes/functions.csvwith address, size, module, compiler and status.
Prompt for ClaudeGOAL: Split <GAME> into per-function assembly and write the function ledger. READ FIRST: `SCOPE.md`, `CLAUDE.md`, `functions.cfg`, the Klonoa README section 'Project Structure'. FENCE: Edit only `functions.cfg`, `<GAME>.toml`, `scripts/`, `src/*.c` (INCLUDE_ASM lines only) and `notes/functions.csv`. `baserom.gba` and the `.sha1` file are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `make compare`. Done means it prints OK and `notes/functions.csv` has one row per function with a size and status. BUDGET: Stop after 90 minutes or 3 failed compares in a row. 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: the OK line and the function count by module. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenmake compareprints OK, andnotes/functions.csvlists every function with its size and status.Proof this works: Klonoa: Empire of Dreams decomp (Luvdis found 93 functions, Ghidra about 300 more, 663 in total), https://github.com/aarant/luvdis
- Run
Match one function end to end
You prove the whole loop on one small function. You replace its
INCLUDE_ASMline with C. You rename it in the config and run the full check.- Pick a short leaf function. A leaf function calls no other function.
- Run
make ctxto writectx.c, the shared types. Then make a draft withm2c -t gba --context ctx.c -f <func> <file>.s. - Run
make expectedsoobjdiffhas target files. Edit the C untilobjdiffshows a full match for that function. - Add the new name under
[renames]in the project.toml. Then runpython3 scripts/generate_asm.pyto update the labels. - Run
make compare. One commit per matched function.
Prompt for ClaudeGOAL: Match `<FUNC>` in C. READ FIRST: `CLAUDE.md`, `asm/nonmatchings/<MODULE>/<FUNC>.s`, `include/`. FENCE: Edit only `src/<MODULE>.c` and the `[renames]` table. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. No `asm("")` barriers, no register pins, no compiler changes. CHECK: Run `make compare`. Done means it prints `<GAME>.gba: OK` with `INCLUDE_ASM` for `<FUNC>` removed. BUDGET: Stop after 5 tries that are each meaningfully different. IF BLOCKED: Stop. Do not work around it. Tell me the best objdiff score, the differing instructions, and your guess at why. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the compare line. 3) Files changed. 4) What is left. 5) New parking-lot items.Done whenmake compareprints OK with that function in C and itsINCLUDE_ASMline gone.Proof this works: Klonoa: Empire of Dreams decomp (README 'Decompiling a Function'), https://github.com/matt-kempster/m2c (target
gba), Klonoa: Empire of Dreams decomp (CLAUDE.md:make ctx,make expected,generate_asm.py)Run the worker loop
Now many small jobs run, often in parallel. Each worker takes one function, in its own git worktree. A worktree is a second working copy of the same repo. The full ROM check, not the function score, decides if a match counts.
- Sort the ledger: small functions first, then those most like already-matched ones.
- Start each worker with
claude -w <func>so it gets its own worktree. Run the setup script in each new worktree before its first build. - Give each worker the target assembly, an
m2cdraft, and up to five similar matched functions. - Merge one match at a time. Run
make compareagain after each merge. - Keep
docs/agbcc-levers.md: general compiler habits that decide matches. No per-function notes in it.
Prompt for ClaudeGOAL: Match the next <N> functions from the ledger, one worker per function. READ FIRST: `CLAUDE.md`, `notes/functions.csv`, `docs/agbcc-levers.md`. FENCE: Lead session: edit only `notes/functions.csv` and `notes/parking-lot.md`. Each worker edits only its own `src/<MODULE>.c` function and the `[renames]` table, in its own worktree. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: After each merge, run `make compare` on the main branch. Done means it prints OK and the ledger shows each merged function as `matched`. BUDGET: Each worker stops after 5 different tries. The lead stops after <N> functions or 3 hours. IF BLOCKED: Stop. Do not work around it. Mark the function `hard` in the ledger with the best score and move on. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: the final compare line and a table of function, result, tries. 3) Files changed. 4) Functions left. 5) New parking-lot items.
Done whenAfter the batch,make compareon the main branch prints OK and the ledger count of matched functions went up.Proof this works: https://github.com/Dream-Atelier/kl-eod-decomp/blob/main/CLAUDE.md, ReKHCoM (claim queue, one worktree and one pull request per piece), https://code.claude.com/docs/en/cli-reference (
--worktree,-w)Crack the hard tail
The last functions are big or odd. Claude tends to claim they cannot be matched. Experienced decompers have shown such claims wrong again and again. You give these to a stronger job type, with stricter stop rules.
- Read the differing instructions first. Name a cause before you change code.
- Try plain-C levers: named externs, array shape, bitfield types, operand order.
- Put the function on decomp.me with the
agbcccompiler and ask the community. - If it still fails, leave it
NonMatchingand say so. A clean 95 percent beats a fake 100.
Prompt for ClaudeGOAL: Match the hard function `<FUNC>` without cheats. READ FIRST: `CLAUDE.md`, `docs/agbcc-levers.md`, the ledger row for `<FUNC>`, past attempts in `notes/attempts/<FUNC>/`. FENCE: Edit only `src/<MODULE>.c` and `notes/attempts/<FUNC>/`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. No `asm("")`, no register pins, no forked compiler, no edits to the `.sha1` file. CHECK: Run `make compare`. Done means OK with `INCLUDE_ASM` removed. Each try goes in a new file in `notes/attempts/<FUNC>/`. BUDGET: Stop after 8 different tries or 60 minutes. IF BLOCKED: Stop. Do not work around it. Report the exact differing instructions and one testable guess. Never call it 'impossible'. OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: the compare line or the best diff. 3) Files changed. 4) What is left. 5) New parking-lot items.Done whenmake compareprints OK for the function, or it is markedNonMatchingwith the exact differing instructions.Proof this works: https://gambiconf.substack.com/p/starting-a-decompilation-project (agent forked agbcc and leaned on register pins), Klonoa: Empire of Dreams decomp (
docs/learnings/agbcc-asm-barriers.md)Harden the decomp
You make sure the match holds on any machine. You add a CI job that builds from scratch. CI means a server that runs your checks on every push. You also add a lint, a script that rejects banned tricks.
- Add a GitHub Actions job that runs
make comparefrom a clean clone. Fetch the ROM from a secret URL, never from the repo. - Add a lint that fails on
asm("")and register pins insrc/. - Have a fresh session re-check ten random matched functions and the lint.
- Name functions and structs. Write
docs/notes by module.
Prompt for ClaudeGOAL: Add a clean-build CI check and a cheat lint. READ FIRST: `CLAUDE.md`, the CI section of the Klonoa decomp README, `.github/workflows/`. FENCE: Edit only `.github/workflows/` and `scripts/lint_*`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. Never put the ROM or its URL in the repo. CHECK: Run the lint locally and `make tidy && make compare`. Done means both pass, and a test file with `asm("")` makes the lint fail. BUDGET: Stop after 3 failed CI runs. 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: local output and the CI run link. 3) Files changed. 4) What is left. 5) New parking-lot items.Done whenCI builds from a clean clone and prints OK, and the lint fails on a plantedasm("").Proof this works: Klonoa: Empire of Dreams decomp (CI fetches the ROM from a
STORAGE_URLsecret), Project Picori (CI skips ROM jobs on fork pull requests)- Add a GitHub Actions job that runs
Port the C to PC
You compile the same
src/for PC. A thin layer replaces the console: a software PPU for graphics, the m4a sound engine in C, input, saves and timing. The ROM build must still match, so PC-only changes sit behind a define.- Pick a pointer plan. ReKHCoM builds 32-bit and puts the GBA memory map at its real addresses. Project Picori builds 64-bit and pins struct layouts with compile-time asserts.
- Wrap PC-only changes in
#ifdef PC_PORTorPLATFORM_PC. Runmake compareafter each one. - Use SDL3 for the window, input and sound. Read game data from the user's ROM at run time.
- Add a headless mode: scripted keys, a fixed exit frame, frame dumps, and SDL dummy video and audio drivers.
Prompt for ClaudeGOAL: Build <GAME> for Windows from the decomp source and reach the title screen. READ FIRST: `SCOPE.md`, `CLAUDE.md`, the README 'How it works' of https://github.com/MatyMeatBoy/ReKHCoM, `AGENTS.md` of https://github.com/999sian/tmc. FENCE: Edit only `port/` and PC-only blocks inside `#ifdef PC_PORT`. `asm/`, `data/` and the `.sha1` file are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run `make compare` (must print OK), then build the PC target and run it headless for <N> frames. Done means both pass and the log shows the game's main loop started. BUDGET: Stop after 3 failed builds with the same error, or 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: the compare line and the headless log. 3) Files changed. 4) What is left. 5) New parking-lot items.
Done whenmake comparestill prints OK, and the PC build runs headless to the game's main loop.Proof this works: ReKHCoM (32-bit build with the GBA address map in place), Project Picori (
#ifdef PC_PORT,PORT_STATIC_ASSERT_OFFSET)Harden the port
Ports break in new ways. Pointers grow on 64-bit. Reads the GBA ignored now crash. You add golden tests that compare frames byte for byte, and battery tests over many scenes.
- Save golden hashes of rendered frames. A renderer change must keep them the same.
- Run batteries over rooms, events and battles. A timeout or crash is a bug, never a retry.
- Guard division by zero and stray reads, but keep GBA behavior.
- Ship a bug-report key that saves a screenshot, the save file and a backtrace.
Prompt for ClaudeGOAL: Add a frame golden-hash gate and a scene battery to the port. READ FIRST: `CLAUDE.md`, `CONTRIBUTING.md` 'Renderer changes' of https://github.com/999sian/tmc, `port/progress/DEBUG_WORKFLOW.md` of https://github.com/MatyMeatBoy/ReKHCoM. FENCE: Edit only `tools/`, `tests/` and `port/` test hooks. Game source is read-only. Do not add features, refactors, tools or cleanups I did not ask for. Never update golden hashes to make a test pass. CHECK: Run the gate and the battery. Done means both pass, and a one-pixel renderer change makes the gate fail. BUDGET: Stop after 3 failed full runs. 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: test output. 3) Files changed. 4) Scenes still failing. 5) New parking-lot items.
Done whenThe golden-hash gate and the battery pass, and a planted one-pixel change fails the gate.Proof this works: Project Picori (
tools/ppu_parity_check.shagainst golden hashes), ReKHCoM (batteries over 209 debug-menu battles)
Tools you need
| Tool | What it does | How to get it | How we know |
|---|---|---|---|
| gbarecomp Required both | The GBA static recompiler and shared runtime. It turns ARM and Thumb code into C++ and models the console around it. Path A | git submodule add https://github.com/mstan/gbarecomp.git gbarecomp (or download gbarecomp-cli-windows-x86_64.zip from the releases page) | README, CLAUDE.md, PRINCIPLES.md, DEBUG.md, TCP.md, docs/GETTING_STARTED.md, docs/TOML_SCHEMA.md, docs/SYMBOL_OVERLAY.md and oracle/README.md (read 2026-11-13); release v0.4.1 of 2026-11-01; used by 9 reviewed projects. Its own Getting Started uses Visual Studio 2022; the game repos use MSYS2. |
| recomp-ui Helpful both | The shared launcher and in-game settings menu that gbarecomp games link in.Path A | git submodule add https://github.com/RetroPortingToolKit/recomp-ui.git recomp-ui | README (read 2026-11-13); mstan/recomp-ui now redirects here; used by Mother 3 Recomp, EmeraldRecomp and others |
| MSYS2 MinGW64 (gcc, CMake, Ninja, SDL2) Required Windows | A Windows build toolchain. It compiles gba_recompile and the generated game code.Path A | Install msys2-x86_64-<date>.exe from msys2.org, then in MINGW64: pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-SDL2 | msys2.org and packages.msys2.org pages for all four packages (read 2026-11-13); named in the READMEs of DBZ Buu's Fury, Emerald, FireRed and MKSC recomps |
| PowerShell 7 Required Windows | The newer PowerShell, run as pwsh. The game repos run their regen, test and release scripts with it.Path A | winget install --id Microsoft.PowerShell --source winget | Microsoft install page (read 2026-11-13); pwsh tools/regen.ps1 in the SMA4, DBZ and MKSC READMEs (read 2026-11-13) |
| mGBA Required both | An accurate GBA emulator. gbarecomp treats it as the oracle for correct behavior. It has Lua scripting and a GDB remote debugger.Path A Path B | Download mGBA-0.10.5-win64-installer.exe from the GitHub releases page | README and release 0.10.5 assets (read 2026-11-13); named as oracle in gbarecomp PRINCIPLES.md |
| gba-recomp (JRickey) Helpful both | A second GBA recompiler, written in Rust. It checks recompiled frames against its own interpreter. FFTARecomp is built on it. Path A | Download gba-recomp-cli-0.4-x86_64-pc-windows-msvc.zip from the releases page, or: git clone https://github.com/JRickey/gba-recomp then cargo build --release (needs Rust and a C compiler named cc on PATH) | README, BUILDING.md and release v0.4 of 2026-06-18 (read 2026-11-13). BUILDING.md calls a Windows source build untested. |
| agbcc Required WSL/Linux | The rebuilt GBA SDK C compiler, based on GCC 2.95. Matching decomps need it to produce the original bytes. Path B | git clone https://github.com/pret/agbcc && cd agbcc && ./build.sh && ./install.sh ../<project> | repo file list (build.sh, install.sh), pokeemerald INSTALL.md and khcom README (read 2026-11-13) |
| GNU Arm binutils (binutils-arm-none-eabi) Required WSL/Linux | The ARM assembler and linker. They turn the split assembly and compiled C back into a ROM. Path B | sudo apt install build-essential binutils-arm-none-eabi git libpng-dev | pokeemerald INSTALL.md (read 2026-11-13); khcom README lists the same package |
| Luvdis Helpful both | A GBA disassembler written in Python. It finds Thumb functions, tells code from data and checks if a ROM dump is known. Path A Path B | python3 -m pip install luvdis --user | README and PyPI version 0.9.0 (read 2026-11-13): -o writes assembly, -c reads a function list, -co writes the guessed list, luvdis info checks a dump; used by the Klonoa decomp |
| Ghidra Helpful both | A free reverse engineering suite. It shows functions, cross references and a rough C view of the code. Path A Path B | Install JDK 25 64-bit, unzip the Ghidra release, run ghidraRun.bat | README and latest release Ghidra_12.2_build (read 2026-11-13); used by the Klonoa decomp and FireRedLeafGreenRecomp |
| gba-ghidra-loader Helpful both | A Ghidra add-on that loads a .gba file with the right memory map and entry point.Path A Path B | In Ghidra: File > Install Extensions > + and pick the release zip that matches your Ghidra version, or build from source with gradle | README and release 1.1.0 (built for Ghidra 12.0.2) (read 2026-11-13) |
| objdiff Required both | Compares your compiled object file with the original, function by function. It supports ARM for the GBA. Path B | Download objdiff-windows-x86_64.exe (GUI) or objdiff-cli from the releases page | README and release v3.8.3 (read 2026-11-13) |
| m2c Helpful both | Turns one function's assembly into a first C draft. It has a gba target.Path B | pip install git+https://github.com/matt-kempster/m2c.git | README (read 2026-11-13): target gba (ARM with APCS), -f and --context flags, installs as a Python package with an m2c command |
| decomp.me Helpful both | A website where you match one function in the browser with the real compiler, and share it for help. Path B | No install. Use https://decomp.me in a browser. | decomp.me source cromper/cromper/compilers.py lists agbcc, old_agbcc and agbcc_arm for GBA (read 2026-11-13). The site itself answers 403 to scripts, so it was not opened. |
| SDL3 Required both | A library for the window, input and sound. Ports of a decomp use it as the PC side of the console layer. Path B | Download SDL3-devel-3.4.20-mingw.zip from the SDL releases page | release-3.4.20 assets (read 2026-11-13); used by Project Picori and ReKHCoM |
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.
matching-decomp (xavirodriguez)
The only vetted matching skill with GBA notes. It sorts each request into a mode, so Claude does not edit when you only asked a question. Use with care: its helper scripts live outside the skill folder.
npx skills add xavirodriguez/skills --skill matching-decomp -a claude-code
matcher
A careful method for matching one function. Claude gathers proof first, tries one idea at a time, and reports fake matches as not done. Install its five sister lemiur skills too, because they call each other.
npx skills add lemiur/game-decompilation-skill-for-claude --skill matcher -a claude-code
native-platform-porting
Guides the port step of Path B. It warns Claude not to hide a small emulator inside the port.
npx skills add lemiur/game-decompilation-skill-for-claude --skill native-platform-porting -a claude-code
verification-before-completion
Claude may not say done without fresh proof. On GBA that proof is make compare or a strict-static coverage line.
npx skills add obra/superpowers --skill verification-before-completion -a claude-code
handoff
Writes a short note so a fresh session can carry on. Tell it to save inside your project, not in the temp folder.
npx skills add mattpocock/skills --skill handoff -a claude-code
ghidra-headless
Runs Ghidra with no window and saves functions and strings to files. Load the ROM with the GBA loader first.
npx skills add trailofbits/skills-curated --skill ghidra-headless -a claude-code
GhidraMCP
Lets Claude ask a running Ghidra for functions and renames. No reviewed GBA project used an MCP server; the gbarecomp TCP debug server played that role. Its README asks for Ghidra 12.1.4, which may clash with the GBA loader zip.
Install `uv`, then the GhidraMCP release zip in Ghidra, then: claude mcp add ghidra -- uvx --from git+https://github.com/LaurieWired/GhidraMCP ghidra-mcp --ghidra-server http://127.0.0.1:8080/
gba-regen-and-accept
Path A has one done-check. This skill makes Claude run it the same way every time and paste the same lines.
A project skill in `.claude/skills/gba-regen-and-accept/SKILL.md`. It runs `pwsh tools/regen.ps1`, rebuilds, runs every route in `tests/*.input` with `GBARECOMP_STRICT_STATIC=1`, and prints one line per route: frames, misses, interpreted instructions, save SHA-256. It says FAIL if any number is off.
agbcc-match-one
Bulk workers in Path B follow the same steps and the same stop rule. Good tries are never lost.
A project skill in `.claude/skills/agbcc-match-one/SKILL.md`. Input: a function name. It makes an `m2c -t gba` draft, saves each try as a new file in `notes/attempts/<func>/`, runs `objdiff-cli` for the score, then `make compare`. It stops after 5 tries and lists banned tricks: `asm("")`, register pins, compiler edits.
Claude setup for this system
On Path A, one unit is one dispatch miss, one wrong frame or one save bug. Each has a route to replay and a coverage line to read. On Path B, one unit is one function, checked by make compare. Library code (m4a, libagbsyscall) is one unit you copy and test, not decompile. The port is cut by subsystem: graphics, sound, input, saves. Each subsystem gets its own golden test.
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 | Check for an existing port, decomp or disassembly of your exact ROM. Pick gbarecomp or a matching decomp. 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 MSYS2 or the WSL packages, add the submodules, write tools/regen.ps1 or the make compare build with its hash gate. | Opus 5.5 effort medium | Sonnet 5.5 effort medium |
| Study the game file | Seed game.toml from decomp symbols, find code copied into IWRAM, split the ROM into functions and mark library code. | 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 B: match small functions, one per worker. Path A: add reviewed seeds for many simple misses at once. | 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 | Big or odd functions that bulk workers could not match in five tries. Also IRQ resume points that keep coming back. | 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 | Path A: host code, save chip, RTC and widescreen mods. Path B: the PC layer with the software PPU, m4a sound and input. | Opus 5.5 effort high | Opus 5.5 effort mediumRaise to high for timing and graphics bugs. |
| Find a bug | Find the first frame where your build and mGBA differ, through the TCP debug server. Prove the cause before any fix. | 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 make compare or the strict-static routes. It checks that no hash, .sha1 file or generated code changed. | 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 notes/coverage.md or notes/functions.csv, notes/findings.md and the handoff note. | Haiku 5.5 effort medium | Haiku 5.5 effort medium |
How many sessions at once
Max 20x (now called Ultra)
Path B: run four to six workers, each in its own worktree on one function, plus one lead session that merges and re-runs make compare. Path A: run one or two sessions, since most units touch game.toml. Give the second one host code or tests. Keep big compiles at low priority.
Max 5x (now called Max)
Path B: run two workers and one lead. Queue easy functions for overnight runs. Path A: one session at a time. Bring in a fresh verify session only at milestones.
Lines for this project's CLAUDE.md
- Read `SCOPE.md` and `notes/PROGRESS.md` at the start of every session.
- Generated code in `generated/` is never edited. Fix `game.toml`, the recompiler or the runtime, then regenerate.
- mGBA is the oracle. When our build and mGBA differ, mGBA is right.
- ROM hash gates everything. Never weaken the SHA-1 check in `tools/regen.ps1` or the `.sha1` file.
- Path A done-check: the strict-static route log shows `FULLY_STATIC dispatch_misses=0 interpreted_insns=0`. Never call a run fully static otherwise.
- Path B done-check: `make compare` prints `<game>.gba: OK`. An objdiff score is evidence, not the verdict.
- No `asm("")` barriers, register pins or compiler forks in committed C.
- Import only names, addresses, sizes and code/data split from a decomp. Never copy its C into the recomp.
- No game-specific special cases inside `gbarecomp/src/gba/`.
- Build with MSYS2 MinGW64 and Ninja from PowerShell. The Bash shell breaks `cc1plus`.
- ROMs, BIOS dumps, generated C++, saves and screenshots never go into Git.
- In a worktree, use absolute paths and run `make compare` there before you report.
- Write side issues in `notes/parking-lot.md` and dead ends in `notes/findings.md`.Keep the context small
- Give Claude one address or one function name, not a pasted wall of assembly.
- Point to the game's
CLAUDE.md, and let it point togbarecomp/PRINCIPLES.mdandDEBUG.md, instead of pasting rules. - Ask for the coverage line and the first miss only. Do not let it read whole log files.
- Add
generated/andbuild/topermissions.denyread rules. The generated shards are huge. - Run
/clearbetween units. The ledger files carry the state.
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, when you are not sure which path fits your game.
GOAL: Tell me whether <GAME> (<REGION>, SHA-1 <SHA1>) should use gbarecomp, a port of an existing decomp, or a new matching decomp. READ FIRST: the gbarecomp README game list, https://github.com/pret, https://github.com/zeldaret, RecompLauncher's GBA list. FENCE: Edit only `SCOPE.md` and `notes/prior-work.md`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. Do not download any ROM, BIOS or game data. CHECK: Done means each option has: prior work with URLs, special cartridge hardware (RTC, flash, gyro), a first milestone and its check, and a rough size in functions with the source of that number. BUDGET: Stop after 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: the table of options with sources. 3) Files changed. 4) Your pick and why. 5) New parking-lot items.
A good answer: A short table with three options, links for every claim, and one pick. It says plainly if a port already exists.
Map the binary
Path B after setup, or Path A when there is no decomp for symbols.
GOAL: Build a function ledger for <GAME>. READ FIRST: `SCOPE.md`, the output of `luvdis <ROM> -o rom.s`, the Ghidra export in `notes/ghidra_functions.csv`. FENCE: Edit only `notes/functions.csv` and `functions.cfg`. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means every row has address, size, ARM or Thumb, module guess, library tag (m4a, libagbsyscall, libgcc or game), and source. For Path B, `make compare` still prints OK. BUDGET: Stop after 90 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: counts by module and by tag. 3) Files changed. 4) Rows with low confidence. 5) New parking-lot items.
A good answer: A CSV with one row per function and a count summary. Doubtful rows are flagged, not guessed.
Unit loop: one dispatch miss (Path A)
Each time a strict-static route stops on a miss.
GOAL: Resolve the dispatch miss at <ADDRESS>. READ FIRST: `CLAUDE.md`, `notes/coverage.md`, the proposal file, the route `<INPUT>`. FENCE: Edit only `game.toml` reviewed entries and `notes/coverage.md`. `generated/` and `gbarecomp/` are read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: First show what code lives at <ADDRESS> (ROM, IWRAM copy or IRQ return) with evidence from mGBA or Ghidra. Then regen, rebuild and replay with `GBARECOMP_STRICT_STATIC=1`. Done means the run passes <ADDRESS>. BUDGET: Stop after 3 regen cycles. 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: the new coverage line. 3) Files changed. 4) The next miss, if any. 5) New parking-lot items.
A good answer: DONE, the evidence for what the address is, one reviewed game.toml entry with a note, and the new coverage line.
Unit loop: one function (Path B)
Each bulk worker session in the matching grind.
GOAL: Match `<FUNC>` in `src/<MODULE>.c`.
READ FIRST: `CLAUDE.md`, `asm/nonmatchings/<MODULE>/<FUNC>.s`, up to five similar matched functions listed in `notes/functions.csv`.
FENCE: Edit only that function in `src/<MODULE>.c` and its `[renames]` line. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. No `asm("")`, no register pins.
CHECK: Run `make compare`. Done means `<GAME>.gba: OK` with the `INCLUDE_ASM` line gone.
BUDGET: Stop after 5 meaningfully different tries.
IF BLOCKED: Stop. Do not work around it. Report the best objdiff score and the exact differing instructions.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: the compare line. 3) Files changed. 4) What is left. 5) New parking-lot items.A good answer: One word first. Then the OK line, or the best score with the differing instructions.
Batch dispatch
In the lead session, to hand out the next set of functions or bugs.
GOAL: Launch one worker for each of the next <N> open units in the ledger. READ FIRST: `CLAUDE.md`, `notes/functions.csv` or `notes/coverage.md`. FENCE: Edit only the ledger status column. Workers each use their own worktree from `claude -w <unit>` and edit only their unit. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: After each worker reports, merge one at a time and run `make compare` (Path B) or the strict-static routes (Path A) on the main branch. Done means all checks pass after the last merge. BUDGET: Stop after <N> units or 3 hours. Mark any unit with 5 failed tries as `hard`. 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: the final check output and a table of unit, worker result, merged yes or no. 3) Files changed. 4) Units left. 5) New parking-lot items.
A good answer: A table of units with results. The main branch passes its check after the last merge.
Debug with evidence
When the game crashes, hangs, sounds wrong or draws wrong.
GOAL: Find the cause of <SYMPTOM>. Do not fix it yet. READ FIRST: `CLAUDE.md`, `gbarecomp/DEBUG.md`, `gbarecomp/TCP.md` (Path A) or the port's debug notes (Path B), `notes/findings.md`. FENCE: Everything is read-only in this session. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means you name the first frame where our build and mGBA differ, the first wrong write, and the code that made it, with TCP or log output pasted for each. BUDGET: Stop after 60 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: the evidence chain. 3) Files changed (none). 4) The fix you suggest and where it belongs. 5) New parking-lot items.
A good answer: A chain of evidence from symptom to first wrong write. No code changed. One suggested fix in the right layer.
Verify and hunt for cheating
After every milestone, in a brand-new session that did not do the work.
GOAL: Check that the claimed work since commit <SHA> is real.
READ FIRST: `CLAUDE.md`, `git log <SHA>..HEAD`, `git diff <SHA>..HEAD`.
FENCE: Everything is read-only. Do not add features, refactors, tools or cleanups I did not ask for.
CHECK: Re-run `make compare` (Path B) or every strict-static route (Path A). Then search the diff for: changes to `.sha1`, hash files, `tools/regen.ps1` gates or golden hashes; edits in `generated/`; `asm("")` or register pins; disabled tests; game checks inside `gbarecomp/src/gba/`; files outside the fence. Done means every item is checked.
BUDGET: Stop after 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) PASS or FAIL. 2) Proof: the check output. 3) Each suspect change with file and line. 4) What I should review by hand. 5) New parking-lot items.A good answer: PASS or FAIL first, the check output, and a list of suspect lines. An empty list is fine if it is true.
Status report
At the end of a week, or before you change plans.
GOAL: Give me a status report from the ledgers only. READ FIRST: `SCOPE.md`, `notes/PROGRESS.md`, `notes/functions.csv` or `notes/coverage.md`, `notes/findings.md`, `notes/parking-lot.md`. FENCE: Everything is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Run the main check once (`make compare` or the strict-static routes) and include its output. Done means every number in the report comes from a file or that output. BUDGET: Stop after 15 minutes. IF BLOCKED: Stop. Do not work around it. Tell me what is missing. REPORT: 1) Milestone and whether its check passes. 2) Counts: matched or covered, open, hard. 3) Bugs found and fixed this week. 4) Top three risks. 5) Parking-lot items that need my decision.
A good answer: Numbers with their source, the check output, and three risks. No padding.
Session handoff
Before you stop for the day or when the context is getting full.
GOAL: Write down everything the next session needs. READ FIRST: what you did this session, `notes/PROGRESS.md`. FENCE: Edit only `notes/PROGRESS.md`, `notes/findings.md` and the ledger. Everything else is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means `notes/PROGRESS.md` has: the current unit and its state, the exact last check command and its output, files touched, dead ends tried, and the next three steps. BUDGET: Stop after 10 minutes. IF BLOCKED: Stop. Tell me what you could not record. REPORT: 1) DONE or PARTIAL. 2) Proof: paste the new section of `notes/PROGRESS.md`. 3) Files changed.
A good answer: A short dated section in notes/PROGRESS.md that a new session can act on without the chat.
Blocked or cannot deliver
When Claude keeps trying the same thing, or says something 'should work'.
GOAL: Give me a plain answer on <TASK>. READ FIRST: `notes/findings.md`, your last attempts. FENCE: Everything is read-only. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means you answer with one of: DONE (with pasted check output), PARTIAL (what works, what does not), or BLOCKED. BUDGET: Answer now. No new attempts. IF BLOCKED: Say what cannot be done, why, with evidence, and list two or three options with their cost. REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof. 3) Options. 4) What you need from me.
A good answer: One word, the evidence, and real options. Never 'impossible' without the exact instructions or data that block it.
Scope change request
When Claude wants to leave the fence, for example to change gbarecomp itself or a shared header.
GOAL: Ask me before you leave the fence for <TASK>. READ FIRST: `SCOPE.md`, the fence in your current task card. FENCE: Make no edits until I say yes. Do not add features, refactors, tools or cleanups I did not ask for. CHECK: Done means you have written the request below and stopped. BUDGET: One message. IF BLOCKED: Stop and wait for me. REPORT: 1) The file or folder you want to change. 2) Why the fence blocks you, with evidence. 3) The smallest change that would work. 4) What could break, such as other games on gbarecomp or the ROM match. 5) How we would check it.
A good answer: A short request with evidence, the smallest change, and its risk. No edits made.
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++ to make a crash go away. | Never edit generated/. Fix game.toml, the recompiler or the runtime, then regenerate. Block edits to generated/** with a PreToolUse hook. |
Claude adds addresses to game.toml from the miss log without checking them. | Each new seed needs a note: where you saw it and how you checked it. The miss list feeds a reviewed proposal, never a direct write. |
| Claude calls a run 'fully static' while the interpreter still filled gaps. | Only a run with GBARECOMP_STRICT_STATIC=1 that prints dispatch_misses=0 interpreted_insns=0 counts. Paste that line or say PARTIAL. |
| Claude puts a fix for one game inside the shared engine, behind a game check. | No game names in gbarecomp/src/gba/. Hardware fixes there need proof from the mGBA oracle. Game fixes go in the game repo. |
Claude says a function cannot be matched, then adds asm(""), register pins or a forked compiler. | Those are banned in committed C. A stuck function stays NonMatching with the exact differing instructions. |
| Claude loosens the ROM or BIOS hash check to get past a bad dump. | Never weaken the identity gate. A new revision is added by its own checksum. Block edits to .sha1 files and hash lines with a hook. |
| Claude widens the picture by moving the camera or repeating the tilemap. | Widescreen mods read only. Patch renderer reads, use the game's own level data, and fall back to 240x160 when probes do not match. |
Problems other projects hit
Code the game copies into IWRAM or onto the stack is missed. The game runs slowly in the interpreter or shows a black screen.
Fix: List each copied block as [[code_copy]] with [[extra_func]] entries. Check it byte for byte against live IWRAM in mGBA.
Seen in: FireRedLeafGreenRecomp, Super Mario Advance 4 Recomp, Mother 3 Recomp, Dragon Ball Z: Buu's Fury Recomp
Interrupts return into the middle of functions. A static scan cannot find those points, so runs stop with misses.
Fix: Keep static_resume_all = true, the default, and regenerate. Add reviewed entries for what still misses. Use the BIOS config that ships with the engine.
Seen in: EmeraldRecomp, Super Mario Advance 2 Recomp, Fire Emblem: The Sacred Stones Recomp
An old single-file generated/recompiled.cpp stops CMake with an error. Or a new config does nothing, because old code was rebuilt.
Fix: Run the regen script after every change to game.toml or the recompiler. Then rebuild.
Seen in: Mario Kart: Super Circuit Recompiled, Mother 3 Recomp, GSRecomp, Super Mario Advance 4 Recomp
Builds fail from Claude's Bash shell, because it sets TEMP to C:\Windows and cc1plus breaks.
Fix: Start builds from PowerShell with MSYS2 MinGW64 on the PATH. Write this in CLAUDE.md.
Seen in: EmeraldRecomp, FireRedLeafGreenRecomp
The Pokemon games lift to about 90,000 functions. The Windows build crashed before main with the default stack size.
Fix: Copy the link option that sets a large stack reserve from a game with the same size. Emerald and FireRed use 256 MB.
Seen in: FireRedLeafGreenRecomp, EmeraldRecomp, Mother 3 Recomp
Each new symbol import overwrote hand-written config. Reviewed entries were lost.
Fix: Keep game.toml as the hand-written base. Put importer output in a separate overlay file that never wins a conflict.
Seen in: EmeraldRecomp, FireRedLeafGreenRecomp
Saves did not work, because the flash chip reported the wrong ID. A debug run also changed a player's real save.
Fix: Test a save round trip early and compare save hashes. Keep test saves in their own folder.
Seen in: Mario Kart: Super Circuit Recompiled, Fire Emblem: The Sacred Stones Recomp
A three-frame boot test passed a build that crashed later. Packaging only checked that files existed.
Fix: Make the release script run long routes on the staged files: thousands of frames, save reload and zero misses.
Seen in: Fire Emblem: The Sacred Stones Recomp
On 64-bit, pointers grow and struct fields shift. Reads that were harmless on the GBA now crash.
Fix: Build 32-bit with the GBA memory map in place, or pin layouts with compile-time asserts. Answer stray reads as the GBA bus would.
Seen in: Project Picori, ReKHCoM
A store listing called the project a recompilation, but the build files show a hand-written interpreter.
Fix: Read CMakeLists.txt before you copy a project's method. Check for generated code and a recompiler step.
Seen in: SuperSaga, KNID
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 | 4 to 18 months | 9 months to 3 years | 3 to 6 years | low confidence |
Read this first
These numbers assume one medium-sized game and one person giving 10 to 15 hours a week. Path A is medium confidence. Many AI-assisted GBA recomps are dated, and they agree on days to weeks. But their authors were skilled, and repo dates hide work done before the first public commit. Path B is low confidence. No GBA decomp with stated AI use has finished yet. The Klonoa decomp, built with Claude Code, reached 51.30 percent in about seven months. The khcom pace does not say whether AI was used. No GBA recomp predates coding agents, so the no-AI Path A figure comes from a PS1 recompiler built by hand.
What makes it faster or slower
- Whether a decomp or disassembly exists. It gives function names and saves weeks on both paths.
- How much code the game copies into RAM, and how many interrupt return points it has.
- Odd cartridge hardware: real-time clock, flash saves, gyro, solar sensor or a large mapper.
- On Path B, the number and size of functions, and how much uses
old_agbccor ARM mode. - On Path B, whether you port 32-bit with the GBA memory map, or fix every 64-bit layout.
The facts behind these numbers
| Project | What happened | Link |
|---|---|---|
| Fire Emblem: The Sacred Stones Recomp | First commit 2026-08-18. First release 2026-08-22. 2 contributors. README says it was built with substantial AI help. | source |
| GSRecomp | Repo first commit 2026-09-26. First release 2026-10-02. Engine fork began 2026-07-17. 2 contributors. README credits AI tools. | source |
| Mother 3 Recomp | First commit and first release both 2026-10-11. 117 commits by 2026-10-28. 2 contributors. | source |
| gbarecomp and MinishCapRecomp | Framework first commit 2026-05-23, first release 2026-05-25. 641 commits and 9 contributors by 2026-11-13. Ships a CLAUDE.md. | source |
| KNID | Developer says Claude did 99% of the work. First commit and release 2026-11-09. 99 commits and 13 releases in five days. Runs on an interpreter. | source |
| Kingdom Hearts: Chain of Memories decomp (khcom) | Scaffold 2026-08-30. decomp.dev shows US 100.00% decompiled (read 2026-11-13). Last commit 2026-10-12. 3,167 commits, 1 contributor. AI use not stated. | source |
| Klonoa: Empire of Dreams decomp | First commit 2026-03-14, last commit 2026-10-05. Built with Claude Code from an empty repo. decomp.dev shows 51.30% (read 2026-11-13). 663 functions. | source |
| ReKHCoM | PC port of khcom. First release 2026-10-26. 5 contributors. Several Claude and Codex agents worked in parallel lanes. | source |
| The Minish Cap decomp (zeldaret/tmc) | Started 2020. 37 contributors. 14 files still in asm/src and 619 C files in src (checked 2026-11-13). No AI stated. | source |
Projects reviewed (14)
The top-starred project for each of the top 12 GBA games on RecompLauncher, plus two whose developers say AI did the work. RecompLauncher lists 29 GBA projects for 26 games; 25 are flagged for AI use.
What each project teaches
Project Picori
The Legend of Zelda: The Minish Cap
Started: 2020-03. First release: 2026-09. Code: C and C++.
AI: yes: the developer flags AI use for code; the repo ships AGENTS.md and agent.txt Agent files: AGENTS.md, agent.txt.
Lesson: Build the same source twice: once with agbcc for the matching ROM, once for PC. Guard PC changes with #ifdef PC_PORT, and give agents a headless smoke run.
FFTARecomp
Final Fantasy Tactics Advance
Started: 2026-10. First release: 2026-10. Code: Rust.
AI: flagged by the store only; the repo states none
Lesson: Gate every game patch on the exact ROM hash. Prove a compiler swap with frame hashes over 600 boot frames.
Mother 3 Recomp
Mother 3
Started: 2026-10. First release: 2026-10. Code: C and C++.
AI: flagged by the store only; the repo states none
Lesson: Record which addresses run in mGBA and compare them with your static coverage. Each miss becomes a reviewed config entry.
GSRecomp
Golden Sun
Started: 2026-09. First release: 2026-10. Code: C++.
AI: yes: README says portions were built with AI tools
Lesson: If you fork the engine, log every change and its reason in MODIFICATIONS.md. Keep every game address out of the engine folder.
Mario Kart: Super Circuit Recompiled
Mario Kart: Super Circuit
Started: 2026-07. First release: 2026-07. Code: C++.
AI: yes: agent rules live in the gbarecomp submodule; part of the R.A.I.D. community
Lesson: Define done as a recorded route replayed headless in strict mode, then compare the save hash on Windows and Linux.
ReKHCoM
Kingdom Hearts: Chain of Memories
Started: 2026-08. First release: 2026-10. Code: C and C++.
AI: yes: AGENTS.md and port/progress/COLA_COLABORATIVA.md describe several Claude and Codex agents in parallel lanes Agent files: AGENTS.md, CLAUDE.md, port/skills/optiport/AGENTS.md.
Lesson: Parallel agents need a real claim queue, one worktree and one pull request per piece, and one merge lock. A chat note is not a claim.
EmeraldRecomp
Pokemon Emerald
Started: 2026-06. First release: 2026-06. Code: C++.
AI: yes: ships a CLAUDE.md; part of the R.A.I.D. community Agent files: CLAUDE.md.
Lesson: Import symbols only after the decomp rebuilds your exact ROM hash. Keep hand-written config apart from importer output.
FireRedLeafGreenRecomp
Pokemon FireRed
Started: 2026-06. First release: 2026-06. Code: C++.
AI: yes: ships a CLAUDE.md; part of the R.A.I.D. community Agent files: CLAUDE.md.
Lesson: Agent files go stale. Its CLAUDE.md names a different ROM revision than its README, so check them against the code.
Dragon Ball Z: Buu's Fury Recomp
Dragon Ball Z: Buu's Fury
Started: 2026-08. First release: 2026-08. Code: C++.
AI: yes: ships a CLAUDE.md that points to the engine's agent rules Agent files: CLAUDE.md.
Lesson: A second game on the engine can be tiny. Its CLAUDE.md points to the engine rules and adds only game facts and a debug port.
Fire Emblem: The Sacred Stones Recomp
Fire Emblem: The Sacred Stones
Started: 2026-08. First release: 2026-08. Code: C++.
AI: yes: README says it was built with substantial help from OpenAI Codex
Lesson: A short boot test can pass a build that crashes later. Run long input routes on the packaged files before each release.
SuperMarioAdvance2Recomp
Super Mario World: Super Mario Advance 2
Started: 2026-07. First release: 2026-08. Code: C++.
AI: flagged by the store; README names the R.A.I.D. AI community
Lesson: A game with no decomp still works. Run the same route twice: on the interpreter as reference, and native in strict mode.
Super Mario Advance 4 Recomp
Super Mario Advance 4: Super Mario Bros. 3
Started: 2026-07. First release: 2026-08. Code: C++.
AI: flagged by the store; README names the R.A.I.D. AI community
Lesson: Its test script demands exact log lines: frame count, zero misses, zero interpreted code. That leaves Claude no room to guess.
KNID
Kirby: Nightmare in Dream Land
Started: 2026-11. First release: 2026-11. Code: C++.
AI: yes: the developer says Claude did 99% of this work
Lesson: Claude can ship a polished single-game app in days, but this one runs on an interpreter. It is not a recomp or a decomp.
SuperSaga
Mario & Luigi: Superstar Saga
Started: 2026-11. First release: 2026-11. Code: C++.
AI: yes: the developer says Claude did 99% of this work
Lesson: Tests that need the ROM skip themselves in CI. So green CI here does not prove the game runs.
What we could not check
- Whether the khcom decomp used AI. Its repo has no agent files and no statement.
- When pret/pokeemerald became fully C. Only its current state was checked: its
asm/folder holds only macros. - The exact current recompile command for EmeraldRecomp and FireRedLeafGreenRecomp. Their README and
game.tomldisagree. - The shared
recomp-templaterules thatgbarecomp/CLAUDE.mdpoints to. They sit outside the public repo. - Whether the
gba-ghidra-loaderrelease works on Ghidra 12.1.4 or 12.2. Its zip was built for 12.0.2. - Whether JRickey's
gba-recompbuilds cleanly on Windows. Its own docs call Windows untested. - How much hidden work came before the first public commit of each recomp. Many repos start on the day of their first release.
- Build times on the reader's machine were not measured.
- No command in this guide was run on this machine. Each one was checked against the tool docs and the project files only.
- The host flags
--frames,--no-windowand--dump-pnglive in each game's own host code, as in SMA4. A new host has them only if you copy that code. - The proposal file name
recomp_seed_proposals.tomlcomes from the SMA4.gitignore, not from the engine docs. - Building the
gbarecompmGBA oracle on Windows was not tried. Its setup script,oracle/setup-mgba.sh, is a shell script. - Whether a Klonoa-style layout builds with plain
pret/agbcc. Klonoa itself uses its ownagbccfork with extra flags.
Sources
- gbarecomp README
- gbarecomp PRINCIPLES.md
- gbarecomp DEBUG.md
- gbarecomp Getting Started
- recomp-ui README
- gba-recomp (JRickey) README
- pokeemerald INSTALL.md
- agbcc
- Klonoa: Empire of Dreams decomp README
- khcom README
- khcom progress on decomp.dev
- Starting a Decompilation Project from Zero (Macabeus)
- zeldaret/tmc README
- objdiff README
- m2c README
- Luvdis README
- gba-ghidra-loader README
- GhidraMCP README
- mGBA README
- MSYS2 install page
- decomp.me compiler list (source)
- GBATEK hardware reference
- Recomp + AI: 5 Months Later (Matthew Stanley)
- Ghidra README
- gbarecomp TOML schema
- gbarecomp TCP debug protocol
- gbarecomp mGBA oracle README
- SMA4 strict-static test script
- Klonoa decomp CLAUDE.md
- Install PowerShell on Windows (Microsoft)
- Claude Code CLI reference
- Claude Code setup (WSL)
- RecompOne interview (PS1, no AI)