How to Recomp PS2 Games: The Complete Walkthrough
This tutorial takes you from a fresh Linux (or Apple Silicon Mac) machine to a PS2 game running in your browser, using the open-source ps2-web-recomp toolchain. Budget around 30–60 minutes, most of it waiting on the first build.
Before you start — the honest version
- Only two games have been brought up so far (Gran Turismo 4 and God of War II). Your game may stop at a system call or graphics feature nobody has implemented yet. That’s the current state of the project, not a bug in your setup.
- You need a disc image of a game you own. No game data is included with the project, and none is downloaded by it.
- You need a browser with WebGPU: Chrome or Edge on Windows/macOS. On Linux it’s off by default (see below).
- Expect roughly 300 MB of disk space per game for the generated code and builds.
Step 1 — Install the toolchain
You need: git, CMake, Ninja, a C++20 compiler (clang is preferred and picked up automatically), Python 3, and 7-Zip if your disc image is inside a .7z archive.
On Debian/Ubuntu-based distributions:
sudo apt install git cmake ninja-build clang python3 p7zip-full On macOS (Apple Silicon), the scripts need a newer bash than the system 3.2:
brew install bash cmake ninja sevenzip The first run installs the Emscripten SDK into tools/emsdk (or uses the one the EMSDK environment variable points to) and downloads wgpu-native for the native runner. If you only want the native window, pass --native-only to skip the browser build entirely — that path needs the SDL2 development files instead.
Step 2 — Clone the repository
git clone https://github.com/snuri00/ps2-web-recomp.git
cd ps2-web-recomp Step 3 — Recompile your game
scripts/port.sh mygame "My Game.iso" port.sh takes an ISO (or a ZIP/7z archive containing one) and does the whole job end to end:
- It reads the boot program named in the disc’s
SYSTEM.CNFand translates the machine code to C++. - It then runs the game headless several times. Static analysis can’t see every function reached through pointers, so each run records the addresses it couldn’t find; the script adds them as entry points and translates again, until a run gets through with no new ones.
- The same runs capture the vector-unit microprograms the game uploads, which are compiled ahead of time as well.
- Finally it builds the web page into
build/web-mygameand a native runner intobuild/native-mygame.
For reference, God of War II goes from ISO to page in about three and a half minutes on an 8-core laptop.
Customizing the discovery runs
By default the exploring runs press start and then cross every five seconds — enough to get most games through their title screens — and insert an empty memory card in slot 1, following the path a player would take.
scripts/port.sh mygame "My Game.iso" --press 900:cross --frames 2400 Frames from the last run land in games/mygame/shots — the quickest way to see how far a new game gets. To rebuild only the page after a change, use scripts/build_web.sh mygame.
Step 4 — Serve it and play
python3 scripts/serve.py build/web-mygame games/mygame/disc.iso Then open http://localhost:8620/. The disc is read over HTTP Range requests, so only the executable is downloaded up front; everything else streams as the game asks for it.
Browser requirements (WebGPU)
- Windows / macOS: Chrome and Edge ship WebGPU by default.
- Linux: WebGPU is off by default — you’ll need to enable it in your browser’s feature flags.
- The GPU renderer is what makes the game fast. Without WebGPU support the page can’t run the GS renderer.
Troubleshooting: if your game doesn’t boot
Set your expectations: two games have been brought up so far. Another game will most likely stop at a system call or an IOP library function nobody has implemented yet. The runner logs exactly that:
[sys] unhandled syscall The game called an operating-system function the high-level emulation doesn’t answer yet.
[iop] missing <library> #<n> An I/O processor library function the game needs hasn’t been reimplemented.
Graphics issues (missing or wrong geometry) The game may use a Graphics Synthesizer feature the renderer doesn’t handle yet.
These aren’t signs you did something wrong — they’re the frontier of the project. Check the project’s GitHub issues to see if your game is being worked on, and share your findings if it isn’t.
What about performance?
The two verified games set the bar to expect:
- Gran Turismo 4 runs a race at full speed — 50 fps for the PAL release — in Chrome on a laptop’s integrated GPU at twice the PS2’s resolution.
- God of War II holds 60 fps in heavy combat at the PS2’s native resolution; at twice the resolution it runs 48–60, limited by the integrated GPU.
You change the internal resolution from the page. On a discrete GPU, expect more headroom.
Next: what games run today?
See the full compatibility breakdown for the verified titles — and what’s known about the road ahead.
PS2 Web Recomp games list →