diff options
author | Shauren <shauren.trinity@gmail.com> | 2016-07-22 17:33:43 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2016-07-22 17:33:43 +0200 |
commit | ed079553728b7d4f927890a6e521139f0bde7687 (patch) | |
tree | 5303d33a2cd74d1a6e021a73decdd38eed0a594f | |
parent | 4587b5d88082d2c6416fafaa2f5b9f5f15038520 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@2702efeae5f63c64f6d883cfcc219daa2fb06108
-rw-r--r-- | dep/CascLib/src/CascRootFile_WoW6.cpp | 80 | ||||
-rw-r--r-- | dep/PackageList.txt | 2 |
2 files changed, 54 insertions, 28 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; } diff --git a/dep/PackageList.txt b/dep/PackageList.txt index ebbe0a949b1..8083bea9347 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -58,7 +58,7 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014) https://github.com/ladislav-zezula/CascLib - Version: fe97d8cf7fd2deb08db7e8c14990a6420a3b47b4 + Version: 2702efeae5f63c64f6d883cfcc219daa2fb06108 rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/) https://github.com/miloyip/rapidjson |