aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-07-22 17:33:43 +0200
committerShauren <shauren.trinity@gmail.com>2016-07-22 17:33:43 +0200
commited079553728b7d4f927890a6e521139f0bde7687 (patch)
tree5303d33a2cd74d1a6e021a73decdd38eed0a594f /dep/CascLib
parent4587b5d88082d2c6416fafaa2f5b9f5f15038520 (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@2702efeae5f63c64f6d883cfcc219daa2fb06108
Diffstat (limited to 'dep/CascLib')
-rw-r--r--dep/CascLib/src/CascRootFile_WoW6.cpp80
1 files changed, 53 insertions, 27 deletions
diff --git a/dep/CascLib/src/CascRootFile_WoW6.cpp b/dep/CascLib/src/CascRootFile_WoW6.cpp
index 2e6a23610f3..e3040d9ebdb 100644
--- a/dep/CascLib/src/CascRootFile_WoW6.cpp
+++ b/dep/CascLib/src/CascRootFile_WoW6.cpp
@@ -66,13 +66,13 @@ struct TRootHandler_WoW6 : public TRootHandler
{
// Linear global list of file entries
DYNAMIC_ARRAY FileTable;
+ DYNAMIC_ARRAY FileDataIdLookupTable;
// Global map of FileName -> FileEntry
PCASC_MAP pRootMap;
// For counting files
DWORD dwTotalFileCount;
- DWORD FileDataId;
};
// Prototype for root file parsing routine
@@ -102,12 +102,17 @@ static bool IsFileDataIdName(const char * szFileName)
return false;
}
+static int FileDataIdCompare(const void *, const void * pvFile1, const void * pvFile2)
+{
+ return ((PCASC_FILE_ENTRY)pvFile1)->FileDataId - ((PCASC_FILE_ENTRY)pvFile2)->FileDataId;
+}
+
// Search by FileDataId
PCASC_FILE_ENTRY FindRootEntry(DYNAMIC_ARRAY & FileTable, DWORD FileDataId)
{
- PCASC_FILE_ENTRY pStartEntry = (PCASC_FILE_ENTRY)FileTable.ItemArray;
- PCASC_FILE_ENTRY pMidlEntry;
- PCASC_FILE_ENTRY pEndEntry = pStartEntry + FileTable.ItemCount - 1;
+ PCASC_FILE_ENTRY* pStartEntry = (PCASC_FILE_ENTRY*)FileTable.ItemArray;
+ PCASC_FILE_ENTRY* pMidlEntry;
+ PCASC_FILE_ENTRY* pEndEntry = pStartEntry + FileTable.ItemCount - 1;
int nResult;
// Perform binary search on the table
@@ -117,9 +122,9 @@ PCASC_FILE_ENTRY FindRootEntry(DYNAMIC_ARRAY & FileTable, DWORD FileDataId)
pMidlEntry = pStartEntry + ((pEndEntry - pStartEntry) / 2);
// Did we find it?
- nResult = (int)FileDataId - (int)pMidlEntry->FileDataId;
+ nResult = (int)FileDataId - (int)(*pMidlEntry)->FileDataId;
if(nResult == 0)
- return pMidlEntry;
+ return *pMidlEntry;
// Move the interval to the left or right
(nResult < 0) ? pEndEntry = pMidlEntry : pStartEntry = pMidlEntry + 1;
@@ -177,10 +182,13 @@ static int ParseRoot_AddRootEntries(
PCASC_ROOT_BLOCK pRootBlock)
{
PCASC_FILE_ENTRY pFileEntry;
+ DWORD dwFileDataId = 0;
// Sanity checks
assert(pRootHandler->FileTable.ItemArray != NULL);
assert(pRootHandler->FileTable.ItemCountMax != 0);
+ assert(pRootHandler->FileDataIdLookupTable.ItemArray != NULL);
+ assert(pRootHandler->FileDataIdLookupTable.ItemCountMax != 0);
// WoW.exe (build 19116): Blocks with zero files are skipped
for(DWORD i = 0; i < pRootBlock->pLocaleBlockHdr->NumberOfFiles; i++)
@@ -190,9 +198,13 @@ static int ParseRoot_AddRootEntries(
return ERROR_INSUFFICIENT_BUFFER;
pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1);
+ if (pRootHandler->FileDataIdLookupTable.ItemCount >= pRootHandler->FileDataIdLookupTable.ItemCountMax)
+ return ERROR_INSUFFICIENT_BUFFER;
+ Array_Insert(&pRootHandler->FileDataIdLookupTable, &pFileEntry, 1);
+
// (004147A3) Prepare the CASC_FILE_ENTRY structure
pFileEntry->FileNameHash = pRootBlock->pRootEntries[i].FileNameHash;
- pFileEntry->FileDataId = pRootHandler->FileDataId + pRootBlock->FileDataIds[i];
+ pFileEntry->FileDataId = dwFileDataId + pRootBlock->FileDataIds[i];
pFileEntry->Locales = pRootBlock->pLocaleBlockHdr->Locales;
pFileEntry->EncodingKey = pRootBlock->pRootEntries[i].EncodingKey;
@@ -201,7 +213,7 @@ static int ParseRoot_AddRootEntries(
// Update the local File Data Id
assert((pFileEntry->FileDataId + 1) > pFileEntry->FileDataId);
- pRootHandler->FileDataId = pFileEntry->FileDataId + 1;
+ dwFileDataId = pFileEntry->FileDataId + 1;
// Move to the next root entry
pFileEntry++;
@@ -216,8 +228,8 @@ static int ParseWowRootFileInternal(
LPBYTE pbRootFile,
LPBYTE pbRootFileEnd,
DWORD dwLocaleMask,
- bool bLoadBlocksWithFlags80,
- BYTE HighestBitValue)
+ BYTE bOverrideArchive,
+ BYTE bAudioLocale)
{
CASC_ROOT_BLOCK RootBlock;
@@ -233,12 +245,12 @@ static int ParseWowRootFileInternal(
if(RootBlock.pLocaleBlockHdr->Flags & 0x100)
continue;
- // WoW.exe (build 19116): Entries with flag 0x80 set are skipped if arg_4 is set to FALSE (which is by default)
- if((RootBlock.pLocaleBlockHdr->Flags & 0x80) && bLoadBlocksWithFlags80 == 0)
+ // WoW.exe (build 19116): Entries with flag 0x80 set are skipped if overrideArchive CVAR is set to FALSE (which is by default in non-chinese clients)
+ if((RootBlock.pLocaleBlockHdr->Flags & 0x80) && bOverrideArchive == 0)
continue;
// WoW.exe (build 19116): Entries with (flags >> 0x1F) not equal to arg_8 are skipped
- if((RootBlock.pLocaleBlockHdr->Flags >> 0x1F) != HighestBitValue)
+ if((RootBlock.pLocaleBlockHdr->Flags >> 0x1F) != bAudioLocale)
continue;
// WoW.exe (build 19116): Locales other than defined mask are skipped too
@@ -254,25 +266,25 @@ static int ParseWowRootFileInternal(
/*
// Code from WoW.exe
- if(dwLocaleMask == CASC_LOCALE_DUAL_LANG)
+ if(dwRegion == CASC_REGION_EU)
{
// Is this english version of WoW?
- if(arg_4 == CASC_LOCALE_BIT_ENUS)
+ if(dwLocale == CASC_LOCALE_BIT_ENUS)
{
- LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENGB, false, HighestBitValue);
- LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENUS, false, HighestBitValue);
+ LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENGB, bOverrideArchive, bAudioLocale);
+ LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_ENUS, bOverrideArchive, bAudioLocale);
return ERROR_SUCCESS;
}
// Is this portuguese version of WoW?
- if(arg_4 == CASC_LOCALE_BIT_PTBR)
+ if(dwLocale == CASC_LOCALE_BIT_PTBR)
{
- LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTPT, false, HighestBitValue);
- LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTBR, false, HighestBitValue);
+ LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTPT, bOverrideArchive, bAudioLocale);
+ LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, CASC_LOCALE_PTBR, bOverrideArchive, bAudioLocale);
}
}
-
- LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, (1 << arg_4), false, HighestBitValue);
+ else
+ LoadWowRootFileLocales(hs, pbRootFile, cbRootFile, (1 << dwLocale), false, bAudioLocale);
*/
static int ParseWowRootFile2(
@@ -281,17 +293,17 @@ static int ParseWowRootFile2(
LPBYTE pbRootFile,
LPBYTE pbRootFileEnd,
DWORD dwLocaleMask,
- BYTE HighestBitValue)
+ BYTE bAudioLocale)
{
// Load the locale as-is
- ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, dwLocaleMask, false, HighestBitValue);
+ ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, dwLocaleMask, false, bAudioLocale);
// If we wanted enGB, we also load enUS for the missing files
if(dwLocaleMask == CASC_LOCALE_ENGB)
- ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_ENUS, false, HighestBitValue);
+ ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_ENUS, false, bAudioLocale);
if(dwLocaleMask == CASC_LOCALE_PTPT)
- ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_PTBR, false, HighestBitValue);
+ ParseWowRootFileInternal(pRootHandler, pfnParseRoot, pbRootFile, pbRootFileEnd, CASC_LOCALE_PTBR, false, bAudioLocale);
return ERROR_SUCCESS;
}
@@ -324,10 +336,15 @@ static int WowHandler_Insert(
if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax)
return ERROR_NOT_ENOUGH_MEMORY;
+ if (pRootHandler->FileDataIdLookupTable.ItemCount >= pRootHandler->FileDataIdLookupTable.ItemCountMax)
+ return ERROR_NOT_ENOUGH_MEMORY;
+
// Insert the item to the linear file list
pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1);
if(pFileEntry != NULL)
{
+ Array_Insert(&pRootHandler->FileDataIdLookupTable, &pFileEntry, 1);
+
// Get the file data ID of the previous item (0 if this is the first one)
if(pRootHandler->FileTable.ItemCount > 1)
FileDataId = pFileEntry[-1].FileDataId;
@@ -388,7 +405,7 @@ static LPBYTE WowHandler_GetKey(TRootHandler_WoW6 * pRootHandler, const char * s
ConvertStringToBinary(szFileName + 4, 8, FileDataIdLE);
FileDataId = ConvertBytesToInteger_4(FileDataIdLE);
- pFileEntry = FindRootEntry(pRootHandler->FileTable, FileDataId);
+ pFileEntry = FindRootEntry(pRootHandler->FileDataIdLookupTable, FileDataId);
}
else
{
@@ -411,6 +428,7 @@ static void WowHandler_Close(TRootHandler_WoW6 * pRootHandler)
if(pRootHandler != NULL)
{
Array_Free(&pRootHandler->FileTable);
+ Array_Free(&pRootHandler->FileDataIdLookupTable);
Map_Free(pRootHandler->pRootMap);
CASC_FREE(pRootHandler);
}
@@ -520,6 +538,11 @@ int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFil
if(nError != ERROR_SUCCESS)
return nError;
+ // Create sorted table that will contain all root items to lookup by FileDataId
+ nError = Array_Create(&pRootHandler->FileDataIdLookupTable, PCASC_FILE_ENTRY, pRootHandler->dwTotalFileCount);
+ if (nError != ERROR_SUCCESS)
+ return nError;
+
// Create the map of FileHash ->FileEntry
pRootHandler->pRootMap = Map_Create(pRootHandler->dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash));
if(pRootHandler->pRootMap == NULL)
@@ -527,5 +550,8 @@ int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFil
// Parse the root file again and insert all files to the map
ParseWowRootFile(pRootHandler, ParseRoot_AddRootEntries, pbRootFile, pbRootFileEnd, dwLocaleMask);
+
+ // Sort entries by FileDataId for searches
+ qsort_pointer_array((void**)pRootHandler->FileDataIdLookupTable.ItemArray, pRootHandler->FileDataIdLookupTable.ItemCount, &FileDataIdCompare, NULL);
return ERROR_SUCCESS;
}