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.
This commit is contained in:
Amos 2022-01-16 01:18:36 +01:00
parent d182652211
commit b9af86b9c1
18 changed files with 236 additions and 48 deletions

View File

@ -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");
}

View File

@ -8,3 +8,14 @@ __declspec(dllexport) void DummyExport()
{
// Required for detours.
}
const std::string R5R_LOGO[] =
{
R"(+---------------------------------------------+)",
R"(| ___ ___ ___ _ _ _ |)",
R"(| | _ \ __| _ \___| |___ __ _ __| |___ __| | |)",
R"(| | /__ \ / -_) / _ \/ _` / _` / -_) _` | |)",
R"(| |_|_\___/_|_\___|_\___/\__,_\__,_\___\__,_| |)",
R"(| |)",
R"(+---------------------------------------------+)"
};

View File

@ -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

33
r5dev/core/termutil.cpp Normal file
View File

@ -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";
}

13
r5dev/core/termutil.h Normal file
View File

@ -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();

View File

@ -180,6 +180,7 @@
<ClInclude Include="core\logdef.h" />
<ClInclude Include="core\r5dev.h" />
<ClInclude Include="core\stdafx.h" />
<ClInclude Include="core\termutil.h" />
<ClInclude Include="ebisusdk\EbisuSDK.h" />
<ClInclude Include="engine\baseclient.h" />
<ClInclude Include="engine\host_cmd.h" />
@ -191,6 +192,7 @@
<ClInclude Include="launcher\IApplication.h" />
<ClInclude Include="mathlib\adler32.h" />
<ClInclude Include="mathlib\bits.h" />
<ClInclude Include="mathlib\color.h" />
<ClInclude Include="mathlib\crc32.h" />
<ClInclude Include="mathlib\IceKey.H" />
<ClInclude Include="mathlib\parallel_for.h" />
@ -367,6 +369,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="core\termutil.cpp" />
<ClCompile Include="ebisusdk\EbisuSDK.cpp" />
<ClCompile Include="engine\baseclient.cpp" />
<ClCompile Include="engine\host_cmd.cpp" />

View File

@ -666,6 +666,12 @@
<ClInclude Include="core\assert.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="mathlib\color.h">
<Filter>sdk\mathlib</Filter>
</ClInclude>
<ClInclude Include="core\termutil.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="client\IVEngineClient.cpp">
@ -875,6 +881,9 @@
<ClCompile Include="core\logdef.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="core\termutil.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="r5dev.def" />

View File

@ -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());

View File

@ -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<spdlog::logger> iconsole = spdlog::get("game_console");
static std::shared_ptr<spdlog::logger> 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();

View File

@ -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):",
""
};

View File

@ -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);
/////////////////////////////////////////////////////////////////////////////

View File

@ -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;
}

View File

@ -31,6 +31,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="core\termutil.cpp" />
<ClCompile Include="ebisusdk\EbisuSDK.cpp" />
<ClCompile Include="engine\baseclient.cpp" />
<ClCompile Include="engine\baseclientstate.cpp" />
@ -223,6 +224,7 @@
<ClInclude Include="core\logdef.h" />
<ClInclude Include="core\r5dev.h" />
<ClInclude Include="core\stdafx.h" />
<ClInclude Include="core\termutil.h" />
<ClInclude Include="ebisusdk\EbisuSDK.h" />
<ClInclude Include="engine\baseclient.h" />
<ClInclude Include="engine\baseclientstate.h" />

View File

@ -405,6 +405,9 @@
<ClCompile Include="core\logdef.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="core\termutil.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="client\cdll_engine_int.h">
@ -1046,6 +1049,9 @@
<ClInclude Include="core\assert.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="core\termutil.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="r5dev.def" />

View File

@ -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

View File

@ -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();

View File

@ -1,3 +1,5 @@
#pragma once
void SetConsoleBackgroundColor(COLORREF color);
void FlashConsoleBackground(int nFlashCount, int nFlashInterval, COLORREF color);
void Console_Init();

View File

@ -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;
///////////////////////////////////////////////////////////////////////////////