public void UnpackFromKey(FileEntryKey entryKey) { string entryPath = _volume.GetEntryPath(entryKey, ParentDirectory); if (string.IsNullOrEmpty(entryPath)) { Program.Log($"Could not determine entry path for Entry key at name Index {entryKey.NameIndex}"); return; } string fullEntryPath = Path.Combine(OutDir ?? string.Empty, entryPath); if (entryKey.Flags.HasFlag(EntryKeyFlags.Directory)) { if (_fileIndexesToExtract.Count == 0) // Make sure not to spam when not needed { if (!_volume.IsPatchVolume || _volume.NoUnpack) { Program.Log($"[:] Entering Directory: {entryPath}"); } } var childEntryBTree = new FileEntryBTree(_volume.TableOfContents.Data, (int)_volume.TableOfContents.RootAndFolderOffsets[(int)entryKey.EntryIndex]); var childUnpacker = new EntryUnpacker(_volume, OutDir, entryPath, _fileIndexesToExtract); childEntryBTree.TraverseAndUnpack(childUnpacker); } else { if (_fileIndexesToExtract.Count != 0 && !_fileIndexesToExtract.Contains((int)entryKey.EntryIndex)) { return; } if (!_volume.IsPatchVolume || _volume.NoUnpack) { Program.Log($"[:] Extracting: {entryPath}"); } var nodeBTree = new FileInfoBTree(_volume.TableOfContents.Data, (int)_volume.TableOfContents.NodeTreeOffset); var nodeKey = new FileInfoKey(entryKey.EntryIndex); uint nodeIndex = nodeBTree.SearchIndexByKey(nodeKey); if (nodeIndex != FileInfoKey.InvalidIndex) { _volume.UnpackNode(nodeKey, fullEntryPath); } } }
/// <summary> /// Loads the table of contents from the underlaying stream. /// </summary> /// <returns></returns> public bool LoadTOC() { var sr = new SpanReader(Data, Endian.Big); byte[] magic = sr.ReadBytes(4); if (!magic.AsSpan().SequenceEqual(SEGMENT_MAGIC.AsSpan())) { Program.Log($"Volume TOC magic did not match, found ({string.Join('-', magic.Select(e => e.ToString("X2")))})"); return(false); } NameTreeOffset = sr.ReadUInt32(); FileExtensionTreeOffset = sr.ReadUInt32(); NodeTreeOffset = sr.ReadUInt32(); uint entryTreeCount = sr.ReadUInt32(); RootAndFolderOffsets = new List <uint>((int)entryTreeCount); for (int i = 0; i < entryTreeCount; i++) { RootAndFolderOffsets.Add(sr.ReadUInt32()); } FileNames = new StringBTree(Data, (int)NameTreeOffset); FileNames.LoadEntries(); Extensions = new StringBTree(Data, (int)FileExtensionTreeOffset); Extensions.LoadEntries(); FileInfos = new FileInfoBTree(Data, (int)NodeTreeOffset); FileInfos.LoadEntries(); Files = new List <FileEntryBTree>((int)entryTreeCount); for (int i = 0; i < entryTreeCount; i++) { Files.Add(new FileEntryBTree(Data, (int)RootAndFolderOffsets[i])); Files[i].LoadEntries(); } return(true); }