Static Recompilation: How PS2 Code Becomes WebAssembly
The static recompilation technique in depth — translating MIPS R5900 game code to WebAssembly ahead of time, why it beats on-the-fly translation, and its honest limits.
Static recompilation is the engine at the heart of the PS2 Web Recomp scene: the technique that converts a PlayStation 2 game's machine code into WebAssembly before it ever reaches your browser. This page explains it properly — what the recompiler actually does, why translating once beats translating forever, where the technique came from, and the per-game limits that keep the playable list honest.
The Problem It Solves
A PlayStation 2 executes MIPS R5900 machine code — a different instruction set from the x86 or ARM CPU in your laptop or phone. Run that game on new hardware and something must bridge the gap. The classical answer is emulation: a program that reads console instructions one at a time and performs the equivalent work on the host, either interpreting directly or just-in-time translating hot code paths as they run.
That works — PCSX2 has run the PS2 library on PCs for two decades — but the translation is a permanent tax. Every instruction, every frame, for the entire session, the emulator pays the bridging cost. The tax is what makes emulation feel heavy, and it is intrinsic to the approach: the emulator cannot know in advance what the game will execute, so it must translate on the fly, forever.
Translate Once, Run Forever
Static recompilation removes the tax by changing when the translation happens. Instead of translating while the game runs, a recompiler analyzes the entire game executable offline — every instruction, every reachable code path, every branch target — and emits an equivalent program in the target language, all at once, ahead of time. The output is a native artifact: on the web, a WebAssembly module. When you load a PS2 Web Recomp port, there is no console code left in it to interpret. The game already speaks the browser's language.
The mental model from the software world is compiling source code into a binary — except the source here is MIPS machine code, and the recompiler performs a mechanical, semantics-preserving translation rather than a rewrite. A MIPS addition becomes the corresponding WebAssembly operation; a branch becomes a WebAssembly branch; memory accesses map onto the linear memory model WASM provides. Done across millions of instructions, the finished module behaves like the original program, at native WASM speed.
What Makes WebAssembly the Right Target
WebAssembly earned its position as the target of this pipeline through three properties. It is fast — browsers compile WASM to actual machine code for your CPU, with a memory model designed for predictable performance. It is universal — every current browser executes it, no plugin, no permission prompt, same behavior everywhere. And it is sandboxed — WASM runs in the browser's security model, which is what makes shipping a translated game as a web page responsible rather than reckless.
The performance point deserves emphasis because it is the whole argument. Game logic in WASM runs close enough to native that the frame budget of a 2000-era console title is met comfortably on ordinary hardware. The PS2 Web Recomp approach means the browser is not struggling to keep up with a translator and a game at once — it just runs the game.
The Half That Is Still Recreation
Translating the CPU code is only half the console. A game constantly talks to its hardware: it kicks DMA transfers, feeds the vector units, programs the Graphics Synthesizer through its registers, streams audio through the SPU2. No amount of code translation reproduces those behaviors, because they are behaviors of silicon, not instructions.
So every recompilation project ships a runtime: a recreation of the surrounding hardware the translated game expects to find. In the web scene, that runtime is itself written for the platform — WebAssembly and TypeScript on the logic side, WebGPU on the rendering side, as the ps2-web-recomp project demonstrates. The runtime is where the per-game difficulty lives. The MIPS translation is mechanical; teaching a young WebGPU recreation to handle every quirk of the Graphics Synthesizer that a specific title abuses is craft work, iteration by iteration.
The Lineage: From Native Recomps to the Web
Static recompilation proved itself off the web first. The broader console recompilation community produced native projects — MIPS translated to C++, compiled for x86 machines — with the God of War PS2 static recompilation standing as the landmark demonstration that a full commercial PS2 title could be converted and run natively at performance dynamic emulation could not match. Parallel work like PS2Recomp turned the approach into reusable tooling rather than one-off heroics, converting PS2 executables to C++ with a runtime underneath.
The web was the natural next stop once two enablers matured: WebAssembly as a universal, near-native target, and WebGPU as a real graphics API. The ps2-web-recomp project — published by developer Samir, snuri00 — combined the recompilation approach with a WebAssembly-and-WebGPU runtime, and the browser instantly became the largest distribution platform a recompiled game has ever had.
The Honest Limits
Three limits keep the scene honest, and every one of them is why a tracker exists. First, per-game work is real: each title that lands playable represents specific effort on its quirks, which is why the playable games list is short and moves title by title rather than in library-wide leaps. Second, the young runtime has rough edges: heavy special effects, unusual rendering tricks and timing-sensitive code can hit unimplemented paths or performance cliffs, as the community's launch-week discussions openly documented. Third, completeness claims are disciplined: the scene marks the difference between a port that boots, one that runs with glitches, and one that is genuinely playable — and this tracker preserves that discipline in its statuses.
A Worked Example, End to End
Concretely, here is the life of one port. A developer picks a title and obtains their own dump of it. The recompilation pipeline analyzes the executable — walking functions, following branches, building a map of every instruction the game can reach — and emits a WebAssembly module implementing the same behavior. Alongside it, the runtime is configured or extended for the game's hardware profile: the DMA patterns it uses, the vector-unit microprograms it uploads, the Graphics Synthesizer modes it engages. The two halves ship together as the hosted page a player then loads.
The per-game craft concentrates in that middle step. Two titles of identical technical appearance can differ wildly in porting effort because one stays on the runtime's paved roads while the other leans on corners no earlier game touched. This is why the scene's lists are honest about statuses, why a playable badge means demonstrated rather than theoretical, and why the arrival of each new port is genuinely news — each one is a proof that the shared machinery cleared another title's particular set of hurdles.
Static Versus Dynamic: The Comparison That Matters
Putting the two approaches side by side clarifies what each is for. Dynamic emulation buys universality: one program, whole library, nothing per-game but configuration. Static recompilation buys performance and deployment: translated code at native WASM speed, shipped as ordinary web artifacts, loadable by anyone with a browser. The PS2 scene now contains both — PCSX2 and its kin in the emulator world, the recomp pipeline in the browser world — and they are complements rather than rivals. The emulator answers what can run everything; the recomp answers what can run brilliantly and travel anywhere. The second answer is the one the web has been waiting for.
None of which changes the trajectory. Every runtime improvement lifts every port; every new port hardens the runtime. Static recompilation took PS2 games from impossible to native on PC, and has now taken them to the browser — the technique is the story, and the games list is the scoreboard.