public FObjectExport(FPackageFileSummary InSum) { Sum = InSum; }
private static void ProcessFile(string Path, string OutPath) { using (var Input = File.OpenRead(Path)) { using (var Reader = new BinaryReader(Input)) { var Sum = new FPackageFileSummary(); Sum.Deserialize(Reader); if ((Sum.CompressionFlags & ECompressionFlags.COMPRESS_ZLIB) == 0) { throw new Exception("Unsupported CompressionFlags"); } // Decrypt the rest of the package header var EncryptedSize = Sum.TotalHeaderSize - Sum.GarbageSize - Sum.NameOffset; EncryptedSize = (EncryptedSize + 15) & ~15; // Round up to the next block var EncryptedData = new byte[EncryptedSize]; Input.Seek(Sum.NameOffset, SeekOrigin.Begin); Input.Read(EncryptedData, 0, EncryptedData.Length); var DecryptedData = Decrypt(EncryptedData); var ChunkInfo = new TArray <FCompressedChunkInfo>(() => new FCompressedChunkInfo(Sum)); using (var DecryptedStream = new MemoryStream(DecryptedData)) { using (var DecryptedReader = new BinaryReader(DecryptedStream)) { // Get the compressed chunk info from inside the encrypted data DecryptedStream.Seek(Sum.CompressedChunkInfoOffset, SeekOrigin.Begin); ChunkInfo.Deserialize(DecryptedReader); // Store exports for reserialization DecryptedStream.Seek(Sum.ExportOffset - Sum.NameOffset, SeekOrigin.Begin); } } // Copy the original file data var FileBuf = new byte[Input.Length]; Input.Seek(0, SeekOrigin.Begin); Input.Read(FileBuf, 0, FileBuf.Length); // Save to output file using (var Output = File.Open(OutPath, FileMode.Create)) { Output.Write(FileBuf, 0, FileBuf.Length); // Write decrypted data Output.Seek(Sum.NameOffset, SeekOrigin.Begin); Output.Write(DecryptedData, 0, DecryptedData.Length); // Decompress compressed chunks foreach (var Chunk in ChunkInfo) { Input.Seek(Chunk.CompressedOffset, SeekOrigin.Begin); var Header = new FCompressedChunkHeader(); Header.Deserialize(Reader); var TotalBlockSize = 0; var Blocks = new List <FCompressedChunkBlock>(); while (TotalBlockSize < Header.Sum.UncompressedSize) { var Block = new FCompressedChunkBlock(); Block.Deserialize(Reader); Blocks.Add(Block); TotalBlockSize += Block.UncompressedSize; } Output.Seek(Chunk.UncompressedOffset, SeekOrigin.Begin); foreach (var Block in Blocks) { var CompressedData = new byte[Block.CompressedSize]; Input.Read(CompressedData, 0, CompressedData.Length); // Zlib inflate var ZlibStream = new InflaterInputStream(new MemoryStream(CompressedData)); ZlibStream.CopyTo(Output); } } } } } }
public FCompressedChunkInfo(FPackageFileSummary InSum) { Sum = InSum; }