Esempio n. 1
0
        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);
        }