import struct, sys, os, io from dataclasses import dataclass, field @dataclass class pak2_chunks: theirsce: bytes = b"" lipsync: bytes = b"" unused: bytes = b"" image_unk1: bytes = b"" image_unk2: bytes = b"" image_blobs: list = field(default_factory=list) @dataclass class pak2_file: #offsets: list char_count: int = 0 slot_count: int = 0 image_count: int = 0 chunks: pak2_chunks = field(default_factory=pak2_chunks) def get_file_name_noext(path): return os.path.splitext(os.path.basename(path))[0] def get_parent_folder(path): return os.path.normpath(os.path.join(path, os.pardir)) def insert_padded_chunk(file: bytes, chunk: bytes, alignment: int = 4): file.write(chunk) pad = (alignment - (file.tell() % alignment)) % alignment file.write(b"\x00" * pad) return file.tell() def get_theirsce_from_pak2(file: bytes)->bytes: offsets = struct.unpack("<3I", file[:12]) # Handle null 2nd offset because of course that's a thing if offsets[1] == 0: return file[offsets[0] : offsets[2]] else: return file[offsets[0] : offsets[1]] def get_data(file: bytes)->pak2_file: offsets = struct.unpack("<6I", file[:24]) data = pak2_file() data.char_count = struct.unpack("bytes: output = io.BytesIO() output.seek(0) output.write(b"\x00" * 0x20) offsets_new = [] offsets_new.append(output.tell()) # theirsce offsets_new.append(insert_padded_chunk(output, data.chunks.theirsce)) # lipsync offsets_new.append(insert_padded_chunk(output, data.chunks.lipsync)) # unused offsets_new.append(insert_padded_chunk(output, data.chunks.unused)) # unk1 offsets_new.append(insert_padded_chunk(output, data.chunks.image_unk1)) # unk2 offsets_new.append(insert_padded_chunk(output, data.chunks.image_unk2)) # images # Create image chunk image_chunk = b"\x00" * (data.image_count * 8) # minimum size insert_padded_chunk(output, image_chunk, 128) image_offsets = [] image_offsets.append(output.tell()) for blob in data.chunks.image_blobs: image_offsets.append(insert_padded_chunk(output, blob, 128)) image_offsets = image_offsets[:-1] image_offsets = [ val for val in image_offsets for _ in (0, 1) ] # image data offsets are duplicated # Write image data offsets output.seek(offsets_new[5]) output.write(struct.pack("<%dI" % len(image_offsets), *image_offsets)) # Write chunk offsets output.seek(0) output.write(struct.pack("<%dI" % len(offsets_new), *offsets_new)) # Write metadata output.write(struct.pack(" 2: with open(sys.argv[2], "rb+") as f: theirsce = f.read() pak2.chunks.theirsce = theirsce with open(sys.argv[1] + ".new", "wb+") as output: output.write(create_pak2(pak2)) print("Done!")