SearchA-ZA › Asteroids

Asteroids

1979 Arcade Open source · Public domain Online

Asteroids (Atari, 1979), designed by Lyle Rains and Ed Logg, is the vector-graphics arcade classic in which you pilot a triangular ship in open space, rotating, thrusting and firing to break drifting asteroids into ever-smaller fragments while dodging flying saucers. This build runs the original Atari board in the browser: a MOS 6502 driving the Atari Digital Vector Generator, with the original ROMs. It boots straight into attract mode, the rotating asteroids drifting across the vector screen, and is wired to the emulators.org in-frame debugger so you can single-step the 6502, read and write the registers and the full 64K memory, watch the vector RAM display list build word by word, and set execution breakpoints and write watchpoints.

Visit the official site ↗

Runs on: Web browser

Asteroids Online Emulator

Play Asteroids using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
AsteroidsAsteroidsAsteroidsgreyOpen ⛶

Machine emulated

The Asteroids arcade board (Atari, 1979) is a single MOS 6502 at 1.512 MHz driving the Atari Digital Vector Generator (DVG): there is no framebuffer, so the CPU builds a list of lines in the 2 KB it shares with the DVG and the DVG steers the beam to draw them on an X-Y monitor. It is one of the defining games of the golden age of arcade video games.

Chips

Notes

Embedding

Asteroids is a MOS 6502 at 1.512 MHz driving the Atari Digital Vector Generator (DVG) -- there is no framebuffer; the DVG reads a display list of lines from the memory it shares with the CPU and steers the beam to draw them. This build vendors a self-hosted machine (no CDN): a JavaScript port of Mike Chambers' public-domain Fake6502 core, our DVG interpreter, and the original Atari ROMs, driven from a host-owned loop so the debugger can control it.

Boot. The three 2 KB program ROMs load at $6800–$7FFF (mirrored high so the reset/NMI vectors resolve) and the 2 KB vector ROM at $5000; the 6502 starts from $FFFC and drops straight into attract mode:

var m = new AsteroidsMachine();   // loads ROMs, builds 6502 + DVG
m.reset();                        // pulls the reset vector at $FFFC
// one display field: 4 NMIs (~246 Hz) of 6144 cycles, then draw the DVG list
for (var s = 0; s < 4; s++) { m.cpu.nmi(); runCycles(6144); }
m.renderTo(ctx, W, H);

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

MemberKindWhat it does
m.cpu.step()methodFetch, decode and run one 6502 instruction; returns its cycle count. The single-step primitive.
m.cpu.nmi()methodPulse the non-maskable interrupt -- the ~246 Hz tick that drives the whole game.
m.dvgGo()methodRun the DVG over vector RAM/ROM and collect the frame's line segments. Triggered when the CPU strobes $3000.
m.dbgRead(a) / m.memWrite(a,v)methodSide-effect-free read and the CPU write path -- what the debugger's memory views read and poke.
m.setInput(id,down)methodDrive a control (left/right/thrust/fire/hyper/coin/start1) into the IN0/IN1 latches.
m.cpu.a/x/y/sp/pc/flagsfieldThe live 6502 registers, read and written directly.

Video. Each field the loop runs one display's worth of 6502 (four NMI slices), then walks the DVG display list the game left in vector RAM and strokes the lines to a 760×570 canvas.

Debugger integration

The debugger drives a host-owned run loop: because the 6502 interpreter runs one instruction at a time, the loop can pause, single-step and check breakpoints between any two instructions -- no changes to the CPU core are needed. window.EMU_BOOT.transport exposes the controls the shared debugger calls:

  • pause / resume / isPaused -- stop or restart the requestAnimationFrame loop.
  • stepInsn(n) -- call cpu.step() exactly n times and redraw, so a single step advances the PC by one instruction.
  • step(n) -- advance n whole display fields (each with its four NMIs).
  • breakpoints -- a Set of PC values. When non-empty the loop runs instruction-by-instruction and pauses before executing a watched address; when empty it runs a field at speed, so an idle debugger costs nothing.
  • watchpoints -- the machine's memWrite is the single write path; it flags a hit when a watched address is written and the loop pauses on it. Because the 6502's registers and the whole 64 KB map are ordinary JavaScript, registers are read and written directly and memory is exposed side-effect-free.

The plug-in (asteroids-debug.js) reads these hooks and calls EmuKit.defineMachine with the 6502 register set bound to the shared mos6502 disassembler, four memory chips (the 64 KB bus, the program ROM, the vector RAM display list and the vector ROM shape library), and the on-screen control panel. A neat trick for a vector machine: point the Vector RAM hex window at $4000 and single-step -- you can watch the game build the frame's line list word by word before it strobes the DVG.

Architecture

Asteroids has no video RAM in the usual sense. A single MOS 6502 builds a list of vectors in the 2 KB it shares with the DVG, then strobes it; the DVG is a tiny stack machine that reads that list and draws lines on an X-Y monitor. Modelled here as plain JavaScript objects:

  • CPU -- a port of Fake6502 (NMOS 6502 with BCD, which the score uses), reaching memory only through the machine's memRead/memWrite, so the bus and I/O live in one place.
  • DVG -- the Digital Vector Generator: it walks the display list as opcodes -- VCTR long vector, SVEC short vector, LABS set position + global scale, JSRL/RTSL call and return into the shape ROM, HALT -- accumulating (dx,dy,brightness) line segments. Scale is a power-of-two divisor so the same asteroid ROM shape draws large or small.
  • Bus / I/O -- 1 KB RAM, the input ports (IN0: fire, hyperspace, coin clock, VG-halt; IN1: coins, start, thrust, rotate) and the DIP switches, plus the DVG "GO", watchdog and sound strobes (sound is stubbed).
  • ROMs -- 6 KB of 6502 program (three mask ROMs) and 2 KB of vector ROM holding the asteroid outlines, letters, digits, ships and saucers the display list calls into.

The one piece of timing the game truly needs is its ~246 Hz NMI (the 12.096 MHz master clock divided down); the host loop reproduces exactly that, four NMIs per ~61.5 Hz display field, and renders the DVG list at the end of each field.