public Stream Open(PackageEntry entry) { List <Stream> streams = new List <Stream>(); if (entry.PreloadSize > 0) { streams.Add(new SubStream(_stream, entry.PreloadOffset, entry.PreloadSize)); } if (entry.Size > 0) { streams.Add(new SubStream(_chunks[entry.Chunk], entry.Offset, entry.Size)); } return(new ConcatStream(streams)); }
public VpkPackage(string directoryFile) { _entries = new List <PackageEntry>(); _stream = OpenFile(directoryFile); string folder = Path.GetDirectoryName(directoryFile) ?? ""; string nameWithoutExt = Path.GetFileNameWithoutExtension(directoryFile) ?? ""; string ext = Path.GetExtension(directoryFile); if (!nameWithoutExt.EndsWith(DirString)) { throw new Exception("This is not a valid VPK directory file."); } string baseName = nameWithoutExt.Substring(0, nameWithoutExt.Length - DirString.Length); // Scan and find all chunk files that match this vpk directory _chunks = new Dictionary <int, Stream>(); string[] matchingFiles = Directory.GetFiles(folder, baseName + "_???" + ext); foreach (string mf in matchingFiles) { string fn = Path.GetFileNameWithoutExtension(mf); string index = fn.Substring(fn.Length - 3); if (ushort.TryParse(index, out ushort num)) { _chunks[num] = OpenFile(mf); } } _chunks[DirectoryIndex] = _stream; // Read the data from the vpk using (BinaryReader br = new BinaryReader(_stream, Encoding.UTF8, true)) { uint sig = br.ReadUInt32(); if (sig != Signature) { throw new Exception($"Unknown package signature: Expected 0x{Signature:x8}, got 0x{sig:x8}."); } uint version = br.ReadUInt32(); uint treeLength = br.ReadUInt32(); _directoryDataOffset = treeLength; switch (version) { case 1: _directoryDataOffset += 12; break; case 2: _directoryDataOffset += 28; int dataLength = br.ReadInt32(); uint archiveMd5Length = br.ReadUInt32(); int fileMd5Length = br.ReadInt32(); int signatureLength = br.ReadInt32(); break; default: throw new Exception($"Unknown version number: Expected 1 or 2, got {version}."); } // Read all the entries from the vpk string extension, path, filename; while ((extension = br.ReadNullTerminatedString()).Length > 0) { while ((path = br.ReadNullTerminatedString()).Length > 0) { // Single space = root directory path = path == " " ? "" : path + '/'; while ((filename = br.ReadNullTerminatedString()).Length > 0) { // get me some file information PackageEntry entry = ReadEntry(br, path + filename + "." + extension); _entries.Add(entry); } } } } }
public Stream Open(PackageEntry entry) { return(new SubStream(_stream, entry.Offset, entry.Size)); }