SearchA-ZS › Star Wars

Star Wars

1983 Arcade Colour vector Online

Star Wars (Atari, 1983) is the landmark colour-vector arcade game: a first-person X-Wing cockpit rendered as glowing coloured wireframe — the Death Star trench, TIE fighters and laser towers — flown through a distinctive two-handed yoke. This build runs the original Atari 6809 board in the browser -- the real program, vector and math-box ROMs on a Motorola 6809 with faithful ports of the Atari colour Analog Vector Generator and the microcoded math box. It is wired to the emulators.org in-frame debugger so you can single-step the 6809, read and write the A/B/X/Y/U/S registers and memory, watch the AVG vector RAM display list build word by word, and set breakpoints and write watchpoints.

Reference hardware (MAME) ↗

Runs on: Web browser

Star Wars Online Emulator

Play Star Wars using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Star WarsStar WarsStar WarsgreyOpen ⛶

Machine emulated

The Star Wars arcade board (Atari, 1983) — a colour-vector machine that draws with an electron beam steered by a display list rather than a raster. The board is a Motorola 6809 with the Atari colour Analog Vector Generator and a microcoded bit-slice math box for the 3-D rotate-and-project maths; this build runs the original ROMs on a 6809 with faithful AVG and math-box ports, so it plugs into the shared 6809 debugger. It was the first colour-vector game to use the X-Y monitor's full palette, and its yoke and Death Star trench run made it one of the definitive arcade cabinets of the era.

Chips

Notes

Embedding

