Skip to the page
It's Decomplicated
Sony, 1994

PlayStation decomp guide

Two free recompilers make PC builds quick; a byte-exact decomp still takes months.

What this system is like

The PlayStation is one of the busiest systems for this work. RecompLauncher lists 179 projects for 143 games. About three in four call themselves recompiles. A static recompile, or recomp, turns the game's machine code into C or C# by tool.

For Path A you use a shared recomp framework. PSXRecomp writes C and runs on Windows. RecompOne writes C# for .NET. PSXRecomp boots on the free OpenBIOS. RecompOne fakes the BIOS calls in its own code. Either way, you only need your own disc. PSXRecomp still calls itself a beta. Some games reach a first frame in days. A full, clean playthrough takes weeks.

Path B is a matching decomp. You write C that the old Sony compiler turns back into the exact same bytes. The tools are mature, but they live on Linux, so you use WSL. Two PlayStation games now have all their game code matched in C. They are Silent Hill and Yu-Gi-Oh! Forbidden Memories. Both still keep some data or library code as assembly.

Most games load extra code from the disc while they run. These files are called overlays. Each one must be found, split and checked on its own. Plan for this from day one.

Code comes in pieces

A game loads level code from the disc into the same RAM range. These files are overlays. Each overlay needs its own function list and its own check. Miss one and that level never works.

One SDK in every game

Nearly every game links Sony's Psy-Q libraries. Signature files can name those functions for you. Recomp runtimes and port layers like PsyCross replace them. Nobody should decompile them by hand.

The GTE math chip

The GTE has its own instructions for 3D math. Plain Ghidra reads them badly. Use the ghidra_psx_ldr loader. REDRIVER2 had to use IDA for its GTE code.

A CD, not a cartridge

Keep the raw 2352-byte sectors. A cooked .iso drops movie audio and video. Many projects check the disc by hash before they build.

Two frameworks, two AI rules

PSXRecomp welcomes AI-assisted work if it is reviewed and tested. RecompOne rejects AI-written pull requests. Its authors also refuse to help AI-made ports. Pick with that in mind.

Some discs kept debug symbols

A few discs shipped with .SYM debug files. REDRIVER2 got every name and type from two of them. Always look for these before you name anything.

Two paths

Path A

Get it running on PC

A framework reads the boot file and each overlay and writes C. It links that C to a runtime that acts like the console. The free OpenBIOS boots the game, so the game needs no BIOS dump. The Beetle debug oracle is another matter: the framework's own notes start it with a retail BIOS file. You fix crashes in the settings, seeds or framework, never in the made code. This guide uses PSXRecomp because it runs on Windows and welcomes AI-assisted work.

Go to the steps

Path B

Full decomp for porting

You split the game with splat and rebuild it at once from its own assembly. Then you swap assembly for C, one function at a time. Each step must keep the whole file byte for byte the same as the disc. When it is done, you link the C to a Psy-Q stand-in like PsyCross and build for PC. Silent Hill's PC port did this with PsyCross. Yu-Gi-Oh! Forbidden Memories matched its game code the same way, then wrote its own PC layer.

Go to the steps

Path A: Get it running on PC

A framework reads the boot file and each overlay and writes C. It links that C to a runtime that acts like the console. The free OpenBIOS boots the game, so the game needs no BIOS dump. The Beetle debug oracle is another matter: the framework's own notes start it with a retail BIOS file. You fix crashes in the settings, seeds or framework, never in the made code. This guide uses PSXRecomp because it runs on Windows and welcomes AI-assisted work.

Method: static recompilation

