def __init__(self, stream): if stream.read_string() != b'UnityFS': raise ValueError('Not a UnityFS file!') version = stream.read_int() if version != 6: raise ValueError('Unsupported version: ' + str(version)) mpv = stream.read_string() fev = stream.read_string() total_file_size = stream.read_long() compressed_size = stream.read_int() decompressed_size = stream.read_int() flags = stream.read_int() if flags & 0x80: if total_file_size == 0: bundle_info_offset = -1 else: bundle_info_offset = total_file_size - compressed_size else: if flags & 0x100: bundle_info_offset = len(mpv) + len(fev) + 2 + 0x1A + 0x0A else: bundle_info_offset = len(mpv) + len(fev) + 0x1A + len( 'UnityFS') + 3 compression_mode = flags & 0x3F dir_info = flags & 0x40 bad_list = flags & 0x80 blocks = [] files = [] block = stream.read_bytes(compressed_size) if compression_mode in (self.COMP_LZ4, self.COMP_LZ4HC): data = lz4.block.decompress(block, uncompressed_size=decompressed_size) s2 = Stream(data) s2.skip(16) block_count = s2.read_int() for _ in range(block_count): decomp_size = s2.read_int() comp_size = s2.read_int() flag = s2.read_short() blocks.append((comp_size, decomp_size)) file_count = s2.read_int() for _ in range(file_count): f_offset = s2.read_long() decomp_size = s2.read_long() flag = s2.read_int() name = s2.read_string() files.append((f_offset, decomp_size, name)) else: raise ValueError('Unsupported compression mode') block_data = io.BytesIO() for i in blocks: bd = stream.read_bytes(i[0]) dc = lz4.block.decompress(bd, uncompressed_size=i[1]) block_data.write(dc) self.files = {} for i in files: block_data.seek(i[0]) self.files[i[2].decode()] = block_data.read(i[1])