Skip to the page
It's Decomplicated
Sony, 2004

PlayStation Portable decomp guide

Many PSP games now run on PC. A full PSP decomp is still new ground.

What this system is like

The PSP is a busy system for recomp work right now. Two shared tools, PortableKit and PSPRecomp, turn a game's code into C++. A recomp is a tool that rewrites machine code as C or C++. More than twenty PSP games have recomp ports. Most of them came out in late 2026, and most used AI help.

The usual route to a PC build is short. You decrypt the game's main file. You run it under a slow stand-in for the CPU, called an interpreter, to see what is missing. Then you turn all the code into C++, build it, and fix one gap at a time.

A full decomp is much harder here. A decomp is readable C that builds back to the exact same bytes. PSP games used three compiler families, much C++ code, and often more than ten thousand functions. No PSP game is fully decompiled yet. One project matched about 41% of a game's code in four weeks with AI agents. That is the best sign so far.

Path A runs on Windows. Path B needs WSL, because the old compilers run there through wibo. Ghidra, PPSSPP and objdiff run on Windows for both paths.

The main file is locked

EBOOT.BIN on most discs is encrypted. You decrypt your own copy before any tool can read it. pspdecrypt or the PortableKit installer does this. A few games run from a plain BOOT.BIN instead.

Code hides in data files

Many PSP games load extra code while they run. These pieces are called overlays. In Monster Hunter Freedom Unite, 298 overlays held about 81% of the code. Each overlay needs its own recompile.

Calls go by number

A game calls system functions by a number called a NID. The runtime must know what each NID does. Your first gap list is simply the NIDs the game uses but the runtime lacks.

Two shared frameworks exist

PortableKit and PSPRecomp already turn PSP code into C++. A new port starts as a game profile on top. Both are early, and every new game finds gaps in them. Still, the reviewed ports took weeks, not months.

A vector unit and a fixed GPU

The VFPU does fast vector math with its own instructions. Ghidra and some recompilers handle it only in part. The GE has odd rules, like alpha used as stencil and 24-bit floats.

Three compiler families

Games were built with CodeWarrior, SNC or Sony's GCC. You must find the right one by test before matching. CodeWarrior and SNC are Windows programs that run in WSL through wibo. The psp-gcc kits are 32-bit Linux programs.

Two paths

Path A

Get it running on PC

You build a game profile on PortableKit. Its installer checks and decrypts your own disc. You run the game under its interpreter to list what is missing. Then psp_recomp writes the C++, and you fix one gap at a time. PSPRecomp also works, but it has no interpreter and no installer.

Go to the steps

Path B

Full decomp for porting

You split each module with splat, find the original compiler by test, and match functions one by one. A match means the old compiler turns your C into the exact same bytes. The tools run in WSL. No PSP game is fully done yet, so this path is still being worked out.

Go to the steps

Path A: Get it running on PC

You build a game profile on PortableKit. Its installer checks and decrypts your own disc. You run the game under its interpreter to list what is missing. Then psp_recomp writes the C++, and you fix one gap at a time. PSPRecomp also works, but it has no interpreter and no installer.

Method: static recompilation

