Skip to the page
It's Decomplicated
Sony, 2013

PlayStation 4 decomp guide

The game's own PC-type code runs as is. You rebuild the console around it.

What this system is like

The PlayStation 4 uses the same kind of chip as your PC. It is an x86-64 chip. So the game's code can run on your PC with no translation. You do not recompile it. You build a runtime instead. A runtime is code that stands in for the console's own system parts. It handles memory, threads, files, sound, pads and saves.

Graphics are the big job. The PS4 graphics chip gets its own kind of commands and shaders. A shader is a small program that runs on the graphics chip. Almost every project here borrows the graphics part of shadPS4, a free PS4 emulator. It turns PS4 graphics work into Vulkan, a PC graphics system.

This method is new. The first port, bbport for Bloodborne, started in late September 2026. By mid-November the RecompLauncher catalog listed 80 ports of 54 games. Their short catalog notes suggest nearly all are built the same way. 66 of them are flagged as made with AI help. New ports start by copying an old one and filling in what the new game needs.

A full decomp of a PS4 game has never been done. Nobody has the exact Sony compiler, so byte matching is not possible. Path B in this guide shows the only real route. You swap the game's code for your own C, one function at a time, while the game keeps running. It is a very long job.

No recompiler at all

The PS4 chip and your PC chip speak the same machine code. So the game's code runs as it is. Your work is the runtime and the graphics, not the CPU. One project calls it Wine plus DXVK for one game.

Ports are forked, not started fresh

Almost every PS4 port began as a copy of an older port. The family tree starts at bbport. Then came gow3_pc (now SpartanPort) and many more. You copy one, delete the old game's parts, and add what your game needs.

The work list comes from the imports

An import is a system function the game asks for by NID. A check command lists the imports your runtime does not answer yet. That list is your to-do list. Projects saw 54 to 259 missing imports at the start.

Graphics come from shadPS4

Most ports copy the graphics part of shadPS4 into their own repo. This part is called the video core. You fix bugs inside a copy you did not write. Every edit gets a marked comment, so you can merge new upstream code later.

Windows is not the console

The game expects console rules for memory, thread storage and the stack. Windows breaks several of them. Ports patch the game's code at start to fix this. Old CPUs without AVX or MOVBE need extra fixes too.

No matching decomp is possible

Sony's compiler is based on Clang, but its exact build is not public. So you cannot prove your C rebuilds the same bytes. A full decomp has to be checked by behaviour instead. Nobody has finished one.

Two paths

Path A

Get it running on PC

You fork a working PS4 port and point it at your game's dump. A script turns eboot.bin into one memory image and links the game's own modules in. A small loader maps the image and jumps into the game. You then fill in each missing system function until the game boots. Last, you fix crashes and graphics bugs one at a time.

Go to the steps

Path B

Full decomp for porting

No one has decompiled a PS4 game. Byte matching is not possible, because Sony's exact compiler is not public. The real route is the one OpenRCT2 used on PC. You keep the original game running inside your Path A port. You replace one function at a time with your own C. A test runs the same scene with and without your function and compares the results.

Go to the steps

Path A: Get it running on PC

You fork a working PS4 port and point it at your game's dump. A script turns eboot.bin into one memory image and links the game's own modules in. A small loader maps the image and jumps into the game. You then fill in each missing system function until the game boots. Last, you fix crashes and graphics bugs one at a time.

Method: compatibility-layer port (native eboot, HLE runtime, shadPS4 video core)

