-
Notifications
You must be signed in to change notification settings - Fork 4
/
find_offsets.py
executable file
·146 lines (119 loc) · 5.53 KB
/
find_offsets.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
#!/usr/bin/env python3
import argparse
import struct
import sys
def bad_find(data, search, align):
index = 0
while index <= len(data) - len(search):
if data[index:index + len(search)] == search:
return index
index += align
return -1
def find_code_vram(data, game):
if game == "mm": # possibly unnecessary
search = bytes.fromhex("00260600 00000009 00010000 00000194")
else:
search = bytes.fromhex("00390600 00000010 00010000 0000")
En_A_Obj_InitVars = data.find(search)
# Find aligned address, since for OoT there is a setup function with 2 or 3 instructions first
return struct.unpack(">I",data[En_A_Obj_InitVars + 0x10:En_A_Obj_InitVars + 0x14])[0] & ~0xF
def find_code_data_offset(data, game):
# Start of the rsp data
search = bytes.fromhex("340A0FC0")
return data.find(search)
def find_code_rodata_offset(data, game):
if game == "mm":
# First rodata in EnItem00
search = bytes.fromhex("3F19999A 80")
return data.find(search)
else:
# For debug
search = b"../z_en_a_keep.c"
EnAKeepRodataStart = data.find(search)
if EnAKeepRodataStart != -1:
return EnAKeepRodataStart
else:
# First float in EnItem00
search = bytes.fromhex("BF19999A")
index = data.find(search)
# look backwards until find bytes not part of a jumptable
while data[index - 4] == 0x80:
index -= 4
return index
def find_kaleido_strings(data, game):
# \0 included to remove filename results
search = b"kaleido_scope\0"
return data.find(search)
def find_kaleido_dlftbls(data, game):
# print(f"{find_code_vram(data, game) + find_kaleido_strings(data, game):08X}")
search = bytes.fromhex(f"{find_code_vram(data, game) + find_kaleido_strings(data, game):08X}")
# print(search)
return data.find(search) - 0x18
def find_actor_dlftbls(data, game):
# Searches for Player's internal actor entry, which is the first entry in the table.
search = bytes.fromhex("00000000 00000000 00000000 00000000 00000000 80")
return data.find(search)
def find_game_dlftbls(data, game):
# 0xA4 is the size of a gameState, in particular, TitleSetup
search = bytes.fromhex("00000000 00000000 00000000 000000A4 00000000")
return data.find(search) - 0x20
def find_effect_dlftbls(data, game):
# This is an unset effect, have to look backwards for the start
search = bytes.fromhex("01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000")
if game == "mm":
return bad_find(data, search, 4) - 0x34
else:
return bad_find(data, search, 4) - 0xDC
# Only OoT has this
def find_map_mark_data_dlftbl(data, game):
search = bytes.fromhex("00000400 00000400 00000000")
return data.find(search) + 0x8
# Only MM has this
def find_fbdemo_dlftbls(data, game):
search = bytes.fromhex("0000000C 00000000 80")
return data.find(search) - 0x18
def main():
description = "Finds the VRAM of the start of code and the offsets of various sections and dlftbls within it."
epilog = ""
parser = argparse.ArgumentParser(description=description, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter)
choices = ["oot", "mm"]
parser.add_argument("game", help="Game to extract.", choices=choices)
parser.add_argument("code", help="code file to parse.")
parser.add_argument("--csv", help="Output in CSV format.", action="store_true")
parser.add_argument("--headers", help="Print CSV headers in CSV mode.", action="store_true")
args = parser.parse_args()
try:
with open(args.code, 'rb') as f:
data = f.read()
except IOError:
print('Failed to read file ' + args.code)
sys.exit(1)
if args.csv:
if args.headers:
print("code_vram_start,code_data_offset,code_rodata_offset,effect_dlftbl,actor_dlftbl,game_dlftbl,kaleido_dlftbl,fbdemo_dlftbl")
print(f"{find_code_vram(data, args.game):X}", end="")
print(f",{find_code_data_offset(data, args.game):06X}", end="")
print(f",{find_code_rodata_offset(data, args.game):06X}", end="")
print(f",{find_effect_dlftbls(data, args.game):06X}", end="")
print(f",{find_actor_dlftbls(data, args.game):06X}", end="")
print(f",{find_game_dlftbls(data, args.game):06X}", end="")
print(f",{find_kaleido_dlftbls(data, args.game):06X}", end="")
if args.game == "oot":
print(f",{find_map_mark_data_dlftbl(data, args.game):06X}", end="")
if args.game == "mm":
print(f",{find_fbdemo_dlftbls(data, args.game):06X}", end="")
print("")
else:
print(f"code VRAM start: {find_code_vram(data, args.game):X}\n")
print(f"code data offset: {find_code_data_offset(data, args.game):06X}")
print(f"code rodata offset: {find_code_rodata_offset(data, args.game):06X}\n")
print(f"effectSs table: {find_effect_dlftbls(data, args.game):06X}")
print(f"actor table: {find_actor_dlftbls(data, args.game):06X}")
print(f"game table: {find_game_dlftbls(data, args.game):06X}")
print(f"kaleido table: {find_kaleido_dlftbls(data, args.game):06X}")
if args.game == "oot":
print(f"map_mark_data table: {find_map_mark_data_dlftbl(data, args.game):06X}")
if args.game == "mm":
print(f"fbdemo table: {find_fbdemo_dlftbls(data, args.game):06X}")
if __name__ == "__main__":
main()