The snuri00/ps2-web-recomp repository shows how PlayStation 2 games can be executed directly in a web console without a traditional emulator. By statically recompiling the Emotion Engine machine code to C++ and then to WebAssembly, and linking it with a reimplementation of the PS2's operating system and hardware that uses WebGPU for graphics and an AudioWorklet for sound, users can run titles such as Gran Turismo 4 and God of War II after providing their own disc image.
This image shows the GitHub repository for the ps2-web-recomp project, which is the subject of the article describing static recompilation of PS2 games to WebAssembly for browser execution.
The recompilation tool (eerecomp) reads the game's executable, follows control flow to identify functions, and emits C++ for 16 KiB blocks, preserving PS2‑specific quirks like 128‑bit registers, multimedia instructions, branch delay slots, the unique floating‑point unit behavior, and the vector unit 0 coprocessor. Jumps between blocks become tail calls, and thread switches unwind the host stack so no per‑guest stack is needed. The Emotion Engine side is handled by high‑level emulation of threads, semaphores, DMA and vertical‑blank interrupt handlers, alarms, and the SIF channel; the I/O processor runs the game's IRX modules on an interpreted R3000 CPU while its kernel and libraries are rewritten in C++. Graphics are performed by WebGPU compute shaders that bin triangles into tiles and rasterize them according to the GS's rules for texturing, palettes, alpha blending, depth and destination alpha tests, keeping all data in GS memory so that texture‑as‑palette effects work as on the console. Sound is delivered via an AudioWorklet from a reimplemented SPU2 with 48 voices of ADPCM and ADSR envelopes, and movies are decoded by an IPU‑based MPEG‑2 decoder.
Demonstrated performance includes Gran Turismo 4 running at 50 fps (PAL) at twice the native resolution on a laptop's integrated GPU, and God of War II sustaining 60 fps in heavy combat at the native resolution. Achieving these rates required optimisations such as hoisting texture uploads ahead of triangles that do not depend on them, caching recently uploaded textures in a 16 MB GPU buffer to cut per‑frame traffic by ~60 %, and uniformly loading GPU setup data to avoid divergent shaders that limited three‑times‑native resolution to 23 fps before the fix. Remaining challenges are noted for future ports: unimplemented system calls, missing IOP library functions, or unsupported Graphics Synthesizer features will appear as `[sys] unhandled syscall` or `[iop] missing <library> #<n>` in the runner logs. The page must be served with cross‑origin isolation headers because it uses SharedArrayBuffer, and WebGPU is required in Chrome/Edge (with appropriate flags on Linux) or the software renderer fallback, which is too slow for 3D gameplay.

The image depicts Gran Turismo 4 running in a browser, illustrating the performance results described in the article where the game achieves 50 fps at twice native resolution on a laptop's integrated GPU.