// filename is a relative path, eg. materials\models\props_map_editor\palette\cubes.vtf // you can use either kind of slash, and it's not case sensitive public byte[] GetFileContents(string filename) { lock (lockThis2) { string fullpath = Path.Combine(folder, filename.Replace("/", "\\")); if (File.Exists(fullpath)) // files in the folder should override those in the package (for us) { return(File.ReadAllBytes(fullpath)); } else { PackageEntry entry = GetEntry(filename); if (entry == null) // if file not in folder or archive { return(null); } if (entry.Size == 0 && entry.SmallData.Length > 0) // if file in archive index { return(entry.SmallData); } else // if file in archive { string archiveName = Path.Combine(folder, string.Format("pak01_{0:D3}.vpk", entry.ArchiveIndex)); if (!File.Exists(archiveName)) { return(null); } using (FileStream f = new FileStream(archiveName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { f.Seek(entry.Offset, SeekOrigin.Begin); byte[] data = new byte[entry.Size]; f.Read(data, 0, (int)entry.Size); return(data); } } // end if file in archive } } }
public void Deserialize(Stream stream) { List <PackageEntry> entries = new List <PackageEntry>(); if (ReadU32(stream) != 0x55AA1234) // Left 4 Dead, before June 25, 2009 update { stream.Seek(-4, SeekOrigin.Current); } else // Left 4 Dead update, Left 4 Dead 2, Alien Swarm, Portal 2, Source Filmmaker, Dota 2 { uint version = ReadU32(stream); uint indexSize = ReadU32(stream); if (version >= 2) // Counter-Strike: Global Offensive { uint zero = ReadU32(stream); // 0 in CSGO uint FooterLength = ReadU32(stream); uint FortyEight = ReadU32(stream); // 48 in CSGO uint zero2 = ReadU32(stream); // 0 in CSGO } } // Types while (true) { string typeName = ReadASCIIZ(stream); if (typeName == "") { break; } // Directories while (true) { string directoryName = ReadASCIIZ(stream); if (directoryName == "") { break; } // Files while (true) { string fileName = ReadASCIIZ(stream); if (fileName == "") { break; } PackageEntry entry = new PackageEntry(); entry.FileName = fileName.ToLowerInvariant(); entry.DirectoryName = directoryName.Replace("/", "\\").ToLowerInvariant(); entry.TypeName = typeName.ToLowerInvariant(); entry.CRC32 = ReadU32(stream); entry.SmallData = new byte[ReadU16(stream)]; entry.ArchiveIndex = ReadU16(stream); entry.Offset = ReadU32(stream); entry.Size = ReadU32(stream); UInt16 terminator = ReadU16(stream); if (terminator != 0xFFFF) { throw new FormatException("invalid terminator"); } if (entry.SmallData.Length > 0) { stream.Read(entry.SmallData, 0, entry.SmallData.Length); } entries.Add(entry); } } } this.Entries = entries; }
public void Deserialize(Stream stream) { List<PackageEntry> entries = new List<PackageEntry>(); if (ReadU32(stream) != 0x55AA1234) // Left 4 Dead, before June 25, 2009 update { stream.Seek(-4, SeekOrigin.Current); } else // Left 4 Dead update, Left 4 Dead 2, Alien Swarm, Portal 2, Source Filmmaker, Dota 2 { uint version = ReadU32(stream); uint indexSize = ReadU32(stream); if (version >= 2) // Counter-Strike: Global Offensive { uint zero = ReadU32(stream); // 0 in CSGO uint FooterLength = ReadU32(stream); uint FortyEight = ReadU32(stream); // 48 in CSGO uint zero2 = ReadU32(stream); // 0 in CSGO } } // Types while (true) { string typeName = ReadASCIIZ(stream); if (typeName == "") { break; } // Directories while (true) { string directoryName = ReadASCIIZ(stream); if (directoryName == "") { break; } // Files while (true) { string fileName = ReadASCIIZ(stream); if (fileName == "") { break; } PackageEntry entry = new PackageEntry(); entry.FileName = fileName.ToLowerInvariant(); entry.DirectoryName = directoryName.Replace("/", "\\").ToLowerInvariant(); entry.TypeName = typeName.ToLowerInvariant(); entry.CRC32 = ReadU32(stream); entry.SmallData = new byte[ReadU16(stream)]; entry.ArchiveIndex = ReadU16(stream); entry.Offset = ReadU32(stream); entry.Size = ReadU32(stream); UInt16 terminator = ReadU16(stream); if (terminator != 0xFFFF) { throw new FormatException("invalid terminator"); } if (entry.SmallData.Length > 0) { stream.Read(entry.SmallData, 0, entry.SmallData.Length); } entries.Add(entry); } } } this.Entries = entries; }