SearchA-ZA › Agon Light

Agon Light

2022 Open source · GPL-3.0 System ROMs · grey Online

The Agon Light (2022) is a modern, fully open-source 8-bit computer designed by Bernardo Kastrup and built by Olimex. It pairs a Zilog eZ80 — a pipelined Z80 superset that runs at 18.432 MHz and addresses 24 bits of flat memory (ADL mode) — with an ESP32 "VDP" video coprocessor, and holds MOS and BBC BASIC in ROM so it boots to a friendly > prompt. This build runs in the browser: the eZ80 half is the genuine ez80 core from fab-agon-emulator, running the real Agon Platform MOS 2.3.3 and BBC BASIC, compiled single-threaded to WebAssembly; the VDP half is re-implemented in JavaScript as a text terminal, so the page needs no special server headers. Because the eZ80, MOS and BASIC are the real firmware, the whole machine can be single-stepped, breakpointed and inspected live through a new eZ80 disassembler.

Visit the fab-agon-emulator project on GitHub ↗

Visit the official site ↗

Runs on: Web browser

Agon Light Online Emulator

Play Agon Light using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
BBC BASICAgon LightAgon LightgreyOpen ⛶
MOS command promptAgon LightAgon LightgreyOpen ⛶
Hello demoAgon LightAgon LightopenOpen ⛶
Primes demoAgon LightAgon LightopenOpen ⛶
Squares demoAgon LightAgon LightopenOpen ⛶

Chips

Notes

Embedding

The Agon is two processors: a Zilog eZ80 running MOS and BBC BASIC, and an ESP32 VDP (a FabGL terminal) they talk to over a serial UART. This build keeps the eZ80 real and emulates the VDP in JavaScript.

The eZ80 is the genuine core. cpu.wasm is Tom Morton's ez80 Rust core (from fab-agon-emulator) with its MOS + host-filesystem layer, compiled single-threaded with Emscripten. It exposes a tiny C ABI; you install the firmware and SD card into its in-memory filesystem, then drive it a slice at a time:

const cpu = await createCPU({ locateFile: f => base + f });
cpu.FS.writeFile('/mos.bin', mosFirmware);       // MOS 2.3.3 (console8)
cpu.FS.writeFile('/sdcard/bin/bbcbasic24.bin', basic);
cpu._agon_cpu_init(512);                       // 512 KiB external RAM
(function loop(){
  cpu._agon_cpu_vsync();                        // ~60Hz vsync interrupt (HALT wakeup)
  cpu._agon_cpu_run_ms(16);                     // ~one frame of eZ80 time
  requestAnimationFrame(loop);
})();

The VDP is JavaScript. The real VDP is a threaded FabGL program that would force SharedArrayBuffer and cross-origin-isolation headers on the whole page. Instead agon-vdp.js models the CPU→VDP byte stream as an 80×30 character terminal drawn to a <canvas>, and answers the few VDP serial-protocol packets MOS waits for at boot (general poll, video-mode info, RTC). The UART is a handful of lines wiring the CPU's host_uart0_send/recv to the terminal:

window.__agon_uart = {
  send: b => vdp.send(b),      // eZ80 -> VDP: VDU bytes to the terminal
  recv: () => vdp.recv(),      // VDP -> eZ80: handshake + keyboard packets
  cts:  () => 1
};
vdp.key('A'.charCodeAt(0), 1);          // a keyboard packet [0x81,4,ascii,0,0,down]

Because MOS and BBC BASIC are the real eZ80 binaries, everything you see is authentic — the debugger single-steps genuine eZ80 code.

Debugger integration

The eZ80 is a Z80 superset, so it needed a new disassembler and a new set of core hooks.

A new eZ80 decoder (/debugger/src/cpus/ez80.js, registered as ez80). It delegates the base opcode space to the shared z80 decoder through a rebased 24-bit byte reader, and adds what is eZ80-specific: the size-suffix prefixes .SIS/.LIS/.SIL/.LIL (the redundant self-loads LD B,B/C,C/D,D/E,E, always consumed as prefixes on the eZ80), and the extra ED-page instructions MLT, LEA, PEA, TST, IN0/OUT0, LD rr,(HL) and LD MB,A. Unknown opcodes decode as .byte.

Core hooks added for the debugger. The stock core only ran; it did not expose its state. The Rust core was extended with an EMSCRIPTEN_KEEPALIVE-style C ABI so the shared framework can reach in without changing how the machine executes:

  • Registers_agon_dbg_reg(i) / _agon_dbg_setreg(i,v) read and write AF, the 24-bit ADL registers BC/DE/HL/IX/IY/SP, PC, MB and the flag byte.
  • Memory_agon_dbg_peek(a) reads a byte side-effect-free (the out-of-bounds marker is cleared so it never trips the machine); _agon_dbg_poke writes.
  • Single step_agon_dbg_step() executes exactly one eZ80 instruction and returns the new PC.
  • Breakpoints & watchpoints — held in the core; run_cycles() stops the CPU before executing a breakpoint address, and the memory-write path flags a watched address. The loop polls _agon_dbg_stop_reason() after each slice (1 = breakpoint, 2 = watchpoint) and pauses.

Because breakpoints and watchpoints live inside run_cycles, they fire at full speed with interrupts still serviced — no slow instruction-by-instruction host loop.

Architecture

The Agon Light (Bernardo Kastrup, 2022; built by Olimex) is a from-scratch open-source 8-bit computer that pairs a modern CPU with a modern video chip yet feels like a 1980s micro:

  • eZ80F92 — Zilog's eZ80 at 18.432 MHz: a pipelined Z80 superset with 24-bit flat addressing (ADL mode), so it can see the full 512 KiB of external RAM without banking, plus new instructions like MLT (8×8 multiply), LEA/PEA and the mixed Z80/ADL size suffixes. It runs the MOS firmware and BBC BASIC.
  • VDP — an ESP32 running the FabGL library as a serial terminal: it owns the VGA output, keyboard, sound and sprites, and the eZ80 drives it with BBC-style VDU codes over a UART. Here it is re-implemented as a text terminal in JavaScript.
  • MOS — the Machine Operating System: a small CP/M-like monitor (here the Agon Platform "console8" MOS 2.3.3) that boots, runs autoexec.txt, and offers a file system on the SD card plus an API the eZ80 reaches through RST calls.
  • BBC BASIC — R.T. Russell's BBC BASIC, ported to the Agon by Dean Belfield; the default here is the 24-bit ADL build (bbcbasic24). It is the whole reason the machine boots to a friendly > prompt.

The Agon is fully open — hardware, MOS and VDP firmware are all public — which is what makes it fair game to self-host in the browser.