This repository contains a browser port of the Eternal Software Initiative (ESI) virtual machine.
It runs capsules produced by the main project and allows loading compressed capsules by URL.
The project includes:
- a port of the ESI C VM (
vm_asm.c), which is compiled to WebAssembly with Clang. - a Web Worker (
worker.js), which renders the framebuffer throughOffscreenCanvas, and sends console output to the page main.js, which- loads the worker and VM
- loads and decompresses "capsules"
- listens for Keyboard events, maps them and sends them to the VM
- renders the canvas and console
- a baic HTML page to host the whole thing
The main Eternal repository contains the ESI architecture specification, LLVM toolchain, Linux port, runtimes, reference VM, and tools for building self-contained software capsules.
This browser port does not include the toolchain or capsule build system.
Useful main-project links:
| Linux | Doom |
|---|---|
![]() |
![]() |
mem[(uint32_t)b] -= mem[(uint32_t)a];
if (mem[(uint32_t)b] <= 0) {
pc = (uint32_t)c;
}- Clang and wasm-ld with the
wasm32target - Python 3 or another static HTTP server
- A browser with WebAssembly and
OffscreenCanvas - Enough memory for the fixed 1.5 GiB guest address space
On Debian or Ubuntu, install the build and server dependencies with:
sudo apt update
sudo apt install clang lld-18 make python3Install Node.js as well to run the tests:
sudo apt install nodejsmake
make serveOpen http://localhost:8000, load one of the linked Linux, Mandelbrot, or Pong
capsules, enter a capsule URL, or select a local .bootimage or .bootimage.xz,
and press Start. Remote servers must permit cross-origin browser requests.
Loading a remote capsule updates the address bar with a shareable
?capsule=<URL> link; opening that link loads and starts the capsule. Click the
framebuffer before using the keyboard.
Capsules can be built or downloaded from the main Eternal repository.
Run the small interpreter smoke test with:
make testTo run the XZ/Linux integration test, clone the main project alongside this repository and run:
make test-xzUse make test-xz CAPSULE=/path/to/capsule.bootimage.xz if the capsule is
elsewhere.
XZ capsules are decompressed in the browser using the vendored
xz-decompress WebAssembly
decoder.
- The interpreter runs bounded batches so the worker can process keyboard and control messages between batches.
- Guest timer interrupts remain instruction-count based, matching
vm/vm.c. - The full guest address space is allocated eagerly for the simplest and fastest desktop implementation. Loading another capsule only clears the portion occupied by the previous capsule, avoiding writes that commit the entire 1.5 GiB address space on memory-constrained browsers.
- XZ decompression streams through the decoder, then collects the decompressed
capsule into an
ArrayBufferbefore transferring it to the VM worker. - ESI
0xRRGGBBframebuffer words are converted to Canvas RGBA pixels in the worker. - Browser keyboard
codevalues are translated to SDL-compatible scancodes inmain.js. The current table covers letters, digits, arrows, and common control keys.
The fixed contiguous guest array still limits support on devices whose browser cannot reserve a 1.5 GiB WebAssembly memory. Supporting those devices will require replacing it with sparse or paged memory.
This project is available under the MIT License. The vendored XZ
decoder contains components under their own permissive licenses; see
vendor/README.md and the license header in the vendored
bundle.

