コード例 #1
0
ファイル: SaveFile.cs プロジェクト: watzlawek/CyberCAT
 private void FindChildren(List <NodeEntry> nodes, NodeEntry node, int maxNextId)
 {
     if (node.ChildId > -1)
     {
         var nextId = node.NextId;
         if (nextId == -1)
         {
             nextId = maxNextId;
         }
         for (int i = node.ChildId; i < nextId; i++)
         {
             var possibleChild = nodes.FirstOrDefault(n => n.Id == i);
             if (possibleChild == null)
             {
                 throw new Exception();
             }
             if (possibleChild.ChildId > -1)//SubChild
             {
                 FindChildren(nodes, possibleChild, nextId);
                 node.AddChild(possibleChild);
             }
             else
             {
                 if (!possibleChild.IsChild)//was already added
                 {
                     node.AddChild(possibleChild);
                 }
             }
         }
     }
 }
コード例 #2
0
ファイル: SaveFile.cs プロジェクト: watzlawek/CyberCAT
        private void ReadNodeInfos(BinaryReader reader)
        {
            var magicStartInt = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(Constants.Magic.NODE_INFORMATION_START), 0);
            var magicEndInt   = BitConverter.ToUInt32(Encoding.ASCII.GetBytes(Constants.Magic.END_OF_FILE), 0);

            reader.BaseStream.Seek(-8, SeekOrigin.End);
            var infoStart = reader.ReadInt32();

            if (reader.ReadUInt32() != magicEndInt)
            {
                throw new Exception("invalid file format");
            }

            reader.BaseStream.Seek(infoStart, SeekOrigin.Begin);
            if (reader.ReadUInt32() != magicStartInt)
            {
                throw new Exception("invalid file format");
            }

            var length = reader.ReadPackedInt();

            for (var i = 0; i < length; i++)
            {
                var name  = reader.ReadPackedString();
                var entry = new NodeEntry();
                entry.NextId  = reader.ReadInt32();
                entry.ChildId = reader.ReadInt32();
                entry.Offset  = reader.ReadInt32();
                entry.Size    = reader.ReadInt32();
                entry.Name    = name;
                FlatNodes.Add(entry);
            }

            reader.BaseStream.Position = 0;
        }
コード例 #3
0
        public void LoadFromCompressedStream(Stream inputStream)
        {
            FlatNodes.Clear();
            Nodes.Clear();
            using (var reader = new BinaryReader(inputStream, Encoding.ASCII, true))
            {
                string magic = reader.ReadString(4);
                Version1           = reader.ReadInt32();
                Version2           = reader.ReadInt32();
                SkippedHeaderBytes = reader.ReadBytes(9);
                Version3           = reader.ReadInt32();
                int blockInfoStart = (int)reader.BaseStream.Position;
                reader.BaseStream.Seek(-8, SeekOrigin.End);
                LastBlockOffset = reader.ReadInt32();
                reader.BaseStream.Seek(LastBlockOffset, SeekOrigin.Begin);
                string edonMagic = reader.ReadString(4);
                var    flags     = new Flags(reader);
                for (int i = 0; i < flags.Length; i++)
                {
                    var    tmpFlags = new Flags(reader.ReadByte());
                    string name     = reader.ReadString(tmpFlags.Length);
                    var    entry    = new NodeEntry();
                    entry.NextId  = reader.ReadInt32();
                    entry.ChildId = reader.ReadInt32();
                    entry.Offset  = reader.ReadInt32();
                    entry.Size    = reader.ReadInt32();
                    entry.Name    = name;
                    FlatNodes.Add(entry);
                }
            }
            inputStream.Seek(0, SeekOrigin.Begin);
            var activeSaveFile   = new SaveFileCompressionHelper();
            var decompressedFile = activeSaveFile.Decompress(inputStream);

            using (MemoryStream memoryStream = new MemoryStream(decompressedFile))
            {
                using (BinaryReader reader = new BinaryReader(memoryStream, Encoding.ASCII))
                {
                    foreach (var node in FlatNodes)
                    {
                        reader.BaseStream.Position = node.Offset;
                        node.Id = reader.ReadInt32();
                    }
                    foreach (var node in FlatNodes)
                    {
                        if (!node.IsChild)
                        {
                            FindChildren(FlatNodes, node, FlatNodes.Count);
                        }
                        if (node.NextId > -1)
                        {
                            node.SetNextNode(FlatNodes.Where(n => n.Id == node.NextId).FirstOrDefault());
                        }
                    }
                    Nodes.AddRange(FlatNodes.Where(n => !n.IsChild));
                    CalculateTrueSizes();
                    ParserUtils.ParseChildren(Nodes, reader, _parsers);
                }
            }
        }
コード例 #4
0
 public void AddChild(NodeEntry child)
 {
     child.IsChild = true;
     if (Children.Count == 0)
     {
         child.IsFirstChild = true;
     }
     Children.Add(child);
     child.SetParent(this);
 }
