Disassembly of Pac-Man (Galaxian Hardware) Note: Only contains the control file with markup to define memory regions, labels, comments and whatnot. It does not contain the ROMs nor the listing itself.

Pedro Gimeno a69d79b7b4 Add values that are not addresses 2 years ago
.gitignore 3e844801f8 Initial commit - Add .gitignore 2 years ago
README.md 9d279f5d0f Add info on the main loop and the interrupt routine 2 years ago
pacmanbl.ctl a69d79b7b4 Add values that are not addresses 2 years ago


PacMan (Galaxian hardware) - Disassembly

This repository contains a dz80 control file to disassemble and comment the PacMan code that runs in Galaxian hardware.

This is work in progress.

How to Use

  • Install d52. Debian: sudo apt-get install d52; other systems: no idea, but the package is here: http://www.efton.sk/t0t1/d52v341.zip
  • Grab puckman.zip from a MAME distribution with merged ROMs. Unzip it to a temporary directory.
  • With bash, use: cat pacmanbl/{1..7} > pacmanbl.bin
  • Move pacmanbl.bin to the directory where pacmanbl.ctl is. You can now remove the temporary directory.
  • From the directory containing pacmanbl.bin and pacmanbl.ctl, run: dz80 pacmanbl.bin (for just the listing) or dz80 -d pacmanbl.bin (for embedding address and data info in the listing).

The last step will generate a pacmanbl.z80 file with the assembly listing.


The code uses a command queue. There are 32 command codes, from 00h to 1Fh. Each command has a parameter. RST 28h is used to enqueue a command; the two bytes following the RST 28h instruction are the command and the parameter. The comments at addresses 2314h-2352h explain the commands. The command handling routines are called with the parameter in register B.

When the on-reset initialization finishes, the main loop is executed. This loop is limited to checking the queue for commands and executing them if there are any. The rest of the logic is in the NMI interrupt routine.

Maskable interrupts are always disabled. The interrupt routine at 38h enters an endless loop that only disables NMI and refreshes the watchdog, effectively forcing a freeze. Possibly used for debugging.

Restart routines:

  • RST 00h: Reset.
  • RST 08h: Fills B bytes with A, starting in HL. Returns with A unchanged, B = 0 and HL pointing to the first byte that wasn't filled.
  • RST 10h: Byte array access, using A as index; HL points to the array. Returns A = value, HL pointing to the byte.
  • RST 18h: Word array access, using B as index; HL points to the array. Returns HL = value; destroys DE and A.
  • RST 20h: Jump table. Given an address array right after the RST 20h opcode, use A as index into the element and jump to it. Note that it's a jump, not a call.
  • RST 28h: Enqueue a command and parameter. Both immediately follow the RST 28h opcode.
  • RST 30h: Purpose still unknown. Looks for a spot in a strided list of 16 records of 3 bytes each, starting at 4090h, at which the first byte of the triplet is zero; if one is found, the 3 bytes following the RST 30h opcode are read and stored in that spot. If not found, it returns without skipping the 3 bytes, potentially causing a crash, so it's suspected that the programmers knew that there would always be a free spot.
  • RST 38h: Purpose unknown; suspected use in debugging or diagnostics. Continuously disables NMI and refreshes the watchdog, causing a freeze.