コード例 #1
0
        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);
        }
コード例 #2
0
        public FreeRecord AddFromFileRecord(BinaryWriter bw, FileRecord fileRecord)
        {
            _lastDicKey = 0;

            var freeRecord = new FreeRecord(fileRecord.Length, fileRecord.RecordBegin, 0);

            Add(bw, freeRecord);

            return(freeRecord);
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
ファイル: FreeListMaker.cs プロジェクト: davidsiaw/LibGGPK
        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");
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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 !!!");
                    }
                }
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        public void Add(FreeRecord freeRecord)
        {
            var node = _freeRecordList.AddLast(freeRecord);

            AddNode(node);
        }
コード例 #9
0
        private void Write(BinaryWriter bw, FreeRecord freeRecord)
        {
            bw.BaseStream.Position = freeRecord.RecordBegin;

            freeRecord.Write(bw, null);
        }