Search › A-Z › Z › Robotron Z1013
Robotron Z1013
The Robotron Z1013 is about the simplest 8-bit computer that ever shipped as a product: a bare single circuit board, sold as a kit in East Germany from 1985, built around the U880, an unlicensed Zilog Z80 clone. There is no video chip and no sound; a fixed 32×32 character frame buffer is scanned straight to the screen, and a single Z80 PIO reads an 8×8 keyboard matrix. This emulator is floooh's header-only chips Z1013 core compiled to WebAssembly, self-hosting the monitor and font ROMs, so it boots straight to the resident machine-code monitor with no downloads.
Because the whole machine lives in one WebAssembly memory with small state-sampling hooks, its Z80 registers and 64 KB of memory can be inspected, single-stepped, breakpointed and watched live in the shared debugger. Extra configurations quick-load classic tape programs such as Z1013-FORTH, KC-BASIC and a handful of games.
Runs on: Web browser
Robotron Z1013 Online Emulator
Play Robotron Z1013 using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Z1013.64 Monitor A.2 | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Z1013.01 Monitor 2.02 | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Z1013-FORTH | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| KC-BASIC | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Mazog (game) | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Boulder Dash (game) | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Galactica (game) | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ | |
| Demolation (game) | Robotron Z1013 | Robotron Z1013 | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
The Z1013 core is floooh's header-only chips emulator compiled to WebAssembly with Emscripten. One .wasm holds the Z80 (U880) CPU, the Z80 PIO, the keyboard matrix, the character-video decoder and all RAM/ROM; a tiny .js loader (an Emscripten MODULARIZE factory) instantiates it. We self-host both files plus the monitor and font ROMs, which are baked into the WASM at build time — there is no CDN and no external asset.
Boot. Instantiate the module, call our z1013dbg_init(type) (which runs z1013_init with the monitor + font ROMs), then own a requestAnimationFrame loop that advances the machine one 20 ms frame at a time and blits the decoded framebuffer to a canvas:
createZ1013({ locateFile: function (p) { return SRC + p; } }).then(function (M) {
M._z1013dbg_init(0); // z1013_init, type 0 = Z1013.64
var imgData = ctx.createImageData(256, 256);
(function frame() {
if (M._z1013dbg_exec(20000)) running = false; // run 20ms; stop if a breakpoint hit
paint(); // render() -> read HEAPU8 -> putImageData
if (running) requestAnimationFrame(frame);
})();
});
The screen is a 32×32 character framebuffer. The Z1013 has no programmable video: 1 KB of RAM at 0xEC00 holds ASCII codes, and an 8×8 font ROM turns each into a glyph. The core decodes the whole 256×256 monochrome image once per frame; our z1013dbg_render() hook expands it through the 2-colour palette into an RGBA buffer that JS copies straight out of the WASM heap into an ImageData.
Quick-loading tape programs. The .z80 tape images (FORTH, KC-BASIC, games) are injected with z1013dbg_quickload(ptr,len), which copies the payload into guest RAM and jumps the Z80 to the file's execution address:
var buf = new Uint8Array(arrayBuffer);
var p = M._malloc(buf.length);
M.HEAPU8.set(buf, p);
M._z1013dbg_quickload(p, buf.length);
M._free(p);
| Member | Kind | What it does |
|---|---|---|
M._z1013dbg_exec(us) | export | Run the machine for us microseconds. Returns 1 if a breakpoint/watchpoint was hit. The play loop's advance. |
M._z1013dbg_step_insn() | export | Advance exactly one Z80 instruction (ticks the core until the opcode boundary). The single-step primitive. |
M._z1013dbg_reg(i) / _z1013dbg_set_reg(i,v) | export | Sample / poke one Z80 register by index (PC SP AF BC DE HL IX IY IR, the shadow bank, IFF). |
M._z1013dbg_read(a) / _z1013dbg_write(a,v) | export | Side-effect-free read / write of the CPU-mapped 64 KB address space (RAM + monitor ROM). |
M._z1013dbg_key_down(k) / _z1013dbg_key_up(k) | export | Feed an ASCII key code into the Z1013's own 8×8 keyboard matrix. |
M._z1013dbg_quickload(p,n) | export | Inject a "KC .z80" tape image at HEAPU8[p..p+n] and jump to its exec address. |
The boot script wraps these exports in small helpers on window.EMU_BOOT (reg, setReg, rd, wr, pc, pressKey) plus a transport, so the debugger plug-in never has to know the machine is WASM.
Debugger integration
This is the point of the build: a compiled WASM core with the same live debugger as the JavaScript emulators. A stock chips WASM keeps its CPU state inside the module where JS cannot see it. Rather than add a callback to the per-cycle loop (which would tax the emulator even with the debugger closed), we rebuilt the core with a few sampling functions that copy state out only when called — the debugger calls them about ten times a second and once per Step.
What was changed in the source. One new translation unit, z1013_wasm.c, includes systems/z1013.h with CHIPS_IMPL (so the static core is in the same unit) and adds these EMSCRIPTEN_KEEPALIVE hooks — nothing in z1013.h itself was edited:
// registers: read the z80_t struct fields on demand
z1013dbg_reg(i) // PC/SP/AF/BC/DE/HL/IX/IY/IR, shadow AF'..HL', IFF1/2
z1013dbg_set_reg(i, v)
z1013dbg_pc()
// memory: side-effect-free, via the core's own mem_rd/mem_wr
z1013dbg_read(addr)
z1013dbg_write(addr, val)
// control
z1013dbg_step_insn() // tick the static _z1013_tick() until z80_opdone()
z1013dbg_exec(us) // run us; checks bps/wps only when some are armed
z1013dbg_bp_set(addr, on)
z1013dbg_wp_set(addr, on)
- Registers are read straight off the
z80_tstruct (cpu.pc,cpu.af,cpu.bc…cpu.af2,cpu.iff1) each refresh, and written back throughset_reg. The Z80 flag byte is unpacked to S Z H P/V N C. - Disassembly uses the shared
z80decoder — the U880 is a Z80 clone, so every opcode (including the DD/FD/ED/CB prefixes) renders correctly. - Memory is the full CPU-visible 64 KB read through the core's own
mem_rd, so the RAM, the character framebuffer at0xEC00and the monitor ROM at0xF000all appear exactly as the CPU sees them, with no I/O side effects. - Single step is real:
z1013dbg_step_insnticks the core's static_z1013_tickuntilz80_opdone()— one true Z80 instruction, not a burst. - Breakpoints are a 64 KB PC-flag table checked at each instruction boundary inside
z1013dbg_exec, and only when at least one is armed — so a running machine with no breakpoints pays nothing. - Write watchpoints use the same zero-cost trick:
z1013dbg_execonly drops into instruction-by-instruction mode when a breakpoint or watchpoint is armed, and after each instruction it compares the watched bytes against a snapshot — a change means that instruction wrote the address, so it pauses. No memory-write hook sits on the hot path.
Play / pause are pure JavaScript: we own the frame loop, so pause just stops calling z1013dbg_exec and resume restarts it — the transport's isPaused() drives both the debugger's Run window and the shell's Play button.
Architecture
The Robotron Z1013 (VEB Robotron, Riesa/Dresden, 1985) is about the simplest 8-bit computer that shipped as a product: a bare single circuit board sold as a kit, with a U880 (an unlicensed East-German Zilog Z80 clone) at 1 or 2 MHz, 16 or 64 KB of RAM, a 2 KB monitor ROM at 0xF000, and a 2 KB font ROM. There is no video chip — a fixed 32×32 character frame buffer sits at 0xEC00 and is scanned into a monochrome picture. A single Z80 PIO drives an 8×8 (or, on the original .01, 8×4) keyboard matrix; there are no interrupts and no built-in sound. It boots straight to a resident machine-code monitor.
z1013.wasm— the whole machine (U880 CPU core, Z80 PIO, keyboard matrix, character-video decoder, flat memory) compiled from floooh'schipsC to WebAssembly, with the debug sampling hooks linked in.z1013.js— the Emscripten loader/factory that instantiates the WASM and exposes the exported functions and heap views.- The ROMs — the monitor A.2 (Z1013.64,
mon_a2), the original monitor 2.02 (Z1013.01,mon202) and the character font — are the machine's original East-German system software, freely redistributed among preservationists (grey); self-hosted, takedowns honoured. - The extra configs quick-load
.z80tape images (Z1013-FORTH, KC-BASIC and games such as Mazog, Boulder Dash, Galactica, Demolation), all grey preservation dumps injected straight into RAM.
How to rebuild. Clone github.com/floooh/chips (MIT) for chips/*.h + systems/z1013.h, and github.com/floooh/chips-test for examples/roms/z1013-roms.h (the ROM dumps) and the .z80 tape images under webpage/z1013/. Put z1013_wasm.c (the wrapper with the hooks above) beside them and, with Homebrew Emscripten on PATH, build:
emcc z1013_wasm.c -I chips -O2 \
-sMODULARIZE=1 -sEXPORT_NAME=createZ1013 -sENVIRONMENT=web \
-sALLOW_MEMORY_GROWTH=1 \
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap,getValue,setValue,HEAPU8,HEAPU32 \
-sEXPORTED_FUNCTIONS=_z1013dbg_init,_z1013dbg_reset,_z1013dbg_exec,\
_z1013dbg_step_insn,_z1013dbg_pc,_z1013dbg_reg,_z1013dbg_set_reg,\
_z1013dbg_read,_z1013dbg_write,_z1013dbg_bp_set,_z1013dbg_bp_clear,\
_z1013dbg_wp_set,_z1013dbg_wp_clear,_z1013dbg_key_down,_z1013dbg_key_up,\
_z1013dbg_quickload,_z1013dbg_disp_w,_z1013dbg_disp_h,_z1013dbg_fb_ptr,\
_z1013dbg_render,_malloc,_free \
-o z1013.js
z1013dbg_init(type) takes 0 for the Z1013.64 (2 MHz, 64 KB, monitor A.2), 1 for the Z1013.16, or 2 for the original Z1013.01 (1 MHz, monitor 2.02). The two output files (z1013.js, z1013.wasm) are the only build artefacts vendored here.