diff options
author | Shauren <shauren.trinity@gmail.com> | 2023-07-13 00:12:42 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2023-07-13 00:12:42 +0200 |
commit | 26f37152cca6be50a0b716a4969245c6f9197121 (patch) | |
tree | 318baecf0c9c74a46047626bdd8da61bcd164d97 | |
parent | b6a0fa3518ad920946c60bb205277e8104fd1cf0 (diff) |
Dep/CascLib: Update to ladislav-zezula/CascLib@a27d2b3b9ccb326768e57b4cc7c49d15a0da9e0c
Closes #29102
Closes #29132
-rw-r--r-- | dep/CascLib/src/CascCommon.h | 2 | ||||
-rw-r--r-- | dep/CascLib/src/CascFiles.cpp | 53 | ||||
-rw-r--r-- | dep/CascLib/src/CascLib.h | 3 | ||||
-rw-r--r-- | dep/CascLib/src/CascOpenStorage.cpp | 15 | ||||
-rw-r--r-- | dep/CascLib/src/CascReadFile.cpp | 9 | ||||
-rw-r--r-- | dep/CascLib/src/CascRootFile_WoW.cpp | 29 | ||||
-rw-r--r-- | dep/PackageList.txt | 2 |
7 files changed, 54 insertions, 59 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h index b47674f1544..fb4a3ee88c8 100644 --- a/dep/CascLib/src/CascCommon.h +++ b/dep/CascLib/src/CascCommon.h @@ -296,7 +296,7 @@ struct TCascStorage LPTSTR szCdnPath; // Remote CDN sub path for the product LPSTR szRegion; // Product region. Only when "versions" is used as storage root file LPSTR szBuildKey; // Product build key, aka MD5 of the build file - DWORD dwDefaultLocale; // Default locale, read from ".build.info" + DWORD dwDefaultLocale; // Mask of installed localles DWORD dwBuildNumber; // Product build number DWORD dwRefCount; // Number of references DWORD dwFeatures; // List of CASC features. See CASC_FEATURE_XXX diff --git a/dep/CascLib/src/CascFiles.cpp b/dep/CascLib/src/CascFiles.cpp index 550b558f7da..90544cb2031 100644 --- a/dep/CascLib/src/CascFiles.cpp +++ b/dep/CascLib/src/CascFiles.cpp @@ -274,9 +274,8 @@ static DWORD GetLocaleValue(LPCSTR szTag) case 0x64654445: return CASC_LOCALE_DEDE; case 0x72755255: return CASC_LOCALE_RURU; case 0x69744954: return CASC_LOCALE_ITIT; + default: return CASC_LOCALE_NONE; } - - return 0; } static bool CheckConfigFileVariable( @@ -579,29 +578,41 @@ static DWORD GetDefaultCdnPath(TCascStorage * hs, const CASC_CSV_COLUMN & Column return ERROR_SUCCESS; } -static DWORD GetDefaultLocaleMask(TCascStorage * hs, const CASC_CSV_COLUMN & Column) +static DWORD GetDefaultLocaleByRegion(LPCSTR szRegion) +{ + #define CASC_REGION_INT(hi, lo) (((DWORD)(hi) << 0x08) | lo) + + // Setup the default locale + switch(CASC_REGION_INT(szRegion[0], szRegion[1])) + { + case CASC_REGION_INT('u', 's'): return CASC_LOCALE_ENUS; + case CASC_REGION_INT('e', 'u'): return CASC_LOCALE_ENGB; + case CASC_REGION_INT('c', 'n'): return CASC_LOCALE_ZHCN; + case CASC_REGION_INT('k', 'r'): return CASC_LOCALE_KOKR; + case CASC_REGION_INT('t', 'w'): return CASC_LOCALE_ZHTW; +// case CASC_REGION_INT('s', 'g'): return CASC_LOCALE_????; + default: return CASC_LOCALE_ENUS; + } +} + +static DWORD GetDefaultLocaleMask(const CASC_CSV_COLUMN & Column) { LPCSTR szTagEnd = Column.szValue + Column.nLength - 4; - LPCSTR szTagPtr = Column.szValue; + LPCSTR szTagPtr; + DWORD dwLocaleValue; DWORD dwLocaleMask = 0; - while(szTagPtr < szTagEnd) + // Go through the whole tag string + for(szTagPtr = Column.szValue; szTagPtr <= szTagEnd; szTagPtr++) { - DWORD dwLocaleValue = GetLocaleValue(szTagPtr); - - if(dwLocaleValue != 0) + // Try to recognize the 4-char locale code + if((dwLocaleValue = GetLocaleValue(szTagPtr)) != CASC_LOCALE_NONE) { - dwLocaleMask = dwLocaleMask | GetLocaleValue(szTagPtr); - szTagPtr += 4; - } - else - { - szTagPtr++; + dwLocaleMask |= dwLocaleValue; + szTagPtr += 3; // Will be moved by 1 more at the end of the loop } } - - hs->dwDefaultLocale = dwLocaleMask; - return ERROR_SUCCESS; + return dwLocaleMask; } static DWORD ParseFile_BuildInfo(TCascStorage * hs, CASC_CSV & Csv) @@ -703,7 +714,7 @@ static DWORD ParseFile_BuildInfo(TCascStorage * hs, CASC_CSV & Csv) return dwErrCode; // If we found tags, we can extract language build from it - GetDefaultLocaleMask(hs, Csv[nSelected]["Tags!STRING:0"]); + hs->dwDefaultLocale = GetDefaultLocaleMask(Csv[nSelected]["Tags!STRING:0"]); // Get the CDN servers and hosts if(hs->dwFeatures & CASC_FEATURE_ONLINE) @@ -734,6 +745,9 @@ static DWORD ParseRegionLine_Versions(TCascStorage * hs, CASC_CSV & Csv, size_t if(hs->szRegion == NULL) hs->szRegion = CascNewStr(Csv[nLine]["Region!STRING:0"].szValue); + // Get the default locale mask based on the region + hs->dwDefaultLocale = GetDefaultLocaleByRegion(hs->szRegion); + // Extract the CDN build key dwErrCode = LoadQueryKey(Csv[nLine]["BuildConfig!HEX:16"], hs->CdnBuildKey); if(dwErrCode != ERROR_SUCCESS) @@ -783,6 +797,9 @@ static DWORD ParseFile_BuildDb(TCascStorage * hs, CASC_CSV & Csv) if(dwErrCode != ERROR_SUCCESS) return dwErrCode; + // Extract tags + hs->dwDefaultLocale = GetDefaultLocaleMask(Csv[CSV_ZERO][2]); + // Verify all variables return (hs->CdnBuildKey.pbData != NULL && hs->CdnConfigKey.pbData != NULL) ? ERROR_SUCCESS : ERROR_BAD_FORMAT; } diff --git a/dep/CascLib/src/CascLib.h b/dep/CascLib/src/CascLib.h index 01e9c314fd0..3b97c18544c 100644 --- a/dep/CascLib/src/CascLib.h +++ b/dep/CascLib/src/CascLib.h @@ -164,6 +164,9 @@ extern "C" { // Default format string for the file ID #define CASC_FILEID_FORMAT "FILE%08X.dat" +// Separator char for path-product delimiter +#define CASC_PARAM_SEPARATOR '*' + //----------------------------------------------------------------------------- // Structures diff --git a/dep/CascLib/src/CascOpenStorage.cpp b/dep/CascLib/src/CascOpenStorage.cpp index 16f0c28da48..909c45c8f94 100644 --- a/dep/CascLib/src/CascOpenStorage.cpp +++ b/dep/CascLib/src/CascOpenStorage.cpp @@ -1072,7 +1072,7 @@ static bool GetStoragePathProduct(TCascStorage * hs, void * pvStorageInfo, size_ // Append the product code name, if any if(hs->szCodeName != NULL) { - *szBuffer++ = _T(':'); + *szBuffer++ = _T(CASC_PARAM_SEPARATOR); CascStrCopy(szBuffer, (szBufferEnd - szBuffer), hs->szCodeName); szBuffer += _tcslen(hs->szCodeName); } @@ -1080,7 +1080,7 @@ static bool GetStoragePathProduct(TCascStorage * hs, void * pvStorageInfo, size_ // Append the product region, if any if(hs->szRegion != NULL) { - *szBuffer++ = _T(':'); + *szBuffer++ = _T(CASC_PARAM_SEPARATOR); CascStrCopy(szBuffer, (szBufferEnd - szBuffer), hs->szRegion); } } @@ -1209,10 +1209,7 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs, L // Failing to select storage on them will lead to the first-in-order file in the list being loaded. // Example: WoW build 32144, file: DBFilesClient\Achievement.db2, file data ID: 1260179 // Locales: koKR frFR deDE zhCN esES zhTW enUS&enGB esMX ruRU itIT ptBT&ptPT (in order of appearance in the build manifest) - if(dwLocaleMask == 0) - { - dwLocaleMask = hs->dwDefaultLocale; - } + dwLocaleMask = (dwLocaleMask != 0) ? dwLocaleMask : hs->dwDefaultLocale; // Continue loading the manifest dwErrCode = LoadBuildManifest(hs, dwLocaleMask); @@ -1250,10 +1247,10 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs, L return dwErrCode; } -// Check for URL pattern. Note that the string may be terminated by ':' instead of '\0' +// Check for URL pattern. Note that the string may be terminated by CASC_PARAM_SEPARATOR instead of '\0' static bool IsUrl(LPCTSTR szString) { - while(szString[0] != 0 && szString[0] != '*') + while(szString[0] != 0 && szString[0] != CASC_PARAM_SEPARATOR) { // Check for "://" if(!_tcsncmp(szString, _T("://"), 3)) @@ -1276,7 +1273,7 @@ static LPTSTR GetNextParam(LPTSTR szParamsPtr, bool bMustBeUrl = false) if(szParamsPtr != NULL) { // Find the separator ("*") or end of string - if((szSeparator = _tcschr(szParamsPtr, _T('*'))) != NULL) + if((szSeparator = _tcschr(szParamsPtr, _T(CASC_PARAM_SEPARATOR))) != NULL) { // Check for URL pattern, if needed if(bMustBeUrl && IsUrl(szSeparator + 1) == false) diff --git a/dep/CascLib/src/CascReadFile.cpp b/dep/CascLib/src/CascReadFile.cpp index 3fd173b9bde..c2a209bb307 100644 --- a/dep/CascLib/src/CascReadFile.cpp +++ b/dep/CascLib/src/CascReadFile.cpp @@ -173,13 +173,16 @@ static DWORD ParseBlteHeader(PCASC_FILE_SPAN pFileSpan, PCASC_CKEY_ENTRY pCKeyEn CASCLIB_UNUSED(HeaderOffset); // On files within storage segments ("data.###"), there is BLTE_ENCODED_HEADER - // On local files, there is just PBLTE_HEADER + // On local files, there is just BLTE_HEADER if(ConvertBytesToInteger_4_LE(pBlteHeader->Signature) != BLTE_HEADER_SIGNATURE) { // There must be at least some bytes if(cbEncodedBuffer < FIELD_OFFSET(BLTE_ENCODED_HEADER, MustBe0F)) return ERROR_BAD_FORMAT; - if(pEncodedHeader->EncodedSize != pCKeyEntry->EncodedSize) + + // Note that some newer WoW builds have the entire encoded part zeroed + // Tested on WoW retail 50401, file DBFilesClient\\LoreTextPublic.db2 + if(pEncodedHeader->EncodedSize != 0 && pEncodedHeader->EncodedSize != pCKeyEntry->EncodedSize) return ERROR_BAD_FORMAT; #ifdef CASCLIB_DEBUG @@ -1039,7 +1042,7 @@ bool WINAPI CascSetFileFlags(HANDLE hFile, DWORD dwOpenFlags) } // Set "overcome encrypted" flag. Will apply on next CascReadFile - hf->bOvercomeEncrypted = (dwOpenFlags & CASC_OVERCOME_ENCRYPTED) != 0; + hf->bOvercomeEncrypted = (dwOpenFlags & CASC_OVERCOME_ENCRYPTED) ? true : false; return true; } diff --git a/dep/CascLib/src/CascRootFile_WoW.cpp b/dep/CascLib/src/CascRootFile_WoW.cpp index 85942c432ba..1253a311517 100644 --- a/dep/CascLib/src/CascRootFile_WoW.cpp +++ b/dep/CascLib/src/CascRootFile_WoW.cpp @@ -79,31 +79,6 @@ typedef struct _FILE_ROOT_GROUP } FILE_ROOT_GROUP, *PFILE_ROOT_GROUP; //----------------------------------------------------------------------------- -// Debug local stuff - -#if defined(_MSC_VER) && defined(CASCLIB_DEBUG) -static FILE * fp = NULL; -static bool bLogEntries = true; - -static void LogEntry(DWORD FileDataId, PCONTENT_KEY pCKey) -{ - if(fp && bLogEntries) - { - char szCKey[MD5_STRING_SIZE + 1]; - - if(FileDataId == 1260179) - { - bLogEntries = false; - __debugbreak(); - } - - StringFromBinary(pCKey->Value, MD5_HASH_SIZE, szCKey); - fprintf(fp, "File Data ID: %u, CKey = %s\n", FileDataId, szCKey); - } -} -#endif - -//----------------------------------------------------------------------------- // TRootHandler_WoW interface / implementation #define FTREE_FLAGS_WOW (FTREE_FLAG_USE_DATA_ID | FTREE_FLAG_USE_LOCALE_FLAGS | FTREE_FLAG_USE_CONTENT_FLAGS) @@ -123,11 +98,11 @@ struct TRootHandler_WoW : public TFileTreeRoot switch(RootFormat) { case RootFormatWoW6x: - dwFeatures |= CASC_FEATURE_ROOT_CKEY | CASC_FEATURE_FNAME_HASHES | CASC_FEATURE_FILE_DATA_IDS | CASC_FEATURE_LOCALE_FLAGS | CASC_FEATURE_CONTENT_FLAGS; + dwFeatures |= CASC_FEATURE_ROOT_CKEY | CASC_FEATURE_LOCALE_FLAGS | CASC_FEATURE_CONTENT_FLAGS | CASC_FEATURE_FNAME_HASHES; break; case RootFormatWoW82: - dwFeatures |= CASC_FEATURE_ROOT_CKEY | CASC_FEATURE_FNAME_HASHES_OPTIONAL | CASC_FEATURE_FILE_DATA_IDS | CASC_FEATURE_LOCALE_FLAGS | CASC_FEATURE_CONTENT_FLAGS; + dwFeatures |= CASC_FEATURE_ROOT_CKEY | CASC_FEATURE_LOCALE_FLAGS | CASC_FEATURE_CONTENT_FLAGS | CASC_FEATURE_FILE_DATA_IDS | CASC_FEATURE_FNAME_HASHES_OPTIONAL; break; } } diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 78accca859c..24b5cc884c1 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -63,7 +63,7 @@ catch2 CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014) https://github.com/ladislav-zezula/CascLib - Version: ebd79e8fd43279343c543a27fce620f6b1b53cb9 + Version: a27d2b3b9ccb326768e57b4cc7c49d15a0da9e0c rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/) https://github.com/Tencent/rapidjson |