At the core of Pacman is on a Z80 CPU supported by a 224x288 color video with hardware sprites and a 3-voice wavetable sound generator... a pretty nice setup for 1980!
Here is all the information I know about the Pacman hardware. For the most part it has been extracted by looking at the sources of various emulators, most notably MAME, but I have spent many hours to re-organize and write it down in a single place. If you find wrong or missing information please email me so that I can improve the content of these pages.
The CPU is a Z80 clocked at 3.072 MHz. The game ROM takes 16K at the beginning of the address space, followed by 2K of video memory and 2K of RAM for game use:
|4000h||0400h||Video RAM (1K, characters)|
|4400h||0400h||Video RAM (1K, color information)|
Several registers that interface with other hardware devices are memory mapped directly in the CPU address space:
|5000h||0001h||Write||Interrupt enable (bit 0: 0=disabled, 1=enabled)|
|5000h||0040h *||Read||IN0 port (joystick and coin slot)|
|5001h||0001h||Write||Sound enable (bit 0: 0=disabled, 1=enabled)|
|5002h||0001h||Write||Aux board enable?|
|5003h||0001h||Write||Flip screen (bit 0: 0=normal, 1=flipped)|
|5004h||0001h||Write||Player 1 start light (bit 0: 1=on, 2=off)|
|5005h||0001h||Write||Player 2 start light|
|5006h||0001h||Write||Coin lockout (bit 0: 0=unlocked, 1=locked)|
|5007h||0001h||Write||Coin counter (trigger by changing the bit 0 from 0 to 1)|
|5040h||0040h *||Read||IN1 port (joystick and start buttons)|
|5080h||0040h *||Read||DIP switch settings|
|50C0h||0040h *||Write||Watchdog reset|
From looking at the ROM code I think port 5002h is unused in Pacman and used in Ms. Pacman to enable the auxiliary board (when 01h is written to the port). At least that's how PIE uses it and it seems to work.
In cocktail (table) mode the screen must be flipped for the second player, otherwise he would see the game upside down. This is made in hardware by writing 01h to the port 5003h and only flips the characters, while the sprites are flipped and repositioned by the game engine.
The IN0 port is connected to the joystick and the coin slots:
|0||Joystick up (0=pressed, 1=released)|
|1||Joystick left (0=pressed, 1=released)|
|2||Joystick right (0=pressed, 1=released)|
|3||Joystick down (0=pressed, 1=released)|
|4||Rack advance (switch, automatically advance to next game level: 0=on, 1=off)|
|5||Coin slot 1 (trigger by changing the bit to 0 then 1)|
|6||Coin slot 2 (trigger by changing the bit to 0 then 1)|
|7||Credit button (0=pressed, 1=released)|
The credit button works like the coin slots but adds a credit without incrementing the coin counter. The IN1 port is connected to the second player joystick (only for cocktail table ) and the start buttons:
|0||Cocktail cabinet: 2nd player joystick up (0=pressed, 1=released)|
|1||Cocktail cabinet: 2nd player joystick left (0=pressed, 1=released)|
|2||Cocktail cabinet: 2nd player joystick right (0=pressed, 1=released)|
|3||Cocktail cabinet: 2nd player joystick down (0=pressed, 1=released)|
|4||Board test (switch: 0=on, 1=off)|
|5||One player start button (0=pressed, 1=released)|
|6||Two players start button (0=pressed, 1=released)|
|7||Cabinet mode (0=table, 1=upright)|
Some game settings such as for example the number of lives per game or the game difficulty are controlled by DIP (Dual In-line Package) switches that are memory mapped to address 5080h. Each switch is represented by a bit that is 1 if the switch is off and 0 if the switch is on:
|0, 1||Coins per game (0=free play, 1=1 coin per game, 2=1 coin per 2 games, 3=2 coins per game)|
|2, 3||Number of lives per game (0=1 life, 1=2 lives, 2=3 lives, 3=5 lives)|
|4, 5||Bonus score for extra life (0=10000 points, 1=15000 points, 2=20000 points, 3=none)|
|6||Difficulty (jumper pad: 0=hard, 1=normal)|
|7||Ghost names (jumper pad: 0=alternate, 1=normal)|
I don't have specific information on the watchdog reset port at 50C0h, so I can only guess it is the port that the game uses to reset the watchdog timer, a CPU-independent clock that resets the CPU after a specified timeout elapses. The port is written at costant intervals during the game (three times per frame) mostly with zeroes and every now and then with a decreasing counter: this tells the watchdog that the program is alive and forces the timer to restart from its initial value.
The display supports a resolution of 224x288 pixels that are actually 8x8 characters arranged in a 28x36 matrix. This allows the video to work with just 2K of RAM, 1K for video information and 1K for color information. The video and color RAM have a very peculiar arrangement with some extra locations that are not visible on the screen.
Colors are defined in a 32-entries palette PROM where each entry contains packed RGB information:
|0||Red||1K ohm resistor|
|1||Red||470 ohm resistor|
|2||Red||220 ohm resistor|
|3||Green||1K ohm resistor|
|4||Green||470 ohm resistor|
|5||Green||220 ohm resistor|
|6||Blue||470 ohm resistor|
|7||Blue||220 ohm resistor|
The resistor values can be used to compute the weights of each bit. The max current output (i.e. intensity) for a color is V/220 + V/470 + V/1000 and this corresponds to 0xFF, the max palette value for a RGB component. Performing the sum and simplifying, as we're only interested in ratios from now on, we get a total of 7934 and individual weights of 4700, 2200 and 1034 respectively (i.e. the 220 ohm resistor allows more current to pass and thus has a greater weight, i.e. is brighter). Scaling those to 0xFF we get the "typical" weights of 0x97, 0x47 and 0x21 that most emulators use.
Although all useable colors are defined in the above palette, character and sprite colors are defined in terms of a logical 256-entries color map that is also stored in a 4-bit PROM. Because each color entry takes only 4 bits only the first 16 entries in the palette can be used, and in fact in Pacman the remaining entries are all zeroed out.
Character definitions are stored in a 4K ROM. There are 256 8x8 characters and each of them is defined using 2 bits per pixel, so one character takes 16 bytes of ROM space. Note that this approach provides only 4 colors per characters. In order to display a character its code must be written in the proper location in the video memory and also it must be assigned a color by writing in the corresponding color memory location. The character color that is actually displayed is obtained by combining 6 bits from the color memory, which apply to the whole character, with the 2 bits that define each character pixel:
pixel_color(x,y) = (character_color shl 6) or character_pixel_color(x,y)
Pacman supports 8 independent 16x16 color sprites that can be moved anywhere on the screen without interfering with the underlying graphics. Each sprite has its own coordinates, color and display mode. There are 64 different sprite shapes and a sprite can take any one of these. The shapes are defined in a 4K ROM with a format that is practically identical to that of characters. However, according to the display mode, a sprite can also be displayed normally, flipped horizontally, flipped vertically and flipped in both directions.
As usual, sprite registers are memory mapped too:
|4FF0h||Sprite #0 shape (upper six bits) and mode (lower two bits)|
|4FF1h||Sprite #0 color|
|4FF2/3h||Sprite #1 shape/color|
|4FF4/5h||Sprite #2 shape/color|
|4FF6/7h||Sprite #3 shape/color|
|4FF8/9h||Sprite #4 shape/color|
|4FFA/Bh||Sprite #5 shape/color|
|4FFC/Dh||Sprite #6 shape/color|
|4FFE/Fh||Sprite #7 shape/color|
|5060h||Sprite #0 X coordinate|
|5061h||Sprite #0 Y coordinate|
|5062/3h||Sprite #1 X/Y coordinates|
|5064/5h||Sprite #2 X/Y coordinates|
|5066/7h||Sprite #3 X/Y coordinates|
|5068/9h||Sprite #4 X/Y coordinates|
|506A/Bh||Sprite #5 X/Y coordinates|
|506C/Dh||Sprite #6 X/Y coordinates|
|506E/Fh||Sprite #7 X/Y coordinates|
Sprites are displayed in reverse order, so if two sprites overlap the one with the higher number can be wholly or partially covered by the one with the lower number.
The sound comes from a custom chip made by Namco that is able to play up to 3 simultaneous voices using wavetable synthesis.
Copyright (c) 1997-2004 Alessandro Scotti. All rights reserved.