internal FPackageFileSummary(BinaryReader reader) { bUnversioned = false; CustomVersionContainer = default; var Tag = reader.ReadInt32(); if (Tag != PACKAGE_FILE_TAG && Tag != PACKAGE_FILE_TAG_SWAPPED) { throw new FileLoadException("Not a UE package"); } // The package has been stored in a separate endianness than the linker expected so we need to force // endian conversion. Latent handling allows the PC version to retrieve information about cooked packages. if (Tag == PACKAGE_FILE_TAG_SWAPPED) { // Set proper tag. Tag = PACKAGE_FILE_TAG; // Toggle forced byte swapping. throw new NotImplementedException("Byte swapping for packages not implemented"); } /** * The package file version number when this package was saved. * * Lower 16 bits stores the UE3 engine version * Upper 16 bits stores the UE4/licensee version * For newer packages this is -7 * -2 indicates presence of enum-based custom versions * -3 indicates guid-based custom versions * -4 indicates removal of the UE3 version. Packages saved with this ID cannot be loaded in older engine versions * -5 indicates the replacement of writing out the "UE3 version" so older versions of engine can gracefully fail to open newer packages * -6 indicates optimizations to how custom versions are being serialized * -7 indicates the texture allocation info has been removed from the summary */ var LegacyFileVersion = reader.ReadInt32(); if (LegacyFileVersion < 0) // means we have modern version numbers { if (LegacyFileVersion < -7) // CurrentLegacyFileVersion { // we can't safely load more than this because the legacy version code differs in ways we can not predict. // Make sure that the linker will fail to load with it. throw new FileLoadException("Can't load legacy UE3 file"); } if (LegacyFileVersion != -4) { reader.BaseStream.Position += 4; // LegacyUE3Version (int32) } FileVersionUE4 = (EUnrealEngineObjectUE4Version)reader.ReadInt32(); FileVersionLicenseeUE4 = (EUnrealEngineObjectLicenseeUE4Version)reader.ReadInt32(); if (LegacyFileVersion <= -2) { CustomVersionContainer = new FCustomVersionContainer(reader); } if (FileVersionUE4 != 0 && FileVersionLicenseeUE4 != 0) { // this file is unversioned, remember that, then use current versions bUnversioned = true; // set the versions to latest here, etc. } } else { // This is probably an old UE3 file, make sure that the linker will fail to load with it. throw new FileLoadException("Can't load legacy UE3 file"); } TotalHeaderSize = reader.ReadInt32(); FolderName = reader.ReadFString(); PackageFlags = (EPackageFlags)reader.ReadUInt32(); NameCount = reader.ReadInt32(); NameOffset = reader.ReadInt32(); // only serialize when file version is past VER_UE4_SERIALIZE_TEXT_IN_PACKAGES GatherableTextDataCount = reader.ReadInt32(); GatherableTextDataOffset = reader.ReadInt32(); ExportCount = reader.ReadInt32(); ExportOffset = reader.ReadInt32(); ImportCount = reader.ReadInt32(); ImportOffset = reader.ReadInt32(); DependsOffset = reader.ReadInt32(); // only serialize when file version is past VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP SoftPackageReferencesCount = reader.ReadInt32(); SoftPackageReferencesOffset = reader.ReadInt32(); // only serialize when file version is past VER_UE4_ADDED_SEARCHABLE_NAMES SearchableNamesOffset = reader.ReadInt32(); ThumbnailTableOffset = reader.ReadInt32(); Guid = new FGuid(reader); { var GenerationCount = reader.ReadInt32(); if (GenerationCount > 0) { Generations = new FGenerationInfo[GenerationCount]; for (int i = 0; i < Generations.Length; i++) { Generations[i] = new FGenerationInfo(reader); } } else { Generations = null; } } // only serialize when file version is past VER_UE4_ENGINE_VERSION_OBJECT SavedByEngineVersion = new FEngineVersion(reader); // only serialize when file version is past VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION CompatibleWithEngineVersion = new FEngineVersion(reader); CompressionFlags = (ECompressionFlags)reader.ReadUInt32(); if (CompressionFlags != ECompressionFlags.COMPRESS_None) // No support for deprecated compression { throw new FileLoadException($"Incompatible compression flags ({(uint)CompressionFlags})"); } if (reader.ReadTArray(() => new FCompressedChunk(reader)).Length != 0) // "CompressedChunks" { throw new FileLoadException("Package level compression is enabled"); } PackageSource = reader.ReadUInt32(); reader.ReadTArray(() => reader.ReadFString()); // "AdditionalPackagesToCook" if (LegacyFileVersion > -7) { // We haven't used texture allocation info for ages and it's no longer supported anyway if (reader.ReadInt32() != 0) // "NumTextureAllocations" { throw new FileLoadException("Can't load legacy UE3 file"); } } AssetRegistryDataOffset = reader.ReadInt32(); BulkDataStartOffset = reader.ReadInt64(); // only serialize when file version is past VER_UE4_WORLD_LEVEL_INFO WorldTileInfoDataOffset = reader.ReadInt32(); // only serialize when file version is past VER_UE4_CHANGED_CHUNKID_TO_BE_AN_ARRAY_OF_CHUNKIDS ChunkIDs = reader.ReadTArray(() => reader.ReadInt32()); // only serialize when file version is past VER_UE4_PRELOAD_DEPENDENCIES_IN_COOKED_EXPORTS PreloadDependencyCount = reader.ReadInt32(); PreloadDependencyOffset = reader.ReadInt32(); }
internal FPackageFileSummary(FAssetArchive Ar) { Tag = Ar.Read <uint>(); if (Tag == PACKAGE_FILE_TAG_ONE) // SOD2, "one" { Ar.Game = EGame.GAME_SOD2; Ar.Ver = Ar.Game.GetVersion(); var legacyFileVersion = Ar.Read <int>(); // seems to be always int.MinValue bUnversioned = true; FileVersionUE4 = (EUnrealEngineObjectUE4Version)Ar.Ver; CustomVersionContainer = Array.Empty <FCustomVersion>(); FolderName = "None"; PackageFlags = EPackageFlags.PKG_FilterEditorOnly; goto afterPackageFlags; } if (Tag != PACKAGE_FILE_TAG && Tag != PACKAGE_FILE_TAG_SWAPPED) { throw new ParserException($"Invalid uasset magic: 0x{Tag:X8} != 0x{PACKAGE_FILE_TAG:X8}"); } // The package has been stored in a separate endianness than the linker expected so we need to force // endian conversion. Latent handling allows the PC version to retrieve information about cooked packages. if (Tag == PACKAGE_FILE_TAG_SWAPPED) { // Set proper tag. //Tag = PACKAGE_FILE_TAG; // Toggle forced byte swapping. throw new ParserException("Byte swapping for packages not supported"); } /* * The package file version number when this package was saved. * * Lower 16 bits stores the UE3 engine version * Upper 16 bits stores the UE4/licensee version * For newer packages this is -7 * -2 indicates presence of enum-based custom versions * -3 indicates guid-based custom versions * -4 indicates removal of the UE3 version. Packages saved with this ID cannot be loaded in older engine versions * -5 indicates the replacement of writing out the "UE3 version" so older versions of engine can gracefully fail to open newer packages * -6 indicates optimizations to how custom versions are being serialized * -7 indicates the texture allocation info has been removed from the summary */ const int CurrentLegacyFileVersion = -7; LegacyFileVersion = Ar.Read <int>(); if (LegacyFileVersion < 0) // means we have modern version numbers { if (LegacyFileVersion < CurrentLegacyFileVersion) { // we can't safely load more than this because the legacy version code differs in ways we can not predict. // Make sure that the linker will fail to load with it. throw new ParserException("Can't load legacy UE3 file"); } LegacyUE3Version = LegacyFileVersion != -4 ? Ar.Read <LegacyUE3Version>() : 0; FileVersionUE4 = Ar.Read <EUnrealEngineObjectUE4Version>(); FileVersionLicenseUE4 = Ar.Read <EUnrealEngineObjectLicenseeUE4Version>(); CustomVersionContainer = LegacyFileVersion <= -2 ? Ar.ReadArray <FCustomVersion>() : Array.Empty <FCustomVersion>(); if (Ar.Versions.CustomVersions == null && CustomVersionContainer.Length > 0) { Ar.Versions.CustomVersions = CustomVersionContainer.ToList(); } if (FileVersionUE4 == 0 && FileVersionLicenseUE4 == 0) { // this file is unversioned, remember that, then use current versions bUnversioned = true; // set the versions to latest here, etc. FileVersionUE4 = (EUnrealEngineObjectUE4Version)Ar.Ver; FileVersionLicenseUE4 = EUnrealEngineObjectLicenseeUE4Version.VER_LIC_AUTOMATIC_VERSION; } else { bUnversioned = false; // Only apply the version if an explicit version is not set if (Ar.Ver == UE4Version.VER_UE4_DETERMINE_BY_GAME) { Ar.Ver = (UE4Version)FileVersionUE4; } } } else { // This is probably an old UE3 file, make sure that the linker will fail to load with it. throw new ParserException("Can't load legacy UE3 file"); } TotalHeaderSize = Ar.Read <int>(); FolderName = Ar.ReadFString(); PackageFlags = Ar.Read <EPackageFlags>(); afterPackageFlags: NameCount = Ar.Read <int>(); NameOffset = Ar.Read <int>(); LocalizationId = !PackageFlags.HasFlag(EPackageFlags.PKG_FilterEditorOnly) && FileVersionUE4 >= VER_UE4_ADDED_PACKAGE_SUMMARY_LOCALIZATION_ID?Ar.ReadFString() : null; if (FileVersionUE4 >= VER_UE4_SERIALIZE_TEXT_IN_PACKAGES) { GatherableTextDataCount = Ar.Read <int>(); GatherableTextDataOffset = Ar.Read <int>(); } else { GatherableTextDataCount = GatherableTextDataOffset = 0; } ExportCount = Ar.Read <int>(); ExportOffset = Ar.Read <int>(); ImportCount = Ar.Read <int>(); ImportOffset = Ar.Read <int>(); DependsOffset = Ar.Read <int>(); if (FileVersionUE4 is < VER_UE4_OLDEST_LOADABLE_PACKAGE or > VER_UE4_AUTOMATIC_VERSION) { SoftPackageReferencesCount = 0; SoftPackageReferencesOffset = 0; SearchableNamesOffset = 0; ThumbnailTableOffset = 0; Guid = default; Generations = Array.Empty <FGenerationInfo>(); SavedByEngineVersion = default; CompatibleWithEngineVersion = default; CompressionFlags = COMPRESS_None; PackageSource = 0; AssetRegistryDataOffset = 0; WorldTileInfoDataOffset = 0; ChunkIds = Array.Empty <int>(); AdditionalPackagesToCook = Array.Empty <string>(); CompressedChunks = Array.Empty <FCompressedChunk>(); PreloadDependencyCount = 0; PreloadDependencyOffset = 0; return; // we can't safely load more than this because the below was different in older files. } if (FileVersionUE4 >= VER_UE4_ADD_STRING_ASSET_REFERENCES_MAP) { SoftPackageReferencesCount = Ar.Read <int>(); SoftPackageReferencesOffset = Ar.Read <int>(); } else { SoftPackageReferencesCount = SoftPackageReferencesOffset = 0; } SearchableNamesOffset = FileVersionUE4 >= VER_UE4_ADDED_SEARCHABLE_NAMES?Ar.Read <int>() : 0; ThumbnailTableOffset = Ar.Read <int>(); if (Ar.Game == EGame.GAME_VALORANT) { Ar.Position += 8; } Guid = Ar.Read <FGuid>(); Generations = Ar.ReadArray <FGenerationInfo>(); if (FileVersionUE4 >= VER_UE4_ENGINE_VERSION_OBJECT) { SavedByEngineVersion = new FEngineVersion(Ar); if (FileVersionUE4 < VER_UE4_CORRECT_LICENSEE_FLAG && SavedByEngineVersion.Major == 4 && SavedByEngineVersion.Minor == 26 && SavedByEngineVersion.Patch == 0 && SavedByEngineVersion.Changelist >= 12740027 && SavedByEngineVersion.IsLicenseeVersion()) { SavedByEngineVersion.Set(4, 26, 0, SavedByEngineVersion.Changelist, SavedByEngineVersion.Branch); } } else { var engineChangelist = Ar.Read <int>(); SavedByEngineVersion = engineChangelist == 0 ? null : new FEngineVersion(4, 0, 0, (uint)engineChangelist, string.Empty); } CompatibleWithEngineVersion = FileVersionUE4 >= VER_UE4_PACKAGE_SUMMARY_HAS_COMPATIBLE_ENGINE_VERSION ? new FEngineVersion(Ar) : SavedByEngineVersion;