Pick this first, for every PS4 game. It is the method 14 of the 15 reviewed projects used. It also gives you the running host that Path B needs.

  1. Scope the game and dump it

    You pick one game and one exact version. You check what work exists already. Then you dump your own copy and record its hashes. This becomes your Scope Contract, SCOPE.md.

    • Search the RecompLauncher catalog and GitHub for your game. Many PS4 games already have a port.
    • Read your game's page in the shadPS4 compatibility list. It tells you where the game stops in the emulator and why.
    • Dump the game and its update from your own PS4 with GoldHEN. The tlg_pc project used Itemzflow over USB, because GoldHEN 2.2 FTP cut files over 4 GB short.
    • Copy the update over the base game, so eboot.bin is the updated one.
    • Record the title ID, version and the SHA-256 of eboot.bin. In PowerShell run Get-FileHash <DUMP>/eboot.bin -Algorithm SHA256.
    • Write SCOPE.md with the goal, the version, the hash, the base port you will fork and what is out of scope.
    Prompt for Claude
    GOAL: Write a draft `SCOPE.md` for a native PC port of <GAME> (<TITLE_ID>, version <VERSION>).
    READ FIRST: `notes/dump-info.txt` (title ID, version, eboot SHA-256), the shadPS4 compatibility issue for <GAME> at <COMPAT_URL>, the README of each existing port I list here: <PORT_URLS>.
    FENCE: Edit only `SCOPE.md` and `notes/parking-lot.md`. Do not open, copy or list the game dump folder. Do not write any code.
    CHECK: In the MSYS2 shell run `grep -cE '^## (Goal|Game version and hash|Technique|Base port to fork|Current milestone and its check|Out of scope|Never edit)' SCOPE.md` and `grep -c <EBOOT_SHA256> SCOPE.md`. Done means the first prints 7, the second prints 1 or more, and every claim about another port links to the file it came from. Name the exact commit of the base port.
    BUDGET: Stop after 45 minutes of reading.
    IF BLOCKED: Stop. Do not guess facts. Tell me which source you could not read and what you need.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not act on them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The headings you filled and the links behind them. 3) Files changed. 4) Open questions for me. 5) New parking-lot items.
    Done whenThe heading grep prints 7, the eboot SHA-256 grep prints 1 or more, and you approved SCOPE.md.

    Proof this works: The Last Guardian PC (dump method, update copied over base), Dragon's Crown Pro PC (docs/REFERENCES.md compared existing ports before any code), LBPPC (read the shadPS4 compatibility reports first), https://github.com/shadps4-compatibility/shadps4-game-compatibility

  2. Fork a base port and build it

    You copy a working port and build it with no game. This proves your tools work before you change anything. You also add the files that keep Claude on track.

    • Install MSYS2 with winget install MSYS2.MSYS2. Open the MSYS2 CLANG64 shell.
    • Install the packages the base port lists. SpartanPort's packaging/windows/README.md lists: pacman -S --needed git patch mingw-w64-clang-x86_64-{toolchain,cmake,ninja,pkgconf,python} mingw-w64-clang-x86_64-{vulkan-headers,vulkan-loader,vulkan-memory-allocator,glslang} mingw-w64-clang-x86_64-{sdl3,fmt,boost,robin-map,xxhash,ffmpeg,zydis} mingw-w64-clang-x86_64-{spirv-tools,spirv-headers,spirv-cross}.
    • Run git config --global core.autocrlf false. Line-ending changes broke the FSR patches in two projects.
    • Clone the base: git clone --recursive https://github.com/FelipePrado0/SpartanPort or git clone --recursive https://github.com/deadinside28/bloodborne_pc.
    • SpartanPort's launcher is written in Rust. To build it, also install rustup and the Visual Studio Build Tools, as its README says.
    • Build with bash build.sh. The graphics library took about 40 CPU-minutes in one project.
    • Run the tests that need no game. In SpartanPort on Windows: python -m unittest discover -s tests -p "test_*.py" and its ninja -C out/gpu <TEST_TARGETS> targets. Its bash build.sh --test runs on Linux only.
    • Add CLAUDE.md, docs/STATUS.md, docs/PROGRESS.md and notes/parking-lot.md. Make one script, such as tools/check.sh, that runs the build and all tests.
    Prompt for Claude
    GOAL: Make `tools/check.sh` build the forked port and run every test that needs no game files, and exit 0.
    READ FIRST: `SCOPE.md`, `README.md`, `build.sh`, `packaging/windows/README.md`.
    FENCE: Edit only `tools/check.sh`, `CLAUDE.md`, `docs/STATUS.md`, `docs/PROGRESS.md` and `notes/parking-lot.md`. Do not change any code in `src/`, `gpu/` or `scripts/`. Do not add features, refactors or tools I did not ask for.
    CHECK: Run `bash tools/check.sh` in the MSYS2 CLANG64 shell. Done means it ends with exit code 0 and prints the test counts.
    BUDGET: Stop after 3 failed build attempts with the same error.
    IF BLOCKED: Stop. Do not work around it. Paste the first error line, what you tried, and what you need from me.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: paste the last 20 lines of the check output. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenbash tools/check.sh exits 0 on a clean clone and prints the number of tests that passed.

    Proof this works: SpartanPort README, Building and Tests sections (read 2026-11-13): build.sh, unittest, Ninja test targets; build.sh --test is Linux only, https://github.com/FelipePrado0/SpartanPort/blob/main/packaging/windows/README.md, CTR-NitroFueled-PC (40 CPU-minutes for the GPU library), Killzone Shadow Fall PC (core.autocrlf false), https://github.com/deadinside28/bloodborne_pc

  3. Map the eboot: imports and hazards

    You turn the dump into a game image and list every import the game needs. You sort them by who answers them. You also scan the code for instructions that Windows or old CPUs cannot run. This map is your work plan.

    • Point the base port at your dump and let it prepare the image. In bbport: BB_GAME_DIR=<DUMP> bash run.sh. In SpartanPort: SPARTAN_GAME_DIR='<DUMP>' bash run.sh.
    • Run the import check of your base. In SpartanPort: out/spartanport-probe out/boot-linked.bin --app0 "<DUMP>" --check-imports. Other bases name it --check-imports or --list-imports. It lists every import with no answer.
    • Name each NID with the NID-to-name list from shadPS4, the file src/core/aerolib/aerolib.inl. LBPPC found the inherited list only named Bloodborne's imports, so extend it.
    • Sort imports into three groups: answered by the game's own modules, already in the runtime, and missing. Save it as docs/imports.md.
    • Scan the code with a small iced-x86 script for fs: thread-storage reads, rdtsc, syscall, and AVX, BMI1, MOVBE and LZCNT instructions. Save the counts. OpenCrown-PC did this survey with capstone.
    Prompt for Claude
    GOAL: Produce `docs/imports.md`, a table of every import <GAME>'s eboot needs, grouped as game-module, runtime, or missing.
    READ FIRST: `SCOPE.md`, `scripts/prepare.py`, `scripts/link_modules.py`, the output of `<IMPORT_CHECK_COMMAND>` saved in `notes/imports-raw.txt`.
    FENCE: Edit only `docs/imports.md`, `tools/` scripts you create for this, and `notes/parking-lot.md`. The dump at <DUMP> is read-only. Never copy game files into the repo.
    CHECK: Run `python tools/count_imports.py`. Done means the table's three group totals add up to the total the import check prints, and each missing row has a library, a name and the shadPS4 source file that implements it, or 'not in shadPS4'.
    BUDGET: Stop after 60 minutes.
    IF BLOCKED: Stop. Say which NIDs have no name and where you looked.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The three totals and the check output. 3) Files changed. 4) Missing imports grouped by library. 5) New parking-lot items.
    Done whendocs/imports.md lists every import, the three group totals add up to the import check's total, and every missing one names its library.

    Proof this works: Dragon's Crown Pro PC (749 imports: 166 game modules, 324 inherited, 259 missing), LBPPC (646 imports from 52 modules, 124 left), OpenCrown-PC (capstone hazard survey before the loader design), CTR-NitroFueled-PC (import names from shadPS4's aerolib list), https://github.com/shadps4-emu/shadPS4/tree/main/src/core/aerolib

  4. First light: boot to the first frame

    You make the loader stop at the first missing import. You write that one function and run again. You repeat until the game draws a frame. A missing function must never fail in silence.

    • Make the loader exit with the import's name and caller when it hits one with no answer. Dragon's Crown Pro used exit code 20 for this.
    • Write each missing function in the matching src/runtime_*.c file. Follow the shadPS4 source for what it must do.
    • Put imports only this game needs in their own file, such as src/runtime_<game>.c.
    • Where you write a placeholder, make it log a clear line once. Never return 0 without a word.
    • Log the blockers in order in docs/FIRST_BOOT.md: the import, what it does, and where the fix came from.
    • Run until the log shows frames being drawn and a screenshot shows the logo or menu.
    Prompt for Claude
    GOAL: Implement the next missing import that stops <GAME> at boot: <IMPORT_NAME> (<LIBRARY>).
    READ FIRST: `docs/imports.md`, the last 50 lines of `logs/last_run.log`, the shadPS4 source for <IMPORT_NAME> at <SHADPS4_PATH>, and the runtime file `src/<RUNTIME_FILE>.c`.
    FENCE: Edit only `src/<RUNTIME_FILE>.c`, its lookup table, a new test in `tests/`, `docs/FIRST_BOOT.md` and `docs/imports.md`. Do not touch `gpu/shadps4/`. No blanket return 0: a real implementation, or a logged stub that fails visibly.
    CHECK: Run `bash tools/check.sh`, then `<RUN_COMMAND>`. Done means the check exits 0 and the new log no longer stops at <IMPORT_NAME>. Paste the new stop line.
    BUDGET: Stop after 3 tries, or 45 minutes with no new progress.
    IF BLOCKED: Stop. Do not work around it. Tell me what the game expects from this call and what you could not find out.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: the old and new stop lines from the log. 3) Files changed. 4) The next blocker. 5) New parking-lot items.
    Done whenThe run log shows the game drawing frames, and a screenshot shows its first logo or menu.

    Proof this works: Dragon's Crown Pro PC (docs/FIRST_BOOT.md blocker list), CTR-NitroFueled-PC (CONTRIBUTING.md: no blanket return 0), Killzone Shadow Fall PC (146 imports, boot to the intro film the same day), The Last Guardian PC (391 of 391 imports resolved before first boot)

  5. Fix crashes one at a time

    You play until it crashes, then find the one cause. You prove the cause before you change code. Many crashes come from Windows rules that differ from the console.

    • Turn on the fault reporter. It should print registers, the stack, and the crash address as an offset in the eboot.
    • Name the functions in a crash stack with llvm-symbolizer. It is in the mingw-w64-clang-x86_64-llvm-tools package, which the MSYS2 clang toolchain group installs.
    • Run the same scene in shadPS4. If it breaks there too, the bug is likely in the shared video core.
    • Open the eboot in Ghidra with the GhidraOrbis loader to read the code at the crash address.
    • Write each finding in docs/PROGRESS.md with the date: what you saw, what you tried, and what fixed it. Write the dead ends too.
    Prompt for Claude
    GOAL: Find the cause of the crash at <EBOOT_OFFSET> in <SCENE>. Do not fix it yet.
    READ FIRST: `logs/<RUN_LOG>` (send it to a subagent and get back the first fault and its module), `docs/PROGRESS.md` dead ends, Ghidra notes in `analysis/<SUBSYSTEM>.md`.
    FENCE: Read-only for all code. You may add logging behind a new switch that is off by default, in `src/` only. Write findings only in `docs/PROGRESS.md`.
    CHECK: Run `bash tools/check.sh` after you add logging. It must exit 0. Then run `<RUN_COMMAND>` to the crash scene twice: once as is, once with a one-line change. Done means you name one cause and show two pieces of proof: a log line or counter that shows it, and the second run where the crash goes away or moves. Compare the same scene in shadPS4 and say what it does.
    BUDGET: Stop after 4 hypotheses ruled out, or 90 minutes.
    IF BLOCKED: Stop. List each hypothesis, the test you ran and its result. Tell me what tool or test run 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 cause and both pieces of proof. 3) Files changed. 4) The fix you propose. 5) New parking-lot items.
    Done whenAfter the fix, two 10-minute runs of the crash scene leave no fault report in their logs, and the cause is written in docs/PROGRESS.md.

    Proof this works: Killzone Shadow Fall PC (game clock tied to a 1.594 GHz rdtsc; root cause found before the patch), The Order: 1886 PC Native Port (llvm-symbolizer on fault stacks), Uncharted Collection PC (compare with shadPS4 in the same scene first), The Last Guardian PC (Ghidra with GhidraOrbis for spot questions)

  6. Fix graphics in the video core

    You fix wrong colors, missing objects and flicker. Most fixes go into your copy of the shadPS4 video core. You mark every edit there so later merges stay possible.

    • Mark every edit in gpu/shadps4/ with a tagged comment, such as // mygame:, plus the reason.
    • Add A/B switches. A toggle file the game re-reads while running lets you flip a fix on or off without a rebuild.
    • Capture a frame with RenderDoc to see which draw goes wrong.
    • After any shader layout change, check the dumped shaders with spirv-val --target-env vulkan1.3. Bad SPIR-V crashed the AMD driver in one project. Uncharted Collection PC dumps them with GOW3_DUMP_SHADERS=1. Your base may name this switch in another way.
    • Know where your base keeps its video core. Most keep a copy in gpu/shadps4/. bbport itself now has its own renderer in gpu/, which started from shadPS4's code.
    • Find a bad draw by turning draws off by shader hash until the fault goes away.
    • Write each fix as: seen, cause, how found, fix, log lines. Keep it in docs/rendering-fixes.md.
    Prompt for Claude
    GOAL: Find and fix the cause of <VISUAL_BUG> at <TEST_SPOT>.
    READ FIRST: `docs/rendering-fixes.md`, `docs/PROGRESS.md`, the A/B switch list in `docs/STATUS.md`, the RenderDoc capture at <CAPTURE_PATH>.
    FENCE: Edit only files under `gpu/`. Every edit in `gpu/shadps4/` gets a `// <TAG>:` comment with the reason. New behaviour sits behind a switch that is off by default. Do not touch `src/`.
    CHECK: Run `bash tools/check.sh`. Then I run the game with the switch off and on at <TEST_SPOT> and the known test spots in `docs/rendering-fixes.md`. Done means the check exits 0, `spirv-val` passes on the dumped shaders, and I confirm the bug is gone with the switch on and nothing else changed.
    BUDGET: Stop after 3 failed fixes, or 2 hours.
    IF BLOCKED: Stop. Tell me which draw or shader you suspect, the proof, and what capture you need.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: check output and spirv-val output. 3) Files changed. 4) What I must look at in game. 5) New parking-lot items.
    Done whenYou see the fix at the test spot with the switch on, the old test spots still look right, and bash tools/check.sh exits 0.

    Proof this works: The Last Guardian PC (.claude/skills/dlaa-debug: live toggles, user judges each step), LBPPC (switch draws off by shader hash; seen/cause/fix write-ups), Uncharted Collection PC (spirv-val on dumped shaders), Shadow of the Colossus PC (RenderDoc helpers, Vulkan validation layers)

  7. Build golden runs Claude can do alone

    You make the game test itself. A pad replay drives it to a known point. A script waits for a log line and takes a screenshot. Now Claude can check its own work without you.

    • Record pad input to a file and replay it. CTR used BB_PAD_RECORD and BB_PAD_REPLAY.
    • Write a run script that starts the game, replays input, waits for a known log line, saves a screenshot and exits.
    • Run it many times with a batch tool. The Order: 1886 used tools/batch_runs.py to count crashes, freezes and frame times.
    • Add a fixed benchmark scene and log frame stats, so speed claims can be compared.
    • Keep tests that need no game in CI. Smoke-test the packaged zip on a clean machine.
    Prompt for Claude
    GOAL: Add `tools/golden_run.py`, which starts <GAME>, replays `tests/pad/<ROUTE>.pad`, waits for the log line <LOG_LINE>, saves a screenshot and exits with 0 on success.
    READ FIRST: `docs/STATUS.md`, the run script `run.py`, the pad code in `src/runtime_pad.c`.
    FENCE: Edit only `tools/golden_run.py`, pad record and replay code in `src/runtime_pad.c` behind a switch that is off by default, `tests/pad/`, and `docs/STATUS.md`. Do not change game behaviour. Never send keys to a game this session did not start. Only close processes this session started.
    CHECK: Run `python tools/golden_run.py --runs 3`. Done means 3 of 3 runs reach <LOG_LINE> inside <SECONDS> seconds and save 3 screenshots. Then break the route on purpose and show that the tool fails.
    BUDGET: Stop after 3 failed tries.
    IF BLOCKED: Stop. Tell me what the game did instead, with the log tail.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: output of the 3 good runs and the failing run. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenpython tools/golden_run.py --runs 3 passes 3 of 3 times, and a broken route makes it fail.

    Proof this works: Killzone Shadow Fall PC (pad input file, wait for a log line, screenshot; text bug confirmed over 4+ runs), The Order: 1886 PC Native Port (tools/batch_runs.py), Driveclub Recomp (BB_BENCHMARK race for repeatable speed tests), P.T. for PC (tools/walkthrough.py plays the whole game without a window)

  8. Harden: patches, checks and release

    You make the port safe for other people's copies. Patches find their place by a byte pattern, not a fixed address. The launcher checks the dump. The package never holds game files.

    • Find every patch and hook site by a byte signature, a short pattern of the original bytes. Check the original bytes before you write. Skip and log a site that does not match.
    • Check the dump in the launcher by title ID, version and the eboot.bin SHA-256. Refuse anything else with a clear message.
    • Make packaging refuse .prx, .sprx and game folders. P.T. for PC refuses a zip with a CUSA01127 folder in it.
    • Run the full check, the golden runs and a long play session on a clean checkout.
    • Write known problems with the cause and the fixed version in the README.
    Prompt for Claude
    GOAL: Move every patch in `patches/<GAME>.xml` and every hook in `src/` from fixed addresses to byte signatures with an original-bytes check.
    READ FIRST: `patches/<GAME>.xml`, `src/signature.h` (or the base port's signature code), `docs/STATUS.md`.
    FENCE: Edit only `patches/`, `src/signature.*`, the hook install code, `tests/test_signatures.*` and `docs/PATCHES.md`. Do not change what any patch writes.
    CHECK: Run `bash tools/check.sh` and `python tools/golden_run.py --runs 3`. Done means both pass, the signature test finds every site exactly once in the reference eboot, and a run with one byte changed skips that site and logs it.
    BUDGET: Stop after 3 failed tries on any one site.
    IF BLOCKED: Stop. List the sites with no unique signature and why.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`. Do not fix them.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: check output, golden run output, signature test output. 3) Files changed. 4) Sites left. 5) New parking-lot items.
    Done whenThe full check and the golden runs pass on a clean checkout. Every patch site is found by signature. The package script refuses game files.

    Proof this works: SpartanPort (one port covers two title IDs and two versions by signature), Driveclub Recomp (hooks check the 1.28 bytes and fail closed), The Order: 1886 PC Native Port (early patches wrote inside instructions and broke code), Dragon's Crown Pro PC (eboot SHA-256 gate per supported build)

Path B: Full decomp for porting

No one has decompiled a PS4 game. Byte matching is not possible, because Sony's exact compiler is not public. The real route is the one OpenRCT2 used on PC. You keep the original game running inside your Path A port. You replace one function at a time with your own C. A test runs the same scene with and without your function and compares the results.

Method: non-matching decompilation by function replacement

Pick this only after Path A works, and only if you want the game on a system that is not x86-64. Expect years, not months. If you just want to play on PC, stop at Path A.

  1. Scope: decide if a decomp is worth it

    You decide what you want from a decomp. You check the size of the job. You pick one part of the game to start with. Write it all in SCOPE.md.

    • Make sure your Path A port runs the game start to end. It is the test bed for every step here.
    • Count the game's functions in Ghidra (see the next step) and write the number down.
    • Pick one subsystem to start, such as menus, save data or game rules. Leave graphics for last.
    • Write down that the check is behaviour, not bytes. Say which tests count as proof.
    • Write down the end goal. For a port to ARM, every game function must be replaced before the eboot can go.
    Prompt for Claude
    GOAL: Write `SCOPE-decomp.md`: is a full non-matching decomp of <GAME> worth it, and where would it start?
    READ FIRST: `SCOPE.md`, `docs/STATUS.md`, `analysis/function-count.txt`, and these references: <REFERENCE_URLS>.
    FENCE: Edit only `SCOPE-decomp.md` and `notes/parking-lot.md`. Write no code.
    CHECK: Run `grep -cE '^## (Goal|Function count|Check|First subsystem|Out of scope|Time range|Unknowns)' SCOPE-decomp.md`. Done means it prints 7. Under those headings: how the function count was measured, the behaviour tests by name, why this subsystem goes first, and the reasoning behind the time range.
    BUDGET: Stop after 45 minutes.
    IF BLOCKED: Stop. Tell me what you could not measure.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The numbers and where they came from. 3) Files changed. 4) Open questions. 5) Your honest view: can one person finish this?
    Done whenThe heading grep on SCOPE-decomp.md prints 7, the function count came from Ghidra, and you approved the file.

    Proof this works: https://github.com/benpye/OpenRCT2 (early README: replace each procedure one by one), The Order: 1886 PC Native Port (.agents/skills/wb-clean-room-rebuild), No PS4 decomp found on GitHub or the web (searched 2026-11-13)

  2. Load the eboot into Ghidra

    You make a Ghidra project of your own eboot with the PS4 loader. You export function lists and code to text files. Claude reads those files instead of the big binary.

    • Install Ghidra 12.1.4, because the newest GhidraOrbis release has a zip for it. The 12.1.4 README asks for JDK 21, 64-bit. (Ghidra 12.2 asks for JDK 25.)
    • Install GhidraOrbis from its release zip: File, Install Extensions, then the + button.
    • Import the decrypted eboot.bin and the game's own .prx modules. Run auto-analysis. tlg_pc needed about 9 minutes with a 16 GB heap.
    • Export functions, strings and imports to text with the ghidra-headless skill. It needs bash, so use Git Bash on Windows and set GHIDRA_HOME yourself.
    • Keep the Ghidra project and exports outside the repo or in an ignored folder.
    Prompt for Claude
    GOAL: Export a function list of <GAME>'s eboot from Ghidra to `analysis/functions.csv`.
    READ FIRST: `SCOPE-decomp.md`, the `ghidra-headless` skill, the Ghidra project at <GHIDRA_PROJECT_PATH>.
    FENCE: Edit only `tools/ghidra/` scripts and files in `analysis/` (an ignored folder). The Ghidra project and the dump are read-only inputs. Never copy disassembly listings into tracked files.
    CHECK: Run `python tools/ghidra/check_export.py`. Done means `analysis/functions.csv` has columns address, size, name, callers, callees, and its row count equals the function count Ghidra reports.
    BUDGET: Stop after 3 failed export runs.
    IF BLOCKED: Stop. Paste the Ghidra error and say what you need.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: the check output with the row count. 3) Files changed. 4) What is left. 5) New parking-lot items.
    Done whenanalysis/functions.csv has one row per function and the row count equals Ghidra's function count.

    Proof this works: The Last Guardian PC (Ghidra with GhidraOrbis on the 1.03 eboot), https://github.com/astrelsky/GhidraOrbis, https://github.com/NationalSecurityAgency/ghidra/blob/Ghidra_12.1.4_build/README.md (JDK 21), https://www.skills.sh/trailofbits/skills-curated/ghidra-headless

  3. Map the binary into a ledger

    You turn the function list into a ledger with a status column. You mark Sony library code and middleware, so nobody decompiles it by hand. You group the rest by subsystem.

    • Mark functions that are Sony library code. bbport found 99 functions of a built-in libGnm copy in Bloodborne.
    • Mark known middleware by its strings, such as an audio or physics library.
    • Group game functions by subsystem, using strings and call trees.
    • Add columns: status (todo, replaced, verified), tests, notes.
    • Find C++ classes by their vtables, the tables of function pointers each class keeps.
    Prompt for Claude
    GOAL: Turn `analysis/functions.csv` into `docs/ledger.csv` with subsystem, kind (game, sdk, middleware) and status for every function.
    READ FIRST: `analysis/functions.csv`, `analysis/strings.txt`, `docs/imports.md`.
    FENCE: Edit only `docs/ledger.csv`, `tools/ledger/` and `notes/parking-lot.md`. Keep every row. Do not guess: mark a row 'unknown' when the evidence is thin.
    CHECK: Run `python tools/ledger/check.py`. Done means every function has a row, every 'sdk' or 'middleware' row cites a string or call that proves it, and the totals print.
    BUDGET: Stop after 2 hours.
    IF BLOCKED: Stop. Say which groups you could not place.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: totals by kind and by subsystem. 3) Files changed. 4) Unknown groups. 5) New parking-lot items.
    Done whenpython tools/ledger/check.py prints totals by kind and subsystem, and every row has a status.

    Proof this works: https://github.com/deadinside28/bloodborne_pc (libGnm statically linked, 99 functions), The Last Guardian PC (analysis/ reports per subsystem), OpenCrown-PC (notes/map/ per-topic findings)

  4. Build the swap-and-compare harness

    You add a way to send one game function to your C version. You add a test that runs the same scene with the swap on and off. Then you prove the test can fail.

    • Use the base port's hook code. Install each hook by signature and check the original bytes first.
    • Give each swapped function its own bit in a toggle file, off by default.
    • Mark every C function the game calls with __attribute__((sysv_abi)). Game code uses the SysV calling rules, and Windows uses its own.
    • Write a differential test: run the same pad replay twice, swap off and swap on. Compare logged state, saves or screenshots.
    • Calibrate it. Plant three wrong versions of one function: a wrong constant, a wrong branch, a wrong edge case. The test must reject all three.
    Prompt for Claude
    GOAL: Add `tools/swaptest.py <FUNCTION>`: it runs the golden route with the swap for <FUNCTION> off, then on, and compares the logged state.
    READ FIRST: `src/signature.h`, the hook install code, `tools/golden_run.py`, `docs/ledger.csv`.
    FENCE: Edit only `tools/swaptest.py`, `src/swap/`, `tests/swap/` and `docs/STATUS.md`. Every swap is off by default. Do not change any existing hook.
    CHECK: Run `python tools/swaptest.py <TEST_FUNCTION>` with the true C version and with three planted wrong versions (constant, branch, edge case). Done means the true version passes and all three wrong versions fail.
    BUDGET: Stop after 4 failed tries.
    IF BLOCKED: Stop. Say what state you cannot capture and why.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: output of all four runs. 3) Files changed. 4) What the test cannot see. 5) New parking-lot items.
    Done whenpython tools/swaptest.py passes the true version of a test function and fails all three planted wrong versions.

    Proof this works: The Order: 1886 PC Native Port (wb-oracle-testing: three planted wrong variants first), SpartanPort (hooks by signature; stubs tested as the game would call them), OpenCrown-PC (sysv_abi on every function the game calls), https://github.com/kevinburke/OpenRCT2 (decompiled C run inside the original program)

  5. First light: replace one small function

    You pick a small leaf function, one that calls nothing else. You write it in C and swap it in. The swap test and the golden run must both pass.

    • Pick a leaf function under 50 instructions from your first subsystem.
    • Read it in Ghidra. Write plain C that does the same thing. Name the fields you can prove.
    • Turn on its swap bit and run python tools/swaptest.py <FUNCTION>.
    • Run the golden route with the swap on.
    • Mark the row 'replaced' in docs/ledger.csv with the test output.
    Prompt for Claude
    GOAL: Replace <FUNCTION> at <EBOOT_OFFSET> with C in `src/swap/<SUBSYSTEM>.c`.
    READ FIRST: Ghidra export `analysis/funcs/<FUNCTION>.txt`, its row in `docs/ledger.csv`, `docs/types.h`.
    FENCE: Edit only `src/swap/<SUBSYSTEM>.c`, its swap table entry, and the ledger row. No inline assembly. No copying bytes from the eboot. Do not call the original function from your version.
    CHECK: Run `python tools/swaptest.py <FUNCTION>` and `python tools/golden_run.py --runs 3 --swap <FUNCTION>`. Done means both pass.
    BUDGET: Stop after 5 tries.
    IF BLOCKED: Stop. Paste the first state difference the swap test shows.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: both outputs. 3) Files changed. 4) Fields or types you guessed. 5) New parking-lot items.
    Done whenOne function is swapped in, tools/swaptest.py passes, and 3 of 3 golden runs pass with the swap on.

    Proof this works: https://github.com/benpye/OpenRCT2, The Order: 1886 PC Native Port (clean-room rebuild of one feature, verified on the same inputs)

  6. Grind: many workers, one function each

    Now you scale up. A lead session picks the next functions from the ledger. Each worker replaces one function in its own git worktree, a separate copy of the project folder. Leaf functions go first.

    • Order the work: leaf functions first, then their callers. Stay inside one subsystem at a time.
    • Start each worker with claude --worktree <NAME>. Give it one card for one function.
    • Limit builds to 2 jobs per worker, such as -j2. SpartanPort set this rule so parallel agents do not starve the machine.
    • Merge passing work one at a time. Run the swap test again on the merged branch.
    • Send functions that fail 5 tries to the hard pile.
    Prompt for Claude
    GOAL: As lead, pick the next <N> todo functions in subsystem <SUBSYSTEM> from `docs/ledger.csv` and hand one to each worker.
    READ FIRST: `docs/ledger.csv`, `docs/STATUS.md`, the unit card in `notes/cards/replace-function.md`.
    FENCE: Edit only `docs/ledger.csv` (claim column) and `notes/dispatch-<DATE>.md`. Workers edit only their own `src/swap/` file in their own worktree. No two workers share a file.
    CHECK: For each worker report, re-run `python tools/swaptest.py <FUNCTION>` on the merged branch. Done means each merged function passes there, and the ledger shows its status.
    BUDGET: <N> workers at most. Stop the round after 3 hours.
    IF BLOCKED: Stop the round. Tell me which workers failed and why.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Table: function, worker result, merged-branch result. 3) Files changed. 4) Functions moved to the hard pile. 5) New parking-lot items.
    Done whenThe ledger's replaced count went up, and every replaced function passes the swap test on the merged branch.

    Proof this works: SpartanPort (at most 2 build jobs per agent; separate worktrees), https://code.claude.com/docs/en/worktrees (claude --worktree <name>, read 2026-11-13), https://momo5502.com/posts/2026-10-09-game-decompilation/ (PC game, many agents, one unit each)

  7. Hard units: classes and data layouts

    Big functions and C++ classes need more care. You write a short behaviour spec first. A fresh worker then writes the C from the spec alone. A third checks both on the same inputs.

    • Write docs/types.h for each class layout you prove. Note the proof next to each field.
    • For a big function, write a spec: inputs, outputs, side effects, and the test that shows each.
    • Use separate sessions for spec writer, builder and checker, like The Order's clean-room skill.
    • Stop after 3 rounds. Leave the original running and note why in the ledger.
    Prompt for Claude
    GOAL: Replace hard function <FUNCTION> using a spec first.
    READ FIRST: `analysis/funcs/<FUNCTION>.txt`, `docs/types.h`, `docs/ledger.csv` notes for it.
    FENCE: Session 1 edits only `specs/<FUNCTION>.md`. Session 2 reads only the spec and edits only `src/swap/<SUBSYSTEM>.c`. Session 3 is read-only and runs the tests. No inline assembly.
    CHECK: Run `python tools/swaptest.py <FUNCTION>` and `python tools/golden_run.py --runs 3 --swap <FUNCTION>`. Done means both pass.
    BUDGET: 3 rounds of spec, build and check. Then stop.
    IF BLOCKED: Stop. Keep the original running. Write the reason in the ledger notes.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: both outputs. 3) Files changed. 4) Spec gaps found. 5) New parking-lot items.
    Done whenThe hard function passes the swap test and the golden runs, or it is marked 'stuck' in the ledger with a reason.

    Proof this works: The Order: 1886 PC Native Port (wb-clean-room-rebuild: analyst, spec writer, rebuilder, verifier, 3 rounds), P.T. for PC (format notes mark guesses as guesses)

  8. Harden: all swaps on, many scenes

    One function passing alone is not enough. You turn every swap on at once and play many scenes. This catches bugs that only show when your functions call each other.

    • Add an 'all swaps on' mode to the golden run.
    • Record more pad routes so the test covers each chapter and menu.
    • Run the full set after every merge. Undo any merge that breaks an older route.
    • Print the ledger totals: replaced, verified, stuck, todo.
    Prompt for Claude
    GOAL: Make `python tools/golden_run.py --all-swaps --routes all` pass on the main branch.
    READ FIRST: `docs/ledger.csv`, `docs/STATUS.md`, the route list in `tests/pad/`.
    FENCE: Edit only `tools/golden_run.py`, `tests/pad/`, and `docs/STATUS.md`. To fix a failure, only turn a swap off and file it in the ledger. Do not edit swapped C here.
    CHECK: Run `bash tools/check.sh`, then `python tools/golden_run.py --all-swaps --routes all --runs 2`. Done means the check exits 0 and every route passes in both runs with all verified swaps on.
    BUDGET: Stop after 2 hours.
    IF BLOCKED: Stop. List the routes that fail and the first swap that breaks each.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: route results. 3) Files changed. 4) Swaps turned off. 5) Ledger totals.
    Done whenEvery route passes with all verified swaps on, two runs in a row, on a clean checkout.

    Proof this works: P.T. for PC (headless walkthrough after every change), https://1379.tech/recomp-ai-5-months-later/ (older results must keep working)

  9. Port: drop the eboot

    Only when every game function is your C can you build without the eboot. Then the runtime and video core become your platform layer. You build it for a new system and run the same golden runs there.

    • Check the ledger: every game row is verified. Sony library code must also be replaced by your runtime.
    • Link your C into one program with no eboot loaded.
    • Run the golden runs on PC first.
    • Build for the new system. Fix 32-bit pointer and size limits the game relied on.
    • Run the same golden runs on the new system.
    Prompt for Claude
    GOAL: Build <GAME> from source with no eboot loaded, and pass the golden runs on PC.
    READ FIRST: `docs/ledger.csv`, `docs/STATUS.md`, `CMakeLists.txt`.
    FENCE: Edit only build files and a new `src/main_noeboot.c`. Do not change swapped C. If any function is not replaced, stop.
    CHECK: Run `python tools/ledger/check.py --require-all-verified` and `python tools/golden_run.py --no-eboot --routes all`. Done means both pass.
    BUDGET: Stop after 3 failed builds.
    IF BLOCKED: Stop. List every function or library the build still needs from the eboot.
    OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
    REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: both outputs. 3) Files changed. 4) What is still tied to the eboot. 5) New parking-lot items.
    Done whenThe ledger check shows every function verified, and all golden runs pass with no eboot loaded.

    Proof this works: https://github.com/benpye/OpenRCT2 (must stay a DLL until every procedure is rewritten), Shadow of the Colossus PC (this eboot keeps 31-bit pointers)

Tools you need

ToolWhat it doesHow to get itHow we know
MSYS2 (CLANG64 shell)
Required Windows
A Windows shell with pacman packages. Its CLANG64 toolset builds 13 of the 15 reviewed ports.
Path A Path B
winget install MSYS2.MSYS2 (or the installer from https://www.msys2.org), then open the MSYS2 CLANG64 shellmsys2.org install page (read 2026-11-13: msys2-x86_64-20260927.exe, Windows 10 1809 or newer); winget id MSYS2.MSYS2 found in microsoft/winget-pkgs (manifests/m/MSYS2/MSYS2, version 20260927) and in SpartanPort's packaging/windows/README.md (read 2026-11-13)
bbport (deadinside28/bloodborne_pc)
Required both
The first native PS4 port and the root of the family. Fork it, or a port built on it, as your base. Its renderer is now its own code, which started from shadPS4's.
Path A Path B
git clone --recursive https://github.com/deadinside28/bloodborne_pc.git bbport && cd bbport && bash build.shrepo README (read 2026-11-13): clone and bash build.sh lines as above, run with BB_GAME_DIR=... bash run.sh, loader probe.c, runtime src/runtime_*.c, Windows build in MSYS2 CLANG64, tests bash build.sh --test and python3 -m unittest discover -s tests
SpartanPort (gow3_pc)
Helpful both
The God of War III port. Four reviewed ports forked it directly, and two more reuse its code. It adds signature-based patches and agent plan files.
Path A Path B
git clone --recursive https://github.com/FelipePrado0/SpartanPort && cd SpartanPort && bash build.shREADME Building and Tests sections and packaging/windows/README.md (read 2026-11-13): clone and build lines as above; the launcher needs rustup and Visual Studio Build Tools; forked by Killzone, The Order, Uncharted Collection and tlg_pc; inFAMOUS Second Son and Dragon's Crown Pro PC reuse its code (review cards)
shadPS4
Required both
A PS4 emulator. You use it as a reference: run the same scene there to see if a bug is yours. Most ports copy its video core.
Path A Path B
Download the win64 QtLauncher zip from https://github.com/shadps4-emu/shadps4-qtlauncher/releases (its builds are marked pre-release), or build the core per documents/building-windows.mdREADME and documents/building-windows.md and Debugging.md (read 2026-11-13); used by 13 of the 15 reviewed projects
shadPS4 game compatibility list
Helpful both
Reports on how each game runs in shadPS4 and where it stops. Read your game's page before you start.
Path A
No install. Search the issues at the URL for your game's title ID.repo metadata (read 2026-11-13); used by LBPPC and linked by The Order: 1886
Ghidra
Required Windows
A free disassembler and decompiler. It shows the game's code as C-like text you can read.
Path A Path B
Install JDK 21 64-bit, download `ghidra_12.1.4_PUBLIC_20260921.zip` from the releases page (12.1.4 to match GhidraOrbis), unzip it, run `ghidraRun.bat`README at tag Ghidra_12.1.4_build (read 2026-11-13): JDK 21 64-bit, ghidraRun.bat; the main README asks for JDK 25, which is for the newest release, 12.2 (2026-10-22)
GhidraOrbis
Required Windows
A Ghidra extension that loads PS4 programs and .prx modules. It is built from older PS4 loaders for IDA and Ghidra.
Path A Path B
Download `ghidra_12.1.4_PUBLIC_20261013_GhidraOrbis.zip` from release 1.0156, then in Ghidra: File, Install Extensions, `+`, pick the zip, restart GhidraREADME and releases (read 2026-11-13): release 1.0156 has zips for Ghidra 12.0 to 12.1.4; used by The Last Guardian PC
iced-x86
Helpful both
A Python x86 disassembler. Ports use it to find and rewrite MOVBE, BMI1 and LZCNT instructions for older CPUs.
Path A Path B
py -m pip install -U iced-x86 (use a python.org Python; MSYS2's Python could not install the wheel in one project)Python README (read 2026-11-13); used by CTR-NitroFueled-PC, The Order: 1886, Killzone and inFAMOUS Second Son
Zydis
Helpful both
A fast x86 disassembler library. Ports link it to patch game code at start, such as clock reads.
Path A
pacman -S mingw-w64-clang-x86_64-zydis (in the MSYS2 CLANG64 shell)repo metadata (read 2026-11-13); in the package list of most reviewed ports; Killzone used it to patch rdtsc sites
RenderDoc
Helpful both
A graphics debugger. It captures one frame so you can see each draw and texture.
Path A
Download `RenderDoc_1.47_64.msi` from https://renderdoc.org/builds and run it. The GitHub release holds source and signatures only.renderdoc.org/builds lists RenderDoc_1.47_64.msi and .zip; GitHub release v1.47 (2026-10-31) has only .asc files (read 2026-11-13); used by Shadow of the Colossus PC; shadPS4 Debugging.md has a renderdoc_enabled setting
SPIRV-Tools (spirv-val)
Helpful both
Checks that shader code given to the graphics driver is valid. Bad shaders crashed the AMD driver at start.
Path A
pacman -S mingw-w64-clang-x86_64-spirv-tools (then `spirv-val --target-env vulkan1.3 <file>.spv`)repo metadata (read 2026-11-13); spirv-val used by Uncharted Collection PC and Driveclub Recomp
LibOrbisPkg (PkgTool, PkgEditor)
Helpful Windows
Opens PS4 .pkg files that are fake-signed, so you can unpack your own dump made as a package.
Path A
Download PkgTool or PkgEditor from the v0.2 release on GitHubREADME and releases (read 2026-11-13); used by P.T. for PC and Uncharted Collection PC
GoldHEN
Required PS4 console
Homebrew for your own PS4. The reviewed ports dump the game and update with it.
Path A Path B
Follow the project's own instructions on your console. This guide does not cover console setup.repo metadata (read 2026-11-13); named by The Last Guardian PC, inFAMOUS Second Son PC and Shadow of the Colossus PC

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.

reverse-engineer-binary

skills.sh

Rules for reading the eboot in Ghidra: read the code first, give an address with every claim. It may suggest installing an MCP bridge; pick and install that yourself.

npx skills add xsyetopz/skills --skill reverse-engineer-binary -a claude-code

ghidra-headless

skills.sh

Runs Ghidra with no window and saves functions and strings to files. Set GHIDRA_HOME yourself on Windows. Good for the Path B ledger.

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

reverse-engineer-anything (REA)

skills.sh

The manual for the REA MCP server. The Last Guardian and The Order: 1886 ports name REA next to Ghidra. Use with care: its fallback runs the newest npm package.

npx skills add morluto/rea --skill reverse-engineer-anything -a claude-code

systematic-debugging

skills.sh

No fix until the cause is found. Killzone's missing-letters bug went through six wrong theories first, so this rule pays off here.

npx skills add obra/superpowers --skill systematic-debugging -a claude-code

verification-before-completion

skills.sh

Claude may not say done without fresh proof. On PS4 that means a log line with real frames or a screenshot, not just a process that started.

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 repo, next to docs/STATUS.md.

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

GhidraMCP

MCP server

Lets Claude ask Ghidra for code, names and cross references at a crash address, instead of reading big text exports. Note: that uvx line fetches the newest code from GitHub each time; it is not pinned to a version.

Install `uv`. Download release 2.0 and add its `ghidra_12.1.4_PUBLIC_<date>_GhidraMCP.zip` in Ghidra 12.1.4: File, Install Extensions, `+`. Restart, then turn on 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/`

build-test

write-your-own

One fixed gate before every commit. Uncharted Collection PC used exactly this skill.

Make `.claude/skills/build-test/SKILL.md` and `run.sh`. It exits 2 if the game is running, builds with `bash build.sh`, runs every C, C++ and Python test, and exits 1 on any failure not in a known-broken list. Adding to that list needs your okay.

trace-analyst (subagent)

write-your-own

PS4 run logs are huge. This keeps them out of the main session. Uncharted Collection PC ships this subagent.

Make `.claude/agents/trace-analyst.md`: a read-only subagent that reads `logs/last_run.log` and frame captures and returns the first fault, its module and eboot offset. It never opens game folders and never builds or runs anything.

live-toggle-debug

write-your-own

Graphics bugs need your eyes. The Last Guardian PC's dlaa-debug skill works this way.

Make `.claude/skills/live-toggle-debug/SKILL.md`: start the game with a toggle file Claude can edit, confirm the suspect by flipping one bit, then bisect. You judge each step by eye. Record the rule, the symptom and the shader hashes in the code and the doc in one commit.

Claude setup for this system

Cut Path A into one missing import, one crash, or one visual bug per session. Each unit has a check. The loader no longer stops there, the crash scene runs 10 minutes, or you see the fix. Cut Path B into one function per session, checked by the swap test and a golden run. Keep a ledger file for each: docs/imports.md, docs/PROGRESS.md and docs/ledger.csv. Never hand Claude the whole game at once.

Which model and effort for each job

The model and effort names come from one shared table, so they stay the same on every guide. See Claude Setup for the reasons.

JobWhat it means on this systemMax 20x (now called Ultra)Max 5x (now called Max)
Plan the projectPick the game, version and base port. Compare existing ports and write SCOPE.md. For Path B, measure the function count first.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 MSYS2 packages, fork the base, get bash build.sh and the no-game tests green. Write tools/check.sh and CLAUDE.md.Opus 5.5
effort medium
Sonnet 5.5
effort medium
Study the game fileBuild the import inventory and the hazard survey. Read crash sites in Ghidra with GhidraOrbis. For Path B, build the function 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 functions in src/runtime_*.c, following shadPS4's source for each one. Fix memory, threads, files, sound and saves.Opus 5.5
effort high
Opus 5.5
effort medium
Raise to high for timing and graphics bugs.
Find a bugFind the cause of a crash, a freeze or a wrong picture. Use the fault report, llvm-symbolizer, RenderDoc, A/B switches and a shadPS4 run of the same scene.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 unitsPath A: simple missing imports in a batch. Path B: replace small leaf functions, one per worker, each with its swap test.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 unitsVideo core bugs, timing bugs and large or class-heavy functions. Use the spec-first method for Path B.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 re-runs tools/check.sh and the golden runs. It checks that each fix really runs in its scene and hunts for silent stubs.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 docs/STATUS.md, docs/PROGRESS.md, the import table and the ledger after each unit.Haiku 5.5
effort medium
Haiku 5.5
effort medium

How many sessions at once

Max 20x (now called Ultra)

Path A: one lead and two or three workers, each in its own worktree on its own runtime file or bug. Only one session may run the game at a time, because you share one GPU and one screen. Path B: one lead and four to six workers on leaf functions, each with -j2 builds.

Max 5x (now called Max)

Path A: one session at a time, plus a read-only subagent for logs. Path B: one lead and one or two workers. Run long golden-run batches at night.

Lines for this project's CLAUDE.md

Add to CLAUDE.md
- Read `SCOPE.md`, `docs/STATUS.md` and the newest entry in `docs/PROGRESS.md` before any change.
- The one check is `bash tools/check.sh`. Work is not done until it exits 0. Paste its output.
- The game dump is read-only. Never copy `eboot.bin`, `.prx`, `.sprx` or `.psarc` files into the repo, a worktree or a cloud session. Only offsets and short notes go in docs.
- Files in `out/` are made by `scripts/`. Never edit them by hand. Change the script and run it again.
- Every edit inside `gpu/shadps4/` carries a `// <TAG>:` comment that says why.
- No silent stubs. A missing system function gets a real version, or a logged stub that fails visibly. Never a blanket return 0.
- Find patch and hook sites by byte signature and check the original bytes first. Never use a fixed address.
- Say it works only with proof: a log line with frame counts, a screenshot, or a golden run. A process that started is not proof.
- A fix behind a switch, hash or check must show a log line proving it ran in the target scene, and a test that fails without it.
- Never build or run tests while the game is open. Close only processes this session started.
- In a worktree, use absolute paths and at most 2 build jobs (`-j2`). Never use an unnamed `git stash`.
- Use the Edit tool for C and C++ files, never shell heredocs.
- Write findings and dead ends in `docs/PROGRESS.md`, dated, newest first, in the same commit as the work.

Keep the context small

  • Send big run logs to a read-only subagent. Get back only the first fault and its eboot offset.
  • Give Claude an eboot offset and a short Ghidra export, not a pasted wall of disassembly.
  • Keep docs/STATUS.md to one page. Put history in docs/PROGRESS.md.
  • Clear the chat between units. The ledger files carry the state.
  • Do not let Claude read the vendored gpu/shadps4/ tree at random. Name the one file it needs.

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 PS4 game. It tells you if a port exists, which base to fork and what will be hard.

Prompt for Claude
GOAL: Tell me if <GAME> (<TITLE_ID>, version <VERSION>) can get a native PC port, and which base port to fork. Write it in `notes/feasibility.md`, as input for `SCOPE.md`.
READ FIRST: The shadPS4 compatibility report for <GAME>, the RecompLauncher catalog entry if any, and the READMEs of these candidate bases: <BASE_URLS>.
FENCE: Edit only `notes/feasibility.md` and `notes/parking-lot.md`. Do not open the game dump. Write no code.
CHECK: Run `grep -cE '^## (Existing ports|Base to fork|What shadPS4 says breaks|First milestone and its check|Out of scope)' notes/feasibility.md`. Done means it prints 5, and each existing port has a link.
BUDGET: 45 minutes.
IF BLOCKED: Stop. Say what you could not find. Do not fill gaps with guesses.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) A one-line verdict: fork, join an existing port, or do not start. 3) Files changed. 4) Risks. 5) Questions for me.

