From a1b70968b92e9b4a9ac41fe4e20f1e5c22e8a97a Mon Sep 17 00:00:00 2001 From: wolf109909 <84360921+wolf109909@users.noreply.github.com> Date: Mon, 21 Oct 2024 19:25:13 +0800 Subject: [PATCH] add windows version check, localize some prompt --- .gitignore | 1 + .vscode/launch.json | 31 ++++++++++++-- .vscode/settings.json | 3 +- primedev/Launcher.cmake | 5 +++ primedev/Northstar.cmake | 6 ++- primedev/core/hooks.cpp | 11 +++-- primedev/dllmain.cpp | 50 ++++++++++++++++++++++- primedev/logging/crashhandler.cpp | 26 +++++++----- primedev/logging/logging.cpp | 5 ++- primedev/ns_version.h | 2 +- primedev/primelauncher/main.cpp | 54 +++++++++++++------------ primedev/primelauncher/resources.rc | 3 ++ primedev/primelauncher/shared.manifest | 8 ++++ primedev/resources.rc | 5 +++ primedev/shared.manifest | 8 ++++ primedev/shared.rc | 2 + primedev/shared.res | Bin 0 -> 516 bytes 17 files changed, 170 insertions(+), 50 deletions(-) create mode 100644 primedev/primelauncher/shared.manifest create mode 100644 primedev/shared.manifest create mode 100644 primedev/shared.rc create mode 100644 primedev/shared.res diff --git a/.gitignore b/.gitignore index c3c50a405..5b50c14e9 100644 --- a/.gitignore +++ b/.gitignore @@ -373,3 +373,4 @@ MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ +.vscode/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 5c7247b40..a895eb31b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,7 +1,30 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", - "configurations": [] + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "D:\\SteamLibrary\\steamapps\\common\\Titanfall2\\NorthstarLauncher.exe", + "args": ["-dedicated"], + "stopAtEntry": false, + "cwd": "D:\\SteamLibrary\\steamapps\\common\\Titanfall2\\", + "environment": [], + "externalConsole": true, + "MIMode": "gdb", + "miDebuggerPath": "C:\\msys64\\usr\\bin\\gdb.exe", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index c396c82f0..d5531eed8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -101,7 +101,8 @@ "stack": "cpp", "valarray": "cpp", "*.inc": "cpp", - "*.def": "cpp" + "*.def": "cpp", + "*.rh": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/primedev/Launcher.cmake b/primedev/Launcher.cmake index 263492d16..05afd3647 100644 --- a/primedev/Launcher.cmake +++ b/primedev/Launcher.cmake @@ -15,6 +15,11 @@ target_link_libraries( set_target_properties(NorthstarLauncher PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${NS_BINARY_DIR}) +target_compile_options(NorthstarLauncher PRIVATE +-finput-charset=utf-8 +-fexec-charset=utf-8 +) + target_link_options(NorthstarLauncher PUBLIC "LINKER:--stack,8000000") add_custom_command(TARGET NorthstarLauncher POST_BUILD diff --git a/primedev/Northstar.cmake b/primedev/Northstar.cmake index 83d43f01d..64ad65878 100644 --- a/primedev/Northstar.cmake +++ b/primedev/Northstar.cmake @@ -21,6 +21,7 @@ set(CMAKE_SHARED_LIBRARY_PREFIX "") add_library( NorthstarDLL SHARED + "resources.rc" "core/anticheat.cpp" "core/anticheat.h" @@ -249,7 +250,10 @@ target_include_directories( target_compile_options( NorthstarDLL - PRIVATE -mavx + PRIVATE + -mavx + -finput-charset=utf-8 + -fexec-charset=utf-8 ) target_precompile_headers( diff --git a/primedev/core/hooks.cpp b/primedev/core/hooks.cpp index afef8886f..8d7dbf95d 100644 --- a/primedev/core/hooks.cpp +++ b/primedev/core/hooks.cpp @@ -247,13 +247,12 @@ static LPSTR WINAPI h_GetCommandLineA() // if some other command line option includes "-northstar" in the future then you have to refactor this check to check with // both either space after or ending with if (!isDedi && argBuffer.str().find("-northstar") != std::string::npos) - MessageBoxA( + MessageBoxW( NULL, - "The \"-northstar\" command line option is NOT supposed to go into ns_startup_args.txt file!\n\nThis option is " - "supposed to go into Origin/Steam game launch options, and then you are supposed to launch the original " - "Titanfall2.exe " - "rather than NorthstarLauncher.exe to make use of it.", - "Northstar Warning", + L"请勿将 \"-northstar\" 填入 ns_startup_args.txt!\n\n该选项" + "仅可用于Steam/EA App的高级启动选项中,通过" + "平台启动北极星CN使用", + L"警告", MB_ICONWARNING); args.append(argBuffer.str()); diff --git a/primedev/dllmain.cpp b/primedev/dllmain.cpp index 48fea3758..d04fd4f17 100644 --- a/primedev/dllmain.cpp +++ b/primedev/dllmain.cpp @@ -22,6 +22,37 @@ #include #include +bool WindowsVersionSupportsUtf8() { + typedef LONG(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); + HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll"); + if (hMod) { + RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion"); + if (fxPtr != nullptr) { + RTL_OSVERSIONINFOW rovi = {0}; + rovi.dwOSVersionInfoSize = sizeof(rovi); + if (fxPtr(&rovi) == 0) { + return (rovi.dwMajorVersion < 10) || + (rovi.dwMajorVersion == 10 && rovi.dwBuildNumber < 18362); + } + } + } + return false; // Default to false if unable to determine +} + +bool IsUtf8BetaOptionEnabled() { + HKEY hKey; + DWORD utf8Enabled = 0; + DWORD bufferSize = sizeof(utf8Enabled); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + RegQueryValueExW(hKey, L"ACP", nullptr, nullptr, reinterpret_cast(&utf8Enabled), &bufferSize); + RegCloseKey(hKey); + } + + return utf8Enabled == 65001; +} + + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { NOTE_UNUSED(hModule); @@ -40,20 +71,37 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv return TRUE; } + extern "C" bool InitialiseNorthstar() -{ +{ + static bool bInitialised = false; if (bInitialised) return false; bInitialised = true; + + InitialiseNorthstarPrefix(); // initialise the console if needed (-northstar needs this) InitialiseConsole(); // initialise logging before most other things so that they can use spdlog and it have the proper formatting InitialiseLogging(); + + if (WindowsVersionSupportsUtf8() && !IsUtf8BetaOptionEnabled()) { + if(strstr(GetCommandLineA(), "-dedicated") == NULL) + { + MessageBoxW(nullptr, + L"由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符,导致带有任何中文路径的Mod无法正常工作或游戏崩溃,并且不支持将游戏安装在包含中文字符的路径中。若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过(1)升级操作系统版本至Windows 10 1903或更高版本。(2)手动重命名游戏安装目录、所有含中文名称的Mod(如模型和音频替换Mod)的目录名称以避免北极星CN出现故障。", + L"警告: 您的操作系统可能不受支持", + MB_OK | MB_ICONWARNING); + + } + std::wcout << L"警告: 由于运行库与旧版Windows存在兼容性问题,北极星CN 1.17只能保证在Windows 10 1903以上的版本在系统默认设置的情况下正常运行,若是Windows10 1903以下的系统版本,需要在控制面板-时钟和区域-区域-管理-更改系统区域设置-勾选使用Unicode UTF-8。如果在旧系统版本中不启用UTF-8,北极星CN将无法正确处理Windows中文字符,导致带有任何中文路径的Mod无法正常工作或游戏崩溃,并且不支持将游戏安装在包含中文字符的路径中。若您的系统版本无Unicode UTF-8 选项,或是启用此选项后其他应用程序或目录出现乱码问题,可以通过(1)升级操作系统版本至Windows 10 1903或更高版本。(2)手动重命名游戏安装目录、所有含中文名称的Mod(如模型和音频替换Mod)的目录名称以避免北极星CN出现故障。" << std::endl; + } + InitialiseVersion(); CreateLogFiles(); diff --git a/primedev/logging/crashhandler.cpp b/primedev/logging/crashhandler.cpp index be1580702..aaaf2b6d3 100644 --- a/primedev/logging/crashhandler.cpp +++ b/primedev/logging/crashhandler.cpp @@ -7,6 +7,8 @@ #include "plugins/pluginmanager.h" #include +#include +#include #define CRASHHANDLER_MAX_FRAMES 32 #define CRASHHANDLER_GETMODULEHANDLE_FAIL "GetModuleHandleExA failed!" @@ -299,15 +301,21 @@ void CCrashHandler::ShowPopUpMessage() if (!IsDedicatedServer()) { - std::string svMessage = fmt::format( - "Northstar has crashed! Crash info can be found at {}/logs!\n\n{}\n{} + {}", - GetNorthstarPrefix(), - GetExceptionString(), - m_svCrashedModule, - m_svCrashedOffset); - - MessageBoxA(GetForegroundWindow(), svMessage.c_str(), "Northstar has crashed!", MB_ICONERROR | MB_OK); - } + std::wstring_convert> converter; + + std::wstring svMessage = fmt::format( + L"北极星CN崩溃了! 详细错误信息已保存至 {}/logs!\n\n{}\n{} + {}\n点击'确定'以在浏览器中查看常见问题疑难解答", + converter.from_bytes(GetNorthstarPrefix()).c_str(), + converter.from_bytes(GetExceptionString()).c_str(), + converter.from_bytes(m_svCrashedModule).c_str(), + converter.from_bytes(m_svCrashedOffset).c_str()); + + int result = MessageBoxW(GetForegroundWindow(), svMessage.c_str(), L"错误", MB_ICONERROR | MB_OKCANCEL); + if (result == IDOK) { + ShellExecuteW(NULL, L"open", L"https://wiki.northstar.cool/#/installing-northstar/troubleshooting", NULL, NULL, SW_SHOWNORMAL); + } + } + } //----------------------------------------------------------------------------- diff --git a/primedev/logging/logging.cpp b/primedev/logging/logging.cpp index e05b3de03..8509699f6 100644 --- a/primedev/logging/logging.cpp +++ b/primedev/logging/logging.cpp @@ -62,8 +62,8 @@ void CreateLogFiles() catch (...) { spdlog::error("Failed creating log file!"); - MessageBoxA( - 0, "Failed creating log file! Make sure the profile directory is writable.", "Northstar Warning", MB_ICONWARNING | MB_OK); + MessageBoxW( + 0, L"无法创建日志文件! 请检查Northstar目录是否可写!", L"警告", MB_ICONWARNING | MB_OK); } } } @@ -130,6 +130,7 @@ void InitialiseConsole() } else { + SetConsoleOutputCP(CP_UTF8); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); } diff --git a/primedev/ns_version.h b/primedev/ns_version.h index f92d2eddf..ff9a69a3f 100644 --- a/primedev/ns_version.h +++ b/primedev/ns_version.h @@ -2,6 +2,6 @@ #ifndef NORTHSTAR_VERSION // Turning off clang-format here so it doesn't mess with style as it needs to be this way for regex-ing with CI // clang-format off -#define NORTHSTAR_VERSION 1,17,3,0 +#define NORTHSTAR_VERSION 1,17,5,0 // clang-format on #endif diff --git a/primedev/primelauncher/main.cpp b/primedev/primelauncher/main.cpp index 96c96c047..51d15b35b 100644 --- a/primedev/primelauncher/main.cpp +++ b/primedev/primelauncher/main.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace fs = std::filesystem; @@ -74,13 +75,13 @@ FARPROC GetLauncherMain() void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* location) { - char text[8192]; + wchar_t text[8192]; std::string message = std::system_category().message(dwMessageId); - sprintf_s( + swprintf_s( text, - "Failed to load the %ls at \"%ls\" (%lu):\n\n%hs\n\nMake sure you followed the Northstar installation instructions carefully " - "before reaching out for help.", + L"无法读取文件 %ls 于 \"%ls\" (%lu):\n\n%hs\n\n请检查安装流程是否正确" + L"或在北极星CN Wiki中查询常见疑难问题解答", libName, location, dwMessageId, @@ -88,44 +89,47 @@ void LibraryLoadError(DWORD dwMessageId, const wchar_t* libName, const wchar_t* if (dwMessageId == 126 && std::filesystem::exists(location)) { - sprintf_s( + swprintf_s( text, - "%s\n\nThe file at the specified location DOES exist, so this error indicates that one of its *dependencies* failed to be " - "found.\n\nTry the following steps:\n1. Install Visual C++ 2022 Redistributable: " - "https://aka.ms/vs/17/release/vc_redist.x64.exe\n2. Repair game files", + L"%s\n\n该文件在文件系统中存在,但其所需的其他文件可能无法被正常读取 " + "\n\n请尝试以下可能得解决方案: \n1. 安装 Visual C++ 2022 运行库: " + "https://aka.ms/vs/17/release/vc_redist.x64.exe" + "\n2. 在您安装游戏的平台中校验游戏完整性", text); } else if (!fs::exists("Titanfall2.exe") && (fs::exists("..\\Titanfall2.exe") || fs::exists("..\\..\\Titanfall2.exe"))) { - auto curDir = std::filesystem::current_path().filename().string(); - auto aboveDir = std::filesystem::current_path().parent_path().filename().string(); - sprintf_s( + auto curDir = std::filesystem::current_path().filename().wstring(); + auto aboveDir = std::filesystem::current_path().parent_path().filename().wstring(); + swprintf_s( text, - "%s\n\nWe detected that in your case you have extracted the files into a *subdirectory* of your Titanfall 2 " - "installation.\nPlease move all the files and folders from current folder (\"%s\") into the Titanfall 2 installation directory " - "just above (\"%s\").\n\nPlease try out the above steps by yourself before reaching out to the community for support.", + L"%s\n\n检测到您将北极星CN的安装包解压到了 Titanfall 2 的次级文件夹中" + "\n请删除或撤销您在当前文件夹中的操作,并将北极星CN安装包解压到与'Titanfall2.exe'同级的文件夹中", text, curDir.c_str(), aboveDir.c_str()); } else if (!fs::exists("Titanfall2.exe")) { - sprintf_s( + swprintf_s( text, - "%s\n\nRemember: you need to unpack the contents of this archive into your Titanfall 2 game installation directory, not just " - "to any random folder.", + L"%s\n\n请注意: 您需要将北极星CN安装包解压到游戏安装目录,与'Titanfall2.exe'同级的文件夹中," + "而不是直接在压缩包内运行或解压到任意位置!", text); } else if (fs::exists("Titanfall2.exe")) { - sprintf_s( + swprintf_s( text, - "%s\n\nTitanfall2.exe has been found in the current directory: is the game installation corrupted or did you not unpack all " - "Northstar files here?", + L"%s\n\n北极星CN安装位置正确,但游戏文件可能损坏或北极星CN文件缺失\n" + "请尝试在游戏安装平台中校验文件完整性,或重新安装北极星CN并确保所有文件都被解压到当前目录中!", text); } - MessageBoxA(GetForegroundWindow(), text, "Northstar Launcher Error", 0); + int result = MessageBoxW(GetForegroundWindow(), text, L"启动北极星CN时出现错误", 0); + if (result == IDOK) { + ShellExecuteW(NULL, L"open", L"https://wiki.northstar.cool/#/installing-northstar/troubleshooting", NULL, NULL, SW_SHOWNORMAL); + } } void AwaitOriginStartup() @@ -339,7 +343,7 @@ HMODULE LoadDediStub(const char* name) int main(int argc, char* argv[]) { - + if (strstr(GetCommandLineA(), "-waitfordebugger")) { while (!IsDebuggerPresent()) @@ -466,10 +470,10 @@ int main(int argc, char* argv[]) std::cout << "[*] Launching the game..." << std::endl; auto LauncherMain = GetLauncherMain(); if (!LauncherMain) - MessageBoxA( + MessageBoxW( GetForegroundWindow(), - "Failed loading launcher.dll.\nThe game cannot continue and has to exit.", - "Northstar Launcher Error", + L"无法找到 launcher.dll.\n启动游戏时失败", + L"错误", 0); std::cout.flush(); diff --git a/primedev/primelauncher/resources.rc b/primedev/primelauncher/resources.rc index 436461227..9216ffd38 100644 --- a/primedev/primelauncher/resources.rc +++ b/primedev/primelauncher/resources.rc @@ -1,5 +1,8 @@ // Microsoft Visual C++ generated resource script. // +#include +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "shared.manifest" + #include "resource1.h" #include "../ns_version.h" diff --git a/primedev/primelauncher/shared.manifest b/primedev/primelauncher/shared.manifest new file mode 100644 index 000000000..f20560493 --- /dev/null +++ b/primedev/primelauncher/shared.manifest @@ -0,0 +1,8 @@ + + + + + UTF-8 + + + \ No newline at end of file diff --git a/primedev/resources.rc b/primedev/resources.rc index 32739daad..f8735c6a9 100644 --- a/primedev/resources.rc +++ b/primedev/resources.rc @@ -1,5 +1,8 @@ // Microsoft Visual C++ generated resource script. // +#include +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "shared.manifest" + #include "resource1.h" #include "../primedev/ns_version.h" @@ -36,6 +39,8 @@ BEGIN "\0" END + + #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// diff --git a/primedev/shared.manifest b/primedev/shared.manifest new file mode 100644 index 000000000..f20560493 --- /dev/null +++ b/primedev/shared.manifest @@ -0,0 +1,8 @@ + + + + + UTF-8 + + + \ No newline at end of file diff --git a/primedev/shared.rc b/primedev/shared.rc new file mode 100644 index 000000000..bc3565af6 --- /dev/null +++ b/primedev/shared.rc @@ -0,0 +1,2 @@ +#include +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "shared.manifest" \ No newline at end of file diff --git a/primedev/shared.res b/primedev/shared.res new file mode 100644 index 0000000000000000000000000000000000000000..029163ac5cd77e6e468ffb7f438725e865b437af GIT binary patch literal 516 zcmZuuJx{|h5OviqAh9!A-V-NGP$g|8Bm_exr1G^I$89aec9b(I-I(|-{4i#I1Lq_l zf@;b3`Q7uo=X3EsB4K>t)I+M!x1^f73bT3JX}i- z;71cet}*w7bJ=T$yV?BJl(bPbXlHYl#tEa!N>^yR$=UtgRdmiMcwq}sI;(QFSHR}8 zljBSPDDzzIsS#GM75ImN2+CT>*-LGwAh*g0h>VuC1Gn~(bY?2R#7)XjiqcF}RjH-$ zXrcuW+G$(39jui1=mmN>aHZFcx^#uQ6&pqSLR;^vDd&By__tP!wfJgz!_SiRf_A~T2jPc-SL&L`ezkqxLNg{b{ literal 0 HcmV?d00001