The Asteroids arcade game keeps a list of the ten best scores, and allows players to enter their initials when they reach a new high score. But it does not store the scores and initials permanently: Whenever the game is powered off, reset, or switched into self-test mode, all score entries are lost.
I wanted to add permanent high score storage to my game. But since the Asteroids main board is displayed through the back panel of my cabinet, the commercially available piggyback board for the CPU socket was not suitable: I don't have room for the extra height it adds – and due to its size, it would have distracted too much from the original main board. Hence, I rolled my own, more compact high score saver.
My high score saver is a small circuit board that replaces one of the program ROMs on the Asteroids board. The board has the exact same footprint as the ROM's socket. It is populated with surface-mounted ICs on both sides. Since these IC packages have a lower profile than the original ROM's dual in-line package, the whole assembly is only 2 mm higher than the original ROM. Hence, it nicely fits behind the Perspex pane in my cabinet, and is quite inconspicuous when one looks at the main board.
The PCB is exactly the size of the ROM socket
High Score Saver installed on Asteroids board
Note: If you want all the technical detail, schematics, GAL code and data sheets are available in the Files & Links section.
The high score saver board replaces the program ROM for the $7800..$7FFF address range. (Atari part 035143, which sits in position C1 on board revision 02 to 04, and in position J2 on board revisions 05 and 06.) The high score saver contains two EEPROMS (electrically eraseable programmable ROM): a parallel EEPROM to store the program code, and a serial EEPROM for non-volatile storage of the high score values and initials.
Access to the serial EEPROM (Microchip 25LC010A) requires some address space for memory-mapped I/O. Also, extra program code is required to store, retrieve and clear the high scores. To fit this into the 2 kByte address space which Asteroids assigns to the ROM socket, the board contains bank switching logic to toggle between two ROM banks of 2 kByte each. The parallel EEPROM, an Atmel AT28C64B, actually has 8 kByte capacity; but only 2*2 kByte are used here. In each bank, 256 bytes of the address space, $7E00..$7EFF, are reserved for memory-mapped I/O. A rather dated piece of programmable logic, a 16V8B GAL, handles the memory-mapped I/O and bank switching.
Since the PCB sits in a ROM socket, which does not have a properly decoded write enable signal, writing to the serial EEPROM is achieved by read accesses to four reserved addresses in the I/O space. (Two each for the EEPROM's data and clock line, for writing a 0 or 1 respectively.) In addition, the enable signal which triggers these write accesses needs to be cleaned up a bit: Since the Output Enable signal on the ROM sockets was never meant to trigger any write operations, the Asteroid board decodes it in the simplest possible manner. The processor's Phi2 clock signal, which indicates that all addresses on the bus are valid, is not factored in. Hence, glitches can occur on the Output Enable signal during address transitions. That's fine as long as all you want to do is reading from a ROM, but it would cause problems when it triggers spurious write operations to the high score memory. Hence, the trigger signal is low-pass filtered by a simple RC-filter to suppress short glitches (< 20ns). Valid Output Enables are 600ns long, so there is ample margin to separate valid from invalid pulses.
PCB and parts: EEPROM program memory, GAL address decoder, serial EEPROM for highscore data
Serial EEPROM and GAL address decoder on the bottom of the PCB
The GAL also detects when the little board is plugged into a programming adapter instead of the Asteroids board, and routes control signals directly from the socket to the parallel EEPROM in that case. This enabled me to still re-program the EEPROM via an external programmer after the SMD chip was soldered onto the board. I knew I would not get it right first time... Three extra pins are provided to route the required extra status and address lines to the programming adapter. These pins can be omitted if the board is built with a stable software pre-programmed into the AT28C64B.
By the way, GALs are such old-fashioned pieces of programmable logic these days that it is almost embarrassing to use them in a new design. (Well – the job at hand was so simple and the package size was convenient, so a GAL seemed just right). But at the time when Asteroids was designed and built, they were not even invented! The precursor technology, PALs (same logical structure, but only programmable once) had just been introduced in 1978, and was the hottest technology in programmable logic ;-)
To actually use the permanent storage in the serial EEPROM, the Asteroids program code needs to be modified. I got by with changes only to the $7800..$7FFF ROM: It contains the Reset startup code, and from there branches to either the main game loop or to the self-test loop. The main game loop normally resides in a different ROM. The new $7800 ROM now contains a copy of that code, with added hooks for retrieving and storing high score data; the original game loop code remains unused. The actual read and write routines for the serial EEPROM also fitted into the first bank of the $7800 ROM. The self-test loop (now with a status display for the high score saver, and the option to clear all high scores) was moved to the second bank.