#!/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)