Exemplo n.º 1
0
 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)
Exemplo n.º 2
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.º 3
0
 def read_vertexes(self, reader: ByteIO):
     for i in range(self.vertex_count):
         vertex_entry = reader.tell()
         vertex = RIPVertex()
         for attrib in self.attributes:
             reader.seek(vertex_entry + attrib.offset)
             if attrib.name == RIPAttrTypes.POSITION:
                 vertex.pos.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.NORMAL:
                 vertex.norm.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.TEXCOORD:
                 vertex.UV.append(RIPVarVector().read(reader,attrib.types))
             elif attrib.name == RIPAttrTypes.COLOR:
                 vertex.color.read(reader,attrib.types)
             elif attrib.name == RIPAttrTypes.TANGENT:
                 reader.skip(attrib.size)
             elif attrib.name == RIPAttrTypes.BLENDINDICES:
                 vertex.blend.read(reader,attrib.types)
             else:
                 print('Found unknown attribute! Please report about this')
         reader.seek(vertex_entry + self.vertex_size)
         self.vertexes.append(vertex)
Exemplo n.º 4
0
class HeroFile:
    me = (2 ** 8) - 1
    ge = (2 ** 16) - 1
    H = math.pow(2, 16) - 1
    X = (math.pow(2, 16) - 2) / 2

    def __init__(self, path):
        self.reader = ByteIO(path=path)
        self.name = Path(path).name
        self.version = 0
        self.i32_count = 0
        self.i16_count = 0
        self.i8_count = 0
        self.i1_count = 0
        self.export_time = 0

        self.i32_offset = 0
        self.i16_offset = 0
        self.i8_offset = 0
        self.i1_offset = 0
        self.bit_cursor = 0

        self._i1_array = []

        self.options = {}
        self.geometry = HeroGeomerty()
        self.vertex_count = 0

    def read_float(self, offset=0):
        self.reader.seek(self.i32_offset + offset)
        ret = self.reader.read_float()
        self.i32_offset += 4
        return ret

    def read_uint32(self, offset=0):
        self.reader.seek(self.i32_offset + offset)
        val = self.read_float()
        ret = round(val)
        return ret

    def read_uint16(self, offset=0, increment=True):
        self.reader.seek(self.i16_offset + offset)
        ret = self.reader.read_uint16()
        if increment:
            self.i16_offset += 2
        return ret

    def read_int8(self, offset=0):
        self.reader.seek(self.i8_offset + offset)
        ret = self.reader.read_uint8()
        self.i8_offset += 1
        return ret

    def read_string(self, offset=0):
        self.reader.seek(self.i8_offset + offset)
        l = self.read_int8()
        ret = self.reader.read_ascii_string(l)
        self.i8_offset += len(ret)
        return ret

    def read_bit(self):
        bit = self._i1_array[self.bit_cursor]
        self.bit_cursor += 1
        return bit

    def get_quaternion_array(self, e):
        e *= 4
        r = np.zeros(e)
        for i in range(e):
            r[i] = self.read_uint16() / self.H * 2 - 1
        return r

    def get_position_array(self, e, t):
        n = np.zeros(e * 3)
        for a in range(e):
            for r in range(3):
                n[3 * a + r] = (self.read_uint16() - self.X) / self.X * t
        return n

    def get_scale_array(self, e, t):
        n = np.zeros(e * 3)
        for a in range(e):
            for r in range(3):
                n[3 * a + r] = self.read_uint16() / self.H * t
        return n

    def read(self):
        reader = self.reader
        self.version = round(reader.read_float(), 2)
        self.get_start_points()
        with reader.save_current_pos():
            reader.seek(self.i1_offset)
            for _ in range(math.ceil(self.i1_count / 8)):
                byte = reader.read_int8()
                for i in range(8):
                    self._i1_array.append(bool(byte & (1 << i)))
        self._init_settings()
        self._init_indices()
        self._init_points()
        self._init_normals()
        self._init_uvs()
        self._init_vertex_colors()
        self._init_blends()
        self._init_weights()
        self._init_parent()
        try:
            self._init_poses();
        except:
            pass

    def get_bit(self):
        self.bit_cursor += 1
        return self._i1_array[self.bit_cursor - 1]

    def get_start_points(self):
        reader = self.reader
        self.i32_count = reader.read_float_int32()
        self.i16_count = reader.read_float_int32()
        self.i8_count = reader.read_float_int32()
        self.i1_count = reader.read_float_int32()
        e = 20
        if self.version >= 1.4:
            e += 4
            self.export_time = reader.read_float()
        self.i32_offset = e
        self.i16_offset = self.i32_offset + 4 * self.i32_count
        self.i8_offset = self.i16_offset + 2 * self.i16_count
        self.i1_offset = self.i8_offset + self.i8_count

    def _init_settings(self):
        default_attributes = ["mesh", "normals", "uv1", "uv2", "blendTargets", "blendNormals", "weights", "animations",
                              "jointScales", "addon", "paintMapping", "singleParent", "frameMappings", "indices32bit",
                              "originalIndices", "vertexColors"]
        if self.version >= 1.2:
            default_attributes.append('posGroups')
        t = 32
        if self.version >= 1.25:
            default_attributes.append('uvSeams')
            default_attributes.append('rivets')
            t -= 2
        r = {}
        for attr in default_attributes:
            r[attr] = self.get_bit()
        if self.version >= 1.2:
            self.bit_cursor += t
            self.options = r
            self.geometry.main_skeleton = not self.options['addon'] and self.options['weights']

    def _init_indices(self):
        if self.options['mesh']:
            indices_count = self.read_uint32()
            if self.options['indices32bit']:
                self.geometry.index = [self.read_uint32() for _ in range(indices_count)]
            else:
                self.geometry.index = [self.read_uint16() for _ in range(indices_count)]
            if self.options['originalIndices']:
                if self.options['indices32bit']:
                    self.geometry.original_indices = [self.read_uint32() for _ in range(indices_count)]
                else:
                    self.geometry.original_indices = [self.read_uint16() for _ in range(indices_count)]

    def _init_points(self):
        if self.options['mesh']:
            vertex_count = self.read_uint32() if self.options['indices32bit'] else self.read_uint16()
            self.vertex_count = vertex_count
            self.geometry.has_geometry = True
            # Z Y X
            bbox = [self.read_float() for _ in range(6)]
            scale = [bbox[3] - bbox[0], bbox[4] - bbox[1], (bbox[5] - bbox[2])]
            self.geometry.offset = [bbox[0] * scale[0], bbox[1] * scale[1], bbox[2] * scale[2]]
            self.geometry.bounds = [bbox[0:3], bbox[3:6]]
            verts = []
            for _ in range(vertex_count):
                verts.append((self.read_uint16() / self.ge * scale[0] + bbox[0],
                              self.read_uint16() / self.ge * scale[1] + bbox[1],
                              self.read_uint16() / self.ge * scale[2] + bbox[2]
                              ))
                self.geometry.positions = verts

    def _init_normals(self):
        if self.options['normals']:
            if self.vertex_count != 0:
                normals = []
                r = 0
                for _ in range(self.vertex_count):
                    normals.append(self.read_int8() / self.me * 2 - 1)
                    normals.append(self.read_int8() / self.me * 2 - 1)
                    normals.append(
                        (2 * self.get_bit() - 1) * (1 - math.pow(normals[r], 2) - math.pow(normals[r + 1], 2)))
                    r += 3
                self.geometry.normals = split(normals, 3)

    def _init_uvs(self):
        if self.options['uv1']:
            uvs = ['uv', 'uv2'] if self.options['uv2'] else ['uv']
            for uv in uvs:
                n = [self.read_float() for _ in range(4)]
                s = [n[2] - n[0], n[3] - n[1]]
                u = []
                for i in range(self.vertex_count):
                    u.append((self.read_uint16() / self.ge * s[0] + n[0], self.read_uint16() / self.ge * s[1] + n[1]))
                setattr(self.geometry, uv, u)

    def _init_vertex_colors(self):
        if self.options['vertexColors']:
            layer_count = self.read_int8()
            for t in range(layer_count):
                layer_name = self.read_string()
                v_colors = []
                for _ in range(self.vertex_count):
                    col = self.read_int8()
                    v_colors.append(col / 255)
                    v_colors.append(col / 255)
                    v_colors.append(col / 255)
                    v_colors.append(1)
                self.geometry.vertex_colors[layer_name] = np.array(v_colors).reshape((-1, 4))

    def _init_blends(self):
        if self.options['blendTargets']:
            shape_key_count = self.read_int8()
            if shape_key_count:
                shape_key_data = {}
                for shape_key_id in range(shape_key_count):
                    shape_key_name = self.read_string()
                    o = [self.read_float() for _ in range(6)]
                    u = [o[3] - o[0], o[4] - o[1], o[5] - o[2]]
                    c = []
                    for d in range(self.vertex_count):
                        c.append(self.read_int8() / self.me * u[0] + o[0])
                        c.append(self.read_int8() / self.me * u[1] + o[1])
                        c.append(self.read_int8() / self.me * u[2] + o[2])
                    shape_key_data[shape_key_name] = split(c, 3)
                    if self.options['blendNormals']:
                        for _ in range(self.vertex_count):
                            self.read_int8()
                            self.read_int8()
                            self.get_bit()
                self.geometry.shape_key_data = shape_key_data

    def _init_weights(self):
        if self.options['weights']:
            self.geometry.skinned = True
            weight_per_vert = self.read_int8()
            additional_weights = max(0, weight_per_vert - 4)
            skin_indices = np.zeros(4 * self.vertex_count, dtype=np.int16)
            additional_skin_indices = np.zeros(additional_weights * self.vertex_count, dtype=np.int16)
            u = 4 if weight_per_vert < 4 else weight_per_vert
            for l in range(u):
                if weight_per_vert > l:
                    if l < 4:
                        for t in range(self.vertex_count):
                            skin_indices[4 * t + l] = self.read_uint16(2 * (t * weight_per_vert + l), False)
                    else:
                        for t in range(self.vertex_count):
                            additional_skin_indices[t * additional_weights + (l - 4)] = self.read_uint16(
                                2 * (t * additional_weights + l), False)
            self.geometry.skin_indices = skin_indices.reshape((-1, u,))
            self.geometry.additional_skin_indices = additional_skin_indices.reshape((-1, u,))
            self.i16_offset = self.i16_offset + weight_per_vert * self.vertex_count * 2;
            skin_weights = np.zeros(4 * self.vertex_count, dtype=np.float32)
            additional_skin_weights = np.zeros(additional_weights * self.vertex_count, dtype=np.float32)
            u = 4 if weight_per_vert < 4 else weight_per_vert
            for f in range(u):
                if weight_per_vert > f:
                    if f < 4:
                        for c in range(self.vertex_count):
                            skin_weights[4 * c + f] = self.read_uint16(2 * (c * weight_per_vert + f), False) / self.ge
                    else:
                        for c in range(self.vertex_count):
                            additional_skin_weights[c * additional_weights + (f - 4)] = self.read_uint16(
                                2 * (c * weight_per_vert + f), False) / self.ge
            self.geometry.skin_weights = skin_weights.reshape((-1, u))
            self.geometry.additional_skin_weights = additional_skin_weights.reshape((-1, weight_per_vert))
            self.i16_offset = self.i16_offset + weight_per_vert * self.vertex_count * 2

    def _init_parent(self):
        if self.options['singleParent']:
            name = self.read_string()
            e = self.read_uint16()
            r = np.zeros(4 * self.vertex_count)
            i = np.zeros(4 * self.vertex_count)
            a = 4 * self.vertex_count
            for n in range(a):
                r[n] = e if n % 4 == 0 else 0
                i[n] = 1 if n % 4 == 0 else 0

            self.geometry.skin_indices = r.reshape((-1, 4))
            self.geometry.skin_weights = i.reshape((-1, 4))

    def _init_poses(self):
        if self.options['animations']:
            bone_count = self.read_int8()
            if self.options['frameMappings']:
                n = self.read_uint16()
                a = [self.read_uint16() for _ in range(n)]
                if n:
                    i = {}
                    for s in range(n):
                        i[a[s]] = s
            p = self.read_float()
            m = self.options['jointScales']
            g = self.read_float() if m else 1
            poses = {}
            locators = {}
            bones = []
            for y in range(bone_count):
                o = self.read_string()
                l = self.read_uint16()
                u = self.read_uint16()
                # print(o, l, u)
                v = lambda: {
                    "pos": self.get_position_array(1, p) if self.get_bit() else self.get_position_array(u, p),
                    "rot": self.get_quaternion_array(1) if self.get_bit() else self.get_quaternion_array(u),
                    "scl": self.get_scale_array(1, g) if self.get_bit() else self.get_scale_array(u, g) if m else [1, 1,
                                                                                                                   1],
                    "frameMapping": i if self.options["frameMappings"] else None
                }
                if o == 'main':
                    for S in range(l):
                        b = self.read_uint16()
                        w = HeroBone()
                        w.bone_id = S
                        w.name = self.read_string()
                        # print(w.name)
                        if b == 5e3:
                            self.geometry.main_skeleton = True
                            w.parent_id = -1
                            print(w.name, b, S)
                        else:
                            w.parent_id = b
                        k = v()
                        w.pos = k['pos']
                        w.quat = k['rot']
                        w.scale = k['scl']
                        bones.append(w)
                elif o == 'locators':
                    for R in range(l):
                        bone = HeroBone()
                        bone.name = self.read_string()
                        C = v()
                        bone.pos = C['pos']
                        bone.scale = C['cls']
                        bone.quat = C['rot']
                        locators[bone.name] = bone
                else:
                    c = {}
                    for x in range(l):
                        c[self.read_string()] = v()
                    poses[o] = c
            # print(h)
            self.geometry.bones = bones
            self.geometry.poses = poses
            self.geometry.locations = locators
