public FPakEntry(PakFileReader reader, string path, FArchive Ar) : base(reader) { Path = path; // FPakEntry is duplicated before each stored file, without a filename. So, // remember the serialized size of this structure to avoid recomputation later. var startOffset = Ar.Position; Offset = Ar.Read <long>(); CompressedSize = Ar.Read <long>(); UncompressedSize = Ar.Read <long>(); Size = UncompressedSize; if (reader.Info.Version < EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod) { try { CompressionMethod = reader.Info.CompressionMethods[Ar.Read <int>()]; } catch { CompressionMethod = CompressionMethod.Unknown; } } else if (reader.Info.Version == EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod && !reader.Info.IsSubVersion) { CompressionMethod = reader.Info.CompressionMethods[Ar.Read <byte>()]; } else { CompressionMethod = reader.Info.CompressionMethods[Ar.Read <int>()]; } if (reader.Info.Version < EPakFileVersion.PakFile_Version_NoTimestamps) { Ar.Position += 8; // Timestamp } Ar.Position += 20; // Hash if (reader.Info.Version >= EPakFileVersion.PakFile_Version_CompressionEncryption) { if (CompressionMethod != CompressionMethod.None) { CompressionBlocks = Ar.ReadArray <FPakCompressedBlock>(); } IsEncrypted = Ar.ReadFlag(); CompressionBlockSize = Ar.Read <uint>(); } if (reader.Info.Version >= EPakFileVersion.PakFile_Version_RelativeChunkOffsets) { // Convert relative compressed offsets to absolute for (var i = 0; i < CompressionBlocks.Length; i++) { CompressionBlocks[i].CompressedStart += Offset; CompressionBlocks[i].CompressedEnd += Offset; } } StructSize = (ushort)(Ar.Position - startOffset); }
private FPakInfo(FArchive Ar, OffsetsToTry offsetToTry) { // New FPakInfo fields. EncryptionKeyGuid = Ar.Read <FGuid>(); // PakFile_Version_EncryptionKeyGuid EncryptedIndex = Ar.Read <byte>() != 0; // Do not replace by ReadFlag // Old FPakInfo fields Magic = Ar.Read <uint>(); if (Magic != PAK_FILE_MAGIC) { // Stop immediately when magic is wrong return; } Version = Ar.Read <EPakFileVersion>(); IsSubVersion = (Version == EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod && offsetToTry == OffsetsToTry.Size8a); IndexOffset = Ar.Read <long>(); IndexSize = Ar.Read <long>(); IndexHash = new FSHAHash(Ar); if (Version == EPakFileVersion.PakFile_Version_FrozenIndex) { var bIndexIsFrozen = Ar.ReadFlag(); // used just for 4.25, so don't do any support unless it's really needed if (bIndexIsFrozen) { throw new ParserException(Ar, "Pak index is frozen"); } } if (Version < EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod) { CompressionMethods = new List <CompressionMethod> { CompressionMethod.None, CompressionMethod.Zlib, CompressionMethod.Gzip, CompressionMethod.Custom, CompressionMethod.Oodle }; } else { var maxNumCompressionMethods = offsetToTry switch { OffsetsToTry.Size8a => 5, OffsetsToTry.Size8 => 4, OffsetsToTry.Size8_1 => 1, OffsetsToTry.Size8_2 => 2, OffsetsToTry.Size8_3 => 3, _ => 4 }; unsafe { var bufferSize = COMPRESSION_METHOD_NAME_LEN * maxNumCompressionMethods; var buffer = stackalloc byte[bufferSize]; Ar.Serialize(buffer, bufferSize); CompressionMethods = new List <CompressionMethod>(maxNumCompressionMethods + 1) { CompressionMethod.None }; for (var i = 0; i < maxNumCompressionMethods; i++) { var name = new string((sbyte *)buffer + i * COMPRESSION_METHOD_NAME_LEN, 0, COMPRESSION_METHOD_NAME_LEN).TrimEnd('\0'); if (string.IsNullOrEmpty(name)) { continue; } if (!Enum.TryParse(name, out CompressionMethod method)) { Log.Warning($"Unknown compression method '{name}' in {Ar.Name}"); method = CompressionMethod.Unknown; } CompressionMethods.Add(method); } } } // Reset new fields to their default states when seralizing older pak format. if (Version < EPakFileVersion.PakFile_Version_IndexEncryption) { EncryptedIndex = default; } if (Version < EPakFileVersion.PakFile_Version_EncryptionKeyGuid) { EncryptionKeyGuid = default; } }
public FPakEntry(PakFileReader reader, string path, FArchive Ar) : base(reader) { Path = path; // FPakEntry is duplicated before each stored file, without a filename. So, // remember the serialized size of this structure to avoid recomputation later. var startOffset = Ar.Position; Offset = Ar.Read <long>(); CompressedSize = Ar.Read <long>(); UncompressedSize = Ar.Read <long>(); Size = UncompressedSize; if (reader.Info.Version < EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod) { var LegacyCompressionMethod = Ar.Read <ECompressionFlags>(); int CompressionMethodIndex; if (LegacyCompressionMethod == ECompressionFlags.COMPRESS_None) { CompressionMethodIndex = 0; } else if (LegacyCompressionMethod == ECompressionFlags.COMPRESS_LZ4) { CompressionMethodIndex = 4; } else if (LegacyCompressionMethod.HasFlag(ECompressionFlags.COMPRESS_ZLIB)) { CompressionMethodIndex = 1; } else if (LegacyCompressionMethod.HasFlag(ECompressionFlags.COMPRESS_GZIP)) { CompressionMethodIndex = 2; } else if (LegacyCompressionMethod.HasFlag(ECompressionFlags.COMPRESS_Custom)) { CompressionMethodIndex = 3; } else { CompressionMethodIndex = -1; //throw new ParserException("Found an unknown compression type in pak file, will need to be supported for legacy files"); } CompressionMethod = CompressionMethodIndex == -1 ? CompressionMethod.Unknown : reader.Info.CompressionMethods[CompressionMethodIndex]; } else if (reader.Info.Version == EPakFileVersion.PakFile_Version_FNameBasedCompressionMethod && !reader.Info.IsSubVersion) { CompressionMethod = reader.Info.CompressionMethods[Ar.Read <byte>()]; } else { CompressionMethod = reader.Info.CompressionMethods[Ar.Read <int>()]; } if (reader.Info.Version < EPakFileVersion.PakFile_Version_NoTimestamps) { Ar.Position += 8; // Timestamp } Ar.Position += 20; // Hash if (reader.Info.Version >= EPakFileVersion.PakFile_Version_CompressionEncryption) { if (CompressionMethod != CompressionMethod.None) { CompressionBlocks = Ar.ReadArray <FPakCompressedBlock>(); } IsEncrypted = Ar.ReadFlag(); CompressionBlockSize = Ar.Read <uint>(); } if (reader.Info.Version >= EPakFileVersion.PakFile_Version_RelativeChunkOffsets) { // Convert relative compressed offsets to absolute for (var i = 0; i < CompressionBlocks.Length; i++) { CompressionBlocks[i].CompressedStart += Offset; CompressionBlocks[i].CompressedEnd += Offset; } } StructSize = (int)(Ar.Position - startOffset); }