[Localization] Move patch here
This commit is contained in:
parent
f32ca8cf71
commit
d90d8985ff
@ -249,6 +249,147 @@ namespace Components
|
|||||||
Localization::Set("IW4X_CREDITS", credits);
|
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;
|
||||||
|
strncpy_s(szTokenBuf, pszTokenStart, pszIn - pszTokenStart);
|
||||||
|
if (bLocOn)
|
||||||
|
{
|
||||||
|
if (!Game::SEH_GetLocalizedTokenReference(szTokenBuf, szTokenBuf, pszMessageType, errType))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
iTokenLen = &szTokenBuf[std::strlen(szTokenBuf) + 1] - &szTokenBuf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTokenLen + iLen >= szStringSize)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
strncpy_s(&pszString[iLen], szStringSize - iLen, szTokenBuf, sizeof(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)
|
||||||
|
{
|
||||||
|
strncpy_s(szInsertBuf, &pszString[i + 3], szStringSize - (i + 3));
|
||||||
|
pszString[i] = 0;
|
||||||
|
++insertIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy_s(&pszString[i], szStringSize - i, szTokenBuf, sizeof(szTokenBuf));
|
||||||
|
|
||||||
|
if ((iTokenLen + i) < szStringSize)
|
||||||
|
{
|
||||||
|
strncpy_s(&pszString[iTokenLen + i], szStringSize - (iTokenLen + i), szInsertBuf, sizeof(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::Localization()
|
||||||
{
|
{
|
||||||
Localization::SetCredits();
|
Localization::SetCredits();
|
||||||
@ -279,6 +420,9 @@ namespace Components
|
|||||||
// Overwrite SetString
|
// Overwrite SetString
|
||||||
Utils::Hook(0x4CE5EE, Localization::SetStringStub, HOOK_CALL).install()->quick();
|
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");
|
Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::DVAR_NONE, "Use localization strings");
|
||||||
|
|
||||||
// Generate localized entries for custom classes above 10
|
// Generate localized entries for custom classes above 10
|
||||||
|
@ -24,5 +24,7 @@ namespace Components
|
|||||||
static void LoadLanguageStrings();
|
static void LoadLanguageStrings();
|
||||||
static void SELoadLanguageStub();
|
static void SELoadLanguageStub();
|
||||||
static void SetCredits();
|
static void SetCredits();
|
||||||
|
|
||||||
|
static const char* SEH_LocalizeTextMessageStub(const char* pszInputBuffer, const char* pszMessageType, Game::msgLocErrType_t errType);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,11 +120,6 @@ namespace Components
|
|||||||
InterlockedIncrement(&Game::deferredQueue->send);
|
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()
|
Security::Security()
|
||||||
{
|
{
|
||||||
// Exploit fixes
|
// Exploit fixes
|
||||||
@ -152,8 +147,5 @@ namespace Components
|
|||||||
|
|
||||||
// Fix packets causing buffer overflow
|
// Fix packets causing buffer overflow
|
||||||
Utils::Hook(0x6267E3, NET_DeferPacketToClientStub, HOOK_CALL).install()->quick();
|
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,5 @@ namespace Components
|
|||||||
static void G_LogPrintfStub(const char* fmt);
|
static void G_LogPrintfStub(const char* fmt);
|
||||||
|
|
||||||
static void NET_DeferPacketToClientStub(Game::netadr_t* net_from, Game::msg_t* net_message);
|
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);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,9 @@ namespace Game
|
|||||||
const dvar_t** ui_mapname = reinterpret_cast<const dvar_t**>(0x62E279C);
|
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** 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)
|
__declspec(naked) void Dvar_SetVariant(dvar_t*, DvarValue, DvarSetSource)
|
||||||
{
|
{
|
||||||
static DWORD Dvar_SetVariant_t = 0x647400;
|
static DWORD Dvar_SetVariant_t = 0x647400;
|
||||||
|
@ -115,6 +115,9 @@ namespace Game
|
|||||||
extern const dvar_t** ui_mapname;
|
extern const dvar_t** ui_mapname;
|
||||||
extern const dvar_t** ui_netGameType;
|
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_SetVariant(dvar_t* var, DvarValue value, DvarSetSource source);
|
||||||
extern void Dvar_SetFromStringFromSource(const dvar_t* dvar, const char* string, DvarSetSource source);
|
extern void Dvar_SetFromStringFromSource(const dvar_t* dvar, const char* string, DvarSetSource source);
|
||||||
}
|
}
|
||||||
|
@ -1208,5 +1208,27 @@ namespace Game
|
|||||||
ret
|
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)
|
#pragma optimize("", on)
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ namespace Game
|
|||||||
typedef unsigned int(*SEH_ReadCharFromString_t)(const char** text, int* isTrailingPunctuation);
|
typedef unsigned int(*SEH_ReadCharFromString_t)(const char** text, int* isTrailingPunctuation);
|
||||||
extern SEH_ReadCharFromString_t SEH_ReadCharFromString;
|
extern SEH_ReadCharFromString_t SEH_ReadCharFromString;
|
||||||
|
|
||||||
typedef int (*SEH_GetCurrentLanguage_t)();
|
typedef int(*SEH_GetCurrentLanguage_t)();
|
||||||
extern SEH_GetCurrentLanguage_t SEH_GetCurrentLanguage;
|
extern SEH_GetCurrentLanguage_t SEH_GetCurrentLanguage;
|
||||||
|
|
||||||
typedef const char*(*SL_ConvertToString_t)(scr_string_t stringValue);
|
typedef const char*(*SL_ConvertToString_t)(scr_string_t stringValue);
|
||||||
@ -832,4 +832,6 @@ namespace Game
|
|||||||
void AimAssist_UpdateAdsLerp(const AimInput* input);
|
void AimAssist_UpdateAdsLerp(const AimInput* input);
|
||||||
|
|
||||||
bool ApplyTokenToField(unsigned int fieldNum, const char* token, visionSetVars_t* settings);
|
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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user