def read_from_file(input, address, reference): input.seek(anal.addr_to_offset(address)) code = anal.read_int(input, 4) size = reference.get_code_size(code, input) input.seek(anal.addr_to_offset(address + 4)) args = [anal.read_int(input, 4) for _ in range(size - 1)] return SceneIns(code, size, args)
def main(args): def show_exception_and_exit(exc_type, exc_value, tb): import traceback traceback.print_exception(exc_type, exc_value, tb) sys.exit(-1) sys.excepthook = show_exception_and_exit if (len(args) == 0): sys.exit(":(") sceneInsReference = ev6anal.InsReference(ev6anal.FE6_SCENE_INS_REFERENCE_ADDR) analyser = anal.RomAnalyser() analyser.set_analysis_handler(ev6anal.ANAL_KEY_SCENE, lambda a, i, d, n: ev6anal.analyse_scene(a, i, d, n, sceneInsReference)) analyser.set_analysis_handler(ev6anal.ANAL_KEY_MOMA, ev6anal.analyse_moma) analyser.set_analysis_handler(ev6anal.ANAL_KEY_UNITS, ev6anal.analyse_units) analyser.set_analysis_handler(ev6anal.ANAL_KEY_ITEMS, ev6anal.analyse_items) analyser.set_analysis_handler(ev6anal.ANAL_KEY_EVLIST, ev6anal.analyse_event_list) analyser.set_analysis_handler(ev6anal.ANAL_KEY_PTRLIST, ev6anal.analyse_chapter_events) with open(args[0], 'rb') as f: CHAPTER_TABLE_ADDR = 0x086637A4 CHAPTER_ASSET_ADDR = 0x08664398 for i in range(45): f.seek(anal.addr_to_offset(CHAPTER_TABLE_ADDR + 0x44*i + 0x3A)) assetId = anal.read_int(f, 1) if assetId != 0: f.seek(anal.addr_to_offset(CHAPTER_ASSET_ADDR + 4*assetId)) analyser.enqueue_analysis(anal.read_int(f, 4), ev6anal.ANAL_KEY_PTRLIST, "chapter{}".format(i)) analyser.analyse_queued(f) printer = anal.AnalysisPrinter() printer.set_printer(ev6anal.ANAL_KEY_SCENE, lambda a: ScenePrinter.print_scene(a, sceneInsReference)) for line in printer.iter_print_list(analyser.get_analysed_sorted()): sys.stdout.write(line)
def get_code_size(self, code, input = None): if code in self.sizeCache: return self.sizeCache[code] elif input: input.seek(anal.addr_to_offset(self.referenceAddr + code*8 + 4)) size = anal.read_int(input, 4) self.sizeCache[code] = size return size raise Exception("uncached code size with no available input")
def main(args): def show_exception_and_exit(exc_type, exc_value, tb): import traceback traceback.print_exception(exc_type, exc_value, tb) sys.exit(-1) sys.excepthook = show_exception_and_exit if (len(args) == 0): sys.exit(":(") analyser = anal.RomAnalyser() analyser.set_analysis_handler(ANAL_KEY_SCENE, analyse_scene) analyser.set_analysis_handler(ANAL_KEY_MOMA, analyse_moma) analyser.set_analysis_handler(ANAL_KEY_UNITS, analyse_units) analyser.set_analysis_handler(ANAL_KEY_ITEMS, analyse_items) analyser.set_analysis_handler(ANAL_KEY_EVLIST, analyse_event_list) analyser.set_analysis_handler(ANAL_KEY_PTRLIST, analyse_chapter_events) with open(args[0], 'rb') as f: CHAPTER_TABLE_ADDR = 0x086637A4 CHAPTER_ASSET_ADDR = 0x08664398 for i in range(45): f.seek(anal.addr_to_offset(CHAPTER_TABLE_ADDR + 0x44*i + 0x3A)) assetId = anal.read_int(f, 1) if assetId != 0: f.seek(anal.addr_to_offset(CHAPTER_ASSET_ADDR + 4*assetId)) analyser.enqueue_analysis(anal.read_int(f, 4), ANAL_KEY_PTRLIST, "chapter{}".format(i)) analyser.analyse_queued(f) for line in analyser.iter_pretty_summary(): print(line)
def analyse_items(analyser, input, address, name): """ Analysis handler for shop item lists. """ input.seek(anal.addr_to_offset(address)) start = address while True: item = anal.read_int(input, 2) address = address + 2 if item == 0: break return anal.AnalysedObject( start, address - start, ANAL_KEY_ITEMS, anal.read_data_at(input, start, address - start), name)
def analyse_units(analyser, input, address, name): """ Analysis handler for unit groups. """ start = address while True: input.seek(anal.addr_to_offset(address)) charId = anal.read_int(input, 1) address = address + 0x10 if charId == 0: break return anal.AnalysedObject( start, address - start, ANAL_KEY_UNITS, anal.read_data_at(input, start, address - start), name)
def analyse_chapter_events(analyser, input, address, name): """ Analysis handler for chapter events root ("pointer arrays"). """ input.seek(anal.addr_to_offset(address)) analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_EVLIST, name + ".turn") # turn events analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_EVLIST, name + ".char") # character events analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_EVLIST, name + ".loca") # location events analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_EVLIST, name + ".action") # misc events analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_UNITS, name + ".blue") # initial blue units analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_UNITS, name + ".red") # initial red units analyser.enqueue_analysis(anal.read_int(input, 4), ANAL_KEY_SCENE, name + ".ending") # ending scene return anal.AnalysedObject( address, 0x1C, ANAL_KEY_PTRLIST, anal.read_data_at(input, address, 0x1C), name)
def analyse_moma(analyser, input, address, name): """ Analysis handler for movement scripts ("MOMAs"). """ input.seek(anal.addr_to_offset(address)) start = address while True: cmd = anal.read_int(input, 1, True) address = address + 1 if (cmd == 12): anal.read_int(input, 1) # void speed address = address + 1 elif (cmd == -1) | (cmd == 4): break return anal.AnalysedObject( start, address - start, ANAL_KEY_MOMA, anal.read_data_at(input, start, address - start), name)