diff --git a/HLExtract.Net/HLLib.cs b/HLExtract.Net/HLLib.cs index 4c99214..2b151a4 100644 --- a/HLExtract.Net/HLLib.cs +++ b/HLExtract.Net/HLLib.cs @@ -19,8 +19,8 @@ using System.Runtime.InteropServices; public sealed class HLLib { #region Constants - public const int HL_VERSION_NUMBER = ((2 << 24) | (4 << 16) | (3 << 8) | 0); - public const string HL_VERSION_STRING = "2.4.3"; + public const int HL_VERSION_NUMBER = ((2 << 24) | (4 << 16) | (4 << 8) | 0); + public const string HL_VERSION_STRING = "2.4.4"; public const uint HL_ID_INVALID = 0xffffffff; diff --git a/HLExtract.Net/Properties/AssemblyInfo.cs b/HLExtract.Net/Properties/AssemblyInfo.cs index 0e46866..2842685 100644 --- a/HLExtract.Net/Properties/AssemblyInfo.cs +++ b/HLExtract.Net/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("HLExtract.Net")] -[assembly: AssemblyCopyright("Copyright (C) 2008-2012 Ryan Gregg")] +[assembly: AssemblyCopyright("Copyright (C) 2008-2013 Ryan Gregg")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2.4.3.0")] -[assembly: AssemblyFileVersion("2.4.3.0")] +[assembly: AssemblyVersion("2.4.4.0")] +[assembly: AssemblyFileVersion("2.4.4.0")] diff --git a/HLExtract/HLExtract.rc b/HLExtract/HLExtract.rc index 1110cf0..bbbdf38 100644 --- a/HLExtract/HLExtract.rc +++ b/HLExtract/HLExtract.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,4,3,0 - PRODUCTVERSION 2,4,3,0 + FILEVERSION 2,4,4,0 + PRODUCTVERSION 2,4,4,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "Comments", "Half-Life Package Extraction Utility" VALUE "FileDescription", "HLExtract Application" - VALUE "FileVersion", "2.4.3" + VALUE "FileVersion", "2.4.4" VALUE "InternalName", "HLExtract" - VALUE "LegalCopyright", "Copyright (C) 2006-2012 Ryan Gregg" + VALUE "LegalCopyright", "Copyright (C) 2006-2013 Ryan Gregg" VALUE "OriginalFilename", "HLExtract.exe" VALUE "ProductName", " HLExtract Application" - VALUE "ProductVersion", "2.4.3" + VALUE "ProductVersion", "2.4.4" END END BLOCK "VarFileInfo" diff --git a/HLLib/Checksum.cpp b/HLLib/Checksum.cpp index 56ba084..85faa3b 100644 --- a/HLLib/Checksum.cpp +++ b/HLLib/Checksum.cpp @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2010 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -206,3 +206,159 @@ hlULong HLLib::CRC32(const hlByte *lpBuffer, hlUInt uiBufferSize, hlULong uiCRC) return uiCRC ^ 0xffffffffUL; } + +const hlULong lpMD5Table[4][16] = +{ + { + 0xD76AA478UL, 0xE8C7B756UL, 0x242070DBUL, 0xC1BDCEEEUL, + 0xF57C0FAFUL, 0x4787C62AUL, 0xA8304613UL, 0xFD469501UL, + 0x698098D8UL, 0x8B44F7AFUL, 0xFFFF5BB1UL, 0x895CD7BEUL, + 0x6B901122UL, 0xFD987193UL, 0xA679438EUL, 0x49B40821UL, + }, + { + 0xF61E2562UL, 0xC040B340UL, 0x265E5A51UL, 0xE9B6C7AAUL, + 0xD62F105DUL, 0x02441453UL, 0xD8A1E681UL, 0xE7D3FBC8UL, + 0x21E1CDE6UL, 0xC33707D6UL, 0xF4D50D87UL, 0x455A14EDUL, + 0xA9E3E905UL, 0xFCEFA3F8UL, 0x676F02D9UL, 0x8D2A4C8AUL, + }, + { + 0xFFFA3942UL, 0x8771F681UL, 0x6D9D6122UL, 0xFDE5380CUL, + 0xA4BEEA44UL, 0x4BDECFA9UL, 0xF6BB4B60UL, 0xBEBFBC70UL, + 0x289B7EC6UL, 0xEAA127FAUL, 0xD4EF3085UL, 0x04881D05UL, + 0xD9D4D039UL, 0xE6DB99E5UL, 0x1FA27CF8UL, 0xC4AC5665UL, + }, + { + 0xF4292244UL, 0x432AFF97UL, 0xAB9423A7UL, 0xFC93A039UL, + 0x655B59C3UL, 0x8F0CCC92UL, 0xFFEFF47DUL, 0x85845DD1UL, + 0x6FA87E4FUL, 0xFE2CE6E0UL, 0xA3014314UL, 0x4E0811A1UL, + 0xF7537E82UL, 0xBD3AF235UL, 0x2AD7D2BBUL, 0xEB86D391UL, + }, +}; + +const hlUInt lpMD5ShiftAmounts[4][16] = +{ + { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, }, + { 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, }, + { 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, }, + { 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, }, +}; + +const hlByte lpMD5Padding[64] = +{ + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +hlULong LeftRoate(hlULong value, hlUInt bits) +{ + return (value << bits) | (value >> (32 - bits)); +} + +hlVoid HLLib::MD5_Initialize(MD5Context& context) +{ + context.lpState[0] = 0x67452301UL; + context.lpState[1] = 0xEFCDAB89UL; + context.lpState[2] = 0x98BADCFEUL; + context.lpState[3] = 0x10325476UL; + context.uiLength = 0; +} + +hlVoid HLLib::MD5_Update(MD5Context& context, const hlByte *lpBuffer, hlUInt uiBufferSize) +{ + hlULong uiBlockLength = context.uiLength % sizeof(context.lpBlock); + while(uiBlockLength + uiBufferSize >= sizeof(context.lpBlock)) + { + hlULong uiCopyLength = std::min(static_cast(uiBufferSize), static_cast(sizeof(context.lpBlock) - uiBlockLength)); + memcpy(reinterpret_cast(context.lpBlock) + uiBlockLength, lpBuffer, uiCopyLength); + context.uiLength += uiCopyLength; + + lpBuffer += uiCopyLength; + uiBufferSize -= uiCopyLength; + + { + hlULong a = context.lpState[0]; + hlULong b = context.lpState[1]; + hlULong c = context.lpState[2]; + hlULong d = context.lpState[3]; + + // Round 1. + for(hlULong i = 0; i < 16; ++i) + { + hlULong x = (b & c) | ((~b) & d); + + hlULong t = d; + d = c; + c = b; + b += LeftRoate(a + x + lpMD5Table[0][i] + context.lpBlock[i], lpMD5ShiftAmounts[0][i]); + a = t; + } + + // Round 2. + for(hlULong i = 0; i < 16; ++i) + { + hlULong x = (d & b) | (c & (~d)); + + hlULong t = d; + d = c; + c = b; + b += LeftRoate(a + x + lpMD5Table[1][i] + context.lpBlock[(5 * i + 1) % 16], lpMD5ShiftAmounts[1][i]); + a = t; + } + + // Round 3. + for(hlULong i = 0; i < 16; ++i) + { + hlULong x = b ^ c ^ d; + + hlULong t = d; + d = c; + c = b; + b += LeftRoate(a + x + lpMD5Table[2][i] + context.lpBlock[(3 * i + 5) % 16], lpMD5ShiftAmounts[2][i]); + a = t; + } + + // Round 4. + for(hlULong i = 0; i < 16; ++i) + { + hlULong x = c ^ (b | (~d)); + + hlULong t = d; + d = c; + c = b; + b += LeftRoate(a + x + lpMD5Table[3][i] + context.lpBlock[(7 * i) % 16], lpMD5ShiftAmounts[3][i]); + a = t; + } + + context.lpState[0] += a; + context.lpState[1] += b; + context.lpState[2] += c; + context.lpState[3] += d; + } + + uiBlockLength = 0; + } + + memcpy(reinterpret_cast(context.lpBlock) + uiBlockLength, lpBuffer, uiBufferSize); + context.uiLength += uiBufferSize; +} + +hlVoid HLLib::MD5_Finalize(MD5Context& context, hlByte (&lpDigest)[16]) +{ + hlULongLong uiLengthInBits = 8ULL * static_cast(context.uiLength); + + hlULong uiBlockLength = context.uiLength % sizeof(context.lpBlock); + if(uiBlockLength < sizeof(context.lpBlock) - sizeof(hlULongLong)) + { + MD5_Update(context, lpMD5Padding, sizeof(context.lpBlock) - sizeof(uiLengthInBits) - uiBlockLength); + } + else + { + MD5_Update(context, lpMD5Padding, 2 * sizeof(context.lpBlock) - sizeof(uiLengthInBits) - uiBlockLength); + } + + MD5_Update(context, reinterpret_cast(&uiLengthInBits), sizeof(uiLengthInBits)); + + memcpy(lpDigest, context.lpState, sizeof(lpDigest)); +} diff --git a/HLLib/Checksum.h b/HLLib/Checksum.h index fd708a3..25ff172 100644 --- a/HLLib/Checksum.h +++ b/HLLib/Checksum.h @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2010 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,17 @@ namespace HLLib { hlULong Adler32(const hlByte *lpBuffer, hlUInt uiBufferSize, hlULong uiAdler32 = 0); hlULong CRC32(const hlByte *lpBuffer, hlUInt uiBufferSize, hlULong uiCRC = 0); + + struct MD5Context + { + hlULong lpState[4]; + hlULong lpBlock[16]; + hlULong uiLength; + }; + + hlVoid MD5_Initialize(MD5Context& context); + hlVoid MD5_Update(MD5Context& context, const hlByte *lpBuffer, hlUInt uiBufferSize); + hlVoid MD5_Finalize(MD5Context& context, hlByte (&lpDigest)[16]); } #endif diff --git a/HLLib/HLLib.rc b/HLLib/HLLib.rc index 12d4d0c..56191c2 100644 --- a/HLLib/HLLib.rc +++ b/HLLib/HLLib.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,4,3,0 - PRODUCTVERSION 2,4,3,0 + FILEVERSION 2,4,4,0 + PRODUCTVERSION 2,4,4,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,12 +69,12 @@ BEGIN BEGIN VALUE "Comments", "Half-Life Package Library" VALUE "FileDescription", "HLLib Dynamic Link Library" - VALUE "FileVersion", "2.4.3" + VALUE "FileVersion", "2.4.4" VALUE "InternalName", "HLLib" - VALUE "LegalCopyright", "Copyright (C) 2006-2012 Ryan Gregg" + VALUE "LegalCopyright", "Copyright (C) 2006-2013 Ryan Gregg" VALUE "OriginalFilename", "HLLib.dll" VALUE "ProductName", " HLLib Dynamic Link Library" - VALUE "ProductVersion", "2.4.3" + VALUE "ProductVersion", "2.4.4" END END BLOCK "VarFileInfo" diff --git a/HLLib/VPKFile.cpp b/HLLib/VPKFile.cpp index ee2c536..629e107 100644 --- a/HLLib/VPKFile.cpp +++ b/HLLib/VPKFile.cpp @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2010 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ using namespace HLLib; const char *CVPKFile::lpAttributeNames[] = { "Archives", "Version" }; const char *CVPKFile::lpItemAttributeNames[] = { "Preload Bytes", "Archive", "CRC" }; -CVPKFile::CVPKFile() : CPackage(), pView(0), uiArchiveCount(0), lpArchives(0), pHeader(0), pDirectoryItems(0) +CVPKFile::CVPKFile() : CPackage(), pView(0), uiArchiveCount(0), lpArchives(0), pHeader(0), pExtendedHeader(0), lpArchiveHashes(0), pDirectoryItems(0) { } @@ -103,14 +103,16 @@ hlBool CVPKFile::MapDataStructures() return hlFalse; } lpViewData += sizeof(VPKHeader); - switch(this->pHeader->uiVersion) + if(this->pHeader->uiVersion >= 2) { - case 2: - // Version two includes 4 more double words. - lpViewData += 4 * sizeof(hlUInt); - break; + this->pExtendedHeader = reinterpret_cast(lpViewData); + lpViewData += sizeof(VPKExtendedHeader); } lpViewDirectoryDataEnd = lpViewData + this->pHeader->uiDirectoryLength; + if(this->pExtendedHeader != 0) + { + this->lpArchiveHashes = reinterpret_cast(lpViewDirectoryDataEnd); + } } while(hlTrue) @@ -149,39 +151,35 @@ hlBool CVPKFile::MapDataStructures() break; } - const VPKDirectoryEntry *pDirectoryEntry; if(lpViewData + sizeof(VPKDirectoryEntry) > lpViewDirectoryDataEnd) { LastError.SetErrorMessage("Invalid file: The file map is not within mapping bounds."); return hlFalse; } - pDirectoryEntry = reinterpret_cast(lpViewData); + const VPKDirectoryEntry *pDirectoryEntry = reinterpret_cast(lpViewData); lpViewData += sizeof(VPKDirectoryEntry); const hlVoid *lpPreloadData = 0; - if(pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE) + if(pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE && pDirectoryEntry->uiEntryLength > 0) { - if(pDirectoryEntry->uiEntryLength > 0) + assert(pDirectoryEntry->uiPreloadBytes == 0); + if(lpViewDirectoryDataEnd + pDirectoryEntry->uiEntryOffset + pDirectoryEntry->uiEntryLength <= lpViewDataEnd) { - if(lpViewDirectoryDataEnd + pDirectoryEntry->uiEntryOffset + pDirectoryEntry->uiEntryLength <= lpViewDataEnd) - { - lpPreloadData = lpViewDirectoryDataEnd + pDirectoryEntry->uiEntryOffset; - } + lpPreloadData = lpViewDirectoryDataEnd + pDirectoryEntry->uiEntryOffset; } } - else + else if(pDirectoryEntry->uiPreloadBytes > 0) { - if(pDirectoryEntry->uiPreloadBytes > 0) + if(lpViewData + pDirectoryEntry->uiPreloadBytes > lpViewDirectoryDataEnd) { - if(lpViewData + pDirectoryEntry->uiPreloadBytes > lpViewDirectoryDataEnd) - { - LastError.SetErrorMessage("Invalid file: The file map is not within mapping bounds."); - return hlFalse; - } - lpPreloadData = lpViewData; - lpViewData += pDirectoryEntry->uiPreloadBytes; + LastError.SetErrorMessage("Invalid file: The file map is not within mapping bounds."); + return hlFalse; } - + lpPreloadData = lpViewData; + lpViewData += pDirectoryEntry->uiPreloadBytes; + } + if(pDirectoryEntry->uiArchiveIndex != HL_VPK_NO_ARCHIVE) + { if((hlUInt)pDirectoryEntry->uiArchiveIndex + 1 > this->uiArchiveCount) { this->uiArchiveCount = pDirectoryEntry->uiArchiveIndex + 1; @@ -435,7 +433,7 @@ hlBool CVPKFile::GetFileExtractableInternal(const CDirectoryFile *pFile, hlBool if(pDirectoryItem->pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE) { - bExtractable = pDirectoryItem->lpPreloadData != 0; + bExtractable = pDirectoryItem->lpPreloadData != 0 || (pDirectoryItem->pDirectoryEntry->uiPreloadBytes == 0 && pDirectoryItem->pDirectoryEntry->uiEntryLength == 0); } else if(pDirectoryItem->pDirectoryEntry->uiEntryLength != 0) { @@ -539,45 +537,7 @@ hlBool CVPKFile::GetFileSizeOnDiskInternal(const CDirectoryFile *pFile, hlUInt & { const VPKDirectoryItem *pDirectoryItem = static_cast(pFile->GetData()); - if(pDirectoryItem->pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE) - { - if(pDirectoryItem->lpPreloadData == 0) - { - uiSize = 0; - } - else - { - uiSize = pDirectoryItem->pDirectoryEntry->uiEntryLength; - } - } - else if(pDirectoryItem->pDirectoryEntry->uiEntryLength != 0) - { - uiSize = pDirectoryItem->pDirectoryEntry->uiEntryLength; - - Mapping::CMapping *pMapping = this->lpArchives[pDirectoryItem->pDirectoryEntry->uiArchiveIndex].pMapping; - if(pMapping == 0) - { - uiSize = 0; - } - else - { - hlUInt uiMappingSize = static_cast(pMapping->GetMappingSize()); - if(pDirectoryItem->pDirectoryEntry->uiEntryOffset >= uiMappingSize) - { - uiSize = 0; - } - else if(pDirectoryItem->pDirectoryEntry->uiEntryOffset + uiSize > uiMappingSize) - { - uiSize = uiMappingSize - pDirectoryItem->pDirectoryEntry->uiEntryOffset; - } - } - - uiSize += pDirectoryItem->pDirectoryEntry->uiPreloadBytes; - } - else - { - uiSize = pDirectoryItem->pDirectoryEntry->uiPreloadBytes; - } + uiSize = pDirectoryItem->pDirectoryEntry->uiEntryLength + pDirectoryItem->pDirectoryEntry->uiPreloadBytes; return hlTrue; } @@ -586,20 +546,24 @@ hlBool CVPKFile::CreateStreamInternal(const CDirectoryFile *pFile, Streams::IStr { const VPKDirectoryItem *pDirectoryItem = static_cast(pFile->GetData()); - if(pDirectoryItem->pDirectoryEntry->uiEntryLength != 0) + if(pDirectoryItem->pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE) { - if(pDirectoryItem->pDirectoryEntry->uiArchiveIndex == HL_VPK_NO_ARCHIVE) + if(pDirectoryItem->lpPreloadData != 0) { - if(pDirectoryItem->lpPreloadData != 0) - { - pStream = new Streams::CMemoryStream(const_cast(pDirectoryItem->lpPreloadData), pDirectoryItem->pDirectoryEntry->uiEntryLength); - } - else - { - return hlFalse; - } + pStream = new Streams::CMemoryStream(const_cast(pDirectoryItem->lpPreloadData), pDirectoryItem->pDirectoryEntry->uiEntryLength + pDirectoryItem->pDirectoryEntry->uiPreloadBytes); } - else if(this->lpArchives[pDirectoryItem->pDirectoryEntry->uiArchiveIndex].pMapping != 0) + else if(pDirectoryItem->pDirectoryEntry->uiPreloadBytes == 0 && pDirectoryItem->pDirectoryEntry->uiEntryLength == 0) + { + pStream = new Streams::CNullStream(); + } + else + { + return hlFalse; + } + } + else if(pDirectoryItem->pDirectoryEntry->uiEntryLength != 0) + { + if(this->lpArchives[pDirectoryItem->pDirectoryEntry->uiArchiveIndex].pMapping != 0) { if(pDirectoryItem->pDirectoryEntry->uiPreloadBytes != 0) { diff --git a/HLLib/VPKFile.h b/HLLib/VPKFile.h index ac0f33b..3aa887d 100644 --- a/HLLib/VPKFile.h +++ b/HLLib/VPKFile.h @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2010 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,15 @@ namespace HLLib hlUInt uiDirectoryLength; }; + // Added in version 2. + struct VPKExtendedHeader + { + hlUInt uiDummy0; + hlUInt uiArchiveHashLength; + hlUInt uiExtraLength; // Looks like some more MD5 hashes. + hlUInt uiDummy1; + }; + struct VPKDirectoryEntry { hlUInt uiCRC; @@ -39,6 +48,15 @@ namespace HLLib hlUShort uiDummy0; // Always 0xffff. }; + // Added in version 2. + struct VPKArchiveHash + { + hlUInt uiArchiveIndex; + hlUInt uiArchiveOffset; + hlUInt uiLength; + hlByte lpHash[16]; // MD5 + }; + #pragma pack() struct VPKArchive @@ -72,6 +90,8 @@ namespace HLLib VPKArchive *lpArchives; const VPKHeader *pHeader; + const VPKExtendedHeader *pExtendedHeader; + const VPKArchiveHash *lpArchiveHashes; CDirectoryItemList *pDirectoryItems; public: diff --git a/HLLib/stdafx.h b/HLLib/stdafx.h index 4eb4023..bfb9c71 100644 --- a/HLLib/stdafx.h +++ b/HLLib/stdafx.h @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2012 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -65,8 +65,8 @@ typedef hlSingle hlFloat; #define hlFalse 0 #define hlTrue 1 -#define HL_VERSION_NUMBER ((2 << 24) | (4 << 16) | (3 << 8) | 0) -#define HL_VERSION_STRING "2.4.3" +#define HL_VERSION_NUMBER ((2 << 24) | (4 << 16) | (4 << 8) | 0) +#define HL_VERSION_STRING "2.4.4" #define HL_ID_INVALID 0xffffffff @@ -375,6 +375,8 @@ typedef hlVoid (*PDefragmentProgressExProc) (const HLDirectoryItem *pFile, hlUIn } #endif +#define NOMINMAX + #if _MSC_VER # define _CRT_SECURE_NO_WARNINGS # define _CRT_NONSTDC_NO_DEPRECATE @@ -444,6 +446,7 @@ typedef hlVoid (*PDefragmentProgressExProc) (const HLDirectoryItem *pFile, hlUIn #include #include +#include #include #include diff --git a/Readme.txt b/Readme.txt index e3bef2a..e794195 100644 --- a/Readme.txt +++ b/Readme.txt @@ -9,11 +9,11 @@ Library/Author Information: =========================== ---- General Library Information ---- -Date : September 18th, 2012 +Date : January 27th, 2013 Author : Ryan Gregg Michael Mohr (Linux Port) Title : HLLib -Build : 2.4.3 +Build : 2.4.4 Email address : ryansgregg@hotmail.com (Ryan Gregg) m.mohr@laposte.net (Michael Mohr) Home page / Website : http://nemesis.thewavelength.net/ @@ -93,6 +93,9 @@ Console Commands (Interactive console mode): Library Changelog: ================== + v2.4.4 + - Fixed support for VPK file format (v1). + v2.4.3 - Added support for new VPK file format (v2). - Added SGA file support. diff --git a/lib/HLLib.h b/lib/HLLib.h index 8536669..6c08c88 100644 --- a/lib/HLLib.h +++ b/lib/HLLib.h @@ -1,6 +1,6 @@ /* * HLLib - * Copyright (C) 2006-2012 Ryan Gregg + * Copyright (C) 2006-2013 Ryan Gregg * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -65,8 +65,8 @@ typedef hlSingle hlFloat; #define hlFalse 0 #define hlTrue 1 -#define HL_VERSION_NUMBER ((2 << 24) | (4 << 16) | (3 << 8) | 0) -#define HL_VERSION_STRING "2.4.3" +#define HL_VERSION_NUMBER ((2 << 24) | (4 << 16) | (4 << 8) | 0) +#define HL_VERSION_STRING "2.4.4" #define HL_ID_INVALID 0xffffffff @@ -580,6 +580,9 @@ HLLIB_API hlBool hlWADFileGetImageData(const HLDirectoryItem *pFile, hlUInt *uiW #endif #ifdef __cplusplus + +# include + namespace HLLib { class HLLIB_API CDirectoryItem; @@ -2211,6 +2214,15 @@ namespace HLLib hlUInt uiDirectoryLength; }; + // Added in version 2. + struct VPKExtendedHeader + { + hlUInt uiDummy0; + hlUInt uiArchiveHashLength; + hlUInt uiExtraLength; // Looks like some more MD5 hashes. + hlUInt uiDummy1; + }; + struct VPKDirectoryEntry { hlUInt uiCRC; @@ -2221,6 +2233,15 @@ namespace HLLib hlUShort uiDummy0; // Always 0xffff. }; + // Added in version 2. + struct VPKArchiveHash + { + hlUInt uiArchiveIndex; + hlUInt uiArchiveOffset; + hlUInt uiLength; + hlByte lpHash[16]; // MD5 + }; + #pragma pack() struct VPKArchive @@ -2242,7 +2263,10 @@ namespace HLLib const hlVoid *lpPreloadData; }; + typedef std::list CDirectoryItemList; + private: + static const char *lpAttributeNames[]; static const char *lpItemAttributeNames[]; Mapping::CView *pView; @@ -2251,7 +2275,9 @@ namespace HLLib VPKArchive *lpArchives; const VPKHeader *pHeader; - class CDirectoryItemList *pDirectoryItems; + const VPKExtendedHeader *pExtendedHeader; + const VPKArchiveHash *lpArchiveHashes; + CDirectoryItemList *pDirectoryItems; public: CVPKFile();