A good answer: Starts with DONE. Gives a clear verdict and names any existing port of the same game. Picks one base with a reason. Lists what shadPS4 reports as broken.

Map the binary: import inventory

Right after the base builds and your dump is prepared.

Prompt for Claude
GOAL: Build `docs/imports.md`: every import of <GAME>'s eboot, grouped as game-module, runtime, or missing, with a name for each NID.
READ FIRST: `notes/imports-raw.txt` (output of `<IMPORT_CHECK_COMMAND>`), shadPS4's NID name list at <AEROLIB_PATH>, `src/runtime_*.c` lookup tables.
FENCE: Edit only `docs/imports.md`, `tools/count_imports.py` and `notes/parking-lot.md`. The dump is read-only.
CHECK: Run `python tools/count_imports.py`. Done means the three group totals add up to the import check's total.
BUDGET: 60 minutes.
IF BLOCKED: Stop. List NIDs with no name.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The totals and check output. 3) Files changed. 4) Missing imports by library, most-called first. 5) New parking-lot items.

A good answer: A table with totals that add up, missing imports grouped by library, and each one pointing at the shadPS4 file that implements it.

Unit loop, Path A: one crash

For each crash or freeze during play, once tools/golden_run.py exists (Path A step 7). Before that, use the step 5 card.

