Games · October 12, 2026 · 8 min read
PS2 Games in the Browser: Static Recompilation Explained
A GitHub project runs PS2 games in the browser, and its authors say it works without an emulator. The project translates each game's machine code ahead of time, compiles the result to WebAssembly, and draws the graphics with WebGPU. This post explains how that approach works and what the reported frame rates mean.
The first game brought up this way was Gran Turismo 4. Next came God of War II, which exposed bugs that the first game never triggered. Both titles now play from the menus into the action, according to the project's own notes.
How PS2 Games in the Browser Run Without an Emulator
The project calls its method static recompilation, and it follows the same method as a sibling project named psp-web-recomp. First, a tool named eerecomp reads the game's executable and follows its control flow to find the functions. Then it emits C++ for those functions in units of 16 KiB of guest code.
Next, a compiler turns that C++ into WebAssembly, which the browser runs. Most of the translation happens before the game starts. However, a few pieces still need translation on the fly, and a later section covers them.
The generated code keeps the quirks of the PS2's main processor, including 128-bit registers and branch delay slots. It also keeps the console's floating point behavior, which rounds differently from the IEEE standard. As a result, games that lean on exact math, like the replays and license tests in Gran Turismo 4, get the behavior they expect.
Static Recompilation Needs a Small PS2 Kernel
Recompiled code still needs an operating system to call, so the project supplies a small one. The main processor's side of the system gets high-level emulation. That covers threads, semaphores, interrupt handlers, and the channel between the main CPU and the I/O processor.
The I/O processor works differently. It runs the game's own IRX modules, such as the sound driver and the disc streaming code, on an interpreter of its R3000 CPU. Meanwhile, the project reimplements the I/O processor's kernel and libraries in C++.
The disc loads over HTTP Range requests. Because of that, the browser downloads only the executable up front and fetches the rest as the game asks for it.
Vector Units and Graphics in PS2 Games in the Browser
Most 3D work in a PS2 game happens in microprograms that the game uploads to vector unit 1. The project runs them with bit-exact PS2 float math. It also models the pipeline delays of the MAC, status, and clip flags, because games schedule their code around those delays.
Microprograms seen during a test run compile ahead of time into SIMD C++. Any program that the page meets for the first time becomes a WebAssembly module on the spot, which takes a few milliseconds. This is the on-the-fly step mentioned earlier.
The graphics side keeps the Graphics Synthesizer's 4 MB of video memory on the GPU. WebGPU compute shaders then bin triangles into tiles and draw them with the console's own rules for texturing, palettes, and blending. For example, effects that render into a texture or reuse a framebuffer as a palette work the same way they do on the console.
The internal resolution can run at one, two, or three times the native size, and a software rasterizer remains as the reference for checking the GPU output.
Sound, Movies, and Threads in Static Recompilation
Sound starts with the SPU2 chip, which has 48 voices. The project reimplements those voices along with their envelopes and the streaming DMA that games use for music.
Audio then reaches an AudioWorklet through shared memory. Movies decode through an implementation of the IPU, the PS2's MPEG-2 decoder.
Threads follow the console's own layout. The emulation runs in a worker, and vector unit 1 gets a worker of its own, just as it runs in parallel on the console. Finally, graphics commands reach the page thread through a ring buffer, and that thread alone owns the WebGPU device.
Gran Turismo 4 and God of War II: Static Recompilation Results
The project reports its numbers from Chrome on a laptop's integrated GPU. Gran Turismo 4 plays from boot through the opening movie, the menus, and the races, with music, sound effects, and saves on a memory card kept in the browser. God of War II runs from its menus through the cutscenes into combat.
| Game | Resolution setting | Reported frame rate |
|---|---|---|
| Gran Turismo 4 | Twice the PS2's resolution | 50 frames per second in a race |
| Gran Turismo 4 | Three times the native resolution | 48 to 50 frames per second |
| God of War II | The PS2's resolution | 60 frames per second in heavy combat |
| God of War II | Twice the PS2's resolution | 48 to 60 frames per second |
Gran Turismo 4 runs at 50 frames per second because that is the rate of this PAL release. God of War II tested the method a second time, since it needed no game-specific code yet still found bugs. These figures come from the project's authors, so independent testing would add confidence.
Static Recompilation Performance Lessons
Speed did not come easily. At first, a race managed only 3 frames per second natively, because the project still used a software rasterizer and a vector unit 1 interpreter. Moving the drawing to WebGPU compute shaders and compiling the vector programs raised that to about 70.
Next, the team attacked wasted work in the GPU renderer. The first version submitted around 650 compute dispatches per frame, because every texture upload split the batch of triangles. Hoisting uploads ahead of independent triangles cut that number to about 80.
| Change | Before | After |
|---|---|---|
| Move drawing to WebGPU compute shaders and compile vector programs | 3 frames per second | about 70 natively |
| Hoist uploads ahead of independent triangles | around 650 compute dispatches per frame | about 80 |
| Add a 16 MB cache of recent upload contents | The same 3 MB of textures uploaded every frame | data sent per frame cut by about 60 percent |
| Load shader setup uniformly and write each frame's data in one piece | 23 frames per second at three times the resolution | 48 to 50 frames per second |
Scheduling inside the browser mattered as well. The browser limits nested setTimeout calls to 4 ms, so the loop switched to a MessageChannel for its pauses. A separate worker for the emulation also steadied a race that had swung between 40 and 50 frames per second.
Static Recompilation Bugs a Second Game Exposed
God of War II went from a disc image to a web page with only generic changes. Each change fixed a bug or a gap that Gran Turismo 4 had never exercised. The first symptom was silence, because the game's sound driver ticks from an I/O processor timer that nothing had implemented yet.
Two deeper bugs followed. In the recompiler, a branch at the end of a 16 KiB unit made the delay slot instruction run twice. Meanwhile, the vector unit model showed the clip flags one instruction later than the game's microcode expected, which produced giant polygons that should have disappeared.
Trying PS2 Games in the Browser Yourself
The project includes no game data, so you need a disc image of a game you own. Setup calls for git, CMake, Ninja, a C++20 compiler, and Python 3. Everything has run on Linux on x86-64 so far, and each game needs about 300 MB of disk space for generated code and builds.
A script named port.sh handles the whole job. It reads the boot program named on the disc and converts that machine code to C++. After that, it runs the game headless a few times.
Those runs reveal functions that static analysis missed, and the script adds them as entry points.
Conclusion: What PS2 Games in the Browser Show
This project shows that static recompilation, WebAssembly, and WebGPU can carry PS2 games in the browser at playable speeds. The numbers come from the authors, so treat them as reported results rather than independent benchmarks.
For more daily tech stories like this one, visit the news page. If you want clear technical explainers for your own product, reach out through the contact page. You can also read the full details in the project repository.
FAQ About PS2 Games in the Browser
Does the project include any PS2 games?
No. The project includes no game data. You bring a disc image of a game you own.
Which games work today?
Gran Turismo 4 and God of War II both play, according to the project. The first title was Gran Turismo 4, and God of War II followed through the same scripts.
How fast do the games run?
In Chrome on a laptop's integrated GPU, a Gran Turismo 4 race runs at 50 frames per second. God of War II stays at 60 frames per second during heavy combat when it uses the PS2's own resolution.
Which browser did the authors use for testing?
The reported results come from Chrome on a laptop's integrated GPU. No other browsers appear in the project notes.
What does the build need?
Expect git, CMake, Ninja, a C++20 compiler, and Python 3. Everything has run on Linux on x86-64 so far.