summaryrefslogtreecommitdiff
path: root/romstr.py
diff options
context:
space:
mode:
authorBryan Bishop <kanzure@gmail.com>2013-08-03 16:10:52 -0500
committerBryan Bishop <kanzure@gmail.com>2013-08-03 16:10:52 -0500
commit28490230cf68f8045fc63a8c7d3de19c7c1d3bcd (patch)
treec4d1a3acbc7d34b77a890f8e19a8d7253917be8c /romstr.py
parenta14c36eadb75ea3d6fbc4cb3f382d7c9785d9fe9 (diff)
make a basic python module
Diffstat (limited to 'romstr.py')
-rw-r--r--romstr.py219
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