-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsetup.py
111 lines (76 loc) · 2.95 KB
/
setup.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
from pathlib import Path
import shutil
import subprocess
import sys
import zlib
import ndspy.code
import ndspy.fnt
import ndspy.rom
VALID_ROM_CRC = 0x197576a
MODULE_PATH = Path(__file__).parent
def apply_xdelta(original: Path, delta: Path, out: Path) -> None:
"""
Apply an xdelta3 patch
"""
if sys.platform == 'win32':
xdelta_path = MODULE_PATH / 'xdelta3'
else:
xdelta_path = 'xdelta3'
subprocess.call([str(xdelta_path), '-d', '-f', '-s', str(original), str(delta), str(out)])
def main():
if len(sys.argv) != 2:
print(f'Usage: {sys.argv[0]} <rom path>')
return
# Open / check rom
rom_path = Path(sys.argv[1]).resolve()
with open(rom_path, 'rb') as f:
rom_data = f.read()
if zlib.crc32(rom_data) != VALID_ROM_CRC:
print('ROM is invalid!')
return
# Create a temporary "original" folder
original_path = MODULE_PATH / 'original'
original_path.mkdir(exist_ok=True)
rom = ndspy.rom.NintendoDSRom(rom_data)
(original_path / 'arm9.bin').write_bytes(rom.arm9)
(original_path / 'arm9ovt.bin').write_bytes(rom.arm9OverlayTable)
(original_path / 'arm7.bin').write_bytes(rom.arm7)
(original_path / 'arm7ovt.bin').write_bytes(rom.arm7OverlayTable)
(original_path / 'fnt.bin').write_bytes(ndspy.fnt.save(rom.filenames))
(original_path / 'header.bin').write_bytes(rom_data[:512])
(original_path / 'overlay9').mkdir(exist_ok=True)
(original_path / 'overlay7').mkdir(exist_ok=True)
for id, overlay in rom.loadArm9Overlays().items():
(original_path / 'overlay9' / f'overlay9_{id}.bin').write_bytes(overlay.data)
# Apply xdelta patches to things in the "original" folder
files_to_xdelta_patch = [
'arm9.bin',
'arm9ovt.bin',
'arm7.bin',
'header.bin',
*(f'overlay9/overlay9_{i}.bin' for i in range(0, 131)),
]
for f in files_to_xdelta_patch:
if not (original_path / f).is_file():
raise RuntimeError(f"File should exist but doesn't: {f}")
(MODULE_PATH / 'Assembly' / 'original' / 'overlay9').mkdir(exist_ok=True)
(MODULE_PATH / 'Assembly' / 'original' / 'overlay7').mkdir(exist_ok=True)
for f in files_to_xdelta_patch:
print(f)
orig = original_path / f
delta = MODULE_PATH / 'patches' / (f + '.xdelta3')
out = MODULE_PATH / 'Assembly' / 'original' / f
apply_xdelta(orig, delta, out)
# A few other things
(MODULE_PATH / 'Assembly' / 'original' / 'arm7ovt.bin').write_bytes(b'')
shutil.copy(
MODULE_PATH / 'patches' / 'fnt.bin',
MODULE_PATH / 'Assembly' / 'original' / 'fnt.bin')
apply_xdelta(
rom_path,
MODULE_PATH / 'patches' / 'Newer Super Mario Bros. DS.nds.xdelta3',
MODULE_PATH / 'Assembly' / 'Newer Super Mario Bros. DS.nds')
print('Newer Super Mario Bros. DS.nds')
# Delete "original" folder
shutil.rmtree(original_path, ignore_errors=True)
main()