diff options
| author | Bryan Bishop <kanzure@gmail.com> | 2013-02-27 23:31:12 -0600 | 
|---|---|---|
| committer | Bryan Bishop <kanzure@gmail.com> | 2013-02-27 23:31:12 -0600 | 
| commit | 4f71947645b2d429035aff3c07090f025c6d893c (patch) | |
| tree | 6a0f9f9685f05325ea27063dbed744692cc9c46f | |
| parent | 2b2f00f08b9cf70ff0901fc1c4381e4de492caf3 (diff) | |
disassemble scripting engine commands
All commands are in scripting.asm, and there's also a small python
script that was written to assist with some of the automation.
original-commit-id: 23003bd772a2b025ea1972fade00309cc04003a7
| -rw-r--r-- | disassemble_map_scripts.py | 151 | 
1 files changed, 151 insertions, 0 deletions
| diff --git a/disassemble_map_scripts.py b/disassemble_map_scripts.py new file mode 100644 index 0000000..21df569 --- /dev/null +++ b/disassemble_map_scripts.py @@ -0,0 +1,151 @@ +# -*- encoding: utf-8 -*- +""" +Dump out asm for scripting things in bank $25. This script will modify main.asm +and insert all scripting commands. +""" + +import crystal +from gbz80disasm import output_bank_opcodes + +rom = crystal.load_rom() +roml = [ord(x) for x in rom] + +script_command_table_address = 0x96cb1 +script_command_count = 170 + +# a list of addresses for each script command +command_pointers = [crystal.calculate_pointer_from_bytes_at(script_command_table_address + (id * 2), bank=0x25) for id in range(0, 170)] + +# a list of hex addresses for each script command in bank $25 +command_pointers_hex = ["$%.2x" % (x % 0x4000 + 0x4000) for x in command_pointers] + +commands = {} + +# force data into a more usable form +for command in crystal.command_classes: +    name = "Script_" + command.macro_name +    id = command.id +    params = {} + +    for (id2, param_type) in command.param_types.items(): +        param = { +            "name": param_type["name"], +            "type": param_type["class"].__name__, +        } +        params[id2] = param + +    if id <= 0xa9: +        commands[id] = { +            "name": name, +            "params": params, +            "address": command_pointers[id], +        } + +avoid = [ +    0x974b0, +    0x974be, +    0x9754b, +    0x97556, +    0x97562, +    0x9756e, +    0x97540, + +    0x96f8e, # verbosegiveitem2 +] + +class DisassembledScriptCommand(): +    """ +    Just a temporary object to store information about a script command's asm. +    This is used by some of the infrastructure in crystal.py to automatically +    insert asm into main.asm, rather than having someone do it manually. +    """ +    dependencies = None + +    def __init__(self, label=None, id=None, address=None, params=None): +        self.id = id +        self.label = crystal.Label(name=label, address=address, object=self) +        self.address = address +        self.params = params + +        max_byte_count = 0x4000 + +        # Some of these scripts need to be truncated before insertion, because +        # output_bank_opcodes doesn't know anything about stopping if some of +        # the local labels are not resolved yet. + +        # Script_if_equal +        if address == 0x97540: +            max_byte_count = 86 + +        # disassemble and laso get the last address +        (asm, last_address, last_hl_address, last_a_address, used_3d97) = output_bank_opcodes(address, max_byte_count=max_byte_count, stop_at=command_pointers, include_last_address=False) + +        # remove indentation +        asm = asm.replace("\n\t", "\n") +        if asm[0] == "\t": +            asm = asm[1:] + +        # remove the last two newlines +        while asm[-1] == "\n": +            asm = asm[:-1] + +        self.asm = asm +        self.last_address = last_address + +        # make sure this gets dumped into main.asm +        #if crystal.script_parse_table[self.address] == None and crystal.script_parse_table[self.last_address] == None: +        crystal.script_parse_table[self.address : self.last_address] = self +        #else: +        #    print ".. hm, something is already at " + hex(self.address) + " for " + self.label.name + +    def to_asm(self): +        #output += self.label + ": ; " + hex(self.address) + "\n" +        output = "; script command " + hex(self.id) + "\n" +        if len(self.params) > 0: +            output += "; parameters:\n" +        for (id2, param) in self.params.items(): +            output += ";     " + param["name"] + " (" + param["type"] + ")\n" +        output += "\n" +        output += self.asm +        return output + +    def get_dependencies(*args, **kwargs): +        return [] + +# make instances of DisassembledScriptCommand +for (id, command) in commands.items(): +    name = command["name"] +    params = command["params"] +    address = command["address"] + +    script_asm = DisassembledScriptCommand(label=name, id=id, address=address, params=params) +    #print script_asm.to_asm() +    #print crystal.to_asm(script_asm, use_asm_rules=True) + +class ScriptCommandTable(): +    address = script_command_table_address +    last_address = script_command_table_address + (2 * 170) +    dependencies = None + +    def __init__(self): +        self.label = crystal.Label(name="ScriptCommandTable", address=self.address, object=self) + +        # make sure this gets dumped into main.asm +        crystal.script_parse_table[self.address : self.last_address] = self + +    def get_dependencies(*args, **kwargs): +        return [] + +    def to_asm(self): +        output = "" +        for (id, command) in commands.items(): +            output += "dw " + command["name"] + "; " + hex(command["address"]) + "\n" +        if output[-1] == "\n": +            output = output[:-1] +        return output +script_command_table = ScriptCommandTable() +#print crystal.to_asm(script_command_table, use_asm_rules=True) + +# automatic asm insertion +asm = crystal.Asm() +asm.insert_and_dump(limit=500) | 
