From 2eab5a3039cff3a8adc5f9510df87452ce56dd2a Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Wed, 7 Jun 2023 19:56:08 +0200 Subject: Version incremented --- src/SBaseFileTable.cpp | 100 +++++++++++++-------------------------------- src/StormLib.h | 4 +- test/StormTest.cpp | 2 +- test/stormlib-test-001.txt | 6 --- 4 files changed, 32 insertions(+), 80 deletions(-) diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index 20d7cc4..befe40f 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -312,59 +312,38 @@ static ULONGLONG DetermineArchiveSize_V1( return (EndOfMpq - MpqOffset); } -static ULONGLONG DetermineArchiveSize_V2( - TMPQHeader * pHeader, - ULONGLONG MpqOffset, - ULONGLONG FileSize) +static ULONGLONG DetermineBlockTableSize_V2(TMPQHeader * pHeader, ULONGLONG MpqHeaderPos, ULONGLONG FileSize) { - ULONGLONG TableOffset; - ULONGLONG TableSize; - ULONGLONG MaxOffset = 0; - - // This could only be called for MPQs version 2.0 - assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_2); + ULONGLONG BlockTablePos = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); + ULONGLONG ArchiveSize = FileSize - MpqHeaderPos; - // Is the hash table end greater than max offset? - TableOffset = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos); - TableSize = (ULONGLONG)pHeader->dwHashTableSize * sizeof(TMPQHash); - if((TableOffset + TableSize) > MaxOffset) - MaxOffset = TableOffset + TableSize; - - // Is the block table end greater than max offset? - TableOffset = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); - TableSize = (ULONGLONG)pHeader->dwBlockTableSize * sizeof(TMPQBlock); - if((TableOffset + TableSize) > MaxOffset) - MaxOffset = TableOffset + TableSize; - - // Is the hi-block table end greater than max offset? - if((TableOffset = pHeader->HiBlockTablePos64) != 0) + // If there is a hi-block table and it is beyond the block table, + // we can determine the block table size from it + if(pHeader->HiBlockTablePos64 != 0) { - TableSize = (ULONGLONG)pHeader->dwBlockTableSize * sizeof(USHORT); - if((TableOffset + TableSize) > MaxOffset) - MaxOffset = TableOffset + TableSize; + if(pHeader->HiBlockTablePos64 > BlockTablePos) + { + return (pHeader->HiBlockTablePos64 - BlockTablePos); + } } - // Cut to the file size - if(MaxOffset > (FileSize - MpqOffset)) - MaxOffset = FileSize - MpqOffset; - return MaxOffset; -} - -static ULONGLONG DetermineBlockTableSize_V2(TMPQHeader * pHeader) -{ - ULONGLONG BlockTableOffset = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos); - ULONGLONG TableOffset; - ULONGLONG TableSize = (pHeader->ArchiveSize64 - BlockTableOffset); - - // Subtract the offset of the hi-block table - if((TableOffset = pHeader->HiBlockTablePos64) != 0) + // If we have valid archive size, we can determine the block table size from the archive size + else { - if(TableOffset > BlockTableOffset) + if((BlockTablePos >> 0x20) == 0 && (ArchiveSize >> 0x20) == 0) { - TableSize = TableOffset - BlockTableOffset; + DWORD dwBlockTablePos32 = (DWORD)(BlockTablePos); + DWORD dwArchiveSize32 = (DWORD)(ArchiveSize); + + if(pHeader->dwArchiveSize == dwArchiveSize32) + { + return (dwArchiveSize32 - dwBlockTablePos32); + } } } - return TableSize; + + // Default is the block table size from MPQ header + return (ULONGLONG)(pHeader->dwBlockTableSize) * sizeof(TMPQBlock); } static ULONGLONG DetermineArchiveSize_V4( @@ -566,35 +545,14 @@ DWORD ConvertMpqHeaderToFormat4( // We require the block table to follow hash table if(BlockTablePos64 >= HashTablePos64) { - // HashTableSize64 may be less than TblSize * sizeof(TMPQHash). - // That means that the hash table is compressed. + // Determine whether the hash table is compressed. This can be detected + // by subtracting hash table position from the block table position. pHeader->HashTableSize64 = BlockTablePos64 - HashTablePos64; - // Calculate the compressed block table size - if(pHeader->HiBlockTablePos64 != 0) - { - // BlockTableSize64 may be less than TblSize * sizeof(TMPQBlock). - // That means that the block table is compressed. - pHeader->BlockTableSize64 = pHeader->HiBlockTablePos64 - BlockTablePos64; - assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock))); - - // Determine real archive size - pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize); - - // Calculate the size of the hi-block table - pHeader->HiBlockTableSize64 = pHeader->ArchiveSize64 - pHeader->HiBlockTablePos64; - assert(pHeader->HiBlockTableSize64 == (pHeader->dwBlockTableSize * sizeof(USHORT))); - } - else - { - // Determine real archive size - pHeader->ArchiveSize64 = DetermineArchiveSize_V2(pHeader, ByteOffset, FileSize); - pHeader->dwArchiveSize = (DWORD)(pHeader->ArchiveSize64); - - // Calculate size of the block table - pHeader->BlockTableSize64 = DetermineBlockTableSize_V2(pHeader); - assert(pHeader->BlockTableSize64 <= (pHeader->dwBlockTableSize * sizeof(TMPQBlock))); - } + // Also, block table may be compressed. We check whether the HiBlockTable is there. + // If not, we try to use the archive size. Note that ArchiveSize may have + // an arbitrary value, because it is not tested by Blizzard games anymore + pHeader->BlockTableSize64 = DetermineBlockTableSize_V2(pHeader, ByteOffset, FileSize); } else { diff --git a/src/StormLib.h b/src/StormLib.h index 94e9813..4aa51c1 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -143,8 +143,8 @@ extern "C" { //----------------------------------------------------------------------------- // Defines -#define STORMLIB_VERSION 0x0918 // Current version of StormLib (9.24) -#define STORMLIB_VERSION_STRING "9.24" // String version of StormLib version +#define STORMLIB_VERSION 0x0919 // Current version of StormLib +#define STORMLIB_VERSION_STRING "9.25" // Current version of StormLib as string #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A') #define ID_MPQ_USERDATA 0x1B51504D // MPQ userdata entry ('MPQ\x1B') diff --git a/test/StormTest.cpp b/test/StormTest.cpp index 249cc80..a65430d 100755 --- a/test/StormTest.cpp +++ b/test/StormTest.cpp @@ -2655,7 +2655,7 @@ static DWORD TestOpenArchive( } // Reset error code, if the failure is expected - if((dwErrCode != ERROR_SUCCESS) && (hMpq == NULL) && (dwFlags & TFLG_WILL_FAIL)) + if((dwErrCode != ERROR_SUCCESS || hMpq == NULL) && (dwFlags & TFLG_WILL_FAIL)) SetLastError(dwErrCode = ERROR_SUCCESS); // Cleanup and exit diff --git a/test/stormlib-test-001.txt b/test/stormlib-test-001.txt index f35c06f..d69a56e 100644 --- a/test/stormlib-test-001.txt +++ b/test/stormlib-test-001.txt @@ -1,7 +1,3 @@ -Microsoft Windows [Version 10.0.19045.2965] -(c) Microsoft Corporation. All rights reserved. - -E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release>StormLib_test.exe ==== Test Suite for StormLib version 9.24 ==== InitWorkFolder: Work directory \Multimedia\MPQs (default) TestLiFiSearch (FLAT-MAP:ListFile_Blizzard.txt) succeeded. @@ -138,5 +134,3 @@ ListFilePos (StormLibTest_ListFilePos.mpq) succeeded. TestBigArchive (StormLibTest_BigArchive_v4.mpq) succeeded. TestModifyMpq (MPQ_2014_v4_Base.StormReplay) succeeded. TestModifyMpq (MPQ_2022_v1_v4.329.w3x) succeeded. - -E:\Ladik\AppDir\StormLib\bin\StormLib_test\x64\Release> \ No newline at end of file -- cgit v1.2.3