mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Read description for changes.
* Completely re-wrote the DirectX creation and hooks. * Using spdlog mostly everywhere now. * Added prints for when compiled in debug. * Using LockCursor now to prevent input to the game while in the gui. * Patched the game to call CMatSystemSurface::LockCursor instead of it calling the inlined version. * Added rebuild CHostState::FrameUpdate (Not finished yet) * Added option to print to command prompt again. * Added log Auto-Clear. * Added scan for NetChan Encryption Key Pointer. * Added more error handling when loading gui config.
This commit is contained in:
parent
27536741f8
commit
17d45a02aa
@ -8,7 +8,7 @@ void DrawConsole();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Globals
|
||||
inline ImVector<char*> Items;
|
||||
extern ImVector<char*> Items;
|
||||
|
||||
class CGameConsole
|
||||
{
|
||||
@ -33,6 +33,7 @@ public:
|
||||
void ProcessCommand(const char* command_line);
|
||||
void ExecCommand(const char* command_line);
|
||||
int TextEditCallback(ImGuiInputTextCallbackData* data);
|
||||
bool ShouldPrintToCommandPrompt() { return g_GuiConfig.CGameConsoleConfig.printCmd; };
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// History
|
||||
@ -46,9 +47,9 @@ public:
|
||||
// Utility
|
||||
void ClearLog()
|
||||
{
|
||||
for (int i = 0; i < Items.Size; i++) { free(Items[i]); }
|
||||
Items.clear();
|
||||
}
|
||||
|
||||
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
|
||||
{
|
||||
char buf[1024];
|
||||
|
@ -332,7 +332,7 @@ enum ClientFrameStage_t
|
||||
FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE
|
||||
};
|
||||
|
||||
enum HostStates_t
|
||||
enum class HostStates_t : int
|
||||
{
|
||||
HS_NEW_GAME = 0x0,
|
||||
HS_LOAD_GAME = 0x1,
|
||||
|
@ -239,8 +239,8 @@ struct QAngle // Implement the proper class of this at some point.
|
||||
class CHostState
|
||||
{
|
||||
public:
|
||||
int m_iCurrentState; //0x0000
|
||||
int m_iNextState; //0x0004
|
||||
HostStates_t m_iCurrentState; //0x0000
|
||||
HostStates_t m_iNextState; //0x0004
|
||||
Vector3 m_vecLocation; //0x0008
|
||||
QAngle m_angLocation; //0x0014
|
||||
char m_levelName[64]; //0x0020
|
||||
|
@ -14,6 +14,9 @@ public:
|
||||
{
|
||||
int bind1 = VK_OEM_3;
|
||||
int bind2 = VK_INSERT;
|
||||
int autoClearLimit = 300;
|
||||
bool autoClear = true;
|
||||
bool printCmd = false;
|
||||
} CGameConsoleConfig;
|
||||
|
||||
struct
|
||||
@ -24,13 +27,13 @@ public:
|
||||
|
||||
void Load()
|
||||
{
|
||||
spdlog::debug("Loading the Gui Config..\n");
|
||||
std::filesystem::path path = std::filesystem::current_path() /= "gui.config"; // Get current path + gui.config
|
||||
|
||||
nlohmann::json in;
|
||||
std::ifstream configFile(path, std::ios::in); // Parse config file.
|
||||
|
||||
if (configFile.good() && configFile) // Check if it parsed.
|
||||
try
|
||||
{
|
||||
std::ifstream configFile(path, std::ios::binary); // Parse config file.
|
||||
configFile >> in;
|
||||
configFile.close();
|
||||
|
||||
@ -41,6 +44,9 @@ public:
|
||||
// CGameConsole
|
||||
CGameConsoleConfig.bind1 = in["config"]["CGameConsole"]["bind1"].get<int>();
|
||||
CGameConsoleConfig.bind2 = in["config"]["CGameConsole"]["bind2"].get<int>();
|
||||
CGameConsoleConfig.autoClearLimit = in["config"]["CGameConsole"]["autoClearLimit"].get<int>();
|
||||
CGameConsoleConfig.autoClear = in["config"]["CGameConsole"]["autoClear"].get<bool>();
|
||||
CGameConsoleConfig.printCmd = in["config"]["CGameConsole"]["printCmd"].get<bool>();
|
||||
|
||||
// CCompanion
|
||||
CCompanionConfig.bind1 = in["config"]["CCompanion"]["bind1"].get<int>();
|
||||
@ -48,6 +54,11 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
{
|
||||
spdlog::critical("Gui Config loading failed. Perhaps re-create it by messing with Options in CGameConsole. Reason: {}\n", ex.what());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Save()
|
||||
@ -57,6 +68,9 @@ public:
|
||||
// CGameConsole
|
||||
out["config"]["CGameConsole"]["bind1"] = CGameConsoleConfig.bind1;
|
||||
out["config"]["CGameConsole"]["bind2"] = CGameConsoleConfig.bind2;
|
||||
out["config"]["CGameConsole"]["autoClearLimit"] = CGameConsoleConfig.autoClearLimit;
|
||||
out["config"]["CGameConsole"]["autoClear"] = CGameConsoleConfig.autoClear;
|
||||
out["config"]["CGameConsole"]["printCmd"] = CGameConsoleConfig.printCmd;
|
||||
|
||||
// CCompanion
|
||||
out["config"]["CCompanion"]["bind1"] = CCompanionConfig.bind1;
|
||||
|
@ -87,6 +87,13 @@ namespace Hooks
|
||||
extern ConCommand_IsFlagSetFn originalConCommand_IsFlagSet;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CMatSystemSurface
|
||||
void LockCursor(void* thisptr);
|
||||
|
||||
using LockCursorFn = void(*)(void*);
|
||||
extern LockCursorFn originalLockCursor;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region WinAPI
|
||||
BOOL WINAPI GetCursorPos(LPPOINT lpPoint);
|
||||
BOOL WINAPI SetCursorPos(int X, int Y);
|
||||
@ -113,6 +120,13 @@ namespace Hooks
|
||||
extern FileSystemWarningFn originalFileSystemWarning;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region HostState
|
||||
void FrameUpdate(void* rcx, void* rdx, float time);
|
||||
|
||||
using FrameUpdateFn = void(*)(void*, void*, float);
|
||||
extern FrameUpdateFn originalFrameUpdate;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Other
|
||||
int MSG_EngineError(char* fmt, va_list args);
|
||||
bool LoadPlaylist(const char* playlist);
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Initialization
|
||||
void SetupImGui();
|
||||
void SetupDXSwapChain();
|
||||
void DrawImGui();
|
||||
void DestroyRenderTarget();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Internals
|
||||
@ -17,16 +14,14 @@ void RemoveDXHooks();
|
||||
// Handlers
|
||||
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
extern HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags);
|
||||
extern HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Globals
|
||||
extern DWORD g_dThreadId;
|
||||
extern BOOL g_bShowConsole;
|
||||
extern BOOL g_bShowBrowser;
|
||||
extern bool g_bShowConsole;
|
||||
extern bool g_bShowBrowser;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#################################################################################
|
||||
// UTILS
|
||||
//#################################################################################
|
||||
// Utils
|
||||
bool LoadTextureFromByteArray(unsigned char* image_data, const int& image_width, const int& image_height, ID3D11ShaderResourceView** out_srv);
|
@ -80,8 +80,8 @@ namespace
|
||||
FUNC_AT_ADDRESS(addr_NetChan_Shutdown, void(*)(void*, const char*, unsigned __int8, char), r5_patterns.StringSearch("Disconnect by server.\n").FindPatternSelf("E8 ? ? ? ? 4C 89 B3 ? ? ? ?", MemoryAddress::Direction::DOWN).FollowNearCallSelf().GetPtr());
|
||||
|
||||
/*0x160686DC0*/
|
||||
MemoryAddress addr_NetChan_EncKeyPtr = MemoryAddress(0x160686DC0);
|
||||
char* addr_NetChan_EncKey = addr_NetChan_EncKeyPtr.Offset(4816).RCast<char*>();
|
||||
MemoryAddress addr_NetChan_EncKeyPtr = r5_patterns.StringSearch("client:NetEncryption_NewKey").FindPatternSelf("48 8D ? ? ? ? ? 48 3B", MemoryAddress::Direction::UP, 150).ResolveRelativeAddressSelf(0x3, 0x7);
|
||||
char* addr_NetChan_EncKey = addr_NetChan_EncKeyPtr.Offset(0x12D0).RCast<char*>();
|
||||
|
||||
/*0x140263E70*/
|
||||
FUNC_AT_ADDRESS(addr_NetChan_SetEncKey, void(*)(uintptr_t, const char*), MemoryAddress(0x140263E70).GetPtr());
|
||||
@ -121,6 +121,12 @@ namespace
|
||||
FUNC_AT_ADDRESS(addr_CBaseFileSystem_FileSystemWarning, void(*)(void*, FileWarningLevel_t, const char*, ...), r5_patterns.PatternSearch("E8 ? ? ? ? 33 C0 80 3B 2A").FollowNearCallSelf().GetPtr());
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CMatSystemSurface
|
||||
/*0x140548A00*/
|
||||
FUNC_AT_ADDRESS(addr_CMatSystemSurface_LockCursor, void(*)(void*), MemoryAddress(0x140548A00).GetPtr()); // Maybe sigscan this via RTTI.
|
||||
|
||||
/*0x1405489C0*/
|
||||
FUNC_AT_ADDRESS(addr_CMatSystemSurface_UnlockCursor, void(*)(void*), MemoryAddress(0x1405489C0).GetPtr()); // Maybe sigscan this via RTTI.
|
||||
#pragma region Utility
|
||||
/*0x140295600*/
|
||||
FUNC_AT_ADDRESS(addr_MSG_EngineError, int(*)(char*, va_list), r5_patterns.StringSearch("Engine Error").FindPatternSelf("48 89 ? ? ? 48 89", MemoryAddress::Direction::UP, 500).GetPtr());
|
||||
@ -174,7 +180,7 @@ namespace
|
||||
PRINT_ADDRESS("CClient::Clear", addr_CClient_Clear);
|
||||
PRINT_ADDRESS("INetChannel::Shutdown", addr_NetChan_Shutdown);
|
||||
PRINT_ADDRESS("INetChannel::SetEncryptionKey", addr_NetChan_SetEncKey);
|
||||
PRINT_ADDRESS("INetChannel::EncryptionKey", addr_NetChan_EncKey)
|
||||
PRINT_ADDRESS("INetChannel::EncryptionKey", addr_NetChan_EncKey);
|
||||
PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify);
|
||||
PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
|
||||
PRINT_ADDRESS("CServer::ConnectClient", addr_CServer_ConnectClient);
|
||||
|
@ -388,8 +388,10 @@ if not EXIST $(SolutionDir)r5net\lib\$(Configuration)\r5net.lib (
|
||||
<ClCompile Include="src\hooks\connectclient.cpp" />
|
||||
<ClCompile Include="src\hooks\cvengineserver.cpp" />
|
||||
<ClCompile Include="src\hooks\hooks.cpp" />
|
||||
<ClCompile Include="src\hooks\hoststate.cpp" />
|
||||
<ClCompile Include="src\hooks\iconvar.cpp" />
|
||||
<ClCompile Include="src\hooks\loadplaylist.cpp" />
|
||||
<ClCompile Include="src\hooks\lockcursor.cpp" />
|
||||
<ClCompile Include="src\hooks\msgbox.cpp" />
|
||||
<ClCompile Include="src\hooks\net.cpp" />
|
||||
<ClCompile Include="src\hooks\netchannel.cpp" />
|
||||
|
@ -106,6 +106,12 @@
|
||||
<Filter Include="hooks\src\cserver">
|
||||
<UniqueIdentifier>{10edfee7-8c10-41de-b8f3-424826d2614a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="hooks\src\hoststate">
|
||||
<UniqueIdentifier>{02d83321-09fe-4a60-86d9-b1e8d5e165f4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="hooks\src\cmatsystemsurface">
|
||||
<UniqueIdentifier>{a2663195-c4f2-4d5f-8d65-cfed54976e4c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\dllmain.cpp">
|
||||
@ -204,6 +210,12 @@
|
||||
<ClCompile Include="src\squirrel.cpp">
|
||||
<Filter>r5-sdk\src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\hooks\hoststate.cpp">
|
||||
<Filter>hooks\src\hoststate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\hooks\lockcursor.cpp">
|
||||
<Filter>hooks\src\cmatsystemsurface</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\external\imgui\include\imgui_impl_win32.h">
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include "CCompanion.h"
|
||||
#include "r5net.h"
|
||||
|
||||
//#define OVERLAY_DEBUG
|
||||
|
||||
CCompanion* g_ServerBrowser = nullptr;
|
||||
bool g_CheckCompBanDB = true;
|
||||
|
||||
@ -92,16 +90,17 @@ void CCompanion::UpdateHostingStatus()
|
||||
if (*reinterpret_cast<std::int32_t*>(0x1656057E0) == NULL) // Check if script checksum is valid yet.
|
||||
break;
|
||||
|
||||
switch (ServerVisibility) {
|
||||
switch (ServerVisibility)
|
||||
{
|
||||
|
||||
case EServerVisibility::Hidden:
|
||||
MyServer.hidden = true;
|
||||
break;
|
||||
|
||||
break;
|
||||
case EServerVisibility::Public:
|
||||
MyServer.hidden = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SendHostingPostRequest();
|
||||
@ -122,9 +121,7 @@ void CCompanion::RefreshServerList()
|
||||
{
|
||||
std::thread t([this]()
|
||||
{
|
||||
#ifdef OVERLAY_DEBUG
|
||||
std::cout << " [+CCompanion+] Refreshing server list with string " << MatchmakingServerStringBuffer << "\n";
|
||||
#endif
|
||||
spdlog::debug("[+CCompanion+] Refreshing server list with string {}\n", MatchmakingServerStringBuffer);
|
||||
bThreadLocked = true;
|
||||
ServerList = r5net->GetServersList(ServerListMessage);
|
||||
bThreadLocked = false;
|
||||
@ -137,6 +134,7 @@ void CCompanion::RefreshServerList()
|
||||
void CCompanion::SendHostingPostRequest()
|
||||
{
|
||||
HostToken = std::string();
|
||||
spdlog::debug("[+CCompanion+] Sending PostServerHost request now..\n");
|
||||
bool result = r5net->PostServerHost(HostRequestMessage,HostToken,
|
||||
ServerListing{
|
||||
MyServer.name,
|
||||
@ -255,10 +253,11 @@ void CCompanion::ServerBrowserSection()
|
||||
{
|
||||
ImGui::InputTextWithHint("##ServerBrowser_ServerConnString", "Enter IP address or \"localhost\"", ServerConnStringBuffer, IM_ARRAYSIZE(ServerConnStringBuffer));
|
||||
|
||||
ImGui::SameLine(); ImGui::InputTextWithHint("##ServerBrowser_ServerEncKey", "Enter the encryption key", ServerEncKeyBuffer, IM_ARRAYSIZE(ServerEncKeyBuffer));
|
||||
ImGui::SameLine();
|
||||
ImGui::InputTextWithHint("##ServerBrowser_ServerEncKey", "Enter the encryption key", ServerEncKeyBuffer, IM_ARRAYSIZE(ServerEncKeyBuffer));
|
||||
ImGui::SameLine();
|
||||
|
||||
|
||||
if (ImGui::SameLine(); ImGui::Button("Connect##ServerBrowser_ConnectByIp", ImVec2(ImGui::GetWindowContentRegionWidth() / 4, 18.5)))
|
||||
if (ImGui::Button("Connect##ServerBrowser_ConnectByIp", ImVec2(ImGui::GetWindowContentRegionWidth() / 4, 18.5)))
|
||||
{
|
||||
ConnectToServer(ServerConnStringBuffer, ServerEncKeyBuffer);
|
||||
}
|
||||
@ -274,8 +273,6 @@ void CCompanion::ServerBrowserSection()
|
||||
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CCompanion::HiddenServersModal()
|
||||
@ -465,6 +462,7 @@ void CCompanion::HostServerSection()
|
||||
{
|
||||
if (!MyServer.name.empty() && !MyServer.playlist.empty())
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Starting Server with name {}, map {} and playlist {}..\n", MyServer.name, ServerMap, MyServer.playlist);
|
||||
ServerNameErr = std::string();
|
||||
UpdateHostingStatus();
|
||||
|
||||
@ -482,11 +480,6 @@ void CCompanion::HostServerSection()
|
||||
std::stringstream cmd;
|
||||
cmd << "map " << ServerMap;
|
||||
ProcessCommand(cmd.str().c_str());
|
||||
|
||||
if (StartAsDedi)
|
||||
{
|
||||
Hooks::ToggleDevCommands();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -512,18 +505,21 @@ void CCompanion::HostServerSection()
|
||||
{
|
||||
if (ImGui::Button("Reload Scripts##ServerHost_ReloadServerButton", ImVec2(ImGui::GetWindowSize().x, 32)))
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Reloading scripts..\n");
|
||||
ProcessCommand("reparse_weapons");
|
||||
ProcessCommand("reload");
|
||||
}
|
||||
|
||||
if (ImGui::Button("Change Level##ServerHost_ChangeLevel", ImVec2(ImGui::GetWindowSize().x, 32)))
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Changing level to {}..\n", ServerMap);
|
||||
strncpy_s(GameGlobals::HostState->m_levelName, ServerMap.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname.
|
||||
GameGlobals::HostState->m_iNextState = HostStates_t::HS_CHANGE_LEVEL_MP; // Force CHostState::FrameUpdate to change the level.
|
||||
}
|
||||
|
||||
if (ImGui::Button("Stop Server##ServerHost_StopServerButton", ImVec2(ImGui::GetWindowSize().x, 32)))
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Stopping server..\n");
|
||||
ProcessCommand("LeaveMatch"); // Use script callback instead.
|
||||
GameGlobals::HostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN; // Force CHostState::FrameUpdate to shutdown the server for dedicated.
|
||||
}
|
||||
@ -594,6 +590,7 @@ void CCompanion::Draw(const char* title)
|
||||
|
||||
void CCompanion::ProcessCommand(const char* command_line)
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Processing command {}\n", command_line);
|
||||
std::thread t(&CCompanion::ExecCommand, this, command_line);
|
||||
t.detach();
|
||||
|
||||
@ -635,15 +632,16 @@ void CCompanion::ConnectToServer(const std::string connString, const std::string
|
||||
|
||||
void CCompanion::RegenerateEncryptionKey()
|
||||
{
|
||||
spdlog::debug("[+CCompanion+] Regenerating Encryption Key..\n");
|
||||
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||
if (BCryptOpenAlgorithmProvider(&hAlgorithm, L"RNG", 0, 0) < 0)
|
||||
{
|
||||
std::cerr << "Failed to open rng algorithm\n";
|
||||
spdlog::critical("[+CCompanion+] Failed to open rng algorithm\n");
|
||||
}
|
||||
unsigned char pBuffer[0x10u];
|
||||
if (BCryptGenRandom(hAlgorithm, pBuffer, 0x10u, 0) < 0)
|
||||
{
|
||||
std::cerr << "Failed to generate random data\n";
|
||||
spdlog::critical("[+CCompanion+] Failed to generate random data\n");
|
||||
}
|
||||
std::string fin;
|
||||
|
||||
@ -671,6 +669,7 @@ void DrawBrowser()
|
||||
static CCompanion browser;
|
||||
static bool AssignPtr = []() {
|
||||
g_ServerBrowser = &browser;
|
||||
spdlog::debug("[+CCompanion+] Created CCompanion Class instance.\n");
|
||||
return true;
|
||||
} ();
|
||||
|
||||
|
@ -6,9 +6,8 @@
|
||||
#include "gameclasses.h"
|
||||
#include "CGameConsole.h"
|
||||
|
||||
#define OVERLAY_DEBUG
|
||||
|
||||
CGameConsole* g_GameConsole = nullptr;
|
||||
ImVector<char*> Items;
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* _cgameconsole.cpp
|
||||
@ -35,17 +34,16 @@ CGameConsole::CGameConsole()
|
||||
CGameConsole::~CGameConsole()
|
||||
{
|
||||
ClearLog();
|
||||
for (int i = 0; i < History.Size; i++)
|
||||
{
|
||||
free(History[i]);
|
||||
}
|
||||
History.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Draw
|
||||
void CGameConsole::Draw(const char* title)
|
||||
{
|
||||
bool copy_to_clipboard = false;
|
||||
bool CopyToClipboard = false;
|
||||
static auto cgameconsoleConfig = &g_GuiConfig.CGameConsoleConfig;
|
||||
static auto ccompanionConfig = &g_GuiConfig.CCompanionConfig;
|
||||
|
||||
if (!ThemeSet)
|
||||
{
|
||||
@ -53,6 +51,12 @@ void CGameConsole::Draw(const char* title)
|
||||
ThemeSet = true;
|
||||
}
|
||||
|
||||
if (cgameconsoleConfig->autoClear && Items.Size > cgameconsoleConfig->autoClearLimit) // Check if Auto-Clear is enabled and if its above our limit. If yes then clear.
|
||||
{
|
||||
ClearLog();
|
||||
History.clear();
|
||||
}
|
||||
|
||||
//ImGui::ShowStyleEditor();
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(1000, 600), ImGuiCond_FirstUseEver);
|
||||
@ -60,7 +64,6 @@ void CGameConsole::Draw(const char* title)
|
||||
|
||||
ImGui::Begin(title, NULL); // ImGui::Begin should never fail, if it does we got another problem.
|
||||
{
|
||||
|
||||
// Reserve enough left-over height and width for 1 separator + 1 input text
|
||||
const float FooterHeightToReserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
||||
const float FooterWidthtoReserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetWindowWidth();
|
||||
@ -69,24 +72,38 @@ void CGameConsole::Draw(const char* title)
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginPopup("Options"))
|
||||
{
|
||||
ImGui::Checkbox("Auto-scroll", &AutoScroll);
|
||||
if (ImGui::Checkbox("Print to Cmd", &cgameconsoleConfig->printCmd))
|
||||
g_GuiConfig.Save();
|
||||
|
||||
ImGui::Checkbox("Auto-Scroll", &AutoScroll);
|
||||
|
||||
if (ImGui::Checkbox("Auto-Clear", &cgameconsoleConfig->autoClear))
|
||||
g_GuiConfig.Save();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::PushItemWidth(100);
|
||||
if (ImGui::InputInt("Auto Clear Limit##AutoClearAfterCertainIndexCGameConsole", &cgameconsoleConfig->autoClearLimit))
|
||||
g_GuiConfig.Save();
|
||||
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::SmallButton("Clear"))
|
||||
{
|
||||
ClearLog();
|
||||
}
|
||||
copy_to_clipboard = ImGui::SmallButton("Copy");
|
||||
|
||||
ImGui::SameLine();
|
||||
CopyToClipboard = ImGui::SmallButton("Copy");
|
||||
ImGui::Text("CG Hotkey:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Hotkey("##OpenCGameConsoleBind1", &g_GuiConfig.CGameConsoleConfig.bind1, ImVec2(80, 80)))
|
||||
{
|
||||
if (ImGui::Hotkey("##OpenCGameConsoleBind1", &cgameconsoleConfig->bind1, ImVec2(80, 80)))
|
||||
g_GuiConfig.Save();
|
||||
}
|
||||
|
||||
ImGui::Text("CC Hotkey:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Hotkey("##OpenCCompanionBind1", &g_GuiConfig.CCompanionConfig.bind1, ImVec2(80, 80)))
|
||||
{
|
||||
|
||||
if (ImGui::Hotkey("##OpenCCompanionBind1", &ccompanionConfig->bind1, ImVec2(80, 80)))
|
||||
g_GuiConfig.Save();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (ImGui::Button("Options"))
|
||||
@ -139,10 +156,11 @@ void CGameConsole::Draw(const char* title)
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::BeginChild("ScrollingRegion", ImVec2(0, -FooterHeightToReserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f });
|
||||
if (copy_to_clipboard)
|
||||
if (CopyToClipboard)
|
||||
{
|
||||
ImGui::LogToClipboard();
|
||||
}
|
||||
|
||||
for (int i = 0; i < Items.Size; i++)
|
||||
{
|
||||
const char* item = Items[i];
|
||||
@ -214,12 +232,15 @@ void CGameConsole::Draw(const char* title)
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_to_clipboard)
|
||||
if (CopyToClipboard)
|
||||
{
|
||||
ImGui::LogFinish();
|
||||
}
|
||||
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) { ImGui::SetScrollHereY(1.0f); }
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
|
||||
{
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
ScrollToBottom = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@ -390,6 +411,7 @@ void DrawConsole()
|
||||
static CGameConsole console;
|
||||
static bool AssignPtr = []() {
|
||||
g_GameConsole = &console;
|
||||
spdlog::debug("[+CGameConsole+] Created CGameConsole Class instance.\n");
|
||||
return true;
|
||||
} ();
|
||||
console.Draw("Console");
|
||||
|
@ -52,6 +52,16 @@ void SetupConsole()
|
||||
printf("THREAD ID: %ld\n\n", threadId0);
|
||||
CloseHandle(hThread0);
|
||||
}
|
||||
|
||||
// Initialize global spdlog.
|
||||
auto console = spdlog::stdout_logger_mt("console");
|
||||
console->set_pattern("[%I:%M:%S:%e] [%L] %v"); // Set pattern.
|
||||
spdlog::set_default_logger(console); // Set as default.
|
||||
spdlog::flush_every(std::chrono::seconds(5)); // Flush buffers every 5 seconds for every logger.
|
||||
#ifdef _DEBUG
|
||||
console->set_level(spdlog::level::debug);
|
||||
#endif
|
||||
spdlog::debug("Console and spdlog are setup now!\n");
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
|
@ -17,10 +17,12 @@ void InitializeR5Dev()
|
||||
InstallOpcodes();
|
||||
g_GuiConfig.Load(); // Load gui config.
|
||||
SetupDXSwapChain();
|
||||
printf("+-----------------------------------------------------------------------------+\n");
|
||||
printf("| R5 DEV -- INITIALIZED ------------------------------------------------- |\n");
|
||||
printf("+-----------------------------------------------------------------------------+\n");
|
||||
printf("\n");
|
||||
|
||||
spdlog::get("console")->set_pattern("%v");
|
||||
spdlog::info("+-----------------------------------------------------------------------------+\n");
|
||||
spdlog::info("| R5 DEV -- INITIALIZED ------------------------------------------------- |\n");
|
||||
spdlog::info("+-----------------------------------------------------------------------------+\n");
|
||||
spdlog::get("console")->set_pattern("[%I:%M:%S:%e] [%L] %v");
|
||||
}
|
||||
|
||||
void TerminateR5Dev()
|
||||
|
@ -326,6 +326,7 @@ namespace GameGlobals
|
||||
|
||||
void NullHostNames()
|
||||
{
|
||||
spdlog::debug("Nulling host names..\n");
|
||||
const char* hostnameArray[] =
|
||||
{
|
||||
"pin_telemetry_hostname",
|
||||
@ -356,6 +357,7 @@ namespace GameGlobals
|
||||
|
||||
void InitGameGlobals()
|
||||
{
|
||||
spdlog::debug("Initializing Game Globals..\n");
|
||||
HostState = reinterpret_cast<CHostState*>(0x141736120); // Get CHostState from memory.
|
||||
InputSystem = *reinterpret_cast<CInputSystem**>(0x14D40B380); // Get IInputSystem from memory.
|
||||
Cvar = *reinterpret_cast<CCVar**>(0x14D40B348); // Get CCVar from memory.
|
||||
@ -377,6 +379,7 @@ namespace GameGlobals
|
||||
|
||||
void InitPlaylist()
|
||||
{
|
||||
spdlog::debug("Parsing Playlist..\n");
|
||||
while (true)
|
||||
{
|
||||
if ((*PlaylistKeyValues))
|
||||
@ -400,6 +403,7 @@ namespace GameGlobals
|
||||
|
||||
void InitAllCommandVariations()
|
||||
{
|
||||
spdlog::debug("Initializing all Custom ConVars and Commands..\n");
|
||||
void* CGameConsoleConCommand = CreateCustomConCommand("cgameconsole", "Opens the R5 Reloaded Console.", 0, CustomCommandVariations::CGameConsole_Callback, nullptr);
|
||||
void* CCompanionConCommand = CreateCustomConCommand("ccompanion", "Opens the R5 Reloaded Server Browser.", 0, CustomCommandVariations::CCompanion_Callback, nullptr);
|
||||
void* KickConCommand = CreateCustomConCommand("kick", "Kick a client from the Server via name. | Usage: kick (name).", 0, CustomCommandVariations::Kick_Callback, nullptr);
|
||||
|
@ -61,8 +61,6 @@ void* Hooks::ConnectClient(void* thisptr, void* packet)
|
||||
finalIPAddress = ss.str();
|
||||
}
|
||||
|
||||
R5Net::Client* r5net = g_ServerBrowser->GetR5Net();
|
||||
|
||||
const char* name = *(const char**)((std::uintptr_t)packet + 0x30);
|
||||
std::int64_t originID = *(std::int64_t*)((std::uintptr_t)packet + 0x28);
|
||||
|
||||
@ -80,6 +78,7 @@ void* Hooks::ConnectClient(void* thisptr, void* packet)
|
||||
|
||||
if (g_CheckCompBanDB)
|
||||
{
|
||||
R5Net::Client* r5net = g_ServerBrowser->GetR5Net();
|
||||
if (r5net)
|
||||
{
|
||||
std::thread t1(IsClientBanned, r5net, finalIPAddress, originID);
|
||||
|
@ -13,6 +13,7 @@ void Hooks::InstallHooks()
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Initialize Minhook
|
||||
spdlog::debug("Hooking game functions now..\n");
|
||||
MH_Initialize();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -25,7 +26,7 @@ void Hooks::InstallHooks()
|
||||
MH_CreateHook(addr_SQVM_RegisterCreatePlayerTasklist, &Hooks::SQVM_RegisterCreatePlayerTasklist, reinterpret_cast<void**>(&originalSQVM_RegisterCreatePlayerTasklist));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook Game Functions
|
||||
// Hook Game functions
|
||||
MH_CreateHook(addr_CHLClient_FrameStageNotify, &Hooks::FrameStageNotify, reinterpret_cast<void**>(&originalFrameStageNotify));
|
||||
MH_CreateHook(addr_CVEngineServer_IsPersistenceDataAvailable, &Hooks::IsPersistenceDataAvailable, reinterpret_cast<void**>(&originalIsPersistenceDataAvailable));
|
||||
MH_CreateHook(addr_CServer_ConnectClient, &Hooks::ConnectClient, reinterpret_cast<void**>(&originalConnectClient));
|
||||
@ -38,14 +39,22 @@ void Hooks::InstallHooks()
|
||||
MH_CreateHook(addr_NetChan_Shutdown, &Hooks::NetChan_Shutdown, reinterpret_cast<void**>(&originalNetChan_ShutDown));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook ConVar | ConCommand functions.
|
||||
// Hook ConVar | ConCommand functions
|
||||
MH_CreateHook(addr_ConVar_IsFlagSet, &Hooks::ConVar_IsFlagSet, reinterpret_cast<void**>(&originalConVar_IsFlagSet));
|
||||
MH_CreateHook(addr_ConCommand_IsFlagSet, &Hooks::ConCommand_IsFlagSet, reinterpret_cast<void**>(&originalConCommand_IsFlagSet));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hooks CBaseFileSystem functions.
|
||||
// Hook CMatSystemSurface functions
|
||||
MH_CreateHook(addr_CMatSystemSurface_LockCursor, &LockCursor, reinterpret_cast<void**>(&originalLockCursor));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook CBaseFileSystem functions
|
||||
//MH_CreateHook(addr_CBaseFileSystem_FileSystemWarning, &Hooks::FileSystemWarning, reinterpret_cast<void**>(&originalFileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook HostState functions
|
||||
//MH_CreateHook(MemoryAddress(0x14023EF80).RCast<void*>(), &Hooks::FrameUpdate, reinterpret_cast<void**>(&originalFrameUpdate));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook Utility functions
|
||||
MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast<void**>(&originalMSG_EngineError));
|
||||
@ -59,12 +68,10 @@ void Hooks::InstallHooks()
|
||||
void* ClipCursorPtr = user32dll.GetExportedFunction("ClipCursor");
|
||||
void* GetCursorPosPtr = user32dll.GetExportedFunction("GetCursorPos");
|
||||
void* ShowCursorPtr = user32dll.GetExportedFunction("ShowCursor");
|
||||
|
||||
MH_CreateHook(SetCursorPosPtr, &Hooks::SetCursorPos, reinterpret_cast<void**>(&originalSetCursorPos));
|
||||
MH_CreateHook(ClipCursorPtr, &Hooks::ClipCursor, reinterpret_cast<void**>(&originalClipCursor));
|
||||
MH_CreateHook(GetCursorPosPtr, &Hooks::GetCursorPos, reinterpret_cast<void**>(&originalGetCursorPos));
|
||||
MH_CreateHook(ShowCursorPtr, &Hooks::ShowCursor, reinterpret_cast<void**>(&originalShowCursor));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Enable WinAPI hooks
|
||||
MH_EnableHook(SetCursorPosPtr);
|
||||
@ -98,10 +105,18 @@ void Hooks::InstallHooks()
|
||||
MH_EnableHook(addr_ConVar_IsFlagSet);
|
||||
MH_EnableHook(addr_ConCommand_IsFlagSet);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enable CMatSystemSurface hooks
|
||||
MH_EnableHook(addr_CMatSystemSurface_LockCursor);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enable CBaseFileSystem hooks
|
||||
//MH_EnableHook(addr_CBaseFileSystem_FileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enable HostState hooks
|
||||
// MH_EnableHook(MemoryAddress(0x14023EF80).RCast<void*>());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enabled Utility hooks
|
||||
MH_EnableHook(addr_MSG_EngineError);
|
||||
@ -132,10 +147,19 @@ void Hooks::RemoveHooks()
|
||||
MH_RemoveHook(addr_NetChan_Shutdown);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook ConVar | ConCommand functions.
|
||||
// Unhook ConVar | ConCommand functions
|
||||
MH_RemoveHook(addr_ConVar_IsFlagSet);
|
||||
MH_RemoveHook(addr_ConCommand_IsFlagSet);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook CMatSystemSurface functions
|
||||
MH_EnableHook(MemoryAddress(0x140548A00).RCast<void*>());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook Utility functions
|
||||
MH_RemoveHook(addr_MSG_EngineError);
|
||||
MH_RemoveHook(addr_LoadPlaylist);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook WinAPI
|
||||
if (Module user32dll = Module("user32.dll"); user32dll.GetModuleBase()) // Is user32.dll valid?
|
||||
@ -144,22 +168,20 @@ void Hooks::RemoveHooks()
|
||||
void* ClipCursorPtr = user32dll.GetExportedFunction("ClipCursor");
|
||||
void* GetCursorPosPtr = user32dll.GetExportedFunction("GetCursorPos");
|
||||
void* ShowCursorPtr = user32dll.GetExportedFunction("ShowCursor");
|
||||
|
||||
MH_RemoveHook(SetCursorPosPtr);
|
||||
MH_RemoveHook(ClipCursorPtr);
|
||||
MH_RemoveHook(GetCursorPosPtr);
|
||||
MH_RemoveHook(ShowCursorPtr);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook Utility functions
|
||||
MH_RemoveHook(addr_MSG_EngineError);
|
||||
MH_RemoveHook(addr_LoadPlaylist);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook CBaseFileSystem functions.
|
||||
//MH_RemoveHook(addr_CBaseFileSystem_FileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook HostState hooks
|
||||
//MH_RemoveHook(MemoryAddress(0x14023EF80).RCast<void*>());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Reset Minhook
|
||||
MH_Uninitialize();
|
||||
@ -171,21 +193,21 @@ void Hooks::ToggleNetTrace()
|
||||
{
|
||||
MH_EnableHook(addr_NET_ReceiveDatagram);
|
||||
MH_EnableHook(addr_NET_SendDatagram);
|
||||
printf("\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("|>>>>>>>>>>>>>| NETCHANNEL TRACE ACTIVATED |<<<<<<<<<<<<<|\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
MH_DisableHook(addr_NET_ReceiveDatagram);
|
||||
MH_DisableHook(addr_NET_SendDatagram);
|
||||
printf("\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("|>>>>>>>>>>>>| NETCHANNEL TRACE DEACTIVATED |<<<<<<<<<<<<|\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("\n");
|
||||
}
|
||||
bToggledNetTrace = !bToggledNetTrace;
|
||||
}
|
||||
@ -196,21 +218,21 @@ void Hooks::ToggleDevCommands()
|
||||
{
|
||||
MH_EnableHook(addr_ConVar_IsFlagSet);
|
||||
MH_EnableHook(addr_ConCommand_IsFlagSet);
|
||||
printf("\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("|>>>>>>>>>>>>>| DEVONLY COMMANDS ACTIVATED |<<<<<<<<<<<<<|\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
MH_DisableHook(addr_ConVar_IsFlagSet);
|
||||
MH_DisableHook(addr_ConCommand_IsFlagSet);
|
||||
printf("\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n");
|
||||
printf("+--------------------------------------------------------+\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("|>>>>>>>>>>>>| DEVONLY COMMANDS DEACTIVATED |<<<<<<<<<<<<|\n");
|
||||
spdlog::info("+--------------------------------------------------------+\n");
|
||||
spdlog::info("\n");
|
||||
}
|
||||
bToggledDevFlags = !bToggledDevFlags;
|
||||
}
|
||||
|
179
r5dev/src/hooks/hoststate.cpp
Normal file
179
r5dev/src/hooks/hoststate.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
#include "pch.h"
|
||||
#include "hooks.h"
|
||||
|
||||
namespace Hooks
|
||||
{
|
||||
FrameUpdateFn originalFrameUpdate = nullptr;
|
||||
}
|
||||
|
||||
void Hooks::FrameUpdate(void* rcx, void* rdx, float time)
|
||||
{
|
||||
static auto setjmpFn = MemoryAddress(0x141205460).RCast<__int64(*)(jmp_buf, void*)>();
|
||||
static auto host_abortserver = MemoryAddress(0x14B37C700).RCast<jmp_buf*>();
|
||||
static auto CHostState_InitFn = MemoryAddress(0x14023E7D0).RCast<void(*)(CHostState*)>();
|
||||
static auto g_ServerAbortServer = MemoryAddress(0x14B37CA22).RCast<char*>();
|
||||
static auto State_RunFn = MemoryAddress(0x14023E870).RCast<void(*)(HostStates_t*,void*,float)>();
|
||||
static auto Cbuf_ExecuteFn = MemoryAddress(0x14020D5C0).RCast<void(*)()>();
|
||||
static auto g_ServerGameClients = MemoryAddress(0x14B383428).RCast<__int64*>();
|
||||
static auto SV_InitGameDLLFn = MemoryAddress(0x140308B90).RCast<void(*)()>();
|
||||
static auto g_CModelLoader = MemoryAddress(0x14173B210).RCast<void*>();
|
||||
static auto CModelLoader_Map_IsValidFn = MemoryAddress(0x1402562F0).RCast<bool(*)(void*, const char*)>();
|
||||
static auto Host_NewGameFn = MemoryAddress(0x140238DA0).RCast<bool(*)(char*, char*, bool, bool, void*)>();
|
||||
static auto Host_Game_ShutdownFn = MemoryAddress(0x14023EDA0).RCast<void(*)(CHostState*)>();
|
||||
static auto src_drawloading = MemoryAddress(0x14B37D96B).RCast<char*>();
|
||||
static auto scr_engineevent_loadingstarted = MemoryAddress(0x1666ED024).RCast<char*>();
|
||||
static auto gfExtendedError = MemoryAddress(0x14B383391).RCast<char*>();
|
||||
static auto g_CEngineVGui = MemoryAddress(0x141741310).RCast<void*>();
|
||||
static auto g_ServerDLL = MemoryAddress(0x141732048).RCast<void**>();
|
||||
static auto Host_ChangelevelFn = MemoryAddress(0x1402387B0).RCast<void(*)(bool, const char*, const char*)>();
|
||||
|
||||
void* placeHolder = nullptr;
|
||||
if (setjmpFn(*host_abortserver, placeHolder))
|
||||
{
|
||||
CHostState_InitFn(GameGlobals::HostState);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
*g_ServerAbortServer = true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
Cbuf_ExecuteFn();
|
||||
HostStates_t oldState = GameGlobals::HostState->m_iCurrentState;
|
||||
switch (GameGlobals::HostState->m_iCurrentState)
|
||||
{
|
||||
case HostStates_t::HS_NEW_GAME:
|
||||
{
|
||||
// Inlined CHostState::State_NewGame
|
||||
GameGlobals::HostState->m_bSplitScreenConnect = false;
|
||||
if (!g_ServerGameClients) // Init Game if it ain't valid.
|
||||
{
|
||||
SV_InitGameDLLFn();
|
||||
}
|
||||
|
||||
if (!g_ServerGameClients) // SV_InitGameDLL failed its still null.
|
||||
{
|
||||
std::cout << "Fatal CHostState::FrameUpdate Error. SV_InitGameDLL() failed." << std::endl;
|
||||
abort(); // Placeholder.
|
||||
}
|
||||
|
||||
if ( !CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName) // Check if map is valid and if we can start a new game.
|
||||
|| !Host_NewGameFn(GameGlobals::HostState->m_levelName, nullptr, GameGlobals::HostState->m_bBackgroundLevel, GameGlobals::HostState->m_bSplitScreenConnect, nullptr) )
|
||||
{
|
||||
// Inlined SCR_EndLoadingPlaque
|
||||
if (*src_drawloading)
|
||||
{
|
||||
*scr_engineevent_loadingstarted = 0;
|
||||
using HideLoadingPlaqueFn = void(*)(void*);
|
||||
(*reinterpret_cast<HideLoadingPlaqueFn**>(g_CEngineVGui))[36](g_CEngineVGui); // (*((void(__fastcall**)(void**))g_CEngineVGui + 36))(&g_CEngineVGui);// HideLoadingPlaque
|
||||
}
|
||||
else if (*gfExtendedError)
|
||||
{
|
||||
using ShowErrorMessageFn = void(*)(void*);
|
||||
(*reinterpret_cast<ShowErrorMessageFn**>(g_CEngineVGui))[35](g_CEngineVGui); // (*((void(__fastcall**)(void**))g_CEngineVGui + 35))(&g_CEngineVGui);// ShowErrorMessage
|
||||
}
|
||||
// End Inline SCR_EndLoadingPlaque
|
||||
|
||||
// Inlined CHostState::GameShutdown
|
||||
if (GameGlobals::HostState->m_bActiveGame)
|
||||
{
|
||||
using GameShutdownFn = void(*)(void*);
|
||||
(*reinterpret_cast<GameShutdownFn**>(g_ServerDLL))[9](g_ServerDLL); // (*(void(__fastcall**)(void*))(*(_QWORD*)g_ServerDLL + 72i64))(g_ServerDLL);// GameShutdown
|
||||
GameGlobals::HostState->m_bActiveGame = 0;
|
||||
}
|
||||
// End Inline CHostState::GameShutdown
|
||||
}
|
||||
|
||||
// Seems useless so nope.
|
||||
// if (g_CHLClient)
|
||||
// (*(void(__fastcall**)(__int64, _QWORD))(*(_QWORD*)g_CHLClient + 1000i64))(g_CHLClient, 0i64);
|
||||
|
||||
GameGlobals::HostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run.
|
||||
|
||||
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
|
||||
if (GameGlobals::HostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !GameGlobals::Cvar->FindVar("host_hasIrreversibleShutdown")->m_iValue)
|
||||
GameGlobals::HostState->m_iNextState = HostStates_t::HS_RUN;
|
||||
|
||||
// End Inline CHostState::State_NewGame
|
||||
break;
|
||||
}
|
||||
case HostStates_t::HS_CHANGE_LEVEL_SP:
|
||||
{
|
||||
GameGlobals::HostState->m_flShortFrameTime = 1.5; // Set frame time.
|
||||
if (CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName)) // Check if map is valid and if we can start a new game.
|
||||
{
|
||||
Host_ChangelevelFn(true, GameGlobals::HostState->m_levelName, GameGlobals::HostState->m_mapGroupName); // Call change level as singleplayer level.
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Fatal CHostState::FrameUpdate Error. Map is not valid.";
|
||||
}
|
||||
|
||||
// Seems useless so nope.
|
||||
// if (g_CHLClient)
|
||||
// (*(void(__fastcall**)(__int64, _QWORD))(*(_QWORD*)g_CHLClient + 1000i64))(g_CHLClient, 0i64);
|
||||
|
||||
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
|
||||
if (GameGlobals::HostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !GameGlobals::Cvar->FindVar("host_hasIrreversibleShutdown")->m_iValue)
|
||||
GameGlobals::HostState->m_iNextState = HostStates_t::HS_RUN;
|
||||
|
||||
break;
|
||||
}
|
||||
case HostStates_t::HS_CHANGE_LEVEL_MP:
|
||||
{
|
||||
GameGlobals::HostState->m_flShortFrameTime = 1.5; // Set frame time.
|
||||
using LevelShutdownFn = void(__thiscall*)(void*);
|
||||
(*reinterpret_cast<LevelShutdownFn**>(*g_ServerDLL))[8](g_ServerDLL); // (*(void (__fastcall **)(void *))(*(_QWORD *)server_dll_var + 64i64))(server_dll_var);// LevelShutdown
|
||||
|
||||
if (CModelLoader_Map_IsValidFn(g_CModelLoader, GameGlobals::HostState->m_levelName)) // Check if map is valid and if we can start a new game.
|
||||
{
|
||||
using ShowErrorMessageFn = void(*)(void*);
|
||||
(*reinterpret_cast<ShowErrorMessageFn**>(g_CEngineVGui))[31](g_CEngineVGui); // (*((void(__fastcall**)(void**))g_CEngineVGUI + 31))(&g_CEngineVGUI);// EnabledProgressBarForNextLoad
|
||||
Host_ChangelevelFn(false, GameGlobals::HostState->m_levelName, GameGlobals::HostState->m_mapGroupName); // Call change level as singleplayer level.
|
||||
}
|
||||
|
||||
// Seems useless so nope.
|
||||
// // if (g_CHLClient)
|
||||
// (*(void(__fastcall**)(__int64, _QWORD))(*(_QWORD*)g_CHLClient + 1000i64))(g_CHLClient, 0i64);
|
||||
|
||||
// If our next state isn't a shutdown or its a forced shutdown then set next state to run.
|
||||
if (GameGlobals::HostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !GameGlobals::Cvar->FindVar("host_hasIrreversibleShutdown")->m_iValue)
|
||||
GameGlobals::HostState->m_iNextState = HostStates_t::HS_RUN;
|
||||
|
||||
break;
|
||||
}
|
||||
case HostStates_t::HS_RUN:
|
||||
{
|
||||
State_RunFn(&GameGlobals::HostState->m_iCurrentState, nullptr, time);
|
||||
break;
|
||||
}
|
||||
case HostStates_t::HS_GAME_SHUTDOWN:
|
||||
{
|
||||
Host_Game_ShutdownFn(GameGlobals::HostState);
|
||||
break;
|
||||
}
|
||||
case HostStates_t::HS_RESTART:
|
||||
{
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldState == HostStates_t::HS_RUN)
|
||||
break;
|
||||
|
||||
if (oldState == HostStates_t::HS_SHUTDOWN || oldState == HostStates_t::HS_RESTART)
|
||||
break;
|
||||
|
||||
if (oldState == HostStates_t::HS_GAME_SHUTDOWN)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
// originalFrameUpdate(rcx, rdx, time);
|
||||
}
|
18
r5dev/src/hooks/lockcursor.cpp
Normal file
18
r5dev/src/hooks/lockcursor.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "pch.h"
|
||||
#include "hooks.h"
|
||||
#include "id3dx.h"
|
||||
|
||||
namespace Hooks
|
||||
{
|
||||
LockCursorFn originalLockCursor = nullptr;
|
||||
}
|
||||
|
||||
void Hooks::LockCursor(void* thisptr)
|
||||
{
|
||||
if (g_bShowConsole || g_bShowBrowser)
|
||||
{
|
||||
addr_CMatSystemSurface_UnlockCursor(thisptr); // Unlock cursor if our gui is shown.
|
||||
return;
|
||||
}
|
||||
return originalLockCursor(thisptr);
|
||||
}
|
@ -51,12 +51,18 @@ void* Hooks::SQVM_Print(void* sqvm, char* fmt, ...)
|
||||
|
||||
vmStr.append(buf);
|
||||
|
||||
if (g_GameConsole && g_GameConsole->ShouldPrintToCommandPrompt())
|
||||
{
|
||||
spdlog::info(vmStr);
|
||||
}
|
||||
|
||||
logger.debug(vmStr);
|
||||
|
||||
|
||||
std::string s = oss_print.str();
|
||||
const char* c = s.c_str();
|
||||
|
||||
Items.push_back(Strdup((const char*)c));
|
||||
Items.push_back(Strdup(c));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -97,12 +103,17 @@ __int64 Hooks::SQVM_Warning(void* sqvm, int a2, int a3, int* stringSize, void**
|
||||
std::string stringConstructor((char*)*string, *stringSize); // Get string from memory via std::string constructor.
|
||||
vmStr.append(stringConstructor);
|
||||
|
||||
if (g_GameConsole && g_GameConsole->ShouldPrintToCommandPrompt())
|
||||
{
|
||||
spdlog::info(vmStr);
|
||||
}
|
||||
|
||||
logger.debug(vmStr);
|
||||
|
||||
std::string s = oss_warning.str();
|
||||
const char* c = s.c_str();
|
||||
|
||||
Items.push_back(Strdup((const char*)c));
|
||||
Items.push_back(Strdup(c));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -129,20 +140,20 @@ __int64 Hooks::SQVM_LoadRson(const char* rson_name)
|
||||
// Returns the new path if the rson exists on the disk
|
||||
if (FileExists(filepath) && originalSQVM_LoadRson(rson_name))
|
||||
{
|
||||
printf("\n");
|
||||
printf("##################################################\n");
|
||||
printf("] '%s'\n", filepath);
|
||||
printf("##################################################\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("##################################################\n");
|
||||
spdlog::info("] '{}'\n", filepath);
|
||||
spdlog::info("##################################################\n");
|
||||
spdlog::info("\n");
|
||||
|
||||
return originalSQVM_LoadRson(filepath);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("##################################################\n");
|
||||
printf("] '%s'\n", rson_name);
|
||||
printf("##################################################\n");
|
||||
printf("\n");
|
||||
spdlog::info("\n");
|
||||
spdlog::info("##################################################\n");
|
||||
spdlog::info("] '{}'\n", rson_name);
|
||||
spdlog::info("##################################################\n");
|
||||
spdlog::info("\n");
|
||||
|
||||
return originalSQVM_LoadRson(rson_name);
|
||||
}
|
||||
@ -166,7 +177,7 @@ bool Hooks::SQVM_LoadScript(void* sqvm, const char* script_path, const char* scr
|
||||
}
|
||||
if (g_bDebugLoading)
|
||||
{
|
||||
printf(" [+] Loading SQVM Script '%s' ...\n", filepath);
|
||||
spdlog::info(" [+] Loading SQVM Script '{}' ...\n", filepath);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Returns true if the script exists on the disk
|
||||
@ -176,7 +187,7 @@ bool Hooks::SQVM_LoadScript(void* sqvm, const char* script_path, const char* scr
|
||||
}
|
||||
if (g_bDebugLoading)
|
||||
{
|
||||
printf(" [!] FAILED. Try SP / VPK for '%s'\n", filepath);
|
||||
spdlog::info(" [!] FAILED. Try SP / VPK for '%s'\n", filepath);
|
||||
}
|
||||
|
||||
return originalSQVM_LoadScript(sqvm, script_path, script_name, flag);
|
||||
|
@ -10,51 +10,29 @@
|
||||
#include "CGameConsole.h"
|
||||
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
|
||||
/*---------------------------------------------------------------------------------
|
||||
* _id3dx.cpp
|
||||
*---------------------------------------------------------------------------------*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Type definitions.
|
||||
typedef HRESULT(__stdcall* IDXGISwapChainPresent)(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags);
|
||||
typedef HRESULT(__stdcall* IDXGIResizeBuffers) (IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
typedef BOOL(WINAPI* IPostMessageA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
typedef BOOL(WINAPI* IPostMessageW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
extern BOOL g_bShowConsole = false;
|
||||
extern BOOL g_bShowBrowser = false;
|
||||
static BOOL g_bInitMenu = false;
|
||||
static BOOL g_bInitialized = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
static WNDPROC g_oWndProc = NULL;
|
||||
static HWND g_hGameWindow = NULL;
|
||||
extern DWORD g_dThreadId = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
static IDXGISwapChainPresent g_fnIDXGISwapChainPresent = nullptr;
|
||||
static IDXGISwapChain* g_pSwapChain = nullptr;
|
||||
static IDXGIResizeBuffers g_oResizeBuffers = nullptr;
|
||||
static ID3D11DeviceContext* g_pDeviceContext = nullptr;
|
||||
static ID3D11Device* g_pDevice = nullptr;
|
||||
static ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
|
||||
static ID3D11DepthStencilView* g_pDepthStencilView = nullptr;
|
||||
static IPostMessageA g_oPostMessageA = nullptr;
|
||||
static IPostMessageW g_oPostMessageW = nullptr;
|
||||
|
||||
//#################################################################################
|
||||
// WINDOW PROCEDURE
|
||||
//#################################################################################
|
||||
// Variables.
|
||||
bool g_bShowConsole = false;
|
||||
bool g_bShowBrowser = false;
|
||||
IDXGISwapChainPresent g_fnIDXGISwapChainPresent = nullptr;
|
||||
IDXGIResizeBuffers g_fnIDXGIResizeBuffers = nullptr;
|
||||
ID3D11Device* g_pDevice = nullptr;
|
||||
ID3D11RenderTargetView* g_pMainRenderTargetView = nullptr;
|
||||
ID3D11DeviceContext* g_pDeviceContext = nullptr;
|
||||
WNDPROC originalWndProc = NULL;
|
||||
DWORD g_dThreadId = NULL;
|
||||
|
||||
LRESULT CALLBACK DXGIMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN)
|
||||
{
|
||||
@ -70,313 +48,113 @@ LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
}
|
||||
|
||||
if (g_bShowConsole || g_bShowBrowser)
|
||||
{//////////////////////////////////////////////////////////////////////////////
|
||||
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
g_bBlockInput = true;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_LBUTTONDOWN:
|
||||
return 1L;
|
||||
case WM_LBUTTONUP:
|
||||
return 1L;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
return 1L;
|
||||
case WM_RBUTTONDOWN:
|
||||
return 1L;
|
||||
case WM_RBUTTONUP:
|
||||
return 1L;
|
||||
case WM_RBUTTONDBLCLK:
|
||||
return 1L;
|
||||
case WM_MBUTTONDOWN:
|
||||
return 1L;
|
||||
case WM_MBUTTONUP:
|
||||
return 1L;
|
||||
case WM_MBUTTONDBLCLK:
|
||||
return 1L;
|
||||
case WM_KEYDOWN:
|
||||
return 1L;
|
||||
case WM_KEYUP:
|
||||
return 1L;
|
||||
case WM_MOUSEACTIVATE:
|
||||
return 1L;
|
||||
case WM_MOUSEHOVER:
|
||||
return 1L;
|
||||
case WM_MOUSEHWHEEL:
|
||||
return 1L;
|
||||
case WM_MOUSELEAVE:
|
||||
return 1L;
|
||||
case WM_MOUSEMOVE:
|
||||
return 1L;
|
||||
case WM_MOUSEWHEEL:
|
||||
return 1L;
|
||||
case WM_SETCURSOR:
|
||||
return 1L;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}//////////////////////////////////////////////////////////////////////////////
|
||||
else
|
||||
{
|
||||
g_bBlockInput = false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
return CallWindowProc(g_oWndProc, hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
// POST MESSAGE
|
||||
//#################################################################################
|
||||
|
||||
BOOL WINAPI HPostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return g_oPostMessageA(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
BOOL WINAPI HPostMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (g_bBlockInput && Msg == WM_MOUSEMOVE)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return g_oPostMessageW(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
// IDXGI PRESENT
|
||||
//#################################################################################
|
||||
|
||||
void GetPresent()
|
||||
{
|
||||
WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC, DXGIMsgProc, 0L, 0L, GetModuleHandleA(NULL), NULL, NULL, NULL, NULL, "DX", NULL };
|
||||
RegisterClassExA(&wc);
|
||||
|
||||
HWND hWnd = CreateWindowA("DX", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL);
|
||||
DXGI_SWAP_CHAIN_DESC sd = { 0 };
|
||||
D3D_FEATURE_LEVEL nFeatureLevelsSet = D3D_FEATURE_LEVEL_11_0;
|
||||
D3D_FEATURE_LEVEL nFeatureLevelsSupported;
|
||||
|
||||
ZeroMemory(&sd, sizeof(sd));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
sd.BufferCount = 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
sd.BufferDesc.Height = 800;
|
||||
sd.BufferDesc.Width = 600;
|
||||
sd.BufferDesc.RefreshRate = { 60, 1 };
|
||||
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
sd.Windowed = TRUE;
|
||||
sd.OutputWindow = hWnd;
|
||||
sd.SampleDesc.Count = 1;
|
||||
sd.SampleDesc.Quality = 0;
|
||||
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
g_hGameWindow = sd.OutputWindow;
|
||||
UINT nFeatureLevelsRequested = 1;
|
||||
HRESULT hr = 0;
|
||||
IDXGISwapChain* pSwapChain = nullptr;
|
||||
ID3D11Device* pDevice = nullptr;
|
||||
ID3D11DeviceContext* pContext = nullptr;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
if (FAILED(hr = D3D11CreateDeviceAndSwapChain(NULL,
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
NULL,
|
||||
NULL,
|
||||
&nFeatureLevelsSet,
|
||||
nFeatureLevelsRequested,
|
||||
D3D11_SDK_VERSION,
|
||||
&sd,
|
||||
&pSwapChain,
|
||||
&pDevice,
|
||||
&nFeatureLevelsSupported,
|
||||
&pContext)))
|
||||
{
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
std::cout << "| >>>>>>>>>| VIRTUAL METHOD TABLE HOOK FAILED |<<<<<<<<< |" << std::endl;
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
RemoveDXHooks();
|
||||
return;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DWORD_PTR* pSwapChainVtable = nullptr;
|
||||
DWORD_PTR* pContextVTable = nullptr;
|
||||
DWORD_PTR* pDeviceVTable = nullptr;
|
||||
|
||||
pSwapChainVtable = (DWORD_PTR*)pSwapChain;
|
||||
pSwapChainVtable = (DWORD_PTR*)pSwapChainVtable[0];
|
||||
pContextVTable = (DWORD_PTR*)pContext;
|
||||
pContextVTable = (DWORD_PTR*)pContextVTable[0];
|
||||
pDeviceVTable = (DWORD_PTR*)pDevice;
|
||||
pDeviceVTable = (DWORD_PTR*)pDeviceVTable[0];
|
||||
|
||||
g_fnIDXGISwapChainPresent = (IDXGISwapChainPresent)(DWORD_PTR)pSwapChainVtable[(int)DXGISwapChainVTbl::Present];
|
||||
g_oResizeBuffers = (IDXGIResizeBuffers)(DWORD_PTR)pSwapChainVtable[(int)DXGISwapChainVTbl::ResizeBuffers];
|
||||
|
||||
pSwapChain->Release();
|
||||
pContext->Release();
|
||||
pDevice->Release();
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
// INITIALIZATION
|
||||
//#################################################################################
|
||||
|
||||
void SetupImGui()
|
||||
{
|
||||
ImGui::CreateContext();
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
ImGui_ImplWin32_Init(g_hGameWindow);
|
||||
ImGui_ImplDX11_Init(g_pDevice, g_pDeviceContext);
|
||||
ImGui::GetIO().ImeWindowHandle = g_hGameWindow;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
}
|
||||
|
||||
void DrawImGui()
|
||||
{
|
||||
if (!GameGlobals::IsInitialized || !GameGlobals::InputSystem) // Check if GameGlobals initialized and if InputSystem is valid.
|
||||
return;
|
||||
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (g_bShowConsole || g_bShowBrowser)
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(false); // Disable input.
|
||||
g_bBlockInput = true; // Prevent mouse cursor from being modified if console is open.
|
||||
if (ImGui_ImplWin32_WndProcHandler(hwnd, uMsg, wParam, lParam) > 0)
|
||||
return 1L;
|
||||
}
|
||||
else
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(true); // Enable input.
|
||||
g_bBlockInput = false; // Allow mouse input.
|
||||
}
|
||||
|
||||
if (g_bShowConsole)
|
||||
{
|
||||
DrawConsole();
|
||||
}
|
||||
|
||||
if (g_bShowBrowser)
|
||||
{
|
||||
DrawBrowser();
|
||||
}
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
g_pDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);
|
||||
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||
return CallWindowProc(originalWndProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void CreateRenderTarget(IDXGISwapChain* pSwapChain)
|
||||
void InitRenderer()
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DXGI_SWAP_CHAIN_DESC sd = { 0 };
|
||||
ID3D11Texture2D* pBackBuffer = { 0 };
|
||||
D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc;
|
||||
spdlog::debug("Registering temporary Window for DirectX..\n");
|
||||
// Register temporary window instance to get DirectX 11 relevant virtual function ptr.
|
||||
WNDCLASSEX ws;
|
||||
ws.cbSize = sizeof(WNDCLASSEX);
|
||||
ws.style = CS_HREDRAW | CS_VREDRAW;
|
||||
ws.lpfnWndProc = DXGIMsgProc;
|
||||
ws.cbClsExtra = 0;
|
||||
ws.cbWndExtra = 0;
|
||||
ws.hInstance = GetModuleHandle(NULL);
|
||||
ws.hIcon = NULL;
|
||||
ws.hCursor = NULL;
|
||||
ws.hbrBackground = NULL;
|
||||
ws.lpszMenuName = NULL;
|
||||
ws.lpszClassName = "R5 Reloaded";
|
||||
ws.hIconSm = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
pSwapChain->GetDesc(&sd);
|
||||
ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc));
|
||||
RegisterClassEx(&ws);
|
||||
|
||||
// Create temporary window.
|
||||
HWND window = CreateWindowA(ws.lpszClassName, "R5 Reloaded Window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, ws.hInstance, NULL);
|
||||
|
||||
g_hGameWindow = sd.OutputWindow;
|
||||
render_target_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
DXGI_RATIONAL refreshRate;
|
||||
refreshRate.Numerator = 60;
|
||||
refreshRate.Denominator = 1;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
|
||||
if (pBackBuffer != NULL) { g_pDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_pRenderTargetView); }
|
||||
g_pDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);
|
||||
pBackBuffer->Release();
|
||||
}
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
|
||||
|
||||
void DestroyRenderTarget()
|
||||
{
|
||||
if (g_pRenderTargetView)
|
||||
// Setup buffer description.
|
||||
DXGI_MODE_DESC bufferDescription;
|
||||
bufferDescription.Width = 100;
|
||||
bufferDescription.Height = 100;
|
||||
bufferDescription.RefreshRate = refreshRate;
|
||||
bufferDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
bufferDescription.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
bufferDescription.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC sampleDescription;
|
||||
sampleDescription.Count = 1;
|
||||
sampleDescription.Quality = 0;
|
||||
|
||||
// Setup swap chain description.
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDescription;
|
||||
swapChainDescription.BufferDesc = bufferDescription;
|
||||
swapChainDescription.SampleDesc = sampleDescription;
|
||||
swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDescription.BufferCount = 1;
|
||||
swapChainDescription.OutputWindow = window;
|
||||
swapChainDescription.Windowed = TRUE;
|
||||
swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||
swapChainDescription.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* swapChain;
|
||||
ID3D11Device* device;
|
||||
ID3D11DeviceContext* context;
|
||||
|
||||
// Create temporary fake device and swap chain.
|
||||
if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 1, D3D11_SDK_VERSION, &swapChainDescription, &swapChain, &device, &featureLevel, &context)))
|
||||
{
|
||||
g_pRenderTargetView->Release();
|
||||
g_pRenderTargetView = nullptr;
|
||||
g_pDeviceContext->OMSetRenderTargets(0, 0, 0);
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
std::cout << "| >>>>>>>>>>>>>>| RENDER TARGET DESTROYED |<<<<<<<<<<<<< |" << std::endl;
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
// INTERNALS
|
||||
//#################################################################################
|
||||
|
||||
HRESULT GetDeviceAndCtxFromSwapchain(IDXGISwapChain* pSwapChain, ID3D11Device** ppDevice, ID3D11DeviceContext** ppContext)
|
||||
{
|
||||
HRESULT ret = pSwapChain->GetDevice(__uuidof(ID3D11Device), (PVOID*)ppDevice);
|
||||
if (SUCCEEDED(ret))
|
||||
{
|
||||
(*ppDevice)->GetImmediateContext(ppContext);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
IDXGIResizeBuffers originalResizeBuffers = nullptr;
|
||||
|
||||
HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags)
|
||||
{
|
||||
g_bShowConsole = false;
|
||||
g_bShowBrowser = false;
|
||||
g_bInitialized = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DestroyRenderTarget();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
return originalResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags);
|
||||
}
|
||||
|
||||
IDXGISwapChainPresent originalPresent = nullptr;
|
||||
|
||||
HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags)
|
||||
{
|
||||
if (!g_bInitialized)
|
||||
{
|
||||
if (FAILED(GetDeviceAndCtxFromSwapchain(pSwapChain, &g_pDevice, &g_pDeviceContext)))
|
||||
{
|
||||
return originalPresent(pSwapChain, nSyncInterval, nFlags);
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
std::cout << "| >>>>>>>>>>| GET DVS AND CTX FROM SCP FAILED |<<<<<<<<< |" << std::endl;
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
}
|
||||
|
||||
CreateRenderTarget(pSwapChain);
|
||||
SetupImGui();
|
||||
|
||||
if (g_oWndProc == nullptr)
|
||||
{ // Only initialize HwndProc pointer once to avoid stack overflow during ResizeBuffers(..)
|
||||
g_oWndProc = (WNDPROC)SetWindowLongPtr(g_hGameWindow, GWLP_WNDPROC, (LONG_PTR)HwndProc);
|
||||
}
|
||||
|
||||
g_bInitialized = true;
|
||||
g_pSwapChain = pSwapChain;
|
||||
std::cout << "Creating Device and Swap Chain failed." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
DrawImGui();
|
||||
g_bInitialized = true;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
return originalPresent(pSwapChain, nSyncInterval, nFlags);
|
||||
DWORD_PTR* swapChainVTable = nullptr;
|
||||
DWORD_PTR* contextVTable = nullptr;
|
||||
DWORD_PTR* deviceVTable = nullptr;
|
||||
|
||||
// Get vtable by dereferencing once.
|
||||
swapChainVTable = (DWORD_PTR*)swapChain;
|
||||
swapChainVTable = (DWORD_PTR*)swapChainVTable[0];
|
||||
contextVTable = (DWORD_PTR*)context;
|
||||
contextVTable = (DWORD_PTR*)contextVTable[0];
|
||||
deviceVTable = (DWORD_PTR*)device;
|
||||
deviceVTable = (DWORD_PTR*)deviceVTable[0];
|
||||
|
||||
// Get virtual functions addresses.
|
||||
g_fnIDXGISwapChainPresent = (IDXGISwapChainPresent)(DWORD_PTR)swapChainVTable[(int)DXGISwapChainVTbl::Present];
|
||||
g_fnIDXGIResizeBuffers = (IDXGIResizeBuffers)(DWORD_PTR)swapChainVTable[(int)DXGISwapChainVTbl::ResizeBuffers];
|
||||
|
||||
// Safe release all relevant ptrs.
|
||||
swapChain->Release();
|
||||
swapChain = nullptr;
|
||||
|
||||
device->Release();
|
||||
device = nullptr;
|
||||
|
||||
context->Release();
|
||||
context = nullptr;
|
||||
|
||||
// Destroy Window used for getting the virtual functions addresses and unregister its class.
|
||||
DestroyWindow(swapChainDescription.OutputWindow);
|
||||
UnregisterClass(ws.lpszClassName, ws.hInstance);
|
||||
}
|
||||
|
||||
bool LoadTextureFromByteArray(unsigned char* image_data, const int& image_width, const int& image_height, ID3D11ShaderResourceView** out_srv)
|
||||
@ -431,57 +209,158 @@ bool LoadTextureFromByteArray(unsigned char* image_data, const int& image_width,
|
||||
return true;
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
// MANAGEMENT
|
||||
//#################################################################################
|
||||
void DrawMenu()
|
||||
{
|
||||
if (!GameGlobals::IsInitialized || !GameGlobals::InputSystem) // Check if GameGlobals initialized and if InputSystem is valid.
|
||||
return;
|
||||
|
||||
// Handle new ImGui frame.
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Handle game input if one of the menus is open.
|
||||
if (g_bShowConsole || g_bShowBrowser)
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(true);
|
||||
}
|
||||
|
||||
if (g_bShowConsole)
|
||||
{
|
||||
DrawConsole();
|
||||
}
|
||||
|
||||
if (g_bShowBrowser)
|
||||
{
|
||||
DrawBrowser();
|
||||
}
|
||||
|
||||
// Handle end of frame and prepare rendering.
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
// Set new render target.
|
||||
// This breaks 4:3 in main menu and load screen if not applying the games DepthStencilView. Applying the games DepthStencilView makes ImGui not render tho.
|
||||
g_pDeviceContext->OMSetRenderTargets(1, &g_pMainRenderTargetView, NULL);
|
||||
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); // Tell ImGui to render all the draw data.
|
||||
}
|
||||
|
||||
IDXGIResizeBuffers originalResizeBuffers = nullptr;
|
||||
HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount, UINT nWidth, UINT nHeight, DXGI_FORMAT dxFormat, UINT nSwapChainFlags)
|
||||
{
|
||||
spdlog::debug("Resizing IDXGIResizeBuffers..\n");
|
||||
// Re-create render target if our window got resized.
|
||||
if (g_pMainRenderTargetView)
|
||||
{
|
||||
g_pDeviceContext->OMSetRenderTargets(0, 0, 0); // Set render target to null.
|
||||
|
||||
// Safe release the render target.
|
||||
g_pMainRenderTargetView->Release();
|
||||
g_pMainRenderTargetView = nullptr;
|
||||
}
|
||||
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects(); // Invalidate all ImGui DirectX objects.
|
||||
|
||||
HRESULT hr = originalResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags); // Let DirectX resize all the buffers.
|
||||
|
||||
if (!g_pDevice) // Valid device?
|
||||
return hr;
|
||||
|
||||
ID3D11Texture2D* pBuffer;
|
||||
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBuffer); // Grab the swapchains buffer.
|
||||
|
||||
if (!pBuffer) // Valid buffer?
|
||||
return hr;
|
||||
|
||||
g_pDevice->CreateRenderTargetView(pBuffer, NULL, &g_pMainRenderTargetView); // Create render target again with the new swapchain buffer.
|
||||
|
||||
// Safe release the buffer.
|
||||
pBuffer->Release();
|
||||
pBuffer = nullptr;
|
||||
|
||||
if (!g_pMainRenderTargetView) // Valid render target?
|
||||
return hr;
|
||||
|
||||
g_pDeviceContext->OMSetRenderTargets(1, &g_pMainRenderTargetView, NULL); // Set new render target.
|
||||
|
||||
// Set up the viewport.
|
||||
D3D11_VIEWPORT vp;
|
||||
vp.Width = nWidth;
|
||||
vp.Height = nHeight;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
g_pDeviceContext->RSSetViewports(1, &vp);
|
||||
|
||||
ImGui_ImplDX11_CreateDeviceObjects(); // Create new DirectX objects for ImGui.
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
IDXGISwapChainPresent originalPresent = nullptr;
|
||||
HRESULT __stdcall Present(IDXGISwapChain* pSwapChain, UINT nSyncInterval, UINT nFlags)
|
||||
{
|
||||
static bool InitializedPresent = false;
|
||||
if (!InitializedPresent)
|
||||
{
|
||||
spdlog::debug("Initializing IDXGISwapChainPresent hook..\n");
|
||||
if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&g_pDevice))) // Get device via swap chain.
|
||||
{
|
||||
g_pDevice->GetImmediateContext(&g_pDeviceContext); // Get device context via device.
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
pSwapChain->GetDesc(&sd); // Get the swap chain description.
|
||||
ID3D11Texture2D* pBuffer;
|
||||
pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBuffer); // Get swap chain buffer.
|
||||
|
||||
if (!pBuffer) // Valid buffer?
|
||||
return originalPresent(pSwapChain, nSyncInterval, nFlags);
|
||||
|
||||
g_pDevice->CreateRenderTargetView(pBuffer, NULL, &g_pMainRenderTargetView); // Create new render target.
|
||||
|
||||
// Safe release the buffer.
|
||||
pBuffer->Release();
|
||||
pBuffer = nullptr;
|
||||
|
||||
originalWndProc = (WNDPROC)SetWindowLongPtr(sd.OutputWindow, GWLP_WNDPROC, (LONG_PTR)WindowProc); // Hook current output window.
|
||||
|
||||
// Initialize ImGui.
|
||||
ImGui::CreateContext();
|
||||
ImGui_ImplWin32_Init(sd.OutputWindow);
|
||||
ImGui_ImplDX11_Init(g_pDevice, g_pDeviceContext);
|
||||
|
||||
InitializedPresent = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return originalPresent(pSwapChain, nSyncInterval, nFlags);
|
||||
}
|
||||
}
|
||||
|
||||
DrawMenu();
|
||||
return originalPresent(pSwapChain, nSyncInterval, nFlags);
|
||||
}
|
||||
|
||||
void InstallDXHooks()
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook SwapChain
|
||||
spdlog::debug("Initializing IDXGISwapChainPresent hook..\n");
|
||||
MH_CreateHook(g_fnIDXGISwapChainPresent, &Present, reinterpret_cast<void**>(&originalPresent));
|
||||
MH_CreateHook(g_oResizeBuffers, &GetResizeBuffers, reinterpret_cast<void**>(&originalResizeBuffers));
|
||||
MH_CreateHook(g_fnIDXGIResizeBuffers, &GetResizeBuffers, reinterpret_cast<void**>(&originalResizeBuffers));
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enable hooks
|
||||
MH_EnableHook(g_fnIDXGISwapChainPresent);
|
||||
MH_EnableHook(g_oResizeBuffers);
|
||||
|
||||
if (Module user32dll = Module("user32.dll"); user32dll.GetModuleBase()) // Is user32.dll valid?
|
||||
{
|
||||
IPostMessageA PostMessageA = user32dll.GetExportedFunction("PostMessageA").RCast<IPostMessageA>();
|
||||
IPostMessageW PostMessageW = user32dll.GetExportedFunction("PostMessageW").RCast<IPostMessageW>();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook PostMessage
|
||||
MH_CreateHook(PostMessageA, &HPostMessageA, reinterpret_cast<void**>(&g_oPostMessageA));
|
||||
MH_CreateHook(PostMessageW, &HPostMessageW, reinterpret_cast<void**>(&g_oPostMessageW));
|
||||
|
||||
MH_EnableHook(PostMessageA);
|
||||
MH_EnableHook(PostMessageW);
|
||||
}
|
||||
MH_EnableHook(g_fnIDXGIResizeBuffers);
|
||||
}
|
||||
|
||||
void RemoveDXHooks()
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook PostMessage
|
||||
if (Module user32dll = Module("user32.dll"); user32dll.GetModuleBase()) // Is user32.dll valid?
|
||||
{
|
||||
IPostMessageA PostMessageA = user32dll.GetExportedFunction("PostMessageA").RCast<IPostMessageA>();
|
||||
IPostMessageW PostMessageW = user32dll.GetExportedFunction("PostMessageW").RCast<IPostMessageW>();
|
||||
|
||||
MH_RemoveHook(PostMessageA);
|
||||
MH_RemoveHook(PostMessageW);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook SwapChain
|
||||
spdlog::debug("Initializing IDXGISwapChainPresent hook..\n");
|
||||
MH_RemoveHook(g_fnIDXGISwapChainPresent);
|
||||
MH_RemoveHook(g_oResizeBuffers);
|
||||
MH_RemoveHook(g_fnIDXGIResizeBuffers);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Shutdown ImGui
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
}
|
||||
@ -489,10 +368,9 @@ void RemoveDXHooks()
|
||||
void PrintDXAddress()
|
||||
{
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
std::cout << "| ID3D11DeviceContext : " << std::hex << std::uppercase << g_pDeviceContext << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| ID3D11Device : " << std::hex << std::uppercase << g_pDevice << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| ID3D11RenderTargetView : " << std::hex << std::uppercase << g_pRenderTargetView << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| IDXGISwapChain : " << std::hex << std::uppercase << g_pSwapChain << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| ID3D11DeviceContext : " << std::hex << std::uppercase << g_pDeviceContext << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| ID3D11Device : " << std::hex << std::uppercase << g_pDevice << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| ID3D11RenderTargetView : " << std::hex << std::uppercase << g_pMainRenderTargetView << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "| IDXGISwapChainPresent : " << std::hex << std::uppercase << g_fnIDXGISwapChainPresent << std::setw(13) << " |" << std::endl;
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
}
|
||||
@ -503,13 +381,14 @@ void PrintDXAddress()
|
||||
|
||||
DWORD __stdcall DXSwapChainWorker(LPVOID)
|
||||
{
|
||||
GetPresent();
|
||||
InitRenderer();
|
||||
InstallDXHooks();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetupDXSwapChain()
|
||||
{
|
||||
spdlog::debug("Setting up DirectX thread..\n");
|
||||
// Create a worker thread for the console overlay
|
||||
DWORD __stdcall DXSwapChainWorker(LPVOID);
|
||||
HANDLE hThread = CreateThread(NULL, 0, DXSwapChainWorker, NULL, 0, &g_dThreadId);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
void InstallOpcodes() /* .TEXT */
|
||||
{
|
||||
spdlog::debug("Patching the game executeable..\n");
|
||||
//-------------------------------------------------------------------------
|
||||
// JNZ --> JMP | Prevent OriginSDK from initializing
|
||||
//Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
|
||||
@ -32,4 +33,26 @@ void InstallOpcodes() /* .TEXT */
|
||||
//-------------------------------------------------------------------------
|
||||
// CALL --> NOP | Prevent random netchan encryption key from being overriden by default key
|
||||
NetChan_EncKey_DefaultAssign.Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 });
|
||||
//-------------------------------------------------------------------------
|
||||
// INLINE CALL --> VTABLE CALL | Call LockCursor VTable class function instead of doing it inlined.
|
||||
//-------------------------------------------------------------------------
|
||||
// .text:0000000140548E2C 80 3D 5C 2E 1D 01 00 cmp cs:byte_14171BC8F, 0
|
||||
// .text:0000000140548E33 48 8B 0D 16 25 EC 0C mov rcx, cs:g_InputStackSystem
|
||||
// .text:0000000140548E3A 48 8B 97 18 01 00 00 mov rdx, [rdi+118h]
|
||||
// .text:0000000140548E41 C6 05 91 7B EC 0C 01 mov cs:byte_14D4109D9, 1
|
||||
// .text:0000000140548E48 48 8B 01 mov rax, [rcx]
|
||||
// .text:0000000140548E4B 74 10 jz short loc_140548E5D
|
||||
// .text:0000000140548E4D 4C 8B 05 8C 7B EC 0C mov r8, cs:qword_14D4109E0
|
||||
// .text:0000000140548E54 48 83 C4 30 add rsp, 30h
|
||||
// .text:0000000140548E58 5F pop rdi
|
||||
// .text:0000000140548E59 48 FF 60 60 jmp qword ptr[rax+60h]
|
||||
//-------------------------------------------------------------------------
|
||||
// TURNS INTO:
|
||||
//-------------------------------------------------------------------------
|
||||
// .text:0000000140548E2C 48 8B 07 mov rax, [rdi]
|
||||
// .text:0000000140548E2F 48 89 F9 mov rcx, rdi
|
||||
// .text:0000000140548E32 FF 90 90 02 00 00 call qword ptr[rax+290h]
|
||||
// .text:0000000140548E38 EB 2F jmp short loc_140548E69
|
||||
//-------------------------------------------------------------------------
|
||||
MemoryAddress(0x140548E2C).Patch({ 0x48, 0x8B, 0x07, 0x48, 0x89, 0xF9, 0xFF, 0x90, 0x90, 0x02, 0x00, 0x00, 0xEB, 0x2F });
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user