Merge pull request #470 from diamante0018/brober-fix

[Localization] Move patch here
This commit is contained in:
Dss0 2022-09-03 21:26:16 +02:00 committed by GitHub
commit fce57a359a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 215 additions and 11 deletions

View File

@ -249,6 +249,144 @@ namespace Components
Localization::Set("IW4X_CREDITS", credits);
}
const char* Localization::SEH_LocalizeTextMessageStub(const char* pszInputBuffer, const char* pszMessageType, Game::msgLocErrType_t errType)
{
constexpr auto szStringCount = 10;
constexpr auto szStringSize = 1024;
char szInsertBuf[szStringSize];
char szTokenBuf[szStringSize];
static thread_local int iCurrString;
static thread_local char szStrings[szStringCount][szStringSize];
iCurrString = (iCurrString + 1) % szStringCount;
std::memset(szStrings[iCurrString], 0, sizeof(szStrings[0]));
auto* pszString = szStrings[iCurrString];
auto iLen = 0;
auto bLocOn = 1;
auto bInsertEnabled = 1;
auto iInsertLevel = 0;
auto insertIndex = 1;
auto bLocSkipped = 0;
const auto* pszTokenStart = pszInputBuffer;
const auto* pszIn = pszInputBuffer;
auto i = 0;
while (*pszTokenStart)
{
if (*pszIn && *pszIn != '\x14' && *pszIn != '\x15' && *pszIn != '\x16')
{
++pszIn;
continue;
}
if (pszIn > pszTokenStart)
{
auto iTokenLen = pszIn - pszTokenStart;
Game::I_strncpyz_s(szTokenBuf, sizeof(szTokenBuf), pszTokenStart, pszIn - pszTokenStart);
if (bLocOn)
{
if (!Game::SEH_GetLocalizedTokenReference(szTokenBuf, szTokenBuf, pszMessageType, errType))
{
return nullptr;
}
iTokenLen = std::strlen(szTokenBuf);
}
if (iTokenLen + iLen >= szStringSize)
{
Game::Com_Printf(Game::CON_CHANNEL_SYSTEM, "%s too long when translated\n", pszMessageType);
return nullptr;
}
for (i = 0; i < iTokenLen - 2; ++i)
{
if (!std::strncmp(&szTokenBuf[i], "&&", 2) && std::isdigit(szTokenBuf[i + 2]))
{
if (bInsertEnabled)
{
++iInsertLevel;
}
else
{
szTokenBuf[i] = '\x16';
bLocSkipped = 1;
}
}
}
if (iInsertLevel <= 0 || iLen <= 0)
{
Game::I_strcpy(&pszString[iLen], szStringSize - iLen, szTokenBuf);
}
else
{
for (i = 0; i < iLen - 2; ++i)
{
if (!std::strncmp(&pszString[i], "&&", 2) && std::isdigit(pszString[i + 2]))
{
const auto digit = pszString[i + 2] - 48;
if (!digit)
{
Game::Com_Printf(Game::CON_CHANNEL_SYSTEM, "%s cannot have &&0 as conversion format: \"%s\"\n", pszMessageType, pszInputBuffer);
}
if (digit == insertIndex)
{
Game::I_strcpy(szInsertBuf, sizeof(szInsertBuf), &pszString[i + 3]);
pszString[i] = 0;
++insertIndex;
break;
}
}
}
Game::I_strcpy(&pszString[i], szStringSize - i, szTokenBuf);
Game::I_strcpy(&pszString[iTokenLen + i], szStringSize - (iTokenLen + i), szInsertBuf);
iLen -= 3;
--iInsertLevel;
}
iLen += iTokenLen;
}
bInsertEnabled = 1;
if (*pszIn == '\x14')
{
bLocOn = 1;
++pszIn;
}
else if (*pszIn == '\x15')
{
bLocOn = 0;
++pszIn;
}
if (*pszIn == '\x16')
{
bInsertEnabled = 0;
++pszIn;
}
pszTokenStart = pszIn;
}
if (bLocSkipped)
{
for (i = 0; i < iLen; ++i)
{
if (pszString[i] == '\x16')
{
pszString[i] = '%';
}
}
}
return pszString;
}
Localization::Localization()
{
Localization::SetCredits();
@ -279,6 +417,9 @@ namespace Components
// Overwrite SetString
Utils::Hook(0x4CE5EE, Localization::SetStringStub, HOOK_CALL).install()->quick();
Utils::Hook(0x49D4A0, Localization::SEH_LocalizeTextMessageStub, HOOK_JUMP).install()->quick();
Utils::Hook::Nop(0x49D4A5, 1);
Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::DVAR_NONE, "Use localization strings");
// Generate localized entries for custom classes above 10

View File