Exemplo n.º 5
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.º 6
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.º 7
0
    def read(self, reader: ByteIO):
        items = reader.get_items()
        for item in items:
            reader.seek(item.offset)
            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('New model',self.name)
            if item.type == 30:
                items2 = reader.get_items()
                for item2 in items2:
                    reader.seek(item2.offset)
                    if item2.type == 1:
                        items3 = reader.get_items()
                        for item3 in items3:
                            reader.seek(item3.offset)
                            flag = reader.read_fmt('BBBB')
                            if flag == (103, 0, 65, 0):
                                mesh_chunk = None
                                mat_chunk = None
                                items4 = reader.get_items()
                                for item4 in items4:
                                    reader.seek(item4.offset)

                                    if item4.type == 31:
                                        items5 = reader.get_items()
                                        for item5 in items5:
                                            reader.seek(item5.offset)
                                            if item5.type == 20:
                                                mesh_chunk = reader.read_ascii_string(
                                                    reader.read_int32())
                                    if item4.type == 33:
                                        items5 = reader.get_items()
                                        for item5 in items5:
                                            reader.seek(item5.offset)
                                            if item5.type == 20:
                                                mat_chunk = reader.read_ascii_string(
                                                    reader.read_int32())
                                if mesh_chunk and mat_chunk:
                                    self.model_data.append(
                                        [mesh_chunk, mat_chunk])
            if item.type == 33:
                items2 = reader.get_items()
                for item2 in items2:
                    reader.seek(item2.offset)
                    if item2.type == 20:
                        tmp = reader.read_int32()
                    if item2.type == 21:
                        self.bone_count = reader.read_int32()
                    if item2.type == 22:
                        self.stream_offset = reader.tell()
                reader.seek(self.stream_offset)
                if self.bone_count:
                    for m in range(self.bone_count):
                        tm = reader.tell()
                        bone = Bone()
                        bone.name = reader.read_ascii_string(32)
                        bone.matrix = reader.read_fmt('f' * 16)
                        reader.skip(4 * 7)
                        bone.skin_id = reader.read_int32()
                        bone.parent = reader.read_int32()
                        reader.skip(4 * 3)
                        self.bones.append(bone)
                        reader.seek(tm + 144)
                        self.name_list[bone.skin_id] = bone.name
            if item.type == 35:
                items2 = reader.get_items()
                for item2 in items2:
                    reader.seek(item2.offset)
                    if item2.type == 1:
                        items3 = reader.get_items()
                        for item3 in items3:
                            reader.seek(item3.offset)
                            flag = reader.read_fmt('BBBB')
                            if flag == (160, 0, 65, 0):
                                items4 = reader.get_items()
                                count = 0
                                stream_offset = 0
                                for item4 in items4:
                                    reader.seek(item4.offset)
                                    if item4.type == 22:
                                        count = reader.read_int32()
                                    if item4.type == 23:
                                        stream_offset = reader.tell()
                                if count:
                                    reader.seek(stream_offset)
                                    self.bone_map_list.append([
                                        reader.read_int32()
                                        for _ in range(count)
                                    ])
