Creating a web based IoT Galaga high scores capture seemed like a worthwhile project.

There are some good solutions that already exist that include JROKs fine Galaga Enhancement pack but it is bordering on unobtanium (for me in Aus) and does not meet all my requirements.

Behold GalagaIoT.


Record System Up (powered on times)

Time Stamp High Scores

Record Any Highest Score since last power on

Store virtually an unlimited number of High Scores

No ROM code modifications

Low(ish) Cost $20 AUD ($8 GAL, $2 74ls273, $4 ESP8266, $3 PCB, $1 3.3v reg, $2 caps and resistors etc)


Learn about GALs

Experiment with Kicad

Learn about Galaga, one of my all time favourites

Could be expanded to log play time statics,, such as individual game play times, total game play times.

Maybe possible (with significant modification) to repopulate the High Score table with the 5 highest scores at power on.


Does not repopulate the high score table at reset or power on.

Does not increase the number of digits in the high score from 6 to 7 (as I believe the enhancement pack does.)

Only records High Scores that appear at the very top of the High Score Table. If a player makes it into the high score Top 5 but is not the highest then the score is not recorded. (Future enhancement perhaps)

How it Works: Summary

Basically Galaga address bus is constantly monitored for write accesses that relate to high score updates. Whenever there is an address hit, the data on the data bus is latched and stored in an array.

The array is constantly scanned for tell tale signs that a high score update has occurred (as distinct from random writes that occur during Galaga's startup sequence)

The high score and the players initials are then sent to a web server for further processing, storing and displaying.

How it Works: Details

Whenever there is a new *top* high score (just getting into the high score table does not count unless it is the top score) Galaga will copy it from screen memory at location 83ED - 83F2 to ram location 8A20 - 8A25 (6 digits on reset RAM will contain " 20000" but stored as 00 00 00 00 02 24)

It then initialises the initials stored at 8A3E - 8A41 (3 chars) to "AAA" and waits about 30 secs for the player to enter their initials.

If the player enters their initials, then these are copied to 8A3E - 8A41 if nothing is entered Galaga again writes "AAA" to RAM locations 8A3E - 8A41 .

GalagaIoT constantly monitors the address bus (Buffer Address Bus "A") and records in an array (score[]) any writes to the high score and initials memory locations 8A20 - 8A25 and 8A3E - 8A41 respectively.

GalagaIoT also converts Galaga character code (I call GALASCII) to ASCII. GALASCII codes of interest are 0x00 - 0x09 -> 0 - 9, 0x0A - 0x23 -> A - Z, 0x2A -> "." and 0x24 -> " ".

It also continual scans the array for a match of "AAA" which signifies a new high score has just been achieved and the system is waiting for initials to be input.

GalagaIoT then waits 30 secs (for the initials entry sequence to finish) and then assumes that the last 12 characters in the array will contain the high score. (Yes, its a cludge). These characters (eg "36250AAASAM") are sent to the webserver where they are further processed (see Processing includes replacing AAA with " " , "b" with " " and "c" with "." It then appends the score/initials combination (eg "36250,SAM") to the high score file.

The high score file is then included as part Galaga.htm whenever a browser points to it.

A GAL16V8 (Generic Array Logic) is used to monitor the address bus for any address hits. It monitors the physical bus (Buffer Address Bus "A") at RAM 2114 location 3E on the Galaga Video PCB. There is only 10 address lines (A9 - A0) so the GAL is only matching a address hits in the range of 0x220 -> 0x225 and not 8A20 -> 8A25). For the hit to be valid the write enable (WE) and chip select (CS) pins must be also active. See galaga.pds for the GAL program/config file.

The GAL asserts a negative going clock (output X pin 14) with a pulse width of approx 270ns which drives the Clock input of the 74LS273. When the clock transitions back to high the 74LS273 latches the D input and transfers to its Q outputs. The 74LS273 D inputs are connected the data bus (Buffer Data Bus "D") 2114 D inputs located at 3E and 3F on the Galaga Video board. The Q outputs are connected to 6 of GPIO pins on the ESP8266. (sadly could not connect all 8 data lines as IO on ESP8266 is limited, but luckily GALASCII character set of interest is in this range of 6 bits or 0 - 63)

The GAL also toggles one of its outputs (output Z pin 18) on each address hit. This drives the ESP8266 GPIO14 interrupt on change. The interrupt routine captures the state of its IO in an array.

Currently the Galaga Data Bus to ESP8266 IO mapping is messy but is kept this way as it eased the code/upload/test process. (If only the ESP8266 had two more usable pins and didnt need to use GPIO0 and GPIO2).

The messy decoding logic running on the ESP8266 reflects the messy IO mapping. See IoTGalaga_V9.ino.

Does it Work


With lots of experimenting and playing lots of Galaga to get high scores to be captured for testing I finally have a working bread boarded system. It has not been tested in the field and currently I am working on some finishing touches to the PCB. See GalagaIoT_v2.kicad.pcb

What now

Working on verifying the PCB before sending to fab and thinking of a way to write back the high scores.