Pick this when you want to play on PC soon. It is the right first goal for almost every PlayStation game.

  1. Scope the game and record the disc

    Pick one game and one disc version. Record its hashes so every later check uses the same disc. Look for work that already exists. A finished decomp or a recomp can save you months.

    • Dump your own disc as .bin/.cue with raw 2352-byte sectors. Keep it outside the repo.
    • Read the serial from SYSTEM.CNF, such as SLUS-00707.
    • Record size, MD5, SHA-1 and SHA-256 in DISC.md, like Ape Escape did.
    • Search the RecompLauncher list, GitHub and the PSXRecomp games table for your game.
    • Look for .SYM debug files on every regional disc you own.
    • Write SCOPE.md: goal, serial, hashes, technique, first milestone, its check, and what is out of scope.
    Prompt for Claude
    GOAL: Draft SCOPE.md for a static recomp of <GAME> (<SERIAL>) with PSXRecomp.
    READ FIRST: DISC.md, https://github.com/RetroPortingToolKit/psxrecomp (Games table), the RecompLauncher entry for <GAME> if any.
    FENCE: Create or edit only SCOPE.md and notes/prior-work.md. Do not touch any disc file. Do not install anything.
    CHECK: Run `Get-FileHash -Algorithm SHA256 <BIN PATH>`. Done means the hash it prints is the one in SCOPE.md and DISC.md. SCOPE.md also names the serial, the technique, milestone 1 and its exact check command. Every prior-work claim has a URL.
    BUDGET: Stop after 30 minutes of searching.
    IF BLOCKED: Stop. Tell me what you could not find 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) The SCOPE.md text. 3) Prior work found, with URLs. 4) Open questions for me.
    Done whenGet-FileHash -Algorithm SHA256 on your .bin prints the same hash that SCOPE.md records, and SCOPE.md names one milestone check. You approved it.

    Proof this works: Ape Escape Recompiled - Enhanced Edition (DISC.md with Redump hashes), REDRIVER2 (names from .SYM files), https://github.com/RetroPortingToolKit/psxrecomp

  2. Set up PSXRecomp on Windows

    You install the tools and let the setup script build a first game project. The script probes the disc, writes game.toml and a seed list, and builds. A seed is a known function start address.

    • In PowerShell run winget install Git.Git Python.Python.3.12.
    • Download cmake-clang-v1-windows-x64.zip from the RetroPorting-Toolchains releases. Extract it to C:\RecompDev\Toolchain.
    • Set $env:PSXRECOMP_TOOLCHAIN_DIR to that folder and add its bin to $env:Path.
    • Run git clone --recurse-submodules https://github.com/RetroPortingToolKit/psxrecomp.git.
    • From psxrecomp, run powershell -File tools\new_project_layout\setup_project.ps1 -Disc '<path>\game.cue' -Dir C:\RecompDev -Name <Name> -GithubRepo <folder> -Players 1 -Yes -EnableRecompUi -NoNetplay -NoFetchBoxart -NoGithub -Generate -EnableBuild.
    • Write tools/check.ps1. It rebuilds with python psxrecomp/psxrecomp_cli.py rebuild --config game.toml --project-root . --build-dir build-release --no-pgo.
    • Then it sets $env:PSX_DEBUG_SERVER = '1' and starts the game file from build-release. The build log names that file.
    • It polls python psxrecomp/tools/debug_client.py ping until the frame count passes a target, such as 600. It exits 1 if that takes more than 60 seconds. Step 4 adds the title check to it.
    • Write CLAUDE.md, PROGRESS.md and notes/parking-lot.md.
    Prompt for Claude
    GOAL: Make one command, tools/check.ps1, that rebuilds the <GAME> project and prints PASS or FAIL.
    READ FIRST: SCOPE.md, psxrecomp/docs/GETTING_STARTED.md, psxrecomp/docs/GAME_PROJECT_SETUP.md, psxrecomp/docs/TCP_COMMANDS.md, game.toml.
    FENCE: Edit only tools/, CLAUDE.md, PROGRESS.md and .gitignore. Never edit generated/, psxrecomp/ or recomp-ui/. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run `powershell -File tools/check.ps1`. Done means it rebuilds, boots the game, sees the frame count pass <FRAMES> through `debug_client.py ping`, and exits 0. Then set the frame target to 1000000000 and run it again. It must exit 1 after 60 seconds. Put the target back after.
    BUDGET: Stop after 3 failed tries, or 45 minutes with no progress.
    IF BLOCKED: Stop. Do not work around it. Paste the exact error and the step it came from.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste both check runs. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whentools/check.ps1 exits 0 on a clean checkout once the frame count passes the target. It exits 1 when the target is out of reach.

    Proof this works: https://github.com/RetroPortingToolKit/psxrecomp/blob/master/docs/GETTING_STARTED.md, PaRappa The Rapper Recompiled, ValkyrieRecomp

  3. Map the code and the overlays

    Claude studies the boot file and finds every overlay. It marks Psy-Q library code so nobody spends time on it. The result is a function ledger and an overlay list in files.

    • Install JDK 21 (64-bit), then Ghidra 12.1.4. Add the ghidra_psx_ldr zip built for 12.1.4 (release 2026.10.03). Load the boot EXE with the PSX loader.
    • Apply the Psy-Q signatures the loader offers. Mark matched library functions as sdk in the ledger.
    • Optional: install GhidraMCP and run claude mcp add ghidra -- uvx --from git+https://github.com/LaurieWired/GhidraMCP ghidra-mcp --ghidra-server http://127.0.0.1:8080/.
    • Write notes/functions.csv with address, size, name, kind and status columns.
    • Find the loader code and write notes/overlays.md: file name, load address and how it was proven.
    • Add confirmed function starts to seeds/ghidra_funcs.txt.
    Prompt for Claude
    GOAL: Write notes/functions.csv and notes/overlays.md for <GAME> (<SERIAL>).
    READ FIRST: SCOPE.md, game.toml, seeds/ghidra_funcs.txt, the Ghidra project <PROJECT> (use the ghidra MCP server).
    FENCE: Edit only notes/ and seeds/ghidra_funcs.txt. Ghidra is read-only except for names and comments. Never edit generated/ or psxrecomp/.
    CHECK: Every overlay row gives the loader function address that proves it. Every seed you add is a real function start in Ghidra. Run tools/check.ps1. Done means it still passes.
    BUDGET: Stop after 2 hours, or after 3 overlays you cannot prove.
    IF BLOCKED: Stop. List what you could not prove and why. Do not guess an address.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts: functions, sdk functions, overlays. 3) Check output. 4) Files changed. 5) Unproven items.
    Done whennotes/functions.csv lists every known function with a status, and each overlay in notes/overlays.md cites its loader address.

    Proof this works: Ape Escape Recompiled - Enhanced Edition (docs/AOT_OVERLAYS.md, Ghidra MCP config), MediEvil Recomp (one entry and function map per overlay), https://github.com/lab313ru/ghidra_psx_ldr

  4. First light: boot to the title screen

    You build and run the game until it shows its first frames. A script proves it with a screenshot, so no person has to watch. This becomes your golden run.

    • In PowerShell, set $env:PSX_DEBUG_SERVER = '1', then start the game. The debug server listens on 127.0.0.1 port 4370.
    • Run python psxrecomp/tools/debug_client.py ping to see the frame count rise.
    • Send button presses with the set_input command, then clear_input, to get past the logos.
    • Run python psxrecomp/tools/debug_client.py screenshot path=<abs path>\title.png.
    • Look at the first good title.png yourself. Save it as tests/golden/title.png. That is your approved picture.
    • Make tools/golden_title.py compare each new title.png with the approved one. Fail if too many pixels differ, or if the title is not reached in time.
    • Add tools/golden_title.py to tools/check.ps1.
    Prompt for Claude
    GOAL: Boot <GAME> to its title screen and make tools/golden_title.py prove it with no person watching.
    READ FIRST: SCOPE.md, psxrecomp/docs/TCP_COMMANDS.md, psxrecomp/docs/EXECUTION_MODEL.md, notes/overlays.md.
    FENCE: Edit only game.toml, seeds/ghidra_funcs.txt and tools/. Never edit generated/ by hand: change the inputs and regenerate. Do not stub any function. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run `python tools/golden_title.py`. Done means it saves title.png within <SECONDS> seconds, the picture matches tests/golden/title.png within <TOLERANCE>, and it exits 0. Then run tools/check.ps1. It must pass. Never replace tests/golden/title.png yourself.
    BUDGET: Stop after 4 failed builds, or 60 minutes with no new frame reached.
    IF BLOCKED: Stop. Report the last frame number, the PC address and the missing call. Do not work around it.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the golden run output and attach title.png. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenpython tools/golden_title.py exits 0 inside the time limit, and its title.png matches your approved tests/golden/title.png within the set tolerance.

    Proof this works: Crash Bandicoot PC (bring-up order in docs/CRASH_BANDICOOT_RECOMP.md), https://github.com/RetroPortingToolKit/psxrecomp/blob/master/docs/TCP_COMMANDS.md

  5. Grind: fix one break at a time

    Now Claude fixes one crash, freeze or missing function per session. It compares your build with the Beetle PSX oracle. An oracle is a trusted reference that shows the right answer. Every fix goes in the seeds, the config or the framework.

    • Write the route list in PROGRESS.md: title, menu, first level, each later level.
    • Build the psx-beetle oracle from the framework source. Its steps are in section 16 of psxrecomp/CLAUDE.md. It listens on port 4380.
    • For a freeze, bring both programs to the same point. Run python psxrecomp/tools/debug_client.py get_registers, then the same with --port 4380. Compare the two.
    • Do not use debug_client.py compare for this. It checks port 4371, the old DuckStation oracle, not Beetle.
    • Add missed function starts to the seeds. Then run python psxrecomp/psxrecomp_cli.py generate --config game.toml --project-root . --disc <path>\game.cue.
    • Log each case in ISSUES.md: addresses, what was tried, what failed, where it stopped.
    • Fix the bring-up classes in the order Crash Bandicoot PC used: BIOS and pad, CD, GPU present, VSync, memcpy, jump tables.
    Prompt for Claude
    GOAL: Fix one break: <SYMPTOM> at <ROUTE POINT> in <GAME>.
    READ FIRST: CLAUDE.md, ISSUES.md, notes/overlays.md, psxrecomp/docs/TCP_COMMANDS.md.
    FENCE: Edit only game.toml, seeds/ghidra_funcs.txt, ISSUES.md and tools/. Never edit generated/. Never deliver a fake event, add a stub or return a made-up value. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run tools/check.ps1 and `python tools/golden_route.py <ROUTE POINT>`. Done means both pass, and the old golden runs still pass.
    BUDGET: Stop after 3 failed fixes, or 60 minutes with no new evidence.
    IF BLOCKED: Stop. Show the first divergence from the Beetle oracle on port 4380 (address, register, frame). Say what you need. Do not guess.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The proven cause, with the oracle output. 3) Check output. 4) Files changed. 5) New parking-lot items.
    Done whenThe new route point passes its golden run, and every older golden run still passes.

    Proof this works: Crash Bandicoot PC (VSync and root-counter fixes), Ape Escape Recompiled - Enhanced Edition (ISSUES.md log), https://github.com/RetroPortingToolKit/psxrecomp/blob/master/CLAUDE.md, https://github.com/RetroPortingToolKit/psxrecomp/blob/master/tools/debug_client.py (compare uses ports 4370 and 4371)

  6. Cover every overlay and disc

    Reaching the title screen does not prove later levels work. Each overlay must be compiled ahead of time or caught and cached. You walk the whole game and close each gap.

    • Read psxrecomp/docs/AOT_SHARDING.md and list each overlay's bytes and loader in notes/overlays.md.
    • Add one golden run per level or area. Use saved inputs, not live play.
    • For a multi-disc game, register the set with python psxrecomp/tools/new_project_layout/update_disc_set.py --game-toml game.toml <disc1.cue> <disc2.cue>.
    • Mark each overlay in the ledger as native, cached or excluded, with the reason.
    Prompt for Claude
    GOAL: Make overlay <OVERLAY FILE> of <GAME> run as native code, proven by a golden run.
    READ FIRST: notes/overlays.md, psxrecomp/docs/AOT_SHARDING.md, psxrecomp/docs/EXECUTION_MODEL.md, ISSUES.md.
    FENCE: Edit only game.toml, seeds/, notes/ and tools/. Never edit generated/ or psxrecomp/. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run tools/check.ps1 and `python tools/golden_route.py <AREA>`. Done means both pass and the ledger row reads native or cached.
    BUDGET: Stop after 3 failed tries on this overlay.
    IF BLOCKED: Stop. Report the overlay bytes, loader address and what the runtime said. Record it as excluded with the reason. Do not hide it.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Ledger row before and after. 4) Files changed.
    Done whenEvery overlay row in notes/overlays.md is native, cached or excluded with a reason, and each area has a passing golden run.

    Proof this works: Ape Escape Recompiled - Enhanced Edition (49 AOT overlay images, two documented exclusions), Symphony Recomp (127 overlay function maps), https://github.com/RetroPortingToolKit/psxrecomp

  7. Harden: a regression set and clean builds

    You make old fixes stay fixed. Saved inputs replay the route on every change. A clean checkout must build and pass with one command. Then you check the release zip itself.

    • Run every golden run from tools/check.ps1. Fail on any one.
    • Pin the framework submodules and record the commits in framework_pins.txt.
    • Build from a fresh clone in a new folder. Run the full check there.
    • Open the release zip outside any git folder and launch it. Check that it holds no .bin, .cue or BIOS file.
    Prompt for Claude
    GOAL: Make tools/check.ps1 run the full regression set for <GAME> from a fresh clone.
    READ FIRST: PROGRESS.md, tools/, framework_pins.txt, the PaRappa and Ape Escape release checks as examples.
    FENCE: Edit only tools/, PROGRESS.md and framework_pins.txt. Do not change any expected screenshot or hash. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: In a fresh clone, run `powershell -File tools/check.ps1`. Done means every golden run passes and the zip check finds no disc or BIOS file.
    BUDGET: Stop after 3 failed tries.
    IF BLOCKED: Stop. Say which run failed and paste its output.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Full check output. 3) Files changed. 4) What is left.
    Done whenA fresh clone passes the full regression set with one command, and the zip check passes.

    Proof this works: PaRappa The Rapper Recompiled (framework_pins.txt, CI zip checks), Ape Escape Recompiled - Enhanced Edition (extract the zip outside git and launch it), ValkyrieRecomp (CI tests the finished artifact)

  8. Add enhancements one at a time

    Only after the stock game works do you add widescreen, higher resolution or mods. Each feature gets its own check. With the feature off, the game must act exactly as before.

    • Turn on the [widescreen] block in game.toml and find the game's cull sites.
    • Compare the same frame with the feature on and off. Do not compare two separate runs.
    • Keep mods as .psxmod packages with byte guards, not as edits to made code.
    • Add one golden run per feature to the regression set.
    Prompt for Claude
    GOAL: Add <FEATURE> to <GAME> without changing the stock game.
    READ FIRST: psxrecomp/docs/WIDESCREEN.md, psxrecomp/psxmod.md, PROGRESS.md.
    FENCE: Edit only game.toml, mods/ and tools/. Never edit generated/. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run tools/check.ps1 with the feature off: all golden runs must pass unchanged. Then run tools/golden_feature.py <FEATURE>. Done means both pass.
    BUDGET: Stop after 3 failed tries.
    IF BLOCKED: Stop. Show the frame where it breaks and say why.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Both check outputs. 3) Files changed. 4) Known limits.
    Done whenWith the feature off, every golden run passes unchanged; with it on, its own golden run passes.

    Proof this works: Crash Bandicoot PC (WideCheck compares the same ordering table), https://github.com/RetroPortingToolKit/psxrecomp/blob/master/docs/WIDESCREEN.md

