Example #1
0
        /// <summary>
        /// Reads the entry from the VPK package.
        /// </summary>
        /// <param name="entry">Package entry.</param>
        /// <param name="output">Output buffer.</param>
        /// <param name="validateCrc">If true, CRC32 will be calculated and verified for read data.</param>
        public void ReadEntry(PackageEntry entry, out byte[] output, bool validateCrc = true)
        {
            output = new byte[entry.SmallData.Length + entry.Length];

            if (entry.SmallData.Length > 0)
            {
                entry.SmallData.CopyTo(output, 0);
            }

            if (entry.Length > 0)
            {
                Stream fs = null;

                try
                {
                    var offset = entry.Offset;

                    if (entry.ArchiveIndex != 0x7FFF)
                    {
                        if (!IsDirVPK)
                        {
                            throw new InvalidOperationException("Given VPK is not a _dir, but entry is referencing an external archive.");
                        }

                        var fileName = $"{FileName}_{entry.ArchiveIndex:D3}.vpk";

                        fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                    }
                    else
                    {
                        fs = Reader.BaseStream;

                        offset += HeaderSize + TreeSize;
                    }

                    fs.Seek(offset, SeekOrigin.Begin);
                    fs.Read(output, entry.SmallData.Length, (int)entry.Length);
                }
                finally
                {
                    if (entry.ArchiveIndex != 0x7FFF)
                    {
                        fs?.Close();
                    }
                }
            }

            if (validateCrc && entry.CRC32 != Crc32.Compute(output))
            {
                throw new InvalidDataException("CRC32 mismatch for read data.");
            }
        }
Example #2
0
        private void ReadEntries()
        {
            var typeEntries = new Dictionary <string, List <PackageEntry> >();

            // Types
            while (true)
            {
                var typeName = Reader.ReadNullTermString(Encoding.UTF8);

                if (typeName == string.Empty)
                {
                    break;
                }

                // Valve uses a space for missing extensions,
                // we replace it with an empty string to match how System.IO.Path deals with it.
                if (typeName == " ")
                {
                    typeName = string.Empty;
                }

                var entries = new List <PackageEntry>();

                // Directories
                while (true)
                {
                    var directoryName = Reader.ReadNullTermString(Encoding.UTF8);

                    if (directoryName == string.Empty)
                    {
                        break;
                    }

                    // Valve uses a space for blank directory names,
                    // we replace it with a null to match how System.IO.Path deals with root paths.
                    if (directoryName == " ")
                    {
                        directoryName = null;
                    }

                    // Files
                    while (true)
                    {
                        var fileName = Reader.ReadNullTermString(Encoding.UTF8);

                        if (fileName == string.Empty)
                        {
                            break;
                        }

                        var entry = new PackageEntry
                        {
                            FileName      = fileName,
                            DirectoryName = directoryName,
                            TypeName      = typeName,
                            CRC32         = Reader.ReadUInt32(),
                            SmallData     = new byte[Reader.ReadUInt16()],
                            ArchiveIndex  = Reader.ReadUInt16(),
                            Offset        = Reader.ReadUInt32(),
                            Length        = Reader.ReadUInt32()
                        };

                        if (Reader.ReadUInt16() != 0xFFFF)
                        {
                            throw new FormatException("Invalid terminator.");
                        }

                        if (entry.SmallData.Length > 0)
                        {
                            Reader.Read(entry.SmallData, 0, entry.SmallData.Length);
                        }

                        entries.Add(entry);
                    }
                }

                typeEntries.Add(typeName, entries);
            }

            Entries = typeEntries;
        }
Example #3
0
        private void ReadEntries()
        {
            var typeEntries = new Dictionary <string, List <PackageEntry> >();

            // Types
            while (true)
            {
                var typeName = Reader.ReadNullTermString(Encoding.UTF8);

                if (typeName?.Length == 0)
                {
                    break;
                }

                var entries = new List <PackageEntry>();

                // Directories
                while (true)
                {
                    var directoryName = Reader.ReadNullTermString(Encoding.UTF8);

                    if (directoryName?.Length == 0)
                    {
                        break;
                    }

                    // Files
                    while (true)
                    {
                        var fileName = Reader.ReadNullTermString(Encoding.UTF8);

                        if (fileName?.Length == 0)
                        {
                            break;
                        }

                        var entry = new PackageEntry
                        {
                            FileName      = fileName,
                            DirectoryName = directoryName,
                            TypeName      = typeName,
                            CRC32         = Reader.ReadUInt32(),
                            SmallData     = new byte[Reader.ReadUInt16()],
                            ArchiveIndex  = Reader.ReadUInt16(),
                            Offset        = Reader.ReadUInt32(),
                            Length        = Reader.ReadUInt32()
                        };

                        if (Reader.ReadUInt16() != 0xFFFF)
                        {
                            throw new FormatException("Invalid terminator.");
                        }

                        if (entry.SmallData.Length > 0)
                        {
                            Reader.Read(entry.SmallData, 0, entry.SmallData.Length);
                        }

                        entries.Add(entry);
                    }
                }

                typeEntries.Add(typeName, entries);
            }

            Entries = typeEntries;
        }