diff --git a/.gitignore b/.gitignore index e7e07d9..3d7709e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ arm9/open_agb_firm9.bin arm11/open_agb_firm11.bin arm9/open_agb_firm9.elf arm11/open_agb_firm11.elf +resources/gba.dat resources/gba.xml open_agb_firm.firm open_agb_firm*.7z diff --git a/resources/gba_db.bin b/resources/gba_db.bin index e534ab2..d3b2926 100644 Binary files a/resources/gba_db.bin and b/resources/gba_db.bin differ diff --git a/resources/gba_db_builder.py b/resources/gba_db_builder.py index 12e8607..7f8ca36 100644 --- a/resources/gba_db_builder.py +++ b/resources/gba_db_builder.py @@ -1,69 +1,78 @@ -# open_agb_firm gba_db.bin Builder v1.2 +# open_agb_firm gba_db.bin Builder v2.0 # By HTV04 - +# # This script parses MAME's gba.xml (found here: https://github.com/mamedev/mame/blob/master/hash/gba.xml) and converts it to a gba_db.bin file for open_agb_firm. -# This script should work with any updates to MAME's gba.xml, unless something this script expects is changed. +# No-Intro's GBA DAT is also used for filtering and naming (found here: https://datomatic.no-intro.org/). The DAT should be renamed to "gba.dat". +# +# This script should work with any updates to MAME's gba.xml and the No-Intro DAT, unless something this script expects is changed. import math import xml.etree.ElementTree as ET -# Use title, title ID, SHA-1, size, and save type to generate gba_db entry as binary string -def gbadbentry(title, titleid, sha, size, savetype): +# Use title, serial, SHA-1, size, and save type to generate gba_db entry as binary string +def gbadbentry(title, serial, sha, size, savetype): entry = b'' - entry += title.encode().ljust(200, b'\x00') # Pad to 200 bytes with null bytes - entry += titleid.encode() - entry += bytes.fromhex(sha) + entry += title.encode().ljust(200, b'\x00') + entry += serial.encode().ljust(4, b'\x00') + entry += bytes.fromhex(sha).ljust(20, b'\x00') entry += (int(math.log(size, 2)) << 27 | savetype).to_bytes(4, 'little') # Save type is stored weirdly - return entry # Entry size is 228 bytes in length + return entry # Entry size is 228 bytes total if __name__ == '__main__': - root = ET.parse('gba.xml').getroot() - gbadb = b'' + skipcount = 0 + count = 0 + addcount = 0 - for software in root.findall('software'): - # Obtain title - title = software.find('description').text - - # Obtain title ID - titleid = '\x00\x00\x00\x00' # If a title ID can't be found, default to null bytes - for info in software.findall('info'): - if info.get('name') == 'serial': - for i in info.get('value').split('-'): # Hacky script that checks for the first part of the serial that has 4 characters, since serials vary - s = i.strip() - if len(s) == 4: - titleid = s + gba = ET.parse('gba.xml').getroot() # MAME gba.xml + nointro = ET.parse('gba.dat').getroot() # No-Intro GBA DAT + + addentries = False # Determine whether to include additional entries + + # Start adding entries + for software in gba.findall('software'): + for part in software.findall('part'): + if part.get('name') == 'cart': + # Obtain CRC32 for No-Intro DAT matching + for dataarea in part.findall('dataarea'): + if dataarea.get('name') == 'rom': + crc = dataarea.find('rom').get('crc') break - break - - for part in software.findall('part'): - if part.get('name') == 'cart': - # Obtain SHA-1 - for dataarea in part.findall('dataarea'): - if dataarea.get('name') == 'rom': - size = int(dataarea.get('size'), 0) # Base 0 so int can decide whether string is decimal or hex - - sha = dataarea.find('rom').get('sha1') - - break + # Obtain title, serial, SHA-1, and size from No-Intro DAT + matchfound = False + for game in nointro.findall('game'): + for rom in game.findall('rom'): + if rom.get('crc') == crc.upper(): + matchfound = True + + title = game.get('name') + serial = rom.get('serial') + if serial in (None, 'N/A'): + serial = '\x00\x00\x00\x00' # If a serial can't be found, default to null bytes + sha = rom.get('sha1') + size = int(rom.get('size')) + + # If not in No-Intro DAT, skip entry + if matchfound == False: + break # Obtain save type savetype = 15 # If a save type can't be found or is unknown, set to "SAVE_TYPE_NONE" for feature in part.findall('feature'): if feature.get('name') == 'slot': slottype = feature.get('value') - if slottype == 'gba_eeprom_4k': + if slottype in ('gba_eeprom', 'gba_eeprom_4k'): savetype = 0 # SAVE_TYPE_EEPROM_8k - if size > 16777216: # If greater than 16 MB, change save type + if size > 0x1000000: # If greater than 16 MB, change save type savetype += 1 # SAVE_TYPE_EEPROM_8k_2 elif slottype == 'gba_eeprom_64k': savetype = 2 # SAVE_TYPE_EEPROM_64k - if size > 16777216: # If greater than 16 MB, change save type + if size > 0x1000000: # If greater than 16 MB, change save type savetype += 1 # SAVE_TYPE_EEPROM_64k_2 elif slottype == 'gba_flash_rtc': savetype = 8 # SAVE_TYPE_FLASH_512k_PSC_RTC @@ -78,9 +87,36 @@ if __name__ == '__main__': break + # If not in No-Intro DAT, skip entry + if matchfound == False: + print ('Skipped "' + software.find('description').text + '"') + skipcount += 1 + + continue + # Expand gba_db with entry - gbadb += gbadbentry(title, titleid, sha, size, savetype) + gbadb += gbadbentry(title, serial, sha, size, savetype) + + print('Added entry "' + software.find('description').text + '"') + count += 1 + + # Add additional entries + if addentries == True: + gbadbentries = ([['Example Game', 'WIP', '', 0x1000000, 14]]) + + print() + + for title, serial, sha, size, savetype in gbadbentries: + gbadb += gbadbentry(title, serial, sha, size, savetype) + + print('Added additional entry "' + title + '"') + addcount += 1 # Create and write to gba_db.bin with open('gba_db.bin', 'wb') as f: f.write(gbadb) + +if addentries == True: + print('\n' + str(count) + ' entries added, ' + str(addcount) + ' additional entries added, ' + str(skipcount) + ' entries skipped') +else: + print('\n' + str(count) + ' entries added, ' + str(skipcount) + ' entries skipped') diff --git a/source/arm11/open_agb_firm.c b/source/arm11/open_agb_firm.c index 4b03d5a..025c40b 100644 --- a/source/arm11/open_agb_firm.c +++ b/source/arm11/open_agb_firm.c @@ -216,19 +216,8 @@ static u16 checkSaveOverride(u32 gameCode) // Generalizations {"\0\0\0\0", SAVE_TYPE_SRAM_256k}, // Homebrew (TODO: Set WAITCNT to 0x4014?) - // Games - {"BTA\0", SAVE_TYPE_EEPROM_64k}, // Astro Boy - Omega Factor - {"B2D\0", SAVE_TYPE_EEPROM_64k}, // Donkey Kong Country 2 - {"AZL\0", SAVE_TYPE_EEPROM_64k}, // Legend of Zelda, The - A Link to the Past & Four Swords - {"A88\0", SAVE_TYPE_EEPROM_64k}, // Mario & Luigi - Superstar Saga - {"B8M\0", SAVE_TYPE_EEPROM_64k}, // Mario Party Advance - {"A6M\0", SAVE_TYPE_EEPROM_64k}, // Mega Man & Bass - {"BIJE", SAVE_TYPE_EEPROM_64k}, // Sonic The Hedgehog - Genesis - {"AA2\0", SAVE_TYPE_EEPROM_64k}, // Super Mario Advance 2 - {"A3A\0", SAVE_TYPE_EEPROM_64k}, // Super Mario Advance 3 - // Homebrew - {"GMB\0", SAVE_TYPE_SRAM_256k}, // Goomba Color (Homebrew) + {"GMB\0", SAVE_TYPE_SRAM_256k}, // Goomba Color }; for(u32 i = 0; i < sizeof(overrideLut) / sizeof(*overrideLut); i++)