mirror of https://github.com/pret/pokecrystal.git
somewhat better command parsing
This commit is contained in:
parent
0e8510e3c2
commit
2c9c2424d8
|
@ -2463,12 +2463,15 @@ pksv_crystal_more = {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Command():
|
class Command():
|
||||||
def __init__(self, address=None):
|
def __init__(self, address=None, *pargs, **kwargs):
|
||||||
raise Exception, "i don't think anything actually calls this?"
|
#raise Exception, "i don't think anything actually calls this?"
|
||||||
self.params = {}
|
self.params = {}
|
||||||
if not is_valid_address(address):
|
if not is_valid_address(address):
|
||||||
raise Exception, "address is invalid"
|
raise Exception, "address is invalid"
|
||||||
self.address = address
|
self.address = address
|
||||||
|
self.last_address = None
|
||||||
|
self.params = {}
|
||||||
|
self.parse()
|
||||||
def to_asm(self):
|
def to_asm(self):
|
||||||
#start with the rgbasm macro name for this command
|
#start with the rgbasm macro name for this command
|
||||||
output = self.macro_name
|
output = self.macro_name
|
||||||
|
@ -2479,15 +2482,17 @@ class Command():
|
||||||
#start reading the bytes after the command byte
|
#start reading the bytes after the command byte
|
||||||
current_address = self.address+1
|
current_address = self.address+1
|
||||||
#add each param
|
#add each param
|
||||||
for param in self.params:
|
for (key, param) in self.params.items():
|
||||||
name = param.name
|
name = param.name
|
||||||
#the first param shouldn't have ", " prefixed
|
#the first param shouldn't have ", " prefixed
|
||||||
if first: first = False
|
if first:
|
||||||
|
output += " "
|
||||||
|
first = False
|
||||||
#but all other params should
|
#but all other params should
|
||||||
else: output += ", "
|
else: output += ", "
|
||||||
#now add the asm-compatible param string
|
#now add the asm-compatible param string
|
||||||
output += obj.to_asm()
|
output += param.to_asm()
|
||||||
current_address += obj.size
|
current_address += param.size
|
||||||
#for param_type in self.param_types:
|
#for param_type in self.param_types:
|
||||||
# name = param_type["name"]
|
# name = param_type["name"]
|
||||||
# klass = param_type["klass"]
|
# klass = param_type["klass"]
|
||||||
|
@ -2505,11 +2510,10 @@ class Command():
|
||||||
def parse(self):
|
def parse(self):
|
||||||
#id, size (inclusive), param_types
|
#id, size (inclusive), param_types
|
||||||
#param_type = {"name": each[1], "class": each[0]}
|
#param_type = {"name": each[1], "class": each[0]}
|
||||||
self.params = {}
|
|
||||||
current_address = self.address+1
|
current_address = self.address+1
|
||||||
byte = int(rom[self.address])
|
byte = ord(rom[self.address])
|
||||||
if not byte == self.id:
|
if not byte == self.id:
|
||||||
raise Exception, "this should never happen"
|
raise Exception, "byte ("+hex(byte)+") != self.id ("+hex(self.id)+")"
|
||||||
i = 0
|
i = 0
|
||||||
for (key, param_type) in self.param_types.items():
|
for (key, param_type) in self.param_types.items():
|
||||||
name = param_type["name"]
|
name = param_type["name"]
|
||||||
|
@ -2522,6 +2526,7 @@ class Command():
|
||||||
#increment our counters
|
#increment our counters
|
||||||
current_address += obj.size
|
current_address += obj.size
|
||||||
i += 1
|
i += 1
|
||||||
|
self.last_address = current_address
|
||||||
return True
|
return True
|
||||||
class GivePoke(Command):
|
class GivePoke(Command):
|
||||||
id = 0x2D
|
id = 0x2D
|
||||||
|
@ -2554,6 +2559,7 @@ class GivePoke(Command):
|
||||||
#increment our counters
|
#increment our counters
|
||||||
current_address += obj.size
|
current_address += obj.size
|
||||||
i += 1
|
i += 1
|
||||||
|
self.last_address = current_address
|
||||||
return True
|
return True
|
||||||
|
|
||||||
#these cause the script to end; used in create_command_classes
|
#these cause the script to end; used in create_command_classes
|
||||||
|
@ -2564,10 +2570,10 @@ def create_command_classes(debug=False):
|
||||||
klasses = []
|
klasses = []
|
||||||
for (byte, cmd) in pksv_crystal_more.items():
|
for (byte, cmd) in pksv_crystal_more.items():
|
||||||
cmd_name = cmd[0]
|
cmd_name = cmd[0]
|
||||||
params = {"id": byte, "size": 1, "end": byte in pksv_crystal_more_enders}
|
params = {"id": byte, "size": 1, "end": byte in pksv_crystal_more_enders, "macro_name": cmd_name}
|
||||||
|
params["param_types"] = {}
|
||||||
if len(cmd) > 1:
|
if len(cmd) > 1:
|
||||||
param_types = cmd[1:]
|
param_types = cmd[1:]
|
||||||
params["param_types"] = {}
|
|
||||||
for (i, each) in enumerate(param_types):
|
for (i, each) in enumerate(param_types):
|
||||||
thing = {"name": each[0], "class": each[1]}
|
thing = {"name": each[0], "class": each[1]}
|
||||||
params["param_types"][i] = thing
|
params["param_types"][i] = thing
|
||||||
|
@ -2583,6 +2589,31 @@ def create_command_classes(debug=False):
|
||||||
return klasses
|
return klasses
|
||||||
command_classes = create_command_classes()
|
command_classes = create_command_classes()
|
||||||
|
|
||||||
|
def parse_script_with_command_classes(start_address):
|
||||||
|
"""parses a script using the Command classes
|
||||||
|
as an alternative to the old method using hard-coded commands"""
|
||||||
|
global command_classes
|
||||||
|
current_address = start_address
|
||||||
|
commands = []
|
||||||
|
end = False
|
||||||
|
while not end:
|
||||||
|
cur_byte = ord(rom[current_address])
|
||||||
|
#find the right address
|
||||||
|
right_kls = None
|
||||||
|
for kls in command_classes:
|
||||||
|
if kls.id == cur_byte:
|
||||||
|
right_kls = kls
|
||||||
|
if right_kls == None:
|
||||||
|
asm_output = ""
|
||||||
|
for command in commands:
|
||||||
|
asm_output += command.to_asm() + "\n"
|
||||||
|
raise Exception, "no command found? id: " + hex(cur_byte) + " at " + hex(current_address) + " asm is:\n" + asm_output
|
||||||
|
cls = right_kls(address=current_address)
|
||||||
|
end = cls.end
|
||||||
|
commands.append(cls)
|
||||||
|
current_address = cls.last_address + 1
|
||||||
|
return commands
|
||||||
|
|
||||||
#use this to keep track of commands without pksv names
|
#use this to keep track of commands without pksv names
|
||||||
pksv_no_names = {}
|
pksv_no_names = {}
|
||||||
def pretty_print_pksv_no_names():
|
def pretty_print_pksv_no_names():
|
||||||
|
@ -6738,7 +6769,7 @@ class TestMultiByteParam(unittest.TestCase):
|
||||||
"line_number": 2
|
"line_number": 2
|
||||||
}]
|
}]
|
||||||
self.assertEqual(self.cls.to_asm(), "poop")
|
self.assertEqual(self.cls.to_asm(), "poop")
|
||||||
class TestPostParsing(unittest.TestCase):
|
class TestPostParsing: #(unittest.TestCase):
|
||||||
"""tests that must be run after parsing all maps"""
|
"""tests that must be run after parsing all maps"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
|
Loading…
Reference in New Issue