Prompt for Claude
GOAL: Fix the crash at eboot offset <OFFSET> in <SCENE>, proven by a cause and a test.
READ FIRST: The first-fault summary from the log subagent, `docs/PROGRESS.md` dead ends, `analysis/<SUBSYSTEM>.md`.
FENCE: Edit only <FILES>. Put the fix behind a switch, on by default only after it is proven. Do not touch unrelated code.
CHECK: Run `bash tools/check.sh`, then `python tools/golden_run.py --route <ROUTE> --runs 2`. Done means both pass, the crash scene runs 10 minutes twice, and the log shows the fix line firing.
BUDGET: 3 fix attempts, or 90 minutes.
IF BLOCKED: Stop. Report each hypothesis and its test result.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: check output, run output, the log line. 3) Files changed. 4) What is left. 5) New parking-lot items.

A good answer: Names one cause with proof, shows the fix's log line firing in the scene, and pastes passing check and golden run output.

Unit loop, Path B: one function

For each function in the Path B grind.

Prompt for Claude
GOAL: Replace <FUNCTION> at <OFFSET> with C so its swap test passes.
READ FIRST: `analysis/funcs/<FUNCTION>.txt`, its row in `docs/ledger.csv`, `docs/types.h`.
FENCE: Edit only `src/swap/<SUBSYSTEM>.c`, its swap table entry and its ledger row. No inline assembly, no bytes copied from the eboot, no call back into the original function.
CHECK: Run `python tools/swaptest.py <FUNCTION>` and `python tools/golden_run.py --runs 3 --swap <FUNCTION>`. Done means both pass.
BUDGET: 5 tries. Then stop.
IF BLOCKED: Stop. Paste the first state difference and your best guess at why.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Proof: both outputs. 3) Files changed. 4) Guessed names or types. 5) New parking-lot items.

