diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-09-01 02:04:34 -0500 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-09-01 02:05:18 -0500 |
commit | a5b718db57a361cf3c196d73cbc5b3e21d3ddf6e (patch) | |
tree | 312937bcf9bced31a13e854e25b1ffb92f5cf48b /redtools/pretty_map_headers.py | |
parent | fc6785b87b7ddd27437ac2ac15bcc0870cc0fe90 (diff) |
dump in pokered/extras/ python stuff from b185b245
Diffstat (limited to 'redtools/pretty_map_headers.py')
-rw-r--r-- | redtools/pretty_map_headers.py | 755 |
1 files changed, 755 insertions, 0 deletions
diff --git a/redtools/pretty_map_headers.py b/redtools/pretty_map_headers.py new file mode 100644 index 0000000..ef26be3 --- /dev/null +++ b/redtools/pretty_map_headers.py @@ -0,0 +1,755 @@ +# -*- coding: utf-8 -*- +#author: Bryan Bishop <kanzure@gmail.com> +#date: 2012-01-02 +#purpose: dump asm for each map header +import json +import extract_maps +import sprite_helper +import random +import string +import analyze_texts #hopefully not a dependency loop + +base = 16 +spacing = " " +all_texts = None + +#map constants +map_constants = [ +["PALLET_TOWN", 0x00], +["VIRIDIAN_CITY", 0x01], +["PEWTER_CITY", 0x02], +["CERULEAN_CITY", 0x03], +["LAVENDER_TOWN", 0x04], +["VERMILION_CITY", 0x05], +["CELADON_CITY", 0x06], +["FUCHSIA_CITY", 0x07], +["CINNABAR_ISLAND", 0x08], +["INDIGO_PLATEAU", 0x09], +["SAFFRON_CITY", 0x0A], +["ROUTE_1", 0x0C], +["ROUTE_2", 0x0D], +["ROUTE_3", 0x0E], +["ROUTE_4", 0x0F], +["ROUTE_5", 0x10], +["ROUTE_6", 0x11], +["ROUTE_7", 0x12], +["ROUTE_8", 0x13], +["ROUTE_9", 0x14], +["ROUTE_10", 0x15], +["ROUTE_11", 0x16], +["ROUTE_12", 0x17], +["ROUTE_13", 0x18], +["ROUTE_14", 0x19], +["ROUTE_15", 0x1A], +["ROUTE_16", 0x1B], +["ROUTE_17", 0x1C], +["ROUTE_18", 0x1D], +["ROUTE_19", 0x1E], +["ROUTE_20", 0x1F], +["ROUTE_21", 0x20], +["ROUTE_22", 0x21], +["ROUTE_23", 0x22], +["ROUTE_24", 0x23], +["ROUTE_25", 0x24], +["REDS_HOUSE_1F", 0x25], +["REDS_HOUSE_2F", 0x26], +["BLUES_HOUSE", 0x27], +["OAKS_LAB", 0x28], +["VIRIDIAN_POKECENTER", 0x29], +["VIRIDIAN_MART", 0x2A], +["VIRIDIAN_SCHOOL", 0x2B], +["VIRIDIAN_HOUSE", 0x2C], +["VIRIDIAN_GYM", 0x2D], +["DIGLETTS_CAVE_EXIT", 0x2E], +["VIRIDIAN_FOREST_EXIT", 0x2F], +["ROUTE_2_HOUSE", 0x30], +["ROUTE_2_GATE", 0x31], +["VIRIDIAN_FOREST_ENTRANCE", 0x32], +["VIRIDIAN_FOREST", 0x33], +["MUSEUM_1F", 0x34], +["MUSEUM_2F", 0x35], +["PEWTER_GYM", 0x36], +["PEWTER_HOUSE_1", 0x37], +["PEWTER_MART", 0x38], +["PEWTER_HOUSE_2", 0x39], +["PEWTER_POKECENTER", 0x3A], +["MT_MOON_1", 0x3B], +["MT_MOON_2", 0x3C], +["MT_MOON_3", 0x3D], +["TRASHED_HOUSE", 0x3E], +["CERULEAN_HOUSE", 0x3F], +["CERULEAN_POKECENTER", 0x40], +["CERULEAN_GYM", 0x41], +["BIKE_SHOP", 0x42], +["CERULEAN_MART", 0x43], +["MT_MOON_POKECENTER", 0x44], +["ROUTE_5_GATE", 0x46], +["PATH_ENTRANCE_ROUTE_5", 0x47], +["DAYCAREM", 0x48], +["ROUTE_6_GATE", 0x49], +["PATH_ENTRANCE_ROUTE_6", 0x4A], +["ROUTE_7_GATE", 0x4C], +["PATH_ENTRANCE_ROUTE_7", 0x4D], +["ROUTE_8_GATE", 0x4F], +["PATH_ENTRANCE_ROUTE_8", 0x50], +["ROCK_TUNNEL_POKECENTER", 0x51], +["ROCK_TUNNEL_1", 0x52], +["POWER_PLANT", 0x53], +["ROUTE_11_GATE_1F", 0x54], +["DIGLETTS_CAVE_ENTRANCE", 0x55], +["ROUTE_11_GATE_2F", 0x56], +["ROUTE_12_GATE", 0x57], +["BILLS_HOUSE", 0x58], +["VERMILION_POKECENTER", 0x59], +["POKEMON_FAN_CLUB", 0x5A], +["VERMILION_MART", 0x5B], +["VERMILION_GYM", 0x5C], +["VERMILION_HOUSE_1", 0x5D], +["VERMILION_DOCK", 0x5E], +["SS_ANNE_1", 0x5F], +["SS_ANNE_2", 0x60], +["SS_ANNE_3", 0x61], +["SS_ANNE_4", 0x62], +["SS_ANNE_5", 0x63], +["SS_ANNE_6", 0x64], +["SS_ANNE_7", 0x65], +["SS_ANNE_8", 0x66], +["SS_ANNE_9", 0x67], +["SS_ANNE_10", 0x68], +["VICTORY_ROAD_1", 0x6C], +["LANCES_ROOM", 0x71], +["HALL_OF_FAME", 0x76], +["UNDERGROUND_PATH_NS", 0x77], +["CHAMPIONS_ROOM", 0x78], +["UNDERGROUND_PATH_WE", 0x79], +["CELADON_MART_1", 0x7A], +["CELADON_MART_2", 0x7B], +["CELADON_MART_3", 0x7C], +["CELADON_MART_4", 0x7D], +["CELADON_MART_5", 0x7E], +["CELADON_MART_6", 0x7F], +["CELADON_MANSION_1", 0x80], +["CELADON_MANSION_2", 0x81], +["CELADON_MANSION_3", 0x82], +["CELADON_MANSION_4", 0x83], +["CELADON_MANSION_5", 0x84], +["CELADON_POKECENTER", 0x85], +["CELADON_GYM", 0x86], +["GAME_CORNER", 0x87], +["CELADON_HOUSE", 0x88], +["CELADONPRIZE_ROOM", 0x89], +["CELADON_DINER", 0x8A], +["CELADON_HOUSE_2", 0x8B], +["CELADONHOTEL", 0x8C], +["LAVENDER_POKECENTER", 0x8D], +["POKEMONTOWER_1", 0x8E], +["POKEMONTOWER_2", 0x8F], +["POKEMONTOWER_3", 0x90], +["POKEMONTOWER_4", 0x91], +["POKEMONTOWER_5", 0x92], +["POKEMONTOWER_6", 0x93], +["POKEMONTOWER_7", 0x94], +["LAVENDER_HOUSE_1", 0x95], +["LAVENDER_MART", 0x96], +["LAVENDER_HOUSE_2", 0x97], +["FUCHSIA_MART", 0x98], +["FUCHSIA_HOUSE_1", 0x99], +["FUCHSIA_POKECENTER", 0x9A], +["FUCHSIA_HOUSE_2", 0x9B], +["SAFARIZONEENTRANCE", 0x9C], +["FUCHSIA_GYM", 0x9D], +["FUCHSIAMEETINGROOM", 0x9E], +["SEAFOAM_ISLANDS_2", 0x9F], +["SEAFOAM_ISLANDS_3", 0xA0], +["SEAFOAM_ISLANDS_4", 0xA1], +["SEAFOAM_ISLANDS_5", 0xA2], +["VERMILION_HOUSE_2", 0xA3], +["FUCHSIA_HOUSE_3", 0xA4], +["MANSION_1", 0xA5], +["CINNABAR_GYM", 0xA6], +["CINNABAR_LAB_1", 0xA7], +["CINNABAR_LAB_2", 0xA8], +["CINNABAR_LAB_3", 0xA9], +["CINNABAR_LAB_4", 0xAA], +["CINNABAR_POKECENTER", 0xAB], +["CINNABAR_MART", 0xAC], +["INDIGO_PLATEAU_LOBBY", 0xAE], +["COPYCATS_HOUSE_1F", 0xAF], +["COPYCATS_HOUSE_2F", 0xB0], +["FIGHTINGDOJO", 0xB1], +["SAFFRON_GYM", 0xB2], +["SAFFRON_HOUSE_1", 0xB3], +["SAFFRON_MART", 0xB4], +["SILPH_CO_1F", 0xB5], +["SAFFRON_POKECENTER", 0xB6], +["SAFFRON_HOUSE_2", 0xB7], +["ROUTE_15_GATE", 0xB8], +["ROUTE_16_GATE_1F", 0xBA], +["ROUTE_16_GATE_2F", 0xBB], +["ROUTE_16_HOUSE", 0xBC], +["ROUTE_12_HOUSE", 0xBD], +["ROUTE_18_GATE_1F", 0xBE], +["ROUTE_18_GATE_2F", 0xBF], +["SEAFOAM_ISLANDS_1", 0xC0], +["ROUTE_22_GATE", 0xC1], +["VICTORY_ROAD_2", 0xC2], +["ROUTE_12_GATE_2F", 0xC3], +["VERMILION_HOUSE_3", 0xC4], +["DIGLETTS_CAVE", 0xC5], +["VICTORY_ROAD_3", 0xC6], +["ROCKET_HIDEOUT_1", 0xC7], +["ROCKET_HIDEOUT_2", 0xC8], +["ROCKET_HIDEOUT_3", 0xC9], +["ROCKET_HIDEOUT_4", 0xCA], +["ROCKET_HIDEOUT_ELEVATOR", 0xCB], +["SILPH_CO_2F", 0xCF], +["SILPH_CO_3F", 0xD0], +["SILPH_CO_4F", 0xD1], +["SILPH_CO_5F", 0xD2], +["SILPH_CO_6F", 0xD3], +["SILPH_CO_7F", 0xD4], +["SILPH_CO_8F", 0xD5], +["MANSION_2", 0xD6], +["MANSION_3", 0xD7], +["MANSION_4", 0xD8], +["SAFARI_ZONE_EAST", 0xD9], +["SAFARI_ZONE_NORTH", 0xDA], +["SAFARI_ZONE_WEST", 0xDB], +["SAFARI_ZONE_CENTER", 0xDC], +["SAFARI_ZONE_REST_HOUSE_1", 0xDD], +["SAFARI_ZONE_SECRET_HOUSE", 0xDE], +["SAFARI_ZONE_REST_HOUSE_2", 0xDF], +["SAFARI_ZONE_REST_HOUSE_3", 0xE0], +["SAFARI_ZONE_REST_HOUSE_4", 0xE1], +["UNKNOWN_DUNGEON_2", 0xE2], +["UNKNOWN_DUNGEON_3", 0xE3], +["UNKNOWN_DUNGEON_1", 0xE4], +["NAME_RATERS_HOUSE", 0xE5], +["CERULEAN_HOUSE_3", 0xE6], +["ROCK_TUNNEL_2", 0xE8], +["SILPH_CO_9F", 0xE9], +["SILPH_CO_10F", 0xEA], +["SILPH_CO_11F", 0xEB], +["SILPH_CO_ELEVATOR", 0xEC], +["BATTLE_CENTER", 0xEF], +["TRADE_CENTER", 0xF0], +["LORELEIS_ROOM", 0xF5], +["BRUNOS_ROOM", 0xF6], +["AGATHAS_ROOM", 0xF7], +["BEACH_HOUSE", 0xF8]] + +#i prefer a different data structure +temp = {} +for constant in map_constants: + value = constant[1] + name = constant[0] + temp[value] = name +map_constants = temp +del temp + +#these appear outside of quotes +constant_abbreviation_bytes = { +} + +#these appear in quotes +char_conversion = [ +(" ", 0x7F), +("A", 0x80), +("B", 0x81), +("C", 0x82), +("D", 0x83), +("E", 0x84), +("F", 0x85), +("G", 0x86), +("H", 0x87), +("I", 0x88), +("J", 0x89), +("K", 0x8A), +("L", 0x8B), +("M", 0x8C), +("N", 0x8D), +("O", 0x8E), +("P", 0x8F), +("Q", 0x90), +("R", 0x91), +("S", 0x92), +("T", 0x93), +("U", 0x94), +("V", 0x95), +("W", 0x96), +("X", 0x97), +("Y", 0x98), +("Z", 0x99), +("(", 0x9A), +(")", 0x9B), +(":", 0x9C), +(";", 0x9D), +("[", 0x9E), +("]", 0x9F), +("a", 0xA0), +("b", 0xA1), +("c", 0xA2), +("d", 0xA3), +("e", 0xA4), +("f", 0xA5), +("g", 0xA6), +("h", 0xA7), +("i", 0xA8), +("j", 0xA9), +("k", 0xAA), +("l", 0xAB), +("m", 0xAC), +("n", 0xAD), +("o", 0xAE), +("p", 0xAF), +("q", 0xB0), +("r", 0xB1), +("s", 0xB2), +("t", 0xB3), +("u", 0xB4), +("v", 0xB5), +("w", 0xB6), +("x", 0xB7), +("y", 0xB8), +("z", 0xB9), +("é", 0xBA), +("'d", 0xBB), +("'l", 0xBC), +("'s", 0xBD), +("'t", 0xBE), +("'v", 0xBF), +("'", 0xE0), +("-", 0xE3), +("'r", 0xE4), +("'m", 0xE5), +("?", 0xE6), +("!", 0xE7), +(".", 0xE8), +("♂", 0xEF), +#("¥", 0xF0), +("/", 0xF3), +(",", 0xF4), +("♀", 0xF5), +("0", 0xF6), +("1", 0xF7), +("2", 0xF8), +("3", 0xF9), +("4", 0xFA), +("5", 0xFB), +("6", 0xFC), +("7", 0xFD), +("8", 0xFE), +("9", 0xFF)] +#these appear in quotes +txt_bytes = { + 0x50: "@", + 0x54: "#", + 0x75: "…", +} +for item in char_conversion: + txt_bytes[item[1]] = item[0] +del char_conversion + +#this was originally for renaming freeze maps for a unique name +def random_hash(): + available_chars = string.hexdigits[:16] + return ''.join( + random.choice(available_chars) + for dummy in xrange(5)) + +def offset_to_pointer(offset): + if type(offset) == str: offset = int(offset, base) + return int(offset) % 0x4000 + 0x4000 + +def map_name_cleaner(name, id): + "names have to be acceptable asm labels" + + #duck out early + if name == "FREEZE": + #name += "_" + random_hash() + "_h" + name += "_" + str(id) + "_h" + return name + + #the long haul + name = name.replace(":", "") + name = name.replace("(", "") + name = name.replace(")", "") + name = name.replace("'", "") + name = name.replace("/", "") #N/S -> NS, W/E -> WE + name = name.replace(".", "") #S.S. -> SS, Mt. -> Mt + name = name.replace(" ", "") #or '_' ?? + name = name + "_h" + + return name + +def write_connections(north, south, west, east): + #north 0, south 1, west 2, east 3 + if north and south and west and east: return "NORTH | SOUTH | WEST | EAST" + if north and south and west and not east: return "NORTH | SOUTH | WEST" + if north and south and not west and east: return "NORTH | SOUTH | EAST" + if north and not south and west and east: return "NORTH | WEST | EAST" + if not north and south and west and east: return "SOUTH | WEST | EAST" + if north and south and not west and not east: return "NORTH | SOUTH" + if not north and not south and west and east: return "WEST | EAST" + if not north and south and west and not east: return "SOUTH | WEST" + if not north and south and not west and east: return "SOUTH | EAST" + if north and not south and west and not east: return "NORTH | WEST" + if north and not south and not west and east: return "NORTH | EAST" + raise Exception, "unpredicted outcome on write_connections" + +#TODO: make this elegant +def connection_line(byte): + if type(byte) == str: + byte = int(byte, base) + + connections = 0 + north, south, west, east = False, False, False, False + + temp = bin(byte)[2:] + + if len(temp) == 1: + if temp[0] == "1": #EAST + east = True + elif len(temp) == 2: + if temp[0] == "1": #WEST + west = True + if temp[1] == "1": #EAST + east = True + elif len(temp) == 3: + if temp[0] == "1": #SOUTH + south = True + if temp[1] == "1": #WEST + west = True + if temp[2] == "1": #EAST + east = True + elif len(temp) == 4: + if temp[0] == "1": #NORTH + north = True + if temp[1] == "1": #SOUTH + south = True + if temp[2] == "1": #WEST + west = True + if temp[3] == "1": #EAST + east = True + + if north: connections += 1 + if south: connections += 1 + if west: connections += 1 + if east: connections += 1 + + #i don't have time to optimize this + if connections == 0: + return "$00" + if connections == 1: + if north: return "NORTH" + if south: return "SOUTH" + if west: return "WEST" + if east: return "EAST" + if connections >= 2: + return write_connections(north, south, west, east) + +def connection_pretty_printer(connections): +#map_id, connected_map_tile_pointer, current_map_tile_pointer, bigness, width, y, x, window_pointer + output = "" + + for connection in connections.keys(): + connection = connections[connection] + map_id = hex(connection["map_id"])[2:].zfill(2) + connected_map_tile_pointer = connection["connected_map_tile_pointer"][2:] + current_map_tile_pointer = connection["current_map_tile_pointer"][2:] + bigness = hex(int(connection["bigness"], base))[2:].zfill(2) + width = hex(int(connection["width"], base))[2:].zfill(2) + y = hex(connection["y"])[2:].zfill(2) + x = hex(connection["x"])[2:].zfill(2) + window_pointer = connection["window_pointer"][2:] + + output += spacing + "db $" + map_id + " ; some map\n" + output += spacing + "dw $" + connected_map_tile_pointer + ", $" + current_map_tile_pointer + " ; pointers (connected, current) (strip)\n" + output += spacing + "db $" + bigness + ", $" + width + " ; bigness, width\n" + output += spacing + "db $" + y + ", $" + x + " ; alignments (y, x)\n" + output += spacing + "dw $" + window_pointer + " ; window\n\n" + + return output + +def map_header_pretty_printer(map_header): + address = map_header["address"] + bank = map_header["bank"] + id = map_header["id"] + + name = map_header["name"] + asm_name = map_name_cleaner(name, id) + if name == "FREEZE": return "" #skip freeze maps + + tileset = map_header["tileset"][2:] + y = int(map_header["y"], base) + x = int(map_header["x"], base) + map_pointer = map_header["map_pointer"] + texts_pointer = map_header["texts_pointer"] + script_pointer = map_header["script_pointer"] + connection_byte = map_header["connection_byte"] + connections = map_header["connections"] + object_data_pointer = map_header["object_data_pointer"] + + byte_size = 12 + (11 * len(connections.keys())) + + map_pointer = hex(offset_to_pointer(map_pointer))[2:] + texts_pointer = hex(offset_to_pointer(texts_pointer))[2:] + script_pointer = hex(offset_to_pointer(script_pointer))[2:] + object_data_pointer = hex(offset_to_pointer(object_data_pointer))[2:] + + #formatting: hex(y)[2:].zill(2) or "%02x" % (y,) + + output = asm_name + ": ; " + address + " to " + hex(int(address, base) + byte_size) + " (" + str(byte_size) + " bytes) (id=" + str(id) + ")\n" + output += spacing + "db $" + str(tileset).zfill(2) + " ; tileset\n" + output += spacing + "db $" + hex(y)[2:].zfill(2) + ", $" + hex(x)[2:].zfill(2) + " ; dimensions (y, x)\n" + output += spacing + "dw $" + map_pointer + ", $" + texts_pointer + ", $" + script_pointer + " ; blocks, texts, scripts\n" + output += spacing + "db " + connection_line(connection_byte) + " ; connections\n\n" + + if len(connections) > 0: + output += spacing + "; connections data\n\n" + output += connection_pretty_printer(connections) + output += spacing + "; end connection data\n\n" + + #TODO: print out label for object_data_pointer if it's already in the file + output += spacing + "dw $" + object_data_pointer + " ; objects\n" + + return output + +def make_object_label_name(name): + """make a label for the asm file + like: PalletTownObject""" + name = map_name_cleaner(name, None) + return name.replace("_h", "") + "Object" + +def make_text_label(map_name, id): + """using standard object labels + for instance, PalletTownText3""" + label = map_name_cleaner(map_name, None)[:-2] + "Text" + str(id) + return label + +def object_data_pretty_printer(map_id): + map = extract_maps.map_headers[map_id] + output = "" + + label_name = make_object_label_name(map["name"]) + object_data_pointer = map["object_data_pointer"] + object = map["object_data"] + size = extract_maps.compute_object_data_size(object) + + output += label_name + ": ; " + object_data_pointer + " (size=" + str(size) + ")\n" + output += spacing + "db $" + hex(object["maps_border_tile"])[2:] + " ; border tile\n" + output += "\n" + output += spacing + "db $" + hex(int(object["number_of_warps"]))[2:] + " ; warps\n" + + #warps + for warp_id in object["warps"]: + warp = object["warps"][warp_id] + y = warp["y"] + x = warp["x"] + warp_to_point = warp["warp_to_point"] + warp_to_map_id = warp["warp_to_map_id"] + + try: + warp_to_map_constant = map_constants[warp_to_map_id] + except Exception, exc: + warp_to_map_constant = "$" + hex(warp_to_map_id)[2:] + + output += spacing + "db $" + hex(int(y))[2:] + ", $" + hex(int(x))[2:] + ", $" + hex(int(warp_to_point))[2:] + ", " + warp_to_map_constant + "\n" + + output += "\n" + output += spacing + "db $" + hex(int(object["number_of_signs"]))[2:] + " ; signs\n" + + #signs + for sign_id in object["signs"]: + sign = object["signs"][sign_id] + y = sign["y"] + x = sign["x"] + text_id = sign["text_id"] + + output += spacing + "db $" + hex(int(y))[2:] + ", $" + hex(int(x))[2:] + ", $" + hex(int(text_id))[2:] + " ; " + make_text_label(map["name"], text_id) + "\n" + + output += "\n" + output += spacing + "db $" + hex(int(object["number_of_things"]))[2:] + " ; people\n" + + #people + for thing_id in object["things"]: + thing = object["things"][thing_id] + + ending = "" + if thing["type"] == "item": + ending = ", $" + hex(int(thing["item_number"]))[2:] + " ; item\n" + elif thing["type"] == "trainer": + ending = ", $" + hex(int(thing["trainer_type"]))[2:] + ", $" + hex(int(thing["pokemon_set"]))[2:] + " ; trainer\n" + else: + ending = " ; person\n" + + picture_number = hex(int(thing["picture_number"]))[2:] + y = hex(int(thing["y"]) - 4)[2:] + x = hex(int(thing["x"]) - 4)[2:] + movement1 = hex(int(thing["movement1"]))[2:] + movement2 = hex(int(thing["movement2"]))[2:] + text_id = hex(int(thing["original_text_string_number"]))[2:] + + output += spacing + "db " + sprite_helper.sprites[thing["picture_number"]] + ", $" + y + " + 4, $" + x + " + 4, $" + movement1 + ", $" + movement2 + ", $" + text_id + ending + + output += "\n" + + if object["number_of_warps"] > 0: + output += spacing + "; warp-to\n" + + for warp_to_id in object["warp_tos"]: + warp_to = object["warp_tos"][warp_to_id] + map_width = map["x"] + warp_to_y = hex(int(warp_to["y"]))[2:] + warp_to_x = hex(int(warp_to["x"]))[2:] + + try: + previous_location = map_constants[object["warps"][warp_to_id]["warp_to_map_id"]] + comment = " ; " + previous_location + except Exception, exc: + comment = "" + + output += spacing + "EVENT_DISP $" + map_width[2:] + ", $" + warp_to_y + ", $" + warp_to_x + comment + "\n" + #output += spacing + "dw $" + hex(int(warp_to["event_displacement"][1]))[2:] + hex(int(warp_to["event_displacement"][0]))[2:] + "\n" + #output += spacing + "db $" + hex(int(warp_to["y"]))[2:] + ", $" + hex(int(warp_to["x"]))[2:] + "\n" + #output += "\n" + + output += "\n" + + while output[-1] == "\n": + output = output[:-1] + + output += "\n" + return output + +def find_all_tx_fars(): + global all_texts + tx_fars = [] #[map_id, text_id, text_pointer, tx_far_pointer, TX_FAR] + for map_id in all_texts: + map2 = all_texts[map_id] + for text_id in map2.keys(): + text = map2[text_id] + for command_id in text.keys(): + command = text[command_id] + if "TX_FAR" in command.keys(): + TX_FAR = command["TX_FAR"] + if TX_FAR[0]["type"] == 0x0: + tx_fars.append([map_id, text_id, analyze_texts.get_text_pointer(int(extract_maps.map_headers[map_id]["texts_pointer"], 16), text_id), command["pointer"], TX_FAR]) + return tx_fars + +def tx_far_label_maker(map_name, text_id): + label = "_" + map_name_cleaner(map_name, None)[:-2] + "Text" + str(text_id) + return label + +def tx_far_pretty_printer(tx_far): + "pretty output for a tx_far" + map_id = tx_far[0] + map2 = extract_maps.map_headers[map_id] + text_id = tx_far[1] + text_pointer = tx_far[2] + tx_far_start_address = tx_far[3] + text_far = tx_far[4] + lines = text_far[0]["lines"] + label = tx_far_label_maker(map2["name"], text_id) + + #add the ending byte on the next line + #lines[len(lines.keys())+1] = [text_far[1]["type"]] + + #add the ending byte to the last line- always seems $57 + lines[len(lines.keys())-1].append(text_far[1]["type"]) + + output = "\n" + output += label + ": ; " + hex(tx_far_start_address) + "\n" + first = True + for line_id in lines: + line = lines[line_id] + output += spacing + "db " + if first: + output += "$0, " + first = False + + quotes_open = False + first_byte = True + was_byte = False + byte_count = 0 + for byte in line: + if byte in txt_bytes: + if not quotes_open and not first_byte: #start text + output += ", \"" + quotes_open = True + first_byte = False + if not quotes_open and first_byte: #start text + output += "\"" + quotes_open = True + output += txt_bytes[byte] + elif byte in constant_abbreviation_bytes: + if quotes_open: + output += "\"" + quotes_open = False + if not first_byte: + output += ", " + output += constant_abbreviation_bytes[byte] + else: + if quotes_open: + output += "\"" + quotes_open = False + + #if you want the ending byte on the last line + #if not (byte == 0x57 or byte == 0x50 or byte == 0x58): + if not first_byte: + output += ", " + + output += "$" + hex(byte)[2:] + was_byte = True + + #add a comma unless it's the end of the line + #if byte_count+1 != len(line): + # output += ", " + + first_byte = False + byte_count += 1 + #close final quotes + if quotes_open: + output += "\"" + quotes_open = False + + output += "\n" + + #output += "\n" + return output + +def print_all_headers(): + maps = [] + for map in extract_maps.map_headers: + maps.append(extract_maps.map_headers[map]) + + maps = sorted(maps, key=lambda map: int(map["address"], base)) + + for map in maps: + output = map_header_pretty_printer(map) + if output != "": print output + +if __name__ == "__main__": + #read binary data from file + extract_maps.load_rom() + + #where are the map structs? + extract_maps.load_map_pointers() + + #load map headers into memory + extract_maps.read_all_map_headers() + + #load texts + all_texts = analyze_texts.analyze_texts() + + #print them out + #print_all_headers() + + #print out only the object data for pallet town (map 0) + #print object_data_pretty_printer(0) + + #prepare to pretty print tx_fars + #first you must load all_texts + #tx_fars = find_all_tx_fars() + #for entry in tx_fars: + # print tx_far_pretty_printer(entry) |