Path B: Full decomp for porting

You split the game with splat and rebuild it at once from its own assembly. Then you swap assembly for C, one function at a time. Each step must keep the whole file byte for byte the same as the disc. When it is done, you link the C to a Psy-Q stand-in like PsyCross and build for PC. Silent Hill's PC port did this with PsyCross. Yu-Gi-Oh! Forbidden Memories matched its game code the same way, then wrote its own PC layer.

Method: matching decompilation

Pick this when you want readable source to port, mod or study. It takes many months. Do Path A first if you just want to play.

  1. Scope: prior work and the compiler

    Check if someone already started a decomp of your game. Look for debug symbols. Note which Psy-Q compiler the game may use. This decides months of work.

    • Search GitHub and decomp.dev for <game> decomp. Known PS1 decomps include sotn-decomp, silent-hill-decomp, memories-decomp and CTR-ModSDK.
    • Look for .SYM files on each regional disc. Dump them with symdump if found.
    • Note the Psy-Q library version strings in the boot EXE.
    • Write SCOPE.md with the EXE hash, the plan for each overlay and what is out of scope.
    Prompt for Claude
    GOAL: Draft SCOPE.md for a matching decomp of <GAME> (<SERIAL>).
    READ FIRST: DISC.md, https://github.com/Xeeynamo/sotn-decomp, https://github.com/shdecompilations/silent-hill-decomp, https://decomp.dev.
    FENCE: Create or edit only SCOPE.md and notes/prior-work.md. Do not install anything. Do not touch disc files.
    CHECK: Run `sha256sum <BOOT EXE>` in WSL. Done means it prints the SHA-256 written in SCOPE.md. SCOPE.md also gives the overlay count, a compiler guess with its evidence, and milestone 1 with its check. Every claim has a URL or an address.
    BUDGET: Stop after 45 minutes.
    IF BLOCKED: Stop. Say what you could not find and what you need.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) SCOPE.md text. 3) Prior work with URLs. 4) Questions for me.
    Done whensha256sum on the boot EXE prints the hash in SCOPE.md, which also gives the overlay count and a compiler guess with evidence. You approved it.

    Proof this works: REDRIVER2 (debug symbols from Italian and Spanish discs), Forbidden Memories Recompiled (compiler fingerprinting), https://github.com/stohrendorf/symdump

  2. Set up WSL and the one check

    You build the matching toolchain in WSL. You extract the boot EXE and overlays from your disc. The one check rebuilds them and compares SHA-256 hashes.

    • In WSL Ubuntu 24.04 run sudo apt install git make python3-venv binutils-mipsel-linux-gnu. maspsx calls mipsel-linux-gnu-as by default, and sotn-decomp installs this package.
    • Make a venv and run python3 -m pip install -U splat64[mips].
    • Download a gcc-2.8.1-psx or gcc-2.7.2-psx tarball from the old-gcc releases into tools/.
    • Add maspsx as a submodule: git submodule add https://github.com/mkst/maspsx tools/maspsx.
    • Run dumpsxiso on your .cue to get the boot EXE and overlay files. Keep them in an ignored folder.
    • Write checksum.sha and a make check target that runs sha256sum -c checksum.sha.
    Prompt for Claude
    GOAL: Make `make check` rebuild <GAME>'s boot EXE and compare its SHA-256 with checksum.sha.
    READ FIRST: SCOPE.md, https://github.com/ethteck/splat, https://github.com/mkst/maspsx, https://github.com/decompals/old-gcc.
    FENCE: Edit only Makefile, tools/, config/ and .gitignore. Never edit checksum.sha after I approve it. Never commit game files. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run `make clean && make check` in WSL. Done means it prints OK for the boot EXE. Then, on a throwaway git branch, change one instruction in one asm file and run it again. It must print FAILED. Delete the branch after.
    BUDGET: Stop after 3 failed tries, or 60 minutes with no progress.
    IF BLOCKED: Stop. Paste the exact error. Do not edit the checksum to get a pass.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Both check runs. 3) Files changed. 4) What is left.
    Done whenmake clean && make check prints OK in WSL, and fails when one byte is wrong.

    Proof this works: Silent Hill Decomp (sha256sum against configs/<version>/checksum.sha), Forbidden Memories Recompiled (make match accepts only the retail SHA-256), https://github.com/Xeeynamo/sotn-decomp/wiki/Build

  3. Split the EXE and each overlay

    splat cuts the EXE into code and data files. At first every function is plain assembly. The build must still match before you write any C.

    • Run python3 -m splat create_config <BOOT EXE> to get a first yaml. Move it to config/<serial>.yaml.
    • Check the yaml's load address against the EXE header. Fix it if needed.
    • Run python3 -m splat split config/<serial>.yaml.
    • Write one yaml and one checksum per overlay, with its own load address.
    • Run make check. Fix the yaml until every file matches.
    Prompt for Claude
    GOAL: Split <GAME>'s boot EXE with splat so the all-assembly build matches.
    READ FIRST: config/<SERIAL>.yaml, notes/functions.csv, https://github.com/ethteck/splat/wiki.
    FENCE: Edit only config/ and symbol_addrs.txt. Never edit asm/ files by hand: regenerate them with splat. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run `make clean && make check`. Done means it prints OK.
    BUDGET: Stop after 4 failed tries.
    IF BLOCKED: Stop. Paste the first mismatching offset and the yaml segment around it.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Segment count. 4) Files changed.
    Done whenThe all-assembly build of the EXE matches, and each split overlay passes its own checksum.

    Proof this works: Silent Hill Decomp (splat yaml per version, overlays per map), Forbidden Memories Recompiled (config/slus_01411/split.yaml), https://github.com/ethteck/splat/blob/main/src/splat/scripts/create_config.py (reads a PS-X EXE)

  4. Map functions and mark the SDK

    Claude fills the function ledger. Psy-Q library functions get marked so they stay as assembly or come from a shared decomp. Game functions get a size and an easy, medium or hard tag.

    • Load the EXE in Ghidra with ghidra_psx_ldr and apply the Psy-Q signatures.
    • Mark matched SDK functions as sdk in notes/functions.csv.
    • Keep names as func_<address> until a name has evidence.
    • Sort game functions by size. Small leaf functions go first.
    Prompt for Claude
    GOAL: Fill notes/functions.csv for <GAME> with address, size, name, kind and status.
    READ FIRST: asm/ (read-only), symbol_addrs.txt, the Ghidra project <PROJECT> through the ghidra MCP server.
    FENCE: Edit only notes/functions.csv and symbol_addrs.txt. Never edit asm/ or src/. Do not rename a symbol without evidence written in the notes column.
    CHECK: Run `make clean && make check` and `python3 tools/ledger_check.py`. Done means both pass and every row has a size and a status.
    BUDGET: Stop after 2 hours.
    IF BLOCKED: Stop. List the rows you could not fill and why.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts by kind and status. 3) Check output. 4) Files changed.
    Done whenEvery function in the ledger has a size, a kind (game or sdk) and a status, and make check still passes.

    Proof this works: PsyDoom (PSXObjSigGen and PSXExeSigMatcher to name SDK code first), Forbidden Memories Recompiled (functions.csv as the one inventory), https://github.com/lab313ru/ghidra_psx_ldr

  5. First light: find the compiler, match one function

    You prove the toolchain by matching one small function. This settles the GCC version, the ASPSX version and the flags. Write the winning setup down as a named profile.

    • Pick a small leaf function with no calls.
    • Get a first draft with python3 m2c.py -t mipsel-gcc-c -f <func> asm/<file>.s.
    • Try gcc-2.8.1-psx and gcc-2.7.2-psx with maspsx --aspsx-version=<ver>. Change one thing per try.
    • Use objdiff or decomp.me with a psyq4.x preset to compare.
    • Save the winner in config/compiler_profiles.json. Never put flags in one-off commands.
    Prompt for Claude
    GOAL: Match one small function, <FUNC>, and record the compiler profile that did it.
    READ FIRST: asm/<FILE>.s, notes/functions.csv, https://github.com/mkst/maspsx (ASPSX version table), config/compiler_profiles.json.
    FENCE: Edit only src/<FILE>.c, config/compiler_profiles.json and notes/attempts.csv. Never edit asm/, checksum.sha or the Makefile check. No inline asm, no register pins, no embedded bytes.
    CHECK: Run `make clean && make check`. Done means OK with <FUNC> built from C, and objdiff shows 100% for it.
    BUDGET: Stop after 12 attempts. Log each one in notes/attempts.csv with the profile and the first difference.
    IF BLOCKED: Stop. Report the best score, the profiles tried and the first differing instruction.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) The profile. 4) Files changed.
    Done whenOne function is built from C, make check still prints OK, and its compiler profile is saved.

    Proof this works: Forbidden Memories Recompiled (GCC 2.8.1 + ASPSX 2.81 with -O2 -G8 -mips1), Silent Hill Decomp (gcc 2.8.1-psx and 2.7.2-cdk with maspsx 2.67 and 2.77), https://decomp.me

  6. Grind: match functions in parallel

    Now workers match one function each. A script picks the next one, not the model. Every try is logged, so no session repeats a dead end. The full build hash is the only verdict.

    • Hand out functions by size, smallest first. Later, pick ones that look like matched ones.
    • Give each worker its own worktree with claude -w <name>.
    • Run decomp-permuter only on near misses, and have Claude explain the result.
    • Commit each verified match on its own. Reset the worktree after a failure.
    • Merge, then run make clean && make check on the merged branch.
    Prompt for Claude
    GOAL: Make <FUNC> in src/<FILE>.c match 100%.
    READ FIRST: asm/<FILE>/<FUNC>.s, notes/attempts.csv rows for <FUNC>, config/compiler_profiles.json, up to 3 matched functions that look like it.
    FENCE: Edit only src/<FILE>.c and notes/attempts.csv. Never edit asm/, include/ shared headers, checksum.sha or the Makefile. No inline asm, no register pins, no embedded bytes, no goto added only to match. Use only named compiler profiles.
    CHECK: Run `make clean && make check`. Done means OK, and objdiff shows 100% for <FUNC>.
    BUDGET: Stop after 10 attempts, or 4 attempts with no gain. Log every attempt with its mismatch reason.
    IF BLOCKED: Stop. Report the best score, the first differing instructions and a cause class. Leave the function as assembly.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Diff summary. 4) Files changed.
    Done whenThe ledger shows the target share of game functions matched, and make clean && make check prints OK on the merged branch.

    Proof this works: Forbidden Memories Recompiled (attempt ledger, make candidates, make match-incremental), Silent Hill Decomp (objdiff, permuter, m2c), https://github.com/Ketbome/decomp-skills

  7. Finish overlays and data

    Each overlay gets the same loop. Then raw data becomes typed C structs. Names replace func_ addresses when there is evidence. A runtime trace answers what static reading cannot.

    • Run the unit loop per overlay, each with its own checksum.
    • Move data tables into C structs and keep make check green.
    • For a runtime question, write a short PCSX-Redux Lua script. Run it with pcsx-redux -interpreter -debugger -iso <cue> -dofile <script>.lua.
    • Paste the result into notes/ with what you saw. Then delete the script.
    Prompt for Claude
    GOAL: Bring overlay <OVERLAY> of <GAME> to 100% matched code.
    READ FIRST: config/<OVERLAY>.yaml, notes/functions.csv rows for <OVERLAY>, notes/attempts.csv.
    FENCE: Edit only src/<OVERLAY>/ and notes/. Never edit asm/, checksum files or the Makefile. Never touch other overlays.
    CHECK: Run `make clean && make check`. Done means OK for the EXE and every overlay.
    BUDGET: Stop after 3 hours, or when the remaining functions all have 10 failed attempts.
    IF BLOCKED: Stop. List the functions left and their best scores.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Matched count before and after. 4) Files changed.
    Done whenEvery overlay's checksum passes with all game code in C, except functions listed as assembly with evidence.

    Proof this works: Forbidden Memories Recompiled (all five overlays 100%, 61 functions kept as handwritten assembly with evidence), Forbidden Memories Recompiled (PCSX-Redux Lua traces in tools/trace), https://pcsx-redux.consoledev.net/cli_flags/

  8. Harden: verify and hunt for cheats

    A fresh agent re-checks the claimed work. It looks for tricks that pass the hash but are not real C. A clean clone must pass the full check.

    • In a fresh clone run make clean && make check.
    • Search src/ for asm(, __asm__, register pins and stray goto.
    • Confirm checksum.sha and the Makefile have not changed since you approved them.
    • Add a Claude Code hook that blocks edits to asm/, checksum.sha and Makefile.
    Prompt for Claude
    GOAL: Verify the last <N> claimed matches in <GAME> are real.
    READ FIRST: git log for the last <N> commits, notes/attempts.csv, CLAUDE.md banned list.
    FENCE: Read-only. Do not edit any file except notes/verify-<DATE>.md.
    CHECK: In a fresh clone run `make clean && make check`. Done means OK, plus a written verdict per commit.
    BUDGET: Stop after 90 minutes.
    IF BLOCKED: Stop. Say what you could not check.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Per commit: real, suspect or cheat, with the line. 4) Any change to checksum.sha, the Makefile or asm/.
    Done whenA fresh clone prints OK, and the verify note finds no inline asm, no edited checksum and no edits outside the fence.

    Proof this works: Forbidden Memories Recompiled (check-matching-source-contracts and other policy checks), https://github.com/cdlewis/snowboardkids2-decomp/tree/main/.claude/hooks

  9. Port: link the C to a Psy-Q stand-in

    You build the matched C for PC against a layer that acts like Psy-Q. Build 32-bit first, because the code stores pointers in 32-bit fields. Mark every port change so the matching build stays the same.

    • Add PsyCross as a submodule. PsyZ is a newer choice with 64-bit support.
    • Wrap each PC change in one #ifdef, like SH_PC_PORT in Silent Hill.
    • Build with -m32 first. Add _Static_assert checks for struct layouts.
    • Build overlays as DLLs, or compile all in and track which one is loaded.
    • Keep make check passing for the console build after every port change.
    • Add golden runs and input replays for the PC build.
    Prompt for Claude
    GOAL: Get <GAME>'s matched C to boot to the title screen on PC through PsyCross.
    READ FIRST: SCOPE.md, https://github.com/OpenDriver2/PsyCross, the Silent Hill port docs on struct offsets, notes/overlays.md.
    FENCE: Edit only port/ and code inside #ifdef <GAME>_PC_PORT blocks. Never change the console build output. Do not add features, refactors, tools or cleanups I did not ask for.
    CHECK: Run `make clean && make check` (console build still OK) and `port/golden_title.sh` (PC build reaches the title in <SECONDS> seconds).
    BUDGET: Stop after 4 failed builds, or 90 minutes with no new frame.
    IF BLOCKED: Stop. Report the crash address, the struct or call involved, and what you need.
    OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Both check outputs. 3) Every port change listed in notes/port-fixes.md. 4) Files changed.
    Done whenThe console build still prints OK, and the PC build passes the same golden runs to the title and first level.

    Proof this works: Silent Hill Decomp (PsyCross, SH_PC_PORT, map DLLs, _Static_assert), CTR Native (32-bit first, retail-shaped GPU packets), https://github.com/Xeeynamo/psyz