Pick this first for any PSP game. Every working project reviewed here took this path. It gives a playable build in weeks.

  1. Scope the game and survey the disc

    You pick one game, one region and one version. You look for earlier work on it. Then you measure the disc so you know the risks before you write code.

    • Note the disc ID, like ULUS10160, from PARAM.SFO or UMD_DATA.BIN.
    • Search RecompLauncher, the PortableKit ports table and GitHub for your game. Look for a recomp, a decomp or a sister game on the same engine.
    • Check if PSP_GAME/SYSDIR/EBOOT.BIN is encrypted or if a plain BOOT.BIN exists.
    • List extra .prx files and big data files that may hold overlays.
    • Play the game in PPSSPP and note the frame rate and any odd features.
    • Have Claude write SCOPE.md. You approve it.
    Prompt for Claude
    GOAL: Write a draft SCOPE.md for a PC recomp of <GAME> (<DISC_ID>, version <VERSION>).
    READ FIRST: `notes/disc-listing.txt` (my file list of the disc), the `PortableKit` README, `docs/BRINGING_UP_A_GAME.md` in PortableKit.
    FENCE: Edit only `SCOPE.md` and `notes/survey.md`. Everything else is read-only. Do not write code, scripts or configs.
    CHECK: `SCOPE.md` has these headings: Goal, Game and hash, Technique, Prior work, Disc survey, Milestone 1 and its check, Out of scope, Never edit. Every claim in Prior work has a URL.
    BUDGET: Stop after 45 minutes of research.
    IF BLOCKED: Stop. Do not guess facts about the disc. List what you need me to look up.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not act on them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The SCOPE.md headings filled. 3) Files changed. 4) Open questions for me. 5) New parking-lot items.
    Done whenSCOPE.md names the disc ID, the executable hash, the framework and the first milestone, and you approved it.

    Proof this works: The 3rd Birthday Recomp (step 0 survey and bake-off), God of War PSP (feasibility study before code), MHForever (measured candidate recompilers first)

  2. Set up the framework and the repo

    You build the framework alone first. It needs no game and takes minutes. Then you make your port repo with the framework as a git submodule. You add the one boot check and the guard against game files.

    • Install Visual Studio 2022 with the C++ workload, CMake 3.20 or newer, Ninja and Python 3. A port also needs SDL3, the Vulkan SDK (it has glslangValidator) and FFmpeg.
    • Run git clone --recursive https://github.com/TeamGDB/PortableKit.git and build it with cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release, cmake --build out -j2 and ctest --test-dir out --output-on-failure. On Windows, run these in a Visual Studio developer prompt.
    • Or use the Visual Studio generator. Then add --config Release to the build and -C Release to ctest.
    • The bundled FFmpeg needs make and a C compiler. Without them, pass -DPORTABLEKIT_FFMPEG=system, or OFF to drop music and movies.
    • In your own repo, add it with git submodule add https://github.com/TeamGDB/PortableKit.git portablekit.
    • Write the profile in host/<game>_profile.cpp. It holds only constants: disc ID, both hashes, decryption tag and key, load address and save folders.
    • Read each value off your own disc and its ELF headers, as PROFILE_GUIDE.md says. Do not recall them.
    • Make .gitignore deny everything first, then allow your own folders. Add a pre-commit check that refuses game files and generated code.
    • Have Claude write tools/boot_check.py with --seconds N, --no-interpreter and --replay <FILE>. It runs the game with no window and no sound, kills it at the limit, and prints PASS or FAIL.
    • Write CLAUDE.md, PROGRESS.md and notes/parking-lot.md.
    Prompt for Claude
    GOAL: Make the port repo build with PortableKit as a submodule and one check command that runs.
    READ FIRST: `SCOPE.md`, `portablekit/README.md`, `portablekit/docs/PROFILE_GUIDE.md`, `portablekit/docs/BUILDING.md`.
    FENCE: Edit only `CMakeLists.txt`, `host/`, `config/`, `tools/boot_check.py`, `.gitignore`, `.githooks/`, `CLAUDE.md`, `PROGRESS.md`. `portablekit/` is read-only. Do not add features I did not ask for.
    CHECK: Run `cmake --build out -j2` then `ctest --test-dir out --output-on-failure`. Done means both exit 0, and `python tools/boot_check.py --help` lists `--seconds`, `--no-interpreter` and `--replay`.
    BUDGET: Stop after 3 failed builds with the same error, or 60 minutes.
    IF BLOCKED: Stop. Do not edit the submodule to make it build. Tell me the error, what you tried and what you need.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the last 20 lines of the build and test output. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whencmake --build and ctest exit 0 on a clean clone, and a test commit with a fake .iso file is refused.

    Proof this works: https://github.com/TeamGDB/PortableKit, Portable Ops Native (PortableKit as a submodule), MHForever (content guard as a pre-commit hook), Renegade Squadron PC (default-deny .gitignore)

  3. Prepare and pin the executable

    You turn your disc into a decrypted executable. You pin its hash so every later step uses the same bytes. A wrong key or version shows up here in seconds.

    • With PortableKit, run <Game>Native --install /path/to/your.iso --in-place. It checks the disc ID and the EBOOT.BIN SHA-256, then decrypts.
    • Without it, decrypt EBOOT.BIN with pspdecrypt from its release zip.
    • If the disc has a plain ELF BOOT.BIN, use that and skip decryption.
    • Put both hashes in the profile: encrypted_executable_sha256 for EBOOT.BIN and executable_sha256 for the decrypted file.
    • Keep the .iso and the decrypted file outside the repo.
    Prompt for Claude
    GOAL: Make the install step produce a decrypted executable whose SHA-256 matches the value pinned in the profile.
    READ FIRST: `SCOPE.md`, `host/<GAME>_profile.cpp`, `portablekit/docs/PROFILE_GUIDE.md`, `portablekit/docs/BRINGING_UP_A_GAME.md` step 2.
    FENCE: Edit only the identity, hash and decryption constants in `host/<GAME>_profile.cpp`. Never copy game files into the repo. Never print keys into logs or notes.
    CHECK: Run `<Game>Native --install <ISO_PATH> --in-place`. Done means it exits 0 with no disc ID, hash or key error. The installer checks the decrypted file against `executable_sha256` itself.
    BUDGET: Stop after 3 failed tries.
    IF BLOCKED: Stop. Do not search the web for keys or download any game file. Tell me which check failed and its exact message.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the install output. 3) Files changed. 4) What is left.
    Done when<Game>Native --install exits 0. It has checked the disc ID, the EBOOT.BIN hash and the decrypted file against the pinned hash.

    Proof this works: Yakumo (installer checks PARAM.SFO and the EBOOT.BIN SHA-256), Vice City Stories Recomp (refuses an ELF whose hash does not match), Sims 2 PSP Recomp (uses the plain BOOT.BIN)

  4. Map the executable

    You load the decrypted file into Ghidra to see functions, imports and overlays. You save a ledger of what the game needs. This is where you learn the size of the job.

    • Install Ghidra 12.1.4 and the ghidra-allegrex zip built for 12.1.4 with File -> Install Extensions. Extensions must match the Ghidra version.
    • Import the decrypted file. Set Image Base to 08804000. Run auto analysis.
    • In PPSSPP, save a .sym file from the Debug menu. Import it with the PpssppImportSymFile script. Start Ghidra with support\pyghidraRun.bat on Windows for this.
    • Run portablekit/tools/ghidra/ExportPSPFunctions.java from the Script Manager. It writes a CSV of name, address and size. Add a status column.
    • List the imports by library. This is your list of system calls to support.
    • Mark SDK and middleware functions so nobody works on them by hand.
    • Find the function that loads overlays, if the game has them.
    Prompt for Claude
    GOAL: Produce `ledger/functions.csv` and `ledger/imports.md` for <GAME>.
    READ FIRST: `SCOPE.md`, `notes/survey.md`, the Ghidra export at `<EXPORT_PATH>`.
    FENCE: Edit only files in `ledger/`. The Ghidra project and the game files are read-only. Do not rename anything in Ghidra unless I ask.
    CHECK: `ledger/functions.csv` has columns address, size, name, kind (game, sdk, middleware), status. Its row count equals the row count of the export at `<EXPORT_PATH>`. `ledger/imports.md` lists every import by library with its NID.
    BUDGET: Stop after 60 minutes.
    IF BLOCKED: Stop. Do not invent names or NIDs from memory. Tell me what is missing.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts: functions, SDK functions, imports, overlays found. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenledger/functions.csv has as many rows as the ExportPSPFunctions CSV, and every import is listed with its library.

    Proof this works: God of War PSP (Ghidra + ghidra-allegrex exports to JSON), https://github.com/kotcrab/ghidra-allegrex, The 3rd Birthday Recomp (import list as the HLE checklist)

  5. First light under the interpreter

    You run the game before any code is recompiled. The interpreter runs it slowly but truly. Each run names the next missing system call. Each fix costs seconds, not hours.

    • Run <PREFIX>_NO_RENDER=1 <PREFIX>_NO_AUDIO=1 timeout 90 <Game>Native. Your tools/boot_check.py does the same on Windows.
    • Add <PREFIX>_LIST_STUBS=1 to print every import nothing implements.
    • Read the last [hle-stub] line before a Runtime stopped message. That call is the next job.
    • Set <PREFIX>_STRICT_HLE=1 so the game stops at a missing call instead of going on with a fake answer.
    • Implement that one call through the profile's register_extra_hle hook or an HLE extension. Run again.
    • A run with a window may not stop on a plain timeout. Use timeout -s KILL, and never leave the game running.
    Prompt for Claude
    GOAL: Implement the system call `<LIBRARY>::<FUNCTION>` so the interpreter boot gets past it.
    READ FIRST: `CLAUDE.md`, the last boot log at `<LOG_PATH>`, `ledger/imports.md`, `PPSSPP` source for this call (read only, never copy).
    FENCE: Edit only the HLE files in `host/` that `register_extra_hle` reaches, or the HLE extension file I name. `portablekit/` is read-only. Do not stub other calls.
    CHECK: Run `python tools/boot_check.py --seconds 90`. Done means the log no longer stops at this call, and the earlier boot milestones in `PROGRESS.md` still print.
    BUDGET: Stop after 3 failed tries or 45 minutes.
    IF BLOCKED: Stop. Do not return a fake success code to move on. Tell me what the game expects and what you could not confirm.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the log lines before and after. 3) Files changed. 4) The next call the game stops on. 5) New parking-lot items.
    Done whenpython tools/boot_check.py --seconds 90 runs past the call, and the log names the next stop or shows the title screen.

    Proof this works: https://github.com/TeamGDB/PortableKit/blob/main/docs/BRINGING_UP_A_GAME.md, Tag Force Recomp (every missing call fails loudly), Ape Escape Mind Over Monkey (bind a call only when its contract is known)

  6. Recompile and boot with no interpreter

    Now you turn all the code into C++ and build it. The build is long, so keep jobs low. Then you prove the boot uses only recompiled code.

    • Run psp_recomp <EBOOT.ELF> --auto generated. It takes a few minutes.
    • Count the unsupported(...) sites in the output before you compile. Thousands in one category means a real recompiler gap.
    • Build with cmake --build out -j2. Generated files are huge, so the build compiles only one per 4 GiB of memory.
    • Use clang-cl for the generated code if you can. In one port, frames took 7 ms with it and 18 to 22 ms with MSVC.
    • Run with PSPRECOMP_NO_INTERPRETER=1. The runtime stops at the first address with no recompiled code and names it.
    • With the interpreter on, PSPRECOMP_INTERPRETER_VERBOSE=1 lists every address it had to run. Recompile the code those belong to.
    • If the game has overlays, extract each one and recompile it into its own library with portablekit/tools/add_overlay.py. Pick the right one at run time by a hash of its code.
    Prompt for Claude
    GOAL: Generate and build the recompiled game, and boot it to <MILESTONE> with the interpreter off.
    READ FIRST: `CLAUDE.md`, `PROGRESS.md`, `portablekit/docs/BRINGING_UP_A_GAME.md` step 4.
    FENCE: Edit only `host/`, `config/` and build settings in `CMakeLists.txt`. Never edit files in `generated/`. If generated code is wrong, report it; the fix goes in the generator or the profile.
    CHECK: Run `python tools/boot_check.py --seconds 120 --no-interpreter`. It sets `PSPRECOMP_NO_INTERPRETER=1`. Done means PASS, the log shows <MILESTONE>, and no `Runtime stopped` line names a missing address.
    BUDGET: Use `-j2` at most. Stop after 2 full builds that fail the same way.
    IF BLOCKED: Stop. Do not turn the interpreter back on to pass. List the first missing address and what code it belongs to.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the unsupported-site counts and the boot log tail. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenpython tools/boot_check.py --no-interpreter prints PASS at the milestone, and no missing address stops the run.

    Proof this works: Dissidia012-PC (no interpreter fallbacks proved this way; VERBOSE listed a missed disc PRX), Portable Ops Native (stage sweep with the interpreter off), Vice City Stories Recomp (clang-cl about 2.5x faster frames than MSVC), Yakumo (355 overlays, each its own library)

  7. Grind: one gap at a time

    Each task is one crash, one missing call or one drawing bug. Claude finds the cause with traces first. PPSSPP is your reference for how the real system acts.

    • Turn on one trace at a time, like <PREFIX>_TRACE_GE_LIST, <PREFIX>_TRACE_IO or <PREFIX>_TRACE_SYNC.
    • Compare with PPSSPP at the same load base. Use its debugger to watch memory writes.
    • Write each fix with its cause and the trace that proved it in PROGRESS.md.
    • Record dead ends too, so no session tries them again.
    • Keep a list of bugs as GitHub issues or a ledger table. Hand out one per worker.
    Prompt for Claude
    GOAL: Fix <BUG> (seen at <WHERE>) with a proven cause.
    READ FIRST: `CLAUDE.md`, `PROGRESS.md` dead ends, the log at `<LOG_PATH>`, the capture at `<CAPTURE_PATH>`.
    FENCE: Edit only `host/` and `config/`. `generated/` and `portablekit/` are read-only. No game-specific hacks that skip the bug.
    CHECK: Run `python tools/boot_check.py --replay <REPLAY_FILE>`. Done means PASS, the bug is gone in the capture at frame <N>, and all older replays still pass.
    BUDGET: Find the cause before any fix. Stop after 2 fixes that do not work, or 90 minutes.
    IF BLOCKED: Stop. Tell me the evidence you have, your best theory and what trace would prove it.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The cause, with the trace lines that prove it. 3) Files changed. 4) Replay results. 5) New parking-lot items.
    Done whenThe replay passes, the capture shows the fix, and every older replay still passes.

    Proof this works: Yakumo (AGENTS.md: trace the hardware, measure before changing), The 3rd Birthday Recomp (PPSSPP as oracle, dated fix log), Tag Force Recomp (TF_HOOK_TRACE found a wrong address in minutes)

  8. Harden: replays, frames and packaging

    You lock in old fixes with tests that run without you. Then you add settings and package a release that holds no game code. The player builds the game from their own disc.

    • Record input sessions and make headless runs repeat exactly. Pin the clock and the gamepad.
    • Keep a slow software renderer as the reference. Compare the GPU output against it frame by frame.
    • Write a script that visits every level or stage and reports crashes and missing calls.
    • Run tests that need no game data in CI.
    • Package only the runtime and launcher. The launcher builds the game on the player's PC.
    • State in the release notes what you tested and what you did not.
    Prompt for Claude
    GOAL: Add `tools/regress.py`, a regression set a fresh checkout can run: replays at fixed frames, a stage sweep and a `--no-interpreter` switch.
    READ FIRST: `CLAUDE.md`, `PROGRESS.md`, `tools/boot_check.py`.
    FENCE: Edit only `tools/` and `tests/`. Do not change game behaviour to make a test pass. Do not commit replays that hold game data.
    CHECK: On a clean clone, run `python tools/regress.py`. Done means it prints PASS for every replay and every stage, then a summary line with the counts.
    BUDGET: Stop after 90 minutes or 3 failed designs.
    IF BLOCKED: Stop. Tell me which run is not repeatable and what changes between runs.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the summary line. 3) Files changed. 4) What the set does not cover. 5) New parking-lot items.
    Done whenpython tools/regress.py prints PASS for all replays and stages on a clean clone.

    Proof this works: God of War PSP (34/34 identical frames, WAV hash, level tour), Renegade Squadron PC (GPU compared to the software renderer), LCS Recomp (stress test with numeric pass and fail), Sims 2 PSP Recomp (900-frame startup check, per-release status log)

