SpectrEm

A ZX Spectrum in a browser tab. Every model from the 48K to the +3, written in C++ and compiled to WebAssembly, with the ULA timed to the frame.

Program: spectrem

SpectrEm running Batman, with the memory map and Z80 debugger open beside the screen

This is the emulator I wanted for the Spectrum: accurate enough that border effects land on the right T-state, and with the debugger built in rather than bolted on. The emulation core is the same C++ as SpectREMCPP, my desktop emulator, compiled with Emscripten so it runs anywhere with a browser.

Nothing to install. Save states live in the browser, so it remembers where you were.

Four machines

1982 48K The original. Issue 2 and Issue 3 boards, 16K ROM, beeper sound, rubber keys.
1985 128K Bank switching on port 7FFD, two ROMs, the AY-3-8912 sound chip and the 128 BASIC editor.
1986 +2 Amstrad's first Spectrum, with the built-in tape deck and a proper keyboard.
1987 +2A / +3 Extra paging on port 1FFD, a 64K ROM, and the +3's 3-inch floppy drive with its uPD765 controller.

What it does

Runs at the right speed

The whole Z80 instruction set, all seven opcode tables, with the ULA stealing cycles for memory contention exactly where the real one did.

Draws the border

256 by 192 with a border that updates mid-frame at 50 Hz, so border effects and multicolour tricks work. Optional PAL decoding on the GPU for the colour bleed you remember.

Loads tapes and disks

TAP and TZX, either instantly or in real time with the loading noise. DSK images on the +3, including the copy-protected ones: Speedlock, weak sectors, odd sector sizes.

Makes the right noises

Beeper, AY on the 128K machines and optionally on the 48K, the SpecDrum sampler, and tape audio while loading.

Takes the peripherals

Kempston, Sinclair and cursor joysticks from a gamepad, the Opus Discovery disk interface, and Spectranet with a real network bridge over WebSocket.

Remembers

SNA and Z80 snapshots in and out, ten named save slots, and an autosave that survives closing the tab.

Looks like a television

A WebGL shader chain with curvature, scanlines, phosphor persistence and shadow mask. All of it can be turned off.

Works on a phone

An on-screen keyboard and joystick overlay that rearranges itself for portrait and landscape.

The debugger

The Z80 debugger panel: registers, flags, a disassembly with the current instruction highlighted, and breakpoints

Z80 debugger

Registers, flags and a coloured disassembly. Breakpoints on an address, on a condition, or on the beam position.

Memory heatmap

Reads and writes light up the memory map as they happen and fade at a speed you choose.

Sound monitor

Waveforms for the beeper and each AY channel, with frequencies and envelope shapes, and a mute per channel.

BASIC editor

A Sinclair BASIC tokeniser with syntax colouring, a variable inspector and line breakpoints.

UDG and font editors

Pixel grids for user-defined graphics and a full 96-character font designer, both with the BASIC to load them.

Retro debugger

The same tools drawn over the screen in the Spectrum's own ROM font, for debugging without leaving the machine.

Under the hood

One core, two homes

The C++ emulation core is shared with SpectREMCPP on the Mac. Here it is compiled with Emscripten to a 1.4 MB WebAssembly binary and runs in a Web Worker, so the page never stalls.

Contention, per model

The ULA's delays are modelled per machine: 69,888 T-states a frame on the 48K, 70,908 on the 128K.

A PAL signal, not a bitmap

The display is generated as a composite video buffer and decoded on the GPU, which is where the fringing and blending come from.

The Spectrum's own colours

The interface uses the eight attribute colours in light and dark, with the accents checked for contrast against the ink.

Program: spectrem