@ -24,5 +24,7 @@ namespace Components
static void LoadLanguageStrings();
static void SELoadLanguageStub();
static void SetCredits();
static const char* SEH_LocalizeTextMessageStub(const char* pszInputBuffer, const char* pszMessageType, Game::msgLocErrType_t errType);
};
}

View File

@ -120,11 +120,6 @@ namespace Components
InterlockedIncrement(&Game::deferredQueue->send);
}
void Security::SEH_LocalizeTextMessageStub(char* dest, const char* src, [[maybe_unused]] int destsize)
{
Game::I_strncpyz(dest, src, 1024);
}
Security::Security()
{
// Exploit fixes
@ -152,8 +147,5 @@ namespace Components
// Fix packets causing buffer overflow
Utils::Hook(0x6267E3, NET_DeferPacketToClientStub, HOOK_CALL).install()->quick();
// Use the correct size for the destination buffer
Utils::Hook(0x49D548, SEH_LocalizeTextMessageStub, HOOK_CALL).install()->quick();
}
}

View File

@ -22,7 +22,5 @@ namespace Components
static void G_LogPrintfStub(const char* fmt);
static void NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message);
static void SEH_LocalizeTextMessageStub(char* dest, const char* src, int destsize);
};
}

View File

@ -59,6 +59,9 @@ namespace Game
const dvar_t** ui_mapname = reinterpret_cast<const dvar_t**>(0x62E279C);
const dvar_t** ui_netGameType = reinterpret_cast<const dvar_t**>(0x62E2838);
const dvar_t** loc_warnings = reinterpret_cast<const dvar_t**>(0x62C8700);
const dvar_t** loc_warningsAsErrors = reinterpret_cast<const dvar_t**>(0x62C86FC);
__declspec(naked) void Dvar_SetVariant(dvar_t*, DvarValue, DvarSetSource)
{
static DWORD Dvar_SetVariant_t = 0x647400;

View File

@ -115,6 +115,9 @@ namespace Game
extern const dvar_t** ui_mapname;
extern const dvar_t** ui_netGameType;
extern const dvar_t** loc_warnings;
extern const dvar_t** loc_warningsAsErrors;
extern void Dvar_SetVariant(dvar_t* var, DvarValue value, DvarSetSource source);
extern void Dvar_SetFromStringFromSource(const dvar_t* dvar, const char* string, DvarSetSource source);
}

View File

@ -805,6 +805,44 @@ namespace Game
}
}
void I_strncpyz_s(char* dest, std::size_t destsize, const char* src, std::size_t count)
{
if (!destsize && !dest)
{
return;
}
if (!src || !count)
{
*dest = '\0';
}
else
{
const auto* p = reinterpret_cast<const unsigned char*>(src - 1);
auto* q = reinterpret_cast<unsigned char*>(dest - 1);
auto n = count + 1;
auto s = count;
if (destsize <= count)
{
n = destsize + 1;
s = destsize - 1;
}
do
{
if (!--n)
{
dest[s] = '\0';
return;
}
*++q = *++p;
} while (*q);
}
}
void I_strcpy(char* dest, std::size_t destsize, const char* src)
{
I_strncpyz_s(dest, destsize, src, destsize);
}
#pragma optimize("", off)
__declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/)
{
@ -1208,5 +1246,27 @@ namespace Game
ret
}
}
int SEH_GetLocalizedTokenReference(char* token, const char* reference, const char* messageType, msgLocErrType_t errType)
{
static DWORD SEH_GetLocalizedTokenReference_t = 0x629BB0;
auto answer = 0;
__asm
{
pushad
mov esi, reference
mov edi, messageType
mov ebx, errType
push token
call SEH_GetLocalizedTokenReference_t
add esp, 0x4
mov answer, eax
popad
}
return answer;
}
#pragma optimize("", on)
}

View File

@ -425,7 +425,7 @@ namespace Game
typedef unsigned int(*SEH_ReadCharFromString_t)(const char** text, int* isTrailingPunctuation);
extern SEH_ReadCharFromString_t SEH_ReadCharFromString;
typedef int (*SEH_GetCurrentLanguage_t)();
typedef int(*SEH_GetCurrentLanguage_t)();
extern SEH_GetCurrentLanguage_t SEH_GetCurrentLanguage;
typedef const char*(*SL_ConvertToString_t)(scr_string_t stringValue);
@ -832,4 +832,9 @@ namespace Game
void AimAssist_UpdateAdsLerp(const AimInput* input);
bool ApplyTokenToField(unsigned int fieldNum, const char* token, visionSetVars_t* settings);
int SEH_GetLocalizedTokenReference(char* token, const char* reference, const char* messageType, msgLocErrType_t errType);
void I_strncpyz_s(char* dest, std::size_t destsize, const char* src, std::size_t count);
void I_strcpy(char* dest, std::size_t destsize, const char* src);
}