def decompress_rom(dmadata_addr, dmadata): rom_segments = { } # vrom start : data s.t. len(data) == vrom_end - vrom_start new_dmadata = bytearray( ) # new dmadata: {vrom start , vrom end , vrom start , 0} decompressed = io.BytesIO(b"") for v_start, v_end, p_start, p_end in dmadata: if p_start == 0xFFFFFFFF and p_end == 0xFFFFFFFF: new_dmadata.extend( struct.pack(">IIII", v_start, v_end, p_start, p_end)) continue if p_end == 0: # uncompressed rom_segments.update( {v_start: fileContent[p_start:p_start + v_end - v_start]}) else: # compressed rom_segments.update( {v_start: decompress(fileContent[p_start:p_end])}) new_dmadata.extend(struct.pack(">IIII", v_start, v_end, v_start, 0)) # write rom segments to vaddrs for vrom_st, data in rom_segments.items(): decompressed.seek(vrom_st) decompressed.write(data) # write new dmadata decompressed.seek(dmadata_addr) decompressed.write(new_dmadata) # pad to size decompressed.seek(UNCOMPRESSED_SIZE - 1) decompressed.write(bytearray([0])) # re-calculate crc return update_crc(decompressed)
def extract(file): """ Extrct the given archive """ with open(file, "rb") as inf: inb = inf.read() while libyaz0.IsYazCompressed(inb): inb = libyaz0.decompress(inb) name = os.path.splitext(file)[0] ext = SarcLib.guessFileExt(inb) if ext != ".sarc": with open(''.join([name, ext]), "wb") as out: out.write(inb) else: arc = SarcLib.SARC_Archive() arc.load(inb) root = os.path.join(os.path.dirname(file), name) if not os.path.isdir(root): os.mkdir(root) files = [] def getAbsPath(folder, path): nonlocal root nonlocal files for checkObj in folder.contents: if isinstance(checkObj, SarcLib.File): files.append( ["/".join([path, checkObj.name]), checkObj.data]) else: path_ = os.path.join(root, "/".join([path, checkObj.name])) if not os.path.isdir(path_): os.mkdir(path_) getAbsPath(checkObj, "/".join([path, checkObj.name])) for checkObj in arc.contents: if isinstance(checkObj, SarcLib.File): files.append([checkObj.name, checkObj.data]) else: path = os.path.join(root, checkObj.name) if not os.path.isdir(path): os.mkdir(path) getAbsPath(checkObj, checkObj.name) for file, fileData in files: print(file) with open(os.path.join(root, file), "wb") as out: out.write(fileData)
def decompressLIBYAZ0(inb): """ Decompress the file using libyaz0 """ try: data = decompress(inb) except: return False else: return data
filename = filenameResult[0] outPath = filenameResult[1] if physEnd == 0: # uncompressed compressed = False size = virtEnd - virtStart else: # compressed compressed = True size = physEnd - physStart if physStart == 0xFFFFFFFF: # file is in table but not on cart? continue if virtStart == 0 and virtEnd == 0: # there are several entries at the end like this... continue print('extracting ' + filename + ' (0x%08X, 0x%08X, 0x%08X)' % (virtStart, virtEnd, size)) if compressed: print('decompressing (' + str(i) + ') ' + filename + ", to " + outPath) decompressed_data = decompress(romData[physStart:physStart + size]) writefile = open(outPath + "/" + filename, 'wb') writefile.write(decompressed_data) writefile.close() else: write_output_file(outPath + '/' + filename, physStart, size)
def change_water(path, water_type=0): water_types = [ 'Normal Water', 'Hot Water', 'Poison', 'Lava', 'Ice Water', 'Mud', 'Clear Water', 'Sea Water' ] for parent_dir, dirs, files in os.walk(path): for file in files: current_path = '{0}{1}'.format(parent_dir, file) if 'water.extm.sstera' not in current_path: continue with open(current_path, 'rb') as infile: infile_binary = infile.read() while libyaz0.IsYazCompressed(infile_binary): infile_binary = libyaz0.decompress(infile_binary) path, extension = os.path.splitext(current_path) filename = os.path.basename(current_path) if infile_binary[0x00:0x04] != b'SARC': print('Not a sarc. :(') sarc = SarcLib.SARC_Archive() sarc.load(infile_binary) with tempfile.TemporaryDirectory() as temp_dir: for sarc_file in sarc.contents: if isinstance(sarc_file, SarcLib.File): pos = 0 data = bytearray(sarc_file.data) while pos + 8 <= len(sarc_file.data): height, x_axis_flow_rate, z_axis_flow_rate, mate_check, mate = \ struct.unpack('<3H2B', data[pos:pos + 0x08]) # height = 0x24cc # x_axis_flow_rate = 0x8125 # z_axis_flow_rate = 0x8125 mate = water_type mate_check = mate + 3 data[pos:pos + 0x08] = struct.pack( '<3H2B', height, x_axis_flow_rate, z_axis_flow_rate, mate_check, mate) pos += 0x08 with open( '{0}/{1}'.format(temp_dir, sarc_file.name), 'wb+') as outfile: outfile.write(data) sarc = SarcLib.SARC_Archive(endianness='>') for path, dirs, files in os.walk(temp_dir): for file in files: with open('{0}/{1}'.format(path, file), 'rb') as infile: sarc.addFile( SarcLib.File(file, infile.read(), True)) data, alignment = sarc.save() data = libyaz0.compress(data, alignment, 5) destination = '{0}/output/MainField - {1}'.format( os.path.dirname(__file__), water_types[water_type]) if not os.path.exists('{0}/output/'.format( os.path.dirname(__file__))): os.makedirs('{0}/output/'.format( os.path.dirname(__file__))) if not os.path.exists('{0}/output/MainField - {1}'.format( os.path.dirname(__file__), water_types[water_type])): os.makedirs('{0}/output/MainField - {1}'.format( os.path.dirname(__file__), water_types[water_type])) with open('{0}/{1}'.format(destination, filename), 'wb+') as outfile: print('saving {0}...'.format(filename)) outfile.write(data)