Esempio n. 1
0
        public FIoStoreTocResource(Stream tocStream, EIoStoreTocReadOptions readOptions = EIoStoreTocReadOptions.Default)
        {
            var streamBuffer = new byte[tocStream.Length];

            tocStream.Read(streamBuffer, 0, streamBuffer.Length);
            using var reader           = new BinaryReader(new MemoryStream(streamBuffer));
            Header                     = new FIoStoreTocHeader(reader);
            reader.BaseStream.Position = Header.TocHeaderSize;

            var totalTocSize   = tocStream.Length - Header.TocHeaderSize;
            var tocMetaSize    = Header.TocEntryCount * FIoStoreTocEntryMeta.SIZE;
            var defaultTocSize = totalTocSize - Header.DirectoryIndexSize - tocMetaSize;

            var tocSize = defaultTocSize;

            if (readOptions.HasAnyFlags(EIoStoreTocReadOptions.ReadTocMeta))
            {
                tocSize = totalTocSize; // Meta data is at the end of the TOC file
            }

            if (readOptions.HasAnyFlags(EIoStoreTocReadOptions.ReadDirectoryIndex))
            {
                tocSize = defaultTocSize + Header.DirectoryIndexSize;
            }

            // Chunk IDs
            ChunkIds = new FIoChunkId[Header.TocEntryCount];
            for (var i = 0; i < Header.TocEntryCount; i++)
            {
                ChunkIds[i] = new FIoChunkId(reader);
            }

            // Chunk offsets
            ChunkOffsetLengths = new FIoOffsetAndLength[Header.TocEntryCount];
            for (var i = 0; i < Header.TocEntryCount; i++)
            {
                ChunkOffsetLengths[i] = new FIoOffsetAndLength(reader);
            }

            // Compression blocks
            CompressionBlocks = new FIoStoreTocCompressedBlockEntry[Header.TocCompressedBlockEntryCount];
            for (var i = 0; i < Header.TocCompressedBlockEntryCount; i++)
            {
                CompressionBlocks[i] = new FIoStoreTocCompressedBlockEntry(reader);
            }

            // Compression methods
            CompressionMethods = new string[Header.CompressionMethodNameCount]; // Not doing +1 nor adding CompressionMethod none here since the FPakInfo implementation doesn't as well
            for (var i = 0; i < Header.CompressionMethodNameCount; i++)
            {
                CompressionMethods[i] = Encoding.ASCII.GetString(reader.ReadBytes((int)Header.CompressionMethodNameLength)).TrimEnd('\0');
            }

            // Chunk block signatures
            if (Header.ContainerFlags.HasAnyFlags(EIoContainerFlags.Signed))
            {
                var hashSize = reader.ReadInt32();
                reader.BaseStream.Position += hashSize; // actually: var tocSignature = reader.ReadBytes(hashSize);
                reader.BaseStream.Position += hashSize; // actually: var blockSignature = reader.ReadBytes(hashSize);

                ChunkBlockSignatures = new FSHAHash[Header.TocCompressedBlockEntryCount];
                for (var i = 0; i < Header.TocCompressedBlockEntryCount; i++)
                {
                    ChunkBlockSignatures[i] = new FSHAHash(reader);
                }

                // You could verify hashes here but nah
            }

            // Directory index
            if (Header.Version >= EIoStoreTocVersion.DirectoryIndex &&
                readOptions.HasAnyFlags(EIoStoreTocReadOptions.ReadDirectoryIndex) &&
                Header.ContainerFlags.HasAnyFlags(EIoContainerFlags.Indexed) &&
                Header.DirectoryIndexSize > 0)
            {
                DirectoryIndexBuffer = reader.ReadBytes((int)Header.DirectoryIndexSize);
            }

            // Meta
            if (readOptions.HasAnyFlags(EIoStoreTocReadOptions.ReadTocMeta))
            {
                ChunkMetas = new FIoStoreTocEntryMeta[Header.TocEntryCount];
                for (var i = 0; i < Header.TocEntryCount; i++)
                {
                    ChunkMetas[i] = new FIoStoreTocEntryMeta(reader);
                }
            }
        }
