From d0e77c42f2ded307acdf2596cadc78d0845efa7a Mon Sep 17 00:00:00 2001 From: Amos Date: Thu, 5 Aug 2021 03:28:03 -0700 Subject: [PATCH] Push SQVM output to in-game console * Upgrade to spdlog for SQVM_PrintFunc * Improve in-game console window * Add print hook for signonstate debug on the client --- external/spdlog/include/tweakme.h | 2 +- r5dedicated/console.cpp | 2 +- r5dedicated/hooks.cpp | 7 +- r5dedicated/hooks.h | 2 +- r5dedicated/net.cpp | 6 +- r5dedicated/pch.h | 2 + r5dedicated/sqvm.cpp | 31 ++++++-- r5dev/include/hooks.h | 8 +- r5dev/include/patterns.h | 4 + r5dev/include/pch.h | 2 + r5dev/src/console.cpp | 2 +- r5dev/src/hooks/hooks.cpp | 81 ++++++++++++-------- r5dev/src/hooks/net.cpp | 43 +++++++++++ r5dev/src/hooks/sqvm.cpp | 48 +++++++++--- r5dev/src/id3dx.cpp | 111 +++++++++++++++------------ r5dev/src/opcptc.cpp | 2 +- r5dev/src/overlay.cpp | 120 ++++++++++++++++-------------- shared/utility.cpp | 2 +- 18 files changed, 306 insertions(+), 169 deletions(-) diff --git a/external/spdlog/include/tweakme.h b/external/spdlog/include/tweakme.h index 4c115bba..afdac42a 100644 --- a/external/spdlog/include/tweakme.h +++ b/external/spdlog/include/tweakme.h @@ -55,7 +55,7 @@ /////////////////////////////////////////////////////////////////////////////// // Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows) // -#define SPDLOG_EOL "\n" +#define SPDLOG_EOL "" /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dedicated/console.cpp b/r5dedicated/console.cpp index 3d77c848..a9be9e56 100644 --- a/r5dedicated/console.cpp +++ b/r5dedicated/console.cpp @@ -69,7 +69,7 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) /////////////////////////////////////////////////////////////////////// // Engine toggles - if (sCommand == "toggle net") { Hooks::ToggleNetHooks(); continue; } + if (sCommand == "toggle net") { Hooks::ToggleNetTrace(); continue; } if (sCommand == "toggle dev") { Hooks::ToggleDevCommands(); continue; } if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } /////////////////////////////////////////////////////////////////////// diff --git a/r5dedicated/hooks.cpp b/r5dedicated/hooks.cpp index 67fa4dc9..2b590d4b 100644 --- a/r5dedicated/hooks.cpp +++ b/r5dedicated/hooks.cpp @@ -43,6 +43,11 @@ void Hooks::InstallHooks() MH_EnableHook(addr_CHLClient_FrameStageNotify); MH_EnableHook(addr_CVEngineServer_IsPersistenceDataAvailable); + /////////////////////////////////////////////////////////////////////////////// + // Enable ConVar | ConCommand hooks + MH_EnableHook(addr_ConVar_IsFlagSet); + MH_EnableHook(addr_ConCommand_IsFlagSet); + /////////////////////////////////////////////////////////////////////////////// // Enabled Utility hooks MH_EnableHook(addr_MSG_EngineError); @@ -115,7 +120,7 @@ void Hooks::ToggleDevCommands() bDev = !bDev; } -void Hooks::ToggleNetHooks() +void Hooks::ToggleNetTrace() { static bool bNet = true; diff --git a/r5dedicated/hooks.h b/r5dedicated/hooks.h index 66ab2187..be69c6ca 100644 --- a/r5dedicated/hooks.h +++ b/r5dedicated/hooks.h @@ -131,6 +131,6 @@ namespace Hooks void InstallHooks(); void RemoveHooks(); - void ToggleNetHooks(); + void ToggleNetTrace(); void ToggleDevCommands(); } \ No newline at end of file diff --git a/r5dedicated/net.cpp b/r5dedicated/net.cpp index 340a4be2..84d2cd50 100644 --- a/r5dedicated/net.cpp +++ b/r5dedicated/net.cpp @@ -34,9 +34,8 @@ struct __declspec(align(8)) netpacket_t }; //----------------------------------------------------------------------------- -// Hook and log the receive datagram +// Purpose: hook and log the receive datagram //----------------------------------------------------------------------------- - bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) { bool result = originalNET_ReceiveDatagram(sock, inpacket, raw); @@ -54,9 +53,8 @@ bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) } //----------------------------------------------------------------------------- -// Hook and log send datagram +// Purpose: hook and log send datagram //----------------------------------------------------------------------------- - unsigned int Hooks::NET_SendDatagram(SOCKET s, const char* buf, int len, int flags) { unsigned int result = originalNET_SendDatagram(s, buf, len, flags); diff --git a/r5dedicated/pch.h b/r5dedicated/pch.h index 7159ba8a..d81d5c4d 100644 --- a/r5dedicated/pch.h +++ b/r5dedicated/pch.h @@ -24,6 +24,8 @@ #include "spdlog.h" #include "sinks/basic_file_sink.h" +#include "sinks/stdout_sinks.h" +#include "sinks/ostream_sink.h" #include "utility.h" //#include "httplib.h" //#include "json.hpp" diff --git a/r5dedicated/sqvm.cpp b/r5dedicated/sqvm.cpp index c3654922..137dd52f 100644 --- a/r5dedicated/sqvm.cpp +++ b/r5dedicated/sqvm.cpp @@ -8,23 +8,39 @@ namespace Hooks } //--------------------------------------------------------------------------------- -// Print the output of the VM. -// TODO: separate SV CL and UI +// Purpose: prints the output of each VM to the console //--------------------------------------------------------------------------------- - void* Hooks::SQVM_Print(void* sqvm, char* fmt, ...) { + int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18); + + static char buf[1024]; + static std::string vmType[3] = { "Script(S):", "Script(C):", "Script(U):" }; + + static auto wconsole = spdlog::stdout_logger_mt("sqvm_wconsole"); // windows console + + std::string vmStr = vmType[vmIdx].c_str(); + + wconsole->set_pattern("[%S.%e] %v"); + wconsole->set_level(spdlog::level::debug); + va_list args; va_start(args, fmt); - vprintf(fmt, args); + + vsnprintf(buf, sizeof(buf), fmt, args); + + buf[sizeof(buf) - 1] = 0; va_end(args); + + vmStr.append(buf); + wconsole->debug(vmStr); + return NULL; } //--------------------------------------------------------------------------------- -// Load the include file from the mods directory +// Purpose: loads the include file from the mods directory //--------------------------------------------------------------------------------- - __int64 Hooks::SQVM_LoadRson(const char* rson_name) { char filepath[MAX_PATH] = { 0 }; @@ -63,9 +79,8 @@ __int64 Hooks::SQVM_LoadRson(const char* rson_name) } //--------------------------------------------------------------------------------- -// Load the script file from the mods directory +// Purpose: loads the script file from the mods directory //--------------------------------------------------------------------------------- - bool Hooks::SQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag) { char filepath[MAX_PATH] = { 0 }; diff --git a/r5dev/include/hooks.h b/r5dev/include/hooks.h index f1681cb3..2e591765 100644 --- a/r5dev/include/hooks.h +++ b/r5dev/include/hooks.h @@ -41,6 +41,10 @@ namespace Hooks #pragma region NetChannel bool NET_ReceiveDatagram(int sock, void* inpacket, bool raw); unsigned int NET_SendDatagram(SOCKET s, const char* buf, int len, int flags); + void NET_PrintFunc(const char* fmt, ...); + + using NET_PrintFuncFn = void(*)(const char* fmt, ...); + extern NET_PrintFuncFn originalNET_PrintFunc; using NET_ReceiveDatagramFn = bool(*)(int, void*, bool); extern NET_ReceiveDatagramFn originalNET_ReceiveDatagram; @@ -82,8 +86,8 @@ namespace Hooks void InstallHooks(); void RemoveHooks(); - void ToggleNetHooks(); - extern bool bToggledNetHooks; + void ToggleNetTrace(); + extern bool bToggledNetTrace; void ToggleDevCommands(); extern bool bToggledDevFlags; } \ No newline at end of file diff --git a/r5dev/include/patterns.h b/r5dev/include/patterns.h index e262cfd7..67402636 100644 --- a/r5dev/include/patterns.h +++ b/r5dev/include/patterns.h @@ -31,6 +31,9 @@ namespace #pragma endregion #pragma region NetChannel + /*0x1402655F0*/ + FUNC_AT_ADDRESS(addr_NET_PrintFunc, bool(*)(int, void*, bool), r5_patterns.PatternSearch("48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 C3 48").GetPtr()); + /*0x1402655F0*/ FUNC_AT_ADDRESS(addr_NET_ReceiveDatagram, bool(*)(int, void*, bool), r5_patterns.PatternSearch("48 89 74 24 18 48 89 7C 24 20 55 41 54 41 55 41 56 41 57 48 8D AC 24 50 EB").GetPtr()); @@ -64,6 +67,7 @@ namespace PRINT_ADDRESS("SQVM_Print", addr_SQVM_Print); PRINT_ADDRESS("SQVM_LoadScript", addr_SQVM_LoadScript); PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson); + PRINT_ADDRESS("NET_PrintFunc", addr_NET_PrintFunc); PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram); PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram); PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify); diff --git a/r5dev/include/pch.h b/r5dev/include/pch.h index 3a1f6c94..b42160e0 100644 --- a/r5dev/include/pch.h +++ b/r5dev/include/pch.h @@ -27,6 +27,8 @@ #include "imgui_impl_win32.h" #include "spdlog.h" #include "sinks/basic_file_sink.h" +#include "sinks/stdout_sinks.h" +#include "sinks/ostream_sink.h" #include "utility.h" #include "httplib.h" #include "json.hpp" diff --git a/r5dev/src/console.cpp b/r5dev/src/console.cpp index 7efe42c6..ec264a85 100644 --- a/r5dev/src/console.cpp +++ b/r5dev/src/console.cpp @@ -71,7 +71,7 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID) /////////////////////////////////////////////////////////////////////// // Engine toggles - if (sCommand == "toggle net") { Hooks::ToggleNetHooks(); continue; } + if (sCommand == "toggle net") { Hooks::ToggleNetTrace(); continue; } if (sCommand == "toggle dev") { Hooks::ToggleDevCommands(); continue; } if (sCommand == "toggle fal") { g_bReturnAllFalse = !g_bReturnAllFalse; continue; } /////////////////////////////////////////////////////////////////////// diff --git a/r5dev/src/hooks/hooks.cpp b/r5dev/src/hooks/hooks.cpp index 72ca5f24..212cf262 100644 --- a/r5dev/src/hooks/hooks.cpp +++ b/r5dev/src/hooks/hooks.cpp @@ -5,8 +5,8 @@ bool g_bBlockInput = false; namespace Hooks { - bool bToggledDevFlags = false; - bool bToggledNetHooks = false; + bool bToggledDevFlags = true; + bool bToggledNetTrace = false; } void Hooks::InstallHooks() @@ -28,6 +28,7 @@ void Hooks::InstallHooks() /////////////////////////////////////////////////////////////////////////////// // Hook Netchan functions + MH_CreateHook(addr_NET_PrintFunc, &Hooks::NET_PrintFunc, reinterpret_cast(&originalNET_PrintFunc)); MH_CreateHook(addr_NET_ReceiveDatagram, &Hooks::NET_ReceiveDatagram, reinterpret_cast(&originalNET_ReceiveDatagram)); MH_CreateHook(addr_NET_SendDatagram, &Hooks::NET_SendDatagram, reinterpret_cast(&originalNET_SendDatagram)); @@ -36,23 +37,34 @@ void Hooks::InstallHooks() MH_CreateHook(addr_ConVar_IsFlagSet, &Hooks::ConVar_IsFlagSet, NULL); MH_CreateHook(addr_ConCommand_IsFlagSet, &Hooks::ConCommand_IsFlagSet, NULL); - /////////////////////////////////////////////////////////////////////////////// - // Hook WinAPI - HMODULE user32dll = GetModuleHandleA("user32.dll"); - void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); - void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); - void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); - void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); - - MH_CreateHook(SetCursorPosPtr, &Hooks::SetCursorPos, reinterpret_cast(&originalSetCursorPos)); - MH_CreateHook(ClipCursorPtr, &Hooks::ClipCursor, reinterpret_cast(&originalClipCursor)); - MH_CreateHook(GetCursorPosPtr, &Hooks::GetCursorPos, reinterpret_cast(&originalGetCursorPos)); - MH_CreateHook(ShowCursorPtr, &Hooks::ShowCursor, reinterpret_cast(&originalShowCursor)); - /////////////////////////////////////////////////////////////////////////////// // Hook Utility functions MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast(&originalMSG_EngineError)); + /////////////////////////////////////////////////////////////////////////////// + // Hook WinAPI + HMODULE user32dll = GetModuleHandleA("user32.dll"); + + if (user32dll) + { + void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); + void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); + void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); + void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); + + MH_CreateHook(SetCursorPosPtr, &Hooks::SetCursorPos, reinterpret_cast(&originalSetCursorPos)); + MH_CreateHook(ClipCursorPtr, &Hooks::ClipCursor, reinterpret_cast(&originalClipCursor)); + MH_CreateHook(GetCursorPosPtr, &Hooks::GetCursorPos, reinterpret_cast(&originalGetCursorPos)); + MH_CreateHook(ShowCursorPtr, &Hooks::ShowCursor, reinterpret_cast(&originalShowCursor)); + + /////////////////////////////////////////////////////////////////////////// + // Enable WinAPI hooks + MH_EnableHook(SetCursorPosPtr); + MH_EnableHook(ClipCursorPtr); + MH_EnableHook(GetCursorPosPtr); + MH_EnableHook(ShowCursorPtr); + } + /////////////////////////////////////////////////////////////////////////////// // Enable Squirrel hooks MH_EnableHook(addr_SQVM_Print); @@ -65,15 +77,13 @@ void Hooks::InstallHooks() MH_EnableHook(addr_CVEngineServer_IsPersistenceDataAvailable); /////////////////////////////////////////////////////////////////////////////// - // Enable ConVar | ConCommand hooks - ToggleDevCommands(); + // Enable Netchan hooks + MH_EnableHook(addr_NET_PrintFunc); /////////////////////////////////////////////////////////////////////////////// - // Enable WinAPI hooks - MH_EnableHook(SetCursorPosPtr); - MH_EnableHook(ClipCursorPtr); - MH_EnableHook(GetCursorPosPtr); - MH_EnableHook(ShowCursorPtr); + // Enable ConVar | ConCommand hooks + MH_EnableHook(addr_ConVar_IsFlagSet); + MH_EnableHook(addr_ConCommand_IsFlagSet); /////////////////////////////////////////////////////////////////////////////// // Enabled Utility hooks @@ -95,6 +105,7 @@ void Hooks::RemoveHooks() /////////////////////////////////////////////////////////////////////////////// // Unhook Netchan functions + MH_RemoveHook(addr_NET_PrintFunc); MH_RemoveHook(addr_NET_ReceiveDatagram); MH_RemoveHook(addr_NET_SendDatagram); @@ -106,15 +117,19 @@ void Hooks::RemoveHooks() /////////////////////////////////////////////////////////////////////////////// // Unhook WinAPI HMODULE user32dll = GetModuleHandleA("user32.dll"); - void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); - void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); - void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); - void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); - MH_RemoveHook(SetCursorPosPtr); - MH_RemoveHook(ClipCursorPtr); - MH_RemoveHook(GetCursorPosPtr); - MH_RemoveHook(ShowCursorPtr); + if (user32dll) + { + void* SetCursorPosPtr = GetProcAddress(user32dll, "SetCursorPos"); + void* ClipCursorPtr = GetProcAddress(user32dll, "ClipCursor"); + void* GetCursorPosPtr = GetProcAddress(user32dll, "GetCursorPos"); + void* ShowCursorPtr = GetProcAddress(user32dll, "ShowCursor"); + + MH_RemoveHook(SetCursorPosPtr); + MH_RemoveHook(ClipCursorPtr); + MH_RemoveHook(GetCursorPosPtr); + MH_RemoveHook(ShowCursorPtr); + } /////////////////////////////////////////////////////////////////////////////// // Unhook Utility functions @@ -125,9 +140,9 @@ void Hooks::RemoveHooks() MH_Uninitialize(); } -void Hooks::ToggleNetHooks() +void Hooks::ToggleNetTrace() { - if (!bToggledNetHooks) + if (!bToggledNetTrace) { MH_EnableHook(addr_NET_ReceiveDatagram); MH_EnableHook(addr_NET_SendDatagram); @@ -147,7 +162,7 @@ void Hooks::ToggleNetHooks() printf("+--------------------------------------------------------+\n"); printf("\n"); } - bToggledNetHooks = !bToggledNetHooks; + bToggledNetTrace = !bToggledNetTrace; } void Hooks::ToggleDevCommands() diff --git a/r5dev/src/hooks/net.cpp b/r5dev/src/hooks/net.cpp index 59eb65f0..d6d6c98b 100644 --- a/r5dev/src/hooks/net.cpp +++ b/r5dev/src/hooks/net.cpp @@ -3,10 +3,50 @@ namespace Hooks { + NET_PrintFuncFn originalNET_PrintFunc = nullptr; NET_ReceiveDatagramFn originalNET_ReceiveDatagram = nullptr; NET_SendDatagramFn originalNET_SendDatagram = nullptr; } +//----------------------------------------------------------------------------- +// Purpose: log the clients signonstate to the console +//----------------------------------------------------------------------------- +void Hooks::NET_PrintFunc(const char* fmt, ...) +{ + static char buf[1024]; + + static auto iconsole = spdlog::stdout_logger_mt("net_iconsole"); // in-game console + static auto wconsole = spdlog::stdout_logger_mt("net_wconsole"); // windows console + + std::ostringstream oss; + auto ostream_sink = std::make_shared(oss); + + iconsole = std::make_shared("ostream", ostream_sink); + iconsole->set_pattern("[%S.%e] %v"); + iconsole->set_level(spdlog::level::debug); + wconsole->set_pattern("[%S.%e] %v"); + wconsole->set_level(spdlog::level::debug); + + va_list args; + va_start(args, fmt); + + vsnprintf(buf, sizeof(buf), fmt, args); + + buf[sizeof(buf) - 1] = 0; + va_end(args); + + iconsole->debug(buf); + wconsole->debug(buf); + + std::string s = oss.str(); + const char* c = s.c_str(); + + Items.push_back(Strdup((const char*)c)); +} + +//----------------------------------------------------------------------------- +// Purpose: hook and log the receive datagram +//----------------------------------------------------------------------------- bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) { bool result = originalNET_ReceiveDatagram(sock, inpacket, raw); @@ -23,6 +63,9 @@ bool Hooks::NET_ReceiveDatagram(int sock, void* inpacket, bool raw) return result; } +//----------------------------------------------------------------------------- +// Purpose: hook and log the send datagram +//----------------------------------------------------------------------------- unsigned int Hooks::NET_SendDatagram(SOCKET s, const char* buf, int len, int flags) { unsigned int result = originalNET_SendDatagram(s, buf, len, flags); diff --git a/r5dev/src/hooks/sqvm.cpp b/r5dev/src/hooks/sqvm.cpp index b0447e84..8eecd5f6 100644 --- a/r5dev/src/hooks/sqvm.cpp +++ b/r5dev/src/hooks/sqvm.cpp @@ -7,29 +7,52 @@ namespace Hooks SQVM_LoadScriptFn originalSQVM_LoadScript = nullptr; } -std::string prefixes[3] = { "Script(S)", "Script(C)", "Script(U)" }; - +//--------------------------------------------------------------------------------- +// Purpose: prints the output of each VM to the console +//--------------------------------------------------------------------------------- void* Hooks::SQVM_Print(void* sqvm, char* fmt, ...) { int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18); - char buf[1024]; + + static char buf[1024]; + static std::string vmType[3] = { "Script(S):", "Script(C):", "Script(U):" }; + + static auto iconsole = spdlog::stdout_logger_mt("sqvm_iconsole"); // in-game console + static auto wconsole = spdlog::stdout_logger_mt("sqvm_wconsole"); // windows console + + std::string vmStr = vmType[vmIdx].c_str(); + std::ostringstream oss; + auto ostream_sink = std::make_shared(oss); + + iconsole = std::make_shared("ostream", ostream_sink); + iconsole->set_pattern("[%S.%e] %v"); + iconsole->set_level(spdlog::level::debug); + wconsole->set_pattern("[%S.%e] %v"); + wconsole->set_level(spdlog::level::debug); + va_list args; va_start(args, fmt); - // external console - printf("%s:", prefixes[vmIdx].c_str()); - vprintf(fmt, args); - - // imgui console - vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args); - buf[IM_ARRAYSIZE(buf) - 1] = 0; + vsnprintf(buf, sizeof(buf), fmt, args); + buf[sizeof(buf) - 1] = 0; va_end(args); - Items.push_back(Strdup(buf)); + vmStr.append(buf); + + iconsole->debug(vmStr); + wconsole->debug(vmStr); + + std::string s = oss.str(); + const char* c = s.c_str(); + + Items.push_back(Strdup((const char*)c)); return NULL; } +//--------------------------------------------------------------------------------- +// Purpose: loads the include file from the mods directory +//--------------------------------------------------------------------------------- __int64 Hooks::SQVM_LoadRson(const char* rson_name) { char filepath[MAX_PATH] = { 0 }; @@ -67,6 +90,9 @@ __int64 Hooks::SQVM_LoadRson(const char* rson_name) return originalSQVM_LoadRson(rson_name); } +//--------------------------------------------------------------------------------- +// Purpose: loads the script file from the mods directory +//--------------------------------------------------------------------------------- bool Hooks::SQVM_LoadScript(void* sqvm, const char* script_path, const char* script_name, int flag) { char filepath[MAX_PATH] = { 0 }; diff --git a/r5dev/src/id3dx.cpp b/r5dev/src/id3dx.cpp index 7b3dce12..e906e91e 100644 --- a/r5dev/src/id3dx.cpp +++ b/r5dev/src/id3dx.cpp @@ -408,6 +408,58 @@ HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT n return originalPresent(pSwapChain, nSyncInterval, nFlags); } +bool LoadTextureFromByteArray(unsigned char* image_data, const int& image_width, const int& image_height, ID3D11ShaderResourceView** out_srv) +{ + // Load from disk into a raw RGBA buffer + //int image_width = 0; + //int image_height = 0; + //unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4); + if (image_data == NULL) + { + return false; + } + + // Create texture + D3D11_TEXTURE2D_DESC desc; + ID3D11Texture2D* pTexture = NULL; + D3D11_SUBRESOURCE_DATA subResource; + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + + ZeroMemory(&desc, sizeof(desc)); + desc.Width = image_width; + desc.Height = image_height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; + + subResource.pSysMem = image_data; + subResource.SysMemPitch = desc.Width * 4; + subResource.SysMemSlicePitch = 0; + + g_pDevice->CreateTexture2D(&desc, &subResource, &pTexture); + + // Create texture view + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + + if (pTexture) + { + g_pDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv); + } + pTexture->Release(); + + //stbi_image_free(image_data); + + return true; +} + //################################################################################# // MANAGEMENT //################################################################################# @@ -416,8 +468,11 @@ void InstallDXHooks() { HMODULE user32dll = GetModuleHandleA("user32.dll"); - IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); - IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + if (user32dll) + { + IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); + IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + } /////////////////////////////////////////////////////////////////////////////// // Hook PostMessage @@ -441,8 +496,11 @@ void RemoveDXHooks() { HMODULE user32dll = GetModuleHandleA("user32.dll"); - IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); - IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + if (user32dll) + { + IPostMessageA PostMessageA = (IPostMessageA)GetProcAddress(user32dll, "PostMessageA"); + IPostMessageW PostMessageW = (IPostMessageW)GetProcAddress(user32dll, "PostMessageW"); + } /////////////////////////////////////////////////////////////////////////////// // Unhook PostMessage @@ -498,47 +556,4 @@ void SetupDXSwapChain() //################################################################################# // UTILS -//################################################################################# -bool LoadTextureFromByteArray(unsigned char* image_data, const int &image_width, const int &image_height, ID3D11ShaderResourceView** out_srv) -{ - // Load from disk into a raw RGBA buffer - //int image_width = 0; - //int image_height = 0; - //unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4); - if (image_data == NULL) - return false; - - // Create texture - D3D11_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Width = image_width; - desc.Height = image_height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - ID3D11Texture2D* pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = image_data; - subResource.SysMemPitch = desc.Width * 4; - subResource.SysMemSlicePitch = 0; - g_pDevice->CreateTexture2D(&desc, &subResource, &pTexture); - - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pDevice->CreateShaderResourceView(pTexture, &srvDesc, out_srv); - pTexture->Release(); - - //stbi_image_free(image_data); - - return true; -} \ No newline at end of file +//################################################################################# \ No newline at end of file diff --git a/r5dev/src/opcptc.cpp b/r5dev/src/opcptc.cpp index f40351b0..c269b078 100644 --- a/r5dev/src/opcptc.cpp +++ b/r5dev/src/opcptc.cpp @@ -8,7 +8,7 @@ void InstallOpcodes() /* .TEXT */ { //------------------------------------------------------------------------- - // JNZ --> JMP | Prevent OriginSDK from initializing on the client + // JNZ --> JMP | Prevent OriginSDK from initializing //Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 }); //Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 }); //------------------------------------------------------------------------- diff --git a/r5dev/src/overlay.cpp b/r5dev/src/overlay.cpp index 1bccb3b6..2ab57b21 100644 --- a/r5dev/src/overlay.cpp +++ b/r5dev/src/overlay.cpp @@ -48,6 +48,8 @@ CGameConsole::~CGameConsole() void CGameConsole::Draw(const char* title) { + bool copy_to_clipboard = false; + if (!ThemeSet) { SetStyleVar(); @@ -56,7 +58,7 @@ void CGameConsole::Draw(const char* title) //ImGui::ShowStyleEditor(); - ImGui::SetNextWindowSize(ImVec2(840, 600), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(1000, 600), ImGuiCond_FirstUseEver); ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver); if (!ImGui::Begin(title, NULL)) // Passing a bool only causes problems if you Begin a new window. I would not suggest to use it. @@ -64,58 +66,59 @@ void CGameConsole::Draw(const char* title) ImGui::End(); return; } - /////////////////////////////////////////////////////////////////////// - // If bToggledDevFlags is true, override text color to be green, if its false red. - Hooks::bToggledDevFlags ? ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 255, 0, 255)) : ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 0, 0, 255)); - if (ImGui::SmallButton("Developer mode")) - { - Hooks::ToggleDevCommands(); - AddLog("+--------------------------------------------------------+\n"); - AddLog("|>>>>>>>>>>>>>>| DEVONLY COMMANDS TOGGLED |<<<<<<<<<<<<<<|\n"); - AddLog("+--------------------------------------------------------+\n"); - ProcessCommand("exec autoexec"); - } - ImGui::PopStyleColor(); // Pop color override. - - ImGui::SameLine(); - - // Do the same for bToggledNetHooks. - Hooks::bToggledNetHooks ? ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 255, 0, 255)) : ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 0, 0, 255)); - if (ImGui::SmallButton("Netchannel Trace")) - { - Hooks::ToggleNetHooks(); - AddLog("+--------------------------------------------------------+\n"); - AddLog("|>>>>>>>>>>>>>>| NETCHANNEL TRACE TOGGLED |<<<<<<<<<<<<<<|\n"); - AddLog("+--------------------------------------------------------+\n"); - ProcessCommand("exec netchan"); - } - - ImGui::PopStyleColor(); // Pop color override. + // Reserve enough left-over height and width for 1 separator + 1 input text + const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); + const float footer_width_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetWindowWidth(); /////////////////////////////////////////////////////////////////////// - ImGui::SameLine(); - if (ImGui::SmallButton("Clear")) - { - ClearLog(); - } - ImGui::SameLine(); - bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::Separator(); if (ImGui::BeginPopup("Options")) { - ImGui::Checkbox("Auto-scroll", &AutoScroll); ImGui::EndPopup(); + ImGui::Checkbox("Auto-scroll", &AutoScroll); + if (ImGui::SmallButton("Clear")) + { + ClearLog(); + } + copy_to_clipboard = ImGui::SmallButton("Copy"); + ImGui::EndPopup(); } if (ImGui::Button("Options")) { ImGui::OpenPopup("Options"); } ImGui::SameLine(); - Filter.Draw("Filter [\"-incl,-excl\"] [\"error\"]", 265); + if (ImGui::BeginPopup("Tools")) + { + Hooks::bToggledDevFlags ? ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 255, 0, 255)) : ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 0, 0, 255)); + if (ImGui::SmallButton("Developer Mode")) + { + Hooks::ToggleDevCommands(); + AddLog("+--------------------------------------------------------+\n"); + AddLog("|>>>>>>>>>>>>>>| DEVONLY COMMANDS TOGGLED |<<<<<<<<<<<<<<|\n"); + AddLog("+--------------------------------------------------------+\n"); + ProcessCommand("exec autoexec"); + } + ImGui::PopStyleColor(); // Pop color override. + Hooks::bToggledNetTrace ? ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0, 255, 0, 255)) : ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 0, 0, 255)); + if (ImGui::SmallButton("Netchannel Trace")) + { + Hooks::ToggleNetTrace(); + AddLog("+--------------------------------------------------------+\n"); + AddLog("|>>>>>>>>>>>>>>| NETCHANNEL TRACE TOGGLED |<<<<<<<<<<<<<<|\n"); + AddLog("+--------------------------------------------------------+\n"); + ProcessCommand("exec netchan"); + } + ImGui::PopStyleColor(); // Pop color override. + ImGui::EndPopup(); + } + if (ImGui::Button("Tools")) + { + ImGui::OpenPopup("Tools"); + } + ImGui::SameLine(); + Filter.Draw("Filter [\"-incl,-excl\"] [\"error\"]", footer_width_to_reserve - 500); ImGui::Separator(); - // Reserve enough left-over height for 1 separator + 1 input text - const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); - /////////////////////////////////////////////////////////////////////// ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f }); @@ -136,15 +139,21 @@ void CGameConsole::Draw(const char* title) /////////////////////////////////////////////////////////////////// // General - if (strstr(item, "[INFO]")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; } - if (strstr(item, "[ERROR]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } - if (strstr(item, "[DEBUG]")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } - if (strstr(item, "[WARNING]")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } - if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); has_color = true; } + if (strstr(item, "[INFO]")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; } + if (strstr(item, "[ERROR]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } + if (strstr(item, "[DEBUG]")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } + if (strstr(item, "[WARNING]")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } + if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); has_color = true; } + + /////////////////////////////////////////////////////////////////// + // Virtual machines + if (strstr(item, "Script(S):")) { color = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); has_color = true; } + if (strstr(item, "Script(C):")) { color = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); has_color = true; } + if (strstr(item, "Script(U):")) { color = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); has_color = true; } /////////////////////////////////////////////////////////////////// // Callbacks - if (strstr(item, "CodeCallback_")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } + //if (strstr(item, "CodeCallback_")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } /////////////////////////////////////////////////////////////////// // Script errors @@ -157,21 +166,20 @@ void CGameConsole::Draw(const char* title) if (strstr(item, "SCRIPT COMPILE")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } if (strstr(item, ".gnut #")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } if (strstr(item, ".nut #")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } - if (strstr(item, " -> ")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } + if (strstr(item, "): -> ")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; } /////////////////////////////////////////////////////////////////// // Script debug - if (strstr(item, "CALLSTACK")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } - if (strstr(item, "LOCALS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } - if (strstr(item, "*FUNCTION")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } - if (strstr(item, "DIAGPRINTS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } - if (strstr(item, " File : ")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } - if (strstr(item, "<><>GRX<><>")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } + if (strstr(item, "CALLSTACK")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } + if (strstr(item, "LOCALS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } + if (strstr(item, "*FUNCTION")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } + if (strstr(item, "DIAGPRINTS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; } + if (strstr(item, " File : ")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } + if (strstr(item, "<><>GRX<><>")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; } /////////////////////////////////////////////////////////////////// // Filters - if (strstr(item, ") -> ")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; } - /////////////////////////////////////////////////////////////////// + //if (strstr(item, ") -> ")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; } if (has_color) { ImGui::PushStyleColor(ImGuiCol_Text, color); } ImGui::TextWrapped(item); @@ -190,7 +198,7 @@ void CGameConsole::Draw(const char* title) /////////////////////////////////////////////////////////////////////// // Console bool reclaim_focus = false; - ImGui::PushItemWidth(750); + ImGui::PushItemWidth(footer_width_to_reserve - 80); if (ImGui::IsWindowAppearing()) { ImGui::SetKeyboardFocusHere(); } ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; diff --git a/shared/utility.cpp b/shared/utility.cpp index 9e85ef8d..eb308a8e 100644 --- a/shared/utility.cpp +++ b/shared/utility.cpp @@ -133,7 +133,7 @@ void HexDump(const char* szHeader, int nFunc, const void* pData, int nSize) // Add timestamp logger->set_level(spdlog::level::trace); - logger->set_pattern("%v [%H:%M:%S.%f]"); + logger->set_pattern("%v [%H:%M:%S.%f]\n"); logger->trace("---------------------------------------------------------"); // Disable EOL and create block header