Tools you need

ToolWhat it doesHow to get itHow we know
PSXRecomp
Required both
A PlayStation recomp framework. It turns MIPS code into C and links it to a shared runtime. It ships the free OpenBIOS and a debug server.
Path A
`winget install Git.Git Python.Python.3.12`, extract `cmake-clang-v1-windows-x64.zip`, then `git clone --recurse-submodules https://github.com/RetroPortingToolKit/psxrecomp.git`README, CLAUDE.md, docs/GETTING_STARTED.md, docs/GAME_PROJECT_SETUP.md and docs/TCP_COMMANDS.md (read 2026-11-13). mstan/psxrecomp now redirects here. Used by: ValkyrieRecomp, PaRappa, Ape Escape, Parasite Eve HD.
RecompOne
Helpful both
A second recomp framework. It turns MIPS code into C# and runs it on .NET. Its authors reject AI-written pull requests.
Path A
Install the .NET 10 SDK, add RecompOne as a submodule, then `dotnet build RecompOne.Recompiler -c Release`README and wiki page 'How to recompile a game?' (read 2026-11-13; the wiki marks itself outdated). Used by: Symphony Recomp, MediEvil Recomp, Crash Bandicoot PC.
Ghidra
Required both
A free disassembler and decompiler. It shows the game's code as assembly and rough C.
Path A Path B
Install JDK 21 (64-bit), download `ghidra_12.1.4_PUBLIC_20260921.zip` from the releases page, extract it, run `ghidraRun.bat`. Use 12.1.4, not 12.2, because GhidraMCP 2.0 needs it. Ghidra 12.2 asks for JDK 25.README at tag Ghidra_12.1.4_build (JDK 21) and current README (JDK 25), releases list (latest Ghidra_12.2_build), read 2026-11-13. Used by: REDRIVER2, ValkyrieRecomp, Ape Escape, GT2 PC, Silent Hill.
ghidra_psx_ldr
Required both
A Ghidra add-on that loads PS-X EXE files. It applies Psy-Q signatures and decodes GTE instructions.
Path A Path B
Download `ghidra_12.1.4_PUBLIC_20261004_ghidra_psx_ldr.zip` from release 2026.10.03, then in Ghidra use File, Install ExtensionsREADME and releases (read 2026-11-13). Release 2026.10.03 has a 12.1.4 build. Used by: Silent Hill Decomp.
GhidraMCP
Helpful both
An MCP server that lets Claude ask Ghidra for code, names and references. MCP is a plug-in link between Claude and a tool.
Path A Path B
Install the release zip in Ghidra 12.1.4, install `uv`, then `claude mcp add ghidra -- uvx --from git+https://github.com/LaurieWired/GhidraMCP ghidra-mcp --ghidra-server http://127.0.0.1:8080/`README, release 2.0 (read 2026-11-13). Ghidra MCP named in the PSXRecomp rules and in Ape Escape's .mcp.json.example.
PCSX-Redux
Helpful both
A PlayStation emulator built for debugging. It has Lua scripts, a GDB server and breakpoints. OpenBIOS comes from this project.
Path A Path B
Download the Windows x64 build from the README's download table. Linux AppImages are listed there too.README and https://pcsx-redux.consoledev.net/cli_flags/ (read 2026-11-13). Used by: Forbidden Memories Recompiled (Lua traces).
mkpsxiso / dumpsxiso
Required both
dumpsxiso pulls every file off a PlayStation disc image and writes an XML layout. mkpsxiso builds a disc back.
Path B
Download the release zip for your system from the releases pageREADME, release v2.30 (read 2026-11-13). Used by: Silent Hill Decomp, REDRIVER2.
splat
Required WSL/Linux
Splits a PS-X EXE or overlay into assembly and data files. It writes the build pieces for a matching decomp.
Path B
In WSL: `python3 -m pip install -U splat64[mips]`README (read 2026-11-13): supports N64, PSX, PS2 and PSP. Used by: Silent Hill Decomp, Forbidden Memories Recompiled, sotn-decomp.
old-gcc
Required WSL/Linux
Prebuilt old GCC versions, including PlayStation builds like gcc-2.8.1-psx and gcc-2.7.2-cdk.
Path B
In WSL, download the `-psx` tarball you need from the releases page and extract it into `tools/`README and release 0.17 asset list (read 2026-11-13). Used by: Forbidden Memories Recompiled.
maspsx
Required WSL/Linux
Stands in for Sony's ASPSX assembler. It reshapes GCC output so GNU as builds the same object.
Path B
`git submodule add https://github.com/mkst/maspsx tools/maspsx`; needs `binutils-mipsel-linux-gnu`, since it calls `mipsel-linux-gnu-as` unless you pass `--gnu-as-path`README with the ASPSX 1.05 to 2.86 table (read 2026-11-13). Used by: Silent Hill Decomp, Forbidden Memories Recompiled, sotn-decomp.
objdiff
Required both
Shows how close your compiled function is to the original, instruction by instruction. It supports PS1 MIPS.
Path B
Download `objdiff-windows-x86_64.exe`, or the CLI from the releases pageREADME, release v3.8.3 (read 2026-11-13). Used by: Silent Hill Decomp.
m2c
Helpful WSL/Linux
Turns one function's assembly into a rough C draft. You then fix the draft until it matches.
Path B
In WSL: `git clone https://github.com/matt-kempster/m2c`, then run `python3 m2c.py -t mipsel-gcc-c`README (read 2026-11-13). Used by: Silent Hill Decomp, Forbidden Memories Recompiled, sotn-decomp.
decomp-permuter
Helpful WSL/Linux
Tries many small random changes to a C function to find a closer match. Use it only on near misses.
Path B
In WSL: clone it, then `python3 -m pip install pynacl toml Levenshtein`README (read 2026-11-13): permuter@home does not work on native Windows, WSL does. Used by: Silent Hill Decomp, Forbidden Memories Recompiled.
PsyCross
Required both
Rebuilds the Psy-Q libraries on SDL2, OpenGL and OpenAL. Decompiled games link to it to run on PC.
Path B
`git submodule add https://github.com/OpenDriver2/PsyCross`; needs SDL2 2.0.16+ and OpenAL-soft 1.21+README (read 2026-11-13). Used by: REDRIVER2, Silent Hill Decomp, CTR Native (as a starting point).
symdump
Helpful Windows
Reads the .SYM debug files that a few discs shipped with. It prints names and types, like Sony's own DUMPSYM.EXE.
Path B
Download `symdump.exe` from release 1.0 on the releases page. It is a C# program from 2017.README and releases list (read 2026-11-13). Its command-line options were not read. Used by: REDRIVER2.

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 (Ketbome)

