From b9af86b9c1c35aec62cc7b77a36fb903c246bf54 Mon Sep 17 00:00:00 2001 From: Amos <48657826+Mauler125@users.noreply.github.com> Date: Sun, 16 Jan 2022 01:18:36 +0100 Subject: [PATCH] Implement terminal utilities for Windows console + add new colors for various output variations * Add new SDK launch logo. * Remove ansi-color coding from in-game console and file loggers. * Improve console colors for Windows. * Implement various string utilities. * Implement various terminal utilities. --- r5dev/core/dllmain.cpp | 10 ++-- r5dev/core/r5dev.h | 11 +++++ r5dev/core/stdafx.h | 3 +- r5dev/core/termutil.cpp | 33 +++++++++++++ r5dev/core/termutil.h | 13 ++++++ r5dev/dedicated.vcxproj | 3 ++ r5dev/dedicated.vcxproj.filters | 9 ++++ r5dev/engine/net_chan.cpp | 5 +- r5dev/engine/sys_utils.cpp | 30 +++++++----- r5dev/engine/sys_utils.h | 14 +++--- r5dev/public/include/utility.h | 2 + r5dev/public/utility.cpp | 48 +++++++++++++++++++ r5dev/r5dev.vcxproj | 2 + r5dev/r5dev.vcxproj.filters | 6 +++ r5dev/squirrel/sqvm.h | 8 ++-- r5dev/windows/console.cpp | 83 ++++++++++++++++++++++++++------- r5dev/windows/console.h | 2 + r5dev/windows/id3dx.cpp | 2 +- 18 files changed, 236 insertions(+), 48 deletions(-) create mode 100644 r5dev/core/termutil.cpp create mode 100644 r5dev/core/termutil.h diff --git a/r5dev/core/dllmain.cpp b/r5dev/core/dllmain.cpp index a8b7a027..493841e0 100644 --- a/r5dev/core/dllmain.cpp +++ b/r5dev/core/dllmain.cpp @@ -1,4 +1,4 @@ -#include "core/stdafx.h" +#include "core/stdafx.h" #include "core/r5dev.h" #include "core/init.h" #include "core/logdef.h" @@ -32,9 +32,11 @@ void R5Dev_Init() #endif // !DEDICATED spdlog::info("\n"); - spdlog::info("+-----------------------------------------------------------------------------+\n"); - spdlog::info("| R5 DEVELOPER CONSOLE -- INITIALIZED ----------------------------------- |\n"); - spdlog::info("+-----------------------------------------------------------------------------+\n"); + for (int i = 0; i < 7; i++) + { + std::string unescaped = StringEscape(R5R_LOGO[i]); + spdlog::info("{}{}{}\n", g_svRedF.c_str(), unescaped.c_str(), g_svReset.c_str()); + } spdlog::info("\n"); } diff --git a/r5dev/core/r5dev.h b/r5dev/core/r5dev.h index 6f4d7cb3..140f938f 100644 --- a/r5dev/core/r5dev.h +++ b/r5dev/core/r5dev.h @@ -8,3 +8,14 @@ __declspec(dllexport) void DummyExport() { // Required for detours. } + +const std::string R5R_LOGO[] = +{ + R"(+---------------------------------------------+)", + R"(| ___ ___ ___ _ _ _ |)", + R"(| | _ \ __| _ \___| |___ __ _ __| |___ __| | |)", + R"(| | /__ \ / -_) / _ \/ _` / _` / -_) _` | |)", + R"(| |_|_\___/_|_\___|_\___/\__,_\__,_\___\__,_| |)", + R"(| |)", + R"(+---------------------------------------------+)" +}; diff --git a/r5dev/core/stdafx.h b/r5dev/core/stdafx.h index be469fa0..0300b956 100644 --- a/r5dev/core/stdafx.h +++ b/r5dev/core/stdafx.h @@ -55,8 +55,9 @@ #include "public/include/httplib.h" #include "public/include/json.hpp" -#include "tier0/basetypes.h" #include "core/assert.h" +#include "core/termutil.h" +#include "tier0/basetypes.h" #if !defined (SDKLAUNCHER) namespace diff --git a/r5dev/core/termutil.cpp b/r5dev/core/termutil.cpp new file mode 100644 index 00000000..13f23e7e --- /dev/null +++ b/r5dev/core/termutil.cpp @@ -0,0 +1,33 @@ +#include "core/stdafx.h" +#include "core/termutil.h" + +std::string g_svGreyF = ""; +std::string g_svRedF = ""; +std::string g_svGreenF = ""; +std::string g_svBlueF = ""; + +std::string g_svGreyB = ""; +std::string g_svRedB = ""; +std::string g_svGreenB = ""; +std::string g_svBlueB = ""; + +std::string g_svReset = ""; + +//----------------------------------------------------------------------------- +// Purpose: sets the global ansi escape sequences. +// If '-ansiclr' has not been passed to the sdk the char will be empty. +//----------------------------------------------------------------------------- +void AnsiColors_Init() +{ + g_svGreyF = "\033[38;2;204;204;204;48;2;000;000;000m"; + g_svRedF = "\033[38;2;255;000;000;48;2;000;000;000m"; + g_svGreenF = "\033[38;2;000;255;000;48;2;000;000;000m"; + g_svBlueF = "\033[38;2;000;000;255;48;2;000;000;000m"; + + g_svGreyB = "\033[38;2;000;000;000;48;2;204;204;204m"; + g_svRedB = "\033[38;2;000;000;000;48;2;255;000;000m"; + g_svGreenB = "\033[38;2;000;000;000;48;2;000;255;000m"; + g_svBlueB = "\033[38;2;000;000;000;48;2;000;000;255m"; + + g_svReset = "\033[38;2;204;204;204;48;2;000;000;000m"; +} \ No newline at end of file diff --git a/r5dev/core/termutil.h b/r5dev/core/termutil.h new file mode 100644 index 00000000..3b87e9d4 --- /dev/null +++ b/r5dev/core/termutil.h @@ -0,0 +1,13 @@ +#pragma once +extern std::string g_svGreyF; +extern std::string g_svRedF; +extern std::string g_svGreenF; +extern std::string g_svBlueF; + +extern std::string g_svGreyB; +extern std::string g_svRedB; +extern std::string g_svGreenB; +extern std::string g_svBlueB; +extern std::string g_svReset; + +void AnsiColors_Init(); diff --git a/r5dev/dedicated.vcxproj b/r5dev/dedicated.vcxproj index 5e4f4103..2e9155d8 100644 --- a/r5dev/dedicated.vcxproj +++ b/r5dev/dedicated.vcxproj @@ -180,6 +180,7 @@ + @@ -191,6 +192,7 @@ + @@ -367,6 +369,7 @@ Create Create + diff --git a/r5dev/dedicated.vcxproj.filters b/r5dev/dedicated.vcxproj.filters index dad27839..9241d12e 100644 --- a/r5dev/dedicated.vcxproj.filters +++ b/r5dev/dedicated.vcxproj.filters @@ -666,6 +666,12 @@ core + + sdk\mathlib + + + core + @@ -875,6 +881,9 @@ core + + core + diff --git a/r5dev/engine/net_chan.cpp b/r5dev/engine/net_chan.cpp index 1c41b74b..f0c1dc95 100644 --- a/r5dev/engine/net_chan.cpp +++ b/r5dev/engine/net_chan.cpp @@ -8,6 +8,7 @@ #include "core/logdef.h" #include "tier0/cvar.h" #include "tier0/completion.h" +#include "mathlib/color.h" #include "engine/sys_utils.h" #include "engine/net_chan.h" #include "engine/baseclient.h" @@ -66,7 +67,7 @@ void HNET_SetKey(std::string svNetKey) DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n"); DevMsg(eDLL_T::ENGINE, "] NET_KEY ----------------------------------------------------\n"); - DevMsg(eDLL_T::ENGINE, "] BASE64: '%s'\n", g_szNetKey.c_str()); + DevMsg(eDLL_T::ENGINE, "] BASE64: %s%s%s\n", g_svGreyB.c_str(), g_szNetKey.c_str(), g_svReset.c_str()); DevMsg(eDLL_T::ENGINE, "--------------------------------------------------------------\n"); NET_SetKey(g_pNetKey, g_szNetKey.c_str()); @@ -102,7 +103,7 @@ void HNET_GenerateKey() DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n"); DevMsg(eDLL_T::ENGINE, "] NET_KEY ----------------------------------------------------\n"); - DevMsg(eDLL_T::ENGINE, "] BASE64: '%s'\n", g_szNetKey.c_str()); + DevMsg(eDLL_T::ENGINE, "] BASE64: %s%s%s\n", g_svGreyB.c_str(), g_szNetKey.c_str(), g_svReset.c_str()); DevMsg(eDLL_T::ENGINE, "--------------------------------------------------------------\n"); NET_SetKey(g_pNetKey, g_szNetKey.c_str()); diff --git a/r5dev/engine/sys_utils.cpp b/r5dev/engine/sys_utils.cpp index 5ff66572..0374b9ec 100644 --- a/r5dev/engine/sys_utils.cpp +++ b/r5dev/engine/sys_utils.cpp @@ -59,7 +59,12 @@ void* HSys_Warning(int level, char* fmt, ...) //----------------------------------------------------------------------------- void DevMsg(eDLL_T idx, const char* fmt, ...) { - static char buf[1024] = {}; + static char szBuf[1024] = {}; + + static std::string svOut; + static std::string svAnsiOut; + + static std::regex rxAnsiExp("\\\033\\[.*?m"); static std::shared_ptr iconsole = spdlog::get("game_console"); static std::shared_ptr wconsole = spdlog::get("win_console"); @@ -69,30 +74,31 @@ void DevMsg(eDLL_T idx, const char* fmt, ...) va_list args{}; va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); + vsnprintf(szBuf, sizeof(szBuf), fmt, args); - buf[sizeof(buf) - 1] = 0; + szBuf[sizeof(szBuf) - 1] = 0; va_end(args); }///////////////////////////// - std::string vmStr = sDLL_T[(int)idx].c_str(); - vmStr.append(buf); + svOut = sDLL_T[(int)idx].c_str(); + svOut.append(szBuf); + svOut = std::regex_replace(svOut, rxAnsiExp, ""); - sqlogger->debug(vmStr); - - if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(vmStr); } + if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(svOut); } else { - std::string vmStrAnsi = sANSI_DLL_T[(int)idx].c_str(); - vmStrAnsi.append(buf); - wconsole->debug(vmStrAnsi); + svAnsiOut = sANSI_DLL_T[(int)idx].c_str(); + svAnsiOut.append(szBuf); + wconsole->debug(svAnsiOut); } + sqlogger->debug(svOut); + #ifndef DEDICATED g_spd_sys_w_oss.str(""); g_spd_sys_w_oss.clear(); - iconsole->info(vmStr); + iconsole->info(svOut); std::string s = g_spd_sys_w_oss.str(); diff --git a/r5dev/engine/sys_utils.h b/r5dev/engine/sys_utils.h index 5a1769ce..aeee3298 100644 --- a/r5dev/engine/sys_utils.h +++ b/r5dev/engine/sys_utils.h @@ -51,13 +51,13 @@ const std::string sDLL_T[8] = const static std::string sANSI_DLL_T[8] = { - "\u001b[94mNative(S):", - "\u001b[90mNative(C):", - "\u001b[33mNative(U):", - "\u001b[37mNative(E):", - "\u001b[96mNative(F):", - "\u001b[92mNative(R):", - "\u001b[91mNative(M):", + "\033[38;2;059;120;218mNative(S):", + "\033[38;2;118;118;118mNative(C):", + "\033[38;2;151;090;118mNative(U):", + "\033[38;2;204;204;204mNative(E):", + "\033[38;2;097;214;214mNative(F):", + "\033[38;2;092;181;089mNative(R):", + "\033[38;2;192;105;173mNative(M):", "" }; diff --git a/r5dev/public/include/utility.h b/r5dev/public/include/utility.h index 692f5a73..1d114d6d 100644 --- a/r5dev/public/include/utility.h +++ b/r5dev/public/include/utility.h @@ -16,5 +16,7 @@ std::string Base64Encode(const std::string& in); std::string Base64Decode(const std::string& in); bool StringReplace(std::string& str, const std::string& from, const std::string& to); std::string CreateDirectories(std::string svFilePath); +std::string StringEscape(const std::string& input); +std::string StringUnescape(const std::string& input); ///////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/public/utility.cpp b/r5dev/public/utility.cpp index b2b64074..431fa831 100644 --- a/r5dev/public/utility.cpp +++ b/r5dev/public/utility.cpp @@ -295,3 +295,51 @@ std::string CreateDirectories(std::string svFilePath) return results; } + +/////////////////////////////////////////////////////////////////////////////// +// For escaping special characters in a string. +std::string StringEscape(const std::string& input) +{ + std::string results; + results.reserve(input.size()); + for (const char c : input) + { + switch (c) + { + case '\'': results += "\\'"; break; + case '\a': results += "\\a"; break; + case '\b': results += "\\b"; break; + case '\f': results += "\\f"; break; + case '\n': results += "\\n"; break; + case '\r': results += "\\r"; break; + case '\t': results += "\\t"; break; + case '\v': results += "\\v"; break; + default: results += c; break; + } + } + return results; +} + +/////////////////////////////////////////////////////////////////////////////// +// For unescaping special characters in a string. +std::string StringUnescape(const std::string& input) +{ + std::string results; + results.reserve(input.size()); + for (const char c : input) + { + switch (c) + { + case '\\': results += "\'"; break; + case '\\a': results += "\a"; break; + case '\\b': results += "\b"; break; + case '\\f': results += "\f"; break; + case '\\n': results += "\n"; break; + case '\\r': results += "\r"; break; + case '\\t': results += "\t"; break; + case '\\v': results += "\v"; break; + default: results += c; break; + } + } + return results; +} diff --git a/r5dev/r5dev.vcxproj b/r5dev/r5dev.vcxproj index 7b28127d..957cc6ca 100644 --- a/r5dev/r5dev.vcxproj +++ b/r5dev/r5dev.vcxproj @@ -31,6 +31,7 @@ Create Create + @@ -223,6 +224,7 @@ + diff --git a/r5dev/r5dev.vcxproj.filters b/r5dev/r5dev.vcxproj.filters index c26cd15c..5eb0bd54 100644 --- a/r5dev/r5dev.vcxproj.filters +++ b/r5dev/r5dev.vcxproj.filters @@ -405,6 +405,9 @@ core + + core + @@ -1046,6 +1049,9 @@ core + + core + diff --git a/r5dev/squirrel/sqvm.h b/r5dev/squirrel/sqvm.h index 1fa08c06..4ae861ea 100644 --- a/r5dev/squirrel/sqvm.h +++ b/r5dev/squirrel/sqvm.h @@ -43,10 +43,10 @@ const static std::string SQVM_LOG_T[4] = const static std::string SQVM_ANSI_LOG_T[4] = { - "\u001b[94mScript(S):", - "\u001b[90mScript(C):", - "\u001b[33mScript(U):", - "\u001b[90mScript(X):" + "\033[38;2;151;149;187mScript(S):", + "\033[38;2;151;149;163mScript(C):", + "\033[38;2;151;123;136mScript(U):", + "\033[38;2;151;149;163mScript(X):" }; namespace diff --git a/r5dev/windows/console.cpp b/r5dev/windows/console.cpp index e950b94a..819d6de4 100644 --- a/r5dev/windows/console.cpp +++ b/r5dev/windows/console.cpp @@ -1,3 +1,9 @@ +//=============================================================================// +// +// Purpose: Windows terminal utilities +// +//=============================================================================// + #include "core/stdafx.h" #include "core/init.h" #include "core/logdef.h" @@ -8,10 +14,56 @@ #include "client/IVEngineClient.h" #include "common/opcodes.h" -//############################################################################# -// INITIALIZATION -//############################################################################# +//----------------------------------------------------------------------------- +// Purpose: sets the windows terminal background color +// Input : color - +//----------------------------------------------------------------------------- +void SetConsoleBackgroundColor(COLORREF color) +{ + CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx{}; + sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + HANDLE consoleOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx); + + COLORREF storedBG = sbInfoEx.ColorTable[0]; + + sbInfoEx.ColorTable[0] = color; + SetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx); +} + +//----------------------------------------------------------------------------- +// Purpose: flashes the windows terminal background color +// Input : nFlashCount - +// nFlashInterval - color - +//----------------------------------------------------------------------------- +void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color) +{ + CONSOLE_SCREEN_BUFFER_INFOEX sbInfoEx{}; + sbInfoEx.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX); + + HANDLE consoleOut = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx); + + COLORREF storedBG = sbInfoEx.ColorTable[0]; + + for (int i = 0; i < nFlashCount; ++i) + { + //-- set BG color + Sleep(nFlashInterval); + sbInfoEx.ColorTable[0] = color; + SetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx); + + //-- restore previous color + Sleep(nFlashInterval); + sbInfoEx.ColorTable[0] = storedBG; + SetConsoleScreenBufferInfoEx(consoleOut, &sbInfoEx); + } +} + +//----------------------------------------------------------------------------- +// Purpose: terminal window setup +//----------------------------------------------------------------------------- void Console_Init() { /////////////////////////////////////////////////////////////////////////// @@ -22,8 +74,7 @@ void Console_Init() return; } - /////////////////////////////////////////////////////////////////////////// - // Set the window title + //-- Set the window title FILE* sBuildTxt; CHAR sBuildBuf[1024] = { 0 }; @@ -38,21 +89,19 @@ void Console_Init() } SetConsoleTitle(sBuildBuf); - /////////////////////////////////////////////////////////////////////////// - // Open input/output streams + //-- Open input/output streams FILE* fDummy; freopen_s(&fDummy, "CONIN$", "r", stdin); freopen_s(&fDummy, "CONOUT$", "w", stdout); freopen_s(&fDummy, "CONOUT$", "w", stderr); - /////////////////////////////////////////////////////////////////////////// - // Create a worker thread to process console commands + //-- Create a worker thread to process console commands DWORD dwMode = NULL; DWORD dwThreadId = NULL; DWORD __stdcall ProcessConsoleWorker(LPVOID); HANDLE hThread = CreateThread(NULL, 0, ProcessConsoleWorker, NULL, 0, &dwThreadId); - //HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); + HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); if (hThread) @@ -68,8 +117,10 @@ void Console_Init() if (!SetConsoleMode(hOutput, dwMode)) // Some editions of Windows have 'VirtualTerminalLevel' disabled by default. { // Warn the user if 'VirtualTerminalLevel' could not be set on users environment. - MessageBox(NULL, "Failed to set console mode 'VirtualTerminalLevel'.\nPlease omit the '-ansiclr' parameter and restart\nthe game if output logging appears distorted.", "SDK Warning", MB_ICONEXCLAMATION | MB_OK); + MessageBox(NULL, "Failed to set console mode 'VirtualTerminalLevel'.\nPlease omit the '-ansiclr' parameter and restart \nthe game if output logging appears distorted.", "SDK Warning", MB_ICONEXCLAMATION | MB_OK); } + SetConsoleBackgroundColor(0x000000); + AnsiColors_Init(); } } @@ -84,16 +135,14 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) { static std::string sCommand = ""; - /////////////////////////////////////////////////////////////////////// - // Get the user input on the debug console - printf(">"); + //printf("] "); + //-- Get the user input on the debug console std::getline(std::cin, sCommand); - /////////////////////////////////////////////////////////////////////// - // Debug toggles + //-- Debug toggles if (sCommand == "pattern test") { PrintHAddress(); continue; } if (sCommand == "opcodes test") { RuntimePtc_Toggle(); continue; } - /////////////////////////////////////////////////////////////////////// + // Execute the command in the r5 SQVM IVEngineClient_CommandExecute(NULL, sCommand.c_str()); sCommand.clear(); diff --git a/r5dev/windows/console.h b/r5dev/windows/console.h index d96a8035..e42d960d 100644 --- a/r5dev/windows/console.h +++ b/r5dev/windows/console.h @@ -1,3 +1,5 @@ #pragma once +void SetConsoleBackgroundColor(COLORREF color); +void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color); void Console_Init(); diff --git a/r5dev/windows/id3dx.cpp b/r5dev/windows/id3dx.cpp index b90db7e1..f2863e6c 100644 --- a/r5dev/windows/id3dx.cpp +++ b/r5dev/windows/id3dx.cpp @@ -429,7 +429,7 @@ bool LoadTextureBuffer(unsigned char* buffer, int len, ID3D11ShaderResourceView* /////////////////////////////////////////////////////////////////////////////// ID3D11Texture2D* pTexture = NULL; D3D11_TEXTURE2D_DESC desc; - D3D11_SUBRESOURCE_DATA subResource; + D3D11_SUBRESOURCE_DATA subResource{}; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ///////////////////////////////////////////////////////////////////////////////