-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathverify_main_dol.py
111 lines (95 loc) · 3.34 KB
/
verify_main_dol.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
"""
Script to verify the target main.dol for authenticity.
"""
import argparse
from colorama import Fore, Style
from pathlib import Path
import sys
from mkwutil.lib.dol import DolBinary
from mkwutil.lib.verify_binary import *
from mkwutil.project import *
from mkwutil.sections import DOL_SECTIONS
# https://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
def verify_dol(reference: Path, target: Path):
"""Verifies the target main.dol for authenticity."""
print("[DOL] Verifying...")
content = open(target, "rb").read()
if check_hash(content, "ac7d72448630ade7655fc8bc5fd7a6543cb53a49"):
print(
Fore.GREEN
+ Style.BRIGHT
+ "[DOL] Everything went okay! Output is matching! ^^"
+ Style.RESET_ALL
)
return
want_len = 2766496
if len(content) != want_len:
print(
(Fore.RED + "Mismatched file size: Got %d (%+d)" + Style.RESET_ALL)
% (len(content), len(content) - want_len)
)
with open(reference, "rb") as file:
good = DolBinary(file)
with open(target, "rb") as file:
bad = DolBinary(file)
for i in range(0, DolBinary.SEGMENT_COUNT):
good_segment = good.segments[i]
bad_segment = bad.segments[i]
if len(good_segment) == 0:
continue
match = good_segment.data == bad_segment.data
tag = "OK" if match else "FAIL"
if good_segment is not None and len(good_segment) != len(bad_segment):
tag = "SIZE"
print(
format_segment(
good_segment.name(),
good_segment.start,
bad_segment.start,
len(good_segment),
len(bad_segment),
tag,
)
)
if not match:
slices = load_dol_slices(sections=DOL_SECTIONS)
amount_printed = 0
for vaddr in range(min(good_segment.start, bad_segment.start), max(good_segment.stop, bad_segment.stop), 4):
good_bytes = good.virtual_read_word(vaddr)
bad_bytes = bad.virtual_read_word(vaddr)
if good_bytes == bad_bytes or amount_printed > 10:
continue
print("%x: Good=%x Bad=%x" % (vaddr, good_bytes, bad_bytes))
slice_it, slice_i = slices.find(vaddr)
if slice_it:
print(" -> This is in %s" % slice_it)
amount_printed += 1
print(
format_segment(
"bss",
good.bss.start,
bad.bss.stop,
len(good.bss),
len(bad.bss),
"OK" if len(good.bss) == len(bad.bss) else "SIZE",
)
)
# TODO: Add diff'ing
print(
Fore.RED + Style.BRIGHT + "[DOL] Oof: Output doesn't match." + Style.RESET_ALL
)
sys.exit(1)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--reference", type=Path, required=True, help="Path to reference main.dol"
)
parser.add_argument(
"--target", type=Path, required=True, help="Path to target main.dol"
)
args = parser.parse_args()
verify_dol(args.reference, args.target)