Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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;
            }
        }
Exemplo n.º 3
0
        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);
        }