mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
refactor script parsing into a Script class
This commit is contained in:
parent
a4b19fe60a
commit
651d801734
@ -1144,7 +1144,7 @@ def find_all_text_pointers_in_script_engine_script(script, bank=None, debug=Fals
|
||||
#TODO: recursively follow any jumps in the script
|
||||
if script == None: return []
|
||||
addresses = set()
|
||||
for (k, command) in script.items():
|
||||
for (k, command) in script.commands.items():
|
||||
if debug:
|
||||
print "command is: " + str(command)
|
||||
if command["type"] == 0x4B:
|
||||
@ -1520,35 +1520,118 @@ stop_points = [0x1aafa2,
|
||||
0x9f58f, #battle tower
|
||||
0x9f62f, #battle tower
|
||||
]
|
||||
def parse_script_engine_script_at(address, map_group=None, map_id=None, force=False, debug=True, origin=False):
|
||||
"""parses a script-engine script
|
||||
force=True if you want to re-parse and get the debug information"""
|
||||
class Script():
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.address = None
|
||||
self.commands = None
|
||||
if len(kwargs) == 0 and len(args) == 0:
|
||||
raise Exception, "Script.__init__ must be given some arguments"
|
||||
#first positional argument is address
|
||||
if len(args) == 1:
|
||||
address = args[0]
|
||||
if type(address) == str:
|
||||
address = int(address, 16)
|
||||
elif type(address) != int:
|
||||
raise Exception, "address must be an integer or string"
|
||||
self.address = address
|
||||
elif len(args) > 1:
|
||||
raise Exception, "don't know what to do with second (or later) positional arguments"
|
||||
#parse the script at the address
|
||||
self.parse(**kwargs)
|
||||
def pksv_list(self):
|
||||
"""shows a list of pksv names for each command in the script"""
|
||||
items = []
|
||||
for (id, command) in self.commands.items():
|
||||
if command["type"] in pksv_crystal:
|
||||
items.append(pksv_crystal[command["type"]])
|
||||
else:
|
||||
items.append(hex(command["type"]))
|
||||
return items
|
||||
def to_pksv(self):
|
||||
"""returns a string of pksv command names"""
|
||||
pksv = self.pksv_list()
|
||||
output = "script starting at: "+hex(self.address)+" .. "
|
||||
first = True
|
||||
for item in pksv:
|
||||
item = str(item)
|
||||
if first:
|
||||
output += item
|
||||
first = False
|
||||
else:
|
||||
output += ", "+item
|
||||
return output
|
||||
def show_pksv(self):
|
||||
"""prints a list of pksv command names in this script"""
|
||||
print self.to_pksv()
|
||||
def parse(self, *args, **kwargs):
|
||||
"""parses a script-engine script; force=True if you want to re-parse
|
||||
and get the debug information"""
|
||||
#can't handle more than one argument
|
||||
if len(args) > 1:
|
||||
raise Exception, "Script.parse_script doesn't know how to handle positional arguments"
|
||||
#use the first positional argument as the address
|
||||
elif len(args) == 1:
|
||||
self.address = args[0]
|
||||
if type(self.address) == str:
|
||||
self.address = int(self.address, 16)
|
||||
elif type(self.address) != int:
|
||||
raise Exception, "address param is the wrong type"
|
||||
#parse any keyword arguments, first make up the defaults
|
||||
kwargsorig = {"map_group": None, "map_id": None, "force": False, "debug": True, "origin": False}
|
||||
#let the caller override any defaults
|
||||
kwargsorig.update(kwargs)
|
||||
#copy these into kwargs
|
||||
kwargs = kwargsorig
|
||||
#set these defaults
|
||||
map_group = kwargs["map_group"]
|
||||
map_id = kwargs["map_id"]
|
||||
force = kwargs["force"]
|
||||
debug = kwargs["debug"]
|
||||
origin = kwargs["origin"]
|
||||
self.map_group = map_group
|
||||
self.map_id = map_id
|
||||
|
||||
global rom
|
||||
if rom == None:
|
||||
load_rom()
|
||||
|
||||
#max number of commands in a 'recursive' script
|
||||
max_cmds = 150
|
||||
|
||||
#set the address to be parsed
|
||||
address = self.address
|
||||
original_start_address = address
|
||||
|
||||
#don't parse these crazy things (battle tower things, some rival things, etc.)
|
||||
if address in stop_points:
|
||||
print "got " + hex(address) + ".. map_group=" + str(map_group) + " map_id=" + str(map_id)
|
||||
return {}
|
||||
return None
|
||||
#don't parse anything that looks crazy
|
||||
if address < 0x4000 and address not in [0x26ef, 0x114, 0x1108]:
|
||||
print "address is less than 0x4000.. address is: " + hex(address)
|
||||
sys.exit()
|
||||
|
||||
#max number of commands in a 'recursive' script
|
||||
max_cmds = 150
|
||||
|
||||
#check if work is being repeated
|
||||
if is_script_already_parsed_at(address) and not force:
|
||||
return script_parse_table[address]
|
||||
original_start_address = address
|
||||
raise Exception, "this script has already been parsed before, please use that instance"
|
||||
#use the commands from a previously-parsed Script object
|
||||
#self.commands = script_parse_table[address].commands
|
||||
#return True
|
||||
|
||||
#return a previously-created Script object
|
||||
#return script_parse_table[address]
|
||||
|
||||
#this next line stops the same script from being re-parsed multiple times
|
||||
#for instance.. maybe there's a script jump, then a jump back
|
||||
#the original script should only be parsed once
|
||||
script_parse_table[original_start_address:original_start_address+1] = "incomplete"
|
||||
|
||||
#set up some variables
|
||||
commands = {}
|
||||
self.commands = {}
|
||||
commands = self.commands
|
||||
offset = address
|
||||
end = False
|
||||
|
||||
#main loop.. parse each command byte
|
||||
while not end:
|
||||
#reset variables so we don't contaminate this command
|
||||
@ -3344,8 +3427,13 @@ def parse_script_engine_script_at(address, map_group=None, map_id=None, force=Fa
|
||||
#add the command into the command list please
|
||||
commands[len(commands.keys())] = command
|
||||
|
||||
script_parse_table[original_start_address : offset-1] = commands
|
||||
return commands
|
||||
self.commands = commands
|
||||
script_parse_table[original_start_address : offset-1] = self
|
||||
return True
|
||||
def parse_script_engine_script_at(address, map_group=None, map_id=None, force=False, debug=True, origin=True):
|
||||
if is_script_already_parsed_at(address) and not force:
|
||||
return script_parse_table[address]
|
||||
return Script(address, map_group=map_group, map_id=map_id, force=force, debug=debug, origin=origin)
|
||||
|
||||
def parse_warp_bytes(some_bytes, debug=True):
|
||||
"""parse some number of warps from the data"""
|
||||
@ -4427,6 +4515,10 @@ for map_group_id in map_names.keys():
|
||||
#set the value in the original dictionary
|
||||
map_names[map_group_id][map_id]["label"] = cleaned_name
|
||||
|
||||
#### pretty printing ###
|
||||
#texts: TextScript.to_asm_at
|
||||
#scripts: Script.to_asm_at
|
||||
|
||||
#### asm utilities ####
|
||||
#these are pulled in from pokered/extras/analyze_incbins.py
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user