mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Merge commit
This commit is contained in:
commit
d77878d638
@ -342,4 +342,31 @@ enum HostStates_t
|
||||
HS_GAME_SHUTDOWN = 0x5,
|
||||
HS_SHUTDOWN = 0x6,
|
||||
HS_RESTART = 0x7,
|
||||
};
|
||||
|
||||
enum SIGNONSTATE
|
||||
{
|
||||
SIGNONSTATE_NONE = 0, // no state yet; about to connect
|
||||
SIGNONSTATE_CHALLENGE = 1, // client challenging server; all OOB packets
|
||||
SIGNONSTATE_CONNECTED = 2, // client is connected to server; netchans ready
|
||||
SIGNONSTATE_NEW = 3, // just got serverinfo and string tables
|
||||
SIGNONSTATE_PRESPAWN = 4, // received signon buffers
|
||||
SIGNONSTATE_GETTING_DATA = 5, // getting persistence data I assume?
|
||||
SIGNONSTATE_SPAWN = 6, // ready to receive entity packets
|
||||
SIGNONSTATE_FIRST_SNAP = 7, // ???
|
||||
SIGNONSTATE_FULL = 8, // we are fully connected; first non-delta packet received
|
||||
SIGNONSTATE_CHANGELEVEL = 9, // server is changing level; please wait
|
||||
};
|
||||
|
||||
enum FileWarningLevel_t
|
||||
{
|
||||
FILESYSTEM_WARNING = -1,
|
||||
FILESYSTEM_WARNING_QUIET = 0,
|
||||
FILESYSTEM_WARNING_REPORTUNCLOSED,
|
||||
FILESYSTEM_WARNING_REPORTUSAGE,
|
||||
FILESYSTEM_WARNING_REPORTALLACCESSES,
|
||||
FILESYSTEM_WARNING_REPORTALLACCESSES_READ,
|
||||
FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE,
|
||||
FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC
|
||||
|
||||
};
|
@ -293,17 +293,20 @@ public:
|
||||
float m_flValue; //0x0068
|
||||
__int64 m_iValue; //0x006C
|
||||
bool m_bHasMin; //0x0070
|
||||
private:
|
||||
char pad_0071[3]; //0x0071
|
||||
public:
|
||||
float m_flMinValue; //0x0074
|
||||
bool m_bHasMax; //0x0078
|
||||
private:
|
||||
char pad_0079[3]; //0x0079
|
||||
public:
|
||||
float m_flMaxValue; //0x007C
|
||||
}; //Size: 0x0080
|
||||
|
||||
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
|
||||
{
|
||||
public:
|
||||
virtual void SetFirst(void) = 0; //0
|
||||
virtual void Next(void) = 0; //1
|
||||
virtual bool IsValid(void) = 0; //2
|
||||
virtual ConCommandBase* Get(void) = 0; //3
|
||||
};
|
||||
|
||||
class CCVar
|
||||
{
|
||||
public:
|
||||
@ -324,6 +327,29 @@ public:
|
||||
using OriginalFn = void*(__thiscall*)(CCVar*, const char*);
|
||||
return (*reinterpret_cast<OriginalFn**>(this))[18](this, szCommandName);
|
||||
}
|
||||
|
||||
CCVarIteratorInternal* FactoryInternalIterator() // @0x140597C10 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
|
||||
{
|
||||
using OriginalFn = CCVarIteratorInternal*(__thiscall*)(CCVar*);
|
||||
return (*reinterpret_cast<OriginalFn**>(this))[41](this);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, ConCommandBase*> DumpToMap()
|
||||
{
|
||||
std::stringstream ss;
|
||||
CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocatd new InternalIterator.
|
||||
|
||||
std::unordered_map<std::string, ConCommandBase*> allConVars;
|
||||
|
||||
for (itint->SetFirst(); itint->IsValid(); itint->Next()) // Loop through all instances.
|
||||
{
|
||||
ConCommandBase* command = itint->Get();
|
||||
const char* commandName = command->m_pszName;
|
||||
allConVars[commandName] = command;
|
||||
}
|
||||
|
||||
return allConVars;
|
||||
}
|
||||
};
|
||||
|
||||
struct Interface
|
||||
|
@ -78,6 +78,13 @@ namespace Hooks
|
||||
extern ShowCursorFn originalShowCursor;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CBaseFileSystem
|
||||
void FileSystemWarning(void* thisptr, FileWarningLevel_t level, const char* fmt, ...);
|
||||
|
||||
using FileSystemWarningFn = void(*)(void*, FileWarningLevel_t, const char*, ...);
|
||||
extern FileSystemWarningFn originalFileSystemWarning;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Other
|
||||
int MSG_EngineError(char* fmt, va_list args);
|
||||
|
||||
|
@ -51,9 +51,13 @@ namespace
|
||||
FUNC_AT_ADDRESS(addr_CVEngineServer_IsPersistenceDataAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr());
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CBaseFileSystem
|
||||
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 Utility
|
||||
/*0x140295600*/
|
||||
FUNC_AT_ADDRESS(addr_MSG_EngineError, int(*)(char*, va_list), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA").GetPtr());
|
||||
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());
|
||||
#pragma endregion
|
||||
// Un-used atm.
|
||||
// DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
|
||||
@ -72,6 +76,7 @@ namespace
|
||||
PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram);
|
||||
PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify);
|
||||
PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
|
||||
PRINT_ADDRESS("CBaseFileSystem::FileSystemWarning", addr_CBaseFileSystem_FileSystemWarning);
|
||||
PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError);
|
||||
std::cout << "+--------------------------------------------------------+" << std::endl;
|
||||
// TODO implement error handling when sigscan fails or result is 0
|
||||
|
@ -369,6 +369,7 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\hooks\cbasefilesystem.cpp" />
|
||||
<ClCompile Include="src\hooks\chlclient.cpp" />
|
||||
<ClCompile Include="src\hooks\cvengineserver.cpp" />
|
||||
<ClCompile Include="src\hooks\hooks.cpp" />
|
||||
|
@ -100,6 +100,9 @@
|
||||
<Filter Include="gui\interface">
|
||||
<UniqueIdentifier>{1979149f-6402-4985-b900-25a91f1168ac}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="hooks\src\cbasefilesystem">
|
||||
<UniqueIdentifier>{90ee1072-2d57-4d4e-aa1e-f19a81e6b27f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\dllmain.cpp">
|
||||
@ -183,6 +186,9 @@
|
||||
<ClCompile Include="src\gui_utility.cpp">
|
||||
<Filter>gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\hooks\cbasefilesystem.cpp">
|
||||
<Filter>hooks\src\cbasefilesystem</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\external\imgui\include\imgui_impl_win32.h">
|
||||
|
@ -152,11 +152,13 @@ void CCompanion::ServerBrowserSection()
|
||||
ImGui::BeginChild("ServerListChild", { 0, -FooterHeight }, true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
if(ImGui::BeginTable("##ServerBrowser_ServerList", 4, ImGuiTableFlags_Resizable))
|
||||
{
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 35);
|
||||
ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthStretch, 25);
|
||||
ImGui::TableSetupColumn("Port", ImGuiTableColumnFlags_WidthStretch, 10);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 8);
|
||||
ImGui::TableHeadersRow();
|
||||
if (ImGui::BeginTable("##ServerBrowser_ServerList", 4, ImGuiTableFlags_Resizable))
|
||||
{
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch, 35);
|
||||
ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthStretch, 25);
|
||||
ImGui::TableSetupColumn("Port", ImGuiTableColumnFlags_WidthStretch, 10);
|
||||
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 8);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (ServerListing& server : ServerList)
|
||||
{
|
||||
@ -164,18 +166,18 @@ void CCompanion::ServerBrowserSection()
|
||||
const char* map = server.map.c_str();
|
||||
const char* port = server.port.c_str();
|
||||
|
||||
if (ServerBrowserFilter.PassFilter(name)
|
||||
|| ServerBrowserFilter.PassFilter(map)
|
||||
|| ServerBrowserFilter.PassFilter(port))
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(name);
|
||||
if (ServerBrowserFilter.PassFilter(name)
|
||||
|| ServerBrowserFilter.PassFilter(map)
|
||||
|| ServerBrowserFilter.PassFilter(port))
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(name);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(map);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(map);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(port);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text(port);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
std::string selectButtonText = "Connect##";
|
||||
@ -193,6 +195,7 @@ void CCompanion::ServerBrowserSection()
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::InputTextWithHint("##ServerBrowser_ServerConnString", "Enter IP address or \"localhost\"", ServerConnStringBuffer, IM_ARRAYSIZE(ServerConnStringBuffer));
|
||||
|
||||
ImGui::Text("hello");
|
||||
@ -437,29 +440,25 @@ void CCompanion::Draw(const char* title)
|
||||
ImGui::SetNextWindowSize(ImVec2(840, 600), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetWindowPos(ImVec2(-500, 50), ImGuiCond_FirstUseEver);
|
||||
|
||||
if (!ImGui::Begin(title, NULL, ImGuiWindowFlags_NoScrollbar))
|
||||
ImGui::Begin(title, NULL, ImGuiWindowFlags_NoScrollbar);
|
||||
{
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
CompMenu();
|
||||
CompMenu();
|
||||
|
||||
switch (CurrentSection)
|
||||
{
|
||||
case ESection::ServerBrowser:
|
||||
ServerBrowserSection();
|
||||
break;
|
||||
case ESection::HostServer:
|
||||
HostServerSection();
|
||||
break;
|
||||
case ESection::Settings:
|
||||
SettingsSection();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (CurrentSection)
|
||||
{
|
||||
case ESection::ServerBrowser:
|
||||
ServerBrowserSection();
|
||||
break;
|
||||
case ESection::HostServer:
|
||||
HostServerSection();
|
||||
break;
|
||||
case ESection::Settings:
|
||||
SettingsSection();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@ -484,14 +483,14 @@ void CCompanion::ConnectToServer(const std::string& ip, const std::string& port)
|
||||
{
|
||||
std::stringstream cmd;
|
||||
cmd << "connect " << ip << ":" << port;
|
||||
g_ServerBrowser->ProcessCommand(cmd.str().c_str());
|
||||
ProcessCommand(cmd.str().c_str());
|
||||
}
|
||||
|
||||
void CCompanion::ConnectToServer(const std::string& connString)
|
||||
{
|
||||
std::stringstream cmd;
|
||||
cmd << "connect " << connString;
|
||||
g_ServerBrowser->ProcessCommand(cmd.str().c_str());
|
||||
ProcessCommand(cmd.str().c_str());
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
|
@ -29,7 +29,6 @@ CGameConsole::CGameConsole()
|
||||
Commands.push_back("CLEAR");
|
||||
Commands.push_back("CLASSIFY");
|
||||
|
||||
|
||||
AddLog("[DEBUG] THREAD ID: %ld\n", g_dThreadId);
|
||||
}
|
||||
|
||||
@ -59,177 +58,207 @@ void CGameConsole::Draw(const char* title)
|
||||
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.
|
||||
ImGui::Begin(title, NULL); // ImGui::Begin should never fail, if it does we got another problem.
|
||||
{
|
||||
ImGui::End(); return;
|
||||
}
|
||||
|
||||
// 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();
|
||||
// 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();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginPopup("Options"))
|
||||
{
|
||||
ImGui::Checkbox("Auto-scroll", &AutoScroll);
|
||||
if (ImGui::SmallButton("Clear"))
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginPopup("Options"))
|
||||
{
|
||||
ClearLog();
|
||||
ImGui::Checkbox("Auto-scroll", &AutoScroll);
|
||||
if (ImGui::SmallButton("Clear"))
|
||||
{
|
||||
ClearLog();
|
||||
}
|
||||
copy_to_clipboard = ImGui::SmallButton("Copy");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
copy_to_clipboard = ImGui::SmallButton("Copy");
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (ImGui::Button("Options"))
|
||||
{
|
||||
ImGui::OpenPopup("Options");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
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"))
|
||||
if (ImGui::Button("Options"))
|
||||
{
|
||||
Hooks::ToggleDevCommands();
|
||||
AddLog("+--------------------------------------------------------+\n");
|
||||
AddLog("|>>>>>>>>>>>>>>| DEVONLY COMMANDS TOGGLED |<<<<<<<<<<<<<<|\n");
|
||||
AddLog("+--------------------------------------------------------+\n");
|
||||
ProcessCommand("exec autoexec");
|
||||
ImGui::OpenPopup("Options");
|
||||
}
|
||||
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"))
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginPopup("Tools"))
|
||||
{
|
||||
Hooks::ToggleNetTrace();
|
||||
AddLog("+--------------------------------------------------------+\n");
|
||||
AddLog("|>>>>>>>>>>>>>>| NETCHANNEL TRACE TOGGLED |<<<<<<<<<<<<<<|\n");
|
||||
AddLog("+--------------------------------------------------------+\n");
|
||||
ProcessCommand("exec netchan");
|
||||
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.
|
||||
if (ImGui::SmallButton("Commands/Convars to Console"))
|
||||
{
|
||||
if (GameGlobals::Cvar)
|
||||
{
|
||||
for (auto map : GameGlobals::Cvar->DumpToMap())
|
||||
{
|
||||
AddLog("%s\n", map.first.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
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();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f });
|
||||
if (copy_to_clipboard)
|
||||
{
|
||||
ImGui::LogToClipboard();
|
||||
}
|
||||
for (int i = 0; i < Items.Size; i++)
|
||||
{
|
||||
const char* item = Items[i];
|
||||
if (!Filter.PassFilter(item))
|
||||
if (ImGui::Button("Tools"))
|
||||
{
|
||||
continue;
|
||||
ImGui::OpenPopup("Tools");
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////
|
||||
ImVec4 color;
|
||||
bool has_color = false;
|
||||
ImGui::SameLine();
|
||||
Filter.Draw("Filter [\"-incl,-excl\"] [\"error\"]", FooterWidthtoReserve - 500);
|
||||
ImGui::Separator();
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::BeginChild("ScrollingRegion", ImVec2(0, -FooterHeightToReserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f });
|
||||
if (copy_to_clipboard)
|
||||
{
|
||||
ImGui::LogToClipboard();
|
||||
}
|
||||
for (int i = 0; i < Items.Size; i++)
|
||||
{
|
||||
const char* item = Items[i];
|
||||
if (!Filter.PassFilter(item))
|
||||
continue;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
ImVec4 color;
|
||||
bool has_color = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Callbacks
|
||||
//if (strstr(item, "CodeCallback_")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Script errors
|
||||
if (strstr(item, ".gnut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
|
||||
if (strstr(item, ".nut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
|
||||
if (strstr(item, "[CLIENT]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "[SERVER]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "[UI]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "SCRIPT ERROR")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
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; }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Callbacks
|
||||
//if (strstr(item, "CodeCallback_")) { 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; }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Script errors
|
||||
if (strstr(item, ".gnut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
|
||||
if (strstr(item, ".nut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
|
||||
if (strstr(item, "[CLIENT]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "[SERVER]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "[UI]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
if (strstr(item, "SCRIPT ERROR")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
|
||||
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 (has_color) { ImGui::PushStyleColor(ImGuiCol_Text, color); }
|
||||
ImGui::TextWrapped(item);
|
||||
if (has_color) { ImGui::PopStyleColor(); }
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// 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; }
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Filters
|
||||
//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);
|
||||
|
||||
if (has_color)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_to_clipboard)
|
||||
{
|
||||
ImGui::LogFinish();
|
||||
}
|
||||
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) { ImGui::SetScrollHereY(1.0f); }
|
||||
ScrollToBottom = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndChild();
|
||||
ImGui::Separator();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Console
|
||||
bool ShouldReclaimFocus = false;
|
||||
ImGui::PushItemWidth(FooterWidthtoReserve - 80);
|
||||
if (ImGui::IsWindowAppearing()) { ImGui::SetKeyboardFocusHere(); }
|
||||
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
|
||||
|
||||
std::function<void(char*)> CommandExec = [&](char* InputBuf)
|
||||
{
|
||||
char* s = InputBuf;
|
||||
const char* replace = "";
|
||||
if (strstr(InputBuf, "`"))
|
||||
{
|
||||
strcpy_s(s, sizeof(replace), replace);
|
||||
}
|
||||
|
||||
Strtrim(s);
|
||||
|
||||
if (s[0])
|
||||
{
|
||||
ProcessCommand(s);
|
||||
}
|
||||
|
||||
strcpy_s(s, sizeof(replace), replace);
|
||||
ShouldReclaimFocus = true;
|
||||
};
|
||||
|
||||
if (ImGui::InputText("##input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
|
||||
{
|
||||
CommandExec(InputBuf);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Submit"))
|
||||
{
|
||||
CommandExec(InputBuf);
|
||||
}
|
||||
|
||||
// Auto-focus on window apparition
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
||||
// Auto focus previous widget
|
||||
if (ShouldReclaimFocus)
|
||||
{
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
}
|
||||
}
|
||||
if (copy_to_clipboard) { ImGui::LogFinish(); }
|
||||
|
||||
if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) { ImGui::SetScrollHereY(1.0f); }
|
||||
ScrollToBottom = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndChild();
|
||||
ImGui::Separator();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Console
|
||||
bool reclaim_focus = false;
|
||||
ImGui::PushItemWidth(footer_width_to_reserve - 80);
|
||||
if (ImGui::IsWindowAppearing()) { ImGui::SetKeyboardFocusHere(); }
|
||||
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
|
||||
|
||||
if (ImGui::InputText("##input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
|
||||
{
|
||||
char* s = InputBuf;
|
||||
const char* replace = "";
|
||||
if (strstr(InputBuf, "`")) { strcpy_s(s, sizeof(replace), replace); }
|
||||
Strtrim(s);
|
||||
if (s[0]) { ProcessCommand(s); }
|
||||
strcpy_s(s, sizeof(replace), replace);
|
||||
reclaim_focus = true;
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Submit"))
|
||||
{
|
||||
char* s = InputBuf;
|
||||
const char* replace = "";
|
||||
if (s[0]) { ProcessCommand(s); }
|
||||
strcpy_s(s, sizeof(replace), replace);
|
||||
reclaim_focus = true;
|
||||
}
|
||||
|
||||
// Auto-focus on window apparition
|
||||
ImGui::SetItemDefaultFocus();
|
||||
|
||||
// Auto focus previous widget
|
||||
if (reclaim_focus)
|
||||
{
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
12
r5dev/src/hooks/cbasefilesystem.cpp
Normal file
12
r5dev/src/hooks/cbasefilesystem.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "pch.h"
|
||||
#include "hooks.h"
|
||||
namespace Hooks
|
||||
{
|
||||
FileSystemWarningFn originalFileSystemWarning = nullptr;
|
||||
}
|
||||
|
||||
void Hooks::FileSystemWarning(void* thisptr, FileWarningLevel_t level, const char* fmt, ...)
|
||||
{
|
||||
// How you call original functions, you dont need it here.
|
||||
// originalFileSystemWarning(thisptr, level, fmt, ...);
|
||||
}
|
@ -37,6 +37,10 @@ void Hooks::InstallHooks()
|
||||
MH_CreateHook(addr_ConVar_IsFlagSet, &Hooks::ConVar_IsFlagSet, NULL);
|
||||
MH_CreateHook(addr_ConCommand_IsFlagSet, &Hooks::ConCommand_IsFlagSet, NULL);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hooks CBaseFileSystem functions.
|
||||
//MH_CreateHook(addr_CBaseFileSystem_FileSystemWarning, &Hooks::FileSystemWarning, reinterpret_cast<void**>(&originalFileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Hook Utility functions
|
||||
MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast<void**>(&originalMSG_EngineError));
|
||||
@ -85,6 +89,10 @@ void Hooks::InstallHooks()
|
||||
MH_EnableHook(addr_ConVar_IsFlagSet);
|
||||
MH_EnableHook(addr_ConCommand_IsFlagSet);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enable CBaseFileSystem hooks
|
||||
//MH_EnableHook(addr_CBaseFileSystem_FileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Enabled Utility hooks
|
||||
MH_EnableHook(addr_MSG_EngineError);
|
||||
@ -135,6 +143,10 @@ void Hooks::RemoveHooks()
|
||||
// Unhook Utility functions
|
||||
MH_RemoveHook(addr_MSG_EngineError);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Unhook CBaseFileSystem functions.
|
||||
//MH_RemoveHook(addr_CBaseFileSystem_FileSystemWarning);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Reset Minhook
|
||||
MH_Uninitialize();
|
||||
|
@ -30,7 +30,7 @@ void Hooks::NET_PrintFunc(const char* fmt, ...)
|
||||
iconsole = std::make_shared<spdlog::logger>("ostream", ostream_sink);
|
||||
iconsole->set_pattern("[%S.%e] %v");
|
||||
iconsole->set_level(spdlog::level::debug);
|
||||
wconsole->set_pattern("[%S.%e] %v");
|
||||
wconsole->set_pattern("[%S.%e] %v\n");
|
||||
wconsole->set_level(spdlog::level::debug);
|
||||
initialized = true;
|
||||
}
|
||||
|
@ -266,23 +266,25 @@ void DrawImGui()
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
if (g_bShowConsole)
|
||||
if (g_bShowConsole || g_bShowBrowser)
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(false); // Disable input.
|
||||
}
|
||||
else
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(true); // Enable input.
|
||||
}
|
||||
|
||||
if (g_bShowConsole)
|
||||
{
|
||||
DrawConsole();
|
||||
}
|
||||
|
||||
if (g_bShowBrowser)
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(false); // Disable input.
|
||||
DrawBrowser();
|
||||
}
|
||||
|
||||
if (!g_bShowConsole && !g_bShowBrowser)
|
||||
{
|
||||
GameGlobals::InputSystem->EnableInput(true); // Enable input.
|
||||
}
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
@ -312,25 +314,6 @@ void CreateRenderTarget(IDXGISwapChain* pSwapChain)
|
||||
pBackBuffer->Release();
|
||||
}
|
||||
|
||||
void CreateViewPort( UINT nWidth, UINT nHeight)
|
||||
{
|
||||
float width = *(float*)(&nWidth);
|
||||
float height = *(float*)(&nHeight);
|
||||
|
||||
D3D11_VIEWPORT vp;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
g_pDeviceContext->RSSetViewports(1, &vp);
|
||||
}
|
||||
|
||||
void DestroyRenderTarget()
|
||||
{
|
||||
if (nullptr != g_pRenderTargetView)
|
||||
@ -368,12 +351,9 @@ HRESULT __stdcall GetResizeBuffers(IDXGISwapChain* pSwapChain, UINT nBufferCount
|
||||
g_bPresentHooked = false;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
ImGui_ImplDX11_InvalidateDeviceObjects();
|
||||
|
||||
DestroyRenderTarget();
|
||||
CreateViewPort(nWidth, nHeight);
|
||||
|
||||
ImGui_ImplDX11_CreateDeviceObjects();
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
return originalResizeBuffers(pSwapChain, nBufferCount, nWidth, nHeight, dxFormat, nSwapChainFlags);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ public:
|
||||
|
||||
enum class Direction : int
|
||||
{
|
||||
UP = 0,
|
||||
DOWN,
|
||||
DOWN = 0,
|
||||
UP,
|
||||
};
|
||||
|
||||
std::uintptr_t GetPtr()
|
||||
@ -135,12 +135,12 @@ public:
|
||||
VirtualProtect((void*)ptr, dwSize, oldProt, &oldProt); // Restore protection.
|
||||
}
|
||||
|
||||
MemoryAddress FindPatternSelf(const char* pattern, Direction searchDirect, int opCodesToScan = 100, int occurence = 1)
|
||||
MemoryAddress FindPatternSelf(const std::string pattern, const Direction searchDirect, const int opCodesToScan = 100, const std::ptrdiff_t occurence = 1)
|
||||
{
|
||||
static auto PatternToBytes = [](const char* pattern)
|
||||
static auto PatternToBytes = [](const std::string pattern)
|
||||
{
|
||||
char* PatternStart = const_cast<char*>(pattern); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern.
|
||||
char* PatternStart = const_cast<char*>(pattern.c_str()); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern.c_str()); // Get end of pattern.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
@ -170,19 +170,20 @@ public:
|
||||
|
||||
const std::vector<int> PatternBytes = PatternToBytes(pattern); // Convert our pattern to a byte array.
|
||||
const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
int occurences = 0;
|
||||
std::ptrdiff_t occurences = 0;
|
||||
|
||||
for (auto i = 01; i < opCodesToScan + BytesInfo.first; ++i)
|
||||
for (long i = 01; i < opCodesToScan + BytesInfo.first; i++)
|
||||
{
|
||||
bool FoundAddress = true;
|
||||
|
||||
int memOffset = searchDirect == Direction::UP ? -i : i;
|
||||
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; ++j)
|
||||
int memOffset = searchDirect == Direction::DOWN ? i : -i;
|
||||
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; j++)
|
||||
{
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
if (ScanBytes[memOffset + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
std::uint8_t currentByte = *(ScanBytes + memOffset + j);
|
||||
if (currentByte != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
{
|
||||
FoundAddress = false;
|
||||
break;
|
||||
@ -194,7 +195,7 @@ public:
|
||||
occurences++;
|
||||
if (occurence == occurences)
|
||||
{
|
||||
ptr = reinterpret_cast<std::uintptr_t>(&ScanBytes[memOffset]);
|
||||
ptr = std::uintptr_t(&*(ScanBytes + memOffset));
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@ -205,12 +206,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
MemoryAddress FindPattern(const char* pattern, Direction searchDirect, int opCodesToScan = 100, int occurence = 1)
|
||||
MemoryAddress FindPattern(const std::string pattern, const Direction searchDirect, const int opCodesToScan = 100, const std::ptrdiff_t occurence = 1)
|
||||
{
|
||||
static auto PatternToBytes = [](const char* pattern)
|
||||
static auto PatternToBytes = [](const std::string pattern)
|
||||
{
|
||||
char* PatternStart = const_cast<char*>(pattern); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern.
|
||||
char* PatternStart = const_cast<char*>(pattern.c_str()); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern.c_str()); // Get end of pattern.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
@ -240,19 +241,20 @@ public:
|
||||
|
||||
const std::vector<int> PatternBytes = PatternToBytes(pattern); // Convert our pattern to a byte array.
|
||||
const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
int occurences = 0;
|
||||
std::ptrdiff_t occurences = 0;
|
||||
|
||||
for (auto i = 01; i < opCodesToScan + BytesInfo.first; ++i)
|
||||
for (long i = 01; i < opCodesToScan + BytesInfo.first; i++)
|
||||
{
|
||||
bool FoundAddress = true;
|
||||
|
||||
int memOffset = searchDirect == Direction::UP ? -i : i;
|
||||
int memOffset = searchDirect == Direction::DOWN ? i : -i;
|
||||
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; ++j)
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; j++)
|
||||
{
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
if (ScanBytes[memOffset + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
std::uint8_t currentByte = *(ScanBytes + memOffset + j);
|
||||
if (currentByte != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
{
|
||||
FoundAddress = false;
|
||||
break;
|
||||
@ -264,10 +266,9 @@ public:
|
||||
occurences++;
|
||||
if (occurence == occurences)
|
||||
{
|
||||
return MemoryAddress(&ScanBytes[memOffset]);
|
||||
return MemoryAddress(&*(ScanBytes + memOffset));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return MemoryAddress();
|
||||
@ -311,20 +312,66 @@ private:
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
|
||||
struct ModuleSections
|
||||
{
|
||||
ModuleSections() = default;
|
||||
ModuleSections(std::string sectionName, std::uintptr_t sectionStartAddress, DWORD sectionSize) : sectionName(sectionName), sectionStartAddress(sectionStartAddress), sectionSize(sectionSize) {}
|
||||
|
||||
bool IsSectionValid()
|
||||
{
|
||||
return sectionSize != 0;
|
||||
}
|
||||
|
||||
std::string sectionName = std::string(); // Name of section.
|
||||
std::uintptr_t sectionStartAddress = 0; // Start memory address of section.
|
||||
DWORD sectionSize = 0; // Size of section.
|
||||
};
|
||||
|
||||
ModuleSections GetSectionByName(const std::string sectionName)
|
||||
{
|
||||
for (ModuleSections& currentSection : moduleSections)
|
||||
{
|
||||
if (currentSection.sectionName.compare(sectionName) == 0)
|
||||
return currentSection;
|
||||
}
|
||||
|
||||
return ModuleSections();
|
||||
}
|
||||
|
||||
void PrintSections()
|
||||
{
|
||||
for (ModuleSections& currentSection : moduleSections)
|
||||
{
|
||||
printf(" [+Module: %s+]%s, %p\n", moduleName.c_str(), currentSection.sectionName.c_str(), currentSection.sectionStartAddress);
|
||||
}
|
||||
}
|
||||
|
||||
Module() = default;
|
||||
Module(std::string moduleName) : moduleName(moduleName)
|
||||
{
|
||||
const MODULEINFO mInfo = GetModuleInfo(moduleName.c_str()); // Get module info.
|
||||
sizeOfModule = (DWORD64)mInfo.SizeOfImage; // Grab the module size.
|
||||
moduleBase = (std::uintptr_t)mInfo.lpBaseOfDll; // Grab module base.
|
||||
|
||||
dosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(moduleBase); // Get dosHeader.
|
||||
ntHeaders = reinterpret_cast<IMAGE_NT_HEADERS64*>(moduleBase + dosHeader->e_lfanew); // Get ntHeaders.
|
||||
|
||||
const IMAGE_SECTION_HEADER* hSection = IMAGE_FIRST_SECTION(ntHeaders); // Get first image section.
|
||||
|
||||
for (WORD i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) // Loop through the sections.
|
||||
{
|
||||
const IMAGE_SECTION_HEADER& currentSection = hSection[i]; // Get current section.
|
||||
moduleSections.push_back(ModuleSections(std::string(reinterpret_cast<const char*>(currentSection.Name)), (std::uintptr_t)(DWORD64)(moduleBase + currentSection.VirtualAddress), currentSection.SizeOfRawData)); // Push back a struct with the section data.
|
||||
}
|
||||
}
|
||||
|
||||
MemoryAddress PatternSearch(const char* signature)
|
||||
MemoryAddress PatternSearch(const std::string pattern, const std::ptrdiff_t patternOccurence = 1)
|
||||
{
|
||||
static auto PatternToBytes = [](const char* pattern)
|
||||
static auto PatternToBytes = [](const std::string pattern)
|
||||
{
|
||||
char* PatternStart = const_cast<char*>(pattern); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern.
|
||||
char* PatternStart = const_cast<char*>(pattern.c_str()); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern.c_str()); // Get end of pattern.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
@ -350,20 +397,27 @@ public:
|
||||
return Bytes;
|
||||
};
|
||||
|
||||
std::uint8_t* ScanBytes = reinterpret_cast<std::uint8_t*>(moduleBase); // Get the base of the module.
|
||||
ModuleSections textSection = GetSectionByName(".text"); // Get the .text section.
|
||||
if (!textSection.IsSectionValid())
|
||||
return MemoryAddress();
|
||||
|
||||
const std::vector<int> PatternBytes = PatternToBytes(signature); // Convert our pattern to a byte array.
|
||||
const std::vector<std::int32_t> PatternBytes = PatternToBytes(pattern); // Convert our pattern to a byte array.
|
||||
const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
|
||||
for (DWORD i = 0ul; i < sizeOfModule - BytesInfo.first; ++i)
|
||||
std::uint8_t* latestOccurence = nullptr;
|
||||
std::ptrdiff_t occurencesFound = 0;
|
||||
|
||||
std::uint8_t* StartOfCodeSection = reinterpret_cast<std::uint8_t*>(textSection.sectionStartAddress); // Get start of .text section.
|
||||
|
||||
for (DWORD i = 0ul; i < textSection.sectionSize - BytesInfo.first; i++)
|
||||
{
|
||||
bool FoundAddress = true;
|
||||
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; ++j)
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; j++)
|
||||
{
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
if (ScanBytes[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
if (StartOfCodeSection[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
{
|
||||
FoundAddress = false;
|
||||
break;
|
||||
@ -372,20 +426,155 @@ public:
|
||||
|
||||
if (FoundAddress)
|
||||
{
|
||||
return MemoryAddress(&ScanBytes[i]);
|
||||
occurencesFound++; // Increment occurences found counter.
|
||||
if (patternOccurence == occurencesFound) // Is it the occurence we want?
|
||||
return MemoryAddress(&StartOfCodeSection[i]); // If yes return it.
|
||||
|
||||
latestOccurence = &StartOfCodeSection[i]; // Stash latest occurence.
|
||||
}
|
||||
}
|
||||
|
||||
return MemoryAddress(latestOccurence);
|
||||
}
|
||||
|
||||
MemoryAddress FindAddressForString(const std::string string, bool nullTerminator)
|
||||
{
|
||||
static auto StringToBytes = [](const std::string string, bool nullTerminator)
|
||||
{
|
||||
char* StringStart = const_cast<char*>(string.c_str()); // Cast const away and get start of string.
|
||||
char* StringEnd = StringStart + std::strlen(string.c_str()); // Get end of string.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
for (char* CurrentByte = StringStart; CurrentByte < StringEnd; ++CurrentByte) // Loop through all the characters in the .rdata string.
|
||||
{
|
||||
Bytes.push_back(*CurrentByte); // Dereference character and push back the byte.
|
||||
}
|
||||
|
||||
if (nullTerminator) // Does the string have a null terminator at the end of it?
|
||||
Bytes.push_back(0x0); // If yes push back 0 at the end of the byte array.
|
||||
|
||||
return Bytes;
|
||||
};
|
||||
|
||||
ModuleSections rdataSection = GetSectionByName(".rdata"); // .Get rdata section, we only loop through here because most important strings are in the .rdata section.
|
||||
if (!rdataSection.IsSectionValid())
|
||||
return MemoryAddress();
|
||||
|
||||
std::vector<std::int32_t> stringBytes = StringToBytes(string, nullTerminator); // Convert our string to a byte array.
|
||||
const std::pair BytesInfo = std::make_pair(stringBytes.size(), stringBytes.data()); // Get the size and data of our bytes.
|
||||
|
||||
std::uint8_t* StartOfRdata = reinterpret_cast<std::uint8_t*>(rdataSection.sectionStartAddress); // Get start of .rdata section.
|
||||
|
||||
for (DWORD i = 0ul; i < rdataSection.sectionSize - BytesInfo.first; i++)
|
||||
{
|
||||
bool FoundAddress = true;
|
||||
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; j++)
|
||||
{
|
||||
if (StartOfRdata[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
{
|
||||
FoundAddress = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FoundAddress)
|
||||
{
|
||||
return MemoryAddress(&StartOfRdata[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return MemoryAddress();
|
||||
}
|
||||
|
||||
MemoryAddress StringSearch(const std::string string, const std::ptrdiff_t occurence = 1, bool nullTerminator = false)
|
||||
{
|
||||
static auto PatternToBytes = [](const std::string pattern)
|
||||
{
|
||||
char* PatternStart = const_cast<char*>(pattern.c_str()); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern.c_str()); // Get end of pattern.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
for (char* CurrentByte = PatternStart; CurrentByte < PatternEnd; ++CurrentByte)
|
||||
{
|
||||
if (*CurrentByte == '?') // Is current char(byte) a wildcard?
|
||||
{
|
||||
++CurrentByte; // Skip 1 character.
|
||||
|
||||
if (*CurrentByte == '?') // Is it a double wildcard pattern?
|
||||
++CurrentByte; // If so skip the next space that will come up so we can reach the next byte.
|
||||
|
||||
Bytes.push_back(-1); // Push the byte back as invalid.
|
||||
}
|
||||
else
|
||||
{
|
||||
// https://stackoverflow.com/a/43860875/12541255
|
||||
// Here we convert our string to a unsigned long integer. We pass our string then we use 16 as the base because we want it as hexadecimal.
|
||||
// Afterwards we push the byte into our bytes vector.
|
||||
Bytes.push_back(std::strtoul(CurrentByte, &CurrentByte, 16));
|
||||
}
|
||||
}
|
||||
return Bytes;
|
||||
};
|
||||
|
||||
ModuleSections textSection = GetSectionByName(".text"); // Get the .text section.
|
||||
if (!textSection.IsSectionValid())
|
||||
return MemoryAddress();
|
||||
|
||||
MemoryAddress stringAddress = FindAddressForString(string, nullTerminator); // Get address for the string in the .rdata section.
|
||||
if (!stringAddress)
|
||||
return MemoryAddress();
|
||||
|
||||
std::uint8_t* latestOccurence = nullptr;
|
||||
std::ptrdiff_t occurencesFound = 0;
|
||||
|
||||
std::uint8_t* StartOfCodeSection = reinterpret_cast<std::uint8_t*>(textSection.sectionStartAddress); // Get the start of the .text section.
|
||||
|
||||
for (DWORD i = 0ul; i < textSection.sectionSize - 0x5; i++)
|
||||
{
|
||||
byte byte = StartOfCodeSection[i];
|
||||
if (byte == 0x8D) // is it a LEA instruction?
|
||||
{
|
||||
MemoryAddress skipOpCode = MemoryAddress((std::uintptr_t)&StartOfCodeSection[i]).OffsetSelf(0x2); // Skip next 2 opcodes, those being the instruction and then the register.
|
||||
|
||||
std::int32_t relativeAddress = skipOpCode.GetValue<std::int32_t>(); // Get 4-byte long string relative address
|
||||
|
||||
std::uintptr_t nextInstruction = skipOpCode.Offset(0x4).GetPtr(); // Get location of next instruction.
|
||||
|
||||
MemoryAddress potentialLocation = MemoryAddress(nextInstruction + relativeAddress); // Get potential string location.
|
||||
|
||||
if (potentialLocation == stringAddress)
|
||||
{
|
||||
occurencesFound++; // Increment occurences found counter.
|
||||
if (occurence == occurencesFound) // Is it the occurence we want?
|
||||
return MemoryAddress(&StartOfCodeSection[i]); // If yes return it.
|
||||
|
||||
latestOccurence = &StartOfCodeSection[i]; // Stash latest occurence.
|
||||
}
|
||||
}
|
||||
}
|
||||
return MemoryAddress(latestOccurence);
|
||||
}
|
||||
|
||||
std::uintptr_t GetModuleBase()
|
||||
{
|
||||
return moduleBase;
|
||||
}
|
||||
|
||||
std::string GetModuleName()
|
||||
{
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string moduleName = std::string();
|
||||
std::uintptr_t moduleBase = 0;
|
||||
DWORD64 sizeOfModule = 0;
|
||||
IMAGE_NT_HEADERS64* ntHeaders = nullptr;
|
||||
IMAGE_DOS_HEADER* dosHeader = nullptr;
|
||||
std::vector<ModuleSections> moduleSections = {};
|
||||
};
|
@ -29,72 +29,6 @@ MODULEINFO GetModuleInfo(const char* szModule)
|
||||
return modinfo;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// For finding a byte pattern in memory of the game process
|
||||
|
||||
std::uint8_t* PatternScan(const char* module, const char* signature)
|
||||
{
|
||||
static auto PatternToBytes = [](const char* pattern)
|
||||
{
|
||||
char* PatternStart = const_cast<char*>(pattern); // Cast const away and get start of pattern.
|
||||
char* PatternEnd = PatternStart + std::strlen(pattern); // Get end of pattern.
|
||||
|
||||
std::vector<std::int32_t> Bytes = std::vector<std::int32_t>{ }; // Initialize byte vector.
|
||||
|
||||
for (char* CurrentByte = PatternStart; CurrentByte < PatternEnd; ++CurrentByte)
|
||||
{
|
||||
if (*CurrentByte == '?') // Is current char(byte) a wildcard?
|
||||
{
|
||||
++CurrentByte; // Skip 1 character.
|
||||
|
||||
if (*CurrentByte == '?') // Is it a double wildcard pattern?
|
||||
++CurrentByte; // If so skip the next space that will come up so we can reach the next byte.
|
||||
|
||||
Bytes.push_back(-1); // Push the byte back as invalid.
|
||||
}
|
||||
else
|
||||
{
|
||||
// https://stackoverflow.com/a/43860875/12541255
|
||||
// Here we convert our string to a unsigned long integer. We pass our string then we use 16 as the base because we want it as hexadecimal.
|
||||
// Afterwards we push the byte into our bytes vector.
|
||||
Bytes.push_back(std::strtoul(CurrentByte, &CurrentByte, 16));
|
||||
}
|
||||
}
|
||||
return Bytes;
|
||||
};
|
||||
|
||||
const MODULEINFO mInfo = GetModuleInfo(module); // Get module info.
|
||||
const DWORD64 SizeOfModule = (DWORD64)mInfo.SizeOfImage; // Grab the module size.
|
||||
std::uint8_t* ScanBytes = reinterpret_cast<std::uint8_t*>(mInfo.lpBaseOfDll); // Get the base of the module.
|
||||
|
||||
const std::vector<int> PatternBytes = PatternToBytes(signature); // Convert our pattern to a byte array.
|
||||
const std::pair BytesInfo = std::make_pair(PatternBytes.size(), PatternBytes.data()); // Get the size and data of our bytes.
|
||||
|
||||
for (DWORD i = 0ul; i < SizeOfModule - BytesInfo.first; ++i)
|
||||
{
|
||||
bool FoundAddress = true;
|
||||
|
||||
for (DWORD j = 0ul; j < BytesInfo.first; ++j)
|
||||
{
|
||||
// If either the current byte equals to the byte in our pattern or our current byte in the pattern is a wildcard
|
||||
// our if clause will be false.
|
||||
if (ScanBytes[i + j] != BytesInfo.second[j] && BytesInfo.second[j] != -1)
|
||||
{
|
||||
FoundAddress = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FoundAddress)
|
||||
{
|
||||
return &ScanBytes[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void DbgPrint(LPCSTR sFormat, ...)
|
||||
|
Loading…
x
Reference in New Issue
Block a user