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
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.
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.
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.
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
shadPS4compatibility 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.binis the updated one. - Record the title ID, version and the SHA-256 of
eboot.bin. In PowerShell runGet-FileHash <DUMP>/eboot.bin -Algorithm SHA256. - Write
SCOPE.mdwith the goal, the version, the hash, the base port you will fork and what is out of scope.
Prompt for ClaudeGOAL: 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 headinggrepprints 7, the eboot SHA-256grepprints 1 or more, and you approvedSCOPE.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
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 theMSYS2 CLANG64shell. - Install the packages the base port lists. SpartanPort's
packaging/windows/README.mdlists: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/SpartanPortorgit clone --recursive https://github.com/deadinside28/bloodborne_pc. - SpartanPort's launcher is written in Rust. To build it, also install
rustupand 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 itsninja -C out/gpu <TEST_TARGETS>targets. Itsbash build.sh --testruns on Linux only. - Add
CLAUDE.md,docs/STATUS.md,docs/PROGRESS.mdandnotes/parking-lot.md. Make one script, such astools/check.sh, that runs the build and all tests.
Prompt for ClaudeGOAL: 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.shexits 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
- Install MSYS2 with
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-importsor--list-imports. It lists every import with no answer. - Name each NID with the NID-to-name list from
shadPS4, the filesrc/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-x86script forfs:thread-storage reads,rdtsc,syscall, andAVX,BMI1,MOVBEandLZCNTinstructions. Save the counts. OpenCrown-PC did this survey withcapstone.
Prompt for ClaudeGOAL: 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.mdlists 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
- Point the base port at your dump and let it prepare the image. In bbport:
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_*.cfile. Follow theshadPS4source 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 ClaudeGOAL: 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)
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 themingw-w64-clang-x86_64-llvm-toolspackage, 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
Ghidrawith theGhidraOrbisloader to read the code at the crash address. - Write each finding in
docs/PROGRESS.mdwith the date: what you saw, what you tried, and what fixed it. Write the dead ends too.
Prompt for ClaudeGOAL: 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 indocs/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)
Fix graphics in the video core
You fix wrong colors, missing objects and flicker. Most fixes go into your copy of the
shadPS4video 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
RenderDocto 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 withGOW3_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 ingpu/, 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 ClaudeGOAL: 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, andbash tools/check.shexits 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)
- Mark every edit in
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_RECORDandBB_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.pyto 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 ClaudeGOAL: 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 3passes 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)
- Record pad input to a file and replay it. CTR used
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.binSHA-256. Refuse anything else with a clear message. - Make packaging refuse
.prx,.sprxand game folders. P.T. for PC refuses a zip with aCUSA01127folder 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 ClaudeGOAL: 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.
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 ClaudeGOAL: 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 headinggreponSCOPE-decomp.mdprints 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)
Load the eboot into Ghidra
You make a
Ghidraproject 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
GhidraOrbisrelease has a zip for it. The 12.1.4 README asks for JDK 21, 64-bit. (Ghidra 12.2 asks for JDK 25.) - Install
GhidraOrbisfrom its release zip: File, Install Extensions, then the+button. - Import the decrypted
eboot.binand the game's own.prxmodules. Run auto-analysis. tlg_pc needed about 9 minutes with a 16 GB heap. - Export functions, strings and imports to text with the
ghidra-headlessskill. It needsbash, so use Git Bash on Windows and setGHIDRA_HOMEyourself. - Keep the Ghidra project and exports outside the repo or in an ignored folder.
Prompt for ClaudeGOAL: 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.csvhas 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
- Install Ghidra 12.1.4, because the newest
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
libGnmcopy 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 ClaudeGOAL: 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.pyprints 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)
- Mark functions that are Sony library code. bbport found 99 functions of a built-in
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 ClaudeGOAL: 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.pypasses 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)
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.csvwith the test output.
Prompt for ClaudeGOAL: 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.pypasses, 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)
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 ClaudeGOAL: 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)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.hfor 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 ClaudeGOAL: 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)
- Write
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 ClaudeGOAL: 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)
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 ClaudeGOAL: 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
| Tool | What it does | How to get it | How 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 shell | msys2.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.sh | repo 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.sh | README 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.md | README 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 Ghidra | README 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 GitHub | README 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
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
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)
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
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
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
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
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
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)
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
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.
| Job | What it means on this system | Max 20x (now called Ultra) | Max 5x (now called Max) |
|---|---|---|---|
| Plan the project | Pick 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 highOne session. This choice shapes months of work. | Opus 5.5 effort highUse Fable 5.2 for this one session if you have weekly room. |
| Set up the project | Install MSYS2 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 file | Build 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 mediumRaise to high for function edges and data layouts. A mistake there spreads. |
| Build the runtime | Write 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 mediumRaise to high for timing and graphics bugs. |
| Find a bug | Find 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 highAfter two failed tries with full evidence, move to Fable 5.2. | Opus 5.5 effort highOne bug at a time. |
| Bulk units | Path 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 mediumHaiku 5.5 for the plainest units. | Sonnet 5.5 effort mediumFewer workers at once. Haiku 5.5 for the plainest units. |
| Hard units | Video core bugs, timing bugs and large or class-heavy functions. Use the spec-first method for Path B. | Fable 5.2 effort highGo to xhigh only after a failed try at high. | Opus 5.5 effort highSend only the last few that still fail to Fable 5.2. |
| Check the work | A 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 mediumAlways a new session, never the one that did the work. | Sonnet 5.5 effort highAlways a new session, never the one that did the work. |
| Keep the records | Update 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
- 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.mdto one page. Put history indocs/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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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 detour | The 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 AI | How sure | |
|---|---|---|---|---|
| Path A: running on PC | 2 to 8 weeks | 5 to 20 weeks | 6 to 18 months | medium confidence |
| Path B: full decomp | 1 to 3 years | 2.5 to 7 years | 8 to 20 years, and in practice nobody has done it | low 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
| Project | What happened | Link |
|---|---|---|
| The Last Guardian PC | Dump 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 PC | Forked 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 PC | 69 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 |
| LBPPC | First notes 2026-10-29. Public beta 2026-11-12, about two weeks later. 2 contributors. | source |
| The Order: 1886 PC Native Port | First commit 2026-10-14. Still only the prologue is checked on 2026-11-12, after 544 commits with heavy agent use. | source |
| bbport | Loader, 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
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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 --testruns 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
- bbport README (deadinside28/bloodborne_pc)
- shadPS4 README
- shadPS4 Windows build guide
- shadPS4 debugging guide
- shadPS4 game compatibility reports
- SpartanPort README (Building and Tests)
- SpartanPort Windows build notes
- MSYS2 install page
- winget manifest for MSYS2.MSYS2
- MSYS2 package llvm-tools (has llvm-symbolizer)
- Ghidra README
- Ghidra 12.1.4 README (JDK 21)
- GhidraMCP README
- RenderDoc builds
- shadPS4 NID name list (aerolib)
- Claude Code worktrees
- GhidraOrbis README and releases
- iced-x86 Python README
- LibOrbisPkg README
- Clang PS4 toolchain driver (orbis-ld, SCE_ORBIS_SDK_DIR)
- RetroReversing: PS4 hardware and OS
- Early OpenRCT2 README: replace procedures one by one
- Maurice Heumann: agents decompile a PC shooter
- Matthew Stanley: recomp five months later
- REA README
- The Order: 1886 AGENTS.md
- Dragon's Crown Pro PC FIRST_BOOT.md
- LBPPC imports note