fix docstring formatting everywhere
This commit is contained in:
@@ -17,12 +17,14 @@ from romstr import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
def load_rom(path):
|
def load_rom(path):
|
||||||
""" Loads a ROM file into an abbreviated RomStr object.
|
"""
|
||||||
|
Loads a ROM file into an abbreviated RomStr object.
|
||||||
"""
|
"""
|
||||||
return direct_load_rom(filename=path)
|
return direct_load_rom(filename=path)
|
||||||
|
|
||||||
def load_asm(path):
|
def load_asm(path):
|
||||||
""" Loads source ASM into an abbreviated AsmList object.
|
"""
|
||||||
|
Loads source ASM into an abbreviated AsmList object.
|
||||||
"""
|
"""
|
||||||
return direct_load_asm(filename=path)
|
return direct_load_asm(filename=path)
|
||||||
|
|
||||||
@@ -38,7 +40,8 @@ def findall_iter(sub, string):
|
|||||||
return iter(next_index(len(sub)).next, -1)
|
return iter(next_index(len(sub)).next, -1)
|
||||||
|
|
||||||
class Address(int):
|
class Address(int):
|
||||||
""" A simple int wrapper to take 0xFFFF and $FFFF addresses.
|
"""
|
||||||
|
A simple int wrapper to take 0xFFFF and $FFFF addresses.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(cls, x=None, *args, **kwargs):
|
def __new__(cls, x=None, *args, **kwargs):
|
||||||
@@ -59,8 +62,9 @@ class Address(int):
|
|||||||
found_blobs = []
|
found_blobs = []
|
||||||
|
|
||||||
class BinaryBlob(object):
|
class BinaryBlob(object):
|
||||||
""" Stores a label, line number, and addresses of a function from Pokémon
|
"""
|
||||||
Red. These details can be used to determine whether or not the function was
|
Stores a label, line number, and addresses of a function from Pokémon Red.
|
||||||
|
These details can be used to determine whether or not the function was
|
||||||
copied into Pokémon Crystal.
|
copied into Pokémon Crystal.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -100,7 +104,8 @@ class BinaryBlob(object):
|
|||||||
self.find_by_first_bytes()
|
self.find_by_first_bytes()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" A beautiful poem.
|
"""
|
||||||
|
A beautiful poem.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
r = "BinaryBlob("
|
r = "BinaryBlob("
|
||||||
@@ -122,13 +127,15 @@ class BinaryBlob(object):
|
|||||||
return self.__repr__()
|
return self.__repr__()
|
||||||
|
|
||||||
def parse_from_red(self):
|
def parse_from_red(self):
|
||||||
""" Reads bytes from Pokémon Red and stores them.
|
"""
|
||||||
|
Reads bytes from Pokémon Red and stores them.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.bytes = redrom[self.start_address : self.end_address + 1]
|
self.bytes = redrom[self.start_address : self.end_address + 1]
|
||||||
|
|
||||||
def pretty_bytes(self):
|
def pretty_bytes(self):
|
||||||
""" Returns a better looking range of bytes.
|
"""
|
||||||
|
Returns a better looking range of bytes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
bytes = redrom.interval(self.start_address, \
|
bytes = redrom.interval(self.start_address, \
|
||||||
@@ -138,7 +145,8 @@ class BinaryBlob(object):
|
|||||||
return bytes
|
return bytes
|
||||||
|
|
||||||
def find_in_crystal(self):
|
def find_in_crystal(self):
|
||||||
""" Checks whether or not the bytes appear in Pokémon Crystal.
|
"""
|
||||||
|
Checks whether or not the bytes appear in Pokémon Crystal.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
finditer = findall_iter(self.bytes, cryrom)
|
finditer = findall_iter(self.bytes, cryrom)
|
||||||
@@ -151,7 +159,8 @@ class BinaryBlob(object):
|
|||||||
print self.label + ": found " + str(len(self.locations)) + " matches."
|
print self.label + ": found " + str(len(self.locations)) + " matches."
|
||||||
|
|
||||||
def find_by_first_bytes(self):
|
def find_by_first_bytes(self):
|
||||||
""" Finds this blob in Crystal based on the first n bytes.
|
"""
|
||||||
|
Finds this blob in Crystal based on the first n bytes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# how many bytes to match
|
# how many bytes to match
|
||||||
@@ -184,7 +193,8 @@ redrom = load_rom(pokered_rom_path)
|
|||||||
redsrc = load_asm(pokered_src_path)
|
redsrc = load_asm(pokered_src_path)
|
||||||
|
|
||||||
def scan_red_asm(bank_stop=3, debug=True):
|
def scan_red_asm(bank_stop=3, debug=True):
|
||||||
""" Scans the ASM from Pokémon Red. Finds labels and objects. Does things.
|
"""
|
||||||
|
Scans the ASM from Pokémon Red. Finds labels and objects. Does things.
|
||||||
|
|
||||||
Uses get_label_from_line and get_address_from_line_comment.
|
Uses get_label_from_line and get_address_from_line_comment.
|
||||||
"""
|
"""
|
||||||
|
@@ -275,10 +275,11 @@ def command_debug_information(command_byte=None, map_group=None, map_id=None, ad
|
|||||||
|
|
||||||
all_texts = []
|
all_texts = []
|
||||||
class TextScript:
|
class TextScript:
|
||||||
""" A text is a sequence of bytes (and sometimes commands). It's not the
|
"""
|
||||||
same thing as a Script. The bytes are translated into characters based
|
A text is a sequence of bytes (and sometimes commands). It's not the same
|
||||||
on the lookup table (see chars.py). The in-text commands are for including
|
thing as a Script. The bytes are translated into characters based on the
|
||||||
values from RAM, playing sound, etc.
|
lookup table (see chars.py). The in-text commands are for including values
|
||||||
|
from RAM, playing sound, etc.
|
||||||
|
|
||||||
see: http://hax.iimarck.us/files/scriptingcodes_eng.htm#InText
|
see: http://hax.iimarck.us/files/scriptingcodes_eng.htm#InText
|
||||||
"""
|
"""
|
||||||
@@ -1157,7 +1158,8 @@ def generate_map_constants():
|
|||||||
print maps
|
print maps
|
||||||
|
|
||||||
def generate_map_constants_dimensions():
|
def generate_map_constants_dimensions():
|
||||||
""" Generate _WIDTH and _HEIGHT properties.
|
"""
|
||||||
|
Generate _WIDTH and _HEIGHT properties.
|
||||||
"""
|
"""
|
||||||
global map_internal_ids
|
global map_internal_ids
|
||||||
output = ""
|
output = ""
|
||||||
@@ -1172,8 +1174,10 @@ def generate_map_constants_dimensions():
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
def transform_wildmons(asm):
|
def transform_wildmons(asm):
|
||||||
""" Converts a wildmons section to use map constants.
|
"""
|
||||||
input: wildmons text. """
|
Converts a wildmons section to use map constants.
|
||||||
|
input: wildmons text.
|
||||||
|
"""
|
||||||
asmlines = asm.split("\n")
|
asmlines = asm.split("\n")
|
||||||
returnlines = []
|
returnlines = []
|
||||||
for line in asmlines:
|
for line in asmlines:
|
||||||
@@ -1899,7 +1903,8 @@ class GivePoke(Command):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
class DataByteWordMacro(Command):
|
class DataByteWordMacro(Command):
|
||||||
""" Only used by the preprocessor.
|
"""
|
||||||
|
Only used by the preprocessor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
id = None
|
id = None
|
||||||
@@ -2000,9 +2005,9 @@ movement_command_bases = {
|
|||||||
|
|
||||||
# create MovementCommands from movement_command_bases
|
# create MovementCommands from movement_command_bases
|
||||||
def create_movement_commands(debug=False):
|
def create_movement_commands(debug=False):
|
||||||
""" Creates MovementCommands from movement_command_bases.
|
"""
|
||||||
This is just a cheap trick instead of manually defining
|
Creates MovementCommands from movement_command_bases. This is just a cheap
|
||||||
all of those classes.
|
trick instead of manually defining all of those classes.
|
||||||
"""
|
"""
|
||||||
#movement_command_classes = inspect.getmembers(sys.modules[__name__], \
|
#movement_command_classes = inspect.getmembers(sys.modules[__name__], \
|
||||||
# lambda obj: inspect.isclass(obj) and \
|
# lambda obj: inspect.isclass(obj) and \
|
||||||
@@ -3561,7 +3566,8 @@ class TrainerFragmentParam(PointerLabelParam):
|
|||||||
|
|
||||||
trainer_group_table = None
|
trainer_group_table = None
|
||||||
class TrainerGroupTable:
|
class TrainerGroupTable:
|
||||||
""" A list of pointers.
|
"""
|
||||||
|
A list of pointers.
|
||||||
|
|
||||||
This should probably be called TrainerGroupPointerTable.
|
This should probably be called TrainerGroupPointerTable.
|
||||||
"""
|
"""
|
||||||
@@ -3639,7 +3645,8 @@ class TrainerGroupHeader:
|
|||||||
script_parse_table[address : self.last_address] = self
|
script_parse_table[address : self.last_address] = self
|
||||||
|
|
||||||
def get_dependencies(self, recompute=False, global_dependencies=set()):
|
def get_dependencies(self, recompute=False, global_dependencies=set()):
|
||||||
""" TrainerGroupHeader has no dependencies.
|
"""
|
||||||
|
TrainerGroupHeader has no dependencies.
|
||||||
"""
|
"""
|
||||||
# TODO: possibly include self.individual_trainer_headers
|
# TODO: possibly include self.individual_trainer_headers
|
||||||
if recompute or self.dependencies == None:
|
if recompute or self.dependencies == None:
|
||||||
@@ -3725,7 +3732,8 @@ class TrainerHeader:
|
|||||||
# TrainerGroupHeader covers its address range
|
# TrainerGroupHeader covers its address range
|
||||||
|
|
||||||
def make_name(self):
|
def make_name(self):
|
||||||
""" Must occur after parse() is called.
|
"""
|
||||||
|
Must occur after parse() is called.
|
||||||
Constructs a name based on self.parent.group_name and self.name.
|
Constructs a name based on self.parent.group_name and self.name.
|
||||||
"""
|
"""
|
||||||
if self.trainer_group_id in [0x14, 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2B, 0x2C, 0x2D, 0x2F, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x41]:
|
if self.trainer_group_id in [0x14, 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1C, 0x1D, 0x1E, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2B, 0x2C, 0x2D, 0x2F, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x41]:
|
||||||
@@ -3806,7 +3814,8 @@ class TrainerHeader:
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
class TrainerPartyMonParser:
|
class TrainerPartyMonParser:
|
||||||
""" Just a generic trainer party mon parser.
|
"""
|
||||||
|
Just a generic trainer party mon parser.
|
||||||
Don't use this directly. Only use the child classes.
|
Don't use this directly. Only use the child classes.
|
||||||
"""
|
"""
|
||||||
id = None
|
id = None
|
||||||
@@ -3863,7 +3872,9 @@ class TrainerPartyMonParser:
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
class TrainerPartyMonParser0(TrainerPartyMonParser):
|
class TrainerPartyMonParser0(TrainerPartyMonParser):
|
||||||
""" Data type <0x00>: Pokémon Data is <Level> <Species>. Used by most trainers. """
|
"""
|
||||||
|
Data type <0x00>: Pokémon Data is <Level> <Species>. Used by most trainers.
|
||||||
|
"""
|
||||||
id = 0
|
id = 0
|
||||||
size = 2 + 1
|
size = 2 + 1
|
||||||
param_types = {
|
param_types = {
|
||||||
@@ -3871,7 +3882,10 @@ class TrainerPartyMonParser0(TrainerPartyMonParser):
|
|||||||
1: {"name": "species", "class": PokemonParam},
|
1: {"name": "species", "class": PokemonParam},
|
||||||
}
|
}
|
||||||
class TrainerPartyMonParser1(TrainerPartyMonParser):
|
class TrainerPartyMonParser1(TrainerPartyMonParser):
|
||||||
""" Data type <0x01>: Pokémon Data is <Level> <Pokémon> <Move1> <Move2> <Move3> <Move4>. Used often for Gym Leaders."""
|
"""
|
||||||
|
Data type <0x01>: Pokémon Data is <Level> <Pokémon> <Move1> <Move2> <Move3>
|
||||||
|
<Move4>. Used often for Gym Leaders.
|
||||||
|
"""
|
||||||
id = 1
|
id = 1
|
||||||
size = 6 + 1
|
size = 6 + 1
|
||||||
param_types = {
|
param_types = {
|
||||||
@@ -3883,7 +3897,9 @@ class TrainerPartyMonParser1(TrainerPartyMonParser):
|
|||||||
5: {"name": "move4", "class": MoveParam},
|
5: {"name": "move4", "class": MoveParam},
|
||||||
}
|
}
|
||||||
class TrainerPartyMonParser2(TrainerPartyMonParser):
|
class TrainerPartyMonParser2(TrainerPartyMonParser):
|
||||||
""" Data type <0x02>: Pokémon Data is <Level> <Pokémon> <Held Item>. Used mainly by Pokéfans. """
|
"""
|
||||||
|
Data type <0x02>: Pokémon Data is <Level> <Pokémon> <Held Item>. Used mainly by Pokéfans.
|
||||||
|
"""
|
||||||
id = 2
|
id = 2
|
||||||
size = 3 + 1
|
size = 3 + 1
|
||||||
param_types = {
|
param_types = {
|
||||||
@@ -3892,8 +3908,11 @@ class TrainerPartyMonParser2(TrainerPartyMonParser):
|
|||||||
2: {"name": "item", "class": ItemLabelByte},
|
2: {"name": "item", "class": ItemLabelByte},
|
||||||
}
|
}
|
||||||
class TrainerPartyMonParser3(TrainerPartyMonParser):
|
class TrainerPartyMonParser3(TrainerPartyMonParser):
|
||||||
""" Data type <0x03>: Pokémon Data is <Level> <Pokémon> <Held Item> <Move1> <Move2> <Move3> <Move4>.
|
"""
|
||||||
Used by a few Cooltrainers. """
|
Data type <0x03>: Pokémon Data is <Level> <Pokémon> <Held Item> <Move1>
|
||||||
|
<Move2> <Move3> <Move4>.
|
||||||
|
Used by a few Cooltrainers.
|
||||||
|
"""
|
||||||
id = 3
|
id = 3
|
||||||
size = 7 + 1
|
size = 7 + 1
|
||||||
param_types = {
|
param_types = {
|
||||||
@@ -3909,7 +3928,8 @@ class TrainerPartyMonParser3(TrainerPartyMonParser):
|
|||||||
trainer_party_mon_parsers = [TrainerPartyMonParser0, TrainerPartyMonParser1, TrainerPartyMonParser2, TrainerPartyMonParser3]
|
trainer_party_mon_parsers = [TrainerPartyMonParser0, TrainerPartyMonParser1, TrainerPartyMonParser2, TrainerPartyMonParser3]
|
||||||
|
|
||||||
def find_trainer_ids_from_scripts():
|
def find_trainer_ids_from_scripts():
|
||||||
""" Looks through all scripts to find trainer group numbers and trainer numbers.
|
"""
|
||||||
|
Looks through all scripts to find trainer group numbers and trainer numbers.
|
||||||
|
|
||||||
This can be used with trainer_group_maximums to figure out the current number of
|
This can be used with trainer_group_maximums to figure out the current number of
|
||||||
trainers in each of the originating trainer groups.
|
trainers in each of the originating trainer groups.
|
||||||
@@ -3930,7 +3950,8 @@ def find_trainer_ids_from_scripts():
|
|||||||
trainer_group_maximums[key] = value
|
trainer_group_maximums[key] = value
|
||||||
|
|
||||||
def report_unreferenced_trainer_ids():
|
def report_unreferenced_trainer_ids():
|
||||||
""" Reports on the number of unreferenced trainer ids in each group.
|
"""
|
||||||
|
Reports on the number of unreferenced trainer ids in each group.
|
||||||
|
|
||||||
This should be called after find_trainer_ids_from_scripts.
|
This should be called after find_trainer_ids_from_scripts.
|
||||||
|
|
||||||
@@ -3971,7 +3992,8 @@ def report_unreferenced_trainer_ids():
|
|||||||
print "total unreferenced trainers: " + str(total_unreferenced_trainers)
|
print "total unreferenced trainers: " + str(total_unreferenced_trainers)
|
||||||
|
|
||||||
def check_script_has_trainer_data(script):
|
def check_script_has_trainer_data(script):
|
||||||
""" see find_trainer_ids_from_scripts
|
"""
|
||||||
|
see find_trainer_ids_from_scripts
|
||||||
"""
|
"""
|
||||||
for command in script.commands:
|
for command in script.commands:
|
||||||
trainer_group = None
|
trainer_group = None
|
||||||
@@ -3999,7 +4021,8 @@ def trainer_name_from_group(group_id, trainer_id=0):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
def trainer_group_report():
|
def trainer_group_report():
|
||||||
""" Reports how many trainer ids are used in each trainer group.
|
"""
|
||||||
|
Reports how many trainer ids are used in each trainer group.
|
||||||
"""
|
"""
|
||||||
output = ""
|
output = ""
|
||||||
total = 0
|
total = 0
|
||||||
@@ -4016,7 +4039,8 @@ def trainer_group_report():
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
def make_trainer_group_name_trainer_ids(trainer_group_table, debug=True):
|
def make_trainer_group_name_trainer_ids(trainer_group_table, debug=True):
|
||||||
""" Edits trainer_group_names and sets the trainer names.
|
"""
|
||||||
|
Edits trainer_group_names and sets the trainer names.
|
||||||
For instance, "AMY & MAY" becomes "AMY_AND_MAY1" and "AMY_AND_MAY2"
|
For instance, "AMY & MAY" becomes "AMY_AND_MAY1" and "AMY_AND_MAY2"
|
||||||
|
|
||||||
This should only be used after TrainerGroupTable.parse has been called.
|
This should only be used after TrainerGroupTable.parse has been called.
|
||||||
@@ -4054,7 +4078,8 @@ def make_trainer_group_name_trainer_ids(trainer_group_table, debug=True):
|
|||||||
print "done improving trainer names"
|
print "done improving trainer names"
|
||||||
|
|
||||||
def pretty_print_trainer_id_constants():
|
def pretty_print_trainer_id_constants():
|
||||||
""" Prints out some constants for trainer ids, for "constants.asm".
|
"""
|
||||||
|
Prints out some constants for trainer ids, for "constants.asm".
|
||||||
|
|
||||||
make_trainer_group_name_trainer_ids must be called prior to this.
|
make_trainer_group_name_trainer_ids must be called prior to this.
|
||||||
"""
|
"""
|
||||||
@@ -4785,7 +4810,8 @@ def old_parse_map_header_at(address, map_group=None, map_id=None, debug=True):
|
|||||||
|
|
||||||
|
|
||||||
def get_direction(connection_byte, connection_id):
|
def get_direction(connection_byte, connection_id):
|
||||||
""" Given a connection byte and a connection id, which direction is this
|
"""
|
||||||
|
Given a connection byte and a connection id, which direction is this
|
||||||
connection?
|
connection?
|
||||||
|
|
||||||
example:
|
example:
|
||||||
@@ -6228,7 +6254,8 @@ def parse_all_map_headers(debug=True):
|
|||||||
map_names[group_id][map_id]["header_old"] = old_parsed_map
|
map_names[group_id][map_id]["header_old"] = old_parsed_map
|
||||||
|
|
||||||
class PokedexEntryPointerTable:
|
class PokedexEntryPointerTable:
|
||||||
""" A list of pointers.
|
"""
|
||||||
|
A list of pointers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -6277,8 +6304,6 @@ class PokedexEntryPointerTable:
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
class PokedexEntry:
|
class PokedexEntry:
|
||||||
""" """
|
|
||||||
|
|
||||||
def __init__(self, address, pokemon_id):
|
def __init__(self, address, pokemon_id):
|
||||||
self.address = address
|
self.address = address
|
||||||
self.dependencies = None
|
self.dependencies = None
|
||||||
@@ -6767,7 +6792,8 @@ class Asm:
|
|||||||
return llabel
|
return llabel
|
||||||
return False
|
return False
|
||||||
def does_address_have_label(self, address):
|
def does_address_have_label(self, address):
|
||||||
""" Checks if an address has a label.
|
"""
|
||||||
|
Checks if an address has a label.
|
||||||
"""
|
"""
|
||||||
# either something will directly have the address
|
# either something will directly have the address
|
||||||
# or- it's possibel that no label was given
|
# or- it's possibel that no label was given
|
||||||
@@ -6993,8 +7019,8 @@ def list_things_in_bank(bank):
|
|||||||
return objects
|
return objects
|
||||||
|
|
||||||
def list_texts_in_bank(bank):
|
def list_texts_in_bank(bank):
|
||||||
""" Narrows down the list of objects
|
"""
|
||||||
that you will be inserting into Asm.
|
Narrows down the list of objects that you will be inserting into Asm.
|
||||||
"""
|
"""
|
||||||
if len(all_texts) == 0:
|
if len(all_texts) == 0:
|
||||||
raise Exception("all_texts is blank.. run_main() will populate it")
|
raise Exception("all_texts is blank.. run_main() will populate it")
|
||||||
@@ -7011,8 +7037,8 @@ def list_texts_in_bank(bank):
|
|||||||
return texts
|
return texts
|
||||||
|
|
||||||
def list_movements_in_bank(bank):
|
def list_movements_in_bank(bank):
|
||||||
""" Narrows down the list of objects
|
"""
|
||||||
to speed up Asm insertion.
|
Narrows down the list of objects to speed up Asm insertion.
|
||||||
"""
|
"""
|
||||||
if len(all_movements) == 0:
|
if len(all_movements) == 0:
|
||||||
raise Exception("all_movements is blank.. run_main() will populate it")
|
raise Exception("all_movements is blank.. run_main() will populate it")
|
||||||
@@ -7027,8 +7053,9 @@ def list_movements_in_bank(bank):
|
|||||||
return movements
|
return movements
|
||||||
|
|
||||||
def dump_asm_for_texts_in_bank(bank, start=50, end=100):
|
def dump_asm_for_texts_in_bank(bank, start=50, end=100):
|
||||||
""" Simple utility to help with dumping texts into a particular bank. This
|
"""
|
||||||
is helpful for figuring out which text is breaking that bank.
|
Simple utility to help with dumping texts into a particular bank. This is
|
||||||
|
helpful for figuring out which text is breaking that bank.
|
||||||
"""
|
"""
|
||||||
# load and parse the ROM if necessary
|
# load and parse the ROM if necessary
|
||||||
if rom == None or len(rom) <= 4:
|
if rom == None or len(rom) <= 4:
|
||||||
@@ -7063,7 +7090,8 @@ def dump_asm_for_movements_in_bank(bank, start=0, end=100):
|
|||||||
print "done dumping movements for bank $%.2x" % (bank)
|
print "done dumping movements for bank $%.2x" % (bank)
|
||||||
|
|
||||||
def dump_things_in_bank(bank, start=50, end=100):
|
def dump_things_in_bank(bank, start=50, end=100):
|
||||||
""" is helpful for figuring out which object is breaking that bank.
|
"""
|
||||||
|
is helpful for figuring out which object is breaking that bank.
|
||||||
"""
|
"""
|
||||||
# load and parse the ROM if necessary
|
# load and parse the ROM if necessary
|
||||||
if rom == None or len(rom) <= 4:
|
if rom == None or len(rom) <= 4:
|
||||||
@@ -7155,7 +7183,8 @@ def get_label_for(address):
|
|||||||
all_new_labels = []
|
all_new_labels = []
|
||||||
|
|
||||||
class Label:
|
class Label:
|
||||||
""" Every object in script_parse_table is given a label.
|
"""
|
||||||
|
Every object in script_parse_table is given a label.
|
||||||
|
|
||||||
This label is simply a way to keep track of what objects have
|
This label is simply a way to keep track of what objects have
|
||||||
been previously written to file.
|
been previously written to file.
|
||||||
@@ -7191,8 +7220,9 @@ class Label:
|
|||||||
all_new_labels.append(self)
|
all_new_labels.append(self)
|
||||||
|
|
||||||
def check_is_in_file(self):
|
def check_is_in_file(self):
|
||||||
""" This method checks if the label appears in the file
|
"""
|
||||||
based on the entries to the Asm.parts list.
|
This method checks if the label appears in the file based on the
|
||||||
|
entries to the Asm.parts list.
|
||||||
"""
|
"""
|
||||||
# assert new_asm != None, "new_asm should be an instance of Asm"
|
# assert new_asm != None, "new_asm should be an instance of Asm"
|
||||||
load_asm2()
|
load_asm2()
|
||||||
@@ -7201,18 +7231,19 @@ class Label:
|
|||||||
return is_in_file
|
return is_in_file
|
||||||
|
|
||||||
def check_address_is_in_file(self):
|
def check_address_is_in_file(self):
|
||||||
""" Checks if the address is in use by another label.
|
"""
|
||||||
|
Checks if the address is in use by another label.
|
||||||
"""
|
"""
|
||||||
load_asm2()
|
load_asm2()
|
||||||
self.address_is_in_file = new_asm.does_address_have_label(self.address)
|
self.address_is_in_file = new_asm.does_address_have_label(self.address)
|
||||||
return self.address_is_in_file
|
return self.address_is_in_file
|
||||||
|
|
||||||
def old_check_address_is_in_file(self):
|
def old_check_address_is_in_file(self):
|
||||||
""" Checks whether or not the address of the object is
|
"""
|
||||||
already in the file. This might happen if the label name
|
Checks whether or not the address of the object is already in the file.
|
||||||
is different but the address is the same. Another scenario
|
This might happen if the label name is different but the address is the
|
||||||
is that the label is already used, but at a different
|
same. Another scenario is that the label is already used, but at a
|
||||||
address.
|
different address.
|
||||||
|
|
||||||
This method works by looking at the INCBINs. When there is
|
This method works by looking at the INCBINs. When there is
|
||||||
an INCBIN that covers this address in the file, then there
|
an INCBIN that covers this address in the file, then there
|
||||||
@@ -7232,7 +7263,8 @@ class Label:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def make_label(self):
|
def make_label(self):
|
||||||
""" Generates a label name based on parents and self.object.
|
"""
|
||||||
|
Generates a label name based on parents and self.object.
|
||||||
"""
|
"""
|
||||||
object = self.object
|
object = self.object
|
||||||
name = object.make_label()
|
name = object.make_label()
|
||||||
|
@@ -10,7 +10,8 @@ from romstr import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
class RomGraph(nx.DiGraph):
|
class RomGraph(nx.DiGraph):
|
||||||
""" Graphs various functions pointing to each other.
|
"""
|
||||||
|
Graphs various functions pointing to each other.
|
||||||
|
|
||||||
TODO: Bank switches are nasty. They should be detected. Otherwise,
|
TODO: Bank switches are nasty. They should be detected. Otherwise,
|
||||||
functions will point to non-functions within the same bank. Another way
|
functions will point to non-functions within the same bank. Another way
|
||||||
@@ -35,7 +36,8 @@ class RomGraph(nx.DiGraph):
|
|||||||
rompath = "../baserom.gbc"
|
rompath = "../baserom.gbc"
|
||||||
|
|
||||||
def __init__(self, rom=None, **kwargs):
|
def __init__(self, rom=None, **kwargs):
|
||||||
""" Loads and parses the ROM into a function graph.
|
"""
|
||||||
|
Loads and parses the ROM into a function graph.
|
||||||
"""
|
"""
|
||||||
# continue the initialization
|
# continue the initialization
|
||||||
nx.DiGraph.__init__(self, **kwargs)
|
nx.DiGraph.__init__(self, **kwargs)
|
||||||
@@ -50,14 +52,16 @@ class RomGraph(nx.DiGraph):
|
|||||||
self.parse()
|
self.parse()
|
||||||
|
|
||||||
def load_rom(self):
|
def load_rom(self):
|
||||||
""" Creates a RomStr from rompath.
|
"""
|
||||||
|
Creates a RomStr from rompath.
|
||||||
"""
|
"""
|
||||||
file_handler = open(self.rompath, "r")
|
file_handler = open(self.rompath, "r")
|
||||||
self.rom = RomStr(file_handler.read())
|
self.rom = RomStr(file_handler.read())
|
||||||
file_handler.close()
|
file_handler.close()
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
""" Parses the ROM starting with the first function address. Each
|
"""
|
||||||
|
Parses the ROM starting with the first function address. Each
|
||||||
function is disassembled and parsed to find where else it leads to.
|
function is disassembled and parsed to find where else it leads to.
|
||||||
"""
|
"""
|
||||||
functions = {}
|
functions = {}
|
||||||
@@ -123,13 +127,15 @@ class RomGraph(nx.DiGraph):
|
|||||||
self.functions = functions
|
self.functions = functions
|
||||||
|
|
||||||
def pretty_printer(self):
|
def pretty_printer(self):
|
||||||
""" Shows some text output describing which nodes point to which other
|
"""
|
||||||
|
Shows some text output describing which nodes point to which other
|
||||||
nodes.
|
nodes.
|
||||||
"""
|
"""
|
||||||
print self.edges()
|
print self.edges()
|
||||||
|
|
||||||
def to_d3(self):
|
def to_d3(self):
|
||||||
""" Exports to d3.js because we're gangster like that.
|
"""
|
||||||
|
Exports to d3.js because we're gangster like that.
|
||||||
"""
|
"""
|
||||||
import networkx.readwrite.json_graph as json_graph
|
import networkx.readwrite.json_graph as json_graph
|
||||||
content = json_graph.dumps(self)
|
content = json_graph.dumps(self)
|
||||||
@@ -138,12 +144,14 @@ class RomGraph(nx.DiGraph):
|
|||||||
fh.close()
|
fh.close()
|
||||||
|
|
||||||
def to_gephi(self):
|
def to_gephi(self):
|
||||||
""" Generates a gexf file.
|
"""
|
||||||
|
Generates a gexf file.
|
||||||
"""
|
"""
|
||||||
nx.write_gexf(self, "graph.gexf")
|
nx.write_gexf(self, "graph.gexf")
|
||||||
|
|
||||||
class RedGraph(RomGraph):
|
class RedGraph(RomGraph):
|
||||||
""" Not implemented. Go away.
|
"""
|
||||||
|
Not implemented. Go away.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rompath = "../pokered-baserom.gbc"
|
rompath = "../pokered-baserom.gbc"
|
||||||
|
@@ -130,7 +130,8 @@ def line_has_comment_address(line, returnable={}, bank=None):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def get_address_from_line_comment(line, bank=None):
|
def get_address_from_line_comment(line, bank=None):
|
||||||
""" wrapper for line_has_comment_address
|
"""
|
||||||
|
wrapper for line_has_comment_address
|
||||||
"""
|
"""
|
||||||
returnable = {}
|
returnable = {}
|
||||||
result = line_has_comment_address(line, returnable=returnable, bank=bank)
|
result = line_has_comment_address(line, returnable=returnable, bank=bank)
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
|
||||||
"""
|
|
||||||
|
|
||||||
# this is modified in crystal.py during run-time
|
# this is modified in crystal.py during run-time
|
||||||
map_names = {
|
map_names = {
|
||||||
|
@@ -32,7 +32,8 @@ end_08_scripts_with = [
|
|||||||
spacing = "\t"
|
spacing = "\t"
|
||||||
|
|
||||||
class RomStr(str):
|
class RomStr(str):
|
||||||
""" Simple wrapper to prevent a giant rom from being shown on screen.
|
"""
|
||||||
|
Simple wrapper to prevent a giant rom from being shown on screen.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -41,13 +42,15 @@ class RomStr(str):
|
|||||||
str.__init__(self)
|
str.__init__(self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" Simplifies this object so that the output doesn't overflow stdout.
|
"""
|
||||||
|
Simplifies this object so that the output doesn't overflow stdout.
|
||||||
"""
|
"""
|
||||||
return "RomStr(too long)"
|
return "RomStr(too long)"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load(cls, filename=None, crystal=True, red=False):
|
def load(cls, filename=None, crystal=True, red=False):
|
||||||
""" Loads a ROM into a RomStr.
|
"""
|
||||||
|
Loads a ROM into a RomStr.
|
||||||
"""
|
"""
|
||||||
if crystal and not red and not filename:
|
if crystal and not red and not filename:
|
||||||
file_handler = open("../baserom.gbc", "r")
|
file_handler = open("../baserom.gbc", "r")
|
||||||
@@ -62,7 +65,8 @@ class RomStr(str):
|
|||||||
return RomStr(bytes)
|
return RomStr(bytes)
|
||||||
|
|
||||||
def load_labels(self, filename="labels.json"):
|
def load_labels(self, filename="labels.json"):
|
||||||
""" Loads labels from labels.json, or parses the source code file and
|
"""
|
||||||
|
Loads labels from labels.json, or parses the source code file and
|
||||||
generates new labels.
|
generates new labels.
|
||||||
"""
|
"""
|
||||||
filename = os.path.join(os.path.dirname(__file__), filename)
|
filename = os.path.join(os.path.dirname(__file__), filename)
|
||||||
@@ -109,7 +113,8 @@ class RomStr(str):
|
|||||||
self.labels = json.read(open(filename, "r").read())
|
self.labels = json.read(open(filename, "r").read())
|
||||||
|
|
||||||
def get_address_for(self, label):
|
def get_address_for(self, label):
|
||||||
""" Returns the address of a label. This is slow and could be improved
|
"""
|
||||||
|
Returns the address of a label. This is slow and could be improved
|
||||||
dramatically.
|
dramatically.
|
||||||
"""
|
"""
|
||||||
label = str(label)
|
label = str(label)
|
||||||
@@ -119,18 +124,20 @@ class RomStr(str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def length(self):
|
def length(self):
|
||||||
""" len(self)
|
"""
|
||||||
|
len(self)
|
||||||
"""
|
"""
|
||||||
return len(self)
|
return len(self)
|
||||||
|
|
||||||
def len(self):
|
def len(self):
|
||||||
""" len(self)
|
"""
|
||||||
|
len(self)
|
||||||
"""
|
"""
|
||||||
return self.length()
|
return self.length()
|
||||||
|
|
||||||
def interval(self, offset, length, strings=True, debug=True):
|
def interval(self, offset, length, strings=True, debug=True):
|
||||||
""" returns hex values for the rom starting at offset until
|
"""
|
||||||
offset+length
|
returns hex values for the rom starting at offset until offset+length
|
||||||
"""
|
"""
|
||||||
returnable = []
|
returnable = []
|
||||||
for byte in self[offset:offset+length]:
|
for byte in self[offset:offset+length]:
|
||||||
@@ -141,13 +148,14 @@ class RomStr(str):
|
|||||||
return returnable
|
return returnable
|
||||||
|
|
||||||
def until(self, offset, byte, strings=True, debug=False):
|
def until(self, offset, byte, strings=True, debug=False):
|
||||||
""" Returns hex values from rom starting at offset until the given
|
"""
|
||||||
byte.
|
Returns hex values from rom starting at offset until the given byte.
|
||||||
"""
|
"""
|
||||||
return self.interval(offset, self.find(chr(byte), offset) - offset, strings=strings)
|
return self.interval(offset, self.find(chr(byte), offset) - offset, strings=strings)
|
||||||
|
|
||||||
def to_asm(self, address, end_address=None, size=None, max_size=0x4000, debug=None):
|
def to_asm(self, address, end_address=None, size=None, max_size=0x4000, debug=None):
|
||||||
""" Disassembles ASM at some address. This will stop disassembling when
|
"""
|
||||||
|
Disassembles ASM at some address. This will stop disassembling when
|
||||||
either the end_address or size is met. Also, there's a maximum size
|
either the end_address or size is met. Also, there's a maximum size
|
||||||
that will be parsed, so that large patches of data aren't parsed as
|
that will be parsed, so that large patches of data aren't parsed as
|
||||||
code.
|
code.
|
||||||
@@ -185,16 +193,19 @@ class RomStr(str):
|
|||||||
#return DisAsm(start_address=start_address, end_address=end_address, size=size, max_size=max_size, debug=debug, rom=self)
|
#return DisAsm(start_address=start_address, end_address=end_address, size=size, max_size=max_size, debug=debug, rom=self)
|
||||||
|
|
||||||
class AsmList(list):
|
class AsmList(list):
|
||||||
""" Simple wrapper to prevent all asm lines from being shown on screen.
|
"""
|
||||||
|
Simple wrapper to prevent all asm lines from being shown on screen.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def length(self):
|
def length(self):
|
||||||
""" len(self)
|
"""
|
||||||
|
len(self)
|
||||||
"""
|
"""
|
||||||
return len(self)
|
return len(self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" Simplifies this object so that the output doesn't overflow stdout.
|
"""
|
||||||
|
Simplifies this object so that the output doesn't overflow stdout.
|
||||||
"""
|
"""
|
||||||
return "AsmList(too long)"
|
return "AsmList(too long)"
|
||||||
|
|
||||||
|
@@ -83,7 +83,8 @@ trainer_group_names = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def remove_parentheticals_from_trainer_group_names():
|
def remove_parentheticals_from_trainer_group_names():
|
||||||
""" Clean up the trainer group names.
|
"""
|
||||||
|
Clean up the trainer group names.
|
||||||
"""
|
"""
|
||||||
i = 0
|
i = 0
|
||||||
for (key, value) in trainer_group_names.items():
|
for (key, value) in trainer_group_names.items():
|
||||||
|
@@ -304,7 +304,8 @@ chars = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def separate_comment(l):
|
def separate_comment(l):
|
||||||
""" Separates asm and comments on a single line.
|
"""
|
||||||
|
Separates asm and comments on a single line.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
asm = ""
|
asm = ""
|
||||||
@@ -333,7 +334,8 @@ def separate_comment(l):
|
|||||||
return asm, comment
|
return asm, comment
|
||||||
|
|
||||||
def quote_translator(asm):
|
def quote_translator(asm):
|
||||||
""" Writes asm with quoted text translated into bytes.
|
"""
|
||||||
|
Writes asm with quoted text translated into bytes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# split by quotes
|
# split by quotes
|
||||||
@@ -411,7 +413,8 @@ def make_macro_table():
|
|||||||
macro_table = make_macro_table()
|
macro_table = make_macro_table()
|
||||||
|
|
||||||
def macro_test(asm):
|
def macro_test(asm):
|
||||||
""" Returns a matching macro, or None/False.
|
"""
|
||||||
|
Returns a matching macro, or None/False.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# macros are determined by the first symbol on the line
|
# macros are determined by the first symbol on the line
|
||||||
@@ -424,7 +427,8 @@ def macro_test(asm):
|
|||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
def macro_translator(macro, token, line):
|
def macro_translator(macro, token, line):
|
||||||
""" Converts a line with a macro into a rgbasm-compatible line.
|
"""
|
||||||
|
Converts a line with a macro into a rgbasm-compatible line.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert macro.macro_name == token, "macro/token mismatch"
|
assert macro.macro_name == token, "macro/token mismatch"
|
||||||
|
Reference in New Issue
Block a user