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
|
#!/usr/bin/env python3
import os
import struct
import sys
NUM_SCENES = 10
SIMPLIFY_OUTPUT = True # setting to True reduces the final output by ~9k lines
MAP_MARK_RAM = 0x80858B70
gMapMarkDataTable = 0x8085F5E8
DUNGEON_NAMES = [
("DekuTree", "Deku Tree"),
("DodongosCavern", "Dodongo's Cavern"),
("JabuJabuBelly", "Jabu-Jabu's Belly"),
("ForestTemple", "Forest Temple"),
("FireTemple", "Fire Temple"),
("WaterTemple", "Water Temple"),
("SpiritTemple", "Spirit Temple"),
("ShadowTemple", "Shadow Temple"),
("BottomWell", "Bottom of the Well"),
("IceCavern", "Ice Cavern")
]
HEADER = """\
#include "global.h"
"""
def RamToOff(vram):
return vram - MAP_MARK_RAM
def GetMapPtrs(data):
off = RamToOff(gMapMarkDataTable)
return struct.unpack_from(">10L", data[off:off+(NUM_SCENES * 4)])
def GetMapsPerScene(ptrs):
result = []
endAddr = list(ptrs)
endAddr.append(gMapMarkDataTable)
for i, ptr in enumerate(ptrs):
v = (endAddr[i+1] - ptr) // 0x72
result.append(v)
return result
def GetPoints(data, ptr, numPoints):
points = []
off = RamToOff(ptr)
for i in range(numPoints):
points.append(struct.unpack_from(">bBB", data[off:off+3]))
off = off + 3
return points
def GetIconData(data, ptr):
off = RamToOff(ptr)
v = struct.unpack_from(">bB", data[off:off+2])
points = GetPoints(data, ptr+2, v[1] if SIMPLIFY_OUTPUT else 12)
return [v[0], v[1], points]
def GetSceneMap(data, ptr):
icons = []
for i in range(3):
icon = GetIconData(data, ptr + (i * 0x26))
if not SIMPLIFY_OUTPUT or icon[0] != 0 or icon[1] > 0:
icons.append(icon)
return icons
def GetSceneMaps(data, ptr, numMaps):
maps = []
for i in range(numMaps):
maps.append(GetSceneMap(data, ptr + (i * 0x72)))
return maps
def GetDungeonSymbol(i):
return f"sMapMark{DUNGEON_NAMES[i][0]}"
def GetDungeonName(i):
return DUNGEON_NAMES[i][1]
def GetIconName(v):
if v == 0:
return "MAP_MARK_CHEST"
if v == 1:
return "MAP_MARK_BOSS"
if v == -1:
return "MAP_MARK_NONE"
return v
def IND(n):
return ' ' * 4 * n
if len(sys.argv) != 2:
print("Script requires an output filename for the generated .c file")
quit()
scriptDir = os.path.dirname(os.path.realpath(__file__))
repo = scriptDir + os.sep + ".." + os.sep + ".."
map_mark_data = []
with open(repo + "/extracted/gc-eu-mq-dbg/baserom/ovl_map_mark_data", "rb") as file:
map_mark_data = bytearray(file.read())
scenemaps = []
scenemap_ptrs = GetMapPtrs(map_mark_data)
maps_per_scene = GetMapsPerScene(scenemap_ptrs)
for i in range(NUM_SCENES):
scenemaps.append((i, GetSceneMaps(map_mark_data, scenemap_ptrs[i], maps_per_scene[i])))
cstr = HEADER
for scenemap in scenemaps:
cstr += f"MapMarkData {GetDungeonSymbol(scenemap[0])}[] = {{\n"
for mapId, map in enumerate(scenemap[1]):
cstr += IND(1) + f"// {GetDungeonName(scenemap[0])} minimap {mapId}\n"
cstr += IND(1) + "{\n"
for icon in map:
if SIMPLIFY_OUTPUT and icon[0] == -1:
cstr += IND(2) + f"{{ {GetIconName(icon[0])}, 0, {{ 0 }} }},\n"
else:
cstr += IND(2) + "{\n"
cstr += IND(3) + f"{GetIconName(icon[0])}, {icon[1]},\n"
cstr += IND(3) + "{\n"
for point in icon[2]:
cstr += IND(4) + f"{{ {point[0]}, {point[1]}, {point[2]} }},\n"
cstr += IND(3) + "}\n"
cstr += IND(2) + "},\n"
cstr += IND(1) + "},\n"
cstr += "};\n\n"
cstr += "MapMarkData* gMapMarkDataTable[] = {\n"
for scenemap in scenemaps:
cstr += f" {GetDungeonSymbol(scenemap[0])},\n"
cstr += "};\n"
with open(sys.argv[1], "w") as file:
file.write(cstr)
|