← Back to demos

VGA Mode 13h

WebAssembly demoscene

What is this?

A collection of real-time graphics demos running entirely in WebAssembly. Each demo is a single .wat file (WebAssembly Text format) generated by Claude Code, compiled in your browser via wabt.js, and rendered to a 320x200 framebuffer with a 256-color palette.

No JavaScript touches the rendering. The WASM code writes palette indices directly into shared memory. The harness reads that memory and blits it to a canvas 60 times per second.

VGA Mode 13h

Mode 13h was the standard 320x200 256-color VGA graphics mode used by DOS games in the late 80s and 90s. It gave developers direct access to a linear 64KB framebuffer at segment A000:0000. Nearly every classic DOS game used it: DOOM, Commander Keen, Duke Nukem, and countless demoscene productions.

This project recreates that constraint in the browser. Same resolution, same palette-indexed rendering, same byte-per-pixel framebuffer. Just WebAssembly instead of x86 assembly.

How it works

The harness provides 256KB of shared WebAssembly memory with a fixed layout:

0x0000Control block: frame counter, mouse position, buttons, tick, keyboard state
0x0040Palette: 256 entries x 3 bytes (RGB)
0x0340Framebuffer: 64000 bytes (320 x 200, 1 byte per pixel)
0x10340+Free for the demo to use however it wants

Each demo exports init() and frame(). The harness calls frame() on every requestAnimationFrame, reads the framebuffer, maps each byte through the palette, and draws the result to an HTML canvas.

The demos

Controls

Interactive demos (like shooter) respond to mouse and keyboard input. The harness writes input state into the control block so demos can read it from shared memory.

MouseMove cursor over the canvas to aim. Click to fire.
KeyboardW A S D / Arrow keys to move. Space for action. Shift, Enter, Esc for secondary controls.
TouchTap and drag on the canvas to aim and fire. On touch devices, a virtual D-pad and action buttons appear below the screen.

Tech stack

Language: WAT (WebAssembly Text format)
Compiler: wabt.js (in-browser)
Renderer: HTML Canvas via ImageData
Generator: Claude Code (Opus)
Hosting: Berrry