From 8005993da0c3dae68b6b91ef38dacd688f50aa67 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Tue, 7 May 2024 16:05:57 +0200 Subject: [PATCH] Ebisu: allow overriding global game language setting The code originally fetches available and selected languages from Origin/EADesktop. The issue however is that its hard to change the language through the Origin/EADesktop app. The second issue is that the languages returned by Origin/EADesktop isn't necvesarily supported by our version of the game, for example, the original implementation of EbisuSDK_GetLanguage() also returns ar_SA, which is supported by the retail version of the game, but our version doesn't have the code to render this language. The code has been rewritten to allow the user to easily change the language using the command line '-language' parameter. The miles code has also been slightly adjusted to fetch the language directly from HEbisuSDK_GetLanguage() instead of miles_language since otherwise we would still error out in engine code as miles_language will be out of sync. --- r5dev/codecs/Miles/miles_impl.cpp | 8 +++--- r5dev/ebisusdk/EbisuSDK.cpp | 42 +++++++++++++++++++++++++++++++ r5dev/ebisusdk/EbisuSDK.h | 7 +++++- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/r5dev/codecs/Miles/miles_impl.cpp b/r5dev/codecs/Miles/miles_impl.cpp index 147b34cf..01d90704 100644 --- a/r5dev/codecs/Miles/miles_impl.cpp +++ b/r5dev/codecs/Miles/miles_impl.cpp @@ -1,9 +1,10 @@ #include "core/stdafx.h" -#include "miles_impl.h" #include "tier0/fasttimer.h" #include "tier0/commandline.h" #include "tier1/cvar.h" #include "filesystem/filesystem.h" +#include "ebisusdk/EbisuSDK.h" +#include "miles_impl.h" static ConVar miles_debug("miles_debug", "0", FCVAR_DEVELOPMENTONLY, "Enables debug prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); static ConVar miles_warnings("miles_warnings", "0", FCVAR_RELEASE, "Enables warning prints for the Miles Sound System", "1 = print; 0 (zero) = no print"); @@ -25,10 +26,7 @@ void AIL_LogFunc(int64_t nLogLevel, const char* pszMessage) //----------------------------------------------------------------------------- bool Miles_Initialize() { - const char* pszLanguage = miles_language->GetString(); - if (!pszLanguage[0]) - pszLanguage = MILES_DEFAULT_LANGUAGE; - + const char* pszLanguage = HEbisuSDK_GetLanguage(); const bool isDefaultLanguage = _stricmp(pszLanguage, MILES_DEFAULT_LANGUAGE) == 0; if (!isDefaultLanguage) diff --git a/r5dev/ebisusdk/EbisuSDK.cpp b/r5dev/ebisusdk/EbisuSDK.cpp index a87115a5..a082356f 100644 --- a/r5dev/ebisusdk/EbisuSDK.cpp +++ b/r5dev/ebisusdk/EbisuSDK.cpp @@ -1,4 +1,5 @@ #include "core/stdafx.h" +#include "tier0/commandline.h" #include "ebisusdk/EbisuSDK.h" #include "engine/server/sv_main.h" @@ -15,6 +16,42 @@ void HEbisuSDK_Init() } } +//----------------------------------------------------------------------------- +// Purpose: returns the currently set language +//----------------------------------------------------------------------------- +const char* HEbisuSDK_GetLanguage() +{ + static bool initialized = false; + static char languageName[32]; + + if (initialized) + { + return languageName; + } + + const char* value = nullptr; + bool useDefault = true; + + if (CommandLine()->CheckParm("-language", &value)) + { + if (V_LocaleNameExists(value)) + { + strncpy(languageName, value, sizeof(languageName)); + useDefault = false; + } + } + + if (useDefault) + { + strncpy(languageName, g_LanguageNames[0], sizeof(languageName)); + } + + languageName[sizeof(languageName) - 1] = '\0'; + initialized = true; + + return languageName; +} + //----------------------------------------------------------------------------- // Purpose: checks if the EbisuSDK is initialized // Output : true on success, false on failure @@ -57,3 +94,8 @@ bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen) size_t pos = strspn(pszName, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"); return pszName[pos] == '\0'; } + +void VEbisuSDK::Detour(const bool bAttach) const +{ + DetourSetup(&EbisuSDK_GetLanguage, &HEbisuSDK_GetLanguage, bAttach); +} diff --git a/r5dev/ebisusdk/EbisuSDK.h b/r5dev/ebisusdk/EbisuSDK.h index 894f8bac..caf1f16c 100644 --- a/r5dev/ebisusdk/EbisuSDK.h +++ b/r5dev/ebisusdk/EbisuSDK.h @@ -3,6 +3,7 @@ inline void(*EbisuSDK_Tier0_Init)(void); inline void(*EbisuSDK_CVar_Init)(void); inline void(*EbisuSDK_SetState)(void); +inline const char*(*EbisuSDK_GetLanguage)(void); inline uint64_t* g_NucleusID = nullptr; inline char* g_NucleusToken = nullptr; /*SIZE = 1024*/ @@ -13,6 +14,8 @@ inline bool* g_EbisuProfileInit = nullptr; /////////////////////////////////////////////////////////////////////////////// void HEbisuSDK_Init(); +const char* HEbisuSDK_GetLanguage(); + bool IsOriginInitialized(); bool IsValidPersonaName(const char* pszName, int nMinLen, int nMaxLen); @@ -24,6 +27,7 @@ class VEbisuSDK : public IDetour LogFunAdr("EbisuSDK_Tier0_Init", EbisuSDK_Tier0_Init); LogFunAdr("EbisuSDK_CVar_Init", EbisuSDK_CVar_Init); LogFunAdr("EbisuSDK_SetState", EbisuSDK_SetState); + LogFunAdr("EbisuSDK_SetState", EbisuSDK_GetLanguage); LogVarAdr("g_NucleusID", g_NucleusID); LogVarAdr("g_NucleusToken", g_NucleusToken); LogVarAdr("g_OriginAuthCode", g_OriginAuthCode); @@ -36,6 +40,7 @@ class VEbisuSDK : public IDetour g_GameDll.FindPatternSIMD("48 83 EC 28 80 3D ?? ?? ?? ?? ?? 0F 85 ?? 02 ?? ?? 48 89 5C 24 20").GetPtr(EbisuSDK_Tier0_Init); g_GameDll.FindPatternSIMD("40 57 48 83 EC 40 83 3D").GetPtr(EbisuSDK_CVar_Init); g_GameDll.FindPatternSIMD("48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 74 5B").GetPtr(EbisuSDK_SetState); + g_GameDll.FindPatternSIMD("48 8B C4 48 81 EC ?? ?? ?? ?? 80 3D ?? ?? ?? ?? ?? 0F 85 ?? ?? ?? ??").GetPtr(EbisuSDK_GetLanguage); } virtual void GetVar(void) const { @@ -47,6 +52,6 @@ class VEbisuSDK : public IDetour g_EbisuSDKInit = CMemory(EbisuSDK_Tier0_Init).Offset(0x0).FindPatternSelf("80 3D", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast(); } virtual void GetCon(void) const { } - virtual void Detour(const bool bAttach) const { } + virtual void Detour(const bool bAttach) const; }; ///////////////////////////////////////////////////////////////////////////////