
  ===============================================================
  |    Where are GameBoy games storing their hi-scores data?    |
  |            Copyright (C) 2010-2015 Mateusz Viste            |
  ===============================================================

Many GameBoy games are using "hiscores" tables. Unfortunately, not every GameBoy game comes 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")


** CRYSTAL QUEST [CRC32: 51300CFD] **
  Crystal Quest stores 8 best scores, where each score is a pair of name+score. The name is a 3-letter string, and the score is an 8-digit long score stored in BCD notation as 4 bytes. The list below presents how the scores are laid out in memory:
    C500h C501h C502h       first name
    C503h C504h C505h C506h first score
    ...
    C531h C532h C533h       eighth name
    C534h C535h C536h C537  eighth score


** 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)


** FLIPUL [CRC32: A2F30B4B] **
  The top score keeped by Flipul is 7-digit long (eg. "0012120"), and each digit is saved in a separated byte, starting at offset 0xC131 in inversed order. Hence the score "0012120" would be saved as the binary string 0x00 0x02 0x01 0x02 0x01 0x00 0x00.


** 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


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


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


** 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)


** QUARTH [CRC32: BFB112AD] **
  The score is written in BCD notation, without the trailing zero, begining
  at location C419h. A score of 64330 would be saved as follows:
  C419h: 33h
  C41Ah: 64h
  C41Bh: 00h



** SOLARSTRIKER [CRC32: 11817103] **
  SolarStriker keeps the hi-score at the location CFF1h. Each digit of the hi-score is kept in a separate byte, hence 7 bytes are used in total. Example for the score 0048500:
  CFF1h: 00
  CFF2h: 00
  CFF3h: 04
  CFF4h: 08
  CFF5h: 05
  CFF6h: 00
  CFF7h: 00


** 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


** TAIL GATOR [CRC32: C5ACCE7C] **
  Tail gator holds a single 'hi-score' value at address C165h. The hi-score value is saved in 3 bytes using BCD notation. Note: the score is always a multiple of 10, and the game do not care about storing the last '0' digit. Example: for a hi-score of 0082900, we will fint the following binary string at offset C165h:
   0x00 0x82 0x90


** 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)


** 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]------------------------------------------------------------------------
