diff options
Diffstat (limited to 'romstr.py')
| -rw-r--r-- | romstr.py | 219 | 
1 files changed, 0 insertions, 219 deletions
| diff --git a/romstr.py b/romstr.py deleted file mode 100644 index 69a4f2a..0000000 --- a/romstr.py +++ /dev/null @@ -1,219 +0,0 @@ -# -*- coding: utf-8 -*- - -import sys -import os -import time -import datetime -from ctypes import c_int8 -from copy import copy -import json - -# New versions of json don't have read anymore. -if not hasattr(json, "read"): -    json.read = json.loads - -from labels import ( -    get_label_from_line, -    get_address_from_line_comment, -) - -relative_jumps = [0x38, 0x30, 0x20, 0x28, 0x18, 0xc3, 0xda, 0xc2, 0x32] -relative_unconditional_jumps = [0xc3, 0x18] -call_commands = [0xdc, 0xd4, 0xc4, 0xcc, 0xcd] -end_08_scripts_with = [ -    0xe9, # jp hl -    0xc9, # ret -] # possibly also: -    # 0xc3,  # jp -    # 0xc18, # jr -    # 0xda, 0xe9, 0xd2, 0xc2, 0xca, 0x38, 0x30, 0x20, 0x28, 0x18, 0xd8, -    # 0xd0, 0xc0, 0xc8, 0xc9 - -spacing = "\t" - -class RomStr(str): -    """ -    Simple wrapper to prevent a giant rom from being shown on screen. -    """ - -    def __init__(self, *args, **kwargs): -        if "labels" in kwargs.keys() and kwargs["labels"] == True: -            self.load_labels() -        str.__init__(self) - -    def __repr__(self): -        """ -        Simplifies this object so that the output doesn't overflow stdout. -        """ -        return "RomStr(too long)" - -    @classmethod -    def load(cls, filename=None, crystal=True, red=False): -        """ -        Load a ROM into a RomStr. -        """ -        if   crystal and not red and not filename: -            file_handler = open("../baserom.gbc", "r") -        elif red and not crystal and not filename: -            file_handler = open("../pokered-baserom.gbc", "r") -        elif filename not in ["", None]: -            file_handler = open(filename, "rb") -        else: -            raise Exception("not sure which rom to load?") -        bytes = file_handler.read() -        file_handler.close() -        return RomStr(bytes) - -    def load_labels(self, filename="labels.json"): -        """ -        Loads labels from labels.json. - -        (Or parses the source code file and -        generates new labels.) -        """ -        filename = os.path.join(os.path.dirname(__file__), filename) - -        # blank out the hash -        self.labels = {} - -        # check if the labels file exists -        file_existence = os.path.exists(filename) - -        generate_labels = False - -        # determine if the labels file needs to be regenerated -        if file_existence: -            modified = os.path.getmtime(filename) -            modified = datetime.datetime.fromtimestamp(modified) -            current  = datetime.datetime.fromtimestamp(time.time()) - -            is_old = (current - modified) > datetime.timedelta(days=3) - -            if is_old: -                generate_labels = True -        else: -            generate_labels = True - -        # scan the asm source code for labels -        if generate_labels: -            asm = open(os.path.join(os.path.dirname(__file__), "../main.asm"), "r").read().split("\n") - -            for line in asm: -                label = get_label_from_line(line) - -                if label: -                    address = get_address_from_line_comment(line) - -                    self.labels[address] = label - -            content = json.dumps(self.labels) -            file_handler = open(filename, "w") -            file_handler.write(content) -            file_handler.close() - -        # load the labels from the file -        self.labels = json.read(open(filename, "r").read()) - -    def get_address_for(self, label): -        """ -        Return the address of a label. - -        This is slow and could be improved dramatically. -        """ -        label = str(label) -        for address in self.labels.keys(): -            if self.labels[address] == label: -                return address -        return None - -    def length(self): -        """ -        len(self) -        """ -        return len(self) - -    def len(self): -        """ -        len(self) -        """ -        return self.length() - -    def interval(self, offset, length, strings=True, debug=True): -        """ -        Return hex values for the rom starting at offset until offset+length. -        """ -        returnable = [] -        for byte in self[offset:offset+length]: -            if strings: -                returnable.append(hex(ord(byte))) -            else: -                returnable.append(ord(byte)) -        return returnable - -    def until(self, offset, byte, strings=True, debug=False): -        """ -        Return hex values from rom starting at offset until the given byte. -        """ -        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): -        """ -        Disassemble ASM at some address. - -        This will stop disassembling when 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 code. -        """ -        if type(address) in [str, unicode] and "0x" in address: -            address = int(address, 16) - -        start_address = address - -        if start_address == None: -            raise Exception, "address must be given" - -        if debug == None: -            if not hasattr(self, "debug"): -                debug = False -            else: -                debug = self.debug - -        # this is probably a terrible idea.. why am i doing this? -        if size != None and max_size < size: -            raise Exception, "max_size must be greater than or equal to size" -        elif end_address != None and (end_address - start_address) > max_size: -            raise Exception, "end_address is out of bounds" -        elif end_address != None and size != None: -            if (end_address - start_address) >= size: -                size = end_address - start_address -            else: -                end_address = start_address + size -        elif end_address == None and size != None: -            end_address = start_address + size -        elif end_address != None and size == None: -            size = end_address - start_address - -        raise NotImplementedError("DisAsm was removed and never worked; hook up another disassembler please.") -        #return DisAsm(start_address=start_address, end_address=end_address, size=size, max_size=max_size, debug=debug, rom=self) - -class AsmList(list): -    """ -    Simple wrapper to prevent all asm lines from being shown on screen. -    """ - -    def length(self): -        """ -        len(self) -        """ -        return len(self) - -    def __repr__(self): -        """ -        Simplifies this object so that the output doesn't overflow stdout. -        """ -        return "AsmList(too long)" - -if __name__ == "__main__": -    cryrom = RomStr(open("../pokecrystal.gbc", "r").read()); -    asm = cryrom.to_asm(sys.argv[1]) -    print asm | 
