Cite as
mburkley/pacman-c
Original
https://github.com/mburkley/pacman-c
Pinned
mburkley/pacman-c @ 3277e56d24df82882fd99712464fed6786706e68
Accessed
2026-10-21
Licence
MIT (LICENSE)
Credit
Mark Burkley translated the Pac-Man ROM's Z80 code into C function by function, keeping each original instruction as a comment above its translation. Function names, which end in the ROM address, and comments quoted in pac-man claims are his.
Notes
pacman.c holds the game. The Makefile and harness load pacman.6e, .6f, .6h, and .6j, the program ROMs of MAME's `pacman` set (Midway's US release); it can also load the `namcopac` ROMs. Claims cite the Z80 lines kept in the comments as well as the C.

Cited on

Claims (8)

In chase mode each Pac-Man ghost steers toward its own target tile. Blinky targets Pac-Man's tile. Pinky targets Pac-Man's tile plus 4 times his direction vector, and Inky takes Pac-Man's tile plus twice the vector, doubles it, and subtracts Blinky's tile. The Z80 does both sums as 16-bit adds of a packed two-byte tile and vector (add hl,hl, add hl,de), so a carry out of the low byte's axis spills into the other axis; away from such a carry, Pinky's target is 4 tiles ahead of Pac-Man and Inky's starts 2 ahead. Clyde targets Pac-Man's tile while the squared distance between them is 64 or more, that is 8 tiles or farther, and otherwise heads for his scatter corner. The translation reads MAME's pacman set, Midway's release.pacman.c L11479pacman.c L11516–11539pacman.c L11576–11617pacman.c L11637–11682pacman.c L12131–12178Makefile L20–23Code
findBestOrientation_2966 turns a target into a move: it tries the four directions in turn, skips the reverse of the ghost's current one and any that points into a maze wall, and keeps the one whose next tile has the smallest squared distance to the target; on a tie the later direction wins.pacman.c L11993–12106Code
A mode counter at $4DC1 runs from 0 to 7: on even values the ghosts head for fixed scatter tiles, on odd values they chase. ghostsChangeOrientation_0e36 counts time and steps the counter when the count meets a 16-bit entry for the current mode, then flags all four ghosts to reverse. At 7 it stops, so the game holds four scatter phases and leaves the fourth chase phase on for good. The count pauses while Pac-Man is powered up.pacman.c L4167–4225pacman.c L11434–11479Code
A frightened ghost picks a random direction from random_2a23, which steps a pointer as p←(5p+1)mod8192 and returns the byte at that address, so the game's own first 8 KB of ROM serve as the random table. The direction is the low 2 bits; a reversal or a wall sends it on to try the next one.pacman.c L12227–12247pacman.c L11905–11980Code
Pac-Man awards one extra life when the score reaches the DIP-switch setting: 10,000, 15,000, or 20,000 points, or never. The table holds BCD thousands (10, 15, 20, and $FF for none). After each score change the code compares the score's ten-thousands and thousands digits with the setting, and a flag bit stops a second award.pacman.c L11383pacman.c L11419–11423data.h L35–36pacman.c L12359–12378pacman.c L12637–12665Code
Each new level advances a pointer one entry along a difficulty table until the entry reads $14 (20). The DIP switch picks the table: one runs 0, 1, 2, … 20 and reaches 20 on level 21; the other, which the comment calls hard, runs 1, 3, 4, 6, 7, 8, … 17, 20 and reaches 20 on level 16. Each entry selects a 6-byte record at $0796 that sets, among other things, the movement pattern and the ghosts' counters for leaving the house.pacman.c L273–282pacman.c L11406pacman.c L3153–3172pacman.c L2221–2292Code
Pac-Man keeps one high score, three BCD bytes at $4E88. After every change to a player's score it compares the score with it from the top byte down and, if the score is higher, copies the 3 bytes over and redraws it.pacman.c L12389–12440Code
The level byte at $4E13 starts at 0 and gains 1 per level, so on level 256 it holds 255. The routine that draws the fruit row loads it and adds 1, and that inc a wraps to 0; 0 passes the "fewer than 8" test, and the draw loop, a djnz counted by that 0, makes 256 passes instead of at most 7. Each pass draws a fruit at HL, writes its color $400 higher, and moves HL on 2 bytes, so from $4004 the loop steps across about 512 bytes of the 1 KB video RAM at $4000 and the matching span of color RAM at $4400.pacman.c L2119–2125pacman.c L3153–3156pacman.c L12932–12947pacman.c L12955–12993memmap.h L42–43Code