A good answer: DONE with both outputs pasted, one file changed, and guessed names clearly listed as guesses.

Batch dispatch

When you have a list of small, separate units: missing imports in different files, or leaf functions.

Prompt for Claude
GOAL: As lead, run one round of <N> workers on the next units from <LEDGER_FILE>.
READ FIRST: <LEDGER_FILE>, `docs/STATUS.md`, the unit card `notes/cards/<CARD>.md`.
FENCE: Edit only the claim column of <LEDGER_FILE> and `notes/dispatch-<DATE>.md`. Each worker gets its own worktree (`claude --worktree <NAME>`) and its own file. No two workers share a file. Workers use `-j2`.
CHECK: After each worker reports, run `bash tools/check.sh` and the unit's own check, `<UNIT_CHECK_COMMAND>`, on the merged branch. Done means both pass there for every merged unit.
BUDGET: <N> workers, 3 hours for the round.
IF BLOCKED: Stop the round. Report which workers failed and why.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) Table: unit, worker result, merged result. 3) Files changed. 4) Units sent to the hard pile. 5) New parking-lot items.

A good answer: A table where each merged unit was re-checked on the merged branch, and failures moved to the hard pile with a reason.

Debug with evidence

When a bug has resisted one or two quick fixes.

Prompt for Claude
GOAL: Find the cause of <BUG>. Do not fix it.
READ FIRST: `docs/PROGRESS.md` dead ends for this bug, the log summary, the A/B switch list in `docs/STATUS.md`.
FENCE: Read-only for code, except new logging behind an off-by-default switch. Write only in `docs/PROGRESS.md`.
CHECK: Run `bash tools/check.sh` after you add logging. It must exit 0. Then run `<RUN_COMMAND>` with the A/B switch off and on. Done means one cause named, with a log line or counter showing it, and the switch run makes the bug go away or move. Also say what shadPS4 does in the same scene.
BUDGET: 4 hypotheses ruled out, or 90 minutes.
IF BLOCKED: Stop. List each hypothesis, its test and result.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The cause and the proof. 3) Files changed. 4) The fix you propose. 5) Hypotheses ruled out, for the dead-end list.

