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 /comparator.py | |
parent | a14c36eadb75ea3d6fbc4cb3f382d7c9785d9fe9 (diff) |
make a basic python module
Diffstat (limited to 'comparator.py')
-rw-r--r-- | comparator.py | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/comparator.py b/comparator.py deleted file mode 100644 index 6cc440c..0000000 --- a/comparator.py +++ /dev/null @@ -1,267 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Find shared functions between red/crystal. -""" - -from crystal import ( - get_label_from_line, - get_address_from_line_comment, - AsmSection, - direct_load_rom, - direct_load_asm, -) - -from romstr import ( - RomStr, - AsmList, -) - -def load_rom(path): - """ - Load a ROM file into an abbreviated RomStr object. - """ - return direct_load_rom(filename=path) - -def load_asm(path): - """ - Load source ASM into an abbreviated AsmList object. - """ - return direct_load_asm(filename=path) - -def findall_iter(sub, string): - # url: http://stackoverflow.com/a/3874760/687783 - - def next_index(length): - index = 0 - length - while True: - index = string.find(sub, index + length) - yield index - - return iter(next_index(len(sub)).next, -1) - -class Address(int): - """ - A simple int wrapper to take 0xFFFF and $FFFF addresses. - """ - - def __new__(cls, x=None, *args, **kwargs): - if type(x) == str: - if "$" in x: - x = x.replace("$", "0x") - - if "0x" in str: - instance = int.__new__(cls, int(x, base=16), *args, **kwargs) - else: - msg = "Address.__new__ doesn't know how to parse this string" - raise Exception, msg - else: - instance = int.__new__(cls, x, *args, **kwargs) - - return instance - -found_blobs = [] - -class BinaryBlob(object): - """ - Store 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. - """ - - start_address = None - end_address = None - label = None - line_number = None - bytes = None - bank = None - debug = False - locations = None - - def __init__(self, start_address=None, end_address=None, label=None, \ - debug=None, line_number=None): - if not isinstance(start_address, Address): - start_address = Address(start_address) - if not isinstance(end_address, Address): - end_address = Address(end_address) - - assert label != None, "label can't be none" - assert isinstance(label, str), "label must be a string" - assert line_number != None, "line_number must be provided" - - self.start_address = start_address - self.end_address = end_address - self.label = label - self.line_number = line_number - self.bytes = [] - self.locations = [] - self.bank = start_address / 0x4000 - - if debug != None: - self.debug = debug - - self.parse_from_red() - # self.find_in_crystal() - self.find_by_first_bytes() - - def __repr__(self): - """ - A beautiful poem. - """ - - r = "BinaryBlob(" - r += "label=\""+self.label+"\", " - r += "start_address="+hex(self.start_address)+", " - r += "size="+str(self.end_address - self.start_address)+", " - locnum = len(self.locations) - if locnum == 1: - r += "located="+hex(self.locations[0]) - elif locnum <= 5: - r += "located="+str([hex(x) for x in self.locations]) - else: - r += "located="+str(locnum) - r += ")" - - return r - - def __str__(self): - return self.__repr__() - - def parse_from_red(self): - """ - Read bytes from Pokémon Red and stores them. - """ - - self.bytes = redrom[self.start_address : self.end_address + 1] - - def pretty_bytes(self): - """ - Returns a better looking range of bytes. - """ - - bytes = redrom.interval(self.start_address, \ - self.end_address - self.start_address, \ - strings=False, debug=True) - - return bytes - - def find_in_crystal(self): - """ - Check whether or not the bytes appear in Pokémon Crystal. - """ - - finditer = findall_iter(self.bytes, cryrom) - self.locations = [match for match in finditer] - - if len(self.locations) > 0: - found_blobs.append(self) - - if self.debug: - print self.label + ": found " + str(len(self.locations)) + " matches." - - def find_by_first_bytes(self): - """ - Find this blob in Crystal based on the first n bytes. - """ - - # how many bytes to match - first_n = 3 - - # no match - if len(self.bytes) <= first_n: - return - - finditer = findall_iter(self.bytes[0:first_n], cryrom) - self.locations = [match for match in finditer] - - # filter out locations that suck - self.locations = [i for i in self.locations if abs(self.start_address - i) <= 0x8000] - - if len(self.locations) > 0: - found_blobs.append(self) - - if self.debug: - print self.label + ": found " + str(len(self.locations)) + " matches." - -pokecrystal_rom_path = "../baserom.gbc" -pokecrystal_src_path = "../main.asm" -pokered_rom_path = "../pokered-baserom.gbc" -pokered_src_path = "../pokered-main.asm" - -cryrom = load_rom(pokecrystal_rom_path) -crysrc = load_asm(pokecrystal_src_path) -redrom = load_rom(pokered_rom_path) -redsrc = load_asm(pokered_src_path) - -def scan_red_asm(bank_stop=3, debug=True): - """ - Scan the ASM from Pokémon Red. Finds labels and objects. Does things. - - Uses get_label_from_line and get_address_from_line_comment. - """ - - # whether or not to show the lines from redsrc - show_lines = False - - line_number = 0 - current_bank = 0 - - current_label = None - latest_label = "ignore me" - current_start_address = None - latest_start_address = 0 - latest_line = "" - - for line in redsrc: - if debug and show_lines: - print "processing a line from red: " + line - - if line[0:7] == "SECTION": - thing = AsmSection(line) - current_bank = thing.bank_id - - if debug: - print "scan_red_asm: switching to bank " + str(current_bank) - - elif line[0:6] != "INCBIN": - if ":" in line and not ";XXX:" in line and not " ; XXX:" in line: - current_label = get_label_from_line(line) - current_start_address = get_address_from_line_comment(line, \ - bank=current_bank) - - if current_label != None and current_start_address != None and latest_start_address != None \ - and current_start_address != 0 and current_start_address != latest_start_address \ - and (current_start_address - latest_start_address) > 1: - if latest_label != None: - if latest_label not in ["Char52", "PokeCenterSignText", "DefaultNamesPlayer", "Unnamed_6a12"]: - blob = BinaryBlob(label=latest_label, \ - start_address=latest_start_address, \ - end_address=current_start_address, \ - line_number=line_number) - - if debug: - print "Created a new blob: " + str(blob) + " from line: " + str(latest_line) - - latest_label = current_label - latest_start_address = current_start_address - latest_line = line - - line_number += 1 - - if current_bank == bank_stop: - if debug: - print "scan_red_asm: stopping because current_bank >= " + \ - str(bank_stop) + " (bank_stop)" - - break - -scan_red_asm(bank_stop=3) - -print "================================" - -for blob in found_blobs: - print blob - -print "Found " + str(len(found_blobs)) + " possibly copied functions." - -print [hex(x) for x in found_blobs[10].locations] |