summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMyrika Fuwa2022-01-16 21:01:09 -0500
committerMyrika Fuwa2022-01-16 21:01:09 -0500
commit6b23ebc7d3c7da68e008adfa9a129e0f727aa53d (patch)
tree569ea69de5dfc2c5e00099cdb7727336dddbc5d7
downloaddatsum-master.tar.gz
datsum-master.zip
Initial commitHEADmaster
-rw-r--r--.gitignore3
-rw-r--r--dat.py132
-rwxr-xr-xdatrom54
-rwxr-xr-xdatsum45
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/
diff --git a/dat.py b/dat.py
new file mode 100644
index 0000000..f93c1a8
--- /dev/null
+++ b/dat.py
@@ -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())
+ })
diff --git a/datrom b/datrom
new file mode 100755
index 0000000..052542b
--- /dev/null
+++ b/datrom
@@ -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)
diff --git a/datsum b/datsum
new file mode 100755
index 0000000..97ae646
--- /dev/null
+++ b/datsum
@@ -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()