skills.sh

A one-function loop with a small dk.py tool for MIPS games on a splat layout. It lists PS1 and keeps state in files. It needs Python 3.9+ with pyelftools, and it makes git commits, so save your work first.

npx skills add ketbome/decomp-skills --skill matching-decomp -a claude-code

decompile-to-matching-c-cpp

skills.sh

Rules for byte-matching C that ban fake matches. It fits the splat, m2c and objdiff setup used here.

npx skills add xsyetopz/skills --skill decompile-to-matching-c-cpp -a claude-code

debug-game-in-emulator

skills.sh

Makes each emulator run the same: a throwaway data folder, a log and a time limit. It lists PS1 and DuckStation. It expects your own BIOS dump, unlike the OpenBIOS path above.

npx skills add xsyetopz/skills --skill debug-game-in-emulator -a claude-code

n64-decomp-splat

skills.sh

A reference for splat yaml files. It was written for N64, but its author says most of it fits PS1.

npx skills add marijnvdwerf/agent-skills --skill n64-decomp-splat -a claude-code

verification-before-completion

skills.sh

Claude may not say done without fresh proof. That fits golden runs and make check.

npx skills add obra/superpowers --skill verification-before-completion -a claude-code

dispatching-parallel-agents

skills.sh

Helps a lead session brief one worker per function or per overlay.

