mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
131 lines
3.5 KiB
Python
Executable File
131 lines
3.5 KiB
Python
Executable File
#!/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)
|
|
|