def load_resources(path: str) -> List[Resource]: reader = BinaryReader.from_path(path) resources = [] file_type = reader.read_string(4) file_version = reader.read_string(4) reader.seek(16) resource_count = reader.read_uint32() reader.seek(24) key_list_offset = reader.read_uint32() resource_list_offset = reader.read_uint32() for i in range(resource_count): reader.seek(key_list_offset + 24 * i) res_ref = reader.read_string(16) reader.skip(4) res_type = ResourceType.get(reader.read_uint16()) reader.skip(2) reader.seek(resource_list_offset + 8 * i) res_offset = reader.read_uint32() res_size = reader.read_uint32() resources.append(Resource(res_ref, res_type, res_size, res_offset)) return resources
def _rgba_bytes_from_dxt1(self, mipmap: int = 0) -> bytearray: dxt_reader = BinaryReader.from_data(self._mipmaps[mipmap]) width, height = self.get_mipmap_size(mipmap) pixels = [0] * width * height for ty in range(height, 0, -4): for tx in range(0, width, 4): color0 = self._rgba565_to_rgb888(dxt_reader.read_int16()) color1 = self._rgba565_to_rgb888(dxt_reader.read_int16()) dxt_pixels = dxt_reader.read_uint32(True) color_code = [] color_code.extend([color0, color1]) if color0 > color1: color_code.append(self._interpolate(0.3333333, color0, color1)) color_code.append(self._interpolate(0.6666666, color0, color1)) else: color_code.append(self._interpolate(0.5555555, color0, color1)) color_code.append(0xFF000000) for y in range(4): for x in range(4): pixel_code = dxt_pixels & 3 dxt_pixels >>= 2 pixels[(ty - 4 + y) * self._width + (tx + x)] = color_code[pixel_code] + 0xFF000000 data = bytearray() for pixel in pixels: data.append((pixel & 0x00FF0000) >> 16) data.append((pixel & 0x0000FF00) >> 8) data.append((pixel & 0x000000FF)) data.append(255) return data
def load(data: bytes) -> TLK: reader = BinaryReader.from_data(data) tlk = TLK() file_type = reader.read_string(4) file_version = reader.read_string(4) tlk.language_id = reader.read_uint32() string_count = reader.read_uint32() string_entries_offset = reader.read_uint32() for i in range(string_count): reader.seek(20 + i * 40) flags = reader.read_uint32() res_ref = reader.read_string(16) reader.skip(4) reader.skip(4) offset_to_string = reader.read_uint32() + string_entries_offset string_size = reader.read_uint32() reader.skip(4) reader.seek(offset_to_string) text = reader.read_string(string_size) tlk.add(Entry.new(res_ref, text)) return tlk
def load(data: bytes) -> ERF: reader = BinaryReader.from_data(data) erf = ERF() file_type = reader.read_string(4) file_version = reader.read_string(4) reader.seek(16) resource_count = reader.read_uint32() reader.seek(24) key_list_offset = reader.read_uint32() resource_list_offset = reader.read_uint32() for i in range(resource_count): reader.seek(key_list_offset + 24 * i) res_ref = reader.read_string(16) reader.skip(4) res_type = ResourceType.get(reader.read_uint16()) reader.skip(2) reader.seek(resource_list_offset + 8 * i) res_offset = reader.read_uint32() res_size = reader.read_uint32() reader.seek(res_offset) res_data = reader.read_bytes(res_size) erf.add(Resource.new(res_ref, res_type, res_data)) return erf
def load(data: bytes) -> WOK: reader = BinaryReader.from_data(data) wok = WOK() file_type = reader.read_string(4) file_version = reader.read_string(4) wok.walkmesh_type = WalkmeshType(reader.read_int32()) reader.skip(48) vertex_count = reader.read_vertex() vertex_count = reader.read_uint32() vertices_offset = reader.read_uint32() face_count = reader.read_uint32() face_indices_offset = reader.read_uint32() face_materials_offset = reader.read_uint32() face_normals_offset = reader.read_uint32() face_distances_offset = reader.read_uint32() aabb_count = reader.read_uint32() aabbs_offset = reader.read_uint32() reader.skip(4) adjacency_count = reader.read_int32() adjacencies_offset = reader.read_int32() edge_count = reader.read_int32() edges_offset = reader.read_int32() perimeter_count = reader.read_int32() perimeters_offset = reader.read_int32() wok.faces = [Face() for _ in range(face_count)] vertices = [] reader.seek(vertices_offset) for i in range(vertex_count): vertices.append(reader.read_vertex()) reader.seek(face_indices_offset) for i in range(face_count): v1 = reader.read_uint32() v2 = reader.read_uint32() v3 = reader.read_uint32() wok.faces[i].vertices[0] = vertices[v1] wok.faces[i].vertices[1] = vertices[v2] wok.faces[i].vertices[2] = vertices[v3] reader.seek(face_materials_offset) for i in range(face_count): wok.faces[i].material = Material(reader.read_int32()) reader.seek(edges_offset) for i in range(edge_count): edge_index = reader.read_int32() transition = reader.read_int32() face_index = edge_index // 3 adjaceny_index = edge_index % 3 if transition != -1: wok.faces[face_index].transitions[adjaceny_index] = transition return wok
def _rgba_bytes_from_dxt5(self, mipmap: int = 0) -> bytearray: dxt_reader = BinaryReader.from_data(self._mipmaps[mipmap]) width, height = self.get_mipmap_size(mipmap) pixels = [0] * width * height for ty in range(height, 0, -4): for tx in range(0, width, 4): alpha0 = dxt_reader.read_uint8() alpha1 = dxt_reader.read_uint8() dxt_alpha = self._integer48(dxt_reader.read_bytes(6)) color0 = self._rgba565_to_rgb888(dxt_reader.read_int16()) color1 = self._rgba565_to_rgb888(dxt_reader.read_int16()) dxt_pixels = dxt_reader.read_uint32(True) color_code = [] color_code.extend([color0, color1]) if color0 > color1: color_code.append(self._interpolate(0.3333333, color0, color1)) color_code.append(self._interpolate(0.6666666, color0, color1)) else: color_code.append(self._interpolate(0.5555555, color0, color1)) color_code.append(0xFF000000) alpha_code = [alpha0, alpha1] if alpha0 > alpha1: alpha_code.append(int((6.0 * alpha0 + 1.0 * alpha1 + 3) / 7)) alpha_code.append(int((5.0 * alpha0 + 2.0 * alpha1 + 3) / 7)) alpha_code.append(int((4.0 * alpha0 + 3.0 * alpha1 + 3) / 7)) alpha_code.append(int((3.0 * alpha0 + 4.0 * alpha1 + 3) / 7)) alpha_code.append(int((2.0 * alpha0 + 5.0 * alpha1 + 3) / 7)) alpha_code.append(int((1.0 * alpha0 + 6.0 * alpha1 + 3) / 7)) else: alpha_code.append(int((4.0 * alpha0 + 1.0 * alpha1 + 1) / 5)) alpha_code.append(int((3.0 * alpha0 + 2.0 * alpha1 + 2) / 5)) alpha_code.append(int((2.0 * alpha0 + 3.0 * alpha1 + 2) / 5)) alpha_code.append(int((1.0 * alpha0 + 4.0 * alpha1 + 2) / 5)) alpha_code.append(0) alpha_code.append(255) for y in range(4): for x in range(4): pixelc_code = dxt_pixels & 3 dxt_pixels >>= 2 a = alpha_code[(dxt_alpha >> (3 * (4 * (3 - y) + x))) & 7] pixel = color_code[pixelc_code] | (a << 24) pixels[(ty - 4 + y) * self.width + (tx + x)] = pixel data = bytearray() for pixel in pixels: data.append((pixel & 0x00FF0000) >> 16) data.append((pixel & 0x0000FF00) >> 8) data.append((pixel & 0x000000FF)) data.append((pixel & 0xFF000000) >> 24) return data
def load(data: bytes) -> SSF: ssf = SSF() reader = BinaryReader.from_data(data) file_type = reader.read_string(4) file_version = reader.read_string(4) table_offset = reader.read_uint32() reader.seek(table_offset) for i in range(40): ssf.entries[i] = reader.read_int32() return ssf
def load_resources(path: str, resources: Dict[int, Resource]) -> None: reader = BinaryReader.from_path(path) file_type = reader.read_string(4) file_version = reader.read_string(4) resource_count = reader.read_uint32() reader.skip(4) resources_offset = reader.read_uint32() reader.seek(resources_offset) for i in range(resource_count): res_id = reader.read_uint32() resources[res_id].res_offset = reader.read_uint32() resources[res_id].res_size = reader.read_uint32() resources[res_id].path = path res_type_id = reader.read_uint32()
def load(data: bytes) -> LIP: lip = LIP() reader = BinaryReader.from_data(data) file_type = reader.read_string(4) file_version = reader.read_string(4) lip.length = reader.read_float32() entry_count = reader.read_int32() ''' KotOR.JS ignores 5 bytes after the header and subtracts the entry count by 1? Not sure why... ''' for i in range(entry_count): time = reader.read_float32() shape = Shape(reader.read_int8()) keyframe = KeyFrame.new(time, shape) lip.frames.append(keyframe) return lip
def load_resources(directory: str) -> Dict[int, Resource]: reader = BinaryReader.from_path(directory + "/chitin.key") resources: Dict[int, Resource] = dict() file_type = reader.read_string(4) file_version = reader.read_string(4) bif_count = reader.read_uint32() key_count = reader.read_uint32() bif_names_offset = reader.read_uint32() keys_offset = reader.read_uint32() bif_paths = [] for i in range(bif_count): reader.seek(bif_names_offset + i * 12) bif_size = reader.read_uint32() filename_offset = reader.read_uint32() filename_size = reader.read_uint16() drive = reader.read_uint16() reader.seek(filename_offset) bif_path = (directory + '/' + reader.read_string(filename_size)).replace('\\', '/') bif_paths.append(bif_path) reader.seek(keys_offset) for i in range(key_count): res_ref = reader.read_string(16) res_type = ResourceType.get(reader.read_uint16()) res_id = reader.read_uint32() resources[res_id] = Resource(res_ref, res_type) for bif in bif_paths: try: _BIFReader.load_resources(bif, resources) finally: pass return resources
def load(data: bytes) -> TPC: tpc = TPC() reader = BinaryReader.from_data(data) size = reader.read_int32() unknown = reader.read_float32() width = reader.read_int16() height = reader.read_int16() encoding = reader.read_uint8() mipmap_count = reader.read_uint8() reader.skip(114) texture_type = TextureType.Invalid if encoding == 1 and size == 0: texture_type = TextureType.Greyscale if encoding == 2 and size == 0: texture_type = TextureType.RGB if encoding == 4 and size == 0: texture_type = TextureType.RGBA if encoding == 2 and size > 0: texture_type = TextureType.DXT1 if encoding == 4 and size > 0: texture_type = TextureType.DXT5 mipmap_width = width mipmap_height = height mipmaps = [] for i in range(mipmap_count): mipmap_data = reader.read_bytes(_TPCReader._get_data_size(texture_type, mipmap_width, mipmap_height)) mipmap_width >>= 1 mipmap_height >>= 1 mipmaps.append(mipmap_data) tpc.set_mipmaps(width, height, mipmaps, texture_type) reader.seek(_TPCReader._get_txi_offset(texture_type, width, height, len(mipmaps), size)) tpc.txi = reader.read_string(reader.size() - reader.position()) return tpc
def load(data: bytes) -> RIM: reader = BinaryReader.from_data(data) rim = RIM() file_type = reader.read_string(4) file_version = reader.read_string(4) reader.skip(4) resource_count = reader.read_uint32() table_offset = reader.read_uint32() reader.skip(100) for i in range(resource_count): reader.seek(table_offset + 32 * i) res_ref = reader.read_string(16) res_type = ResourceType.get(reader.read_uint32()) reader.skip(4) res_offset = reader.read_uint32() res_size = reader.read_uint32() reader.seek(res_offset) res_data = reader.read_bytes(res_size) rim.add(Resource.new(res_ref, res_type, res_data)) return rim
def load(data: bytes) -> TwoDA: reader = BinaryReader.from_data(data) twoda = TwoDA() file_type = reader.read_string(4) file_version = reader.read_string(4) reader.skip(1) columns = [] while reader.peek() != 0: columns.append(reader.read_terminated_string('\t')) twoda.add_column(columns[-1]) column_count = len(columns) reader.skip(1) row_count = reader.read_int32() for i in range(row_count): row_name = reader.read_terminated_string('\t') cell_count = row_count * len(columns) cell_offsets = [] for i in range(cell_count): cell_offsets.append(reader.read_uint16()) reader.skip(2) data_offset = reader.position() for i in range(row_count): twoda.add_row() for j in range(column_count): cell_index = j + i * column_count reader.seek(data_offset + cell_offsets[cell_index]) data = reader.read_terminated_string('\0') twoda.set_data(columns[j], i, data) return twoda