npx skills add obra/superpowers --skill dispatching-parallel-agents -a claude-code

handoff

skills.sh

Writes a short note so a fresh session can carry on. Tell it to save inside your repo, not the temp folder.

npx skills add mattpocock/skills --skill handoff -a claude-code

GhidraMCP

MCP server

The PSXRecomp author needed Ghidra in the loop to stop Claude from guessing. Ape Escape ships a Ghidra MCP example config.

claude mcp add ghidra -- uvx --from git+https://github.com/LaurieWired/GhidraMCP ghidra-mcp --ghidra-server http://127.0.0.1:8080/

psx-unit-match

write-your-own

Every worker matches the same way, with the same stop rule and the same log.

A project skill in `.claude/skills/psx-unit-match/SKILL.md`. It reads one function's `.s` file, its ledger rows and three similar matched functions. It runs `m2c`, then loops on `make clean && make check` with one change per try. It logs each try to `notes/attempts.csv` and stops at 10 tries. It names the banned tricks: inline asm, register pins, embedded bytes.

psx-crash-triage

write-your-own

Path A bugs get a proven cause first. That stops stubs and fake events.

A project skill in `.claude/skills/psx-crash-triage/SKILL.md`. It starts the build with `PSX_DEBUG_SERVER=1`. It reads `get_registers` from port 4370 and from the Beetle oracle on port 4380, one at a time, and compares them. It never uses `compare`, which points at the old port 4371. It reads the PC address in Ghidra and writes the first divergence to `ISSUES.md` before any fix.

Claude setup for this system

On Path A, one unit is one crash, one missing function or one overlay. Each unit has a golden run that a script checks. On Path B, one unit is one function. Its check is the full make clean && make check hash. Group work by overlay, so two workers never edit the same file. Keep the Psy-Q library out of the queue.

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 projectCheck for an existing decomp, recomp or .SYM files. Pick the disc version and the framework. 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 PSXRecomp on Windows, or the splat, old-gcc and maspsx toolchain in WSL. Write tools/check.ps1 or make check.Opus 5.5
effort medium
Sonnet 5.5
effort medium
Study the game fileLoad the EXE with ghidra_psx_ldr. Mark Psy-Q code, find overlay loaders and fill notes/functions.csv.Opus 5.5
effort high
Opus 5.5
effort medium
Raise to high for function edges and data layouts. A mistake there spreads.
Bulk unitsMatch small game functions, one per worker. Add proven seeds for missed functions.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 unitsBig functions, GTE-heavy code and odd ASPSX output. Functions that failed 10 bulk tries.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 runtimeFramework fixes on Path A: timing, VSync, CD and XA, pad input. On Path B, port glue in PsyCross or PsyZ.Opus 5.5
effort high
Opus 5.5
effort medium
Raise to high for timing and graphics bugs.
Find a bugFreezes and wrong frames. Compare with the Beetle oracle or a PCSX-Redux trace before any fix.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 the check in a clean clone. It hunts for inline asm, edited hashes, stubs and fake events.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, ISSUES.md, the ledger and the parking lot after each unit.Haiku 5.5
effort medium
Haiku 5.5
effort medium

How many sessions at once

Max 20x (now called Ultra)

Path B: run 3 to 5 workers, each in its own worktree on its own overlay or file group. Add one lead and one verify session. Path A: run 1 or 2 workers on separate areas, since most fixes touch shared config.

Max 5x (now called Max)

Path B: run 1 or 2 workers and a verify pass at the end of the day. Path A: one worker at a time. Save hard units for when you have room in your weekly limit.

Lines for this project's CLAUDE.md

Add to CLAUDE.md
- Read `SCOPE.md` and `PROGRESS.md` at the start of every session.
- Never edit files in `generated/` or `asm/`. Change the seeds, the config or the generator, then regenerate.
- The only verdict is `make clean && make check` (Path B) or `powershell -File tools/check.ps1` (Path A). A diff score is evidence, not proof.
- Never edit `checksum.sha`, `DISC.md` hashes, golden screenshots or the check scripts.
- No stubs, no fake events, no made-up return values. A missing function aborts with an error.
- No inline asm, register pins or embedded bytes to force a match.
- Use only named compiler profiles from `config/compiler_profiles.json`.
- Keep names as `func_<address>` until you have evidence. Write the evidence in the ledger.
- Log every attempt in `notes/attempts.csv` with its mismatch reason. Read it before you start a function.
- If you cannot answer from Ghidra, the disassembly or the oracle, say 'I don't know yet'.
- Put side issues in `notes/parking-lot.md`. Do not fix them.
- In a worktree, use absolute paths and run the build only inside that worktree.

Keep the context small

  • Give Claude a function address and file path, not pasted assembly.
  • Ask a subagent to read big Ghidra output and report ten lines back.
  • Clear the chat after each function or crash. Start the next one from the ledger.
  • Keep CLAUDE.md short. Point to notes/ by topic.
  • Use the debug server for runtime state. Do not dump huge log files.

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 choose Path A or Path B for one game.

Prompt for Claude
GOAL: Tell me if <GAME> (<SERIAL>) is a good PlayStation project, and by which path.
READ FIRST: DISC.md, https://github.com/RetroPortingToolKit/psxrecomp, https://github.com/BlackLabelHQ/RecompOne, decomp.dev, GitHub search for '<GAME> decomp' and '<GAME> recomp'.
FENCE: Write only notes/feasibility.md. Do not install anything or touch disc files.
CHECK: Run `Get-FileHash -Algorithm SHA256 <BIN PATH>`. Done means the hash matches DISC.md, and the note lists prior work with URLs, the overlay count from the disc file list, and a path choice with three reasons.
BUDGET: Stop after 45 minutes.
IF BLOCKED: Stop. Say what you could not learn.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Path A or B, and why. 3) Prior work. 4) Risks. 5) A draft SCOPE.md.

A good answer: A clear pick, real URLs, an overlay count and a draft SCOPE.md. It says plainly if a decomp already exists.

Map the binary

After setup, to build the function ledger and overlay list.

Prompt for Claude
GOAL: Build notes/functions.csv and notes/overlays.md for <GAME>.
READ FIRST: SCOPE.md, the Ghidra project <PROJECT> through the ghidra MCP server, the disc file list from dumpsxiso.
FENCE: Edit only notes/. Ghidra: names and comments only.
CHECK: Every function row has address, size, kind and status. Every overlay row cites its loader address. Run `python3 tools/ledger_check.py`. Done means it passes.
BUDGET: Stop after 2 hours.
IF BLOCKED: Stop. List what you could not prove.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts. 3) Check output. 4) Unproven items.

A good answer: Counts of game and SDK functions, a list of overlays with loader addresses, and a short list of open items.

Unit loop, Path A (one break)

For each crash, freeze or missing function in the recomp.

Prompt for Claude
GOAL: Fix <SYMPTOM> at <ROUTE POINT> in the <GAME> recomp.
READ FIRST: ISSUES.md, notes/overlays.md, psxrecomp/docs/TCP_COMMANDS.md.
FENCE: Edit only game.toml, seeds/ and ISSUES.md. Never edit generated/. No stubs, no fake events.
CHECK: Run tools/check.ps1 and `python tools/golden_route.py <ROUTE POINT>`. Done means both pass.
BUDGET: Stop after 3 failed fixes.
IF BLOCKED: Stop. Show the first divergence from the Beetle oracle on port 4380.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proven cause. 3) Check output. 4) Files changed.

A good answer: DONE with the oracle evidence for the cause, a small change to seeds or config, and passing checks.

Unit loop, Path B (one function)

For each function in the matching grind.

Prompt for Claude
GOAL: Make <FUNC> match 100%.
READ FIRST: asm/<FILE>/<FUNC>.s, notes/attempts.csv rows for <FUNC>, config/compiler_profiles.json.
FENCE: Edit only src/<FILE>.c and notes/attempts.csv. No inline asm, no register pins, no embedded bytes.
CHECK: Run `make clean && make check`. Done means OK and objdiff shows 100% for <FUNC>.
BUDGET: Stop after 10 attempts, or 4 with no gain.
IF BLOCKED: Stop. Report the best score and the first differing instructions.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Files changed.

A good answer: DONE with make check output pasted, or PARTIAL with the best score and a named cause.

Batch dispatch

A lead session hands out the next functions to workers.

