open_agb_firm gba_db.bin Builder v2.0 and other changes

open_agb_firm gba_db.bin Builder:
* Updated to v2.0
* No-Intro DAT support
* Additional entry support
* Entries added/skipped are now output
* Other optimizations

Other changes:
* Remove most overrides in `open_agb_firm.c` to prepare for gba_db.bin
* Add `resources/gba.dat` entry to gitignore
This commit is contained in:
Harrison 2021-02-22 21:26:08 -05:00 committed by profi200
parent 2c8db472ab
commit c4f6f3dabe
4 changed files with 77 additions and 51 deletions

1
.gitignore vendored
View File

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

Binary file not shown.

View File

@ -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')

View File

@ -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++)