Star Wars is a colour-vector game with no framebuffer: a Motorola 6809 builds a display list of 16-bit words in the RAM it shares with the Atari Analog Vector Generator (AVG), using a bit-slice math box for the 3-D rotate-and-project arithmetic, then strobes "GO" and the AVG draws the coloured line segments. This build is a genuine emulation of that board: the vendored MIT CPU6809 core runs the original Atari ROM set (self-hosted, every CRC32 verified against MAME's starwars parent set), driving faithful JavaScript ports of MAME's colour AVG state machine and the math-box microcode, from a host-owned loop so the debugger can control it.

Boot. The 6809 takes its reset vector from $FFFE and runs the program ROM at $8000-$FFFF plus the banked page at $6000-$7FFF. A ~246 Hz periodic IRQ drives the game; each display field it rebuilds the vector list and strobes GO:

var m = new StarWarsMachine();   // loads the ROMs, builds the 6809 + AVG + math box
m.reset();                        // pulls the reset vector from $FFFE
m.assertIRQ();                    // the ~246 Hz interrupt that drives the game
m.stepCPU();                      // run one 6809 instruction (honouring a pending IRQ)
m.renderTo(ctx, W, H);            // stroke the AVG's colour line list

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.advanceInsn()methodFetch, decode and run one 6809 instruction; returns its cycle count. The single-step primitive.
m.assertIRQ() / m.stepCPU()methodAssert the level-triggered IRQ line (~246 Hz); step one instruction honouring a pending IRQ (cleared by the game's ack at $4660).
m.avgGo()methodRun the colour AVG state machine over vector RAM/ROM and collect the field's line segments. Fired when the CPU strobes $4600.
m.mathbox.math_w(off,v)methodThe math-box command window ($4700-$4707): pokes an operand, runs the microcoded matrix processor, or the hardware divider.
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.cpu.saveState() / m.cpu.set(reg,v)methodThe live 6809 registers (A/B/X/Y/U/S/PC/DP/CC), read and written directly.

Video. Each field the loop runs the 6809 (six ~246 Hz IRQ slices), walks the AVG display list the game left in vector RAM, and strokes the coloured line segments to the canvas.

Debugger integration

The debugger drives a host-owned run loop: because the 6809 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) -- run n 6809 instructions and redraw, so a single step advances the PC by one instruction.
  • step(n) -- advance n whole display fields (each six IRQ slices).
  • 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.
  • 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. The 6809's registers and the whole map are ordinary JavaScript, so registers are read and written directly and memory is exposed side-effect-free.

The plug-in (starwars-debug.js) reads these hooks and calls EmuKit.defineMachine with the full 6809 register file (A/B/D, X/Y/U/S, PC, DP, CC and the flags) bound to the shared m6809 disassembler, four memory chips (the 64 K CPU bus, the program ROM, the vector ROM and the math RAM shared with the math box) and the yoke control panel. A neat trick for this machine: point the Math RAM hex window at $5000 and single-step through a frame -- you watch the 6809 poke operands into the shared RAM, trigger the math box at $4700, and read the projected coordinates back that become the 3-D vectors.

Architecture

Star Wars draws with an electron beam steered by a display list, not a raster. Emulated here as plain JavaScript objects wired to the original ROMs:

  • CPU -- a Motorola MC6809E (the vendored MIT CPU6809 core by Martin Maly), reaching memory only through the machine's memRead/memWrite, so the bus, banking and I/O live in one place and it single-steps cleanly.
  • AVG -- the Atari colour Analog Vector Generator, a faithful port of MAME's avg_starwars_device: a state machine clocked through the 256×4 state PROM (136021-109) whose three decoded bits fire the strobe handlers that latch vector words, integrate the beam and emit colour segments (colour from a STAT word through color111).
  • Math box -- the bit-slice coprocessor, a port of MAME's machine/starwars.cpp: its microcode is pre-decoded from the four 1K×4 PROMs (136021-110/111/112/113) and executed exactly (a serial subtract-multiply-accumulate plus a restoring divider) on the 2 KB math RAM it shares with the CPU.
  • Bus / I/O -- 12 KB RAM, the 4 KB vector ROM, the banked program ROM ($6000), the fixed program ROM ($8000), the input ports, the ADC (yoke), the AVG GO/reset strobes, the math-box window and the periodic IRQ.
  • ROMs -- the original Atari starwars set (six 6809 program ROMs, the vector ROM, the AVG state PROM and the four math-box PROMs), self-hosted and CRC-verified, grey-area preservation copies (© Atari).

The timing the game needs is its ~246 Hz IRQ (the 12.096 MHz master clock divided down); the host loop reproduces it, six IRQ slices per display field, rendering the AVG list at the end of each field.

The fix that made it render. The board banks $6000-$7FFF through the LS259 out-latch's Q4 line (MPAGE): bank 1 holds the math/vector routines, bank 0 holds a display-list copy routine at $611E. The game runs its foreground with interrupts enabled and MPAGE freely toggled to bank 1, but the ~246 Hz IRQ handler does JSR $611E assuming bank 0 and never touches the bank latch. When an IRQ landed while the foreground was mid-bank 1, the handler executed bank 1 garbage, the PC ran off the end of ROM and halted at the self-test BRA-to-self at $EF54 — so the AVG was never strobed and the screen stayed black (only two GO strobes in three million instructions). The fix models the board as keeping MPAGE transparent to interrupt service: on IRQ entry stepCPU saves the current bank and forces bank 0 for the handler, then restores it when that handler's RTI fires (matched by the pushed frame's stack pointer). With that, the 6809 no longer diverges and the AVG renders up to ~1025 colour segments per field.

The fix that made attract cycle. DSW0 bit 7 is the cabinet Freeze diagnostic switch, and its normal (running) position reads as 1. The game's ~246 Hz IRQ latches DSW0 through an edge detector into $4824, and the main foreground loop at $6005 only advances the attract state machine (and rebuilds the vector scene) on a field where $4824 bit 7, a start/fire edge, or the power-on timer is set. The build had DSW0 set with that bit clear — i.e. Freeze ON — so the board was literally frozen on one static ~1000-segment field, exactly as a real cabinet freezes with that switch. Setting DSW0 to the correct default (Freeze off) lets attract animate and cycle through its title and demo states ($0C→$05→$06→…).

Sound

The real sound board, emulated. Star Wars carries a second board driven from the main CPU through an 8-bit latch, and this build runs it for real (starwars-sound.js): a dedicated MC6809E executing the original Atari sound ROMs (136021-107/-208, self-hosted and CRC/SHA1-verified), a MOS6532 RIOT (interval timer + two I/O ports), four Atari POKEYs (the shared debugger/src/chips/pokey.js) and a TMS5220 LPC speech synthesiser. All of it runs at the same 1.512 MHz (12.096 MHz / 8) as the main CPU; the TMS clocks at MASTER_CLOCK/2/9.

How the two boards talk. The main CPU writes a command byte to $4400 (the sound latch); that sets the RIOT's PA7, whose edge interrupts the sound 6809, which reads the command and drives the POKEYs (music, engine hum, laser fire, explosions) and streams LPC frames to the TMS5220 for speech. The sound board answers on a second latch the main CPU reads back at $4400/$4401 (the boot handshake returns $5A). The TMS5220 core is ported from MAME's sound/tms5220.cpp with its exact 5220 coefficient ROM (energy/pitch/chirp and the ten K reflection-coefficient tables from tms5110r.hxx); it parses the frame bitstream (4-bit energy, 1-bit repeat, 6-bit pitch, 5/5/4/4/4/4/4/3/3/3-bit K1..K10), interpolates over eight sub-periods and runs the 10-stage lattice filter at 8 kHz. There is no separate speech ROM: the LPC data lives in the sound ROMs and is streamed by the sound program, exactly as on the real board.

Mix & rate. Each of the four POKEYs and the TMS is generated directly at EmuAudio.sampleRate (a fractional accumulator converts each chip's base clock to output samples, so pitch is correct with no resampling); they are summed, packed to interleaved-stereo Int16 and pushed as Math.round(EmuAudio.sampleRate/60) pairs per video frame. window.EMU_BOOT.transport exposes isMuted()/setMute() delegating to the shared sink; it starts muted (browsers block audio before a gesture) and the shell's Sound button unmutes from a real click. The board boots into its own attract mode and plays the ROM's attract music. Press coin and Start, or just fire since this runs free play, to begin a game; the POKEY fanfare and the TMS5220 speech then play at the game's own moments.

Faithfulness. The POKEY music/effects and the TMS5220 speech are both live and driven by the real sound program. The mix balance and the TMS interpolation are a faithful approximation rather than a cycle-exact copy of the analog board.