Esempio n. 2
0
        public FIoGlobalData(FFileIoStoreReader globalReader, IReadOnlyCollection <FFileIoStoreReader> allReaders)
        {
            var globalNamesIoBuffer      = globalReader.Read(new FIoChunkId(0, 0, EIoChunkType.LoaderGlobalNames));
            var globalNameHashesIoBuffer = globalReader.Read(new FIoChunkId(0, 0, EIoChunkType.LoaderGlobalNameHashes));
            var globalNameMap            = new List <FNameEntrySerialized>();

            GlobalNameHashes = new List <ulong>();
            FNameEntrySerialized.LoadNameBatch(globalNameMap, GlobalNameHashes, globalNamesIoBuffer, globalNameHashesIoBuffer);
            GlobalNameMap = globalNameMap.ToArray();

            var initialLoadIoBuffer = globalReader.Read(new FIoChunkId(0, 0, EIoChunkType.LoaderInitialLoadMeta));
            var initialLoadIoReader = new BinaryReader(new MemoryStream(initialLoadIoBuffer, false));
            var numScriptObjects    = initialLoadIoReader.ReadInt32();

            var scriptObjectByGlobalIdKeys   = new FPackageObjectIndex[numScriptObjects];
            var scriptObjectByGlobalIdValues = new FScriptObjectDesc[numScriptObjects];
            var globalIndices = new Dictionary <FPackageObjectIndex, int>(numScriptObjects);

            for (var i = 0; i < numScriptObjects; i++)
            {
                var scriptObjectEntry = new FScriptObjectEntry(initialLoadIoReader);
                globalIndices.TryAdd(scriptObjectEntry.GlobalIndex, i);
                var mappedName = new FMappedName(scriptObjectEntry.ObjectName, GlobalNameMap, null);

                if (!mappedName.IsGlobal())
                {
                    Debug.WriteLine(i);
                }

                scriptObjectByGlobalIdKeys[i]   = scriptObjectEntry.GlobalIndex;
                scriptObjectByGlobalIdValues[i] = new FScriptObjectDesc(GlobalNameMap[(int)mappedName.GetIndex()], mappedName, scriptObjectEntry);
            }

            for (var i = 0; i < numScriptObjects; i++)
            {
                var scriptObjectDesc = scriptObjectByGlobalIdValues[i];

                if (!scriptObjectDesc.FullName.IsNone)
                {
                    continue;
                }

                var    scriptObjectStack = new Stack <FScriptObjectDesc>();
                var    current           = i;
                string fullName          = string.Empty;

                while (current > 0)
                {
                    var currentDesc = scriptObjectByGlobalIdValues[current];

                    if (!currentDesc.FullName.IsNone)
                    {
                        fullName = currentDesc.FullName.String;
                        break;
                    }

                    scriptObjectStack.Push(currentDesc);
                    globalIndices.TryGetValue(currentDesc.OuterIndex, out current);
                }

                while (scriptObjectStack.Count != 0)
                {
                    var currentStack = scriptObjectStack.Pop();

                    if (fullName.Length == 0 || fullName.EndsWith('/'))
                    {
                        fullName = string.Concat(fullName, currentStack.Name.String);
                    }
                    else
                    {
                        fullName = string.Concat(fullName, "/", currentStack.Name.String);
                    }

                    currentStack.FullName = new FName(fullName);
                }
            }

            ScriptObjectByGlobalId = Enumerable.Range(0, numScriptObjects).ToDictionary(i => scriptObjectByGlobalIdKeys[i], i => scriptObjectByGlobalIdValues[i]);

            var packageByPackageIdMap = new Dictionary <FPackageId, FPackageStoreEntry>();

            foreach (var reader in allReaders)
            {
                var headerChunkId = new FIoChunkId(reader.ContainerId.Id, 0, EIoChunkType.ContainerHeader);
                if (reader.DoesChunkExist(headerChunkId) && !reader.IsEncrypted)
                {
                    var buffer = reader.Read(headerChunkId);
                    using var headerReader = new BinaryReader(new MemoryStream(buffer, false));

                    var containerHeader = new FContainerHeader(headerReader);

                    using var storeEntryReader = new BinaryReader(new MemoryStream(containerHeader.StoreEntries));

                    var containerPackages = new List <FPackageDesc>();

                    for (var i = 0; i < containerHeader.PackageCount; i++)
                    {
                        var containerEntry = new FPackageStoreEntry(storeEntryReader);

                        var packageId = containerHeader.PackageIds[i];
                        if (!packageByPackageIdMap.TryGetValue(packageId, out var packageDesc))
                        {
                            /*
                             * packageDesc = new FPackageDesc();
                             * packageDesc.PackageId = packageId;
                             * packageDesc.Size = containerEntry.ExportBundlesSize;
                             * packageDesc.Exports = new FExportDesc[containerEntry.ExportCount];
                             * packageDesc.ExportBundleCount = containerEntry.ExportBundleCount;
                             * packageDesc.LoadOrder = containerEntry.LoadOrder;
                             */
                            packageByPackageIdMap[packageId] = containerEntry;
                        }
                        //containerPackages.Add(packageDesc);
                    }
                }
            }
        }