shithub: pokered

Download patch

ref: d74daf3273582f489e78b60102bbbcc7a6d0abb8
parent: 020ccf422a9c2f658f0d3b16e156359e95b6ecd8
author: Bryan Bishop <kanzure@gmail.com>
date: Mon Jan 2 16:26:32 EST 2012

tool to dump asm for each map header

hg-commit-id: 812226d99dc0


--- /dev/null
+++ b/extras/pretty_map_headers.py
@@ -1,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()