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()