private GgpkDirectory GetRootDirectory() { RecordHeader ggpkHeader; do { ggpkHeader = Stream.ReadRecordHeader(); } while (ggpkHeader.Type != RecordType.Ggpk); var ggpk = new GgpkRecord(Stream, ggpkHeader.Length); DirectoryRecord?dirRecord = default; foreach (var offset in ggpk.RecordOffsets) { Stream.Position = offset; RecordHeader header = Stream.ReadRecordHeader(); if (header.Type == RecordType.Directory) { dirRecord = new DirectoryRecord(Stream, header.Length); break; } } return(dirRecord switch { not null => GgpkDirectory.CreateRootDirectory(dirRecord, this), _ => throw ParseException.GgpkParseFailure, });
public void Save(string pathToGgpkNew, Action <string> output) { if (output != null) { output("Saving GGPK..." + Environment.NewLine); } FileStream readStream; FileStream writeStream; using (readStream = File.OpenRead(_pathToGppk)) using (writeStream = File.OpenWrite(pathToGgpkNew)) { var reader = new BinaryReader(readStream); var writer = new BinaryWriter(writeStream); var ggpkRecord = RecordOffsets[0] as GgpkRecord; if (ggpkRecord == null) { throw new Exception("First record isn't GGPK record"); } // Skip GGPK record for now writer.Seek((int)ggpkRecord.Length, SeekOrigin.Begin); // recursively write files and folders records var changedOffsets = new Dictionary <long, long>(); var previousPercentComplete = 0.0; var fileCopied = 0.0; DirectoryTreeNode.TraverseTreePostorder( DirectoryRoot, dir => dir.Record.Write(writer, changedOffsets), file => { var data = file.ReadFileContent(reader); file.Write(writer, changedOffsets); writer.Write(data); fileCopied++; var percentComplete = fileCopied / _files.Count; if (!(percentComplete - previousPercentComplete >= 0.05f)) { return; } if (output != null) { output(String.Format(" {0:00.00}%", 100.0 * percentComplete)); } previousPercentComplete = percentComplete; }); if (output != null) { output(" 100%"); } // write root directory var rootDirectoryOffset = writer.BaseStream.Position; DirectoryRoot.Record.Write(writer, changedOffsets); // write single Free record var firstFreeRecordOffset = writer.BaseStream.Position; var freeRecord = new FreeRecord(16, firstFreeRecordOffset, 0); freeRecord.Write(writer, null); // write GGPK record writer.Seek(0, SeekOrigin.Begin); var ggpkRecordNew = new GgpkRecord(ggpkRecord.Length); ggpkRecordNew.RecordOffsets[0] = rootDirectoryOffset; ggpkRecordNew.RecordOffsets[1] = firstFreeRecordOffset; ggpkRecordNew.Write(writer, changedOffsets); if (output != null) { output("Finished !!!"); } } }
public void SerializeRecords(string pathToBin, Action <string> output) { if (output != null) { output(Environment.NewLine); output("Serializing... "); } var Serialized = File.Create(pathToBin); var s = new BinaryWriter(Serialized); foreach (var record in RecordOffsets) { s.Write(record.Key); var baseRecord = record.Value; if (baseRecord is FileRecord) { s.Write((byte)1); FileRecord fr = (FileRecord)baseRecord; s.Write(fr.RecordBegin); s.Write(fr.Length); s.Write(fr.Hash); s.Write(fr.Name); s.Write(fr.DataBegin); s.Write(fr.DataLength); } else if (baseRecord is GgpkRecord) { s.Write((byte)2); GgpkRecord gr = (GgpkRecord)baseRecord; s.Write(gr.RecordBegin); s.Write(gr.Length); s.Write(gr.RecordOffsets.Length); foreach (long l in gr.RecordOffsets) { s.Write(l); } } else if (baseRecord is FreeRecord) { s.Write((byte)3); FreeRecord fr = (FreeRecord)baseRecord; s.Write(fr.RecordBegin); s.Write(fr.Length); s.Write(fr.NextFreeOffset); } else if (baseRecord is DirectoryRecord) { s.Write((byte)4); DirectoryRecord dr = (DirectoryRecord)baseRecord; s.Write(dr.RecordBegin); s.Write(dr.Length); s.Write(dr.Hash); s.Write(dr.Name); s.Write(dr.EntriesBegin); s.Write(dr.Entries.Count); foreach (var directoryEntry in dr.Entries) { s.Write(directoryEntry.EntryNameHash); s.Write(directoryEntry.Offset); } } } Serialized.Flush(); Serialized.Close(); output?.Invoke("Done!" + Environment.NewLine); }