From f862e018fbab2916948c8880692517361b2ca80f Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 18 Nov 2024 02:13:52 -0500 Subject: [PATCH] Update VPK models --- .../VPK/ArchiveMD5SectionEntry.cs | 27 +++++++++++++++++ SabreTools.Models/VPK/DirectoryEntry.cs | 20 +++++++++++++ SabreTools.Models/VPK/DirectoryItem.cs | 1 + SabreTools.Models/VPK/ExtendedHeader.cs | 22 +++++++++----- SabreTools.Models/VPK/Header.cs | 6 +++- SabreTools.Models/VPK/OtherMD5Section.cs | 18 ++++++++++++ SabreTools.Models/VPK/SignatureSection.cs | 29 +++++++++++++++++++ 7 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 SabreTools.Models/VPK/ArchiveMD5SectionEntry.cs create mode 100644 SabreTools.Models/VPK/OtherMD5Section.cs create mode 100644 SabreTools.Models/VPK/SignatureSection.cs diff --git a/SabreTools.Models/VPK/ArchiveMD5SectionEntry.cs b/SabreTools.Models/VPK/ArchiveMD5SectionEntry.cs new file mode 100644 index 0000000..c726dff --- /dev/null +++ b/SabreTools.Models/VPK/ArchiveMD5SectionEntry.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ArchiveMD5SectionEntry + { + public uint ArchiveIndex; + + /// + /// Where to start reading bytes + /// + public uint StartingOffset; + + /// + /// How many bytes to check + /// + public uint Count; + + /// + /// Expected checksum + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? MD5Checksum = new byte[16]; + } +} \ No newline at end of file diff --git a/SabreTools.Models/VPK/DirectoryEntry.cs b/SabreTools.Models/VPK/DirectoryEntry.cs index 0412469..4b8a789 100644 --- a/SabreTools.Models/VPK/DirectoryEntry.cs +++ b/SabreTools.Models/VPK/DirectoryEntry.cs @@ -3,17 +3,37 @@ using System.Runtime.InteropServices; namespace SabreTools.Models.VPK { /// + /// [StructLayout(LayoutKind.Sequential)] public sealed class DirectoryEntry { + /// + /// A 32bit CRC of the file's data. + /// public uint CRC; + /// + /// The number of bytes contained in the index file. + /// public ushort PreloadBytes; + /// + /// A zero based index of the archive this file's data is contained in. + /// If 0x7fff, the data follows the directory. + /// public ushort ArchiveIndex; + /// + /// If ArchiveIndex is 0x7fff, the offset of the file data relative to the + /// end of the directory (see the header for more details). + /// Otherwise, the offset of the data from the start of the specified archive. + /// public uint EntryOffset; + /// + /// If zero, the entire file is stored in the preload data. + /// Otherwise, the number of bytes stored starting at EntryOffset. + /// public uint EntryLength; /// diff --git a/SabreTools.Models/VPK/DirectoryItem.cs b/SabreTools.Models/VPK/DirectoryItem.cs index 3d12235..6e6d824 100644 --- a/SabreTools.Models/VPK/DirectoryItem.cs +++ b/SabreTools.Models/VPK/DirectoryItem.cs @@ -1,6 +1,7 @@ namespace SabreTools.Models.VPK { /// + /// public sealed class DirectoryItem { public string? Extension { get; set; } diff --git a/SabreTools.Models/VPK/ExtendedHeader.cs b/SabreTools.Models/VPK/ExtendedHeader.cs index f4f8e58..e62a8cf 100644 --- a/SabreTools.Models/VPK/ExtendedHeader.cs +++ b/SabreTools.Models/VPK/ExtendedHeader.cs @@ -6,27 +6,33 @@ namespace SabreTools.Models.VPK /// Added in version 2. /// /// + /// [StructLayout(LayoutKind.Sequential)] public sealed class ExtendedHeader { /// - /// Reserved + /// How many bytes of file content are stored in this + /// VPK file (0 in CSGO) /// - public uint Dummy0; + public uint FileDataSectionSize; /// - /// Archive hash length + /// The size, in bytes, of the section containing MD5 + /// checksums for external archive content /// - public uint ArchiveHashLength; + public uint ArchiveMD5SectionSize; /// - /// Looks like some more MD5 hashes. + /// The size, in bytes, of the section containing MD5 + /// checksums for content in this file (should always be 48) /// - public uint ExtraLength; + public uint OtherMD5SectionSize; /// - /// Reserved + /// The size, in bytes, of the section containing the public + /// key and signature. This is either 0 (CSGO & The Ship) or + /// 296 (HL2, HL2:DM, HL2:EP1, HL2:EP2, HL2:LC, TF2, DOD:S & CS:S) /// - public uint Dummy1; + public uint SignatureSectionSize; } } diff --git a/SabreTools.Models/VPK/Header.cs b/SabreTools.Models/VPK/Header.cs index ccaa7ff..aa57e1c 100644 --- a/SabreTools.Models/VPK/Header.cs +++ b/SabreTools.Models/VPK/Header.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; namespace SabreTools.Models.VPK { /// + /// [StructLayout(LayoutKind.Sequential)] public sealed class Header { @@ -13,6 +14,9 @@ namespace SabreTools.Models.VPK public uint Version; - public uint DirectoryLength; + /// + /// The size, in bytes, of the directory tree + /// + public uint TreeSize; } } diff --git a/SabreTools.Models/VPK/OtherMD5Section.cs b/SabreTools.Models/VPK/OtherMD5Section.cs new file mode 100644 index 0000000..976e6c3 --- /dev/null +++ b/SabreTools.Models/VPK/OtherMD5Section.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class OtherMD5Section + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? TreeChecksum = new byte[16]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? ArchiveMD5SectionChecksum = new byte[16]; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[]? WholeFileChecksum = new byte[16]; + } +} \ No newline at end of file diff --git a/SabreTools.Models/VPK/SignatureSection.cs b/SabreTools.Models/VPK/SignatureSection.cs new file mode 100644 index 0000000..1e1ae22 --- /dev/null +++ b/SabreTools.Models/VPK/SignatureSection.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Models.VPK +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class SignatureSection + { + /// + /// Always seen as 160 (0xA0) bytes + /// + public uint PublicKeySize; + + /// + /// + /// + public byte[]? PublicKey; + + /// + /// Always seen as 128 (0x80) bytes + /// + public uint SignatureSize; + + /// + /// + /// + public byte[]? Signature; + } +} \ No newline at end of file