/// <param name="filePath">Path to Content.ggpk</param> public GGPK(string filePath) { // Open File FileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); // Read ROOT Directory Record BaseRecord ggpk; while ((ggpk = ReadRecord()) is not GGPKRecord) { ; } GgpkRecord = (GGPKRecord)ggpk; Root = (DirectoryRecord)ReadRecord(GgpkRecord.RootDirectoryOffset); Root.Name = "ROOT"; // Build Linked FreeRecord List FreeRecords = new(); var NextFreeOffset = GgpkRecord.FirstFreeRecordOffset; while (NextFreeOffset > 0) { var current = (FreeRecord)ReadRecord(NextFreeOffset); FreeRecords.AddLast(current); NextFreeOffset = current.NextFreeOffset; } }
/// <summary> /// Load GGPK /// </summary> /// <param name="path">Path to GGPK file</param> public GGPKContainer(string path, bool BundleMode = false) { // Open File fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); Reader = new BinaryReader(fileStream); Writer = new BinaryWriter(fileStream); // Read ROOT Directory Record BaseRecord ggpk; while (!((ggpk = GetRecord()) is GGPKRecord)) { ; } ggpkRecord = ggpk as GGPKRecord; rootDirectory = GetRecord(ggpkRecord.RootDirectoryOffset) as DirectoryRecord; rootDirectory.Name = "ROOT"; // Build Linked FreeRecord List long NextFreeOffset = ggpkRecord.FirstFreeRecordOffset; while (NextFreeOffset > 0) { FreeRecord current = GetRecord(NextFreeOffset) as FreeRecord; LinkedFreeRecords.AddLast(current); NextFreeOffset = current.NextFreeOffset; } if (BundleMode) { return; } // Read Bundles var Bundles2DirectoryNameHash = MurmurHash2Unsafe.Hash("bundles2", 0); OriginalBundles2 = rootDirectory.Children.First(d => d.GetNameHash() == Bundles2DirectoryNameHash) as DirectoryRecord; if (OriginalBundles2.Children.FirstOrDefault(r => r.Name == "_.index.bin") is FileRecord _index) { IndexRecord = _index; fileStream.Seek(_index.DataBegin, SeekOrigin.Begin); Index = new IndexContainer(Reader); FakeBundles2 = new BundleDirectoryNode("Bundles2", "", MurmurHash2Unsafe.Hash("bundles2", 0), (int)OriginalBundles2.Offset, OriginalBundles2.Length, this); rootDirectory.Children.Remove(OriginalBundles2); rootDirectory.Children.Add(FakeBundles2); foreach (var f in Index.Files) { BuildBundleTree(f, FakeBundles2); } } foreach (var br in Index.Bundles) { RecordOfBundle[br] = (FileRecord)FindRecord(br.Name, OriginalBundles2); } }
/// <summary> /// Load GGPK /// </summary> /// <param name="path">Path to GGPK file</param> public GGPKContainer(string path, bool BundleMode = false, bool SteamMode = false, bool BuildTree = true) { // Steam Mode (No GGPK) if (SteamMode) { if (BundleMode) { throw new NotSupportedException("BundleMode and SteamMode cannot be both true"); } Environment.CurrentDirectory = Directory.GetParent(path).FullName; Index = new IndexContainer(path); if (BuildTree) { rootDirectory = FakeBundles2 = new BundleDirectoryNode("Bundles2", "", MurmurHash2Unsafe.Hash("bundles2", 0), 0, 0, this); foreach (var f in Index.Files) { BuildBundleTree(f, rootDirectory); } } return; } // Open File fileStream = File.Open(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); Reader = new BinaryReader(fileStream); Writer = new BinaryWriter(fileStream); // Read ROOT Directory Record BaseRecord ggpk; while ((ggpk = GetRecord()) is not GGPKRecord) { ; } ggpkRecord = ggpk as GGPKRecord; rootDirectory = GetRecord(ggpkRecord.RootDirectoryOffset) as DirectoryRecord; rootDirectory.Name = "ROOT"; // Build Linked FreeRecord List LinkedFreeRecords = new LinkedList <FreeRecord>(); var NextFreeOffset = ggpkRecord.FirstFreeRecordOffset; while (NextFreeOffset > 0) { FreeRecord current = GetRecord(NextFreeOffset) as FreeRecord; LinkedFreeRecords.AddLast(current); NextFreeOffset = current.NextFreeOffset; } // Read Bundles OriginalBundles2 = rootDirectory.Children.FirstOrDefault(d => d.GetNameHash() == MurmurHash2Unsafe.Hash("bundles2", 0)) as DirectoryRecord; if (OriginalBundles2?.Children.FirstOrDefault(r => r.Name == "_.index.bin") is FileRecord _index) { IndexRecord = _index; if (BundleMode) { return; } fileStream.Seek(_index.DataBegin, SeekOrigin.Begin); Index = new IndexContainer(Reader); if (BuildTree) { FakeBundles2 = new BundleDirectoryNode("Bundles2", "", MurmurHash2Unsafe.Hash("bundles2", 0), (int)OriginalBundles2.Offset, OriginalBundles2.Length, this); rootDirectory.Children.Remove(OriginalBundles2); rootDirectory.Children.Add(FakeBundles2); foreach (var f in Index.Files) { BuildBundleTree(f, FakeBundles2); } } _RecordOfBundle = new Dictionary <LibBundle.Records.BundleRecord, FileRecord>(Index.Bundles.Length); } // else BundleMode = true; }