aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-07-13 00:12:42 +0200
committerShauren <shauren.trinity@gmail.com>2023-07-13 00:12:42 +0200
commit26f37152cca6be50a0b716a4969245c6f9197121 (patch)
tree318baecf0c9c74a46047626bdd8da61bcd164d97 /dep/CascLib
parentb6a0fa3518ad920946c60bb205277e8104fd1cf0 (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@a27d2b3b9ccb326768e57b4cc7c49d15a0da9e0c
Closes #29102 Closes #29132
Diffstat (limited to 'dep/CascLib')
-rw-r--r--dep/CascLib/src/CascCommon.h2
-rw-r--r--dep/CascLib/src/CascFiles.cpp53
-rw-r--r--dep/CascLib/src/CascLib.h3
-rw-r--r--dep/CascLib/src/CascOpenStorage.cpp15
-rw-r--r--dep/CascLib/src/CascReadFile.cpp9
-rw-r--r--dep/CascLib/src/CascRootFile_WoW.cpp29
6 files changed, 53 insertions, 58 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;
}
}