Created
February 20, 2022 16:13
-
-
Save codeman38/8d3b96f4fffb655293de3aa7ac67650b to your computer and use it in GitHub Desktop.
Decode and display the boot logo in a Game Boy ROM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
# Reads the Nintendo logo from a Game Boy ROM, | |
# pairs up 32-bit DWORDs from each half of the logo, | |
# pairs up nibbles from each half of the DWORD, | |
# then outputs the decoded logo as a readable bitmap. | |
# | |
# codeman38 | |
# original script coded 8 June 2010 | |
# revised 3 July 2011 | |
# cleaned up and updated for Python 3, 20 Feb 2022 | |
import argparse | |
import struct | |
def main(): | |
parser = argparse.ArgumentParser( | |
description='Decodes a Game Boy boot logo in a ROM.') | |
parser.add_argument('filename', | |
help='ROM filename') | |
parser.add_argument('offset', nargs='?', | |
type=int, default=0x184, | |
help='offset to read from (default: %(default)d)') | |
args = parser.parse_args() | |
fp = open(args.filename, 'rb') | |
address = args.offset | |
fp.seek(address) | |
logo = fp.read(0x30) | |
dwords = struct.unpack('>12I',logo) | |
decoded = [decode_dword(d) for d in pair_dwords(dwords)] | |
logo_dec = struct.pack('>12I', *decoded) | |
print_logo(logo_dec) | |
def pair_dwords(dwords): | |
""" | |
Logo is stored as all even-numbered DWORDs followed by | |
all odd-numbered DWORDs. This gets them in the right order. | |
""" | |
for x in range(len(dwords)//2): | |
yield dwords[x] | |
yield dwords[len(dwords)//2 + x] | |
def decode_dword(dword): | |
""" | |
For input nibbles 12345678, output nibbles are 15263748. | |
In other words, pair up nibbles from each half of the DWORD. | |
""" | |
outval = 0 | |
for x in range(3,-1,-1): | |
outval *= 16 | |
outval += (dword>>16+4*x)%16 | |
outval *= 16 | |
outval += (dword>>4*x)%16 | |
return outval | |
def print_logo(logo): | |
lines = ['']*8 | |
for y in range(len(logo)): | |
lines[y%8] += '{0:08b}'.format(logo[y]) | |
for y in lines: | |
print(y.replace('0',' ').replace('1','#')) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment