Exemplo n.º 1
0
 def read(self, reader: ByteIO):
     header_chunks = reader.get_items()
     for tex_chunk in header_chunks:
         reader.seek(tex_chunk.offset)
         if tex_chunk.type == 20:
             self.chunk_name = reader.read_ascii_string(reader.read_int32())
         if tex_chunk.type == 21:
             self.name = Path(reader.read_ascii_string(reader.read_int32()))
         if tex_chunk.type == 1:
             texture_data_chunks = reader.get_items()
             for tex_data in texture_data_chunks:
                 reader.seek(tex_data.offset)
                 if tex_data.type == 20:
                     reader.skip(3)
                     items3 = reader.get_items()[:1]
                     for n, item3 in enumerate(items3):
                         reader.seek(item3.offset)
                         flag = reader.read_fmt('BBBB')
                         if flag == (36, 0, 65, 0):
                             items4 = reader.get_items()
                             for item4 in items4:
                                 reader.seek(item4.offset)
                                 if item4.type == 20:
                                     self.width = reader.read_int32()
                                 if item4.type == 21:
                                     self.height = reader.read_int32()
                                 if item4.type == 23:
                                     self.format = reader.read_int32()
                                 if item4.type == 22:
                                     self.offset = reader.tell()
                             reader.seek(self.offset)
                             if self.format == 7:
                                 pixel_mode = ('bcn', 1, 0)
                             elif self.format == 11:
                                 pixel_mode = ('bcn', 3, 0)
                             elif self.format == 9:
                                 pixel_mode = ('bcn', 2, 0)
                             # elif self.format == 5:
                             #     pixel_mode = ('bcn', 7, 0)
                             else:
                                 raise NotImplementedError(
                                     'Format:{} is not supported yet'.
                                     format(self.format))
                             im_data = reader.read_bytes(self.width *
                                                         self.height * 4)
                             image = Image.frombuffer(
                                 'RGBA', (self.width, self.height), im_data,
                                 *pixel_mode)
                             del im_data
                             tex_path = self.path / 'textures'
                             os.makedirs(tex_path, exist_ok=True)
                             image.save(tex_path / self.name.with_name(
                                 self.name.stem).with_suffix('.tga'))
Exemplo n.º 2
0
    def read(self, reader: ByteIO):
        items = reader.get_items()
        for item in items:
            item.seek_to()

            if item.type == 20:
                self.chunk_name = reader.read_ascii_string(reader.read_int32())
            if item.type == 21:
                self.name = reader.read_ascii_string(reader.read_int32())
            if item.type == 100:
                self.temp_path = reader.read_ascii_string(reader.read_int32())

            if item.type == 1:
                items2 = item.get_items()
                for item2 in items2:
                    item2.seek_to()
                    if item2.type == 30:
                        item2.seek_to()
                        self.size = reader.read_uint32()
                    if item2.type == 31:
                        self.data = reader.read_bytes(self.size)
Exemplo n.º 3
0
class OVL(OVLBase):
    is_x64 = False
    unknown_type = OVLTypeHeader()

    def __init__(self, path):
        self.path = Path(path)
        self.reader = ByteIO(self.path.open('rb'))
        self.header = OVLHeader()
        self.types = []  # type:List[OVLTypeHeader]
        self.files = []  # type:List[OVLFileDescriptor]
        self.archive_name_table_offset = 0
        self.archives = []  # type: List[OVLArchiveV2]
        self.dirs = []  # type:List[OVLDir]
        self.parts = []  # type:List[OVLPart]
        self.others = []  # type:List[OVLOther]
        self.unknown = []  # type:List[OVLUnk]
        self.archives2 = []  # type:List[OVLArchive2]
        self.static_archive = None  # type: OVLArchiveV2

        self.files_by_hash = {}  #type: Dict[int,OVLFileDescriptor]
        self.hash_by_name = {}  #type: Dict[str,int]

    def read(self):
        self.header.read(self.reader)
        self.is_x64 = True  # self.header.flags & 0x08
        self.reader.skip(self.header.names_length)
        for _ in range(self.header.type_count):
            ovl_type = OVLTypeHeader()
            self.register(ovl_type)
            ovl_type.read(self.reader, is_x64=self.is_x64)
            self.types.append(ovl_type)
        for _ in range(self.header.file_count):
            ovl_file = OVLFileDescriptor()
            self.register(ovl_file)
            ovl_file.read(self.reader)
            self.files.append(ovl_file)
        self.files_by_hash = {f.file_hash: f for f in self.files}
        self.hash_by_name = {f.name: f.file_hash for f in self.files}
        self.archive_name_table_offset = self.reader.tell()
        self.reader.skip(self.header.archive_names_length)
        for _ in range(self.header.archive_count):
            ovl_archive = OVLArchiveV2()
            self.register(ovl_archive)
            ovl_archive.read(self.reader, self.archive_name_table_offset)
            self.archives.append(ovl_archive)

        for _ in range(self.header.dir_count):
            ovl_dir = OVLDir()
            self.register(ovl_dir)
            ovl_dir.read(self.reader)
            self.dirs.append(ovl_dir)

        for _ in range(self.header.part_count):
            ovl_part = OVLPart()
            self.register(ovl_part)
            ovl_part.read(self.reader)
            for file in self.files:
                if ovl_part.hash == file.file_hash:
                    ovl_part.name = file.name
            self.parts.append(ovl_part)

        for _ in range(self.header.other_count):
            ovl_other = OVLOther()
            self.register(ovl_other)
            ovl_other.read(self.reader)
            self.others.append(ovl_other)

        for _ in range(self.header.unknown_count):
            ovl_unk = OVLUnk()
            self.register(ovl_unk)
            ovl_unk.read(self.reader)
            self.unknown.append(ovl_unk)

        for _ in range(self.header.archive_count):
            ovl_archive2 = OVLArchive2()
            self.register(ovl_archive2)
            ovl_archive2.read(self.reader)
            self.archives2.append(ovl_archive2)

        for archive in self.archives:
            print(archive)
            try:
                if archive.name == 'STATIC':
                    archive.uncompressed_data = zlib.decompress(
                        self.reader.read_bytes(archive.packed_size))
                    self.static_archive = archive
                else:
                    self.reader.seek(archive.ovs_offset)
                    archive.uncompressed_data = zlib.decompress(
                        self.reader.read_bytes(archive.packed_size))

                with open(
                        r'test_data\{}-{}.decompressed'.format(
                            self.path.stem, archive.name), 'wb') as fp:
                    fp.write(self.static_archive.uncompressed_data)
            except:
                pass

    def write(self, writer: ByteIO):
        self.header.write(writer)
        # not all header fields are accurate yet,
        # but we'll come back and re-write this section
        names_start = writer.tell()
        for ovl_type in sorted(self.types, key=lambda x: x.name_offset):
            ovl_type.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_type.name, True)
        for ovl_file in sorted(self.files, key=lambda x: x.name_offset):
            ovl_file.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_file.name, True)
        for ovl_dir in sorted(self.dirs, key=lambda x: x.name_offset):
            ovl_dir.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_dir.name, True)
        for ovl_part in sorted(self.parts, key=lambda x: x.name_offset):
            ovl_part.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_part.name, True)
        for ovl_other in sorted(self.others, key=lambda x: x.name_offset):
            ovl_other.name_offset = writer.tell() - names_start
            writer.write_ascii_string(ovl_other.name, True)
        writer.align(8)
        self.header.names_length = writer.tell() - names_start
        for ovl_type in self.types:
            ovl_type.write(writer, self.is_x64)
        for ovl_file in self.files:
            ovl_file.write(writer)
        archive_name_table_start = writer.tell()
        for ovl_archive in self.archives:
            ovl_archive.nameIndex = writer.tell() - archive_name_table_start
            writer.write_ascii_string(ovl_archive.name, True)
        writer.align(8, archive_name_table_start)
        self.header.archive_names_length = writer.tell(
        ) - archive_name_table_start
        for ovl_archive in self.archives:
            ovl_archive.unpacked_size = len(ovl_archive.uncompressed_data)
            ovl_archive.compressed_data = zlib.compress(
                ovl_archive.uncompressed_data)
            ovl_archive.packed_size = len(ovl_archive.compressed_data)
            ovl_archive.write(writer)
        for ovl_dir in self.dirs:
            ovl_dir.write(writer)
        for ovl_part in self.parts:
            ovl_part.write(writer)
        for ovl_other in self.others:
            ovl_other.write(writer)
        for ovl_unk in self.unknown:
            ovl_unk.write(writer)
        for ovl_archive2 in self.archives2:
            ovl_archive2.write(writer)
        for ovl_archive in self.archives:
            writer.write_bytes(ovl_archive.compressed_data)
        writer.seek(0)
        self.header.write(writer)

    def get_file_by_hash(self, hash_value) -> OVLFileDescriptor:
        if not self.files_by_hash:
            self.files_by_hash = {f.file_hash: f for f in self.files}
        return self.files_by_hash.get(hash_value)

    def get_type_by_hash(self, hash_value) -> OVLTypeHeader:
        for t in self.types:
            if t.type_hash == hash_value:
                return t
        return self.unknown_type
Exemplo n.º 4
0
    def read(self, reader: ByteIO):
        self.reader = reader
        section_offsets = []
        total_size = 0
        for _ in range(self.archive.file_type_header_count):
            header = OVSTypeHeader()
            self.register(header)
            header.read(reader)
            self.ovs_headers.append(header)
        for _ in range(self.archive.sub_header_count):
            sub_header = OVLTypeSubHeader()
            self.register(sub_header)
            sub_header.read(reader)
            total_size += sub_header.size
            section_offsets.append(sub_header.offset)
            self.ovs_sub_headers.append(sub_header)

        for i in range(1, len(section_offsets)):
            section_offsets[i] -= section_offsets[0]
        section_offsets[0] = 0

        offset = 0

        for _ in range(self.archive.file_data_header_count):
            file_header = OVLDataHeader()
            self.register(file_header)
            file_header.part_array_offset = offset
            file_header.read(reader)
            offset += file_header.part_count
            file_header.file_name = self.parent.get_file_by_hash(file_header.file_hash).name
            self.hash2file_data_header[file_header.file_hash] = file_header
            self.ovs_file_headers.append(file_header)

        for _ in range(self.archive.embedded_file_count):
            embedded_header = OVLEmbeddedFileDescriptor()
            self.register(embedded_header)
            embedded_header.read(reader)
            self.embedded_file_headers.append(embedded_header)

        for _ in range(self.archive.asset_count):
            asset = OVLAsset()
            self.register(asset)
            asset.read(reader)
            if asset.chunk_id > 0:
                asset.new_offset = section_offsets[asset.chunk_id] + asset.offset
            else:
                asset.new_offset = 0
            self.ovs_assets.append(asset)

        for _ in range(self.archive.relocation_num):
            relocation = OVLRelocation()
            self.register(relocation)
            relocation.read(reader)
            relocation.offset1 = section_offsets[relocation.section1] + relocation.offset1
            relocation.offset2 = section_offsets[relocation.section2] + relocation.offset2
            self.relocations.append(relocation)

        self.extra_data = reader.read_bytes(self.archive.size_extra)

        self.buffer = reader.read_bytes(total_size)
        relocation_buffer = ByteIO(byte_object=copy(self.buffer))

        for relocation in self.relocations:
            relocation_buffer.seek(relocation.offset1)
            relocation_buffer.write_uint32(relocation.offset2)
        self.relocated_reader = relocation_buffer
        self.ovs_cur_pos = reader.tell()


        for file_header in self.ovs_file_headers:
            if file_header.type_hash != 193506774:
                for j in range(file_header.part_count):
                    embedded_header_id = file_header.part_array_offset + j
                    embedded_header = self.embedded_file_headers[embedded_header_id]
                    if embedded_header.archive_id == 0:
                        embedded_header.offset = self.ovs_cur_pos
                        self.ovs_cur_pos += embedded_header.size
        for file_header in self.ovs_file_headers:
            if file_header.type_hash != 193506774:
                for j in range(file_header.part_count):
                    embedded_header_id = file_header.part_array_offset + j
                    embedded_header = self.embedded_file_headers[embedded_header_id]
                    if embedded_header.archive_id == 1:
                        embedded_header.offset = self.ovs_cur_pos
                        self.ovs_cur_pos += embedded_header.size
        for file_header in self.ovs_file_headers:
            if file_header.type_hash == 193506774:
                for j in range(file_header.part_count):
                    embedded_header_id = file_header.part_array_offset + j
                    embedded_header = self.embedded_file_headers[embedded_header_id]
                    embedded_header.offset = self.ovs_cur_pos
                    self.ovs_cur_pos += embedded_header.size
        for file_header in self.ovs_file_headers:
            if file_header.type_hash != 193506774:
                for j in range(file_header.part_count):
                    embedded_header_id = file_header.part_array_offset + j
                    embedded_header = self.embedded_file_headers[embedded_header_id]
                    if embedded_header.archive_id == 2:
                        embedded_header.offset = self.ovs_cur_pos
                        self.ovs_cur_pos += embedded_header.size

        pass
Exemplo n.º 5
0
    def read(self, reader: ByteIO):
        items = reader.get_items()
        for item in items:
            item.seek_to()

            if item.type == 20:
                self.chunk_name = reader.read_ascii_string(reader.read_int32())
            if item.type == 21:
                self.name = reader.read_ascii_string(reader.read_int32())
                print(self.name)
            if item.type == 1:
                items2 = item.get_items()
                for item2 in items2:
                    item2.seek_to()
                    if item2.type == 10:
                        reader.skip(3)
                        items4 = item2.get_items()
                        for item4 in items4:
                            item4.seek_to()
                            flag = reader.read_fmt('BBBB')
                            print(flag)
                            if flag == (7, 0, 65, 0):  #bone
                                items5 = item4.get_items()
                                for item5 in items5:
                                    print(item5)
                                    item5.seek_to()

                                    if item5.type == 20:
                                        b_name = reader.read_ascii_string(
                                            reader.read_int32())
                                        print('\t', b_name)
                                        self.bone_names.append(b_name)
                                    if item5.type == 24:
                                        items6 = item5.get_items()
                                        for item6 in items6:
                                            item6.seek_to()
                                            if item6.type == 21:
                                                self.frame_count = reader.read_uint32(
                                                )
                                            if item6.type == 22:
                                                self.frame_offset = reader.tell(
                                                )
                                        if self.frame_offset and self.frame_count:
                                            for _ in range(self.frame_count):
                                                self.anim_data.append(
                                                    reader.read_bytes(16))

                                    if item5.type == 25:
                                        items6 = item5.get_items()
                                        for item6 in items6:
                                            item6.seek_to()
                                            if item6.type == 21:
                                                items7 = item5.get_items()
                                                for item7 in items7:
                                                    item7.seek_to()
                                                    if item7.type == 22:
                                                        self.frame_count = reader.read_uint32(
                                                        )
                                                    if item7.type == 23:
                                                        self.frame_offset = reader.tell(
                                                        )
                                                    if item7.type == 30:
                                                        self.frame_count2 = reader.read_uint32(
                                                        )
                                                    if item7.type == 31:
                                                        self.frame_offset2 = reader.tell(
                                                        )

                                        if self.frame_offset and self.frame_count:
                                            reader.seek(self.frame_offset)
                                            for _ in range(self.frame_count):
                                                self.anim_data2.append(
                                                    reader.read_bytes(6))
                                        if self.frame_offset2 and self.frame_count2:
                                            reader.seek(self.frame_offset2)
                                            for _ in range(self.frame_count2):
                                                self.anim_data3.append(
                                                    reader.read_bytes(8))