Path B: Full decomp for porting

You split each module with splat, find the original compiler by test, and match functions one by one. A match means the old compiler turns your C into the exact same bytes. The tools run in WSL. No PSP game is fully done yet, so this path is still being worked out.

Method: matching decompilation

Pick this after Path A works, or when you want to change the game deeply. Expect many months. If you only want to play, stay on Path A.

  1. Scope and find the compiler

    You check what decomp work exists for your game. Then you find which compiler and flags built it. You test candidates on a few small functions and count exact matches.

    • Search GitHub and decomp.dev for your game and its engine. Check sotn-decomp, mhp2g-decomp and HST-Decomp for setups you can copy.
    • Pick three to six small functions from the smallest module.
    • Compile each with every candidate: mwccpsp builds, pspsnc, psp-gcc 1.3.1 and 1.7.1, at common flags.
    • Count exact matches for each compiler and flag set.
    • Write the winner and its flags into SCOPE.md.
    Prompt for Claude
    GOAL: Find the compiler and flags that built <GAME>, by experiment.
    READ FIRST: `SCOPE.md`, the six target functions in `asm/<MODULE>/`, `notes/compilers.md`.
    FENCE: Edit only `notes/compilers.md` and files under `try/compiler-test/`. Everything else is read-only.
    CHECK: For each compiler and flag set, run `<MATCH_TOOL> try/compiler-test/<FUNC>.c`. Done means `notes/compilers.md` has a table of exact matches per compiler and flag set, with the command used.
    BUDGET: Stop after testing every candidate once, or 90 minutes.
    IF BLOCKED: Stop. Do not download compilers from unknown sites. Tell me which candidate you could not run.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The match table. 3) Files changed. 4) Your pick and why. 5) New parking-lot items.
    Done whenOne compiler and flag set matches every test function exactly, and the table is in notes/compilers.md.

    Proof this works: Dissidia012-PC (SNC matched 5 of 6 at -O2, 6 of 6 with -g), https://github.com/angelof-exe/ygo-tf-5-decomp (mwccpsp_3.0.1_219, flags -O4,s; builds 180 to 219 all match its simple functions), https://github.com/decompme/compilers (PSP compiler kits)

  2. Set up the matching build in WSL

    You set up WSL with the splitter, the disassembler, an Allegrex assembler, the diff tool and the old compiler. The build must check the hash of every module. One command builds and checks all.

    • In WSL (Ubuntu 24.04), run sudo apt-get install binutils-mipsel-linux-gnu ninja-build python3-venv libc6-i386. Then make a venv with python3 -m venv .venv.
    • libc6-i386 is needed because the Sony psp-gcc kits are 32-bit Linux programs.
    • Install the Python tools with .venv/bin/python3 -m pip install -U splat64[mips] spimdisasm ninja_syntax.
    • Stock binutils may not know Allegrex. Get allegrex-as.tar.gz from the cc1-psx-26 release of sotn-decomp, check its SHA-256, and unpack it.
    • Download wibo-i686 (1.2.0) and objdiff-cli-linux-x86_64 from their release pages. Run chmod +x on both.
    • Download your kit, like mwccpsp_3.0.1_219.tar.gz, from the compilers release of decompme/compilers. Unpack it in bin/ on the Linux file system, outside Git.
    • Pin the kit's SHA-256 in a file, like mhp2g-decomp does with bin/mwccpsp_219.tar.gz.sha256.
    • Add mwccgap as a submodule if you use CodeWarrior. It lets C files hold not-yet-matched functions as assembly. Point its --as-path at the Allegrex assembler.
    • Write configure.py that writes a build.ninja. The last build step runs sha1sum -c on every module.
    Prompt for Claude
    GOAL: Make `ninja` build the module <MODULE> from its assembly and check its SHA-1.
    READ FIRST: `SCOPE.md`, `notes/compilers.md`, `configure.py`, the setup of `tclamb/mhp2g-decomp` as a model.
    FENCE: Edit only `configure.py`, `config/`, `tools/` and `requirements.txt`. Never edit the checksum files in `config/*.sha1`. Never commit compilers or game files.
    CHECK: In WSL, run `python3 configure.py && ninja`. Done means it exits 0 and the last line shows the module's `sha1sum -c` OK.
    BUDGET: Stop after 3 failed tries with the same error, or 60 minutes.
    IF BLOCKED: Stop. Do not change a checksum to pass. Tell me the error and what you need.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the `ninja` output tail. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenninja exits 0 and sha1sum -c reports OK for the module built from assembly.

    Proof this works: https://github.com/tclamb/mhp2g-decomp (configure.py, mwccgap, wibo, sha1sum, patched Allegrex assembler), Dissidia012-PC tools/setup_wsl.sh (binutils-mipsel-linux-gnu plus allegrex-as from sotn-decomp), Dissidia012-PC (SNC through wibo in WSL Ubuntu 24.04), https://github.com/decompals/wibo

  3. Split each module

    splat cuts a module into code, data and a linker script. Start with the smallest module. Overlays and extra .prx files are separate modules.

    • Write a splat config per module in config/<module>.yaml.
    • Run python3 -m splat split config/<module>.yaml.
    • Fix segment edges until the module rebuilds from assembly with the right hash.
    • If the splat linker script pads segments, write your own linker script.
    • Keep symbol_addrs.txt as the one place for names.
    Prompt for Claude
    GOAL: Split <MODULE> with splat so it rebuilds byte for byte from assembly.
    READ FIRST: `config/<MODULE>.yaml`, `notes/compilers.md`, the splat wiki page on segments.
    FENCE: Edit only `config/<MODULE>.yaml`, `config/<MODULE>.symbol_addrs.txt` and the module linker script. Never edit files in `asm/` by hand; they are generated.
    CHECK: In WSL, run `python3 -m splat split config/<MODULE>.yaml && ninja`. Done means `sha1sum -c` prints OK for <MODULE>.
    BUDGET: Stop after 5 split attempts with no progress, or 60 minutes.
    IF BLOCKED: Stop. Tell me which segment edge is wrong and the bytes around it.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the `sha1sum` line. 3) Files changed. 4) Segments still unsure. 5) New parking-lot items.
    Done whenThe module rebuilt from split assembly passes sha1sum -c.

    Proof this works: Dissidia012-PC (splat linker script replaced by a hand-written one), https://github.com/ethteck/splat, https://github.com/angelof-exe/ygo-tf-5-decomp (section-accurate splat config)

  4. Map functions and mark library code

    You build the function ledger. You mark SDK and middleware code so no one matches it by hand. You find repeated functions, because one match can solve many.

    • Export the function list with sizes from Ghidra or the splat output.
    • Mark Sony SDK, C library and middleware functions in the ledger.
    • Find functions with the same bytes. A match for one is a match for all copies.
    • Sort the rest by size. Small leaf functions go first.
    • Set up objdiff with an objdiff.json so it can report progress.
    Prompt for Claude
    GOAL: Build `ledger/functions.csv` for <MODULE> with kind, size, duplicate group and status.
    READ FIRST: `config/<MODULE>.symbol_addrs.txt`, the Ghidra export at `<EXPORT_PATH>`, `ledger/README.md`.
    FENCE: Edit only `ledger/`. Everything else is read-only.
    CHECK: Run `python3 tools/ledger_check.py`. Done means it prints OK: every function in the module is in the ledger once, and each has a kind and a status.
    BUDGET: Stop after 60 minutes.
    IF BLOCKED: Stop. Do not guess library names. Mark unsure rows as unknown and tell me how many.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts by kind and the number of duplicate groups. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whentools/ledger_check.py prints OK and every function has a kind and a status.

    Proof this works: https://github.com/Jstar269/HST-Decomp (SDK code kept out; duplicates reused by a tool), Tag Force Recomp (pick functions by session coverage)

  5. Match the first function

    You match one small function end to end. This proves the compiler, flags and build. Then the whole module must still pass its hash.

    • Pick a small leaf function from the smallest module.
    • Get a draft from m2c on its assembly.
    • Edit the C until objdiff shows 100% for that function.
    • Replace its INCLUDE_ASM line with the C.
    • Run the full build. The module hash must still match.
    Prompt for Claude
    GOAL: Make `<FUNCTION>` in `src/<MODULE>/<FILE>.c` match exactly.
    READ FIRST: `asm/<MODULE>/<FUNCTION>.s`, `notes/compilers.md`, `notes/compiler-quirks.md`.
    FENCE: Edit only `src/<MODULE>/<FILE>.c` and headers in `include/` that this function needs. No inline asm, no `.word`, no `.incbin`, no `#pragma` tricks.
    CHECK: In WSL, run `ninja`. Done means objdiff shows 100% for `<FUNCTION>` and `sha1sum -c` prints OK for the whole module.
    BUDGET: Stop after 10 attempts with no gain. Save each attempt as a new file in `try/<FUNCTION>/`.
    IF BLOCKED: Stop. Report the best score, the remaining differing instructions and your theory.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the objdiff score and the sha1sum line. 3) Files changed. 4) Compiler lessons learned.
    Done whenobjdiff shows 100% for the function and the full module passes sha1sum -c.

    Proof this works: Dissidia012-PC (started on the 24 KB extra overlay), https://github.com/angelof-exe/ygo-tf-5-decomp (smallest module first, 15 of 16 matched), https://github.com/matt-kempster/m2c

  6. Bulk grind with many workers

    Now you match many functions in parallel. A script picks the next units, not the model. Duplicates and tool output go first, then small functions, then bigger ones.

    • Let tools handle repeated code and plain translations first. They cost no tokens.
    • Give each worker its own git worktree and its own slice of the ledger.
    • One function per session. Clear the chat between functions.
    • Workers save near misses in wip/ with a note. Only exact matches go in src/.
    • Merge one branch at a time. Run the full build after each merge.
    Prompt for Claude
    GOAL: Match the functions in batch <BATCH_ID> from `ledger/batches/<BATCH_ID>.txt`, one at a time.
    READ FIRST: `CLAUDE.md`, `notes/compiler-quirks.md`, the batch file. Nothing else unless a function needs it.
    FENCE: Work only in worktree `<WORKTREE_PATH>`. Edit only the `src/` files of functions in this batch and `wip/`. Never edit `asm/`, `config/*.sha1`, `tools/` or the ledger.
    CHECK: After each function, run `ninja`. A function is done only when objdiff shows 100% and `sha1sum -c` prints OK.
    BUDGET: At most 5 serious attempts per function. Then save the best try in `wip/` with a note and move on.
    IF BLOCKED: Stop the batch. Tell me what broke the build and the last good commit.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) A table: function, result, attempts. 3) Files changed. 4) Functions left. 5) New parking-lot items.
    Done whenEvery function in the batch is either matched with a passing build or saved in wip/ with a note.

    Proof this works: https://github.com/Jstar269/HST-Decomp (tools first, agents on the rest, 41% of code in about four weeks), https://blog.chrislewis.au/the-unexpected-effectiveness-of-one-shot-decompilation-with-claude/ (Snowboard Kids 2: one function per headless run)

  7. Work the hard tail

    Some functions resist the bulk workers. They need a stronger job type and a shared file of compiler lessons. Some may never match without a trick, and that is allowed to stay open.

    • Send units that failed five bulk tries to the hard queue.
    • Keep notes/compiler-quirks.md short and general. No notes about single functions.
    • Check VFPU code. Allow inline VFPU asm only where the original used it, and mark it.
    • Try the other compiler kits only for functions the main one cannot reproduce.
    • Leave a function non-matching rather than accept a fake match.
    Prompt for Claude
    GOAL: Match `<FUNCTION>`, which failed 5 bulk attempts.
    READ FIRST: `wip/<FUNCTION>.c` and its note, `asm/<MODULE>/<FUNCTION>.s`, `notes/compiler-quirks.md`.
    FENCE: Edit only `src/<MODULE>/<FILE>.c`, `wip/<FUNCTION>.c` and `notes/compiler-quirks.md` (general lessons only). No asm that emits non-VFPU instructions, no `.word`, no data in `.text`.
    CHECK: Run `ninja`. Done means 100% in objdiff and `sha1sum -c` OK.
    BUDGET: Stop after 15 attempts with no gain. Save each try in `try/<FUNCTION>/`.
    IF BLOCKED: Stop. Name the exact differing instructions and a theory class, not a vague guess. Say if it may need a different compiler build.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Best score and the diff summary. 3) Files changed. 4) The lesson for `compiler-quirks.md`, if general.
    Done whenThe function matches with a passing build, or it is left in wip/ with the exact remaining differences named.

    Proof this works: https://github.com/Jstar269/HST-Decomp (VFPU inline asm rule, secondary compiler only for leftovers), Dissidia012-PC (-g changes SNC scheduling; twelve functions differ without it)

  8. Harden: gates, review and progress

    You add checks that catch fake matches. A fresh agent re-checks claimed work. CI rebuilds everything from scratch on a machine Claude cannot touch.

    • Write a gate script that rejects .word, .incbin, non-VFPU asm and data forced into code.
    • Block edits to config/*.sha1 and tools/ with a Claude Code hook.
    • Run a fresh verify session on every merged batch.
    • Have CI run configure.py and ninja from a clean clone.
    • Publish an objdiff progress report on each merge.
    Prompt for Claude
    GOAL: Verify the matches claimed in branch <BRANCH> and hunt for cheating.
    READ FIRST: `CLAUDE.md`, the diff of <BRANCH> against main, `tools/gate.py`.
    FENCE: Read only. Do not fix anything. Write findings only in `notes/verify-<BRANCH>.md`.
    CHECK: On a clean clone, run `python3 configure.py && ninja && python3 tools/gate.py`. Done means you report each claimed function as REAL or FAKE with proof.
    BUDGET: Stop after 60 minutes.
    IF BLOCKED: Stop. Tell me what you could not check and why.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the build and gate output. 3) A table: function, REAL or FAKE, reason. 4) Any edits outside the fence in the diff. 5) Any changed checksum or tool file.
    Done whenA clean clone builds, sha1sum -c passes, the gate passes, and the verify note lists no fake matches.

    Proof this works: https://github.com/Jstar269/HST-Decomp (hstgate.py rejects fake matches), https://github.com/cdlewis/snowboardkids2-decomp/tree/main/.claude/hooks (hooks block checksum and asm edits)

  9. Port: swap recompiled code for your C

    No PSP game has a finished decomp port yet. The realistic route is a hybrid. Your matched C replaces recompiled functions inside the Path A runtime. When every function is C, you drop the generated code.

    • Hook each recompiled function so your C can run in its place.
    • Add a --verify-overrides switch to tools/regress.py. It runs the original and your C from the same state, like Tag Force's TF_DECOMP_VERIFY.
    • Run the old and new versions from the same state and compare results.
    • Grow the C part one module at a time, driven by your replays.
    • Move system calls behind one interface so the runtime can change.
    • Fix 64-bit pointer and byte-order issues before a new target.
    • Build for the new system and run the same replays.
    Prompt for Claude
    GOAL: Replace the recompiled `<FUNCTION>` with the decomp C in the Path A runtime.
    READ FIRST: `src/<MODULE>/<FILE>.c`, the hook table in `host/`, `PROGRESS.md`.
    FENCE: Edit only the override file in `host/overrides/` and the hook table. Never edit `generated/`. Do not change the matched source.
    CHECK: Run `python tools/regress.py --verify-overrides`. Done means the original and the override give the same results from the same state, and all replays pass.
    BUDGET: Stop after 3 failed tries.
    IF BLOCKED: Stop. Tell me which value differs, where, and your theory.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Paste the compare and replay output. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenThe override gives the same results as the original from the same state, and all replays pass.

    Proof this works: Dissidia012-PC (matched C used as native overrides), Tag Force Recomp (TF_DECOMP_VERIFY runs both from the same state), https://github.com/nicolalol3/mhfu-decomp (non-matching C injected into the real program)

Tools you need

ToolWhat it doesHow to get itHow we know
PortableKit
Required both
A PSP recompiler and full runtime. Its team (TeamGDB) took it out of Yakumo. It has an interpreter, a Vulkan renderer, audio, saves and an installer.
Path A Path B
git clone --recursive https://github.com/TeamGDB/PortableKit.git, then cmake -S . -B out -G Ninja -DCMAKE_BUILD_TYPE=Release and cmake --build out -j2 (on Windows, in a Visual Studio developer prompt)README, BRINGING_UP_A_GAME.md, BUILDING.md and PROFILE_GUIDE.md read 2026-11-13. Extracted from Yakumo; used by: Dissidia012-PC, Portable Ops Native (a fork). CI tests the framework on Windows, but its README says only Yakumo has run a game there.
PSPRecomp
Helpful both
The other PSP recomp framework. It gives psp_analyze, psp_recomp and a runtime. You add a game profile. It has no interpreter and no decryption.
Path A
git clone https://github.com/jessicanataliagta/PSPRecomp.git, then cmake -S . -B out/framework -DPSPRECOMP_PROFILE="" and cmake --build out/framework --config ReleaseREADME and docs/PROFILE_GUIDE.md read 2026-11-13; Yakumo, Ape Escape and Sims 2 also build it on Linux; used by: LCS Recomp, Vice City Stories Recomp, Renegade Squadron PC, Ape Escape, Sims 2 PSP, MHForever
PPSSPP
Required Windows
The main PSP emulator. You use it as the reference for how the real system acts, and to save function names as a .sym file.
Path A Path B
Download PPSSPPSetup.exe or ppsspp_win.zip (version 1.20.4) from https://www.ppsspp.org/download/download page read 2026-11-13; used by: The 3rd Birthday (oracle), God of War PSP, Dissidia012-PC
pspdecrypt
Required both
Decrypts a PSP program file, like EBOOT.BIN, into an ELF or PRX you can read.
Path A Path B
Download pspdecrypt-1.0-windows.zip or pspdecrypt-1.0-linux.zip from the releases pageREADME and release 1.0 assets read 2026-11-13; used by: mhp2g-decomp, LCS Recomp; Dissidia012-PC used the hrydgard fork
Ghidra
Required both
A free tool that shows a program's functions and turns machine code into rough C. You use it to map the game.
Path A Path B
Install JDK 21 64-bit, then unzip ghidra_12.1.4_PUBLIC_20260921.zip from the Ghidra_12.1.4_build release. Use 12.1.4, not 12.2, because GhidraMCP needs it.README at tag Ghidra_12.1.4_build (JDK 21) and release list read 2026-11-13; latest is 12.2 (JDK 25); GhidraMCP README asks for 12.1.4; used by: God of War PSP and Dissidia012-PC (12.1.3), Tag Force Recomp
ghidra-allegrex
Required both
A Ghidra add-on for the PSP's CPU. It reads PSP relocations, VFPU code and PPSSPP symbol files.
Path A Path B
Download ghidra_12.1.4_PUBLIC_20261025_ghidra-allegrex.zip from release v21.4, then File -> Install Extensions in Ghidra. For Ghidra 12.2, use v21.6 instead.README and releases v21.4 and v21.6 read 2026-11-13; used by: God of War PSP, Dissidia012-PC (v21.4)
Visual Studio 2022, CMake and Ninja
Required Windows
The C++ compiler and build tools for Path A on Windows. clang-cl from Visual Studio or LLVM builds the generated code faster.
Path A
Install Visual Studio 2022 with the C++ workload; install CMake 3.20 or newer and Ninja. Run Ninja builds from a Visual Studio developer prompt.PortableKit and PSPRecomp READMEs read 2026-11-13; used by: Vice City Stories Recomp, LCS Recomp, Renegade Squadron PC
Vulkan SDK
Required both
Headers, the shader compiler and validation layers for the Vulkan renderer. The validation layer finds draw-order bugs.
Path A
Download the Windows installer from https://vulkan.lunarg.com/PortableKit README read 2026-11-13: a port needs a Vulkan loader, headers and glslangValidator; used by: Vice City Stories Recomp (glslc), The 3rd Birthday (sync validation), Sims 2 PSP (CI validation)
splat
Required WSL/Linux
Splits a PSP module into assembly, data and a linker script. It supports PSP binaries.
Path B
python3 -m pip install -U splat64[mips]README and Quickstart wiki read 2026-11-13; used by: Dissidia012-PC (0.50.0), mhp2g-decomp, sotn-decomp
spimdisasm
Required WSL/Linux
A MIPS disassembler that makes assembly which builds back exactly. It knows the PSP's Allegrex instructions.
Path B
python3 -m pip install -U spimdisasmREADME read 2026-11-13; used by: Dissidia012-PC (1.42.4), mhp2g-decomp
m2c
Helpful both
Turns MIPS assembly into a first C draft. You then edit the draft until it matches.
Path B
python3 -m pip install "m2c @ git+https://github.com/matt-kempster/m2c.git"README read 2026-11-13; used by: sotn-decomp, ygo-tf-5-decomp
objdiff
Required both
Compares your compiled function with the original, byte by byte. The CLI writes progress reports.
Path B
Download objdiff-windows-x86_64.exe (GUI) and objdiff-cli-linux-x86_64 (for WSL) from the v3.8.3 releaseREADME and v3.8.3 release assets read 2026-11-13 (lists MIPS PSP); used by: mhp2g-decomp (v3.6.1 pinned in configure.py)
wibo
Required WSL/Linux
Runs small Windows command-line programs on Linux. PSP decomps use it to run the old Windows compilers in WSL.
Path B
Download wibo-i686 from the releases page (1.2.0) and make it executable with chmod +xREADME and release 1.2.0 read 2026-11-13; used by: Dissidia012-PC (SNC), mhp2g-decomp, HST-Decomp
PSP compiler kits (decomp.me)
Required WSL/Linux
The list of PSP compilers the decomp community uses: mwccpsp builds 121 to 219, psp-gcc 1.3.1 and 1.7.1, and pspsnc 1.2.7503.0.
Path B
In WSL: wget https://github.com/decompme/compilers/releases/download/compilers/<KIT>.tar.gz, then tar xzf it into bin/<KIT> on the Linux file system, outside Gitrepo tree and the PSP Dockerfiles read 2026-11-13: each kit downloads <KIT>.tar.gz from the compilers release; HST-Decomp says to install compilers from these kits
mwccgap
Helpful WSL/Linux
Lets a C file hold unmatched functions as assembly when you use the CodeWarrior compiler. It swaps the assembly in after compiling.
Path B
git submodule add https://github.com/mkst/mwccgap.git tools/mwccgapREADME read 2026-11-13 (it gives no install command; mhp2g-decomp adds it as a submodule at tools/mwccgap); used by: mhp2g-decomp, sotn-decomp
Allegrex assembler (allegrex-as)
Required WSL/Linux
A GNU assembler build that knows the PSP's Allegrex and VFPU instructions. PSP matching builds use it in place of the stock MIPS assembler.
Path B
In WSL: download allegrex-as.tar.gz from the cc1-psx-26 release of Xeeynamo/sotn-decomp, check its SHA-256, and unpack itsotn-decomp Makefile and Dissidia012-PC tools/setup_wsl.sh read 2026-11-13; used by: sotn-decomp, Dissidia012-PC; mhp2g-decomp builds a patched pspas instead
WSL with Ubuntu 24.04
Required Windows
Linux inside Windows. Path B runs its build here, with ninja, MIPS binutils, Python and the old compilers.
Path B
wsl --install -d Ubuntu-24.04, then in WSL: sudo apt-get install binutils-mipsel-linux-gnu ninja-build python3-venv libc6-i386Dissidia012-PC card (WSL Ubuntu 24.04, binutils-mipsel-linux-gnu); sotn-decomp tools/requirements-debian.txt (ninja-build, python3-venv); HST-Decomp docs/GUIDE.md (libc6-i386) read 2026-11-13

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 (decomp-skills)

skills.sh

A one-function-at-a-time method with a small tool, dk.py, for MIPS splat projects. PSP is on its list. It commits matches and undoes misses, 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 and C++ that ban fake matches. It fits Path B, where much PSP code is C++.

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

debug-game-in-emulator

skills.sh

Makes every PPSSPP run the same: a throwaway data folder, a log and a time limit. Claude must name the failing layer before any change.

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

dl-binary-recompilation-engineer

skills.sh

A design guide for a recompiler and runtime. Use it if your game needs changes inside PortableKit or PSPRecomp. It suggests running npx rea-agents setup; decide that yourself.

npx skills add alexishida/dalhe-cli --skill dl-binary-recompilation-engineer -a claude-code

ghidra-headless

skills.sh

Runs Ghidra with no window and writes functions and code to files. Set GHIDRA_HOME yourself on Windows. Install ghidra-allegrex first.

npx skills add trailofbits/skills-curated --skill ghidra-headless -a claude-code

orchestrator

skills.sh

Runs a Path B push with many workers, each in its own worktree and slice. Every merge must pass the byte check.

npx skills add lemiur/game-decompilation-skill-for-claude --skill orchestrator -a claude-code

verification-before-completion

skills.sh

Claude may not say DONE without fresh proof from the check. That fits both the boot check and the hash check.

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

handoff

skills.sh

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

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

GhidraMCP

MCP server

Lets Claude list functions, read decompiled code and rename things in Ghidra. It needs Ghidra 12.1.4, so use the 12.1.4 build of ghidra-allegrex too. MHForever planned a Ghidra plus MCP setup.

In Ghidra 12.1.4, add the release 2.0 zip with File -> Install Extensions and enable GhidraMCPPlugin in File -> Configure -> Developer. Then run: claude mcp add ghidra -- uvx --from git+https://github.com/LaurieWired/GhidraMCP ghidra-mcp --ghidra-server http://127.0.0.1:8080/

psp-boot-check

write-your-own

Every Path A task ends with the same bounded run. The skill makes Claude run it the same way each time and read the right log lines.

A project skill in `.claude/skills/psp-boot-check/SKILL.md`. It runs `python tools/boot_check.py` with a time limit, the interpreter on or off, and a replay file. It reads the log and reports the first `[hle-stub]` line, the stop reason and interpreted addresses. It never leaves the game running.

psp-match-one

write-your-own

Path B workers need one fixed loop with a hard stop. This keeps every worker on the same compiler, flags and verdict.

A project skill in `.claude/skills/psp-match-one/SKILL.md`. It builds one function with the chosen `mwccpsp` or `pspsnc` kit through `wibo`, prints the `objdiff` score, runs `ninja` and `sha1sum -c`, and saves each try in `try/<function>/`. It lists the banned constructs and stops after five tries.

Claude setup for this system

On Path A, one task is one missing system call, one crash or one drawing bug. Each ends with the bounded boot check or a replay. On Path B, one task is one function, checked by objdiff and the module hash. Keep the ledger as the list of units. Give each worker a slice, never the whole game.

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 projectSurvey the disc, pick PortableKit or PSPRecomp, find prior work and write SCOPE.md. For Path B, also run the compiler test.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 projectBuild the framework, write the profile constants, the boot check and the content guard. For Path B, set up WSL, splat, wibo and ninja.Opus 5.5
effort medium
Sonnet 5.5
effort medium
Study the game fileMap the decrypted program in Ghidra with ghidra-allegrex. List imports by NID, find overlays and mark SDK code in the ledger.Opus 5.5
effort high
Opus 5.5
effort medium
Raise to high for function edges and data layouts. A mistake there spreads.
Build the runtimeWrite missing system calls, GE drawing features, audio and saves in the game profile. Use PPSSPP behaviour as the reference.Opus 5.5
effort high
Opus 5.5
effort medium
Raise to high for timing and graphics bugs.
Find a bugFind why a scene crashes or draws wrong. Use the _TRACE_ switches, PPSSPP memory watches and frame captures. No fix until the cause is proven.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.
Bulk unitsMatch small Path B functions, one per session, in parallel worktrees. On Path A, add simple calls that the import list already describes.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 unitsFunctions that failed five bulk tries, VFPU-heavy code, and compiler quirks. On Path A, timing bugs and overlay switching.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.
Check the workA fresh session rebuilds from a clean clone. It reruns the boot check with the interpreter off, or the hash check. It hunts for fake matches and faked calls.Opus 5.5
effort medium
Always a new session, never the one that did the work.
Sonnet 5.5
effort high
Always a new session, never the one that did the work.
Keep the recordsUpdate PROGRESS.md, the ledger counts, dead ends and the compiler-quirks file after each batch.Haiku 5.5
effort medium
Haiku 5.5
effort medium

How many sessions at once

Max 20x (now called Ultra)

Path A: run one lead session and two or three workers, each on one bug in its own worktree. Only one full build runs at a time, because generated files use gigabytes of memory. Path B: run four to six match workers in worktrees, plus one verify session.

Max 5x (now called Max)

Path A: one worker at a time, plus a short verify session at the end of each day. Path B: two match workers in worktrees. Send hard units to one session late in the week.

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/`. If generated code is wrong, fix the generator or the profile, then regenerate.
- Bound every game run with a time limit. Never leave the game running or drive it with an open-ended input loop.
- Path A: build with `cmake --build out --target <TARGET> -j2`, never `ninja` directly. Never delete `.ninja_deps` or `.ninja_log`.
- A boot is done only when `python tools/boot_check.py --no-interpreter` prints PASS.
- Trace the hardware; do not recall it. Never write GE register numbers, PSP structs or NID meanings from memory.
- A missing system call must stop the run with its name. Never return a fake success to move on.
- No game data in Git: no ISO, EBOOT, PRX, decrypted files, generated code or captures.
- `portablekit/` is read-only. Framework changes go in numbered patch files I approve.
- Path B: only `ninja` with `sha1sum -c` OK counts as a match. Never edit `config/*.sha1`, `asm/` or `tools/`.
- Path B: no inline asm except VFPU asm the original used, no `.word`, no `.incbin`, no data in `.text`.
- Never paste game disassembly into decomp.me or other public sites.
- In a worktree, use absolute paths and run builds only inside that worktree.
- Write side issues in `notes/parking-lot.md`. Write each result and dead end in `PROGRESS.md`.
- Do not copy code from `PPSSPP` into this repo. Read it as a reference only.

Keep the context small

  • Give Claude an address and a log path, not pasted disassembly.
  • Ask for one _TRACE_ switch at a time. Full traces of a hot module run for a long time and fill the context.
  • Never let Claude open files in generated/. They are huge. Use dump_function for one function instead.
  • Clear the chat after each fixed bug or matched function.
  • Use a subagent to read a long Ghidra export and return a short summary.
  • Keep CLAUDE.md short. Point to notes/compiler-quirks.md and the bring-up doc by topic.

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 on a new PSP game. It ends with a draft SCOPE.md and a clear yes, no or maybe.

Prompt for Claude
GOAL: Decide if <GAME> (<DISC_ID>) can be recompiled for PC, and which framework to use.
READ FIRST: `notes/disc-listing.txt`, the READMEs of `TeamGDB/PortableKit` and `jessicanataliagta/PSPRecomp`, the RecompLauncher PSP list.
FENCE: Edit only `SCOPE.md` and `notes/survey.md`. Write no code.
CHECK: `SCOPE.md` answers: is EBOOT.BIN encrypted, extra PRX modules, overlays, import count by library, VFPU use, prior work with URLs, framework pick with reasons, first milestone and its check.
BUDGET: Stop after 45 minutes.
IF BLOCKED: Stop. Say plainly what you cannot know without the disc or a test run.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Verdict: go, no-go or test first, with reasons. 3) Files changed. 4) Risks ranked. 5) New parking-lot items.

A good answer: A filled SCOPE.md, a one-line verdict, and risks ranked with evidence, like 300 overlays or 2,000 VFPU instructions.

Map the binary

After the executable is decrypted and pinned. Use it to build the function ledger and the import list.

Prompt for Claude
GOAL: Build `ledger/functions.csv` and `ledger/imports.md` from the Ghidra export of <GAME>.
READ FIRST: `SCOPE.md`, `<EXPORT_PATH>`, the `PPSSPP` `.sym` file at `<SYM_PATH>`.
FENCE: Edit only `ledger/`. The Ghidra project is read-only.
CHECK: Run `python tools/ledger_check.py`. Done means it prints OK and the function count equals the export's.
BUDGET: Stop after 60 minutes.
IF BLOCKED: Stop. Mark unsure rows as unknown. Do not invent names.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts: functions, SDK, middleware, imports, overlays. 3) Files changed. 4) What is left.

A good answer: A ledger whose counts match Ghidra, imports grouped by library, and overlay loaders named by address.

Unit loop: one missing system call (Path A)

Each time the boot stops at a missing call.

Prompt for Claude
GOAL: Implement `<LIBRARY>::<FUNCTION>` so the boot passes it.
READ FIRST: `CLAUDE.md`, the boot log `<LOG_PATH>`, `ledger/imports.md`.
FENCE: Edit only the HLE files in `host/`. `portablekit/` and `generated/` are read-only.
CHECK: Run `python tools/boot_check.py --seconds 90`. Done means the log passes this call and earlier milestones still print.
BUDGET: Stop after 3 failed tries or 45 minutes.
IF BLOCKED: Stop. Do not fake a return value. Tell me what the game expects.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Log lines before and after. 3) Files changed. 4) The next stop.

A good answer: DONE, the log lines showing the call passed, one small file changed, and the next missing call named.

Unit loop: match one function (Path B)

For each function in the bulk queue.

Prompt for Claude
GOAL: Make `<FUNCTION>` match exactly with <COMPILER> <FLAGS>.
READ FIRST: `asm/<MODULE>/<FUNCTION>.s`, `notes/compiler-quirks.md`.
FENCE: Edit only `src/<MODULE>/<FILE>.c`. No inline asm except original VFPU asm, no `.word`, no `#pragma` tricks.
CHECK: In WSL, run `ninja`. Done means objdiff 100% for `<FUNCTION>` and `sha1sum -c` OK.
BUDGET: 5 serious attempts. Save each in `try/<FUNCTION>/`.
IF BLOCKED: Stop. Save the best try in `wip/` with a note naming the differing instructions.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Score and sha1sum line. 3) Files changed. 4) Lesson, if general.

A good answer: DONE with 100% and an OK hash, or PARTIAL with the best try saved and the exact differences named.

Batch dispatch

In the lead session, to hand out the next units to workers.

Prompt for Claude
GOAL: Pick the next <N> units from `ledger/functions.csv` (or `ledger/bugs.md`) and start one worker per unit.
READ FIRST: `CLAUDE.md`, the ledger, `PROGRESS.md`.
FENCE: Edit only the status column of the ledger and `ledger/batches/`. Each worker gets its own worktree at an absolute path. Do not do unit work yourself.
CHECK: Each worker reports with the unit's check output. Done means every unit is marked matched, fixed, wip or blocked, with proof pasted.
BUDGET: At most <N> workers at once. Stop the batch if two workers break the build.
IF BLOCKED: Stop. Tell me which worker broke what and the last good commit.
OTHER PROBLEMS: Collect them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Table: unit, worker, result, proof line. 3) Ledger rows changed. 4) Next batch suggestion.

A good answer: A table with one row per unit, each with a proof line, and ledger statuses updated to match.

Debug with evidence

When a scene crashes, hangs or draws wrong.

Prompt for Claude
GOAL: Find the cause of <SYMPTOM> at <WHERE>. Do not fix it yet.
READ FIRST: `PROGRESS.md` dead ends, the log `<LOG_PATH>`, the capture `<CAPTURE_PATH>`.
FENCE: Read only, except new trace output under `out/traces/`. No code changes.
CHECK: Done means you name the cause and show trace lines or a `PPSSPP` comparison that prove it.
BUDGET: Stop after 60 minutes or 3 theories that fail.
IF BLOCKED: Stop. List each theory, the test you ran and what it showed.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The cause and its proof. 3) The fix you suggest and its risk. 4) Dead ends to record.

A good answer: One cause backed by trace lines or a memory diff, a suggested fix, and dead ends written down.

Verify and hunt for cheating

In a fresh session after each batch or before each release.

Prompt for Claude
GOAL: Check that the work claimed in <BRANCH> is real.
READ FIRST: `CLAUDE.md`, the diff of <BRANCH> against main.
FENCE: Read only. Write only `notes/verify-<BRANCH>.md`.
CHECK: On a clean clone, run the full check: Path A `python tools/regress.py --no-interpreter`; Path B `python3 configure.py && ninja && python3 tools/gate.py`. Done means each claim is marked REAL or FAKE with proof.
BUDGET: Stop after 60 minutes.
IF BLOCKED: Stop. Say what you could not check.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Check output. 3) Look for: edited hashes, edited tools, edits in `generated/`, fake system call returns, interpreter left on, asm in sources, disabled tests. 4) Verdict per claim.

A good answer: A list of every claim with REAL or FAKE, the check output pasted, and any edit outside the fence named.

Status report

At the end of a day or a batch.

Prompt for Claude
GOAL: Report project status from the ledger and logs only.
READ FIRST: `ledger/functions.csv`, `ledger/bugs.md`, `PROGRESS.md`, the last regression output.
FENCE: Read only. Write only `notes/status-<DATE>.md`.
CHECK: Every number in the report comes from a file or a command you ran. Name the source next to each number.
BUDGET: 15 minutes.
IF BLOCKED: Stop. Say which number you could not get.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Counts: matched, wip, open bugs, replays passing, stages reached. 3) Change since last report. 4) Top three blockers. No prose padding.

A good answer: A short list of numbers with sources, the change since last time, and three blockers.

Session handoff

Before you stop for the day or when a session gets long.

Prompt for Claude
GOAL: Write what the next session needs into the ledger files.
READ FIRST: `PROGRESS.md`, `git status`, `git log -5`.
FENCE: Edit only `PROGRESS.md` and the ledger status columns. No code changes.
CHECK: A new session can start from `PROGRESS.md` alone. It names the current unit, its state, the last check output, the next step and the dead ends.
BUDGET: 10 minutes.
IF BLOCKED: Stop. Say what state you could not confirm.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The new `PROGRESS.md` section. 3) Uncommitted files and why.

A good answer: A dated PROGRESS.md section with the next step, the last proof and the dead ends, plus a list of uncommitted files.

Blocked or cannot deliver

When a task has gone around in circles or Claude says it is impossible.

Prompt for Claude
GOAL: Give me a plain answer on <TASK>: can it be done, and how.
READ FIRST: Your notes on this task and `PROGRESS.md` dead ends.
FENCE: Read only. No more attempts.
CHECK: Done means you state one of: can do with <PLAN>, cannot do because <PROOF>, or unknown until <TEST>.
BUDGET: 10 minutes.
IF BLOCKED: Say unknown and name the one test that would tell.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) What cannot be done and why, with evidence. 3) Two or three options with cost in sessions. 4) Your pick.

A good answer: A short, honest verdict with evidence and priced options, not another attempt.

Scope change request

When Claude finds that the task needs edits outside the fence.

Prompt for Claude
GOAL: Ask me before you leave the fence for <TASK>.
READ FIRST: `SCOPE.md`, the task card you are on.
FENCE: Make no edits outside the fence while you wait.
CHECK: Done means I have your request with: the file or folder, the exact change, why the task needs it, and the risk.
BUDGET: 5 minutes to write the request.
IF BLOCKED: Park the task in `PROGRESS.md` and stop.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) BLOCKED. 2) The request. 3) What you will do if I say no.

A good answer: A short request naming the file, the change and the risk, and a plan for a no.

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 generated C++ to fix a crash.Never edit generated/. Fix the generator or the profile, then regenerate. Block the folder with a hook.
Claude returns a fake success from a missing system call so the game moves on.A missing call stops the run with its name. Use strict HLE mode. A fake return is a failed task.
Claude writes GE register numbers, PSP structs or NID meanings from memory.Trace the hardware; do not recall it. Every constant needs a trace line, a PPSSPP source line or a doc link.
Claude says the game runs, but the interpreter ran the missing parts.A boot counts only when python tools/boot_check.py --no-interpreter prints PASS. Paste that output.
Claude starts a full rebuild or many compile jobs and the machine runs out of memory.Build named targets with -j2. Full rebuilds and sweeps only for release candidates, when I ask.
Claude leaves the game running or drives it with an endless input loop.Every run goes through tools/boot_check.py with a time limit. No open-ended loops.
Claude forces a match with .word, non-VFPU asm or data placed in code.The gate script refuses these. A clean non-match in wip/ beats a fake match.
Claude copies code from PPSSPP into an MIT project, or pastes game code into decomp.me.PPSSPP is a read-only reference. Never post game bytes or disassembly to public sites.

Problems other projects hit

System calls silently did nothing because the recompiler found stubs by section name, and the game had its section names stripped.

Fix: Find import stubs from the import table, not section names. Run a bake-off on your own executable before picking a tool.

Seen in: The 3rd Birthday Recomp

The 16 KiB scratchpad memory at 0x00010000 was not mapped. Bone data stayed zero and the hero was invisible.

Fix: Map every PSP memory region, including the scratchpad. Add a test for it in the framework.

Seen in: The 3rd Birthday Recomp, Ape Escape Mind Over Monkey, The Sims 2 PSP Recomp

Most of the code lived in overlays loaded at run time, so a recompile of EBOOT.BIN alone missed it.

Fix: Survey overlays early. Recompile each one at its load address, and pick it by a hash of bytes the game never writes.

Seen in: MHForever, Yakumo, Dissidia012-PC, Portable Ops Native

Generated files are huge. Too many compile jobs ran out of memory, and the first build took an hour or more.

Fix: Use -j2 or one job per 4 GiB. Use ccache. Keep generated code out of link-time optimisation.

Seen in: Yakumo, Renegade Squadron PC, Vice City Stories Recomp, LCS Recomp

The game crashed at start on Linux because the recompiled code nests very deep.

Fix: Give the main thread a 64 MiB stack. On Linux run ulimit -s 65536 first.

Seen in: Yakumo, Ape Escape Mind Over Monkey

Some VFPU instructions were not handled, and Ghidra shows VFPU code poorly.

Fix: Count unsupported(...) sites before compiling. Translate instructions, not Ghidra's C. Test VFPU code against a reference.

Seen in: God of War PSP, Ape Escape Mind Over Monkey

Ghidra's C hid function arguments and return values, which led to crashes in hand-written code.

Fix: Read the registers set before each call and the load widths. Never trust Ghidra's C for call arguments.

Seen in: Tag Force Recomp

A paletted texture was rebuilt every frame. Memory grew past 10 GB or frame time jumped.

Fix: Apply the palette on the GPU in the pixel shader. Cache textures by content.

Seen in: Vice City Stories Recomp, Renegade Squadron PC

Addresses were built for one region, so other discs glitched in game.

Fix: Pin one disc version. Give each region its own hash, generated code and address table.

Seen in: LCS Recomp, Tag Force Recomp, The Sims 2 PSP Recomp

The SNC compiler made different code without -g, and the splat linker script padded segments.

Fix: Find flags by test, including debug flags. Write your own linker script when splat's pads.

Seen in: Dissidia012-PC

Antivirus blocked the compiler or the new game.dll while the launcher built the game.

Fix: Tell players to allow the build folder. Check that downloads are whole by hash.

Seen in: The 3rd Birthday Recomp, God of War PSP

How long it takes

Max 20x (now called Ultra)Max 5x (now called Max)One person, no AIHow sure
Path A: running on PC3 to 10 weeks2 to 6 months6 to 18 monthshigh confidence
Path B: full decomp6 to 18 months1 to 3 years5 to 10 yearslow confidence

Read this first

These numbers assume one medium game and one person giving 10 to 15 hours a week. Path A is fairly sure: four dated AI projects on this system took weeks, not months. But none says how many hours it took, and some hid earlier private work. Path B is a guess. No PSP game is fully decompiled, and the last part of a decomp is always the slowest. The no-AI numbers come from other systems, because no PSP recomp predates agents.

What makes it faster or slower

  • Whether PortableKit or PSPRecomp already covers most system calls your game uses.
  • How much code sits in overlays or extra modules.
  • How much VFPU code and how many rare GE features the game uses.
  • Your PC: the first full build can take hours and needs a lot of memory.
  • For Path B: which compiler, how many functions, and how much is C++.

The facts behind these numbers

ProjectWhat happenedLink
Dissidia012-PCDecomp setup dated 2026-10-10. Recompiled build reached the title screen on 2026-10-18. First release 2026-10-24. One person, with a lot of AI help, on PortableKit.source
The 3rd Birthday RecompTwo-weekend bake-off, work log dated 2026-09-26, first release 2026-10-23. Four contributors. README says much of the code was written with Claude.source
Portable Ops NativeFirst commit 2026-10-17. First prerelease 2026-11-08. One contributor, with an AGENTS.md and a commit naming a Claude session.source
Renegade Squadron PCFirst commit 2026-10-03. First release 2026-10-18. One person with Codex and Claude.source
Ape Escape Mind Over MonkeyFirst commit 2026-08-12, the same day PSPRecomp was created, so its history may include the framework. First release 2026-10-15. Developer notes Claude and Codex.source
HST-DecompCreated 2026-10-15. On 2026-11-10: 41.4% of code bytes and 68.9% of 19,634 functions matched. One person, tools plus AI agents.source
mhp2g-decompCreated 2026-01-28. 3.55% decompiled on decomp.dev on 2026-11-13. One contributor, CodeWarrior build 219.source
God of War PSPIts own feasibility study on 2026-10-15 guessed 6 to 12 months to a full game. Version 0.1.0 came out 2026-10-17, after earlier private work.source

Projects reviewed (17)

We took the top-starred project for each of the top 12 PSP games on RecompLauncher. We added two more that used AI. The catalog has no working PSP decomp, so three Path B projects come from outside it.

sotn-decomp1.2K starssotn-decompCastlevania: Symphony of the Night (Dracula X Chronicles, PSP)matching decompYakumo613 starsAI usedYakumoMonster Hunter Portable 3rdstatic recompLCS Recomp300 starsLCS RecompGrand Theft Auto: Liberty City Storiesstatic recompGod of War PSP210 starsAI usedGod of War PSPGod of War: Chains of Olympus; God of War: Ghost of Spartastatic recompAce Combat X Recompilation103 starsAI usedAce Combat X RecompilationAce Combat X: Skies of Deceptionstatic recompDissidia012-PC93 starsAI usedDissidia012-PCDissidia 012 Duodecim Final Fantasystatic recompMHForever74 starsAI usedMHForeverMonster Hunter Freedom Unitestatic recompVice City Stories Recomp67 starsVice City Stories RecompGrand Theft Auto: Vice City Storiesstatic recompmhp2g-decomp42 starsmhp2g-decompMonster Hunter Portable 2nd Gmatching decompThe 3rd Birthday Recomp39 starsAI usedThe 3rd Birthday RecompThe 3rd Birthdaystatic recompStreet Fighter Alpha 3 MAX39 starsAI usedStreet Fighter Alpha 3 MAXStreet Fighter Alpha 3 MAXotherPortable Ops Native34 starsAI usedPortable Ops NativeMetal Gear Solid: Portable Opsstatic recompRenegade Squadron PC33 starsAI usedRenegade Squadron PCStar Wars Battlefront: Renegade Squadronstatic recompTag Force Recomp30 starsAI usedTag Force RecompYu-Gi-Oh! GX Tag Forcestatic recompApe Escape Mind Over Monkey11 starsAI usedApe Escape Mind Over MonkeySaru Get You: Saru Saru Daisakusenstatic recompThe Sims 2 PSP Recomp4 starsAI usedThe Sims 2 PSP RecompThe Sims 2static recomphst-decomp4 starsAI usedhst-decompHot Shots Tennis: Get a Gripmatching decomp

What each project teaches

sotn-decomp

Castlevania: Symphony of the Night (Dracula X Chronicles, PSP)

From outside RecompLaunchermatching decompin progress
mwccpsp build 219splatm2casm-differdecomp-permuter

Started: 2021-12. First release: none. Code: C.

AI: none stated

Lesson: The furthest PSP matching decomp, at about 83% for the PSP version. It had a head start from the same game's PS1 decomp.

Yakumo

Monster Hunter Portable 3rd

Top rated on RecompLauncherstatic recompplayable
PSPRecompCMakeNinjaVulkanSDL3FFmpeg

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

AI: yes: ships AGENTS.md and CLAUDE.md for coding agents; how much code AI wrote is not stated Agent files: AGENTS.md, CLAUDE.md.

Lesson: Bound every run and trace the hardware instead of recalling it. Its AGENTS.md rules are a strong model for any PSP port.

LCS Recomp

Grand Theft Auto: Liberty City Stories

Top rated on RecompLauncherstatic recompplayable
PSPRecompclang-clCMakeNinjaDirectX 12Vulkan

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

AI: none stated

Lesson: A file-based control channel lets a script drive the game and check movement with numbers. That is a test an agent can run alone.

God of War PSP

God of War: Chains of Olympus; God of War: Ghost of Sparta

Top rated on RecompLauncherstatic recompplayable
own Python recompilerGhidraghidra-allegrexUnicornCMakeSDL3

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

AI: yes: AGENTS.md, CLAUDE.md and .claude/ are kept local and git-ignored

Lesson: Test each recompiled function against an independent CPU model on random inputs. Make headless runs repeat frame for frame.

Ace Combat X Recompilation

Ace Combat X: Skies of Deception

Top rated on RecompLauncherstatic recompplayable
pspreco (own Python recompiler)clangVulkanSDL3

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

AI: yes: NOTICE.md says the Vulkan backend was written with substantial help from Claude

Lesson: Split the pipeline into steps you can rerun and check alone. Add a golden boot trace test early.

Dissidia012-PC

Dissidia 012 Duodecim Final Fantasy

Top rated on RecompLauncherstatic recompplayable
PortableKitSNC 1.2.7503.0splatspimdisasmwiboGhidra

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

AI: yes: CONTRIBUTING.md says it is built with a lot of AI help

Lesson: Pair a recomp with a matching decomp. Recompile everything to play, and use matched C only where a feature needs it.

MHForever

Monster Hunter Freedom Unite

Top rated on RecompLauncherstatic recompplayable
PSPRecomp (generator)CMakeClangpspdevOpenGL 3.3SDL3

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

AI: yes: README says developed with AI assistance; docs refer to a local CLAUDE.md

Lesson: Test the runtime on your own small homebrew programs first. Then CI can test it with no game data.

Vice City Stories Recomp

Grand Theft Auto: Vice City Stories

Top rated on RecompLauncherstatic recomparchived
PSPRecompclang-clCMakeVulkan SDKDirectX 12

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

AI: none stated

Lesson: Set the generator to stop on any missing function. Gaps then show up when you generate, not when you play.

mhp2g-decomp

Monster Hunter Portable 2nd G

From outside RecompLaunchermatching decompin progress
mwccpsp 3.0.1 build 219mwccgapwibosplatspimdisasmobjdiff

Started: 2026-01. First release: none. Code: C++.

AI: none stated

Lesson: A clean model of a PSP matching build: hash-pinned tools, one ninja command, and sha1sum -c as the final step.

The 3rd Birthday Recomp

The 3rd Birthday

Top rated on RecompLauncherstatic recompplayable
AljandrOrtega PSP recompilerMSYS2 GCClldPPSSPPVulkanSDL3

Started: 2026-06. First release: 2026-10. Code: C and Python.

AI: yes: README says much of the code was written with Claude

Lesson: Run a short bake-off of frameworks on your own executable with fixed checks. Only one of three worked here.

Street Fighter Alpha 3 MAX

Street Fighter Alpha 3 MAX

Top rated on RecompLauncherotherstalled

Started: unknown. First release: 2026-11. Code: unknown.

AI: yes: the catalog flags AI use for code; the repo could not be read

Lesson: The repo returned 404 a week after its last release. Do not build on a project you cannot read.

Portable Ops Native

Metal Gear Solid: Portable Ops

Top rated on RecompLauncherstatic recompin progress
PortableKitCMakeNinjaGCCVulkanSDL3

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

AI: yes: AGENTS.md and a commit naming a Claude session Agent files: AGENTS.md.

Lesson: Boot every stage headless with the interpreter off. Anything that stops is missing code.

Renegade Squadron PC

Star Wars Battlefront: Renegade Squadron

Top rated on RecompLauncherstatic recompplayable
PSPRecompMSVCCMakeNinjaVulkanDirectX 12

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

AI: yes: README credits Codex for the first recomp and Claude for speed and rendering work

Lesson: Write renderer tests that need no game files. Say next to each claim what was not proven.

Tag Force Recomp

Yu-Gi-Oh! GX Tag Force

Top rated on RecompLauncherstatic recompplayable
own Python translatorTinyCCMSYS2Direct3D 11VulkanGhidra

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

AI: yes: AGENTS.md and CLAUDE.md are listed as local-only in .gitignore

Lesson: Replace generated functions one by one with readable C++ and run both from the same state to compare. That turns a recomp into a decomp.

Ape Escape Mind Over Monkey

Saru Get You: Saru Saru Daisakusen

Added: developer used AIstatic recompplayable
PSPRecompCMakeNinjallvm-mingwVulkanSDL3

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

AI: yes: developer note says Claude and Codex for coding

Lesson: Bind a system call only when its behaviour is known. Let every other call stop the run, so gaps are reported, not faked.

The Sims 2 PSP Recomp

The Sims 2

Added: developer used AIstatic recompplayable
PSPRecomp (modified)MSVCCMakeDirect3D 11SDL GPUVulkan

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

AI: yes: developer note says AI helped with code, tests and docs

Lesson: Wrap the whole flow in one command that checks the disc, builds and runs a startup check. Log what each release did not test.

hst-decomp

Hot Shots Tennis: Get a Grip

From outside RecompLaunchermatching decompin progress
mwccpsp build 219psp-gcc kitswiboWSLown match tools

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

AI: yes: README says AI agents work on functions the tools cannot match Agent files: AGENTS.md.

Lesson: Tools first, agents on the rest, and one strict match checker as the only verdict. It reached 41% of code in about four weeks.

What we could not check

  • How many hours a week any dated project spent. The time ranges assume 10 to 15.
  • Earlier private history of Tag Force Recomp, God of War PSP, MHForever, Yakumo and Sims 2. Their first public commit may not be their start.
  • Whether HST-Decomp's pace holds past 41%. No PSP game is fully decompiled.
  • What Street Fighter Alpha 3 MAX was. Its repo returned 404.
  • The current Vulkan SDK version. The LunarG page did not show it.
  • PSP RAM and VRAM sizes. They were seen only in search snippets, so they are left out.
  • Whether PortableKit builds a full port on Windows for a new game. Its CI tests the framework on Windows; Yakumo runs on Windows.
  • Whether the <PREFIX>_STRICT_HLE and <PREFIX>_LIST_STUBS switches work the same in PSPRecomp. They come from the PortableKit docs.
  • Stars for the three outside projects come from GitHub on 2026-11-13, not from the catalog.
  • No command in this guide was run here. Each was checked against live docs or the review cards only.
  • How to get SDL3 and FFmpeg for a PortableKit port on Windows. Its README gives install steps for macOS only.
  • Whether a plain timeout works in Git Bash on Windows. Let tools/boot_check.py enforce the time limit itself.
  • Whether stock binutils-mipsel-linux-gnu accepts -march=allegrex. The reviewed decomps use allegrex-as or a patched pspas instead.
  • That ghidra-allegrex and GhidraMCP work together in one Ghidra 12.1.4 install. Both READMEs were read, but the pair was not run.
  • PSPRECOMP_INTERPRETER_VERBOSE comes from the Dissidia012-PC card only. The PortableKit docs do not list it.
  • A third PSP framework, Nakagawa Recomp by the HST-Decomp author, exists but was not reviewed for this guide.

Sources