Q*bert
Q*bert (Gottlieb, 1982), designed by Warren Davis and Jeff Lee, is one of the defining games of the golden age of the arcades: you hop a round orange creature across a pyramid of cubes, changing every cube to a target colour while dodging Coily the snake and the bouncing balls. It runs on Gottlieb System 1 hardware which, unusually for its era, is built around a 16-bit Intel 8088. There is no ready-made browser core for it, so this build is written from scratch: a complete 8086/8088 interpreter plus a port of the System 1 video and I/O hardware, self-hosted with no CDN. It boots straight into the attract mode and is wired to the emulators.org in-frame debugger, so you can single-step the 8088, read and write AX/BX/CX/DX/SI/DI/BP/SP/IP and the segment registers, browse the 64K bus as hex or 8086 disassembly, and set execution breakpoints and write watchpoints.
Q*bert at the Internet Archive ↗
Runs on: Web browser
Q*bert Online Emulator
Play Q*bert using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Q*bert | Q*bert | Q*bert | grey | Open ⛶ | |
| Mad Planets | Q*bert | Mad Planets | grey | Open ⛶ |
Machines emulated
Chips
Notes
Embedding
Q*bert is a 1982 Gottlieb arcade machine built on System 1 hardware. Where almost every arcade board of the era used an 8-bit CPU, Gottlieb reached for a 16-bit Intel 8088 at 5 MHz. There is no ready-made browser core for it, so this build is written from scratch and vendored whole: a complete 8086/8088 interpreter (i8088.js) driving a port of the System 1 video and I/O hardware (gottlieb.js). Everything is self-hosted; nothing is fetched from a CDN.
Boot. The board decodes only the low 16 address lines, so the 8088's 20-bit space wraps to 64 KB and the reset vector at F000:FFF0 lands at physical 0xFFF0 — a JMP FAR 0000:A000 into the first program ROM. From cold reset the machine runs to its attract mode with no coin:
var m = GottliebMachine(roms); // qb-rom0/1/2 + qb-fg0..3 + qb-bg0/1
m.cpu.reset(); // 8088 -> F000:FFF0 -> 0000:A000
// per frame: fire the vertical-blank NMI, run the CPU, draw
if (m.canNmi()) m.nmi();
while (budget-- && !m.cpu.isHalted()) m.cpu.step();
m.render();
The machine object. GottliebMachine exposes the whole board as ordinary fields and methods:
| Member | Kind | What it does |
|---|---|---|
cpu.step() | method | Fetch, decode and execute one 8088 instruction; the debugger's single-step calls this directly. |
cpu.nmi() | method | Deliver the vertical-blank NMI — pushes FLAGS/CS/IP and vectors through 0x0008. The whole game is driven by this once-a-frame interrupt. |
render() / framebuffer | method / field | Rasterise the 32×30 background tilemap and the 62 hardware sprites, then rotate the 256×240 raster into the cabinet's ROT270 240×256 portrait image. |
peek(a) | method | Side-effect-free byte read of the 64 KB space — what the debugger's memory windows use. |
buttonsBit / joyBit | method | Drive the coin/start latch (0x5801) and the diagonal 4-way joystick latch (0x5804). |
Video. Q*bert's background comes from a 256-entry ROM character set (qb-bg0/1), not the System 1 character RAM, so each frame walks the tilemap at 0x3800, decodes 8×8 4-bpp tiles, overlays the 16×16 sprites from the four bit-plane ROMs (qb-fg0..3), resolves colours through the 16-entry resistor-ladder palette at 0x5000, and rotates the result for the upright cabinet.
Debugger integration
The debugger drives a host-owned run loop. Because the 8088 interpreter executes one instruction at a time in JavaScript, the loop can pause, single-step, breakpoint and watch between any two instructions — the core needs no special build.
window.EMU_BOOT.transport exposes the controls the shared debugger calls:
- pause / resume / isPaused — stop or restart the
requestAnimationFrameloop. - stepInsn(n) — call
cpu.step()exactly n times and redraw, so one step advances IP by a single 8088 instruction. - step(n) — advance n whole 61 Hz frames, each with its vertical-blank NMI.
- breakpoints — a
Setof linear PC values (CS<<4 + IP). When non-empty the loop steps instruction-by-instruction and pauses before executing a watched address; when empty it runs a frame at speed. - watchpoints — the same
Setthe machine's memory-write path consults, so a write to a watched address pauses the loop on the very next instruction boundary.
The plug-in (qbert-debug.js) reads these hooks and calls EmuKit.defineMachine with the full 8086 register file — AX BX CX DX SI DI BP SP IP, the ES CS SS DS segments and the O D I S Z A P C flag bits, each with a live read and a write-back set() — the 64 KB bus and program ROM as hex / 8086 disassembly, the sprite, tilemap and palette RAM as hex, and an on-screen control pad. It reuses the shared x86 disassembler at /debugger/src/cpus/x86.js; no new decoder was needed.
Architecture
The Gottlieb System 1 board is a single Intel 8088 at 5 MHz with a 64 KB memory-mapped world (the upper address lines are not decoded, so the megabyte space folds down to 64 KB). Modelled here as plain JavaScript:
- CPU — a full real-mode 8086/8088 interpreter: every documented opcode, ModR/M addressing, the string primitives with
REP, shifts and rotates,MUL/DIV, the BCD adjusts, and eagerly-computed flags. - RAM —
0x0000–0x2FFF, including the 8088 interrupt-vector table the game installs at0x0000. - Video — a 32×30 background tilemap at
0x3800over a 256-tile ROM font, 62 hardware sprites at0x3000drawn from four 8 KB bit-plane ROMs, and a 16-colour resistor-ladder palette at0x5000. - I/O — DIP switches, the coin/start/service latch and the diagonal 4-way joystick at
0x5800–0x5804; a watchdog and a sound-command port (the separate 6502 sound board is not modelled). - Interrupts — a single unconditional NMI at every vertical blank (~61 Hz) vectors through
0x0008and drives the entire game.
Program code lives in three 8 KB ROMs (qb-rom2 at 0xA000, qb-rom1 at 0xC000, qb-rom0 at 0xE000); the graphics live in the two background ROMs and four sprite ROMs, none of which sit in the CPU's address space — only the video hardware sees them.