← Back to Home
Developer Tools

REA and the SNESAgents are taking apart old cartridges

How does Super Mario World decide Mario's top running speed? How does A Link to the Past move a sprite from one screen to the next? Until recently, answering a question like that meant years of annotating a disassembly by hand. REA, a GitHub project that gives coding agents a reverse engineering toolbox over MCP, made me look at those questions again. The SNES community has been running agents against these games for a while now, and their results show both what works and what keeps the output honest.

01
Why SNES games are hard to read
The CPU decides at runtime what the bytes mean
CPU
8 or 16 bits, you choose

The SNES runs a 65816. Two status flags, M and X, switch the accumulator and the index registers between 8 and 16 bits while the game is running. The same bytes decode to different instructions depending on those flags, so a static disassembler has to guess. Guess wrong once and everything after it is garbage.

Memory
Banks and mappings

A cartridge is laid out as LoROM or HiROM, code jumps between 64 KB banks, and a single address can mean different things depending on the bank register. Experienced disassemblers split the ROM bank by bank and set the right flags for each one before they read any code.

Hardware
Chips in the cartridge

Star Fox runs on the Super FX, Super Mario RPG on the SA-1, and Mega Man X2 and X3 on the Cx4. Each one is a separate processor with its own instruction set. Understanding a game can mean reverse engineering a second CPU too.

How long this took by hand

The zelda3 project rebuilt A Link to the Past as roughly 80,000 lines of C. It was built on top of an existing community disassembly, and the result still borrows the PPU and audio code from an emulator. The navigation work is what takes so long: following a jump, working out which bank you are in, figuring out what a RAM address stores, and doing that thousands of times.

02
What REA is
github.com/morluto/rea · MIT · rea-agents on npm
One CLI and one MCP server in front of real analysis tools

REA stands for Reverse Engineer Anything. It does not include its own decompiler. It drives the tools you already have, Ghidra, Hopper or IDA for native code, and exposes them as MCP tools such as search_strings, xrefs, procedure_callers, procedure_pseudo_code and trace_feature. npx rea-agents setup registers the server with Claude Code, Codex, Cursor, Gemini CLI and a few others, and installs a skill that tells the agent how to run an investigation. The repository was created in April 2026 and shipped its first release in July. It then sat at a few hundred stars until October.

View morluto/rea on GitHub →
GitHub stars · morluto/rea
513 stars on 30 September. 83,437 on 11 October.

The project hit #1 on GitHub trending on 7 October. Coverage that week reported about 13,000 stars on 8 October and almost 59,000 a day or two later. Eleven releases shipped between 3 and 11 October, taking it from version 3.2 to 6.4.

Show data
DateStars
Source: star-history.com sampling, final value from the GitHub API on 11 October 2026.
The part that matters
Every answer comes with evidence

Each tool call becomes a record with the target's hash, the provider version, the exact parameters, the raw result and its limitations. When the agent says "this routine handles horizontal speed", there is a record with the address and the instructions behind it, and you can check it yourself.

Closest showcases
Old games are already on the list

REA's own case studies include DX-Ball, a 1996 Windows game, where a sound-pan helper was rebuilt in C that reproduces all 63 compiled bytes. Another is Touhou 4 on the PC-98, where the 16-bit bullet ring angle code was recovered. Neither is a SNES game, but both are the same kind of work: one small routine in an old binary, explained and rebuilt.

03
Example: Super Metroid, recompiled
mstan/SuperMetroidRecomp on the snesrecomp framework
Recompile the CPU, emulate the silicon

snesrecomp is a static recompiler that translates 65816 machine code into C and links it against a shared SNES hardware runtime. Only the game logic becomes native code. Graphics, audio, DMA and bank mapping still run through emulation, and any function without a verified translation falls back to an interpreter running the original ROM. Super Metroid is the fourth game on the framework. Its default build boots, plays the attract demo, starts a new game, goes through doors and saves at Samus's ship. The repository ships a CLAUDE.md, and the project belongs to R.A.I.D., a Discord community for AI-assisted retro reverse engineering.

What the CLAUDE.md tells the agent
Rule
Never edit the generated C. Fix the generator, the per-game config or the runtime, then regenerate everything. A partial regeneration breaks references between the 8-bit and 16-bit variants of functions across banks.
Truth
Function boundaries and symbols come from snesrev/sm, an existing human decompilation, pinned to a specific version. The agent does not guess where functions start.
Oracle
A headless snes9x build writes work RAM traces for every frame. Whole-RAM diffs do not line up frame by frame, so the file says to compare the timeline of a single variable instead, such as the game state at $0998.
Gates
Merging investigation branches, releasing and reconciling engine branches need the owner's approval. Debug overlays must not change behavior: a traced run has to match one without tracing.
snesrecomp
Mega Man X

