From dfb61aff74810f13da44ad44be3da77a67824d9e Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:04:23 +0200 Subject: [PATCH 1/4] Attempt to load the startup CFG from platform Attempt to load it from there as well on failure. --- r5dev/tier0/commandline.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/r5dev/tier0/commandline.cpp b/r5dev/tier0/commandline.cpp index 8b456d8b..1c7091a0 100644 --- a/r5dev/tier0/commandline.cpp +++ b/r5dev/tier0/commandline.cpp @@ -10,15 +10,22 @@ //----------------------------------------------------------------------------- void CCommandLine::AppendParametersFromFile(const char* const pszConfig) { - FILE* const pFile = fopen(pszConfig, "r"); + char szTextBuf[2048]; + FILE* pFile = fopen(pszConfig, "r"); + if (!pFile) { - printf("%s: '%s' does not exist!\n", - __FUNCTION__, pszConfig); - return; - } + // Try the 'PLATFORM' folder. + snprintf(szTextBuf, sizeof(szTextBuf), "platform/%s", pszConfig); + pFile = fopen(szTextBuf, "r"); - char szTextBuf[2048]; + if (!pFile) + { + printf("%s: '%s' does not exist!\n", + __FUNCTION__, pszConfig); + return; + } + } while (fgets(szTextBuf, sizeof(szTextBuf), pFile)) { From 9e6b0e567f72194ac2665d7f02fe7a5ab8d46746 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:20:47 +0200 Subject: [PATCH 2/4] Port everything to CCommandLine Before, we had to do a hack of capturing the command line using GetCommandLineA, and then checking if a certain argument is present. This was required due to how early the GameSDK dll was loaded (the g_CmdLine object was far from initialized in the engine). Due to the loader refactor, the commandline can be used directly after creation in the game's entry point (which is the time the SDK is getting loaded). Therefore, no copies of the command line are required anymore. This commit contains the following changes: - Correctly ordered the initialization, and deinitialization of systems (first init = last shutdown). - Factored out command line string copy in favor of game's implementation. - Factored the R5Reloaded emblem print into its own function. - Removed 'SpdLog_PostInit()', we can now directly call DevMsg() once SpdLog_Init() has been called, the logger callback sink deals with the formatting of the output. - Fixed a bug where the logger did not print the correct color for 'SYSTEM_WARNING' and 'SYSTEM_ERROR' in the external console. - Fixed a bug where the command line did not work when the game wasn't launched with the '-launcher' parameter. - Logs now equally appear on the external, and in-game console windows. --- r5dev/core/dllmain.cpp | 77 +++++++++++++++++++-------------- r5dev/core/init.cpp | 45 ++++++++++--------- r5dev/core/init.h | 2 + r5dev/core/logdef.cpp | 29 +++---------- r5dev/core/logdef.h | 4 +- r5dev/core/logger.cpp | 24 +++++----- r5dev/core/r5dev.h | 4 -- r5dev/core/termutil.cpp | 2 - r5dev/core/termutil.h | 2 - r5dev/launcher/launcher.cpp | 68 +++-------------------------- r5dev/launcher/launcher.h | 2 - r5dev/netconsole/netconsole.cpp | 8 ++-- r5dev/public/tier0/dbg.h | 10 +++-- r5dev/windows/console.cpp | 5 ++- r5dev/windows/console.h | 2 +- 15 files changed, 108 insertions(+), 176 deletions(-) diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index b81fbbcb..d5a5e455 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -5,6 +5,7 @@ #include "core/logger.h" #include "tier0/basetypes.h" #include "tier0/crashhandler.h" +#include "tier0/commandline.h" /*****************************************************************************/ #ifndef DEDICATED #include "windows/id3dx.h" @@ -21,8 +22,10 @@ #define SDK_DEFAULT_CFG "cfg/startup_dedi_default.cfg" #endif +bool g_bSdkInitialized = false; + //############################################################################# -// INITIALIZATION +// UTILITY //############################################################################# void Crash_Callback() @@ -33,6 +36,24 @@ void Crash_Callback() // TODO[ AMOS ]: This is where we want to call backtrace from. } +void Show_Emblem() +{ + // Logged as 'SYSTEM_ERROR' for its red color. + for (size_t i = 0; i < SDK_ARRAYSIZE(R5R_EMBLEM); i++) + { + DevMsg(eDLL_T::SYSTEM_ERROR, "%s\n", R5R_EMBLEM[i]); + } + + // Log the SDK's 'build_id' under the emblem. + DevMsg(eDLL_T::SYSTEM_ERROR, "+------------------------------------------------[%010d]-+\n", + g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp); + DevMsg(eDLL_T::SYSTEM_ERROR, "\n"); +} + +//############################################################################# +// INITIALIZATION +//############################################################################# + void Tier0_Init() { #if !defined (DEDICATED) @@ -50,10 +71,10 @@ void Tier0_Init() g_SDKDll = CModule("dedicated.dll"); #endif // !DEDICATED - // Setup logger callback sink. - g_CoreMsgVCallback = &EngineLoggerSink; + g_pCmdLine = g_GameDll.GetExportedSymbol("g_pCmdLine").RCast(); + g_CoreMsgVCallback = &EngineLoggerSink; // Setup logger callback sink. - // Setup crash callback. + g_pCmdLine->CreateCmdLine(GetCommandLineA()); g_CrashHandler->SetCrashCallback(&Crash_Callback); } @@ -61,45 +82,35 @@ void SDK_Init() { Tier0_Init(); - if (strstr(GetCommandLineA(), "-launcher")) + if (!CommandLine()->CheckParm("-launcher")) { - g_svCmdLine = GetCommandLineA(); - } - else - { - g_svCmdLine = LoadConfigFile(SDK_DEFAULT_CFG); + CommandLine()->AppendParametersFromFile(SDK_DEFAULT_CFG); } + + const bool bAnsiColor = CommandLine()->CheckParm("-ansicolor") ? true : false; + #ifndef DEDICATED - if (g_svCmdLine.find("-wconsole") != std::string::npos) - { - Console_Init(); - } -#else - Console_Init(); + if (CommandLine()->CheckParm("-wconsole")) #endif // !DEDICATED - - SpdLog_Init(); - Winsock_Init(); // Initialize Winsock. - - for (size_t i = 0; i < SDK_ARRAYSIZE(R5R_EMBLEM); i++) { - spdlog::info("{:s}{:s}{:s}\n", g_svRedF, R5R_EMBLEM[i], g_svReset); + Console_Init(bAnsiColor); } - // Log the SDK's 'build_id' under the emblem. - spdlog::info("{:s}+------------------------------------------------[{:010d}]-+{:s}\n", - g_svRedF, g_SDKDll.GetNTHeaders()->FileHeader.TimeDateStamp, g_svReset); - spdlog::info("\n"); + SpdLog_Init(bAnsiColor); + Show_Emblem(); + Winsock_Init(); // Initialize Winsock. Systems_Init(); - WinSys_Init(); + WinSys_Init(); #ifndef DEDICATED Input_Init(); #endif // !DEDICATED curl_global_init(CURL_GLOBAL_ALL); lzham_enable_fail_exceptions(true); + + g_bSdkInitialized = true; } //############################################################################# @@ -110,26 +121,28 @@ void SDK_Shutdown() { static bool bShutDown = false; assert(!bShutDown); + if (bShutDown) { spdlog::error("Recursive shutdown!\n"); return; } + bShutDown = true; spdlog::info("Shutdown GameSDK\n"); curl_global_cleanup(); - Winsock_Shutdown(); - Systems_Shutdown(); - WinSys_Shutdown(); - #ifndef DEDICATED Input_Shutdown(); #endif // !DEDICATED - Console_Shutdown(); + WinSys_Shutdown(); + Systems_Shutdown(); + Winsock_Shutdown(); + SpdLog_Shutdown(); + Console_Shutdown(); } //############################################################################# diff --git a/r5dev/core/init.cpp b/r5dev/core/init.cpp index 333c7ccf..4973f58c 100644 --- a/r5dev/core/init.cpp +++ b/r5dev/core/init.cpp @@ -149,7 +149,7 @@ void Systems_Init() { - spdlog::info("+-------------------------------------------------------------+\n"); + DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); QuerySystemInfo(); DetourRegister(); @@ -159,8 +159,8 @@ void Systems_Init() DetourInit(); initTimer.End(); - spdlog::info("+-------------------------------------------------------------+\n"); - spdlog::info("{:16s} '{:10.6f}' seconds ('{:12d}' clocks)\n", "Detour->InitDB()", + DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); + DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->InitDB()", initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles()); initTimer.Start(); @@ -187,9 +187,9 @@ void Systems_Init() } initTimer.End(); - spdlog::info("{:16s} '{:10.6f}' seconds ('{:12d}' clocks)\n", "Detour->Attach()", + DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Attach()", initTimer.GetDuration().GetSeconds(), initTimer.GetDuration().GetCycles()); - spdlog::info("+-------------------------------------------------------------+\n"); + DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); ConVar_StaticInit(); } @@ -224,9 +224,9 @@ void Systems_Shutdown() DetourTransactionCommit(); shutdownTimer.End(); - spdlog::info("{:16s} '{:10.6f}' seconds ('{:12d}' clocks)\n", "Detour->Detach()", + DevMsg(eDLL_T::NONE, "%-16s '%10.6f' seconds ('%12lu' clocks)\n", "Detour->Detach()", shutdownTimer.GetDuration().GetSeconds(), shutdownTimer.GetDuration().GetCycles()); - spdlog::info("+-------------------------------------------------------------+\n"); + DevMsg(eDLL_T::NONE, "+-------------------------------------------------------------+\n"); } ///////////////////////////////////////////////////// @@ -275,20 +275,20 @@ void QuerySystemInfo() { char szDeviceName[128]; wcstombs(szDeviceName, dd.DeviceString, sizeof(szDeviceName)); - spdlog::info("{:25s}: '{:s}'\n", "GPU model identifier", szDeviceName); + DevMsg(eDLL_T::NONE, "%-25s: '%s'\n", "GPU model identifier", szDeviceName); } } #endif // !DEDICATED const CPUInformation& pi = GetCPUInformation(); - spdlog::info("{:25s}: '{:s}'\n","CPU model identifier", pi.m_szProcessorBrand); - spdlog::info("{:25s}: '{:s}'\n","CPU vendor tag", pi.m_szProcessorID); - spdlog::info("{:25s}: '{:12d}' ('{:2d}' {:s})\n", "CPU core count", pi.m_nPhysicalProcessors, pi.m_nLogicalProcessors, "logical"); - spdlog::info("{:25s}: '{:12d}' ({:12s})\n", "CPU core speed", pi.m_Speed, "Cycles"); - spdlog::info("{:20s}{:s}: '{:12d}' (0x{:<10X})\n", "L1 cache", "(KiB)", pi.m_nL1CacheSizeKb, pi.m_nL1CacheDesc); - spdlog::info("{:20s}{:s}: '{:12d}' (0x{:<10X})\n", "L2 cache", "(KiB)", pi.m_nL2CacheSizeKb, pi.m_nL2CacheDesc); - spdlog::info("{:20s}{:s}: '{:12d}' (0x{:<10X})\n", "L3 cache", "(KiB)", pi.m_nL3CacheSizeKb, pi.m_nL3CacheDesc); + DevMsg(eDLL_T::NONE, "%-25s: '%s'\n","CPU model identifier", pi.m_szProcessorBrand); + DevMsg(eDLL_T::NONE, "%-25s: '%s'\n","CPU vendor tag", pi.m_szProcessorID); + DevMsg(eDLL_T::NONE, "%-25s: '%12hhu' ('%2hhu' %s)\n", "CPU core count", pi.m_nPhysicalProcessors, pi.m_nLogicalProcessors, "logical"); + DevMsg(eDLL_T::NONE, "%-25s: '%12lld' (%-12s)\n", "CPU core speed", pi.m_Speed, "Cycles"); + DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' (0x%-10X)\n", "L1 cache", "(KiB)", pi.m_nL1CacheSizeKb, pi.m_nL1CacheDesc); + DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' (0x%-10X)\n", "L2 cache", "(KiB)", pi.m_nL2CacheSizeKb, pi.m_nL2CacheDesc); + DevMsg(eDLL_T::NONE, "%-20s%s: '%12lu' (0x%-10X)\n", "L3 cache", "(KiB)", pi.m_nL3CacheSizeKb, pi.m_nL3CacheDesc); MEMORYSTATUSEX statex{}; statex.dwLength = sizeof(statex); @@ -301,13 +301,13 @@ void QuerySystemInfo() DWORDLONG availPhysical = (statex.ullAvailPhys / 1024) / 1024; DWORDLONG availVirtual = (statex.ullAvailVirtual / 1024) / 1024; - spdlog::info("{:20s}{:s}: '{:12d}' ('{:9d}' {:s})\n", "Total system memory", "(MiB)", totalPhysical, totalVirtual, "virtual"); - spdlog::info("{:20s}{:s}: '{:12d}' ('{:9d}' {:s})\n", "Avail system memory", "(MiB)", availPhysical, availVirtual, "virtual"); + DevMsg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Total system memory", "(MiB)", totalPhysical, totalVirtual, "virtual"); + DevMsg(eDLL_T::NONE, "%-20s%s: '%12llu' ('%9llu' %s)\n", "Avail system memory", "(MiB)", availPhysical, availVirtual, "virtual"); } else { - spdlog::error("Unable to retrieve system memory information: {:s}\n", - std::system_category().message(static_cast(::GetLastError()))); + Error(eDLL_T::COMMON, NO_ERROR, "Unable to retrieve system memory information: %s\n", + std::system_category().message(static_cast(::GetLastError())).c_str()); } } @@ -337,12 +337,11 @@ void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 ( void DetourInit() // Run the sigscan { - LPSTR pCommandLine = GetCommandLineA(); - - bool bLogAdr = (strstr(pCommandLine, "-sig_toconsole") != nullptr); + const bool bLogAdr = CommandLine()->CheckParm("-sig_toconsole") ? true : false; + const bool bNoSmap = CommandLine()->CheckParm("-nosmap") ? true : false; bool bInitDivider = false; - g_SigCache.SetDisabled((strstr(pCommandLine, "-nosmap") != nullptr)); + g_SigCache.SetDisabled(bNoSmap); g_SigCache.LoadCache(SIGDB_FILE); for (const IDetour* pDetour : g_DetourVector) diff --git a/r5dev/core/init.h b/r5dev/core/init.h index 836fa4ae..0647794e 100644 --- a/r5dev/core/init.h +++ b/r5dev/core/init.h @@ -14,3 +14,5 @@ void CheckCPU(); void DetourInit(); void DetourAddress(); void DetourRegister(); + +extern bool g_bSdkInitialized; diff --git a/r5dev/core/logdef.cpp b/r5dev/core/logdef.cpp index f4dabafe..27986967 100644 --- a/r5dev/core/logdef.cpp +++ b/r5dev/core/logdef.cpp @@ -10,7 +10,7 @@ std::shared_ptr g_LogSink; //############################################################################# // SPDLOG INIT //############################################################################# -void SpdLog_Init(void) +void SpdLog_Init(const bool bAnsiColor) { static bool bInitialized = false; @@ -30,7 +30,7 @@ void SpdLog_Init(void) g_LogSink = std::make_shared(g_LogStream); g_ImGuiLogger = std::make_shared("game_console", g_LogSink); spdlog::register_logger(g_ImGuiLogger); // in-game console logger. - g_ImGuiLogger->set_pattern("[0.000] %v"); + g_ImGuiLogger->set_pattern("%v"); g_ImGuiLogger->set_level(spdlog::level::trace); } #endif // !NETCONSOLE @@ -45,14 +45,14 @@ void SpdLog_Init(void) #endif // NETCONSOLE // Determine if user wants ansi-color logging in the terminal. - if (g_svCmdLine.find("-ansicolor") != string::npos) + if (bAnsiColor) { - g_TermLogger->set_pattern("[0.000] %v\u001b[0m"); + g_TermLogger->set_pattern("%v\u001b[0m"); g_bSpdLog_UseAnsiClr = true; } else { - g_TermLogger->set_pattern("[0.000] %v"); + g_TermLogger->set_pattern("%v"); } //g_TermLogger->set_level(spdlog::level::trace); } @@ -91,25 +91,6 @@ void SpdLog_Create() , fmt::format("{:s}\\{:s}", g_LogSessionDirectory, "filesystem.log"), SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v"); } -//############################################################################# -// SPDLOG POST INIT -//############################################################################# -void SpdLog_PostInit() -{ -#ifndef NETCONSOLE - spdlog::flush_every(std::chrono::seconds(5)); // Flush buffers every 5 seconds for every logger. - g_ImGuiLogger->set_pattern("%v"); -#endif // !NETCONSOLE - - if (g_svCmdLine.find("-ansicolor") != string::npos) - { - g_TermLogger->set_pattern("%v\u001b[0m"); - g_bSpdLog_UseAnsiClr = true; - } - else { g_TermLogger->set_pattern("%v"); } - g_bSpdLog_PostInit = true; -} - //############################################################################# // SPDLOG SHUTDOWN //############################################################################# diff --git a/r5dev/core/logdef.h b/r5dev/core/logdef.h index 2f998635..b43c8006 100644 --- a/r5dev/core/logdef.h +++ b/r5dev/core/logdef.h @@ -14,7 +14,6 @@ constexpr int SPDLOG_MAX_SIZE = 10 * 1024 * 1024; // Sets number of bytes before constexpr int SPDLOG_NUM_FILE = 512; // Sets number of files to rotate to. inline bool g_bSpdLog_UseAnsiClr = false; -inline bool g_bSpdLog_PostInit = false; extern std::shared_ptr g_TermLogger; extern std::shared_ptr g_ImGuiLogger; @@ -24,7 +23,6 @@ extern std::shared_ptr g_ImGuiLogger; extern std::ostringstream g_LogStream; extern std::shared_ptr g_LogSink; -void SpdLog_Init(void); +void SpdLog_Init(const bool bAnsiColor); void SpdLog_Create(void); -void SpdLog_PostInit(void); void SpdLog_Shutdown(void); diff --git a/r5dev/core/logger.cpp b/r5dev/core/logger.cpp index b65d2418..4c5e897a 100644 --- a/r5dev/core/logger.cpp +++ b/r5dev/core/logger.cpp @@ -1,5 +1,5 @@ -#include "core/stdafx.h" #include "tier0/utility.h" +#include "init.h" #include "logdef.h" #include "logger.h" #ifndef DEDICATED @@ -95,10 +95,10 @@ const char* GetContextNameByIndex(eDLL_T context, const bool ansiColor = false) case eDLL_T::VIDEO: case eDLL_T::NETCON: case eDLL_T::COMMON: - contextName = s_DllAnsiColor[index]; - break; case eDLL_T::SYSTEM_WARNING: case eDLL_T::SYSTEM_ERROR: + contextName = s_DllAnsiColor[index]; + break; case eDLL_T::NONE: default: break; @@ -141,7 +141,7 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context, const UINT exitCode /*= NO_ERROR*/, const char* pszUptimeOverride /*= nullptr*/) { const char* pszUpTime = pszUptimeOverride ? pszUptimeOverride : Plat_GetProcessUpTime(); - string message = g_bSpdLog_PostInit ? pszUpTime : ""; + string message(pszUpTime); const bool bToConsole = (logLevel >= LogLevel_t::LEVEL_CONSOLE); const bool bUseColor = (bToConsole && g_bSpdLog_UseAnsiClr); @@ -288,15 +288,15 @@ void EngineLoggerSink(LogType_t logType, LogLevel_t logLevel, eDLL_T context, #ifndef DEDICATED g_ImGuiLogger->debug(message); - if (g_bSpdLog_PostInit) - { - const string logStreamBuf = g_LogStream.str(); - g_pConsole->AddLog(ConLog_t(logStreamBuf, overlayColor)); + const string logStreamBuf = g_LogStream.str(); + g_pConsole->AddLog(ConLog_t(logStreamBuf, overlayColor)); - if (logLevel >= LogLevel_t::LEVEL_NOTIFY) // Draw to mini console. - { - g_pOverlay->AddLog(overlayContext, logStreamBuf); - } + // We can only log to the in-game overlay console when the SDK has + // been fully initialized, due to the use of ConVar's. + if (g_bSdkInitialized && logLevel >= LogLevel_t::LEVEL_NOTIFY) + { + // Draw to mini console. + g_pOverlay->AddLog(overlayContext, logStreamBuf); } #endif // !DEDICATED } diff --git a/r5dev/core/r5dev.h b/r5dev/core/r5dev.h index e5ade806..fe65d82e 100644 --- a/r5dev/core/r5dev.h +++ b/r5dev/core/r5dev.h @@ -1,9 +1,5 @@ #pragma once -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include - __declspec(dllexport) void DummyExport() { // Required for detours. diff --git a/r5dev/core/termutil.cpp b/r5dev/core/termutil.cpp index a4e88ba5..be1521e7 100644 --- a/r5dev/core/termutil.cpp +++ b/r5dev/core/termutil.cpp @@ -15,8 +15,6 @@ const char* g_svYellowB = ""; const char* g_svReset = ""; -std::string g_svCmdLine; - //----------------------------------------------------------------------------- // Purpose: sets the global ansi escape sequences. // If '-ansicolor' has not been passed to the sdk the char will be empty. diff --git a/r5dev/core/termutil.h b/r5dev/core/termutil.h index cbd7cab0..674d8c7a 100644 --- a/r5dev/core/termutil.h +++ b/r5dev/core/termutil.h @@ -13,6 +13,4 @@ extern const char* g_svYellowB; extern const char* g_svReset; -extern std::string g_svCmdLine; - void AnsiColors_Init(); diff --git a/r5dev/launcher/launcher.cpp b/r5dev/launcher/launcher.cpp index cf3bbe28..0cec2d8b 100644 --- a/r5dev/launcher/launcher.cpp +++ b/r5dev/launcher/launcher.cpp @@ -14,10 +14,14 @@ int LauncherMain(HINSTANCE hInstance) { - SpdLog_PostInit(); + // Flush buffers every 5 seconds for every logger. + // Has to be done here, don't move this to SpdLog + // init, as this could cause deadlocks on certain + // compilers (VS2017)!!! + spdlog::flush_every(std::chrono::seconds(5)); int results = v_LauncherMain(hInstance); - spdlog::info("{:s} returned: {:s}\n", __FUNCTION__, ExitCodeToString(results)); + DevMsg(eDLL_T::NONE, "%s returned: %s\n", __FUNCTION__, ExitCodeToString(results)); return results; } @@ -73,66 +77,6 @@ void AppendSDKParametersPreInit() CommandLine()->AppendParm("-nojoy", ""); CommandLine()->AppendParm("-nosendtable", ""); } - - // Assume default configs if the game isn't launched with the SDKLauncher. - if (!CommandLine()->FindParm("-launcher")) - { - ParseAndApplyConfigFile(g_svCmdLine); - } -} - -string LoadConfigFile(const char* svConfig) -{ - fs::path cfgPath = fs::current_path() /= svConfig; // Get cfg path for default startup. - - if (!FileExists(cfgPath)) - { - // Load it from PLATFORM. - cfgPath = fs::current_path() /= string("platform/") + svConfig; - } - - ifstream cfgFile(cfgPath); - - if (!cfgFile) - { - spdlog::error("{:s}: '{:s}' does not exist!\n", __FUNCTION__, svConfig); - return ""; - } - - string svArguments; - stringstream ss; - ss << cfgFile.rdbuf(); - svArguments = ss.str(); - - return svArguments; -} - -void ParseAndApplyConfigFile(const string& svConfig) -{ - stringstream ss(svConfig); - string svInput; - - if (!svConfig.empty()) - { - while (std::getline(ss, svInput, '\n')) - { - string::size_type nPos = svInput.find(' '); - if (!svInput.empty() - && nPos > 0 - && nPos < svInput.size() - && nPos != svInput.size()) - { - string svValue = svInput.substr(nPos + 1); - string svArgument = svInput.erase(svInput.find(' ')); - - CommandLine()->AppendParm(svArgument.c_str(), svValue.c_str()); - } - else - { - CommandLine()->AppendParm(svInput.c_str(), ""); - } - } - } } const char* ExitCodeToString(int nCode) diff --git a/r5dev/launcher/launcher.h b/r5dev/launcher/launcher.h index 1f470714..7e4f5d81 100644 --- a/r5dev/launcher/launcher.h +++ b/r5dev/launcher/launcher.h @@ -13,8 +13,6 @@ inline auto v_RemoveSpuriousGameParameters = p_RemoveSpuriousGameParameters.RCas #endif // !GAMEDLL_S0 || !GAMEDLL_S1 void AppendSDKParametersPreInit(); -string LoadConfigFile(const char* svConfig); -void ParseAndApplyConfigFile(const string& svConfig); const char* ExitCodeToString(int nCode); /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/netconsole/netconsole.cpp b/r5dev/netconsole/netconsole.cpp index 07b36be0..c3734240 100644 --- a/r5dev/netconsole/netconsole.cpp +++ b/r5dev/netconsole/netconsole.cpp @@ -101,11 +101,11 @@ bool CNetCon::Shutdown(void) //----------------------------------------------------------------------------- void CNetCon::TermSetup(void) { - g_svCmdLine = GetCommandLineA(); + const char* pszCommandLine = GetCommandLineA(); + const bool bEnableColor = strstr("-ansicolor", pszCommandLine) != nullptr; - SpdLog_Init(); - SpdLog_PostInit(); - Console_Init(); + SpdLog_Init(bEnableColor); + Console_Init(bEnableColor); } //----------------------------------------------------------------------------- diff --git a/r5dev/public/tier0/dbg.h b/r5dev/public/tier0/dbg.h index a3e2418d..22619bfb 100644 --- a/r5dev/public/tier0/dbg.h +++ b/r5dev/public/tier0/dbg.h @@ -66,9 +66,11 @@ enum class LogLevel_t LEVEL_NOTIFY // Emit to in-game mini console }; //----------------------------------------------------------------------------- -constexpr const char s_CommonAnsiColor[] = "\033[38;2;255;204;153m"; -constexpr const char s_DefaultAnsiColor[]= "\033[38;2;204;204;204m"; -constexpr const char* s_DllAnsiColor[12] = +constexpr const char s_CommonAnsiColor[] = "\033[38;2;255;204;153m"; +constexpr const char s_WarningAnsiColor[] = "\033[38;2;255;255;000m"; +constexpr const char s_ErrorAnsiColor[] = "\033[38;2;255;000;000m"; +constexpr const char s_DefaultAnsiColor[] = "\033[38;2;204;204;204m"; +constexpr const char* s_DllAnsiColor[14] = { "\033[38;2;059;120;218mNative(S):", "\033[38;2;118;118;118mNative(C):", @@ -81,6 +83,8 @@ constexpr const char* s_DllAnsiColor[12] = "\033[38;2;185;000;235mNative(V):", "\033[38;2;204;204;204mNetcon(X):", s_CommonAnsiColor, + s_WarningAnsiColor, + s_ErrorAnsiColor, s_DefaultAnsiColor }; //----------------------------------------------------------------------------- diff --git a/r5dev/windows/console.cpp b/r5dev/windows/console.cpp index 04e2447d..05771b60 100644 --- a/r5dev/windows/console.cpp +++ b/r5dev/windows/console.cpp @@ -67,8 +67,9 @@ void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color) //----------------------------------------------------------------------------- // Purpose: terminal window setup +// Input : bAnsiColor - //----------------------------------------------------------------------------- -void Console_Init() +void Console_Init(const bool bAnsiColor) { #ifndef NETCONSOLE /////////////////////////////////////////////////////////////////////////// @@ -102,7 +103,7 @@ void Console_Init() HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); DWORD dwMode = NULL; - if (g_svCmdLine.find("-ansicolor") != string::npos) + if (bAnsiColor) { GetConsoleMode(hOutput, &dwMode); dwMode |= ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING; diff --git a/r5dev/windows/console.h b/r5dev/windows/console.h index 3e6b4d1f..6a0e4d41 100644 --- a/r5dev/windows/console.h +++ b/r5dev/windows/console.h @@ -3,5 +3,5 @@ void SetConsoleBackgroundColor(COLORREF color); void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color); -void Console_Init(); +void Console_Init(const bool bAnsiColor); void Console_Shutdown(); From d37f12aa4f15d303d1278ce636226a107a31647b Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jul 2023 02:11:39 +0200 Subject: [PATCH 3/4] Don't recreate the command line Don't recreate it in the engine (LauncherMain) if its already created in the SDK. This solution toggles a hybrid between creating it in the SDK, or in the engine when -noworkerdll is passed to the loader. --- r5dev/core/dllmain.cpp | 5 +++++ r5dev/tier0/commandline.cpp | 32 +++++++++++++++++++++++++++++++- r5dev/tier0/commandline.h | 19 ++++++++++++------- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index d5a5e455..b380b754 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -76,6 +76,11 @@ void Tier0_Init() g_pCmdLine->CreateCmdLine(GetCommandLineA()); g_CrashHandler->SetCrashCallback(&Crash_Callback); + + // This prevents the game from recreating it, + // see 'CCommandLine::StaticCreateCmdLine' for + // more information. + g_bCommandLineCreated = true; } void SDK_Init() diff --git a/r5dev/tier0/commandline.cpp b/r5dev/tier0/commandline.cpp index 1c7091a0..3fd09577 100644 --- a/r5dev/tier0/commandline.cpp +++ b/r5dev/tier0/commandline.cpp @@ -5,6 +5,25 @@ //=============================================================================// #include "tier0/commandline.h" +bool g_bCommandLineCreated = false; + +//----------------------------------------------------------------------------- +// Purpose: Create a command line from the passed in string +// Note that if you pass in a @filename, then the routine will read settings +// from a file instead of the command line +//----------------------------------------------------------------------------- +void CCommandLine::StaticCreateCmdLine(CCommandLine* thisptr, const char* pszCommandLine) +{ + // The SDK creates the cmdline instead, when loaded. We hook this + // function, and skip the actual creation of subsequent calls. + // This is required as otherwise our own appended parameters will + // get lost when the game recreates it in 'LauncherMain'. + if (!g_bCommandLineCreated) + { + v_CCommandLine__CreateCmdLine(thisptr, pszCommandLine); + } +} + //----------------------------------------------------------------------------- // Purpose: parses a text file and appends its parameters/values //----------------------------------------------------------------------------- @@ -60,7 +79,7 @@ void CCommandLine::AppendParametersFromFile(const char* const pszConfig) pArgValue = pArg; } - CommandLine()->AppendParm(szTextBuf, pArgValue); + AppendParm(szTextBuf, pArgValue); } fclose(pFile); @@ -68,3 +87,14 @@ void CCommandLine::AppendParametersFromFile(const char* const pszConfig) /////////////////////////////////////////////////////////////////////////////// CCommandLine* g_pCmdLine = nullptr; + + +void VCommandLine::Attach() const +{ + DetourAttach(&v_CCommandLine__CreateCmdLine, &CCommandLine::StaticCreateCmdLine); +} + +void VCommandLine::Detach() const +{ + DetourDetach(&v_CCommandLine__CreateCmdLine, &CCommandLine::StaticCreateCmdLine); +} \ No newline at end of file diff --git a/r5dev/tier0/commandline.h b/r5dev/tier0/commandline.h index e7061c76..ff905d52 100644 --- a/r5dev/tier0/commandline.h +++ b/r5dev/tier0/commandline.h @@ -4,6 +4,7 @@ class CCommandLine : public ICommandLine // VTABLE @0x141369C78 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM { public: + static void StaticCreateCmdLine(CCommandLine* thisptr, const char* pszCommandLine); void AppendParametersFromFile(const char* const pszConfig); private: @@ -19,6 +20,7 @@ private: char* m_ppParms[MAX_PARAMETERS]; }; +extern bool g_bCommandLineCreated; extern CCommandLine* g_pCmdLine; //----------------------------------------------------------------------------- // Instance singleton and expose interface to rest of code @@ -28,21 +30,24 @@ inline CCommandLine* CommandLine(void) return g_pCmdLine; } +inline CMemory p_CCommandLine__CreateCmdLine; +inline auto v_CCommandLine__CreateCmdLine = p_CCommandLine__CreateCmdLine.RCast(); + /////////////////////////////////////////////////////////////////////////////// class VCommandLine : public IDetour { virtual void GetAdr(void) const { - LogVarAdr("g_pCmdLine", reinterpret_cast(g_pCmdLine)); + LogFunAdr("CCommandLine::CreateCmdLine", p_CCommandLine__CreateCmdLine.GetPtr()); } - virtual void GetFun(void) const { } - virtual void GetVar(void) const + virtual void GetFun(void) const { - g_pCmdLine = g_GameDll.FindPatternSIMD("40 55 48 83 EC 20 48 8D 6C 24 ?? 48 89 5D 10 49 C7 C0 ?? ?? ?? ??") - .FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 250).ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + p_CCommandLine__CreateCmdLine = g_GameDll.FindPatternSIMD("48 89 54 24 ?? 48 89 4C 24 ?? 53 41 55 B8 ?? ?? ?? ??"); + v_CCommandLine__CreateCmdLine = p_CCommandLine__CreateCmdLine.RCast(); } + virtual void GetVar(void) const { } virtual void GetCon(void) const { } - virtual void Attach(void) const { } - virtual void Detach(void) const { } + virtual void Attach(void) const; + virtual void Detach(void) const; }; /////////////////////////////////////////////////////////////////////////////// From d7245a04e4357d323bac1787fc76024aa1fa502a Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 1 Jul 2023 11:20:44 +0200 Subject: [PATCH 4/4] Test recursive shutdown on global init bool Test on this instead, it has to be unset anyways. --- r5dev/core/dllmain.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index b380b754..e123a11f 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -124,16 +124,15 @@ void SDK_Init() void SDK_Shutdown() { - static bool bShutDown = false; - assert(!bShutDown); + assert(g_bSdkInitialized); - if (bShutDown) + if (!g_bSdkInitialized) { spdlog::error("Recursive shutdown!\n"); return; } - bShutDown = true; + g_bSdkInitialized = false; spdlog::info("Shutdown GameSDK\n"); curl_global_cleanup();