From 909ff807e78b0b92afffaf0d5ed7149982d8ac33 Mon Sep 17 00:00:00 2001 From: Ladislav Zezula Date: Sat, 30 Dec 2023 08:59:09 +0100 Subject: Regression tests passed --- src/SBaseCommon.cpp | 2 +- src/SBaseFileTable.cpp | 43 ++++++++++++++++++++++++++++++------------- src/SFileCreateArchive.cpp | 3 +++ src/SFileOpenArchive.cpp | 5 +++++ src/StormCommon.h | 1 + src/StormLib.h | 1 + 6 files changed, 41 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/SBaseCommon.cpp b/src/SBaseCommon.cpp index 4fc473a..7415583 100644 --- a/src/SBaseCommon.cpp +++ b/src/SBaseCommon.cpp @@ -15,7 +15,7 @@ #include "StormLib.h" #include "StormCommon.h" -char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2014"; +char StormLibCopyright[] = "StormLib v " STORMLIB_VERSION_STRING " Copyright Ladislav Zezula 1998-2023"; //----------------------------------------------------------------------------- // Local variables diff --git a/src/SBaseFileTable.cpp b/src/SBaseFileTable.cpp index a53d6a6..ca14693 100644 --- a/src/SBaseFileTable.cpp +++ b/src/SBaseFileTable.cpp @@ -385,20 +385,39 @@ static ULONGLONG DetermineArchiveSize_V4( return ArchiveSize; } -ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) +ULONGLONG GetFileOffsetMask(TMPQArchive * ha) { + ULONGLONG FileOffsetMask = (ULONGLONG)(-1); + + // Sanity checks + assert(ha != NULL); + assert(ha->pHeader != NULL); + + // MPQs of format 1 are 32-bit only if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) - { - // For MPQ archive v1, any file offset is only 32-bit - return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset); - } - else - { - // For MPQ archive v2+, file offsets are full 64-bit - return ha->MpqPos + MpqOffset; - } + FileOffsetMask = (ULONGLONG)(DWORD)(-1); + return FileOffsetMask; } +ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) +{ + return (ha->MpqPos + MpqOffset) & ha->FileOffsetMask; +} + +//ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset) +//{ +// if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) +// { +// // For MPQ archive v1, any file offset is only 32-bit +// return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset); +// } +// else +// { +// // For MPQ archive v2+, file offsets are full 64-bit +// return ha->MpqPos + MpqOffset; +// } +//} + ULONGLONG CalculateRawSectorOffset( TMPQFile * hf, DWORD dwSectorOffset) @@ -418,9 +437,7 @@ ULONGLONG CalculateRawSectorOffset( // For MPQs version 1.0, the offset is purely 32-bit // - RawFilePos = hf->RawFilePos + dwSectorOffset; - if(hf->ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1) - RawFilePos = (DWORD)hf->ha->MpqPos + (DWORD)hf->pFileEntry->ByteOffset + dwSectorOffset; + RawFilePos = (hf->RawFilePos + dwSectorOffset) & hf->ha->FileOffsetMask; // We also have to add patch header size, if patch header is present if(hf->pPatchInfo != NULL) diff --git a/src/SFileCreateArchive.cpp b/src/SFileCreateArchive.cpp index c0ea367..bae3dcc 100644 --- a/src/SFileCreateArchive.cpp +++ b/src/SFileCreateArchive.cpp @@ -238,6 +238,9 @@ bool WINAPI SFileCreateArchive2(const TCHAR * szMpqName, PSFILE_CREATE_MPQ pCrea pHeader->dwBlockTablePos = pHeader->dwHashTablePos + dwHashTableSize * sizeof(TMPQHash); pHeader->dwBlockTableSize = dwBlockTableSize; + // Set the mask for MPQ byte offset + ha->FileOffsetMask = GetFileOffsetMask(ha); + // For MPQs version 4 and higher, we set the size of raw data block // for calculating MD5 if(pCreateInfo->dwMpqVersion >= MPQ_FORMAT_VERSION_4) diff --git a/src/SFileOpenArchive.cpp b/src/SFileOpenArchive.cpp index baad848..4b2d3b4 100644 --- a/src/SFileOpenArchive.cpp +++ b/src/SFileOpenArchive.cpp @@ -463,6 +463,11 @@ bool WINAPI SFileOpenArchive( if(IsStarcraftBetaArchive(ha->pHeader)) ha->dwFlags |= MPQ_FLAG_STARCRAFT_BETA; + // Set the mask for the file offset. In MPQs version 1, + // all offsets are 32-bit and overflow is allowed. + // For MPQs v2+, file offset if 64-bit. + ha->FileOffsetMask = GetFileOffsetMask(ha); + // Maps from StarCraft and Warcraft III need special treatment switch(MapType) { diff --git a/src/StormCommon.h b/src/StormCommon.h index 34077fd..c73543d 100644 --- a/src/StormCommon.h +++ b/src/StormCommon.h @@ -251,6 +251,7 @@ TMPQFile * IsValidFileHandle(HANDLE hFile); //----------------------------------------------------------------------------- // Support for MPQ file tables +ULONGLONG GetFileOffsetMask(TMPQArchive * ha); ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset); ULONGLONG CalculateRawSectorOffset(TMPQFile * hf, DWORD dwSectorOffset); diff --git a/src/StormLib.h b/src/StormLib.h index b78f7ef..e211cd8 100644 --- a/src/StormLib.h +++ b/src/StormLib.h @@ -830,6 +830,7 @@ typedef struct _TMPQArchive ULONGLONG UserDataPos; // Position of user data (relative to the begin of the file) ULONGLONG MpqPos; // MPQ header offset (relative to the begin of the file) ULONGLONG FileSize; // Size of the file at the moment of file open + ULONGLONG FileOffsetMask; // 0xFFFFFFFF for MPQ v 1, otherwise 0xFFFFFFFFFFFFFFFFull struct _TMPQArchive * haPatch; // Pointer to patch archive, if any struct _TMPQArchive * haBase; // Pointer to base ("previous version") archive, if any -- cgit v1.2.3