summaryrefslogtreecommitdiff
path: root/pokemontools/disassemble_map_scripts.py
diff options
context:
space:
mode:
Diffstat (limited to 'pokemontools/disassemble_map_scripts.py')
-rw-r--r--pokemontools/disassemble_map_scripts.py151
1 files changed, 151 insertions, 0 deletions
diff --git a/pokemontools/disassemble_map_scripts.py b/pokemontools/disassemble_map_scripts.py
new file mode 100644
index 0000000..21df569
--- /dev/null
+++ b/pokemontools/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)