Esempio n. 1
0
        private int AssignOffsets(StringNode node, int offset, IDictionary <StringNode, int> nodeOffsetMap)
        {
            foreach (var internalNode in node.Nodes)
            {
                offset = AssignOffsets(internalNode, offset, nodeOffsetMap);

                if (!string.IsNullOrEmpty(node.Text))
                {
                    var sameNode = nodeOffsetMap.Keys.FirstOrDefault(x => x.Text == node.Text);
                    nodeOffsetMap[node] = sameNode != null ? nodeOffsetMap[sameNode] : offset;

                    if (sameNode == null)
                    {
                        offset += node.Text.Length + 1;
                    }
                }
            }

            if (!string.IsNullOrEmpty(node.Text))
            {
                var sameNode = nodeOffsetMap.Keys.FirstOrDefault(x => x.Text == node.Text);
                nodeOffsetMap[node] = sameNode != null ? nodeOffsetMap[sameNode] : offset;

                if (sameNode == null)
                {
                    offset += node.Text.Length + 1;
                }
            }

            return(offset);
        }
Esempio n. 2
0
        private void WriteNodes(StringNode node, BinaryWriterX bw, IDictionary <StringNode, int> nodeOffsetMap, ref int fileId)
        {
            bw.Write((short)node.Nodes.Count);

            var nextPosition = bw.BaseStream.Position + node.Nodes.Count * 4;

            foreach (var internalNode in node.Nodes)
            {
                var currentPosition = bw.BaseStream.Position;

                var isEnd = internalNode.Nodes.Count <= 0;
                var flags = isEnd ? (fileId++ << 1) | 1 : nextPosition << 1;

                if (internalNode.Nodes.Count > 0)
                {
                    bw.BaseStream.Position = nextPosition;
                    WriteNodes(internalNode, bw, nodeOffsetMap, ref fileId);

                    nextPosition = bw.BaseStream.Position;
                }

                if (currentPosition == 0x18C)
                {
                    Debugger.Break();
                }

                bw.BaseStream.Position = currentPosition;
                bw.Write((short)nodeOffsetMap[internalNode]);
                bw.Write((short)flags);
            }

            bw.BaseStream.Position = nextPosition;
        }
Esempio n. 3
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var nameOffset = 8;

            // Build string tree
            var fileNames = files.Select(x => x.FilePath.ToRelative().FullName).ToArray();

            var rootNode = new StringNode();

            rootNode.AddRange(fileNames);

            // Assign offsets to nodes
            var nodeOffsetMap   = new Dictionary <StringNode, int>();
            var nameTableOffset = AssignOffsets(rootNode, nameOffset, nodeOffsetMap);

            nameTableOffset = (nameTableOffset + 1) & ~1;

            // Write node tree
            output.Position = nameTableOffset;
            var fileId = 0;

            WriteNodes(rootNode, bw, nodeOffsetMap, ref fileId);

            var entryOffset = bw.BaseStream.Length;
            var fileOffset  = entryOffset + files.Count * EntrySize;

            // Write files
            var entries = new List <PakEntry>();

            var filePosition = fileOffset;

            foreach (var file in files.Cast <ArchiveFileInfo>())
            {
                output.Position = filePosition;
                var writtenSize = file.SaveFileData(output);

                entries.Add(new PakEntry
                {
                    offset = (int)filePosition,
                    size   = (int)writtenSize
                });

                filePosition += writtenSize;
            }

            // Write entries
            output.Position = entryOffset;
            bw.WriteMultiple(entries);

            // Write strings
            foreach (var pair in nodeOffsetMap)
            {
                output.Position = pair.Value;
                bw.WriteString(pair.Key.Text, Encoding.ASCII, false);
            }

            // Write header
            output.Position = 0;
            bw.WriteType(new PakHeader
            {
                fileCount   = (short)files.Count,
                entryOffset = (int)entryOffset,
                nameTable   = (short)nameTableOffset
            });
        }
Esempio n. 4
0
        private void Add(string input, int position)
        {
            // If no nodes exist yet, add substring without processing it
            if (Nodes.Count < 0)
            {
                Nodes.Add(new StringNode {
                    Text = input.Substring(position, input.Length - position)
                });
                return;
            }

            // Determine best matching node
            StringNode matchingNode = null;

            foreach (var node in Nodes)
            {
                if (node.Text[0] == input[position])
                {
                    matchingNode = node;
                    break;
                }
            }

            // If no node matched, create a new one with substring
            if (matchingNode == null)
            {
                Nodes.Add(new StringNode {
                    Text = input.Substring(position, input.Length - position)
                });
                return;
            }

            // Match node until end or difference
            var length = Math.Min(matchingNode.Text.Length, input.Length - position);

            for (var i = 1; i < length; i++)
            {
                if (input[position + i] != matchingNode.Text[i])
                {
                    // Split and relocate nodes
                    var splitNode = new StringNode()
                    {
                        Text = matchingNode.Text.Substring(i, matchingNode.Text.Length - i)
                    };
                    var newNode = new StringNode()
                    {
                        Text = input.Substring(position + i, input.Length - position - i)
                    };

                    matchingNode.Text = matchingNode.Text.Substring(0, i);

                    splitNode.Nodes    = matchingNode.Nodes;
                    matchingNode.Nodes = new List <StringNode> {
                        splitNode, newNode
                    };

                    return;
                }
            }

            // If strings only differed in length
            if (matchingNode.Text.Length < input.Length - position)
            {
                matchingNode.Add(input, position + matchingNode.Text.Length);
            }

            if (input.Length - position < matchingNode.Text.Length)
            {
                var splitNode = new StringNode()
                {
                    Text = matchingNode.Text.Substring(input.Length - position, matchingNode.Text.Length - (input.Length - position))
                };
                matchingNode.Text = matchingNode.Text.Substring(0, input.Length - position);

                splitNode.Nodes    = matchingNode.Nodes;
                matchingNode.Nodes = new List <StringNode> {
                    splitNode
                };
            }
        }