Listed as fully playable, with Windows, macOS and Linux builds and an experimental true widescreen mod.

snesrecomp
Super Mario World

Believed playable end to end, with 4:3, fixed 16:9, an adaptive view and MSU-1 audio.

snesrecomp
A Link to the Past

Playable through the early dungeon. The project calls itself alpha software, and the status table says the same.

04
Example: the NES ancestor, done end to end
Wynplusplus/LLMario
One agent, one ROM, byte-identical output

The 65816 is an extended 6502, the CPU in the NES. LLMario is a matching decompilation of Super Mario Bros. produced end to end by an LLM agent, DeepSeek V4.1 Flash running in OpenCode. Its 6502 listing reassembles byte for byte into the original 32 KB program ROM. The C translation passed 10,910 differential trials against a separate reference interpreter with zero mismatches.

Where it went wrong first

Ghidra on its own found about 1,067 instructions. The agent had to write its own traversal that follows the game's jump table before coverage reached 66.6%. The first verification round failed because five reachable entry points were missing and the differential test could not see the gaps. It passed on the third round. It is not playable yet: there is no sound and no rendering PPU.

The same lesson from a much bigger project

This week momo5502 published a write-up on letting a fleet of Claude Code and Codex agents decompile a PC shooter using 500+ billion tokens. After a month, 80% of the game was "decompiled" and it ran, but the code was semantically wrong. Things only improved once a script compared every function byte for byte against the original compiler output. The agents then tried to edit that script, so CI started checking its hash. The conclusion: "Correctness should be defined and machine-checkable."

05
Where REA fits on a SNES ROM
Honest about the gaps
Ghidra does not speak 65816 out of the box

Ghidra ships with 6502 support but not 65816. There is a community processor module, achan1989/ghidra-65816, that has not been updated since 2024 and may need a rebuild for current Ghidra. REA can force a Ghidra language with REA_GHIDRA_LANGUAGE_ID and checks the value against the languages your install knows. REA's documentation does not cover SNES ROMs, and I have not tested a raw .sfc file. Expect setup work before the first useful answer.

What it adds once it runs

The SNES projects above each built their own tooling: custom traversals, trace scripts, symbol importers. REA gives an agent the generic part for free, meaning cross references, callers, pseudocode and assembly, behind one MCP server and with an evidence record for every call. The project-specific part is still yours to build: the bank map, the M/X state, and the emulator that checks the result.

The question I would start with

A small one. "In this Super Mario World ROM, find the routine that caps Mario's horizontal speed while running. Show the instructions, the RAM addresses it reads and writes, and the constants it compares against. Label each claim as observed or inferred. Then check it in an emulator: hold right with run held and log Mario's X speed for 120 frames." One routine, one question, and a way to check the answer against the real game. That is the same shape as REA's DX-Ball and Touhou showcases, and it is how the larger projects started too.

npx rea-agents setup
export REA_ANALYSIS_PROVIDER=ghidra
export REA_GHIDRA_LANGUAGE_ID=<the 65816 language id from your Ghidra module>

rea --help
06
What the SNES scene already learned
Lessons that apply to any agent-driven reverse engineering
What makes it work
✓A check the agent cannot argue with: byte-identical reassembly, a matching RAM trace, a PASS or FAIL script
✓Ground truth pinned from earlier human work, such as symbols and function boundaries, so the agent builds on it instead of guessing
✓Rules written into the repo: never edit generated code, always regenerate everything
✓Small questions about one routine before big goals like "decompile the game"
Things to keep in mind
!Bring your own ROM. Every project above ships code only and requires a legally obtained copy of the game.
!Reverse engineering is legal for some purposes and not others. REA's README puts that responsibility on you, and it should.
!"It runs" does not mean "it is right". 80% decompiled and wrong is worse than 20% and verified.
Takeaway
The agent handles the navigation. The emulator decides who is right.

REA gives an agent the disassembler work that used to take years. The SNES projects show the other half: pinned ground truth, a machine-checkable oracle, and rules that stop the agent from taking shortcuts. If you have a cartridge you always wanted to understand, pick one routine, write down how you will check the answer, and then run npx rea-agents setup.

github.com/morluto/rea →