Classroom Public page

Lab 5.1: Boot a Game Boy ROM in SameBoy and Read the Header

801 words

~90 minutes. Download a Game Boy homebrew ROM; boot it in SameBoy; locate and decode the Game Boy cartridge header.


Goal: extend your ROM-format intuition to a second platform. Find and decode the Game Boy header (different from INES but the same idea, a structured prefix that tells the emulator how to interpret the ROM).

Estimated time: 90 minutes

Prerequisites: SameBoy installed (per SETUP.md); week 1-4 NES experience

Steps

Step 1: Download a Game Boy homebrew ROM (20 minutes)

Visit one of:

  • https://itch.io/games/tag-game-boy (filter to free / homebrew)
  • https://gbdev.io/games.html (community-curated list)

Pick a small homebrew Game Boy ROM. Save it to ~/spk-101/roms/gameboy/. The file extension should be .gb (Game Boy) or .gbc (Game Boy Color).

Step 2: Boot the ROM in SameBoy (15 minutes)

Launch SameBoy. File → Open ROM. Load your downloaded .gb file. The game should boot.

Notice the Nintendo logo that appears briefly at boot. This logo is REQUIRED by the Game Boy's boot ROM, Nintendo legendarily used the logo as a copy protection measure (the logo is trademarked; cartridges had to include it to boot; including it without permission was trademark infringement).

Play for ~5 minutes. Take a screenshot.

Step 3: Open the ROM in your hex editor (5 minutes)

Open the same .gb file in your hex editor (HxD / Hex Fiend / Bless / hexedit). Navigate to offset 0x100. This is where the Game Boy cartridge header starts.

The header is 80 bytes long, ending at offset 0x14F. (Bytes 0x150 onward are the actual game code.)

Step 4: Decode the header fields (30 minutes)

Read through the header byte by byte. The Game Boy header layout:

Offset Length Field Meaning
0x100 4 Entry point Usually 00 C3 50 01 (NOP + JP 0x0150, jump past the rest of the header to game code)
0x104 48 Nintendo logo The required Nintendo logo bitmap. Should be exactly CE ED 66 66 CC 0D 00 0B 03 73 00 83 00 0C 00 0D 00 08 11 1F 88 89 00 0E DC CC 6E E6 DD DD D9 99 BB BB 67 63 6E 0E EC CC DD DC 99 9F BB B9 33 3E. ANY different byte here causes the boot ROM to reject the cart. (This was Nintendo's anti-piracy mechanism in 1989)
0x134 16 Title The game's title, in ASCII, NUL-padded
0x143 1 CGB flag 0x80 = Game Boy Color enhanced; 0xC0 = Game Boy Color only; 0x00 = original Game Boy only
0x144 2 New licensee code (Game Boy Color and later) publisher ID
0x146 1 SGB flag Super Game Boy enhanced (0x03) or not (0x00)
0x147 1 Cart type 0x00 = ROM only; 0x01-0x09 = MBC1 mapper; etc.
0x148 1 ROM size 0x00 = 32 KB; 0x01 = 64 KB; 0x02 = 128 KB; etc.
0x149 1 RAM size 0x00 = no RAM; 0x01-0x05 = various RAM sizes
0x14A 1 Destination code 0x00 = Japanese; 0x01 = non-Japanese
0x14B 1 Old licensee code Pre-Game Boy Color publisher ID
0x14C 1 Version Usually 0x00
0x14D 1 Header checksum A checksum that the boot ROM verifies; if wrong the cart will not boot
0x14E 2 Global checksum A 2-byte checksum the boot ROM does NOT verify

Walk through each field for your ROM. Write down values.

Step 5: Verify the Nintendo logo (10 minutes)

Compare the 48 bytes at offset 0x104-0x133 in your ROM against the canonical Nintendo logo bytes listed above. They should match exactly. If they do not match, your ROM should not have booted; check whether you are looking at the right file.

Take a screenshot of your hex editor showing the Nintendo logo bytes.

Step 6: Journal (10 minutes)

Open ~/spk-101/journal/lab-5-1-notes.md. Write:

  • The ROM you used (title, source)
  • Each header field's value
  • The Nintendo logo bytes (or a note that they matched)
  • A reflection: how does the Game Boy header compare to the INES NES header from week 2? Which one feels more sophisticated, and why?
  • Speculation: why might Nintendo have made the logo check a hardware-level boot-ROM feature rather than a software-level emulator concern?

Expected output

  • Game Boy homebrew ROM downloaded and bootable in SameBoy
  • Complete decoded header (all 13 fields)
  • Verified Nintendo logo bytes
  • Journal entry with reflection

Common pitfalls

  • The "title" field shows weird text: it is NUL-padded ASCII. The actual title might be 5 characters padded with 11 zero bytes
  • Header checksum does not appear to match anything visible: the checksum is computed across bytes 0x134-0x14C (inclusive); the algorithm is x = 0; for i = 0x134..0x14C: x = x - rom[i] - 1; result = x & 0xFF. You do not need to verify by hand; just note that the value exists
  • Modern Game Boy Color games have additional header fields: bytes 0x143 + 0x144 may have CGB-specific values you did not expect

Stretch (optional)

  • Try changing the ASCII title (similar to lab 4.2 but on Game Boy). Stay within the 16-byte title length. Reload in SameBoy and confirm the new title (some games display the cartridge title; others don't)
  • Find one other homebrew Game Boy ROM and decode its header. Compare to your first
  • Look up the Nintendo logo at https://gbdev.io/pandocs/The_Cartridge_Header.html#0104-0133--nintendo-logo. The 48 bytes encode a small bitmap of the word "Nintendo"

Lab 5.1 v0.1. Game Boy headers, with extra appreciation for Nintendo's 1989 trademark-as-DRM cleverness.