A good answer: One cause, two pieces of proof, the shadPS4 comparison, and the ruled-out ideas written down so no one tries them again.

Verify: hunt for cheating

In a fresh session, after any unit is reported DONE.

Prompt for Claude
GOAL: Check that the work in <BRANCH_OR_COMMITS> is real.
READ FIRST: The diff of <BRANCH_OR_COMMITS>, the task card it answered, `CLAUDE.md`.
FENCE: Read-only. Do not fix anything. You may run checks.
CHECK: Re-run `bash tools/check.sh` and the golden run named in the card. Then look for: blanket return 0 stubs, fixes behind a switch that never fires (no log line in the scene), tests added to a known-broken list, edits to expected hashes or test data, patches at fixed addresses, edits to `gpu/shadps4/` with no tag, game files added to git, and changes outside the card's fence.
BUDGET: 45 minutes.
IF BLOCKED: Stop. Say what you could not check.
REPORT: 1) PASS or FAIL. 2) Check output. 3) Each finding with file, line and why it matters. 4) What the worker claimed but did not prove. 5) Changes outside the fence.

A good answer: PASS or FAIL first, the re-run output pasted, and each finding tied to a file and line.

Status report

Once a week, or before you plan the next block of work.

Prompt for Claude
GOAL: Give me a status report with numbers from the ledgers only.
READ FIRST: `docs/STATUS.md`, `docs/imports.md`, `docs/ledger.csv`, the last 7 days of `docs/PROGRESS.md`, `notes/parking-lot.md`.
FENCE: Read-only. Edit nothing.
CHECK: Run `python tools/count_imports.py` and, for Path B, `python tools/ledger/check.py`. Take the totals from their output. Every other number comes from a file you name. `git status --short` must show no change from you.
BUDGET: 15 minutes.
IF BLOCKED: Say which file is missing or stale.
REPORT: 1) Imports: missing count now and a week ago. 2) Furthest point reached in game, with the golden run that proves it. 3) Open crashes and visual bugs, by count. 4) Path B: replaced, verified, stuck, todo. 5) Top three parking-lot items. No prose padding.

