diff options
author | Bryan Bishop <kanzure@gmail.com> | 2012-01-02 21:26:32 -0600 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2012-01-02 21:26:32 -0600 |
commit | d74daf3273582f489e78b60102bbbcc7a6d0abb8 (patch) | |
tree | 7d75d72f803ca64698bf00a3578cf92c0d7a7577 /extras | |
parent | 020ccf422a9c2f658f0d3b16e156359e95b6ecd8 (diff) |
tool to dump asm for each map header
hg-commit-id: 812226d99dc0
Diffstat (limited to 'extras')
-rw-r--r-- | extras/pretty_map_headers.py | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/extras/pretty_map_headers.py b/extras/pretty_map_headers.py new file mode 100644 index 00000000..339758f7 --- /dev/null +++ b/extras/pretty_map_headers.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +#author: Bryan Bishop <kanzure@gmail.com> +#date: 2012-01-02 +#purpose: dump asm for each map header +import json +import extract_maps +import random +import string + +base = 16 +spacing = " " + +#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 + "db $" + 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 = int(map_header["tileset"], base) + 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) (bank=" + str(int(bank, base)) + ") (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" + output += spacing + "; connections data\n\n" + output += connection_pretty_printer(connections) + output += spacing + "; end connection data\n\n" + output += spacing + "dw $" + object_data_pointer + " ; objects\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() + + #print them out + print_all_headers() |