mirror of https://github.com/pret/pokecrystal.git
keep track of which scripts have been parsed
This commit is contained in:
parent
550ca496d6
commit
69f541f541
|
@ -6,6 +6,10 @@
|
||||||
import sys
|
import sys
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
|
#for IntervalMap
|
||||||
|
from bisect import bisect_left, bisect_right
|
||||||
|
from itertools import izip
|
||||||
|
|
||||||
#table of pointers to map groups
|
#table of pointers to map groups
|
||||||
#each map group contains some number of map headers
|
#each map group contains some number of map headers
|
||||||
map_group_pointer_table = 0x94000
|
map_group_pointer_table = 0x94000
|
||||||
|
@ -296,6 +300,109 @@ for key, value in jap_chars.items():
|
||||||
if key not in chars.keys():
|
if key not in chars.keys():
|
||||||
chars[key] = value
|
chars[key] = value
|
||||||
|
|
||||||
|
class IntervalMap(object):
|
||||||
|
"""
|
||||||
|
This class maps a set of intervals to a set of values.
|
||||||
|
|
||||||
|
>>> i = IntervalMap()
|
||||||
|
>>> i[0:5] = "hello world"
|
||||||
|
>>> i[6:10] = "hello cruel world"
|
||||||
|
>>> print i[4]
|
||||||
|
"hello world"
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
"""initializes an empty IntervalMap"""
|
||||||
|
self._bounds = []
|
||||||
|
self._items = []
|
||||||
|
self._upperitem = None
|
||||||
|
def __setitem__(self, _slice, _value):
|
||||||
|
"""sets an interval mapping"""
|
||||||
|
assert isinstance(_slice, slice), 'The key must be a slice object'
|
||||||
|
|
||||||
|
if _slice.start is None:
|
||||||
|
start_point = -1
|
||||||
|
else:
|
||||||
|
start_point = bisect_left(self._bounds, _slice.start)
|
||||||
|
|
||||||
|
if _slice.stop is None:
|
||||||
|
end_point = -1
|
||||||
|
else:
|
||||||
|
end_point = bisect_left(self._bounds, _slice.stop)
|
||||||
|
|
||||||
|
if start_point>=0:
|
||||||
|
if start_point < len(self._bounds) and self._bounds[start_point]<_slice.start:
|
||||||
|
start_point += 1
|
||||||
|
|
||||||
|
if end_point>=0:
|
||||||
|
self._bounds[start_point:end_point] = [_slice.start, _slice.stop]
|
||||||
|
if start_point < len(self._items):
|
||||||
|
self._items[start_point:end_point] = [self._items[start_point], _value]
|
||||||
|
else:
|
||||||
|
self._items[start_point:end_point] = [self._upperitem, _value]
|
||||||
|
else:
|
||||||
|
self._bounds[start_point:] = [_slice.start]
|
||||||
|
if start_point < len(self._items):
|
||||||
|
self._items[start_point:] = [self._items[start_point], _value]
|
||||||
|
else:
|
||||||
|
self._items[start_point:] = [self._upperitem]
|
||||||
|
self._upperitem = _value
|
||||||
|
else:
|
||||||
|
if end_point>=0:
|
||||||
|
self._bounds[:end_point] = [_slice.stop]
|
||||||
|
self._items[:end_point] = [_value]
|
||||||
|
else:
|
||||||
|
self._bounds[:] = []
|
||||||
|
self._items[:] = []
|
||||||
|
self._upperitem = _value
|
||||||
|
def __getitem__(self,_point):
|
||||||
|
"""gets a value from the mapping"""
|
||||||
|
assert not isinstance(_point, slice), 'The key cannot be a slice object'
|
||||||
|
|
||||||
|
index = bisect_right(self._bounds, _point)
|
||||||
|
if index < len(self._bounds):
|
||||||
|
return self._items[index]
|
||||||
|
else:
|
||||||
|
return self._upperitem
|
||||||
|
def items(self):
|
||||||
|
"""returns an iterator with each item being
|
||||||
|
((low_bound, high_bound), value)
|
||||||
|
these items are returned in order"""
|
||||||
|
previous_bound = None
|
||||||
|
for (b, v) in izip(self._bounds, self._items):
|
||||||
|
if v is not None:
|
||||||
|
yield (previous_bound, b), v
|
||||||
|
previous_bound = b
|
||||||
|
if self._upperitem is not None:
|
||||||
|
yield (previous_bound, None), self._upperitem
|
||||||
|
def values(self):
|
||||||
|
"""returns an iterator with each item being a stored value
|
||||||
|
the items are returned in order"""
|
||||||
|
for v in self._items:
|
||||||
|
if v is not None:
|
||||||
|
yield v
|
||||||
|
if self._upperitem is not None:
|
||||||
|
yield self._upperitem
|
||||||
|
def __repr__(self):
|
||||||
|
s = []
|
||||||
|
for b,v in self.items():
|
||||||
|
if v is not None:
|
||||||
|
s.append('[%r, %r] => %r'%(
|
||||||
|
b[0],
|
||||||
|
b[1],
|
||||||
|
v
|
||||||
|
))
|
||||||
|
return '{'+', '.join(s)+'}'
|
||||||
|
|
||||||
|
#keys are intervals "500..555" of byte addresses for each script
|
||||||
|
#last byte is not inclusive
|
||||||
|
#this is how to make sure scripts are not recalculated
|
||||||
|
script_parse_table = IntervalMap()
|
||||||
|
|
||||||
|
def is_script_already_parsed_at(address):
|
||||||
|
"""looks up whether or not a script is parsed at a certain address"""
|
||||||
|
if script_parse_table[address] == None: return False
|
||||||
|
return True
|
||||||
|
|
||||||
def map_name_cleaner(input):
|
def map_name_cleaner(input):
|
||||||
"""generate a valid asm label for a given map name"""
|
"""generate a valid asm label for a given map name"""
|
||||||
return input.replace(":", "").\
|
return input.replace(":", "").\
|
||||||
|
@ -412,7 +519,7 @@ def clean_up_long_info(long_info):
|
||||||
long_info = "\n".join(new_lines)
|
long_info = "\n".join(new_lines)
|
||||||
return long_info
|
return long_info
|
||||||
|
|
||||||
def command_debug_information(command_byte=None, map_group=None, map_id=None, address=None, info=None, long_info=None, pksv_name=None):
|
def command_debug_information(command_byte=None, map_group=None, map_id=None, address=0, info=None, long_info=None, pksv_name=None):
|
||||||
info1 = "parsing command byte " + hex(command_byte) + " for map " + \
|
info1 = "parsing command byte " + hex(command_byte) + " for map " + \
|
||||||
str(map_group) + "." + str(map_id) + " at " + hex(address)
|
str(map_group) + "." + str(map_id) + " at " + hex(address)
|
||||||
info1 += " pksv: " + str(pksv_name)
|
info1 += " pksv: " + str(pksv_name)
|
||||||
|
@ -1095,24 +1202,37 @@ def pretty_print_pksv_no_names():
|
||||||
for address in addresses:
|
for address in addresses:
|
||||||
print " " + hex(address)
|
print " " + hex(address)
|
||||||
|
|
||||||
def parse_script_engine_script_at(address, map_group=None, map_id=None):
|
def parse_script_engine_script_at(address, map_group=None, map_id=None, force=False):
|
||||||
"""parses a script-engine script"""
|
"""parses a script-engine script"""
|
||||||
global rom
|
global rom
|
||||||
if rom == None:
|
if rom == None:
|
||||||
load_rom()
|
load_rom()
|
||||||
|
#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
|
||||||
|
#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 = {}
|
commands = {}
|
||||||
offset = address
|
offset = address
|
||||||
end = False
|
end = False
|
||||||
|
#main loop.. parse each command byte
|
||||||
while not end:
|
while not end:
|
||||||
|
#reset variables so we don't contaminate this command
|
||||||
info, long_info, size = None, None, 0
|
info, long_info, size = None, None, 0
|
||||||
|
#read the current command byte
|
||||||
command_byte = ord(rom[offset])
|
command_byte = ord(rom[offset])
|
||||||
|
#setup the current command representation
|
||||||
command = {"type": command_byte, "start_address": offset}
|
command = {"type": command_byte, "start_address": offset}
|
||||||
|
|
||||||
#size is the total size including the command byte
|
#size is the total size including the command byte
|
||||||
#last_byte_address is offset+size-1
|
#last_byte_address is offset+size-1
|
||||||
start_address = offset
|
start_address = offset
|
||||||
|
|
||||||
|
#start checking against possible command bytes
|
||||||
if command_byte == 0x00: #Pointer code [2b+ret]
|
if command_byte == 0x00: #Pointer code [2b+ret]
|
||||||
pksv_name = "2call"
|
pksv_name = "2call"
|
||||||
info = "pointer code"
|
info = "pointer code"
|
||||||
|
@ -2781,6 +2901,8 @@ def parse_script_engine_script_at(address, map_group=None, map_id=None):
|
||||||
offset += 1
|
offset += 1
|
||||||
#add the command into the command list please
|
#add the command into the command list please
|
||||||
commands[len(commands.keys())] = command
|
commands[len(commands.keys())] = command
|
||||||
|
|
||||||
|
script_parse_table[original_start_address : offset-1] = commands
|
||||||
return commands
|
return commands
|
||||||
|
|
||||||
def parse_warp_bytes(some_bytes):
|
def parse_warp_bytes(some_bytes):
|
||||||
|
|
Loading…
Reference in New Issue