A good answer: Short, all numbers with their source file, and no claims without a golden run behind them.

Session handoff

At the end of every session, or before your plan's limit runs out.

Prompt for Claude
GOAL: Write what the next session needs into the repo, so it can carry on from the files alone.
READ FIRST: `git status`, `git log -10 --oneline`, `docs/STATUS.md`, this session's work.
FENCE: Edit only `docs/STATUS.md`, `docs/PROGRESS.md` and `notes/parking-lot.md`.
CHECK: Run `grep -c '<TODAY_YYYY-MM-DD>' docs/PROGRESS.md` and `git status --short`. Done means the first prints 1 or more, and `git status` shows only the three files above changed. The new entry has: the goal, what was done, the check output, dead ends, the branch name, and the exact next card. `docs/STATUS.md` states the current point in one sentence.
BUDGET: 10 minutes.
IF BLOCKED: Say what you could not record.
OTHER PROBLEMS: Write them in `notes/parking-lot.md`.
REPORT: 1) DONE, PARTIAL or BLOCKED. 2) The new entry, pasted. 3) Files changed. 4) Uncommitted work, if any. 5) The next card.

A good answer: A dated entry a new session could act on without asking you anything, ending with the next task card.

Blocked: cannot deliver

When Claude keeps trying and failing, or says something should work without proof.

Prompt for Claude
GOAL: Give me a plain answer on <TASK>: can it be done now, and if not, why.
READ FIRST: The last report on <TASK>, `docs/PROGRESS.md` entries for it.
FENCE: Read-only. Do not try again in this session.
CHECK: Run `git status --short`. Done means it shows no change from this session, and you answer with one of: CAN DO (with the next card), CANNOT DO YET (with the missing piece), or NOT POSSIBLE (with the reason and the proof).
BUDGET: 15 minutes.
IF BLOCKED: Say so in one line.
REPORT: 1) CAN DO, CANNOT DO YET, or NOT POSSIBLE. 2) The proof. 3) What was tried, in one line each. 4) Two or three options for me, with the cost of each. 5) Nothing else.

A good answer: One of the three verdicts, with proof, and real choices for you. No 'should work' and no new attempt.

Scope change request

When Claude wants to go outside its fence, such as editing the video core during a runtime task.

Prompt for Claude
GOAL: Ask me before you leave the fence for <TASK>.
READ FIRST: The current card, `SCOPE.md`.
FENCE: Make no edits until I answer.
CHECK: Run `git status --short`. Done means it shows no change since this request began, and you have written the request and stopped.
BUDGET: 5 minutes.
IF BLOCKED: Stop and say so.
REPORT: 1) The files or areas you want to touch. 2) Why the current fence is not enough, with proof. 3) The smallest change that would do. 4) The risk to other work. 5) What you will do if I say no.

