-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnointro-sort.py
executable file
·113 lines (89 loc) · 2.89 KB
/
nointro-sort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python
##
## nointro-sort.py by Naomi Peori <[email protected]>
## Sort roms using NoIntro-compatible datfiles.
##
import os
import sys
import binascii
import zipfile
import xml.etree.ElementTree as ET
import shutil
import multiprocessing
##
## Configuration
##
datfolder = "00_DATFILES"
offsets = { 'a78':128, 'lnx':64, 'nes': 16 }
##
## Check the arguments.
##
if len(sys.argv) < 2:
print "Usage:", sys.argv[0], "<source>"
sys.exit()
source = sys.argv[1]
if not os.path.isdir(source):
print "ERROR: Source directory doesn't exist:", source
sys.exit()
##
## Load the datfiles.
##
roms = {}
for dirname, subdirectories, filenames in os.walk(datfolder):
for datfile in filenames:
if datfile.endswith(".dat"):
print datfile
tree = ET.parse(datfolder + "/" + datfile)
root = tree.getroot()
for game in root.findall('game') + root.findall('machine'):
gamename = game.get('name')
for rom in game.findall('rom'):
if not rom.get('merge') and not rom.get('status') == "nodump":
romname = rom.get('name')
size = int(rom.get('size')) if rom.get('size') else 0
crc = int(rom.get('crc'),16) if rom.get('crc') else 0
filename = datfile[:-4] + "/" + gamename + ".zip"
if not size in roms:
roms[size] = {}
if not crc in roms[size]:
roms[size][crc] = []
roms[size][crc].append({'filename': filename, 'romname': romname})
##
## Functions
##
def scanDirectory(directory):
if os.path.isdir(directory):
for dirname, subdirectories, filenames in os.walk(directory):
[pool.apply_async(scanFile, args=(dirname + "/" + filename,)) for filename in filenames]
def scanFile(filename):
if filename.endswith(".zip"):
print filename
with zipfile.ZipFile(filename, mode="r", allowZip64=True) as file:
for info in file.infolist():
data = file.read(info.filename)
extension = info.filename[-3:]
offset = offsets[extension] if extension in offsets else 0
crc = info.CRC if offset == 0 else binascii.crc32(data[offset:]) & 0xFFFFFFFF
size = info.file_size - offset
matchFile(size, crc, data)
def matchFile(size, crc, data):
if size in roms:
if crc in roms[size]:
for rom in roms[size][crc]:
writeFile(rom['filename'],rom['romname'], data)
def writeFile(filename, romname, data):
if not os.path.isfile(filename):
directory = os.path.dirname(filename)
if not os.path.isdir(directory):
os.makedirs(os.path.dirname(filename))
with zipfile.ZipFile(filename, mode="a", compression=zipfile.ZIP_DEFLATED, allowZip64=True) as file:
if not romname in file.namelist():
print " " + filename + " " + romname
file.writestr(romname, data);
##
## Main Program
##
pool = multiprocessing.Pool(4)
scanDirectory(source)
pool.close()
pool.join()