Exemplo n.º 8
0
 def read(self, reader: ByteIO):
     items = reader.get_items()
     for item in items:
         reader.seek(item.offset)
         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 == 30:
             items2 = reader.get_items()
             for item2 in items2:
                 reader.seek(item2.offset)
                 if item2.type == 20:
                     self.diffuse = reader.read_ascii_string(
                         reader.read_int32())
         if item.type == 32:
             items2 = reader.get_items()
             for item2 in items2:
                 reader.seek(item2.offset)
                 if item2.type == 20:
                     self.glow = reader.read_ascii_string(
                         reader.read_int32())
         if item.type == 42 or item.type == 50:
             items2 = reader.get_items()
             for item2 in items2:
                 reader.seek(item2.offset)
                 if item2.type == 20:
                     self.normal = reader.read_ascii_string(
                         reader.read_int32())
         if item.type == 44:
             items2 = reader.get_items()
             for item2 in items2:
                 reader.seek(item2.offset)
                 if item2.type == 20:
                     self.mask = reader.read_ascii_string(
                         reader.read_int32())
         if item.type == 49:
             items2 = reader.get_items()
             for item2 in items2:
                 reader.seek(item2.offset)
                 if item2.type == 20:
                     self.something1 = reader.read_ascii_string(
                         reader.read_int32())
