SearchA-ZZ › ZX81

ZX81

2015 Open source · GPL-3.0 Online

The Sinclair ZX81 running in the browser. This build vendors JtyOne, Simon Holdsworth's JavaScript port of Mike Wynne's EightyOne, and drives its interpreted Z80 core from a pausable, instruction-steppable loop, so the shared debugger can single-step the CPU, read and write registers and memory, and set breakpoints. It boots straight to the ZX81 BASIC "K" cursor.

Visit the official site ↗

Runs on: Web browser

ZX81 Online Emulator

Play ZX81 using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
ZX81 BASICZX81Sinclair ZX81greyOpen ⛶

Machines emulated

Chips

Notes

Embedding

JtyOne is plain-global JavaScript with no bundler: three constructors (Z80, ZX81, ZX81Display) hang off the window. The stock ZX81EmulatorUI/JtyOne wrappers install a self-scheduling setTimeout loop that cannot be paused or single-stepped, so instead we wire the parts by hand and drive our own loop.

Boot. Build a keyboard, a display and the machine, then let the machine load its ROM (asynchronously) and call us back:

var kbd     = new ZX81Keyboard();
var display = new ZX81Display(statusSpan, canvas);
var machine = new ZX81('', 0, 0, kbd.zxKeyboard);   // no tape
machine.start(function(){ startOurLoop(); });       // fires once the 8K ROM has loaded + CPU reset

The machine is plain objects - there is no wasm heap. Everything the debugger needs is a live handle we exposed on the vendored core:

MemberKindWhat it does
machine.z80.doOpcode()methodExecute exactly one Z80 instruction and return its T-state cost. This is our single-step primitive.
machine.doScanLine(display)methodRun a scanline's worth of CPU + raster the ZX81's software-generated picture into the display buffer. Our free-run loop calls this until a frame's vertical sync completes, then blits.
machine.z80.get/set*methodLive register access. The stock core exposed PC SP DE I R; we added AF BC HL IX IY AF' IM IFF as one-line accessors over its register array.
machine.readByte(a) / writeByte(a,v)methodThe 64K bus. Reads are side-effect-free (safe for the auto-polling hex view); writes honour ROM protection below $2000.
display.blit()methodCopy the finished frame to the visible canvas (we exposed the core's private blit).

The ZX81 has no display hardware. The ROM builds the picture by racing the beam with the CPU, which is why the frame runner is doScanLine rather than a separate video chip.

Debugger integration

The plug-in (zx81-debug.js) reads the live machine from window.EMU_BOOT and calls EmuKit.defineMachine with a transport, the full Z80 register set and the memory bus, reusing the shared z80 disassembler (/debugger/src/cpus/z80.js).

Single-step is machine.z80.doOpcode() - one instruction, registers update live. Free run calls doScanLine until the frame's vertical-sync completes, then display.blit().

Breakpoints are a Set of PC values. To avoid slowing the hot path when the debugger is idle, the vendored doScanLine only consults a hook when one is installed:

if (window.__ZX81BP && window.__ZX81BP(p.getPC())) { this._brk = true; break }

window.__ZX81BP is null whenever there are no breakpoints or watchpoints, so the per-instruction cost is a single truthy test only while you are actually using them. Watchpoints wrap machine.writeByte and raise the same halt flag when a watched address is written.

Architecture

The ZX81 is a Z80 with 8K of ROM and (here) 16K of RAM, and almost no dedicated hardware:

  • Z80 - a readable interpreted core. doOpcode() fetches and executes one instruction (base page plus the CB/ED/DD/FD prefixes) and returns its T-states; interrupt() raises the 50Hz maskable interrupt and nmi() the display NMI.
  • ZX81 - the machine: the 64K bus ($0000 ROM, RAM from $4000), the port handlers (keyboard on even ports, NMI generator control), and doScanLine, which interleaves CPU execution with rastering the character picture the ROM paints by manipulating the R register and the video address.
  • ZX81Display - turns the emulated beam into ARGB pixels and blits them to the canvas.
  • ZX81Keyboard - an 8×5 key matrix; the stock core maps physical keys by character, so symbols land correctly.
  • roms/zx81.rom - the 8K Sinclair/Nine Tiles system ROM, loaded at boot into the bottom of the bus.