Dig Dug
Dig Dug (Namco, 1982) is one of the defining maze/digging games of the golden age of arcades: you tunnel through the earth and destroy the Pooka and Fygar monsters by inflating them with a pump until they burst, or by dropping rocks on them. This build runs the original three-Z80 Galaga-family board in the browser — the real program ROMs on three JavaScript Z80 cores, the Namco custom I/O chips modelled behaviourally, and a hand-written model of the dual-playfield video — and boots straight into the attract-mode demo. It is wired to the emulators.org in-frame debugger so you can single-step the main Z80, read and write the registers and the full 64K memory, and set execution breakpoints and write watchpoints.
Runs on: Web browser
Dig Dug Online Emulator
Play Dig Dug using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Dig Dug | Dig Dug | Dig Dug | grey | Open ⛶ |
Machine emulated
The Dig Dug arcade board (Namco, 1982) is the Galaga-family hardware: three Zilog Z80 CPUs at 3.072 MHz (main, sub and sound) sharing one 64 KB address space, with the Namco 06xx/51xx/53xx custom chips for I/O, coinage and protection, a background playfield plus a foreground character layer and 16×16 hardware sprites, driving a 224×288 raster rotated 90° in the upright cabinet.
Chips
Notes
Embedding
Dig Dug is the 1982 Namco arcade machine on the Galaga-family board: three Zilog Z80 CPUs at 3.072 MHz sharing one 64 KB address space, plus the Namco 06xx/51xx/53xx custom I/O chips, driving a 224×288 raster rotated 90° in the upright cabinet. This build runs the original program ROMs on three instances of DrGoldfire/Z80.js (MIT), an instruction-at-a-time Z80 interpreter, wrapped in a hand-written model of the Dig Dug board. The memory map, the Namco custom-chip protocol, the interrupt schedule, the graphics-ROM decode, the colour PROMs and the dual-playfield renderer are ported from the galagino project (GPL-3.0).
Boot. Creating the machine decodes the graphics ROMs and colour PROMs, resets all three Z80s and comes up running the board's power-on self-test; the host loop fast-forwards through it and the game drops into attract mode:
var dd = new DigDug(); // decodes gfx/PROMs, resets 3 Z80s + customs
for (var i = 0; i < 1200; i++) // run past the self-test into attract mode
dd.runFrame(brkSet);
dd.render(buf32); // paint the 224x288 RGBA frame
The machine object. DigDug presents the whole cabinet as plain methods:
| Member | Kind | What it does |
|---|---|---|
runFrame(brk) | method | Run every device forward by one 60 Hz field; if the breakpoint Set is non-empty it steps the main Z80 one instruction at a time. Returns 0, 1 (breakpoint) or 2 (watchpoint). |
stepInsn() | method | Run exactly one instruction of the main Z80 and return its T-cycle count. |
render(buf32) | method | Paint the 224×288 frame: the background playfield, the foreground character layer and up to 64 hardware sprites. |
peek(a) / poke(a,v) | method | Side-effect-free access to the main-CPU address space — what the debugger's memory views read and poke. |
setInput(id,down) | method | Drive the joystick, pump, coin and start lines read back through the Namco 51xx. |
reset() | method | Clear RAM and reset all three Z80s — the cabinet's power-cycle. |
Video. Each animation frame the loop advances the machine one field, then re-renders. Dig Dug has two tile layers: a background playfield selected from a 4×1 KB ROM (the four dig patterns) and a foreground character layer in RAM at 0x8000, composited with up to 64 16×16 sprites. Colours come from the 32-entry palette PROM through the tile and sprite colour-map PROMs.
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 of the main CPU — no changes to the CPU core are needed. Following the runbook, the machine model exposes exactly what the debugger asks for.
window.EMU_BOOT.transport maps the shared debugger's controls onto the machine:
- pause / resume / isPaused — stop or restart the
requestAnimationFrameloop that callsrunFrame. - stepInsn(n) — run exactly n instructions of the main Z80 (the CPU that runs the game) and redraw; the sub and sound CPUs stay frozen while paused, exactly as on a stopped bus.
- step(n) — advance n whole 60 Hz fields (each with the Namco NMI and the vblank RST 38 interrupts).
- breakpoints — a
Setof PC values. When it is non-emptyrunFramereads the main Z80's PC (viagetState()) before every instruction and pauses before executing an address in the set; when empty it runs a whole field at speed, so an idle debugger costs nothing. - watchpoints — the main CPU's memory-write path is instrumented, so a write to a watched address sets a flag that pauses the loop after that instruction.
The plug-in (digdug-debug.js) reads these hooks and calls EmuKit.defineMachine with the full main-Z80 register file (AF/BC/DE/HL and their bytes, IX/IY, SP, PC, I, R and the S Z H P/V N C flags), each read live from getState() and written back through setState(). It reuses the shared z80 disassembler (/debugger/src/cpus/z80.js) for the hex/disasm views over the 64 KB bus, the 16 KB program ROM and the video/tile RAM. Memory reads route through a side-effect-free peek that skips the Namco I/O window so inspecting memory never disturbs the machine.
Architecture
The Dig Dug board (Namco, 1982) is the Galaga-family hardware — three Z80s and a set of Namco custom chips, all modelled here as plain JavaScript hanging off DigDug:
- Main CPU — a Z80 running the game; 16 KB of program ROM at
0x0000, shared work / video / sprite RAM from0x8000. This is the CPU the debugger targets. - Sub CPU — a second Z80 for object handling, held in reset until the main CPU has finished its self-test and released it through the latch at
0x6820. - Sound CPU — a third Z80 driving the Namco 3-voice wavetable sound generator, whose
$6800-$681Fregister writes clock the WSG fed from the real Namco waveform PROM (see the Sound section). - Namco 06xx / 51xx / 53xx — the I/O bus controller and the input / DIP custom chips, modelled behaviourally at
0x7000: the main CPU writes a command to0x7100and reads the joystick, buttons, coin/credit and DIP switches back from0x7000, with a command triggering a main-CPU NMI a few instructions later. - Video — a background playfield (four dig patterns in a 4×1 KB ROM), a foreground 8×8 character layer in RAM and up to 64 16×16 sprites, coloured through the 32-entry palette PROM and the tile/sprite colour-map PROMs, scanned as a 224×288 portrait raster.
Interrupts follow the board: a per-field RST 38 to the main and sub CPUs when enabled, two NMIs per field to the sound CPU, and the Namco command NMI to the main CPU, all reproduced by the host loop every frame.
Sound
This build uses Pattern S (the core models no sound device of its own) driving the shared /debugger/src/chips/namco-wsg.js — the same wavetable engine Pac-Man and Bosconian use — but fed the real Namco Dig Dug waveform PROM, not a synthesized table. Dig Dug makes all of its music and effects with the Namco 3-voice Waveform Sound Generator, famous for the walking tune. Each voice is a 20-bit phase accumulator plus a 4-bit volume and a waveform selector; each output sample is the sum over the voices of waveform[sel][(acc>>15) & 31] × volume, and every tick advances acc by the voice's 20-bit frequency.
Real waveform PROM. The 256-byte Namco sound PROM (136007.110) holds eight 32-sample waveforms, four bits each in the low nibble. Its bytes are decoded verbatim into a flat 0..15 table and handed to the WSG as its wave memory (waveform-select masked to three bits, exactly as the hardware wires sel & 7); the render path centres each sample by −8 like the DAC. This replaces the earlier synthesized approximation, so the timbre of every waveform index is now bit-exact to the chip. (The board's second sound PROM, 136007.109, is a clock-timing PROM not connected to the waveform DAC, so it is not used for audio — matching the hardware.)
Where it hooks. The main CPU writes the WSG's registers into the Namco sound window at $6800-$681F; the core's write path latches those writes into the WSG register file:
if ((addr & 0xffe0) === 0x6800) { if (wsg) wsg.write(addr & 0x1f, value); return; }
The registers decode as three voices in the standard Namco layout (voice 0 frequency in nibbles 0-4, volume 5, waveform $05; voices 1 and 2 at 6/a/$0a and b/f/$0f). The phase accumulators advance every sample even while a voice is silent, exactly as the chip clocks them.
Sample rate and pitch. The real WSG advances its accumulators at ~96 kHz (3.072 MHz / 32), so a note's pitch is freq × 96000 / 2^20 Hz. We generate directly at the host EmuAudio.sampleRate by advancing the accumulator by freq × (96000 / sampleRate) per output sample, so pitch is correct at any device rate with no resampling. Each video frame the run loop generates exactly Math.round(EmuAudio.sampleRate / 60) interleaved-stereo Int16 samples (the mono chip duplicated to both channels) and calls EmuAudio.push().
Mute. window.EMU_BOOT.transport exposes isMuted()/setMute(), wired straight to the shared EmuAudio sink loaded from /debugger/src/audio.js. Audio starts muted (browsers block audio before a gesture); the shell's Sound button unmutes from a real click.
Sound in play. Dig Dug's cut-down attract demo in this port does not drive the sound driver, so attract mode is quiet. Insert a coin and press Start to begin a round and the walking music plays; everything you hear is the game's own sound driver clocking the real WSG through the genuine waveform PROM.