SearchA-ZP › Pac-Man

Pac-Man

1980 Arcade Open source · MIT Online

Pac-Man (Namco, 1980), designed by Toru Iwatani, is the maze-chase arcade game that became a worldwide phenomenon and one of the most recognisable video games ever made. This build runs the original Namco board in the browser, a pure-JavaScript Zilog Z80 core plus the Namco tile-and-sprite video hardware and its colour PROMs, and boots straight into the game’s attract mode. It is wired to the emulators.org in-frame debugger so you can single-step the Z80, read and write the registers and the full 64K memory (video RAM sits at 0x4000), set execution breakpoints and set write watchpoints.

Visit the official site ↗

Runs on: Web browser

Pac-Man Online Emulator

Play Pac-Man using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Pac-ManPac-ManPac-MangreyOpen ⛶

Machine emulated

The Pac-Man arcade board (Namco, 1980) - a Zilog Z80 at 3.072 MHz with 16 KB of program ROM, 2 KB of RAM and a fixed tilemap video system: a 36×28 playfield of 8×8 tiles plus eight hardware sprites, coloured through a pair of PROMs, on a 288×224 raster rotated 90° in the upright cabinet. It is one of the best-selling and most influential arcade machines of all time.

Chips

Notes

Embedding

Pac-Man is the 1980 Namco arcade machine: a Zilog Z80 at 3.072 MHz driving a tile-and-sprite raster (288×224 landscape, rotated 90° to 224×288 in the upright cabinet). This build vendors the pure-JavaScript Z80 core, the Namco video pipeline and the colour/palette PROM decoders from derpyder/pacman-fpga (MIT) and drives them from a host-owned loop so the debugger can control the machine.

Boot. The four 4 KB program ROMs are concatenated into 0x0000–0x3FFF and the Z80 starts at 0x0000, dropping straight into the game's attract mode with no coin:

var prog = new Uint8Array(0x4000);
prog.set(rom_6e, 0x0000);            // pacman.6e/6f/6h/6j -> 0x0000..0x3FFF
prog.set(rom_6f, 0x1000);
var cpu = new Z80(bus);
cpu.reset();                       // PC=0x0000 -> attract mode

The machine. A single bus object routes every Z80 access to the right chip, and a shared STATE holds the live RAM and decoded ROMs the renderer reads each frame:

MemberKindWhat it does
cpu.step()methodFetch, decode and run one Z80 instruction; returns the elapsed t-states and advances cpu.pc.
bus.read8(a) / bus.write8(a,v)methodSide-effect-free access to the 64 KB map: ROM at 0x0000, video RAM at 0x4000, colour RAM at 0x4400, work/sprite RAM to 0x4FFF, I/O at 0x5000.
bus.out(0, v)methodLatches the IM 2 interrupt vector the video code programs each frame.
renderFrame(ctx)methodWalks video + colour RAM through the tile/sprite caches and the palette PROMs, then applies the cabinet's 90° rotation onto the 224×288 canvas.
in0 / in1fieldThe two active-low input latches (0x5000/0x5040): joystick, coin, 1P/2P start and cabinet/DIP bits.

Video. Each animation frame the loop runs 51,200 Z80 cycles (one 60 Hz field), raises the maskable interrupt the game vectors through I:vector, then renders the 36×28 tile playfield and eight hardware sprites and rotates the landscape image 90° for the upright screen.

Debugger integration

The debugger drives a host-owned run loop: because the Z80 interpreter runs one instruction at a time in JavaScript, the loop can pause, single-step and check breakpoints between any two instructions; the CPU core is used unmodified.

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 60 Hz fields, each with its maskable interrupt.
  • breakpoints - a Set of PC values. When it is non-empty the loop runs instruction-by-instruction and pauses before executing a watched address; when empty it runs a full field at speed, so an idle debugger costs nothing.
  • watchpoints - bus.write8 is wrapped so a write to a watched address raises a flag that pauses the loop after that instruction. Because the Z80's own memory writes flow through write8, the watchpoint catches sprite, score and maze-state stores as the game makes them.

The plug-in (pacman-debug.js) reads these hooks and calls EmuKit.defineMachine with the full Z80 register file (A/F and the BC/DE/HL pairs plus their primes, IX/IY, SP, PC, the interrupt vector I, refresh R, and the S Z H P/V N C flag bits - every field writeable), the memory chips (64K bus, 16K program ROM, video RAM and colour RAM) bound to the shared z80 disassembler at /debugger/src/cpus/z80.js, and the on-screen control panel.

Architecture

The Namco Pac-Man board is a single Zilog Z80 at 3.072 MHz with 16 KB of program ROM, 2 KB of RAM and a fixed tilemap video system, all modelled here as plain JavaScript:

  • CPU - a Z80 interpreter running in interrupt mode 2; the display hardware latches a new interrupt vector through I/O port 0 each field, and a write to 0x5000 gates the interrupt on.
  • Video RAM - 1 KB of tile codes at 0x4000 and 1 KB of colour attributes at 0x4400, addressing a 36×28 playfield through Namco's serpentine row/column mapper.
  • Character & sprite ROMs - a 4 KB tile ROM (pacman.5e) and a 4 KB sprite ROM (pacman.5f), each 2 bits per pixel, pre-decoded into pixel caches at boot.
  • Palette PROMs - a 32-byte palette (82s123.7f) of 3-3-2 RGB and a 256-byte colour lookup (82s126.4a) that map a tile/sprite's 6-bit colour code plus 2-bit pixel to a final palette entry.
  • Sprites - eight hardware sprites; their codes and colours live at 0x4FF0 and their X/Y positions in the I/O page at 0x5060, drawn over the playfield with per-sprite horizontal and vertical flip.
  • Sound - the Namco 3-channel WSG waveform PROMs are present in the ROM set but audio is not wired up in this build.

The single per-field maskable interrupt is the only timing the game truly depends on, so the host loop runs one field's worth of Z80 cycles (51,200) and raises exactly that interrupt before each redraw.