aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorp0358 <p0358@users.noreply.github.com>2022-01-01 22:41:45 +0100
committerp0358 <p0358@users.noreply.github.com>2022-01-01 22:41:45 +0100
commit65c2e58a6a788a504c352d4ed34d43be17d0abdd (patch)
tree0c96fb745385ce80ee29c68f5f0d9717eda493e4
parent8327cd3e13f80cde3c0b0f6482e400793e67007f (diff)
downloadNorthstarLauncher-65c2e58a6a788a504c352d4ed34d43be17d0abdd.tar.gz
NorthstarLauncher-65c2e58a6a788a504c352d4ed34d43be17d0abdd.zip
Language selection/detection fixes, no more "files corrupted" error, will throw the proper Origin error now :D
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj2
-rw-r--r--NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters6
-rw-r--r--NorthstarDedicatedTest/dllmain.cpp4
-rw-r--r--NorthstarDedicatedTest/languagehooks.cpp109
-rw-r--r--NorthstarDedicatedTest/languagehooks.h3
5 files changed, 123 insertions, 1 deletions
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 1a79bee8..cabaf573 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -515,6 +515,7 @@
<ClInclude Include="include\spdlog\tweakme.h" />
<ClInclude Include="include\spdlog\version.h" />
<ClInclude Include="keyvalues.h" />
+ <ClInclude Include="languagehooks.h" />
<ClInclude Include="logging.h" />
<ClInclude Include="main.h" />
<ClInclude Include="masterserver.h" />
@@ -554,6 +555,7 @@
<ClCompile Include="hooks.cpp" />
<ClCompile Include="hookutils.cpp" />
<ClCompile Include="keyvalues.cpp" />
+ <ClCompile Include="languagehooks.cpp" />
<ClCompile Include="memalloc.cpp" />
<ClCompile Include="miscclientfixes.cpp" />
<ClCompile Include="misccommands.cpp" />
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index e4ddd92c..ac2684a3 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1422,6 +1422,9 @@
<ClInclude Include="include\libcurl\include\curl\urlapi.h">
<Filter>Header Files\include\libcurl</Filter>
</ClInclude>
+ <ClInclude Include="languagehooks.h">
+ <Filter>Header Files\Client</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
@@ -1532,6 +1535,9 @@
<ClCompile Include="miscserverfixes.cpp">
<Filter>Source Files\Server</Filter>
</ClCompile>
+ <ClCompile Include="languagehooks.cpp">
+ <Filter>Source Files\Client</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="include\spdlog\fmt\bundled\LICENSE.rst">
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 87fb4d5f..79f54374 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -26,6 +26,7 @@
#include "miscclientfixes.h"
#include "miscserverfixes.h"
#include "memalloc.h"
+#include "languagehooks.h"
bool initialised = false;
@@ -63,7 +64,7 @@ bool InitialiseNorthstar()
{
if (initialised)
{
- spdlog::warn("Called InitialiseNorthstar more than once!");
+ //spdlog::warn("Called InitialiseNorthstar more than once!");
return false;
}
@@ -78,6 +79,7 @@ bool InitialiseNorthstar()
InitialiseInterfaceCreationHooks();
AddDllLoadCallback("tier0.dll", InitialiseTier0GameUtilFunctions);
+ AddDllLoadCallback("tier0.dll", InitialiseTier0LanguageHooks);
AddDllLoadCallback("engine.dll", WaitForDebugger);
AddDllLoadCallback("engine.dll", InitialiseEngineGameUtilFunctions);
AddDllLoadCallback("server.dll", InitialiseServerGameUtilFunctions);
diff --git a/NorthstarDedicatedTest/languagehooks.cpp b/NorthstarDedicatedTest/languagehooks.cpp
new file mode 100644
index 00000000..08bacaf9
--- /dev/null
+++ b/NorthstarDedicatedTest/languagehooks.cpp
@@ -0,0 +1,109 @@
+#include "pch.h"
+#include "languagehooks.h"
+#include "gameutils.h"
+#include <filesystem>
+#include <regex>
+
+namespace fs = std::filesystem;
+
+typedef char* (*GetGameLanguageType)();
+char* GetGameLanguage();
+
+typedef LANGID(*Tier0_DetectDefaultLanguageType)();
+
+GetGameLanguageType GetGameLanguageOriginal;
+
+bool CheckLangAudioExists(char* lang)
+{
+ std::string path{ "r2\\sound\\general_" };
+ path += lang;
+ path += ".mstr";
+ return fs::exists(path);
+}
+
+std::vector<std::string> file_list(fs::path dir, std::regex ext_pattern)
+{
+ std::vector<std::string> result;
+
+ using iterator = fs::directory_iterator;
+
+ const iterator end;
+ for (iterator iter{ dir }; iter != end; ++iter)
+ {
+ const std::string filename = iter->path().filename().string();
+ std::smatch matches;
+ if (fs::is_regular_file(*iter) && std::regex_match(filename, matches, ext_pattern))
+ {
+ result.push_back(std::move(matches.str(1)));
+ }
+ }
+
+ return result;
+}
+
+std::string GetAnyInstalledAudioLanguage()
+{
+ for (const auto& lang : file_list("r2\\sound\\", std::regex(".*?general_([a-z]+)_patch_1\\.mstr")))
+ if (lang != "general" || lang != "")
+ return lang;
+ return "NO LANGUAGE DETECTED";
+}
+
+char* GetGameLanguageHook()
+{
+ auto tier0Handle = GetModuleHandleA("tier0.dll");
+ auto Tier0_DetectDefaultLanguageType = GetProcAddress(tier0Handle, "Tier0_DetectDefaultLanguage");
+ char* ingameLang1 = (char*)tier0Handle + 0xA9B60; // one of the globals we need to override if overriding lang (size: 256)
+ bool& canOriginDictateLang = *(bool*)((char*)tier0Handle + 0xA9A90);
+
+ const char* forcedLanguage;
+ if (CommandLine()->CheckParm("-language", &forcedLanguage))
+ {
+ if (!CheckLangAudioExists((char*)forcedLanguage))
+ {
+ spdlog::info("User tried to force the language (-language) to \"{}\", but audio for this language doesn't exist and the game is bound to error, falling back to next option...", forcedLanguage);
+ }
+ else
+ {
+ spdlog::info("User forcing the language (-language) to: {}", forcedLanguage);
+ strncpy(ingameLang1, forcedLanguage, 256);
+ return ingameLang1;
+ }
+ }
+
+ canOriginDictateLang = true; // let it try
+ {
+ auto lang = GetGameLanguageOriginal();
+ if (!CheckLangAudioExists(lang))
+ {
+ spdlog::info("Origin detected language \"{}\", but we do not have audio for it installed, falling back to the next option", lang);
+
+ }
+ else
+ {
+ spdlog::info("Origin detected language: {}", lang);
+ return lang;
+ }
+ }
+
+ Tier0_DetectDefaultLanguageType(); // force the global in tier0 to be populated with language inferred from user's system rather than defaulting to Russian
+ canOriginDictateLang = false; // Origin has no say anymore, we will fallback to user's system setup language
+ auto lang = GetGameLanguageOriginal();
+ spdlog::info("Detected system language: {}", lang);
+ if (!CheckLangAudioExists(lang))
+ {
+ spdlog::warn("Caution, audio for this language does NOT exist. You might want to override your game language with -language command line option.");
+ auto lang = GetAnyInstalledAudioLanguage();
+ spdlog::warn("Falling back to first installed audio language: {}", lang.c_str());
+ strncpy(ingameLang1, lang.c_str(), 256);
+ return ingameLang1;
+ }
+
+ return lang;
+}
+
+void InitialiseTier0LanguageHooks(HMODULE baseAddress)
+{
+ HookEnabler hook;
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0xF560, &GetGameLanguageHook, reinterpret_cast<LPVOID*>(&GetGameLanguageOriginal));
+} \ No newline at end of file
diff --git a/NorthstarDedicatedTest/languagehooks.h b/NorthstarDedicatedTest/languagehooks.h
new file mode 100644
index 00000000..55b591e0
--- /dev/null
+++ b/NorthstarDedicatedTest/languagehooks.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void InitialiseTier0LanguageHooks(HMODULE baseAddress);