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:
parent
2c8db472ab
commit
c4f6f3dabe
|
@ -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.
|
@ -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')
|
||||
|
|
|
@ -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++)
|
||||
|
|
Loading…
Reference in New Issue