Exemplo n.º 9
0
    def read(self, reader: ByteIO):
        header_chunks = reader.get_items()
        for item in header_chunks:
            reader.seek(item.offset)

            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 == 1:
                items = reader.get_items()
                for item in items:
                    reader.seek(item.offset)

                    if item.type == 10:
                        items2 = reader.get_items()
                        for item2 in items2:
                            reader.seek(item2.offset)
                            if item2.type == 21:
                                self.indices_count = reader.read_int32()
                            if item2.type == 22:
                                self.indices_offset = reader.tell()
                        if self.indices_count is not None:
                            self.mode = 1
                            reader.seek(self.indices_offset)
                            self.indices = [
                                reader.read_uint16()
                                for _ in range(self.indices_count)
                            ]

                    if item.type == 21:
                        items2 = reader.get_items()
                        for item2 in items2:
                            reader.seek(item2.offset)
                            if item2.type == 21:
                                self.indices_count = reader.read_int32()
                            if item2.type == 22:
                                self.indices_offset = reader.tell()
                        if self.indices_count is not None:
                            self.mode = 2
                            reader.seek(self.indices_offset)
                            self.indices = [
                                reader.read_uint16()
                                for _ in range(self.indices_count)
                            ]

                    if item.type == 11:
                        items2 = reader.get_items()
                        for item2 in items2:
                            reader.seek(item2.offset)
                            if item2.type == 20:
                                items3 = reader.get_items()
                                for item3 in items3:
                                    reader.seek(item3.offset)

                                    if item3.type == 21:
                                        self.vert_stride = reader.read_int32()
                                    if item3.type == 22:
                                        self.vert_item_count = reader.read_int32(
                                        )
                                    if item3.type == 23:
                                        self.vert_offset = reader.tell()
                                    reader.seek(self.vert_offset)
                                off = 0
                                for k in range(self.vert_item_count):
                                    a, b, c, d = reader.read_fmt('BBBB')
                                    # print k,a,b,c,d,vertStrideSize
                                    if c == 1: self.pos_offset = off
                                    if c == 5 and a == 0:
                                        self.uv_offset = off
                                    # print k,a,b,c,d,vertStrideSize
                                    if c == 11: self.skin_ind_offset = off
                                    if c == 10: self.skin_weight_offset = off
                                    if d == 2: off += 12
                                    if d == 1: off += 8
                                    if d == 3: off += 16
                                    if d == 4: off += 1
                                    if d == 7: off += 1
                                    if d == 15: off += 4
                            if item2.type == 21:
                                self.vert_count = reader.read_int32()
                            if item2.type == 22:
                                self.stream_offset = reader.tell()
        reader.seek(self.stream_offset)
        for k in range(self.vert_count):
            tk = reader.tell()
            if self.pos_offset is not None:
                reader.seek(self.pos_offset + tk)
                self.vertices.append(reader.read_fmt('fff'))
            if self.uv_offset is not None:
                reader.seek(self.uv_offset + tk)
                self.uv.append([reader.read_float(), 1 - reader.read_float()])
            if self.skin_ind_offset:
                # reader.seek(self.skin_ind_offset + tk)
                i1, i2, i3 = reader.read_fmt('BBB')
                self.weight_inds.append([i1, i2])
            if self.skin_weight_offset:
                # reader.seek(self.skin_weight_offset + tk)
                w1, w2 = reader.read_fmt('BB')
                w3 = 255 - (w1 + w2)
                self.weight_weight.append([w1, w2])
            reader.seek(tk + self.vert_stride)
Exemplo n.º 10
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))