A good answer: A short request with proof and a smallest-change option, then a stop. 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 makes a missing system function return 0 so the game gets past it. The game then fails later in a strange way.No silent stubs. A real version, or a logged stub that fails visibly. Never a blanket return 0. (CTR-NitroFueled-PC's CONTRIBUTING.md)
Claude adds a fix behind a switch or hash check and reports it fixed. The fix never runs in the scene.A gated fix must show a log line proving it ran in the target scene, and a test that fails without it. (The Order: 1886 AGENTS.md)
Claude says the bug is fixed because the game started and did not crash at once.Say it worked only after real game frames show in the log or a capture. Never inject keys or use a script that closes the game. (SpartanPort plan files)
Claude patches the game at a fixed address it found once. It breaks on another version and can write inside an instruction.Find every site by byte signature, check the original bytes first, and test the hook as the game would call it. (SpartanPort roadmap)
Claude edits the vendored shadPS4 code with no marks, so the next upstream merge loses the fix.Every edit inside gpu/shadps4/ gets a // <TAG>: comment saying why. A reviewer subagent blocks commits without it. (Uncharted Collection PC conventions-reviewer)
Claude copies the eboot into the repo, a worktree or a cloud session to study it.The game executable stays in the dump. Only offsets and short excerpts go in docs. Packaging refuses .prx and .sprx files. (SpartanPort roadmap, Shadow of the Colossus CLAUDE.md)
Claude adds a failing test to the known-broken list to get a green run.Never add a test to the known-broken list without the owner's okay. (Uncharted Collection PC build-test skill)
Claude clears caches or deletes folders to get a clean start, and deletes saves or game files through linked folders.Do not delete or clear user/, shader caches, saves or the installed game. Use a separate profile folder for experiments. (The Order: 1886 AGENTS.md; SpartanPort warns about junction folders)

Problems other projects hit

The game uses CPU instructions some PCs lack: AVX, BMI1, MOVBE, LZCNT and F16C. On older CPUs, LZCNT does not even fail. It quietly gives wrong answers.

Fix: Rewrite those instructions when the game loads, using iced-x86 or Zydis to find them. Rewrite by a static scan, not by catching faults. Say plainly that CPUs without AVX cannot run it.

Seen in: SpartanPort, The Order: 1886 PC Native Port, Bloodborne PC, uncharted_pc, inFAMOUS Second Son PC

Windows writes its crash data into the 128 bytes just below the stack pointer. Game code keeps values there. This gave random crashes, mostly on Intel 12th gen and newer.

Fix: Find functions that use that area and rewrite them at start to run with the stack 128 bytes lower.

Seen in: The Last Guardian PC, Uncharted Collection PC

The game reads its thread data through the fs register. On Windows that register cannot be moved.

Fix: Rewrite those reads at load time to use a Windows thread slot claimed at the start of main.

Seen in: CTR-NitroFueled-PC, Bloodborne PC, inFAMOUS Second Son PC

Killzone ran at about double speed. Its timer assumed the PS4 clock of 1.594 GHz.

Fix: Patch each rdtsc site found with Zydis and report a 1.594 GHz guest clock. Scan for jump targets first: two earlier patch versions crashed because code jumped into the patched bytes.

Seen in: Killzone Shadow Fall PC

Games pack pointers or sizes into fewer bits. Bloodborne keeps 40-bit pointers, Shadow of the Colossus 31-bit ones, and Killzone a 32-bit free-memory count.

Fix: Check how the game stores pointers before you pick load addresses. Place the image, stacks and heaps low enough. Grow memory pools together when you raise the resolution.

Seen in: Bloodborne PC, Shadow of the Colossus PC, Killzone Shadow Fall PC, uncharted_pc

Draws were skipped while their shader was still compiling. Killzone draws each letter only once, so letters went missing for the whole session.

Fix: Do not skip draws in games that cache results. Wait for the shader, or prove the skip changes nothing. Key the shader cache by the recompiler version.

Seen in: Killzone Shadow Fall PC, LBPPC, inFAMOUS Second Son PC

Code left over from the base port's game caused bugs: wrong hooks, wrong upscaler settings, and image shimmer.

Fix: Turn off every feature you inherited from the old game before you chase image bugs. Rename or remove old names in a release review.

Seen in: The Last Guardian PC, Uncharted Collection PC, Dragon's Crown Pro PC

Git on Windows turned line endings into CRLF, and the FSR patches stopped applying to the submodule.

Fix: Run git config --global core.autocrlf false before you clone. To undo build patches, reverse them; do not use checkout -f or clean.

Seen in: SpartanPort, Killzone Shadow Fall PC

The dump was broken. GoldHEN 2.2 FTP cut files over 4 GB short. A merged update kept the old param.sfo.

Fix: Dump big files over USB with Itemzflow. Check every file's size against the console. Check the version in param.sfo and the eboot.bin hash.

Seen in: The Last Guardian PC, inFAMOUS Second Son PC

The NID name list in the base port only named the old game's imports. Functions the runtime already had looked missing.

Fix: Build the name list from shadPS4's full NID list, not from the base port's copy.

Seen in: LBPPC, CTR-NitroFueled-PC

How long it takes

Max 20x (now called Ultra)Max 5x (now called Max)One person, no AIHow sure
Path A: running on PC2 to 8 weeks5 to 20 weeks6 to 18 monthsmedium confidence
Path B: full decomp1 to 3 years2.5 to 7 years8 to 20 years, and in practice nobody has done itlow confidence

Read this first

Numbers assume one medium game and one person giving 10 to 15 hours a week. The fast PS4 dates come from people who worked long days, often with a close base port. So Path A is medium confidence. No pre-AI native PS4 port exists, so the no-AI number is a guess from the size of the work. No PS4 decomp exists at all, so Path B is low confidence and borrowed from PC projects.

What makes it faster or slower

  • Whether a port of a sister game exists. Forking a close base cut first boot to a day or two in several projects.
  • How many imports are missing at the start. Projects saw from 54 to 259.
  • Graphics bugs in the shared video core. They take the longest and need your eyes.
  • How much the game leans on Windows-unfriendly tricks: clock reads, packed pointers, red-zone use.
  • For Path B: the number of game functions and how much is C++ classes with unknown layouts.

The facts behind these numbers

ProjectWhat happenedLink
The Last Guardian PCDump to playable and published on 12 and 13 October 2026, by forking gow3_pc. 9 contributors. Claude skill in the repo.source
Killzone Shadow Fall PCForked gow3_pc on 2026-10-15 and listed 146 missing imports. By the end of that day the notes say all were done and the intro film rendered. Chapter 1 played and beta 0.1.1 out on 2026-10-16. AI session log in the repo. 2 contributors.source
CTR-NitroFueled-PC (SacredFire)SacredFire started from bbport on 2026-10-09. The Windows fork came out on 2026-10-12. 92 of the last 100 commits name Claude as co-author.source
Uncharted Collection PC69 missing imports cut to 0 by 2026-10-13. Uncharted 1 and 3 playable start to end by 2026-11-04. Built with Claude.source
LBPPCFirst notes 2026-10-29. Public beta 2026-11-12, about two weeks later. 2 contributors.source
The Order: 1886 PC Native PortFirst commit 2026-10-14. Still only the prologue is checked on 2026-11-12, after 544 commits with heavy agent use.source
bbportLoader, runtime, graphics and sound added on 2026-09-25. The base for all the ports above.source
OpenRCT2 (PC, for Path B)Rewrote the original program's procedures in C one by one, run inside the original program until all were done. Repo created 2014-04.source
PC first-person shooter decomp (for Path B)About 3 months, up to 16 agents on two top plans, 99% of functions present and 83% byte exact. It had the real compiler, which PS4 work does not.source

Projects reviewed (15)

The top-starred project for each of the top 12 PS4 games on RecompLauncher, plus three projects whose developers say they used AI. RecompLauncher lists 80 PS4 projects for 54 games.

What each project teaches

Bloodborne PC

Bloodborne

Top rated on RecompLauncherotherplayable
bbport loader and runtimeshadPS4 video coreMSYS2 CLANG64CMakeNinjaPyInstaller

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

AI: yes: two feature docs say they were written with Claude, and one with OpenAI Codex

Lesson: The Windows build of bbport. Every speed fix sits behind a switch in a toggle file, so you can test it in the running game.

SpartanPort

God of War III Remastered

Top rated on RecompLauncherotherplayable
bbport family runtimeshadPS4 video coreMSYS2 CLANG64Rust launcherobjdumprizin

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

AI: yes: CLAUDE.md, agent plan files, plans name Claude Code on the web and on Windows Agent files: CLAUDE.md, docs/agents/domain.md, docs/agents/issue-tracker.md, docs/agents/triage-labels.md.

Lesson: Find every patch site by byte signature. That lets one port cover two title IDs and two versions.

P.T. for PC

P.T.

Top rated on RecompLauncherreimplementationcomplete
own Hallway Engineclang-clCMakeNinjaVulkanDirectX 12

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

AI: yes: README says AI coding tools were used to develop and debug

Lesson: A short game can be rebuilt as a new engine that only reads the original data. A headless walkthrough test checks every change.

uncharted_pc

Uncharted: The Nathan Drake Collection

Top rated on RecompLauncherotherplayable
bbport loader and runtimeshadPS4 video coreMSYS2 CLANG64Zydisclang PGO

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

AI: yes: 13 of the last 100 commits carry a Co-Authored-By: Claude trailer

Lesson: When you raise the resolution, follow the size through the game's own memory pools. They must all grow together.

Shadow of the Colossus PC

Shadow of the Colossus

Top rated on RecompLauncherotherplayable
bbport loader and runtimeshadPS4 video coreMSYS2 CLANG64RenderDocVulkan validation layers

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

AI: yes: ships a CLAUDE.md for Claude Code Agent files: CLAUDE.md.

Lesson: Its CLAUDE.md records one hard memory bug and its fix, so Claude does not undo it. Repeatable benchmark scenes back every speed claim.

inFAMOUS Second Son PC

inFAMOUS Second Son

Top rated on RecompLauncherotherin progress
tlg_pc coreshadPS4 video coreMSYS2 CLANG64gcc-14iced-x86Zydis

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

AI: none stated (store flag only)

Lesson: Fixes from sister ports come in as numbered backports. Each can be switched off, so players can find which one broke things.

Driveclub Recomp

Driveclub

Top rated on RecompLauncherotherplayable
bbport family runtimeshadPS4 video coreMSYS2 CLANG64siritspirv-valllvm-profdata

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

AI: none stated (store flag only)

Lesson: Despite the name, nothing is recompiled. Its hooks check the exact version's bytes and fail closed, and a built-in race gives repeatable speed tests.

CTR-NitroFueled-PC

Crash Team Racing: Nitro-Fueled

Top rated on RecompLauncherotherplayable
SacredFire and bbport runtimeshadPS4 video coreMSYS2 CLANG64iced-x86ZydisGitHub Actions

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

AI: yes: README credits Claude; 92 of the last 100 commits carry a Co-Authored-By: Claude trailer

Lesson: A new game is mostly an import job. Its import log has a 'confirmed by' column, and its rules forbid silent stubs.

The Last Guardian PC

The Last Guardian

Top rated on RecompLauncherotherplayable
gow3_pc coreshadPS4 video coreGhidraGhidraOrbisREAMSYS2 CLANG64

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

AI: yes: ships a Claude Code skill (dlaa-debug); docs name REA next to Ghidra Agent files: .claude/skills/dlaa-debug/SKILL.md.

Lesson: From console dump to a published, playable port in two days, by forking a close base. Ghidra was used only for spot questions.

Dragon's Crown Pro PC

Dragon's Crown Pro

Top rated on RecompLauncherotherplayable
own earlier port plus gow3_pc partsshadPS4 video coreMSYS2 CLANG64PowerShell build scriptsFreeType

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

AI: yes: README says AI tools helped with analysis, code, debugging and docs

Lesson: It compared all existing ports before writing code. Then an import inventory became the work plan, and the loader stopped at each missing import.

The Order: 1886 PC Native Port

The Order: 1886

Top rated on RecompLauncherotherin progress
gow3_pc coreshadPS4 video coreMSYS2 CLANG64iced-x86llvm-symbolizerREA

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

AI: yes: AGENTS.md, CLAUDE.md and many agent skills; a report of an unattended agent run Agent files: AGENTS.md, CLAUDE.md, AI-WORKBENCH.md, .agents/skills/wb-*/SKILL.md.

Lesson: Heavy agent use did not make this port quick: four weeks in, only the prologue is checked. Its AGENTS.md rules on proving a fix are worth copying.

Killzone Shadow Fall PC

Killzone Shadow Fall

Top rated on RecompLauncherotherplayable
gow3_pc coreshadPS4 video coreMSYS2 CLANG64Zydisllvm-symbolizer

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

AI: yes: an AI-written session log in docs; 44 of the last 100 commits carry a Co-Authored-By: Claude trailer

Lesson: Fixes were tried first in a patched shadPS4 build, where the game already ran. A dated log of every theory, including wrong ones, cracked a six-theory bug.

Uncharted Collection PC

Uncharted: The Nathan Drake Collection

Added: developer used AIotherplayable
gow3_pc coreshadPS4 video coreMSYS2 CLANG64spirv-vallldbclangd

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

AI: yes: README credits Claude for research, code, testing, packaging and docs Agent files: CLAUDE.md, .claude/agents/conventions-reviewer.md, .claude/agents/trace-analyst.md, .claude/skills/build-test/SKILL.md.

Lesson: A build-test skill, a read-only reviewer and a read-only log reader keep Claude honest. A handoff file lets each new session start in the same place.

Dragons Crown Pro

Dragon's Crown Pro

Added: developer used AIotherplayable
own loader dcp_runown SDL GPU renderercapstoneMinGW-w64 GCCCMakeNinja

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

AI: yes: README says much of the code and reverse engineering was written by Claude

Lesson: You do not have to use shadPS4. For a 2D game, it captured the game's draw calls and replayed them through its own renderer.

LBPPC

LittleBigPlanet 3

Added: developer used AIotherplayable
Bloodborne PC 1.9.5 runtimeshadPS4 video coreMSYS2 CLANG64ZydisPyInstaller

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

AI: yes: developer flag in the catalog (code and art); not described in the repo

Lesson: Diff the game's imports against the runtime you reuse before writing code. Then debug graphics with a repeatable scene and a number score per frame.

What we could not check

  • No PS4 game has a full decompilation. GitHub and web searches on 2026-11-13 found none. Path B is a proposed route built from PC projects and PS4 port parts, not a tested PS4 recipe.
  • The exact Sony compiler build and flags for any PS4 game are not public. The Clang base comes from the clang driver's PS4 toolchain file, not from Sony.
  • The function count of a medium PS4 game was not measured. Path B times rest on PC projects.
  • The no-AI times are estimates. No native PS4 port made without AI was found.
  • Most reviewed repos started from inherited history. Their first-commit dates are the base port's, not their own.
  • SacredFire (T3CHNOLOG1C/SacredFire) returned 404 on 2026-11-13. Its start date comes from the CTR-NitroFueled-PC README only.
  • Itemzflow, used to dump games, was not checked. Console setup is not covered here.
  • GhidraOrbis has no zip for Ghidra 12.2 yet, so this guide uses Ghidra 12.1.4 with JDK 21. Loading a PS4 eboot with that pair was not tried here.
  • No step in this guide was run for this check. No PS4 dump was used. Commands and flags were checked against the tools' own docs and the review cards only.
  • The guide's own helper scripts (tools/check.sh, tools/count_imports.py, tools/golden_run.py, tools/swaptest.py, tools/ledger/check.py, tools/ghidra/check_export.py) do not exist in any base port. You and Claude write them. Their flags are this guide's design.
  • The test commands differ by base port. SpartanPort's bash build.sh --test runs on Linux only. The Ninja test target names change between ports and versions.
  • How AI was used in inFAMOUS Second Son PC and Driveclub Recomp is unknown. The flag was set by the store.
  • Other catalog entries named 'recomp' (Resogun, Dead Nation, Deception IV, Until Dawn) were not reviewed. They may or may not be true recompilers.
  • The psdevwiki pages on PS4 file formats returned HTTP 403 and were not read.
  • GhidraMCP's install steps were read from its README, but GhidraMCP and GhidraOrbis were not tried together in one Ghidra here.

Sources