Prompt for Claude
GOAL: Pick the next <N> functions and start one worker per function.
READ FIRST: notes/functions.csv, notes/attempts.csv, CLAUDE.md.
FENCE: Do not edit src/ yourself. Each worker uses its own worktree (`claude -w <name>`) and only its own file. Skip sdk rows and rows with 10 failed attempts.
CHECK: After workers finish, merge and run `make clean && make check` on the merged branch. Done means OK.
BUDGET: Stop after one batch.
IF BLOCKED: Stop. Report which merges broke the build.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Per function: matched or not. 3) Merged check output.

A good answer: A table of functions and results, and one merged make check output that prints OK.

Debug with evidence

When the game freezes, crashes or draws wrong.

Prompt for Claude
GOAL: Find the cause of <BUG> in <GAME>. Do not fix it yet.
READ FIRST: ISSUES.md, git log since <DATE> for the files involved.
FENCE: Read-only, except ISSUES.md. Run `git show <COMMIT> -- <FILE>` first if a commit is suspected.
CHECK: The cause is proven by one of: an oracle divergence, a PCSX-Redux trace, or a git diff. Write the proof in ISSUES.md.
BUDGET: Stop after 60 minutes.
IF BLOCKED: Stop. List what you ruled out and what evidence you need.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The cause and its proof. 3) A fix plan for me to approve.

A good answer: One proven cause with an address or a diff, plus a fix plan. No code changed yet.

Verify (hunt for cheating)

In a fresh session after any batch of claimed work.

Prompt for Claude
GOAL: Check that the last <N> commits did real work.
READ FIRST: git log -<N>, CLAUDE.md.
FENCE: Read-only, except notes/verify-<DATE>.md.
CHECK: In a fresh clone, run the project check. Search the diff for inline asm, stubs, fake events, edited hashes, edited golden images and edits outside each card's fence.
BUDGET: Stop after 90 minutes.
IF BLOCKED: Stop. Say what you could not check.
OTHER PROBLEMS: Write them in notes/parking-lot.md. Do not fix them.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Per commit: real, suspect or cheat, with the line.

A good answer: A verdict per commit with line numbers. Any cheat is named, not excused.

Status report

At the end of a week, or before you plan the next one.

Prompt for Claude
GOAL: Give me a status report for <GAME>.
READ FIRST: PROGRESS.md, notes/functions.csv, notes/overlays.md, ISSUES.md.
FENCE: Read-only.
CHECK: Every number comes from a file or a command you ran. Run the project check and paste the summary line.
BUDGET: Stop after 15 minutes.
IF BLOCKED: Stop. Say which file is missing.
REPORT: 1) Matched or native counts, by overlay. 2) Golden runs passing. 3) Open issues. 4) Next three units.

A good answer: Short numbers from the ledger and one pasted check line. No padding.

Session handoff

Before you stop for the day or clear the chat.

Prompt for Claude
GOAL: Save what the next session needs.
READ FIRST: PROGRESS.md, ISSUES.md, notes/attempts.csv.
FENCE: Edit only PROGRESS.md and ISSUES.md.
CHECK: A fresh session could start the next unit from these files alone. Run the project check and paste its last line.
BUDGET: Stop after 10 minutes.
IF BLOCKED: Stop. Say what you could not record.
REPORT: 1) What works now. 2) The unit in progress and its best result. 3) Dead ends. 4) The next step.

A good answer: PROGRESS.md names the next unit, its files and its check, plus the dead ends tried.

Blocked or cannot deliver

When a unit keeps failing and you need a straight answer.

Prompt for Claude
GOAL: Tell me plainly if <UNIT> can be done, and how.
READ FIRST: notes/attempts.csv or ISSUES.md rows for <UNIT>.
FENCE: Read-only.
CHECK: Run the unit's check once more (`make clean && make check` or `powershell -File tools/check.ps1`) and paste the output. Each claim cites an attempt row, an address or that output.
BUDGET: Stop after 20 minutes.
IF BLOCKED: Say so. Do not guess.
REPORT: 1) CAN, CANNOT or UNKNOWN. 2) Why, with evidence. 3) Two or three options, with cost in hours. 4) What you need from me.

A good answer: One word first, evidence after, and real options such as 'keep as assembly with notes'.

Scope change request

When Claude wants to work outside its fence.

Prompt for Claude
GOAL: Ask me before you leave the fence for <UNIT>.
READ FIRST: SCOPE.md, the current task card.
FENCE: Make no edits until I answer.
CHECK: Your request names the files, the reason with evidence, and how we will check the change.
BUDGET: One message.
IF BLOCKED: Wait for my answer. Do not work around the fence.
REPORT: 1) What you want to change. 2) Why, with proof. 3) The risk. 4) The check.

A good answer: A short request I can answer yes or no. 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 detourThe rule to give Claude
Claude edits the made C in generated/ to get past a crash.Never edit generated/. Fix the seeds, game.toml or the framework, then regenerate. Block the folder with a hook.
Claude hand-delivers a fake event or a stub so a screen unlocks.No stubs, no fake events. A missing function aborts with an error. The phase is done only when the real screen shows.
Claude names VSync or another SDK call by guess, and timing goes wrong.Name an SDK function only from a signature match or a traced call. Write the proof in the ledger.
Claude adds fprintf logging and fills the disk with traces.Use the debug server or a short Lua trace. No new log files.
Claude tries a new compiler or flag inside one command to force a match.Use only named profiles in config/compiler_profiles.json. A new profile needs my approval.
Claude renames many func_ symbols to make progress look better.Do not rename without evidence. Write the evidence in the ledger notes column.
Claude trusts a match from one worktree and merges it.A match counts only after make clean && make check on the merged branch.

Problems other projects hit

A cooked 2048-byte .iso loses XA audio and STR movies.

Fix: Dump raw 2352-byte .bin/.cue. Check it against Redump hashes.

Seen in: CTR Native, Weltall, Gran Turismo 2 PC, VR & Browser

A config named an internal wait routine as VSync. The game ran at double speed.

Fix: Find the real Psy-Q VSync entry before you write the stand-in. Dump the game's timing values first.

Seen in: Crash Bandicoot PC

Jumps into the middle of a function broke function-level recompiling. Duff's device loops were one case.

Fix: Replace such routines with a high-level stand-in, or emit a switch on known targets.

Seen in: Crash Bandicoot PC

Overlays share load addresses. Code in a missed overlay never gets compiled.

Fix: Give each overlay its own entry and function map. Find overlays from the loader code, not from play.

Seen in: MediEvil Recomp, Symphony Recomp, Ape Escape Recompiled - Enhanced Edition

Hardcoded struct offsets read the wrong field on 64-bit with no crash.

Fix: Build 32-bit first. Use offsetof and add _Static_assert layout checks.

Seen in: Silent Hill Decomp, CTR Native, Forbidden Memories Recompiled

The old-gcc PSX patch can drop default flags such as soft float.

Fix: Pass every flag on purpose in a named compiler profile.

Seen in: Forbidden Memories Recompiled

PCSX-Redux breakpoints do not fire on the dynarec CPU.

Fix: Start it with -interpreter when you trace.

Seen in: Forbidden Memories Recompiled

A release shipped with an empty Mods page. The build log looked fine.

Fix: Open the finished zip in CI and check its contents.

Seen in: ValkyrieRecomp, Ape Escape Recompiled - Enhanced Edition

Build folders shared between worktrees reused another checkout's objects.

Fix: Give each worktree its own build folder. Force a full rebuild when the checkout changes.

Seen in: Forbidden Memories Recompiled

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 weeks4 to 12 monthsmedium confidence
Path B: full decomp5 to 14 months10 months to 3 years4 to 10 yearslow confidence

Read this first

All numbers assume one medium-sized game and one person directing Claude for 10 to 15 hours a week. Path A rests on several dated AI-assisted PlayStation projects, but only one states a duration, so confidence is medium. That one was a prototype, and its author built the framework at the same time. Path B rests on one PlayStation project that used 20 people, plus one N64 project. That fits our one-person case poorly, so confidence is low.

What makes it faster or slower

  • How many overlays the game has. Each one is its own split, map and check.
  • Whether a decomp, a recomp or .SYM debug files already exist for the game.
  • How fast you find the exact GCC and ASPSX versions.
  • How much GTE math and hand-written assembly the game uses.
  • Movies, XA audio and multi-disc games add runtime work on Path A.

The facts behind these numbers

