
  ===============================================================
  |    Where are GameBoy games storing their hi-scores data?    |
  |                - written by Mateusz Viste -                 |
  ===============================================================

Many GameBoy games are using "hiscores" tables. Unfortunately, not every GameBoy game come with an internal battery to be able to save these hiscores between two plays. I decided to investigate a bit, and find out in what areas of memory such games are storing their hiscores. This way, I was able to add a unique feature to zBoy (my GameBoy emulator), that is saving hiscores in games that aren't able to do so by themselves!

Below I present the results of my investigations.


** ASTEROIDS [CRC32: C1F88833] **
  Asteroids holds 6 hi-scores position. Each position has a name entry of 9 bytes, and a score of 5 bytes (every decimal digit of the score is stored in a separate byte).
  DB00h: Name for the 1st hiscore (9 bytes)
  DB09h: First score (5 bytes)
  DB0Eh: Name for the 2nd hiscore (9 bytes)
    ...etc, for all 6 hiscore positions.


** BATTLECITY [CRC32: A37A814A] **
  This game stores its highest score as a 5 bytes long ASCII string at offset CA02h. Therefore, if the highest score would be 29300, then we would  find following values in memory:
  CA02h = 32h (ASCII character "2")
  CA03h = 39h (ASCII character "9")
  CA04h = 33h (ASCII character "3")
  CA05h = 30h (ASCII character "0")
  CA06h = 30h (ASCII character "0")


** DIG DUG [CRC32: 6C742478] **
  The DIG DUG game is actually two different games: "Dig Dug" and "New Dig Dug". Both these games have different scoring rules, and keep their hiscores separately. Every score is written using 8 bytes, where every byte represent a single decimal digit of the score.
  DE08h..DE0Fh: Dig Dug best score (8 bytes)
  DE10h..DE17h: New Dig Dug best score (8 bytes)


** GALAGA & GALAXIAN [CRC32: 6A6ECFEC] **
  The "Galaga & Galaxian" ROM is storing hiscores for the Galaga and the Galaxian games separately.
  D70Dh..D711h: Hi-score for Galaxian (the last 0 of the score is not stored at all)
  D712h..D716h: Hi-score for Galaga (the last 0 of the score is not stored at all)


** HYPER LODE RUNNER [CRC32: B3A86164] **
  Hyper Lode Runner is saving one hi score only. The score's last digit can't be different than "0", therefore it looks like the game don't even bother saving this last digit. The score is saved using three bytes at following addresses: FFA7h, FFA8h and FFA9h. If the score would be "0118650", then we would see following values:
  FFA7h = 65h
  FFA8h = 18h
  FFA9h = 01h


** PIPE DREAM [CRC32: F59CEDEA] **
  After having done a memory dump of a running Pipe Dream ROM, I found out that hi-scores are stored at following addresses of the internal RAM area:

  C212h: First player name [Space=00, A=01, B=02, C=03, etc...) in 4 letters
  C216h: First player level in 1 byte
  C217h: First player score in 4 bytes (written in BCD, ie 61350 would be written as 0x00 0x06 0x13 0x50)

  C21Bh: Second player name in 4 letters
  C21Fh: Second player level in 1 byte
  C220h: Second player score in 4 bytes (BCD)

  C224h: Third player name in 4 letters
  C228h: Third player level in 1 byte
  C229h: Third player score in 4 bytes (BCD)


** SUPER MARIOLAND v1.0 and v1.1 [CRC32: 90776841 and 2C27EC70] **
  Let's say that the HiScore is 00019710. Following memory addresses will be written:
  C0C0h = 10h
  C0C1h = 97h
  C0C2h = 01h
  C0C3h = 00h


** TETRIS v1.0 and v1.1 [CRC32: 63F9407D and 46DF91AD] **
  HiScores for gametype A (total: 270 bytes):
  D654h: Score #1 for game A, level 0 (3 bytes)
  D657h: Score #2 for game A, level 0 (3 bytes)
  D65Ah: Score #3 for game A, level 0 (3 bytes)

  D65Dh: Description of Score #1 for game A, lev 0 (6 bytes)
  D663h: Description of Score #2 for game A, lev 0 (6 bytes)
  D669h: Description of Score #3 for game A, lev 0 (6 bytes)

  D66Fh: Score #1 for game A, level 1 (3 bytes)
    ...etc (up to level 9)


  HiScores for gametype B (total: 1620 bytes):
  D000h: Score #1 for game B, level 0, H0 (3 bytes)
  D003h: Score #2 for game B, level 0, H0 (3 bytes)
  D006h: Score #3 for game B, level 0, H0 (3 bytes)

  D009h: Description of Score #1 for game B, level 0, H0 (6 bytes)
  D00Fh: Description of Score #2 for game B, level 0, H0 (6 bytes)
  D016h: Description of Score #3 for game B, level 0, H0 (6 bytes)

  D01Ch: Score #1 for game B, level 1, H0 (3 bytes)
    ...etc (up to level 9, H5)


** PAC-MAN [CRC32: 0509069C or B681E243] **
  FF8Ch: Score's third BCD byte
  FF8Dh: Score's second BCD byte
  FF8Eh: Score's first BCD byte


** MS. PAC-MAN [CRC32: 0E5BB1C4] **
  D8C7h: Score's third BCD byte
  D8C8h: Score's second BCD byte
  D8C9h: Score's first BCD byte


** TETRIS ATTACK v1.0 [CRC32: B76C769B] **
  Here we have two different modes of game that save hiscores. The "endless" mode, which stores only a single highest score, and the "time trial" mode, which stores 5 best scores, along with a 3-letter "name".

  The "time trial" scores are stored at following addresses:
  CF00h: 1st best score (5 bytes)
  CF05h: The name for the 1st best score (3 bytes)
  CF08h: 2nd best score (5 bytes)
    ...etc, for all 5 entries.

  The "endless" mode score is stored at CF28h, and every decimal digit of this score is saved as a separate byte. That is, if the score would be 5596, we would find following values:
  CF28h = 00h
  CF29h = 05h
  CF2Ah = 05h
  CF2Bh = 09h
  CF2Ch = 06h

-[EOF]------------------------------------------------------------------------
