/// <summary> /// Reads the PAK file metadata, including file list information and the file list /// </summary> /// <exception cref="NotSupportedException">Is thrown if the given PAK file does not have a valid signature</exception> private void ReadMetadata() { using (BinaryReader reader = new BinaryReader(new MemoryStream(File.ReadAllBytes(FilePath)))) { reader.BaseStream.Seek(-9L, SeekOrigin.End); uint fileListOffset = reader.ReadUInt32(); uint fileCount = reader.ReadUInt32(); if ((reader.ReadByte()) != 0x12) { throw new NotSupportedException("The signature of this PAK file is invalid!"); } reader.BaseStream.Seek(fileListOffset, SeekOrigin.Begin); for (uint i = 0; i < fileCount; i++) { FileEntry fileEntry = new FileEntry(); fileEntry.FileNameLength = reader.ReadByte(); fileEntry.Compression = reader.ReadByte(); fileEntry.Offset = reader.ReadUInt32(); fileEntry.FileSize = reader.ReadUInt32(); fileEntry.RealFileSize = reader.ReadUInt32(); byte[] tempName = reader.ReadBytes(fileEntry.FileNameLength); if (fileEntry.Compression < 4) { uint decryptionKey = (uint)Key; reader.BaseStream.Seek(1L, SeekOrigin.Current); fileEntry.FileName = Encoding.UTF8.GetString(XOR.Cipher(tempName, decryptionKey)); } else { uint[] decryptionKey = (uint[])Key; fileEntry.Compression ^= 0x20; fileEntry.FileName = DecryptFileName(tempName, decryptionKey); uint[] decryptionData = { fileEntry.Offset, fileEntry.RealFileSize }; uint[] resultData = XTEA.Decipher(16, decryptionData, decryptionKey); fileEntry.Offset = resultData[0]; fileEntry.RealFileSize = resultData[1]; } Entries.Add(fileEntry); } } }
/// <summary> /// Reads the file entries of the PAK file /// </summary> public void ReadFileEntries() { long Position = Reader.BaseStream.Position; Reader.BaseStream.Seek(FileListOffset, SeekOrigin.Begin); for (uint i = 0; i < FileCount; i++) { FileEntry fileEntry = new FileEntry(); fileEntry.FileNameLength = Reader.ReadByte(); fileEntry.Compression = Reader.ReadByte(); fileEntry.Offset = Reader.ReadUInt32(); fileEntry.FileSize = Reader.ReadUInt32(); fileEntry.RealFileSize = Reader.ReadUInt32(); byte[] tempName = Reader.ReadBytes(fileEntry.FileNameLength); if (fileEntry.Compression < 4 && fileEntry.Compression > -1) { uint decryptionKey = (uint)Key; fileEntry.Unknown1 = Reader.ReadByte(); fileEntry.FileName = Encoding.UTF8.GetString(XOR.Cipher(tempName, decryptionKey)); } else { uint[] decryptionKey = (uint[])Key; fileEntry.Compression ^= 0x20; fileEntry.FileName = DecryptFileName(tempName, decryptionKey); uint[] decryptionData = new uint[] { fileEntry.Offset, fileEntry.RealFileSize }; uint[] resultData = XTEA.Decipher(16, decryptionData, decryptionKey); fileEntry.Offset = resultData[0]; fileEntry.RealFileSize = resultData[1]; } Entries.Add(fileEntry); } Reader.BaseStream.Seek(Position, SeekOrigin.Begin); }