예제 #1
0
        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();
        }
예제 #2
0
        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;