SearchA-ZW › Williams Arcade

Williams Arcade

1982 Arcade Open source · GPL-3.0 Online

Williams Arcade is Williams Electronics' second-generation arcade board (1980–82): a Motorola 6809 driving a bitmap display, a hardware blitter and 6821 PIAs. This build runs the board in the browser, a pure-JavaScript machine model plus an MIT 6809 core, and boots Robotron: 2084 (Vid Kidz / Williams, 1982) straight into attract mode, with Joust as a sibling on the same hardware. It is wired to the emulators.org in-frame debugger so you can single-step the 6809, read and write the registers and the full 64K memory, set execution breakpoints and write watchpoints, and use the on-screen twin-stick pad.

Visit the official site ↗

Runs on: Web browser

Williams Arcade Online Emulator

Play Williams Arcade using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Robotron: 2084Williams ArcadeWilliamsgreyOpen ⛶
JoustWilliams ArcadeWilliamsgreyOpen ⛶

Machine emulated

The Williams arcade board (1980–82) - a Motorola 6809 at ~1 MHz with 48 KB of RAM, up to 48 KB of bank-switched ROM and 1 KB of battery-backed CMOS. Its 304×256, 16-colour bitmap lives directly in RAM, drawn by a custom hardware blitter, and the monitor is turned 90° in the cabinet. It ran Defender, Stargate, Robotron: 2084, Joust, Bubbles and Sinistar.

Chips

Notes

Embedding

The Williams "6809" board (Defender, Stargate, Robotron, Joust, Bubbles, Sinistar) is a single Motorola 6809 at ~1 MHz driving a 304×256, 16-colour bitmap held directly in main RAM, with a hardware blitter for fast sprite copies and a pair of 6821 PIAs for the controls. This build vendors the pure-JavaScript machine model from 8bitworkshop (GPL-3.0) together with Martin Maly's MIT CPU6809 core, and drives them from a loop the host owns so the debugger can control the machine.

Boot. The 0xC000-byte program image is loaded (Robotron by default), the CPU is pointed at the memory bus and reset through the $FFFE vector, and it runs its self-test straight into attract mode:

var m = new WilliamsMachine({ isDefender: false });
m.loadROM(WILLIAMS_ROMS['robotron']);   // 12 x 4K program ROMs, concatenated
m.cpu.init(write, m.membus.read, 0);       // bind bus + reset (reads $FFFE)
m.banksel = 1;                            // ROM banked in at $0000-$8FFF
(function loop(){ m.advanceFrame(); requestAnimationFrame(loop); })();

The machine is plain objects. Everything the debugger needs is a method or field on the machine or its CPU:

MemberKindWhat it does
m.advanceFrame(trap)methodRun one 304-line video field, firing the quarter-screen IRQs the game times on. trap() is polled before every instruction so the host can stop on a breakpoint or watchpoint.
m.cpu.advanceInsn()methodExecute exactly one 6809 instruction and return its cycle count, the single-step primitive.
m.cpu.saveState() / m.cpu.set(reg,v)methodRead the whole register file (PC A B X Y U SP DP CC) and write any register back, how the debugger shows and edits registers.
m.read(a) / m.write(a,v) / m.readConst(a)methodLive bus access and a side-effect-free read (the $C000-$CBFF I/O window is skipped) for the memory views.
m.ram / m.rom / m.nvram / m.palettefieldThe 48K work+video RAM, the 48K program ROM, the 1K CMOS and the 16-entry palette, as plain arrays.
m.pia6821 / m.setSwitch(i,mask,down)fieldThe eight input latches and a helper to set/clear a control bit, how coins, start and the twin sticks reach the game.

Video. Writes to $0000-$97FF land two 4-bit pixels each into a 256×304 buffer; the display is the Williams monitor rotated 90°, so the host un-rotates the buffer onto the canvas each field. Palette writes to $C000-$C00F repaint live.

Debugger integration

The debugger drives a host-owned run loop: because the 6809 interpreter runs one instruction at a time in JavaScript, the loop can pause, single-step and check breakpoints between any two instructions; no changes to the CPU core are needed beyond one added register setter.

window.EMU_BOOT.transport exposes the controls the shared debugger calls:

  • pause / resume / isPaused - stop or restart the requestAnimationFrame loop.
  • stepInsn(n) - call cpu.advanceInsn() exactly n times and redraw, so a single step advances the PC by one instruction.
  • step(n) - advance n whole 60 Hz video fields (with their four quarter-screen IRQs).
  • breakpoints - a Set of PC values. When non-empty the frame loop runs instruction-by-instruction and pauses before executing an address in the set; when empty it runs a full field at speed, so an idle debugger costs nothing.
  • watchpoints - the CPU's memory-write path is wrapped (the core is re-init'd with a write shim), so a store to a watched address pauses the loop. This is the one place the core is extended.

The plug-in (williams-debug.js) reads these hooks and calls EmuKit.defineMachine with the full 6809 register set (read from saveState(), written through cpu.set(), with the E F H I N Z V C flags decoded from CC), memory chips for the 64K CPU bus / RAM / ROM / CMOS using the shared m6809 disassembler, and a custom twin-stick control view. Memory reads for the views use readConst, which skips the I/O window so auto-polling never ticks the video counter or a PIA.

Architecture

Williams' second-generation arcade board is one Motorola 6809 with 48 KB of RAM, up to 48 KB of ROM (bank-switched over the low RAM), 1 KB of battery-backed CMOS and two signature custom parts, all modelled here as plain JavaScript on WilliamsMachine:

  • CPU - the 6809, with the whole 64 KB memory map built from range decoders. $0000-$8FFF is RAM or banked ROM (a write to $9000 flips the bank); $9800-$BFFF is work RAM; $C000-$CFFF is the I/O page; $D000-$FFFF is fixed ROM.
  • Blitter - the "special chip" DMA copier: eight registers at $CA00 describe a source, destination, width, height and a flags byte (transparency, solid fill, shifted pixels, X/Y mirroring); one write to $CA00 runs the copy that draws every sprite.
  • Video - no framebuffer chip: the CRT simply scans $0000-$97FF, one byte per two horizontal-nibble pixels, through a 16-entry RRRGGGBB palette at $C000. A quarter-screen interrupt fires four times a field for split-screen timing.
  • I/O - two 6821 PIAs carry the coin door, start buttons and the joysticks; on the real board a second 6808 + DAC plays sound (dropped in this silent build).
  • CMOS - 1 KB of non-volatile RAM at $CC00 holds bookkeeping and high scores; a watchdog resets the board if the game stops kicking it.

Robotron: 2084 (Vid Kidz / Williams, 1982) uses this board with two 8-way joysticks - one to run, one to fire - and it is the default boot here; Joust (1982) is the same hardware and ships as a sibling config.