-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcreate.py
187 lines (158 loc) · 6.36 KB
/
create.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
from pathlib import Path
import pickle
import re
import subprocess
py_command = 'python'
def get_global_paths():
global nsps, base, updates, dlc, output
changed = False
try:
with open('path.pickle', 'r+b') as file:
nsps = pickle.load(file)
output = pickle.load(file)
except (FileNotFoundError, AttributeError):
nsps = Path(input('Enter NSPs Directory: '))
output = input('Enter Output Directory: ')
# Squirrel -o cannot handle a trailing slash
# pathlib does not handle trailing slash from an input, but will handle it if passed later.
output = Path(output)
changed = True
while True:
base = nsps / 'base'
updates = nsps / 'updates'
dlc = nsps / 'dlc'
if not base.exists() or not dlc.exists():
changed = True
print('Could not locate subdirectories.')
print(f'Tried paths were:\n{base}\n{updates}\n{dlc}')
nsps = Path(input('Enter nsps Directory: '))
if not updates.exists() and base.exists() and dlc.exists():
updates = nsps / 'updates (1)'
if not updates.exists():
print(f'base and dlc sub-folders found, updates sub-folder not found, '
f'nor was hbg meme of updates (1) sub-folder')
nsps = Path(input('Enter nsps Directory: '))
if base.exists() and dlc.exists() and updates.exists():
break
if changed:
with open('path.pickle', 'wb') as file:
pickle.dump(nsps, file)
pickle.dump(output, file)
return
def create_database():
database = {}
for file in base.glob('*.nsp'):
title_id = re.findall(r'\[0100[a-zA-Z0-9]{12}]', str(file))
if len(title_id) == 0:
print(f'Error on {file}\n'
f'No title id found, ignoring base file.')
elif len(title_id) > 1:
print(f'Error on {file}\n'
f'{title_id[0]} and {title_id[1]} found\n'
f'Unable to determine correct title id, ignoring base file')
else:
database.update({title_id[0][1:-5]: [file]})
for file in updates.glob('*.nsp'):
title_id = re.findall(r'\[0100[a-zA-Z0-9]{12}]', str(file))
if len(title_id) == 1 and title_id[0][1:-5] in database:
database[title_id[0][1:-5]].append(file)
for file in dlc.glob('*.nsp'):
title_id = re.findall(r'\[0100[a-zA-Z0-9]{12}]', str(file))
if len(title_id) == 1 and title_id[0][1:-5] in database:
database[title_id[0][1:-5]].append(file)
return database
def load_database():
skip = 0
old_database = {}
try:
with open('database.pickle', 'rb') as db:
old_database = pickle.load(db)
except (FileNotFoundError, EOFError):
print('No database found')
while True:
skip = input('Enter 0 to start from scratch and create all XCIs\n'
'Enter 1 to create a complete database and no XCIs\n\n'
'Input : ')
if skip not in ['0', '1']:
print(f'{skip} is not an accepted answer')
else:
break
return old_database, skip
def save_database(title_id, paths, old_database):
with open('database.pickle', 'wb') as db:
old_database[title_id] = paths
pickle.dump(old_database, db)
def create_xci(title_id, paths):
string = ''
for path in paths:
string += path.as_posix() + '\n'
with open('multi.txt', 'w+', encoding='utf-8') as multi:
multi.write(string)
number_of_updates = number_of_dlc = name = 0
for path in paths:
if path.parent == base:
name = path.stem
if path.parent == updates:
number_of_updates += 1
name = path.stem
name = re.sub(title_id + r'([a-zA-Z0-9])(800])', title_id + r'\g<1>000]', name)
if path.parent == dlc:
number_of_dlc += 1
if number_of_updates > 0 or number_of_dlc > 0:
name += f' (1G'
if number_of_updates > 0:
name += f'+{number_of_updates}U'
if number_of_dlc > 0:
name += f'+{number_of_dlc}D'
name += ')'
root = Path.cwd()
squirrel = subprocess.Popen(f'{py_command} "{root / "ztools/squirrel.py"}" '
f'-o "{output}" '
f'-dmul "file" '
f'-tfile "{root / "multi.txt"}" '
f'-t xci',
shell=True, stdout=subprocess.PIPE).stdout.read()
nscb_xci = output / f'file[nscb].xci'
if b"Exception" in squirrel:
nscb_xci.unlink()
print(f'Failed to create xci for {title_id}')
print('The following is the output from NSCB as to why it failed:')
print(squirrel)
passed = False
else:
custom_xci = output / f'{name}.xci'
try:
nscb_xci.replace(custom_xci)
print(f'Created {custom_xci}')
print(f'This has the following files in it:\n{string}')
passed = True
except FileNotFoundError:
print(f'Failed to create xci for {title_id}')
print('PATHs messed up?')
print('Python command not found?')
print('Most likely not a NSCB failure, but its output below anyways')
print(squirrel)
passed = False
return passed
def delete_old_xci(title_id):
for file in output.glob('*.xci'):
if re.search(r'\[' + title_id + '[a-zA-Z0-9]{4}]', str(file)):
print(f'Deleted old file : {file}')
file.unlink()
break
def main():
get_global_paths()
old_database, skip = load_database()
database = create_database()
if skip == '1':
with open('database.pickle', 'wb') as db:
pickle.dump(database, db)
else:
for title_id, paths in database.items():
if paths != old_database.get(title_id):
delete_old_xci(title_id)
passed = create_xci(title_id, paths)
if passed:
save_database(title_id, paths, old_database)
print('Done')
main()