diff options
| author | Myrika Fuwa | 2022-01-16 21:01:09 -0500 |
|---|---|---|
| committer | Myrika Fuwa | 2022-01-16 21:01:09 -0500 |
| commit | 6b23ebc7d3c7da68e008adfa9a129e0f727aa53d (patch) | |
| tree | 569ea69de5dfc2c5e00099cdb7727336dddbc5d7 | |
| download | datsum-master.tar.gz datsum-master.zip | |
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | dat.py | 132 | ||||
| -rwxr-xr-x | datrom | 54 | ||||
| -rwxr-xr-x | datsum | 45 |
4 files changed, 234 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..14499ad --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +__init__.py +__pycache__ +test/ @@ -0,0 +1,132 @@ +# vim: set encoding=utf-8 noet ts=4 +# TODO: Better recursive multi-track (bin+cue) support +# TODO: ClrMamePro, ListXML, RomCenter + +"""Parse DAT files for ROM management.""" + +import xml.etree.ElementTree as ET +from pathlib import Path + +class DAT: + """ + DAT (ROM Management Datafile). + """ + header = {} + name = "" + sums = [] + + def csv(self): + """ + Print CRC-32 to csv4 (Comma Seperated Value) format. + """ + + for i in self.sums: + try: + path, name = i["name"].split("/") + except ValueError: + name = i["name"] + path = "" + + print("\"{0}\",{1},{2},\"{3}\",".format( + name, i["size"], i["crc"], path + )) + + def name(self, crc, size): + """ + Get rom name from crc+size. + """ + + for i in self.sums: + if i["crc"] == crc and i["size"] == size: + return i["name"] + + def md5sum(self): + """ + Print MD5 to md5sum (GNU coreutils) format. + """ + + for i in self.sums: + print("{0} {1}/{2}".format(i["md5"], self.name, i["name"])) + + def sfv(self): + """ + Print CRC-32 to SFV (Simple File Verification) format. + """ + + print(";\n; DAT file converted by datsum") + print(";\n; Name: {0}".format(self.header["name"])) + print("; Version: {0}".format(self.header["version"])) + print("; Website: {0}\n;".format(self.header["url"])) + + for i in self.sums: + print("{0}/{1} {2}".format(self.name, i["name"], i["crc"])) + + def sha1sum(self): + """ + Print SHA1 to sha1sum (GNU coreutils) format. + """ + + for i in self.sums: + print("{0} {1}/{2}".format(i["sha1"], self.name, i["name"])) + +class ClrMamePro: + """ + ClrMamePro format. + """ + + pass + +class ListXML: + """ + MAME List XML format. + """ + + pass + +class RomCenter: + """ + RomCenter format. + """ + + pass + +class GenericXML(DAT): + """ + Logiqx generic XML format. + """ + + def __init__(self, datafile): + """ + Parse DAT file. + """ + + self.name = Path(datafile).stem + + tree = ET.parse(datafile) + root = tree.getroot() + + for header in root.findall('header'): + self.header = { + "name": header.find('name').text, + "description": header.find('description').text, + "version": header.find('version').text, + "author": header.find('author').text, + "homepage": header.find('homepage').text, + "url": header.find('url').text + } + + for game in root.iter('game'): + count = sum(1 for _ in game.iter('rom')) + directory = "" + + if count > 1: + directory = "{0}/".format(game.get('name')) + + for rom in game.iter('rom'): + self.sums.append({ + "crc": str(rom.get('crc').lower()), + "md5": str(rom.get('md5').lower()), + "name": str(directory + rom.get('name')), + "size": int(rom.get('size')), + "sha1": str(rom.get('sha1').lower()) + }) @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 noet ts=4 +# TODO: NES headers + +"""Identify ROM with DAT file.""" + +import binascii, os, sys +from dat import DAT + +def identify(datafile, romfile): + """ + ROM file to identify. + """ + with open(romfile,'rb') as f: + crc = "{:08x}".format(binascii.crc32(f.read())) + print("CRC: {0}".format(crc)) + + size = os.path.getsize(romfile) + print("Size: {0}".format(size)) + + dat = DAT(datafile) + name = dat.name(crc, size) + print("Name: {0}".format(name)) + return name + +def rename(romfile, name): + """ + Rename ROM file from name in DAT. + """ + romfile = os.path.abspath(romfile) + name = os.path.join(os.path.dirname(romfile), name) + os.rename(romfile, name) + print("\nSource: {0}\nDestination: {1}".format(romfile, name)) + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser(add_help=False, description=__doc__) + + parser.add_argument('DAT', help=DAT.__doc__) + parser.add_argument('ROM', help=identify.__doc__) + + parser.add_argument( + '-h', '--help', action='help', default=argparse.SUPPRESS, + help='Show this help message and exit.' + ) + parser.add_argument( + '-r', '--rename', action='store_true', + help=rename.__doc__ + ) + + args = parser.parse_args() + name = identify(args.DAT, args.ROM) + if args.rename: + rename(args.ROM, name) @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 noet ts=4 +# TODO: DAT format detection. + +"""Convert DAT file to hash sums.""" + +import argparse, os, signal, sys +from dat import DAT, GenericXML + +if __name__ == '__main__': + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + + parser = argparse.ArgumentParser(add_help=False, description=__doc__) + parser.add_argument('DAT', help=DAT.__doc__) + parser.add_argument( + '-h', '--help', action='help', default=argparse.SUPPRESS, + help='Show this help message and exit.' + ) + + fmt = parser.add_argument_group('hash arguments') + fmtgrp = fmt.add_mutually_exclusive_group(required=True) + fmtgrp.add_argument( + '-c' , '--csv4', action='store_true', help=DAT.csv.__doc__ + ) + fmtgrp.add_argument( + '-C' , '--sfv', action='store_true', help=DAT.sfv.__doc__ + ) + fmtgrp.add_argument( + '-H' , '--sha1', action='store_true', help=DAT.sha1sum.__doc__ + ) + fmtgrp.add_argument( + '-M' , '--md5', action='store_true', help=DAT.md5sum.__doc__ + ) + + args = parser.parse_args() + dat = GenericXML(args.DAT) + + if args.csv4: + dat.csv() + elif args.md5: + dat.md5sum() + elif args.sfv: + dat.sfv() + elif args.sha1: + dat.sha1sum() |
