mirror of https://github.com/pret/pokecrystal.git
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.
This commit is contained in:
parent
01e10a11b2
commit
23003bd772
|
@ -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)
|
5
main.asm
5
main.asm
|
@ -10305,8 +10305,11 @@ INCLUDE "maps/map_headers.asm"
|
|||
|
||||
INCLUDE "maps/second_map_headers.asm"
|
||||
|
||||
INCBIN "baserom.gbc",$966b0,$97f7e - $966b0
|
||||
INCBIN "baserom.gbc",$966b0,$96cb1 - $966b0
|
||||
|
||||
INCLUDE "scripting.asm"
|
||||
|
||||
INCBIN "baserom.gbc",$97c20,$35e
|
||||
|
||||
SECTION "bank26",DATA,BANK[$26]
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue