diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-08-03 16:10:52 -0500 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-08-03 16:10:52 -0500 |
commit | 28490230cf68f8045fc63a8c7d3de19c7c1d3bcd (patch) | |
tree | c4d1a3acbc7d34b77a890f8e19a8d7253917be8c /graph.py | |
parent | a14c36eadb75ea3d6fbc4cb3f382d7c9785d9fe9 (diff) |
make a basic python module
Diffstat (limited to 'graph.py')
-rw-r--r-- | graph.py | 169 |
1 files changed, 0 insertions, 169 deletions
diff --git a/graph.py b/graph.py deleted file mode 100644 index 47087e5..0000000 --- a/graph.py +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding: utf-8 -*- - -import networkx as nx - -from romstr import ( - RomStr, - relative_jumps, - call_commands, - relative_unconditional_jumps, -) - -class RomGraph(nx.DiGraph): - """ - Graphs various functions pointing to each other. - - TODO: Bank switches are nasty. They should be detected. Otherwise, - functions will point to non-functions within the same bank. Another way - to detect bankswitches is retroactively. By disassembling one function - after another within the function banks, it can be roughly assumed that - anything pointing to something else (within the same bank) is really - actually a bankswitch. An even better method to handle bankswitches - would be to just detect those situations in the asm (but I presently - forget how bankswitches are performed in pokecrystal). - """ - - # some areas shouldn't be parsed as asm - exclusions = [] - - # where is the first function located? - start_address = 0x150 - - # and where is a good place to stop? - end_address = 0x4000 * 0x03 # only do the first bank? sure.. - - # where is the rom stored? - rompath = "../baserom.gbc" - - def __init__(self, rom=None, **kwargs): - """ - Loads and parses the ROM into a function graph. - """ - # continue the initialization - nx.DiGraph.__init__(self, **kwargs) - - # load the graph - if rom == None: - self.load_rom() - else: - self.rom = rom - - # start parsing the ROM - self.parse() - - def load_rom(self): - """ - Creates a RomStr from rompath. - """ - file_handler = open(self.rompath, "r") - self.rom = RomStr(file_handler.read()) - file_handler.close() - - def parse(self): - """ - Parses the ROM starting with the first function address. Each - function is disassembled and parsed to find where else it leads to. - """ - functions = {} - - address = self.start_address - - other_addresses = set() - - count = 0 - - while True: - if count > 3000: - break - - if address < self.end_address and (address not in functions.keys()) and address >= 0x150: - # address is okay to parse at, keep going - pass - elif len(other_addresses) > 0: - # parse some other address possibly in a remote bank - address = other_addresses.pop() - else: - # no more addresses detected- exit loop - break - - # parse the asm - func = self.rom.to_asm(address) - - # check if there are any nops (probably not a function) - nops = 0 - for (id, command) in func.asm_commands.items(): - if command.has_key("id") and command["id"] == 0x0: - nops += 1 - - # skip this function - if nops > 1: - address = 0 - continue - - # store this parsed function - functions[address] = func - - # where does this function jump to? - used_addresses = set(func.used_addresses()) - - # add this information to the graph - for used_address in used_addresses: - # only add this remote address if it's not yet parsed - if used_address not in functions.keys(): - other_addresses.update([used_address]) - - # add this other address to the graph - if used_address > 100: - self.add_node(used_address) - - # add this as an edge between the two nodes - self.add_edge(address, used_address) - - # setup the next function to be parsed - address = func.last_address - - count += 1 - - self.functions = functions - - def pretty_printer(self): - """ - Shows some text output describing which nodes point to which other - nodes. - """ - print self.edges() - - def to_d3(self): - """ - Exports to d3.js because we're gangster like that. - """ - import networkx.readwrite.json_graph as json_graph - content = json_graph.dumps(self) - fh = open("crystal/crystal.json", "w") - fh.write(content) - fh.close() - - def to_gephi(self): - """ - Generates a gexf file. - """ - nx.write_gexf(self, "graph.gexf") - -class RedGraph(RomGraph): - """ - Not implemented. Go away. - """ - - rompath = "../pokered-baserom.gbc" - -class CryGraph(RomGraph): - exclusions = [ - [0x000, 0x149], - ] - - rompath = "../baserom.gbc" - -if __name__ == "__main__": - crygraph = CryGraph() - crygraph.pretty_printer() - crygraph.to_gephi() |