ProjectWhat happenedLink
PSXRecomp + Tomba!A playable prototype after about three weeks, by a person new to compilers using Claude Code. He says a first game takes weeks to months, later ones days to weeks.source
PaRappa The Rapper RecompiledFirst commit 2026-10-05, first release 2026-10-07. 3 contributors. Developer says AI was used. Only Stage 1 was tested.source
Forbidden Memories RecompiledFirst commit 2026-08-30, preview release 2026-09-26, all 1,134 game C targets matched by November 2026. 20 contributors. AI used.source
Symphony RecompFirst commit 2026-07-09, first release 2026-08-02. 6 contributors. No AI. Built on RecompOne, whose author had worked on it for about five months (readonlymemo.com interview).source
PsyDoomFirst commit 2019-10-03, first release 2020-01-23. 4 contributors. No AI stated.source
REDRIVER2Skeleton Feb 2019, a year of preparation, fully playable Sep 2020. 7 contributors. No AI stated.source
silent-hill-decompRepo created 2021-11-22. All 6,530 functions matched, but only about 52% of data, on decomp.dev on 2026-11-13. README says human-driven. 27 contributors.source
Snowboard Kids (N64, same MIPS family)A matching decomp of 2,145 functions in about 84 days. One main author and three key helpers used agents from the start.source

Projects reviewed (15)

The top-starred project for each of the top 12 PlayStation games on RecompLauncher, plus three where the developer says AI was used. RecompLauncher lists 179 PlayStation projects for 143 games.

What each project teaches

REDRIVER2

Driver 2

Top rated on RecompLauncherotherplayable
GhidraIDASymdumpPsyCrossPremake 5SDL2

Started: 2019-02. First release: 2020-11. Code: C.

AI: none stated

Lesson: A hand-made, non-matching decomp can work if you tag each function as decompiled, tested or altered. Debug symbols from two discs gave every name.

Symphony Recomp

Castlevania: Symphony of the Night

Top rated on RecompLauncherstatic recompplayable
RecompOne.NET 10OpenGLOpenAL

Started: 2026-07. First release: 2026-08. Code: C#.

AI: none: README says no AI was used and AI pull requests are closed

Lesson: One JSON config lists every overlay with its own function map. An existing decomp gave the names, even though the build does not use it.

Silent Hill Decomp

Silent Hill

Top rated on RecompLauncherport of a decompplayable
silent-hill-decompPsyCrosssplatmaspsxobjdiffCMake

Started: 2021-09. First release: 2026-03. Code: C and C++.

AI: yes: README says the PC port is heavily AI-assisted with Claude, and a workflow runs Claude Code on @claude mentions; the decomp itself was human work Agent files: CLAUDE.md, .claude/settings.json.

Lesson: Port a finished decomp by linking it to PsyCross. Wrap every PC change in one #ifdef so the matching build stays exact.

Severed Chains

Legend of Dragoon

Top rated on RecompLauncherotherplayable
Java 25GradleLWJGLJUnit

Started: 2021-06. First release: 2022-12. Code: Java.

AI: none: README says AI was not used

Lesson: A hand rewrite in Java from the disassembly. It keeps the original address in each name, so code stays traceable.

PsyDoom

Doom

Top rated on RecompLauncherothercomplete
Avocado (early host)PSXObjSigGenPSXExeSigMatcherCMakeVulkan

Started: 2019-10. First release: 2020-01. Code: C++ and C.

AI: none stated

Lesson: Replace emulated code one function at a time, so the game runs at every step. Demo replays with stored results check each change.

CTR Native

Crash Team Racing

Top rated on RecompLauncherport of a decompplayable
CTR-ModSDKPsyCross (derived)SDL3CMakeMSVC x86

Started: 2022-08. First release: 2026-06. Code: C.

AI: none stated Agent files: externals/SDL/CLAUDE.md (SDL's own file).

Lesson: Build the port 32-bit first. PS1 code keeps pointers in 32-bit fields, and GPU packets need retail-shaped links.

Crash Bandicoot PC

Crash Bandicoot

Top rated on RecompLauncherstatic recompplayable
RecompOne.NET 10rabbitizerVulkanOpenGL

Started: 2026-07. First release: 2026-07. Code: C#.

AI: none stated (store flag only)

Lesson: Its docs give a bring-up order: BIOS and pad, CD, GPU, VSync, memcpy, jump tables. A wrong VSync name made the game run at double speed.

Forbidden Memories Recompiled

Yu-Gi-Oh! Forbidden Memories

Top rated on RecompLauncherport of a decompplayable
splatold-gcc 2.8.1maspsxm2cdecomp-permuterIDA

Started: 2026-08. First release: 2026-09. Code: C.

AI: yes: README says decompiled 'by hand and AI'; 60+ of 100 recent commits sampled carry Claude co-author trailers; a Copilot CLI instruction file Agent files: .github/copilot-instructions.md.

Lesson: The best PS1 model for agents: one hash check, one function ledger, an attempt log, and named compiler profiles. It reached 100% matched game C.

MediEvil Recomp

MediEvil

Top rated on RecompLauncherstatic recompplayable
RecompOne.NET 10OpenGLOpenAL

Started: 2026-08. First release: 2026-10. Code: C#.

AI: none: README says no AI was used

Lesson: Keep enhancements as separate patch files. Never commit the made code; regenerate it from the disc.

Parasite Eve HD Remaster

Parasite Eve

Top rated on RecompLauncherstatic recompin progress
PSXRecompOpenBIOSPGXPSDL3

Started: 2026-09. First release: none. Code: none published.

AI: not stated for code; README says backgrounds were upscaled with AI (store flag only for code)

Lesson: A news page only, with no source yet. It shows a decomp helps a recomp with file formats and addresses.

Weltall

Xenogears

Top rated on RecompLauncherreimplementationplayable
Unreal Engine 5.8CMakeCatch2ctest

Started: 2026-10. First release: 2026-10. Code: C++.

AI: none stated

Lesson: Tests compare the port with digests from the original code run on an emulated CPU. Tests skip, not fail, when no disc is present.

Gran Turismo 2 PC, VR & Browser

Gran Turismo 2

Top rated on RecompLauncherreimplementationplayable
Ghidra (headless)gt2interpgt2verifyCMakeVulkan

Started: 2026-09. First release: 2026-09. Code: C++.

AI: none stated

Lesson: A small R3000 interpreter runs the original routine as a test oracle. Any difference from the port fails the test.

ValkyrieRecomp

Valkyrie Profile

Added: developer used AIstatic recompin progress
PSXRecomprecomp-uiGhidraCMakeNinja

Started: 2026-08. First release: 2026-08. Code: C and Python.

AI: yes: README says AI-assisted tools may be used and are reviewed; catalog names Codex

Lesson: A PSXRecomp game project can be tiny: game.toml, a seed list and a CMake file. Record the disc hashes in the config.

Ape Escape Recompiled - Enhanced Edition

Ape Escape

Added: developer used AIstatic recompplayable
PSXRecomp v4GhidrachdmanCMakeNinjaCTest

Started: 2026-05. First release: 2026-10. Code: Python, C and C++.

AI: yes: developer flag in the catalog; the repo ships a Ghidra MCP example config, and the inherited upstream CLAUDE.md was deleted on 2026-10-16

Lesson: Find overlays from the loader code and log each investigation in ISSUES.md. A later session can then resume without repeating work.

PaRappa The Rapper Recompiled

PaRappa the Rapper

Added: developer used AIstatic recompin progress
PSXRecomprecomp-uiCMakeNinjaMSYS2

Started: 2026-10. First release: 2026-10. Code: C.

AI: yes: developer flag in the catalog

Lesson: First seeds come from the boot file's call targets, 605 here. Expect to add more as overlays show up.

What we could not check

  • No step here was run on this machine. Commands come from the tools' own docs and the reviewed repos.
  • Whether splat, m2c and maspsx run on native Windows. Their READMEs do not say. Every PS1 matching project read uses Linux or WSL.
  • GhidraMCP 2.0 needs Ghidra 12.1.4, and the newest Ghidra is 12.2. Pairing 12.1.4 with the 2026.10.03 ghidra_psx_ldr build was not tested.
  • Whether the psx-beetle oracle can boot with OpenBIOS. The framework's notes start it with a retail SCPH1001.BIN, so you may need your own BIOS dump to use it.
  • Whether a game project made by setup_project.ps1 can build psx-beetle itself. The build steps found are for the framework repo.
  • The PCSX-Redux Lua trace command in Path B was put together from its flag list. It was not run here.
  • The command-line options of symdump. Only its README and release list were read.
  • The exact day Forbidden Memories reached 100% matched code.
  • How long the PlayStation games in the evidence took to become playable start to finish. Most repos give only release dates.
  • The RecompOne wiki marks itself outdated, so its commands may have changed.
  • Whether the AI flags set by the store, not the developer, are accurate.
  • The tools/golden_*.py, tools/ledger_check.py and check.ps1 scripts in the steps are scripts you write. They are not part of any tool.

Sources