SearchA-ZX › Xerox Alto

Xerox Alto

1973 Open source · AGPL-3.0 Online

The Xerox Alto, built at Xerox PARC in 1973, is the machine that invented the modern personal computer: the first to combine a bitmap display, a mouse and a windowed graphical desktop, and the machine on which Bravo (WYSIWYG editing) and Smalltalk were written. It has no conventional CPU. The Alto is microcoded, and its microcode runs an emulator for a Data General Nova-like instruction set that ordinary Alto programs are written in.

This page runs ContrAltoJS, a pure-JavaScript Xerox Alto by Seth Morabito and Vanessa Freudenberg, ported from Living Computers: Museum + Labs' ContrAlto. It boots a Diablo-31 disk pack to the Alto Executive on the tall 606 × 808 portrait display, with the mouse driven by your pointer. Open the debugger to single-step one emulated Nova instruction, inspect the AC0-AC3 / PC registers and the live cursor state, disassemble core memory in octal, and set breakpoints and watchpoints.

ContrAltoJS on GitHub ↗

Visit the official site ↗

Runs on: Web browser

Xerox Alto Online Emulator

Play Xerox Alto using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Xerox Alto (games disk)Xerox AltoXerox AltogreyOpen ⛶

Machines emulated

Chips

Notes

Embedding

ContrAltoJS is a set of plain-global JavaScript modules (no bundler). Vendor js/** and load them in dependency order, then drive the machine yourself instead of calling the repo's main.js loop, which cannot be paused or single-stepped, exactly what the debugger needs.

Boot. The Alto boots from its disk. Build the system (its constructor resets the machine), fetch a Diablo-31 pack into drive 0, then reset() so the boot microcode reads the pack, and run your own loop. The Alto is microcoded, so one system.step() is one microinstruction; a burst of ~98000 per animation frame is roughly real time:

var system = new altoSystem();                 // constructor resets the machine
var pack = new DiabloPack(DiabloDiskType.DIABLO_31);
pack.load(diskUrl, false, function () {         // async XHR of the .dsk
  diskController.drives[0].loadPack(pack);
  system.reset();                              // boot microcode now sees the disk
  (function frame(){
    for (var i=0; i<98000; i++) system.step();  // one microinstruction each
    altoDisplay.render();
    requestAnimationFrame(frame);
  })();
});

The machine is plain objects. Everything the debugger needs is a live global, no wasm heap:

MemberKindWhat it does
system.step()methodRun exactly one microinstruction (clocks the memory bus, CPU and scheduler).
cpu.rfieldThe R register file. The emulator task keeps the Nova accumulators there: AC0=r[3] AC1=r[2] AC2=r[1] AC3=r[0], and the emulated program counter in r[6].
cpu.currentTask.mpcfieldThe microcode PC. The emulator task sits at mpc = 0o20 at each instruction fetch, the boundary we step one Nova instruction to.
memory.read(a, task, xm)methodSide-effect-free read of one 16-bit word of the 64K core store, what the debugger's memory views call.
memory.load(a, v, task, xm)methodWrite one word. The bus store path calls this, so wrapping it gives host-side watchpoints.
altoDisplay.render()methodBlit the 606x808 1-bit framebuffer into the <canvas id="altoDisplay">.
keyboard.keys / mousefieldThe Alto key matrix (4 words) and the mouse (poll-driven delta); driven from browser key and pointer events.

Because the CPU, core store and I/O are ordinary JavaScript, the debugger single-steps by clocking to the next fetch, reads and writes registers straight off cpu.r, and implements breakpoints and watchpoints as host-side checks, with no changes to the emulator core.

Debugger integration

The boot shim publishes window.EMU_BOOT with a full transport: pause / resume / isPaused, stepInsn(n) (one emulated Nova instruction), step(n) (a microinstruction burst), reset, plus breakpoints (program-counter values checked at each instruction fetch) and watchpoints (core addresses, checked inside the write path).

Stepping a microcoded machine. The Alto has no fixed hardware ISA, so "one instruction" means one instruction of the Nova-like target its microcode emulates. stepInsn clocks system.step() until the emulator task returns to its fetch microaddress (mpc = 0o20), which advances PC = cpu.r[6] by one emulated instruction. Breakpoints compare cpu.r[6] against the set at every fetch boundary; watchpoints wrap memory.load.

Decoder. A dedicated /debugger/src/cpus/alto.js disassembles the emulated instruction set into native octal: the memory-reference ops (JMP JSR ISZ DSZ) and LDA / STA with page-zero / PC-relative / AC2 / AC3 addressing, the Nova arithmetic-logic class (COM NEG MOV INC ADC SUB ADD AND with L/R/S shift, carry and skip modifiers), and the Alto-specific ops (CYCLE JSRII JSRIS CONVERT and the I/O group MUL DIV RCLK SIO BLT BITBLT). Unknown words fall back to .word 0oNNNNNN.

Memory. The 64K-word core store is exposed as a 128 KB chip: each 16-bit Alto word is two bytes little-endian (byte 2n low, 2n+1 high), so the decoder reads read(a) | read(a+1)<<8 and every instruction is length two. pc() is byte-scaled so the disassembly gutter, the PC highlight and breakpoints line up on word boundaries. The Alto registers AC0-AC3, PC, L, T, M, IR and the microcode PC are joined by the live display state, cursor X / cursor register and the mouse X / Y, shown as extra registers.

Architecture

The Xerox Alto (1973, Xerox PARC) is the machine that introduced the bitmap display, the mouse and the desktop GUI. It has no conventional CPU: a 16-bit microcoded engine runs up to 16 cooperating microcode tasks in priority order, and the highest-level task - the emulator task - interprets a Data General Nova-like instruction set that ordinary Alto programs are written in.

  • cpu - the microengine: the R and S register files, the L / T / M / IR registers, the ALU and the task scheduler. clock() executes one microinstruction of the current task.
  • tasks/* - the microcode tasks: the emulator (Nova interpreter), the disk-sector and disk-word tasks, and the display word / horizontal / vertical / cursor tasks that stream the bitmap.
  • memory + memory_bus - the 64K-word core store, extended-memory banks and the memory-mapped I/O page (keyboard, mouse, disk).
  • io/diablo_* + disk_controller - the Diablo 31 removable disk pack and its controller; the OS boots from sector 0 of drive 0.
  • io/alto_display + display_controller - the portrait 606x808 1-bit display, rastered word-by-word into a canvas, plus the hardware cursor.
  • rom.js - the control ROM, constant ROM and microcode, embedded as arrays; the system is self-contained apart from the disk pack.

ContrAltoJS is a faithful, readable emulation whose entire state is live JavaScript, which is what makes the microcoded Alto, normally opaque, a debuggable machine.