You've already forked firmware
mirror of
https://github.com/FlipperMCE/firmware.git
synced 2026-02-16 16:55:36 -08:00
164 lines
4.5 KiB
Python
164 lines
4.5 KiB
Python
import os
|
|
|
|
replacer = r'\((.*)\)'
|
|
|
|
class GameId:
|
|
name = ""
|
|
id = ""
|
|
region = ""
|
|
def __init__(self, name, id):
|
|
self.name = name
|
|
self.id = id
|
|
parts = id.strip().split("-")
|
|
if parts and len(parts) > 2:
|
|
self.id = parts[2]
|
|
if len(parts[-1]) < 3:
|
|
self.region = parts[-2]
|
|
else:
|
|
self.region = parts[-1]
|
|
self.region = re.sub(replacer, "", self.region).strip()
|
|
|
|
def __str__(self):
|
|
return "Id " + self.id + " Name " + self.name + " Region " + self.region
|
|
|
|
def __lt__(self, o):
|
|
return self.name < o.name
|
|
|
|
|
|
def getFileName(rootdir):
|
|
regex = re.compile('(.*dat$)')
|
|
filename = None
|
|
|
|
for root, dirs, files in os.walk(rootdir):
|
|
for file in files:
|
|
if regex.match(file):
|
|
filename = "{}/{}".format(root, file)
|
|
return filename
|
|
|
|
def parseGameEntry(element):
|
|
name = element.attrib["name"]
|
|
serials = element.findall("serial")
|
|
game_serials = []
|
|
if serials and serials[0].text:
|
|
for s in serials[0].text.split(","):
|
|
if len(s.strip()) > 0:
|
|
game_serials.append(s.strip())
|
|
|
|
|
|
return (name, game_serials)
|
|
|
|
def createGameList(name_to_serials):
|
|
|
|
gamenames_full = list(name_to_serials.keys())
|
|
gamenames_full.sort()
|
|
|
|
gameList = []
|
|
|
|
# Try to figure out multi disc games by game name
|
|
parent_serials = {}
|
|
for game in gamenames_full:
|
|
for serial in name_to_serials[game]:
|
|
gameName = re.sub(replacer, "", game).strip()
|
|
game_item = GameId(gameName, serial)
|
|
gameList.append(game_item)
|
|
return gameList
|
|
|
|
import xml.etree.ElementTree as ET
|
|
import re
|
|
|
|
def createDbFile(rootdir, outputdir):
|
|
dirname = rootdir.split("/")[-1]
|
|
if len(dirname) < 1:
|
|
dirname = rootdir.split("/")[-2]
|
|
|
|
tree = ET.parse(getFileName(rootdir))
|
|
|
|
root = tree.getroot()
|
|
|
|
name_to_serials = {}
|
|
|
|
regions = []
|
|
|
|
# Create Mapping from serial to full game name
|
|
for element in root:
|
|
if element.tag == 'game':
|
|
name, serials = parseGameEntry(element)
|
|
if len(serials) < 1:
|
|
continue
|
|
name_to_serials[name] = serials
|
|
|
|
|
|
redump_games = createGameList(name_to_serials)
|
|
|
|
gamenames = []
|
|
games_sorted = {}
|
|
|
|
|
|
# Create Prefix list and game name list
|
|
# Create dict that contains all games sorted by prefix
|
|
for game in redump_games:
|
|
if game.name not in gamenames:
|
|
gamenames.append(game.name)
|
|
games_sorted[game.id] = game
|
|
|
|
|
|
print("Redump {} Game Names".format(len(gamenames)))
|
|
print("Redump {} Games".format(len(redump_games)))
|
|
|
|
redump_games.sort()
|
|
term = 0
|
|
|
|
game_ids_offset = 0
|
|
game_names_base_offset = 0 + (len(games_sorted) * 12) + 12
|
|
|
|
offset = game_names_base_offset
|
|
game_name_to_offset = {}
|
|
print(f"Offset Base {hex(offset)}")
|
|
|
|
# Calculate offset for each game name
|
|
for gamename in gamenames:
|
|
if gamename not in game_name_to_offset:
|
|
game_name_to_offset[gamename] = offset
|
|
offset = offset + len(gamename) + 1
|
|
|
|
with open("{}/gamedbgc.dat".format(outputdir), "wb") as out:
|
|
|
|
# Next: write game entries for each index in the format:
|
|
# 4 Byte: Game ID without prefix, Big Endian
|
|
# 4 Byte: Offset to game name, Big Endian
|
|
# 4 Byte: Parent Game ID - if multi disc this is equal to Game ID
|
|
for id in games_sorted:
|
|
game = games_sorted[id]
|
|
out.write(game.id.encode('ascii'))
|
|
out.write(game_name_to_offset[game.name].to_bytes(4, 'big'))
|
|
out.write(game.region.encode('ascii'))
|
|
out.write(int(0).to_bytes(1, 'big'))
|
|
# print("Game Name: {} Offset: {}".format(game.name, game_name_to_offset[game.name]))
|
|
|
|
out.write(term.to_bytes(12, 'big'))
|
|
# Last: write null terminated game names
|
|
for game in game_name_to_offset:
|
|
out.write(game.encode('ascii'))
|
|
out.write(term.to_bytes(1, 'big'))
|
|
|
|
|
|
from urllib.request import urlopen
|
|
from io import BytesIO
|
|
from zipfile import ZipFile
|
|
|
|
|
|
def downloadDat(path):
|
|
url = "http://redump.org/datfile/gc/serial"
|
|
http_response = urlopen(url)
|
|
zipfile = ZipFile(BytesIO(http_response.read()))
|
|
zipfile.extractall(path=path)
|
|
|
|
import argparse
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("dirname")
|
|
parser.add_argument("outputdir")
|
|
args = parser.parse_args()
|
|
|
|
downloadDat(args.dirname)
|
|
|
|
createDbFile(args.dirname, args.outputdir) |