public long AllocSpace(BinaryWriter bw, uint length) { long position = 0; var freeRecords = GetFreeRecordsByLength(length); if (freeRecords != null) { LinkedListNode <FreeRecord> oldFreeRecordNode = freeRecords[0]; var oldFreeRecord = oldFreeRecordNode.Value; position = oldFreeRecord.RecordBegin; if (oldFreeRecord.Length > length) { FreeRecord newFreeRecord = new FreeRecord( oldFreeRecord.Length - length, oldFreeRecord.RecordBegin + length, oldFreeRecord.NextFreeOffset); Add(bw, newFreeRecord, oldFreeRecordNode); } Remove(bw, oldFreeRecordNode); } return(position > 0 ? position : bw.BaseStream.Length); }
public FreeRecord AddFromFileRecord(BinaryWriter bw, FileRecord fileRecord) { _lastDicKey = 0; var freeRecord = new FreeRecord(fileRecord.Length, fileRecord.RecordBegin, 0); Add(bw, freeRecord); return(freeRecord); }
/// <summary> /// Builds a linked list of FREE records by traversing FREE records in GGPK file /// </summary> /// <param name="recordOffsets">Map of record offsets in GGPK file</param> /// <returns>Linked list containing list of FREE records</returns> internal static LinkedList <FreeRecord> BuildFreeList(Dictionary <long, BaseRecord> recordOffsets) { LinkedList <FreeRecord> freeList = new LinkedList <FreeRecord>(); // This offset is a directory, add it as a child of root and process all of it's entries GGPKRecord currentDirectory = recordOffsets[0] as GGPKRecord; FreeRecord currentFreeRecord = null; foreach (var item in currentDirectory.RecordOffsets) { if (recordOffsets[item] is FreeRecord) { currentFreeRecord = recordOffsets[item] as FreeRecord; break; } } if (currentFreeRecord == null) { throw new Exception("Failed to find FREE record root in GGPK header"); } while (true) { freeList.AddLast(currentFreeRecord); long nextFreeOFfset = currentFreeRecord.NextFreeOffset; if (nextFreeOFfset == 0) { break; } if (!recordOffsets.ContainsKey(nextFreeOFfset)) { throw new Exception("Failed to find next FREE record in map of record offsets"); } currentFreeRecord = recordOffsets[currentFreeRecord.NextFreeOffset] as FreeRecord; if (currentFreeRecord == null) { throw new Exception("Found a record that wasn't a FREE record while looking for next FREE record"); } } return(freeList); }
internal static LinkedList <FreeRecord> BuildFreeList(Dictionary <long, BaseRecord> recordOffsets) { LinkedList <FreeRecord> linkedList = new LinkedList <FreeRecord>(); GGPKRecord gGPKRecord = recordOffsets[0L] as GGPKRecord; FreeRecord freeRecord = null; long[] recordOffsets2 = gGPKRecord.RecordOffsets; for (int i = 0; i < recordOffsets2.Length; i++) { long key = recordOffsets2[i]; if (recordOffsets[key] is FreeRecord) { freeRecord = (recordOffsets[key] as FreeRecord); break; } } if (freeRecord == null) { throw new Exception("Failed to find FREE record root in GGPK header"); } while (true) { linkedList.AddLast(freeRecord); long nextFreeOffset = freeRecord.NextFreeOffset; if (nextFreeOffset == 0L) { return(linkedList); } if (!recordOffsets.ContainsKey(nextFreeOffset)) { break; } freeRecord = (recordOffsets[freeRecord.NextFreeOffset] as FreeRecord); if (freeRecord == null) { goto Block_5; } } throw new Exception("Failed to find next FREE record in map of record offsets"); Block_5: throw new Exception("Found a record that wasn't a FREE record while looking for next FREE record"); }
private void Add(BinaryWriter bw, FreeRecord freeRecord, LinkedListNode <FreeRecord> targetNode = null) { Write(bw, freeRecord); LinkedListNode <FreeRecord> node = null; if (targetNode == null) { node = _freeRecordList.AddLast(freeRecord); } else { node = _freeRecordList.AddAfter(targetNode, freeRecord); } if (node.Previous != null) { node.Previous.Value.NextFreeOffset = freeRecord.RecordBegin; Write(bw, node.Previous.Value); } AddNode(node); }
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); }
public void Add(FreeRecord freeRecord) { var node = _freeRecordList.AddLast(freeRecord); AddNode(node); }
private void Write(BinaryWriter bw, FreeRecord freeRecord) { bw.BaseStream.Position = freeRecord.RecordBegin; freeRecord.Write(bw, null); }