コード例 #5
0
        public void Write(NodeEntry node)
        {
            var isChild  = _currentDepth > _lastDepth;
            var isNext   = _currentDepth == _lastDepth;
            var isParent = _currentDepth < _lastDepth;

            _lastDepth = _currentDepth;
            _currentDepth++;

            var currentId = _currentId++;
            var nodeInfo  = new SaveFile.NodeInfo
            {
                Name   = node.Name,
                Offset = (int)BaseStream.Position
            };

            if (isChild)
            {
                _nodeInfos[_nodeInfos.Count - 1].ChildId = currentId;
            }
            if (_nodeInfos.Count > 0 && isNext)
            {
                _nodeInfos[_nodeInfos.Count - 1].ChildId = -1;
                _nodeInfos[_nodeInfos.Count - 1].NextId  = currentId;
            }
            if (isParent)
            {
                _nodeInfos[_nodeInfos.Count - 1].ChildId = -1;
                _nodeInfos[_nodeInfos.Count - 1].NextId  = -1;
                var lastIdSameLevel = _nodeMetaInfos.LastOrDefault(n => n.Depth == _currentDepth).Id;
                _nodeInfos[lastIdSameLevel].NextId = currentId;
            }

            _nodeInfos.Add(nodeInfo);
            _nodeMetaInfos.Add(new NodeMeta(currentId, _currentDepth));

            var parser = GetParser(node);

            Write(currentId);
            parser.Write(this, node);

            nodeInfo.Size = (int)(BaseStream.Position - nodeInfo.Offset);
            if (node.WritesOwnTrailingSize)
            {
                nodeInfo.Size -= node.TrailingSize;
            }

            _currentDepth--;
        }
コード例 #6
0
ファイル: SaveFile.cs プロジェクト: watzlawek/CyberCAT
        private void CalculateTrueSizes(IReadOnlyList <NodeEntry> nodes, int maxLength)
        {
            for (var i = 0; i < nodes.Count; ++i)
            {
                var currentNode = nodes[i];
                var nextNode    = i + 1 < nodes.Count ? nodes[i + 1] : null;

                if (currentNode.Children.Count > 0)
                {
                    // Check if there is a blob before the first child
                    var nextChild = currentNode.Children.First();
                    var blobSize  = nextChild.Offset - currentNode.Offset;
                    currentNode.DataSize = blobSize;
                    CalculateTrueSizes(currentNode.Children, maxLength);
                }
                else
                {
                    currentNode.DataSize = currentNode.Size;
                }

                if (nextNode != null)
                {
                    // There is a node after us. Check if there is a blob in between
                    var blobSize = nextNode.Offset - (currentNode.Offset + currentNode.Size);
                    if (blobSize < 0)
                    {
                        throw new InvalidDataException("Found a datablob with negative size");
                    }
                    currentNode.TrailingSize = blobSize;
                }
                else
                {
                    // There might be a blob that is part of the children due to the parents size, check for that
                    if (currentNode.GetParent() == null)
                    {
                        // This is the last node on the root list. Trailing data should have been cought by the last inner child and assigned here but check again.
                        var lastNodeEnd = currentNode.Offset + currentNode.Size;
                        Debug.Assert(lastNodeEnd <= maxLength);
                        if (lastNodeEnd < maxLength)
                        {
                            // There is a trailing blob
                            currentNode.TrailingSize = maxLength - lastNodeEnd;
                        }

                        continue;
                    }
                    nextNode = currentNode.GetParent().GetNextNode();
                    if (nextNode == null)
                    {
                        // This is the last child on the last node. The next valid offset would be the end of the data
                        // Create a virtual node for this so the code below can grab the offset
                        nextNode        = new NodeEntry();
                        nextNode.Offset = maxLength;
                    }
                    var parentMax = currentNode.GetParent().Offset + currentNode.GetParent().Size;
                    var childMax  = currentNode.Offset + currentNode.Size;
                    // The parent size should never be smaller than the end of the last child.
                    Debug.Assert(parentMax >= childMax);
                    var blobSize = nextNode.Offset - (currentNode.Offset + currentNode.Size);
                    if (blobSize < 0)
                    {
                        throw new InvalidDataException("Found a datablob with negative size");
                    }
                    if (parentMax > childMax)
                    {
                        // Blob belongs to this child
                        currentNode.TrailingSize = blobSize;
                    }
                    else if (parentMax == childMax)
                    {
                        // Blob belongs to the parent but as trailing.
                        currentNode.GetParent().TrailingSize = blobSize;
                    }
                }
            }
        }
コード例 #7
0
 private INodeParser GetParser(NodeEntry node)
 {
     return(GetParser(node.Name));
 }
コード例 #8
0
 public void SetParent(NodeEntry parent)
 {
     _parent = parent;
 }
コード例 #9
0
 public void SetPreviousNode(NodeEntry previousNode)
 {
     _previousNode = previousNode;
 }
コード例 #10
0
 public void SetNextNode(NodeEntry nextNode)
 {
     _nextNode = nextNode;
     _nextNode.SetPreviousNode(this);
 }