from pathlib import Path from pprint import pprint import io from parse import parse def sorted_map_headers(): # hack to remove unused/duplicate underground_path_route_7 map_headers = sorted(parse.map_headers, key=lambda m: m.name2) return filter(lambda m: m.name1 != "UndergroundPathRoute7Copy", map_headers) def includes(): for map_header in sorted_map_headers(): block_path = parse.maps_blocks_list[map_header.blocks()] yield f'#include "res/{block_path}.h"' for tileset_name in sorted(parse.tileset_constants_list): tileset_index = parse.tileset_constants_list[tileset_name] tileset_header = parse.tileset_headers_list[tileset_index] blockset_path = parse.gfx_tilesets_list[tileset_header.blockset()] gfx_path = parse.gfx_tilesets_list[tileset_header.gfx()] yield f'#include "res/{blockset_path}.h"' yield f'#include "res/{gfx_path}.h"' yield "" def struct_start_size_t(): return [ "struct start_size_t {", "uint8_t const * const start;", "uint32_t size;", "};", ] def struct_tileset_t(): tileset_names = ( f"{name.lower()}," for name in sorted(parse.tileset_constants_list) ) return [ "struct tileset_t {", "start_size_t blockset;", "start_size_t tileset;", "", "enum tileset {", *tileset_names, "};", "};", ] def struct_map_t(): map_names = ( f"{map_header.name2.lower()}," for map_header in sorted_map_headers() ) return [ "struct map_t {", "start_size_t blocks;", "enum tileset_t::tileset tileset;", "uint32_t width;", "uint32_t height;", "", "enum map {", *map_names, "};", "};", ] def binary_res(path, suffix): # _binary_res_gfx_blocksets_overworld_bst_start name = path.replace('/', '_').replace('.', '_') return f"_binary_res_{name}_{suffix}" def start_size_value(path): start = binary_res(path, "start") size = binary_res(path, "size") return [ f"reinterpret_cast(&{start}),", f"reinterpret_cast(&{size}),", ] def blockset_tileset(name: str): tileset_index = parse.tileset_constants_list[name] tileset_header = parse.tileset_headers_list[tileset_index] blockset_path = parse.gfx_tilesets_list[tileset_header.blockset()] gfx_path = parse.gfx_tilesets_list[tileset_header.gfx()] return [ f"[tileset_t::{name.lower()}] = {{", ".blockset = {", *start_size_value(blockset_path), "},", ".tileset = {", *start_size_value(gfx_path), "}", "}," ] def tilesets(): yield "const tileset_t tilesets[] = {" for tileset in sorted(parse.tileset_constants_list): yield from blockset_tileset(tileset) yield "};" def map(map_header): block_path = parse.maps_blocks_list[map_header.blocks()] map_constant = parse.map_constants_list[map_header.name2] return [ f"[map_t::{map_header.name2.lower()}] = {{", ".blocks = {", *start_size_value(block_path), "},", f".tileset = tileset_t::{map_header.tileset.lower()},", f".width = {map_constant.width},", f".height = {map_constant.height},", "},", ] def maps(): yield "const map_t maps[] = {" for map_header in sorted_map_headers(): yield from map(map_header) yield "};" def _render(out, lines): indent = " " level = 0 for l in lines: if l and l[0] == "}": level -= 2 assert level >= 0, out.getvalue() out.write(indent * level + l + "\n") if l and l[-1] == "{": level += 2 if level == 0 and l and l[-1] == ";": out.write("\n") return out def renderer(): out = io.StringIO() def render(lines): return _render(out, lines) return render, out def generate(): #pprint(parse.maps_blocks_list) #pprint(parse.map_headers) #pprint(parse.tileset_constants_list) #pprint(parse.tileset_headers_list) #pprint(parse.gfx_tilesets_list) render, out = renderer() render(includes()) render(struct_start_size_t()) render(struct_tileset_t()) render(struct_map_t()) render(tilesets()) render(maps()) print(out.getvalue(), end='') generate() """ map_headers[0].tileset == 'OVERWORLD' map_headers[0].name1 = 'PalletTown' map_headers[0].name2 = 'PALLET_TOWN' map_headers[0].blocks() == 'PalletTown_Blocks' map_constants_list['PALLET_TOWN'] == MapConstant(10, 19) maps_blocks_list['PalletTown_Blocks'] == 'maps/PalletTown.blk' tileset_constants_list['OVERWORLD'] == 0 tileset_headers_list[0].name == 'Overworld' tileset_headers_list[0].blockset() == 'Overworld_Block' tileset_headers_list[0].gfx() == 'Overworld_GFX' gfx_tilesets_list['Overworld_Block'] == 'gfx/blocksets/overworld.bst' gfx_tilesets_list['Overworld_GFX'] == 'gfx/tilesets/overworld.2bpp' """