def do_compile(self, project_entry, base_rom_entry, rom_entry): base_rom = base_rom_entry.get() rom = rom_entry.get() project = project_entry.get() if base_rom and rom and project: self.save_default_tab() base_rom_rom = Rom() base_rom_rom.from_file(base_rom) if base_rom_rom.type == "Earthbound" and len(base_rom_rom) == 0x300000: confirm = tkMessageBox.askquestion("Expand Your Base ROM?", "You are attempting to compile using a base ROM which is " "unexpanded. It is likely that this will not succeed, as CoilSnake " "needs the extra space in an expanded ROM to store additional data." "\n\n" "Would you like to expand this base ROM before proceeding? This " "will permanently overwrite your base ROM.", icon='warning') if confirm == "yes": base_rom_rom.expand(0x400000) base_rom_rom.to_file(base_rom) del base_rom_rom # Update the GUI self.console.clear() self.disable_all_components() self.progress_bar.clear() log.info("Starting compilation...") thread = Thread(target=self._do_compile_help, args=(project, base_rom, rom)) thread.start()
def expand_rom(root, ex=False): rom = Rom() filename = tkFileDialog.askopenfilename( parent=root, initialdir=os.path.expanduser("~"), title="Select a ROM to expand", filetypes=ROM_FILETYPES) if filename: rom.from_file(filename) if (not ex and len(rom) >= 0x400000) or (ex and (len(rom) >= 0x600000)): tkMessageBox.showerror( parent=root, title="Error", message="This ROM is already expanded.") else: if ex: rom.expand(0x600000) else: rom.expand(0x400000) rom.to_file(filename) del rom tkMessageBox.showinfo( parent=root, title="Expansion Successful", message="Your ROM was expanded.")
def do_compile(self, project_entry, base_rom_entry, rom_entry): base_rom = base_rom_entry.get() rom = rom_entry.get() project = project_entry.get() if base_rom and rom and project: self.save_default_tab() base_rom_rom = Rom() base_rom_rom.from_file(base_rom) if base_rom_rom.type == "Earthbound" and len(base_rom_rom) == 0x300000: confirm = tkinter.messagebox.askquestion("Expand Your Base ROM?", "You are attempting to compile using a base ROM which is " "unexpanded. It is likely that this will not succeed, as CoilSnake " "needs the extra space in an expanded ROM to store additional data." "\n\n" "Would you like to expand this base ROM before proceeding? This " "will permanently overwrite your base ROM.", icon='warning') if confirm == "yes": base_rom_rom.expand(0x400000) base_rom_rom.to_file(base_rom) del base_rom_rom # Update the GUI self.console.clear() self.disable_all_components() self.progress_bar.clear() log.info("Starting compilation...") thread = Thread(target=self._do_compile_help, args=(project, base_rom, rom)) thread.start()
def expand(romfile, ex=False): rom = Rom() rom.from_file(romfile) if (not ex and len(rom) >= 0x400000) or (ex and (len(rom) >= 0x600000)): return False else: if ex: rom.expand(0x600000) else: rom.expand(0x400000) rom.to_file(romfile) del rom return True
class TestRom(TestAllocatableBlock): def setup(self): self.block = Rom() def test_detect_rom_type(self): self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "EB_fake_noheader.smc")) assert_equal(self.block.type, "Earthbound") self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "EB_fake_header.smc")) assert_equal(self.block.type, "Earthbound") self.block.from_file(os.path.join(TEST_DATA_DIR, "binaries", "empty.bin")) assert_equal(self.block.type, ROM_TYPE_NAME_UNKNOWN) self.block.from_file(os.path.join(TEST_DATA_DIR, "binaries", "1kb_null.bin")) assert_equal(self.block.type, ROM_TYPE_NAME_UNKNOWN) self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "EB_fake_header.smc")) assert_equal(self.block.type, "Earthbound") self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "real_EarthBound.smc")) assert_equal(self.block.type, "Earthbound") @raises(NotImplementedError) def test_add_header_unknown(self): self.block.from_list([0]) self.block.add_header() def test_add_header_eb(self): self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "real_EarthBound.smc")) assert_equal(self.block.size, 0x300000) self.block.add_header() assert_equal(self.block.size, 0x300200) assert_equal(len(self.block.data), 0x300200) assert_equal(self.block[0:0x200].to_list(), [0] * 0x200) @raises(NotImplementedError) def test_expand_unknown(self): self.block.from_list([0]) self.block.expand(0x123456) def test_expand_eb(self): self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "real_EarthBound.smc")) assert_raises(InvalidArgumentError, self.block.expand, 0x400200) assert_raises(InvalidArgumentError, self.block.expand, 0x300000) self.block.expand(0x400000) assert_equal(self.block.size, 0x400000) assert_equal(len(self.block.data), 0x400000) assert_list_equal(self.block[0x300000:0x400000].to_list(), [0] * 0x100000) self.block.expand(0x600000) assert_equal(self.block.size, 0x600000) assert_equal(len(self.block.data), 0x600000) assert_equal(self.block[0xffd5], 0x25) assert_equal(self.block[0xffd7], 0x0d) self.block.from_file(os.path.join(TEST_DATA_DIR, "roms", "real_EarthBound.smc")) self.block.expand(0x600000) assert_equal(self.block.size, 0x600000) assert_equal(len(self.block.data), 0x600000) assert_equal(self.block[0xffd5], 0x25) assert_equal(self.block[0xffd7], 0x0d)
def patch_rom(clean_rom_filename, patched_rom_filename, patch_filename, headered, progress_bar=None): if not os.path.isfile(clean_rom_filename): raise RuntimeError("Clean Rom \"" + clean_rom_filename + "\" is not a file.") if not os.path.isfile(patch_filename): raise RuntimeError("Patch \"" + patch_filename + "\" is not a file.") if clean_rom_filename != patched_rom_filename: copyfile(clean_rom_filename, patched_rom_filename) log.info("Patching ROM {} with patch {}".format(patched_rom_filename, patch_filename)) patching_start_time = time.time() if patch_filename.endswith(".ips"): output_rom = Rom() output_rom.from_file(clean_rom_filename) patch = IpsPatch() elif patch_filename.endswith(".ebp"): output_rom = EbRom() output_rom.from_file(clean_rom_filename) patch = EbpPatch() else: raise CoilSnakeError("Unknown patch format.") # Load the patch and expand the ROM as needed add_header = headered and not isinstance(patch, EbpPatch) extra = int(add_header)*0x200 # 0x200 if a header will be added, 0 otherwise patch.load(patch_filename) if isinstance(patch, EbpPatch): log.info("Patch: {title} by {author}".format(**patch.metadata)) if patch.last_offset_used > len(output_rom) + extra: if patch.last_offset_used < 0x400000 + extra: output_rom.expand(0x400000) elif patch.last_offset_used < 0x600000 + extra: output_rom.expand(0x600000) else: output_rom.expand(patch.last_offset_used) # If the user specified the patch was made for a headered ROM, add a header # to the ROM if add_header: output_rom.add_header() # Apply the patch and write out the patched ROM patch.apply(output_rom) if add_header: # Remove the header that was added, so that we're always dealing with # unheadered ROMs in the end output_rom.data = output_rom.data[0x200:] output_rom.size -= 0x200 output_rom.to_file(patched_rom_filename) log.info("Patched to {} in {:.2f}s".format(patched_rom_filename, time.time() - patching_start_time))