aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLadislav Zezula <zezula@volny.cz>2023-12-30 09:02:20 +0100
committerGitHub <noreply@github.com>2023-12-30 09:02:20 +0100
commit8978bdc8214f4ec3543ac11962fc094c3b0803b2 (patch)
tree0b819048623265303dc22374831cc1f84be6f328 /src
parent61b6665433e8de0e4be68e69ddfb0128421d4057 (diff)
parent909ff807e78b0b92afffaf0d5ed7149982d8ac33 (diff)
Merge pull request #316 from ladislav-zezula/LZ_HashEntryIndex_Fix
Multiple changes
Diffstat (limited to 'src')
-rw-r--r--src/SBaseCommon.cpp2
-rw-r--r--src/SBaseFileTable.cpp43
-rw-r--r--src/SFileCreateArchive.cpp3
-rw-r--r--src/SFileOpenArchive.cpp5
-rw-r--r--src/SFileOpenFileEx.cpp18
-rw-r--r--src/StormCommon.h1
-rw-r--r--src/StormLib.h1
7 files changed, 53 insertions, 20 deletions
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/SFileOpenFileEx.cpp b/src/SFileOpenFileEx.cpp
index d26e01e..157ad15 100644
--- a/src/SFileOpenFileEx.cpp
+++ b/src/SFileOpenFileEx.cpp
@@ -16,10 +16,13 @@
/* Local functions */
/*****************************************************************************/
+// Finds hash index of the entry that was open by pseudo-name
static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex)
{
TMPQHash * pHashTableEnd;
TMPQHash * pHash;
+ DWORD dwHashIndex = HASH_ENTRY_FREE;
+ DWORD dwCount = 0;
// Should only be called if the archive has hash table
assert(ha->pHashTable != NULL);
@@ -31,15 +34,18 @@ static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex)
{
if(MPQ_BLOCK_INDEX(pHash) == dwFileIndex)
{
- // Find the first hash entry that points to it.
- // If there are multiple hash entries that point
- // to the same file, only the first one is returned.
- return (DWORD)(pHash - ha->pHashTable);
+ // Example: MPQ_2023_v1_Lusin2Rpg1.28.w3x, file index 24483
+ // ReplaceableTextures\CommandButtons\BTNHaboss79.blp
+ // Hash Table Index #1 = 18
+ // Hash Table Index #2 = 8446
+ if(dwCount++ > 0)
+ return HASH_ENTRY_FREE;
+ dwHashIndex = (DWORD)(pHash - ha->pHashTable);
}
}
- // No item was found
- return HASH_ENTRY_FREE;
+ // Return the found hash index, if there are no duplicities
+ return dwHashIndex;
}
static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
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