diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-08-03 16:10:52 -0500 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-08-03 16:10:52 -0500 |
commit | 28490230cf68f8045fc63a8c7d3de19c7c1d3bcd (patch) | |
tree | c4d1a3acbc7d34b77a890f8e19a8d7253917be8c /pokemontools/dump_sections.py | |
parent | a14c36eadb75ea3d6fbc4cb3f382d7c9785d9fe9 (diff) |
make a basic python module
Diffstat (limited to 'pokemontools/dump_sections.py')
-rwxr-xr-x | pokemontools/dump_sections.py | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/pokemontools/dump_sections.py b/pokemontools/dump_sections.py new file mode 100755 index 0000000..fef35d8 --- /dev/null +++ b/pokemontools/dump_sections.py @@ -0,0 +1,129 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +""" +Use this tool to dump an asm file for a new source code or disassembly project. + +usage: + + from dump_sections import dump_sections + + output = dump_sections("../../butt.gbc") + + file_handler = open("main.asm", "w") + file_handler.write(output) + file_handler.close() + +You can also use this script from the shell, where it will look for +"baserom.gbc" in the current working path or whatever file path you pass in the +first positional argument. +""" + +import os +import sys +import argparse + +def upper_hex(input): + """ + Converts the input to an uppercase hex string. + """ + if input in [0, "0"]: + return "0" + elif input <= 0xF: + return ("%.x" % (input)).upper() + else: + return ("%.2x" % (input)).upper() + +def format_bank_number(address, bank_size=0x4000): + """ + Returns a str of the hex number of the bank based on the address. + """ + return upper_hex(address / bank_size) + +def calculate_bank_quantity(path, bank_size=0x4000): + """ + Returns the number of 0x4000 banks in the file at path. + """ + return float(os.lstat(path).st_size) / bank_size + +def dump_section(bank_number, separator="\n\n"): + """ + Returns a str of a section header for the asm file. + """ + output = "SECTION \"" + if bank_number in [0, "0"]: + output += "bank0\",HOME" + else: + output += "bank" + output += bank_number + output += "\",DATA,BANK[$" + output += bank_number + output += "]" + output += separator + return output + +def dump_incbin_for_section(address, bank_size=0x4000, baserom="baserom.gbc", separator="\n\n"): + """ + Returns a str for an INCBIN line for an entire section. + """ + output = "INCBIN \"" + output += baserom + output += "\",$" + output += upper_hex(address) + output += ",$" + output += upper_hex(bank_size) + output += separator + return output + +def dump_sections(path, bank_size=0x4000, initial_bank=0, last_bank=None, separator="\n\n"): + """ + Returns a str of assembly source code. The source code delineates each + SECTION and includes bytes from the file specified by baserom. + """ + if not last_bank: + last_bank = calculate_bank_quantity(path, bank_size=bank_size) + + if last_bank < initial_bank: + raise Exception("last_bank must be greater than or equal to initial_bank") + + baserom_name = os.path.basename(path) + + output = "" + + banks = range(initial_bank, last_bank) + + for bank_number in banks: + address = bank_number * bank_size + + # get a formatted hex number of the bank based on the address + formatted_bank_number = format_bank_number(address, bank_size=bank_size) + + # SECTION + output += dump_section(formatted_bank_number, separator=separator) + + # INCBIN a range of bytes from the ROM + output += dump_incbin_for_section(address, bank_size=bank_size, baserom=baserom_name, separator=separator) + + # clean up newlines at the end of the output + if output[-2:] == "\n\n": + output = output[:-2] + output += "\n" + + return output + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("rompath", nargs="?", metavar="rompath", type=str) + args = parser.parse_args() + + # default to "baserom.gbc" in the current working directory + baserom = "baserom.gbc" + + # but let the user override the default + if args.rompath: + baserom = args.rompath + + # generate some asm + output = dump_sections(baserom) + + # dump everything to stdout + sys.stdout.write(output) |