God of War on PSP now runs in a browser tab, recompiled to WebAssembly rather than emulated
PSP Web Recomp turns a disc image of Chains of Olympus or Ghost of Sparta into a web page that plays at up to 60 frames per second, phones included. You bring the disc; nothing from the games is in...
AI-drafted from 3 sources. This story was written with AI from the outside reporting listed under Sources, and checked by automated tools before it went up. The originals have the full detail.
Ready at Dawn's 2008 PSP game God of War: Chains of Olympus now plays in a web browser without an emulator in the usual sense. PSP Web Recomp, published on GitHub by snuri00 on 7 October, translates the game's MIPS machine code into C++ ahead of time, compiles that to WebAssembly and runs it against a small rewrite of the PSP's operating system and graphics chip that draws with WebGL2.
The README says Chains of Olympus plays from boot through menus, cutscenes and combat at 60 frames per second in the scenes measured so far, in Chrome and Firefox on a laptop, at up to four times the PSP's 480x272, and on phones with touch controls on screen. Music, speech and sound effects work; the game's movies are skipped for now. A second game, God of War: Ghost of Sparta, followed through the same scripts and runs at 55 to 60 frames per second at three times native resolution. Saving and loading arrived in a commit on 9 October, with saves kept in the browser and an export to a ZIP laid out like the PSP's SAVEDATA folder.
How it gets from a disc to a page
The recompiling itself is done by PSPRecomp, a static recompilation framework for PSP software that appeared in August. This project patches it and adds a web target. Everything the game asks of the PSP's system software, from threads and semaphores to the file system, controller, audio and save dialogs, is answered by high-level code on the host side. Disc data is streamed over HTTP range requests, so only the executable downloads up front.
The graphics chip runs on a worker thread with its own canvas, the way the real PSP drew one frame while its CPU prepared the next. That split took a busy fight in Firefox from about 17 ms a frame to about 10. The README is candid about where the rest of the speed came from: the first playable build ran at 6 frames per second, and the biggest single fix was noticing that God of War swaps its framebuffer without waiting for the vertical blank, so it was drawing around eight frames for every one that reached the screen. Holding it to the blank, a trick PPSSPP also uses, cut the work per displayed frame by eight. Ghost of Sparta needed the PSP's disc DRM decryption for one 176-byte file and a lighting fix for a white sky, and no performance work at all.
What you need
No game code or data is in the repository. You supply a disc image of a game you own, a tool to decrypt its executable (the README names DecEboot and pspdecrypt, or a dump from PPSSPP's developer tools), and a Linux machine with CMake, Ninja, a C++20 compiler and Python. A port script turns the disc into a local page in about four minutes on an 8-core laptop, and needs around 2 GB per game. The page uses SharedArrayBuffer, so it has to be served with cross-origin isolation headers, which the included server sends.
The author asks that the generated C++ and WebAssembly stay on your own machine, since they are translations of the game and belong to its owners. They also set expectations for anything else: both working games share one engine, and another studio's game will most likely stop at a system call nobody has written yet, which the runtime logs by name. The code is MIT licensed, with the ATRAC3+ audio decoder borrowed from PPSSPP under its own LGPL licence.
Sources
- God of War on PSP, recompiled to WebAssembly and running in the browser (GitHub)
- Discussion: God of War on PSP, recompiled to WebAssembly and running in the browser (Hacker News)
- PSPRecomp: A static recompilation framework for PSP software (GitHub)
Image: Image: God of War: Chains of Olympus running in a browser, from the PSP Web Recomp README