Files
libretro/exports/rocknix/rocknix-systems
T

243 lines
13 KiB
Python
Executable File

#!/usr/bin/env python
from __future__ import print_function
from hashlib import md5
from os.path import isfile
from collections import OrderedDict
import sys
import zipfile
import xml.etree.ElementTree as elementTree
systems = {
# ---------- Microsoft ---------- #
"xbox": { "name": "Microsoft Xbox", "biosFiles": [ { "md5": "d49c52a4102f6df7bcf8d0617ac475ed", "file": "bios/xemu/bios/mcpx_1.0.bin" },
{ "md5": "21445c6f28fca7285b0f167ea770d1e5", "file": "bios/xemu/bios/Complex_4627v1.03.bin" }] },
# ---------- Nintendo ---------- #
"gamecube": { "name": "Nintendo GameCube", "biosFiles": [ { "md5": "db92574caab77a7ec99d4605fd6f2450", "file": "bios/GC/EUR/IPL.bin" },
{ "md5": "b17148254a5799684c7d783206504926", "file": "bios/GC/JAP/IPL.bin" },
{ "md5": "b17148254a5799684c7d783206504926", "file": "bios/GC/USA/IPL.bin" },
{ "md5": "1f118b8735fcf40c20b38c3184eebfd9", "file": "bios/codehandler.bin", "emulator": "retroarch", "core": "dolphin" } ] },
"nds": { "name": "Nintendo DS", "biosFiles": [ { "md5": "94bc5094607c5e6598d50472c52f27f2", "file": "bios/firmware.bin" },
{ "md5": "df692a80a5b1bc90728bc3dfc76cd948", "file": "bios/bios7.bin" },
{ "md5": "a392174eb3e572fed6447e956bde4b25", "file": "bios/bios9.bin" },
{ "md5": "559dae4ea78eb9d67702c56c1d791e81", "file": "bios/dsi_bios7.bin" },
{ "md5": "87b665fce118f76251271c3732532777", "file": "bios/dsi_bios9.bin" },
{ "md5": "74f23348012d7b3e1cc216c47192ffeb", "file": "bios/dsi_firmware.bin" },
{ "md5": "d71edf897ddd06bf335feeb68edeb272", "file": "bios/dsi_nand.bin" } ] },
"gb": { "name": "Nintendo Gameboy", "biosFiles": [ { "md5": "32fbbd84168d3482956eb3c5051637f5", "file": "bios/gb_bios.bin" } ] },
"gba": { "name": "Nintendo Gameboy Advance", "biosFiles": [ { "md5": "a860e8c0b6d573d191e4ec7db1b1e4f6", "file": "bios/gba_bios.bin" } ] },
"gbc": { "name": "Nintendo Gameboy Color", "biosFiles": [ { "md5": "dbfce9db9deaa2567f6a84fde55f9680", "file": "bios/gbc_bios.bin" } ] },
# ---------- Sega ---------- #
"dreamcast": { "name": "Sega Dreamcast", "biosFiles": [ { "md5": "e10c53c2f8b90bab96ead2d368858623", "file": "bios/dc/dc_boot.bin" },
{ "md5": "0a93f7940c455905bea6e392dfde92a4", "file": "bios/dc/dc_flash.bin" },
{ "md5": "3bffafac42a7767d8dcecf771f5552ba", "file": "bios/dc/naomi_boot.bin" } ] },
"gamegear": { "name": "Sega Game Gear", "biosFiles": [ { "md5": "672e104c3be3a238301aceffc3b23fd6", "file": "bios/bios.gg" } ] },
"mastersystem": { "name": "Sega Master System", "biosFiles": [ { "md5": "840481177270d5642a14ca71ee72844c", "file": "bios/bios.sms" } ] },
"segacd": { "name": "Sega CD", "biosFiles": [ { "md5": "e66fa1dc5820d254611fdcdba0662372", "file": "bios/bios_CD_E.bin" },
{ "md5": "2efd74e3232ff260e371b99f84024f7f", "file": "bios/bios_CD_U.bin" },
{ "md5": "278a9397d192149e84e820ac621a8edd", "file": "bios/bios_CD_J.bin" } ] },
"saturn": { "name": "Sega Saturn", "biosFiles": [ { "md5": "85ec9ca47d8f6807718151cbcca8b964", "file": "bios/sega_101.bin" },
{ "md5": "3240872c70984b6cbfda1586cab68dbe", "file": "bios/mpr-17933.bin" },
{ "md5": "255113ba943c92a54facd25a10fd780c", "file": "bios/mpr-18811-mx.ic1" },
{ "md5": "1cd19988d1d72a3e7caa0b73234c96b4", "file": "bios/mpr-19367-mx.ic1" },
{ "md5": "af5828fdff51384f99b3c4926be27762", "file": "bios/saturn_bios.bin" } ] },
# ---------- Sony ---------- #
"psx": { "name": "PSX", "biosFiles": [ { "md5": "c53ca5908936d412331790f4426c6c33", "file": "bios/psxonpsp660.bin" },
{ "md5": "6e3735ff4c7dc899ee98981385f6f3d0", "file": "bios/scph101.bin" },
{ "md5": "dc2b9bf8da62ec93e868cfd29f0d067d", "file": "bios/scph1001.bin" },
{ "md5": "8dd7d5296a650fac7319bce665a6a53c", "file": "bios/scph5500.bin" },
{ "md5": "490f666e1afb15b7362b406ed1cea246", "file": "bios/scph5501.bin" },
{ "md5": "32736f17079d0b2b7024407c39bd3050", "file": "bios/scph5502.bin" },
{ "md5": "1e68c231d0896b7eadcad1d7d8e76129", "file": "bios/scph7001.bin" } ] },
"ps2": { "name": "PS2", "biosFiles": [ { "md5": "21038400dc633070a78ad53090c53017", "file": "bios/pcsx2/bios/ps2-0230a-20080220.bin" },
{ "md5": "21038400dc633070a78ad53090c53017", "file": "bios/aethersx2/bios/ps2-0230a-20080220.bin" } ] },
"ps3": { "name": "PS3", "biosFiles": [ { "md5": "a2b60b6ac1d2e49e230144345616927c", "file": "bios/PS3UPDAT.PUP" } ] }, #4.93
#"psvita": { "name": "PS Vita", "biosFiles": [ { "md5": "59dcf059d3328fb67be7e51f8aa33418", "file": "bios/psvita/PSP2UPDAT.PUP" },
# { "md5": "f2c7b12fe85496ec88a0391b514d6e3b", "file": "bios/psvita/PSVUPDAT.PUP"} ] },
}
class BiosStatus:
MISSING = "MISSING"
UNTESTED = "UNTESTED"
def md5sum(filename, blocksize=65536):
hash = md5()
with open(filename, "rb") as f:
for block in iter(lambda: f.read(blocksize), b""):
hash.update(block)
return hash.hexdigest()
def checkInsideZip(container, fileName, md5sum):
# Check inside Zip files
try:
archive = zipfile.ZipFile(container)
except Exception as e:
print ('Error opening file {}: {}.'.format(container, e))
return False
blocksize = 1024**2 #1M chunks
for fname in archive.namelist():
# Only check if the file matches
if fname.casefold() == fileName.casefold():
if md5sum == "":
return True
archive = zipfile.ZipFile(container)
blocksize = 1024**2 #1M chunks
for fname in archive.namelist():
if fname == fileName:
entry = archive.open(fname)
zippedHash = md5()
while True:
block = entry.read(blocksize)
if not block:
break
zippedHash.update(block)
if zippedHash.hexdigest() == md5sum:
return True
else:
print('Mismatch inside .zip: File {} in {} has MD5 {} (expected {})'.format(fileName, container, zippedHash.hexdigest(), md5sum))
return False
# File was not found in zip.
print('Missing file inside .zip: File {} not found in {}'.format(fileName, container))
return False
def coreExists(checkMe, emuDict):
if "emulator" in checkMe:
if checkMe["emulator"] in emuDict.keys():
hasEmu = True
else:
hasEmu = False
else:
# Emulator not defined, check BIOS
hasEmu = True
if hasEmu and "core" in checkMe:
if checkMe["core"] in emuDict[checkMe["emulator"]]:
hasCore = True
else:
hasCore = False
else:
# Either core is undefined or emulator is not installed.
# Set core presence to emulator presence, we'll assume there's only one core or it applies to all.
hasCore = hasEmu
return hasCore
def checkBios(systems, prefix, filterROMs):
systemDict = {}
emuDict = {}
systemName = ""
configFile = "/storage/.config/emulationstation/es_systems.cfg"
configData = elementTree.parse(configFile)
configRoot = configData.getroot()
if filterROMs:
# Load systems & emulators from es_systems.cfg
# System full name stored but not currently used, may be useful for the readme function.
for activeSystem in configRoot:
for systemTag in activeSystem:
if systemTag.tag == "fullname":
systemName = systemTag.text
elif systemTag.tag == "name":
systemDict[systemTag.text] = systemName
systemName = ""
elif systemTag.tag == "emulators":
for emulatorTag in systemTag:
emulatorName = emulatorTag.attrib['name']
for coreTag in emulatorTag[0]:
if emulatorName in emuDict.keys():
if not coreTag.text in emuDict[emulatorName]:
emuDict[emulatorName].append(coreTag.text)
else:
emuDict[emulatorName] = [coreTag.text]
else:
for system in systems.keys():
systemDict[system] = systems[system]['name']
missingBios = {}
for system in systems.keys():
if system in systemDict.keys():
if coreExists(systems[system], emuDict) or filterROMs == False:
for file in systems[system]["biosFiles"]:
if coreExists(file, emuDict) or filterROMs == False:
filepath = prefix + "/" + file["file"]
if isfile(filepath):
if not "zippedFile" in file:
md5 = md5sum(filepath)
if md5 != file["md5"] and file["md5"] != "":
if system not in missingBios:
missingBios[system] = {}
missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] }
else:
if 'altmd5' in file:
if not checkInsideZip(filepath, file["zippedFile"], file["md5"], file["altmd5"]):
if system not in missingBios:
missingBios[system] = {}
missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] }
else:
if not checkInsideZip(filepath, file["zippedFile"], file["md5"]):
if system not in missingBios:
missingBios[system] = {}
missingBios[system][file["file"]] = { "status": BiosStatus.UNTESTED, "md5": file["md5"], "file": file["file"] }
else:
if system not in missingBios:
missingBios[system] = {}
missingBios[system][file["file"]] = { "status": BiosStatus.MISSING, "md5": file["md5"], "file": file["file"] }
return missingBios
def displayMissingBios(systems, missingBios):
sortedMissingBios = OrderedDict(sorted(missingBios.items()))
if sortedMissingBios:
for system in sortedMissingBios:
print("> {}".format(system))
for file in sortedMissingBios[system].keys():
md5str = "-"
if sortedMissingBios[system][file]["md5"] != "":
md5str = sortedMissingBios[system][file]["md5"]
print("{} {} {}".format(sortedMissingBios[system][file]["status"], md5str, sortedMissingBios[system][file]["file"]))
else:
print("No missing bios")
def createReadme(systems):
for system in sorted(systems):
print("{}:".format(systems[system]["name"]))
for bios in systems[system]["biosFiles"]:
print("{} {}".format(bios["md5"], bios["file"]))
print("")
if __name__ == '__main__':
if len(sys.argv) == 1:
prefix = "/storage/roms"
displayMissingBios(systems, checkBios(systems, prefix, True))
elif sys.argv[1] == "--noFilter":
prefix = "/storage/roms"
displayMissingBios(systems, checkBios(systems, prefix, False))
elif sys.argv[1] == "--createReadme":
createReadme(systems)
elif len(sys.argv) == 3 and sys.argv[1] == "--filter":
prefix = "/storage/roms"
lowered_name = sys.argv[2].lower()
filtered_systems = {}
for system in systems:
if lowered_name in system.lower() or lowered_name in systems[system]['name'].lower():
filtered_systems[system] = systems[system]
if len(filtered_systems) == 0:
print("No system named {} found".format(sys.argv[2]))
exit(1)
displayMissingBios(filtered_systems, checkBios(filtered_systems, prefix, True))