Merge indev into master. (#44)

* Added separate function to resolve relative addresses in address.h

* Added new patterns to the print function.

* Updated IsFlagSet hooks.

* Cleaned up code to properly mask off Dev and Cheat flags.
* Added separate define from _DEBUG so you can define it in release builds for people without C++ Debug Restributeables.

* Removed un-used define in hooks.h

* Fixed potential crashes in r5net and added debug prints.

* Potential crashes were when in certain post functions the returned status wasn't 200.

* Changed map-select drop down menu, now it displays 'Map Name + Season' instead of file-name. (#41)

* Host Server shows normal map names

* Changed a few stuff...

* redid some stuff that isn't crucial

* Update CCompanion.cpp

* Update CCompanion.cpp

* Updated mapname displaying.

* Moved "ServerMap" as a static object into CCompanion::HostServerSection().

Co-authored-by: IcePixelx <41352111+PixieCore@users.noreply.github.com>

* prevent squirrel compiler errors from killing game process (#43)

* Read description for all changes.

* Added ability to register custom ConVar.
* Added 2 custom ConVars to open the CGameConsole and CCompanion Windows.
* Changed ResolveRelativeAddress.
* Added Config System for the Gui.
* Added ImGui::Hotkey.
* Added the ability to change 2 hotkeys for opening the window for CGameConsole and CCompanion.
* Changed pattern for Squirrel_CompilerError to use a String.
* Added IMemAlloc::AllocWrapper to patterns.h

* Changes in description.

* Added icon to launcher.exe
* Launcher.exe gets remnamed to Run R5 Reloaded.exe in launcher release compilation configuration.
* Extended argument buffer for starting the game in launcher.exe.
* Added exception printing if in the custom ConVars an invalid value gets passed.

* Wrong return.

* Added shortcut with launch params.

* Fixed prints.

Co-authored-by: Marcii0 <58266292+Marcii0@users.noreply.github.com>
Co-authored-by: BobTheBob <32057864+BobTheBob9@users.noreply.github.com>
This commit is contained in:
PixieCore 2021-08-19 15:26:44 +02:00 committed by GitHub
parent 3c641687f1
commit 7bb4fd6313
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 914 additions and 124 deletions

View File

@ -548,6 +548,7 @@ namespace ImGui
IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0, double step_fast = 0.0, const char* format = "%.6f", ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0);
IMGUI_API bool Hotkey(const char* label, int* key, const ImVec2& size);
// Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.)
// - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible.

View File

@ -8048,4 +8048,365 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
}
const char* const KeyNames[] =
{
"Null",
"Mouse1",
"Mouse2",
"Cancel",
"Mouse3",
"Mouse4",
"Mouse5",
"Undefined",
"Back",
"Tab",
"Reserved",
"Reserved",
"Clear",
"Return",
"Undefined",
"Undefined",
"Shift",
"Control",
"Menu",
"Pause",
"Capital",
"Kana",
"Ime On",
"Junja",
"Final",
"Kanji",
"Ime Off",
"Escape",
"Convert",
"Nonconvert",
"Accept",
"Modechange",
"Space",
"Prior",
"Next",
"End",
"Home",
"Left",
"Up",
"Right",
"Down",
"Select",
"Print",
"Execute",
"Snapshot",
"Insert",
"Delete",
"Help",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"Lwin",
"Rwin",
"Apps",
"Unknown",
"Sleep",
"Numpad0",
"Numpad1",
"Numpad2",
"Numpad3",
"Numpad4",
"Numpad5",
"Numpad6",
"Numpad7",
"Numpad8",
"Numpad9",
"Multiply",
"Add",
"Separator",
"Subtract",
"Decimal",
"Divide",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"F13",
"F14",
"F15",
"F16",
"F17",
"F18",
"F19",
"F20",
"F21",
"F22",
"F23",
"F24",
"Unassigned",
"Unassigned",
"Unassigned",
"Unassigned",
"Unassigned",
"Unassigned",
"Unassigned",
"Unassigned",
"Numlock",
"Scroll",
"Oem_nec_equal",
"Oem_fj_masshou",
"Oem_fj_touroku",
"Oem_fj_loya",
"Oem_fj_roya",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Unknown",
"Lshift",
"Rshift",
"Lcontrol",
"Rcontrol",
"Lmenu",
"Rmenu",
"Browser Back",
"Browser Stop",
"Browser Refresh",
"Browser Search",
"Browser Favorite",
"Browser Home",
"Volume Mute",
"Volume Down",
"Volume Up",
"Next Track",
"Previous Track",
"Media Stop",
"Play/Pause",
"Mail",
"Media",
"App1",
"App2",
"Reserved",
"Reserved",
"Reserved",
":;",
"+",
",",
"-",
".",
"?",
"~",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined",
"Undefined"
};
bool ImGui::Hotkey(const char* label, int* key, const ImVec2& ssize)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
const ImGuiStyle& style = g.Style;
float backupPaddingY = style.FramePadding.y;
g.Style.FramePadding.y = 0.0f;
const ImGuiID id = window->GetID(label);
const ImVec2 labelSize = ImGui::CalcTextSize(label, NULL, true);
const ImVec2 size = ImGui::CalcItemSize(ssize, ImGui::CalcItemWidth(), labelSize.y + style.FramePadding.y * 2.0f);
const ImRect frameBB(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, labelSize.y + style.FramePadding.y));
const ImRect total_bb(frameBB.Min, frameBB.Max + ImVec2(labelSize.x > 0.0f ? style.ItemInnerSpacing.x + labelSize.x : 0.0f, 0.0f));
ImGui::ItemSize(total_bb, style.FramePadding.y);
if (!ImGui::ItemAdd(total_bb, id))
{
g.Style.FramePadding.y = backupPaddingY;
return false;
}
const bool requestedFocus = ImGui::FocusableItemRegister(window, id);
const bool isHovered = ImGui::ItemHoverable(frameBB, id);
if (isHovered) {
ImGui::SetHoveredID(id);
g.MouseCursor = ImGuiMouseCursor_TextInput;
}
const bool didClick = isHovered && io.MouseClicked[0];
if (requestedFocus || didClick)
{
if (g.ActiveId != id)
{
memset(io.MouseDown, 0, sizeof(io.MouseDown));
memset(io.KeysDown, 0, sizeof(io.KeysDown));
*key = 0;
}
ImGui::SetActiveID(id, window);
ImGui::FocusWindow(window);
}
else if (io.MouseClicked[0])
{
if (g.ActiveId == id)
{
ImGui::ClearActiveID();
}
}
bool didValueChange = false;
int kkey = *key;
if (g.ActiveId == id)
{
for (auto i = 0x1; i <= 0xA5; i++)
{
if (io.KeysDown[i])
{
kkey = i;
didValueChange = true;
ImGui::ClearActiveID();
}
}
if (IsKeyPressedMap(ImGuiKey_Escape))
{
*key = NULL;
ImGui::ClearActiveID();
}
else
{
*key = kkey;
}
}
char displayBuf[24] = "None";
if (*key != 0 && g.ActiveId != id)
{
strcpy_s(displayBuf, KeyNames[*key]);
}
else if (g.ActiveId == id)
{
strcpy_s(displayBuf, "Press key");
}
const ImRect clip_rect(frameBB.Min.x, frameBB.Min.y, frameBB.Min.x + size.x, frameBB.Min.y + size.y);
ImGui::RenderTextClipped(frameBB.Min + style.FramePadding, frameBB.Max - style.FramePadding, displayBuf, NULL, NULL, style.ButtonTextAlign, &clip_rect);
g.Style.FramePadding.y = backupPaddingY;
return didValueChange;
}
#endif // #ifndef IMGUI_DISABLE

View File

@ -291,12 +291,13 @@ public:
const char* m_pzsCurrentValue; //0x0058
__int64 m_iStringLength; //0x0060
float m_flValue; //0x0068
__int64 m_iValue; //0x006C
int m_iValue; //0x006C
bool m_bHasMin; //0x0070
float m_flMinValue; //0x0074
bool m_bHasMax; //0x0078
float m_flMaxValue; //0x007C
}; //Size: 0x0080
char pad_0080[32]; //0x0080
}; //Size: 0x00A0
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
{
@ -368,6 +369,7 @@ namespace GameGlobals
extern CInputSystem* InputSystem;
extern CCVar* Cvar;
ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk);
void InitGameGlobals();
extern bool IsInitialized;
}

View File

@ -1,6 +1,74 @@
#pragma once
/////////////////////////////////////////////////////////////////////////////
// Internals
int Stricmp(const char* s1, const char* s2);
int Strnicmp(const char* s1, const char* s2, int n);
char* Strdup(const char* s);
void Strtrim(char* s);
class GuiConfig
{
public:
struct
{
int bind1 = VK_OEM_3;
int bind2 = VK_INSERT;
} CGameConsoleConfig;
struct
{
int bind1 = VK_HOME;
int bind2 = VK_F10;
} CCompanionConfig;
void Load()
{
std::filesystem::path path = std::filesystem::current_path() /= "gui.config"; // Get current path + gui.config
nlohmann::json in;
std::ifstream config_file(path, std::ios::in); // Parse config file.
if (config_file.good() && config_file) // Check if it parsed.
{
config_file >> in;
config_file.close();
if (!in.is_null())
{
if (!in["config"].is_null())
{
// CGameConsole
CGameConsoleConfig.bind1 = in["config"]["CGameConsole"]["bind1"].get<int>();
CGameConsoleConfig.bind2 = in["config"]["CGameConsole"]["bind2"].get<int>();
// CCompanion
CCompanionConfig.bind1 = in["config"]["CCompanion"]["bind1"].get<int>();
CCompanionConfig.bind2 = in["config"]["CCompanion"]["bind2"].get<int>();
}
}
}
}
void Save()
{
nlohmann::json out;
// CGameConsole
out["config"]["CGameConsole"]["bind1"] = CGameConsoleConfig.bind1;
out["config"]["CGameConsole"]["bind2"] = CGameConsoleConfig.bind2;
// CCompanion
out["config"]["CCompanion"]["bind1"] = CCompanionConfig.bind1;
out["config"]["CCompanion"]["bind2"] = CCompanionConfig.bind2;
std::filesystem::path path = std::filesystem::current_path() /= "gui.config"; // Get current path + gui.config
std::ofstream out_file(path, std::ios::out | std::ios::trunc); // Write config file..
out_file << out.dump(4); // Dump it into config file..
out_file.close(); // Close the file handle.
};
};
extern GuiConfig g_GuiConfig;

View File

@ -64,7 +64,6 @@ namespace Hooks
#pragma region ConVar
bool ConVar_IsFlagSet(ConVar* cvar, int flag);
bool ConCommand_IsFlagSet(ConCommandBase* cmd, int flag);
void Map_Callback(void* args);
using ConVar_IsFlagSetFn = bool(*)(ConVar*, int);
extern ConVar_IsFlagSetFn originalConVar_IsFlagSet;

View File

@ -36,6 +36,11 @@ namespace
MemoryAddress FairFight_Init = r5_op.PatternSearch("40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6");
#pragma endregion
#pragma region Squirrel
/*0x14105CCA0*/
MemoryAddress Squirrel_CompileError = r5_op.StringSearch("%s SCRIPT COMPILE ERROR: %s").FindPatternSelf("48 89 5C", MemoryAddress::Direction::UP);
#pragma endregion
void PrintOAddress() // Test the sigscan results
{
std::cout << "+--------------------------------------------------------+" << std::endl;
@ -46,6 +51,7 @@ namespace
PRINT_ADDRESS("Host_NewGame", Host_NewGame.GetPtr());
PRINT_ADDRESS("CServer_Auth", CServer_Auth.GetPtr());
PRINT_ADDRESS("FairFight_Init", FairFight_Init.GetPtr());
PRINT_ADDRESS("Squirrel_CompileError", Squirrel_CompileError.GetPtr());
std::cout << "+--------------------------------------------------------+" << std::endl;
// TODO implement error handling when sigscan fails or result is 0

View File

@ -23,8 +23,10 @@ namespace
/*0x141057FD0*/
FUNC_AT_ADDRESS(addr_SQVM_Print, void*, r5_patterns.PatternSearch("83 F8 01 48 8D 3D ? ? ? ?").OffsetSelf(0x3).FollowNearCallSelf(0x3, 0x7).GetPtr());
/*0x14105F950*/
FUNC_AT_ADDRESS(addr_SQVM_Warning, __int64(*)(__int64, int, int, const char*, std::size_t*), r5_patterns.PatternSearch("E8 ? ? ? ? 85 C0 0F 99 C3").FollowNearCallSelf().GetPtr());
/*0x140B1E55*/
FUNC_AT_ADDRESS(addr_SQVM_Warning_ReturnAddr, void*, r5_patterns.PatternSearch("E8 ? ? ? ? 85 C0 0F 99 C3").OffsetSelf(0x5).GetPtr());
//DWORD64 p_SQVM_LoadScript = FindPattern("r5apex.exe", (const unsigned char*)"\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x48\x89\x4C\x24\x08\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); // For S0 and S1
@ -53,7 +55,7 @@ namespace
#pragma region CHLClient
/*0x1405C0740*/
FUNC_AT_ADDRESS(addr_CHLClient_FrameStageNotify, void(*)(void* rcx, int curStage), r5_patterns.PatternSearch("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr());
FUNC_AT_ADDRESS(addr_CHLClient_FrameStageNotify, void(*)(void*, int), r5_patterns.PatternSearch("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr());
#pragma endregion
#pragma region CVEngineServer
@ -62,12 +64,16 @@ namespace
#pragma endregion
#pragma region CBaseFileSystem
/*0x14038BE20*/
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.StringSearch("Engine Error").FindPatternSelf("48 89 ? ? ? 48 89", MemoryAddress::Direction::UP, 500).GetPtr());
/*0x1401B31C0*/
FUNC_AT_ADDRESS(addr_MemAlloc_Wrapper, void*(*)(__int64), r5_patterns.StringSearch("ConversionModeMenu").FindPatternSelf("E8 ? ? ? ? 48", MemoryAddress::Direction::UP).FollowNearCallSelf().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"));
@ -82,6 +88,8 @@ namespace
PRINT_ADDRESS("SQVM_Print", addr_SQVM_Print);
PRINT_ADDRESS("SQVM_LoadScript", addr_SQVM_LoadScript);
PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson);
PRINT_ADDRESS("SQVM_Warning", addr_SQVM_Warning);
PRINT_ADDRESS("SQVM_Warning_ReturnAddr", addr_SQVM_Warning_ReturnAddr);
PRINT_ADDRESS("NET_PrintFunc", addr_NET_PrintFunc);
PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram);
PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram);
@ -90,6 +98,7 @@ namespace
PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
PRINT_ADDRESS("CBaseFileSystem::FileSystemWarning", addr_CBaseFileSystem_FileSystemWarning);
PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError);
PRINT_ADDRESS("MemAlloc_Wrapper", addr_MemAlloc_Wrapper);
std::cout << "+--------------------------------------------------------+" << std::endl;
// TODO implement error handling when sigscan fails or result is 0
}

View File

@ -151,7 +151,7 @@
<AdditionalDependencies>Minhook.x64.lib;r5net.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>del $(SolutionDir)bin\$(Configuration)\r5dev.dll
<Command>del "$(SolutionDir)bin\$(Configuration)\r5dev.dll"
rename "$(TargetPath)" "r5dev.dll"</Command>
</PostBuildEvent>
<PreBuildEvent>

View File

@ -11,10 +11,20 @@
CCompanion* g_ServerBrowser = nullptr;
std::map<std::string, std::string> mapArray =
{
{ "mp_rr_canyonlands_64k_x_64k", "King's Canyon Season 0" },
{ "mp_rr_desertlands_64k_x_64k", "World's Edge Season 3" },
{ "mp_rr_canyonlands_mu1", "King's Canyon Season 2" },
{ "mp_rr_canyonlands_mu1_night", "King's Canyon Season 2 After Dark" },
{ "mp_rr_desertlands_64k_x_64k_nx", "World's Edge Season 3 After Dark" },
{ "mp_lobby", "Lobby Season 3" },
{ "mp_rr_canyonlands_staging", "King's Canyon Firing Range" }
};
/*-----------------------------------------------------------------------------
* _ccompanion.cpp
*-----------------------------------------------------------------------------*/
CCompanion::CCompanion() : MatchmakingServerStringBuffer("r5a-comp-sv.herokuapp.com"), r5net(new R5Net::Client("r5a-comp-sv.herokuapp.com"))
{
memset(ServerConnStringBuffer, 0, sizeof(ServerConnStringBuffer));
@ -26,7 +36,16 @@ CCompanion::CCompanion() : MatchmakingServerStringBuffer("r5a-comp-sv.herokuapp.
int slashPos = filename.rfind("\\", std::string::npos);
filename = filename.substr((INT8)slashPos + 1, std::string::npos);
filename = filename.substr(0, filename.size() - 6);
MapsList.push_back(filename);
auto it = mapArray.find(filename); // Find MapName in mapArray.
if (it != mapArray.end())
{
MapsList.push_back(it->second);
}
else
{
MapsList.push_back(filename);
}
}
// copy assignment kjek
@ -358,6 +377,7 @@ void CCompanion::ServerBrowserSection()
void CCompanion::HostServerSection()
{
static std::string ServerNameErr = "";
static std::string ServerMap = std::string();
ImGui::InputTextWithHint("##ServerHost_ServerName", "Server Name (Required)", &MyServer.name);
ImGui::InputTextWithHint("##ServerHost_ServerPassword", "Password (Optional)", &MyServer.password);
@ -369,13 +389,18 @@ void CCompanion::HostServerSection()
if (ImGui::Selectable(item.c_str(), item == MyServer.map))
{
MyServer.map = item;
for (auto it = mapArray.begin(); it != mapArray.end(); ++it)
{
if (it->second.compare(MyServer.map) == NULL)
ServerMap = it->first;
}
}
}
ImGui::EndCombo();
}
ImGui::Spacing();
ImGui::Checkbox("Start as dedicated server (HACK)##ServerHost_DediCheckbox", &StartAsDedi);
ImGui::Checkbox("Start as Dedicated Server (HACK)##ServerHost_DediCheckbox", &StartAsDedi);
ImGui::SameLine();
@ -389,9 +414,8 @@ void CCompanion::HostServerSection()
{
ServerNameErr = std::string();
UpdateHostingStatus();
std::stringstream cmd;
cmd << "map " << MyServer.map;
cmd << "map " << ServerMap;
ProcessCommand(cmd.str().c_str());
if (StartAsDedi)
@ -407,7 +431,7 @@ void CCompanion::HostServerSection()
if (ImGui::Button("Force Start##ServerHost_ForceStart", ImVec2(ImGui::GetWindowSize().x, 32)))
{
strncpy_s(GameGlobals::HostState->m_levelName, MyServer.map.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname.
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_NEW_GAME; // Force CHostState::FrameUpdate to start a server.
}
@ -428,7 +452,7 @@ void CCompanion::HostServerSection()
if (ImGui::Button("Change Level##ServerHost_ChangeLevel", ImVec2(ImGui::GetWindowSize().x, 32)))
{
strncpy_s(GameGlobals::HostState->m_levelName, MyServer.map.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname.
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.
}

View File

@ -75,6 +75,18 @@ void CGameConsole::Draw(const char* title)
ClearLog();
}
copy_to_clipboard = ImGui::SmallButton("Copy");
ImGui::Text("CG Hotkey:");
ImGui::SameLine();
if (ImGui::Hotkey("##OpenCGameConsoleBind1", &g_GuiConfig.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)))
{
g_GuiConfig.Save();
}
ImGui::EndPopup();
}
if (ImGui::Button("Options"))

View File

@ -15,6 +15,7 @@ void InitializeR5Dev()
SetupConsole();
Hooks::InstallHooks();
InstallOpcodes();
g_GuiConfig.Load(); // Load gui config.
SetupDXSwapChain();
printf("+-----------------------------------------------------------------------------+\n");
printf("| R5 DEV -- INITIALIZED ------------------------------------------------- |\n");

View File

@ -1,8 +1,60 @@
#include "pch.h"
#include "gameclasses.h"
#include "id3dx.h"
namespace GameGlobals
{
namespace CustomConVar
{
void CGameConsole_Callback(void* cmd)
{
std::string szValue = *(const char**)((std::uintptr_t)cmd + 0x18);
try
{
int value = std::stoi(szValue);
switch (value)
{
case 0:
g_bShowConsole = false;
break;
case 1:
g_bShowConsole = true;
break;
default:
break;
}
}
catch (std::exception& e)
{
std::cout << " [+CGameConsole+] Please don't input a character that isn't a number into cgameconsole :(. Error: " << e.what() << std::endl;
}
}
void CCompanion_Callback(void* cmd)
{
std::string szValue = *(const char**)((std::uintptr_t)cmd + 0x18);
try
{
int value = std::stoi(szValue);
switch (value)
{
case 0:
g_bShowBrowser = false;
break;
case 1:
g_bShowBrowser = true;
break;
default:
break;
}
}
catch (std::exception& e)
{
std::cout << " [+CCompanion+] Please don't input a character that isn't a number into ccompanion :(. Error: " << e.what() << std::endl;
};
}
}
bool IsInitialized = false;
CHostState* HostState = nullptr;
CInputSystem* InputSystem = nullptr;
@ -49,7 +101,29 @@ namespace GameGlobals
// {
// printf("%s: %p\n", current->InterfaceName, current->InterfacePtr);
// }
ConVar* CGameConsoleConVar = CreateCustomConVar("cgameconsole", "0", 0, "Opens the R5 Reloaded Console", false, 0.f, false, 0.f, CustomConVar::CGameConsole_Callback, nullptr);
ConVar* CCompanionConVar = CreateCustomConVar("ccompanion", "0", 0, "Opens the R5 Reloaded Server Browser", false, 0.f, false, 0.f, CustomConVar::CCompanion_Callback, nullptr);
EmptyHostNames();
IsInitialized = true;
}
ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk)
{
static MemoryAddress ConVarVtable = MemoryAddress(0x14046FB50).Offset(0x12).ResolveRelativeAddress(); // Get vtable ptr for ConVar table.
static MemoryAddress ICvarVtable = MemoryAddress(0x14046FB50).Offset(0x29).ResolveRelativeAddress(); // Get vtable ptr for ICvar table.
static MemoryAddress CreateConVar = MemoryAddress(0x140470540); // Get CreateConvar address.
ConVar* allocatedConvar = reinterpret_cast<ConVar*>(addr_MemAlloc_Wrapper(0xA0)); // Allocate new memory with StdMemAlloc else we crash.
memset(allocatedConvar, 0, 0xA0); // Set all to null.
std::uintptr_t cvarPtr = reinterpret_cast<std::uintptr_t>(allocatedConvar); // To ptr.
*(void**)(cvarPtr + 0x40) = ICvarVtable.RCast<void*>(); // 0x40 to ICvar table.
*(void**)cvarPtr = ConVarVtable.RCast<void*>(); // 0x0 to ConVar table.
CreateConVar.RCast<void(*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, void*, void*)>() // Call to create ConVar.
(allocatedConvar, name, defaultValue, flags, helpString, bMin, fMin, bMax, fMax, callback, unk);
return allocatedConvar; // Return allocated ConVar.
}
}

View File

@ -1,6 +1,7 @@
#include "pch.h"
#include "gui_utility.h"
GuiConfig g_GuiConfig;
/*-----------------------------------------------------------------------------
* _gui_utility.cpp
@ -40,4 +41,4 @@ void Strtrim(char* s)
while (str_end > s && str_end[-1] == ' ')
str_end--; *str_end = 0;
}
}

View File

@ -1,6 +1,10 @@
#include "pch.h"
#include "hooks.h"
#ifdef _DEBUG
#define MaskOffCheats
#endif
namespace Hooks
{
ConVar_IsFlagSetFn originalConVar_IsFlagSet = nullptr;
@ -10,19 +14,19 @@ namespace Hooks
bool Hooks::ConVar_IsFlagSet(ConVar* cvar, int flag)
{
#ifdef _DEBUG
#ifdef MaskOffCheats
if (g_bDebugConsole)
{
printf("--------------------------------------------------\n");
printf(" Flaged: %08X\n", cvar->m_ConCommandBase.m_nFlags);
std::cout << "--------------------------------------------------\n";
std::cout << cvar->m_ConCommandBase.m_pszName << " Flags: " << std::hex << std::uppercase << cvar->m_ConCommandBase.m_nFlags << "\n";
}
// Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY
cvar->m_ConCommandBase.m_nFlags &= 0xFFFFBFFD;
// Mask off FCVAR_DEVELOPMENTONLY and FCVAR_CHEAT.
cvar->m_ConCommandBase.m_nFlags &= ~(FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
if (g_bDebugConsole)
{
printf(" Masked: %08X\n", cvar->m_ConCommandBase.m_nFlags);
printf(" Verify: %08X\n", flag);
printf("--------------------------------------------------\n");
std::cout << cvar->m_ConCommandBase.m_pszName << " Flags: " << std::hex << std::uppercase << cvar->m_ConCommandBase.m_nFlags << "\n";
std::cout << cvar->m_ConCommandBase.m_pszName << " Verify: " << std::hex << std::uppercase << flag << "\n";
std::cout << "--------------------------------------------------\n";
}
if (flag & FCVAR_RELEASE)
@ -30,14 +34,12 @@ bool Hooks::ConVar_IsFlagSet(ConVar* cvar, int flag)
return true;
}
if (!g_bReturnAllFalse)
{
return (cvar->m_ConCommandBase.m_nFlags & flag) != 0;
}
else
if (g_bReturnAllFalse)
{
return false;
}
return (cvar->m_ConCommandBase.m_nFlags & flag) != 0;
#else
// Mask off FCVAR_DEVELOPMENTONLY if existing.
cvar->m_ConCommandBase.m_nFlags &= ~FCVAR_DEVELOPMENTONLY;
@ -48,19 +50,19 @@ bool Hooks::ConVar_IsFlagSet(ConVar* cvar, int flag)
bool Hooks::ConCommand_IsFlagSet(ConCommandBase* cmd, int flag)
{
#ifdef _DEBUG
#ifdef MaskOffCheats
if (g_bDebugConsole)
{
printf("--------------------------------------------------\n");
printf(" Flaged: %08X\n", cmd->m_nFlags);
std::cout << "--------------------------------------------------\n";
std::cout << cmd->m_pszName << " Flags: " << std::hex << std::uppercase << cmd->m_nFlags << "\n";
}
// Mask off FCVAR_CHEATS and FCVAR_DEVELOPMENTONLY
cmd->m_nFlags &= 0xFFFFBFFD;
// Mask off FCVAR_DEVELOPMENTONLY and FCVAR_CHEAT.
cmd->m_nFlags &= ~(FCVAR_DEVELOPMENTONLY | FCVAR_CHEAT);
if (g_bDebugConsole)
{
printf(" Masked: %08X\n", cmd->m_nFlags);
printf(" Verify: %08X\n", flag);
printf("--------------------------------------------------\n");
std::cout << cmd->m_pszName << " Flags: " << std::hex << std::uppercase << cmd->m_nFlags << "\n";
std::cout << cmd->m_pszName << " Verify: " << std::hex << std::uppercase << flag << "\n";
std::cout << "--------------------------------------------------\n";
}
if (flag & FCVAR_RELEASE)
@ -68,14 +70,12 @@ bool Hooks::ConCommand_IsFlagSet(ConCommandBase* cmd, int flag)
return true;
}
if (!g_bReturnAllFalse)
{
return (cmd->m_nFlags & flag) != 0;
}
else
if (g_bReturnAllFalse)
{
return false;
}
return (cmd->m_nFlags & flag) != 0;
#else
// Mask off FCVAR_DEVELOPMENTONLY if existing.
cmd->m_nFlags &= ~FCVAR_DEVELOPMENTONLY;

View File

@ -56,17 +56,14 @@ LRESULT CALLBACK DXGIMsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
LRESULT CALLBACK HwndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_KEYDOWN)
if (uMsg == WM_KEYUP || uMsg == WM_SYSKEYDOWN)
{
if (wParam == VK_OEM_3 || wParam == VK_INSERT) // For everyone without a US keyboard layout.
if (wParam == g_GuiConfig.CGameConsoleConfig.bind1 || wParam == g_GuiConfig.CGameConsoleConfig.bind2)
{
g_bShowConsole = !g_bShowConsole;
}
}
if (uMsg == WM_SYSKEYDOWN)
{
if (wParam == VK_F10)
if (wParam == g_GuiConfig.CCompanionConfig.bind1 || wParam == g_GuiConfig.CCompanionConfig.bind2)
{
g_bShowBrowser = !g_bShowBrowser;
}

View File

@ -26,4 +26,7 @@ void InstallOpcodes() /* .TEXT */
//-------------------------------------------------------------------------
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server
FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 });
//-------------------------------------------------------------------------
// CALL --> NOP | Prevent squirrel compiler errors from calling Error
Squirrel_CompileError.Offset(0x12C).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 });
}

BIN
r5launcher/R5 Reloaded.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,6 +1,6 @@
#include <string>
#include <stdio.h>
#include <iostream>
#include <Windows.h>
#include <detours.h>
@ -40,7 +40,7 @@ bool LaunchR5Apex(LAUNCHMODE lMode, LAUNCHSTATE lState)
BOOL result;
FILE* sLaunchParams;
CHAR sArgumentBuffer[1024] = { 0 };
CHAR sArgumentBuffer[2048] = { 0 };
CHAR sCommandDirectory[MAX_PATH];
LPSTR sCommandLine = sCommandDirectory;
@ -182,14 +182,75 @@ int main(int argc, char* argv[], char* envp[])
Sleep(2000);
return EXIT_SUCCESS;
}
if ((arg == "-debug") || (arg == "-dbg"))
{
LaunchR5Apex(LAUNCHMODE::LM_DEBUG, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
}
if ((arg == "-release") || (arg == "-rl"))
{
LaunchR5Apex(LAUNCHMODE::LM_GAME, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
}
}
LaunchR5Apex(LAUNCHMODE::LM_GAME, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
std::cout << "If you choose Dev as start parameter do not host servers into the Server Browser\n\n"
<< "Every command will be and people can execute any script on your server.\n\n"
<< "Use release for normal playing.\n\n"
<< "Dev should only be used for testing purposes.\n\n";
std::cout << "Enter 1 for Dev Build. Enter 2 for Release Build:\n";
std::string input = std::string();
if (std::cin >> input)
{
try
{
LAUNCHMODE iinput = (LAUNCHMODE)std::stoi(input);
switch (iinput)
{
case LAUNCHMODE::LM_DEBUG:
{
LaunchR5Apex(LAUNCHMODE::LM_DEBUG, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
}
case LAUNCHMODE::LM_GAME:
{
LaunchR5Apex(LAUNCHMODE::LM_GAME, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
}
case LAUNCHMODE::LM_DEDI:
{
LaunchR5Apex(LAUNCHMODE::LM_DEDI, LAUNCHSTATE::LS_CHEATS);
Sleep(2000);
return EXIT_SUCCESS;
}
default:
{
std::cout << "R5 Reloaded asked for a number between 1 and 2 :(.\n";
Sleep(2000);
return EXIT_FAILURE;
}
}
}
catch (std::exception& e)
{
std::cout << "R5 Reloaded asked for a number and not a letter or anything of that sort :(. Error: " << e.what() << std::endl;
Sleep(5000);
return EXIT_FAILURE;
}
}
std::cout << "R5 Reloaded needs an input to launch :(.\n";
Sleep(5000);
return EXIT_FAILURE;
}

View File

@ -5,9 +5,10 @@
//-----------------------------------------------------------------------------
enum class LAUNCHMODE : int
{
LM_GAME, // Dev DLL
LM_DEDI, // Dedi DLL
LM_DEBUG // Debug DLL
LM_NULL,
LM_DEBUG, // Debug DLL
LM_GAME, // Release DLL
LM_DEDI // Dedi DLL
};
//-----------------------------------------------------------------------------

71
r5launcher/r5launcher.rc Normal file
View File

@ -0,0 +1,71 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// German (Germany) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "R5 Reloaded.ico"
#endif // German (Germany) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -165,8 +165,8 @@
<AdditionalDependencies>detours.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>
</Command>
<Command>del "$(SolutionDir)bin\$(Configuration)\Run R5 Reloaded.exe"
rename "$(TargetPath)" "Run R5 Reloaded.exe"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
@ -174,6 +174,13 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="r5launcher.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="R5 Reloaded.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -23,5 +23,18 @@
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="r5launcher.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="R5 Reloaded.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
</Project>

16
r5launcher/resource.h Normal file
View File

@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by r5launcher.rc
//
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1,6 +1,8 @@
#pragma once
#pragma message("Precompiling r5net headers.\n")
//#define DebugR5Net
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <thread>

View File

@ -22,7 +22,7 @@ namespace R5Net
std::vector<ServerListing> GetServersList(std::string& outMessage);
bool PostServerHost(std::string& outMessage, std::string& outToken, const ServerListing& serverListing);
bool GetServerByToken(ServerListing& outServer, std::string& outError, const std::string& token, const std::string& password = "");
bool GetServerByToken(ServerListing& outServer, std::string& outMessage, const std::string token, const std::string password = "");
std::string GetVersionString();
};
}

View File

@ -16,11 +16,19 @@ std::vector<ServerListing> R5Net::Client::GetServersList(std::string& outMessage
nlohmann::json reqBody = nlohmann::json::object();
reqBody["version"] = GetVersionString();
std::string reqBodyStr = reqBody.dump();;
std::string reqBodyStr = reqBody.dump();
#ifdef DebugR5Net
std::cout << " [+R5Net+] Sending GetServerList post now..\n";
#endif
httplib::Result res = m_HttpClient.Post("/servers", reqBody.dump().c_str(), reqBody.dump().length(), "application/json");
if (res)
#ifdef DebugR5Net
std::cout << " [+R5Net+] GetServerList replied with " << res->status << "\n";
#endif
if (res && res->status == 200) // STATUS_OK
{
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (resBody["success"].is_boolean() && resBody["success"].get<bool>())
@ -42,7 +50,10 @@ std::vector<ServerListing> R5Net::Client::GetServersList(std::string& outMessage
}
else
{
outMessage = "Failed to reach comp-server";
if (res)
outMessage = std::string("Failed to reach comp-server ") + std::to_string(res->status);
else
outMessage = "Failed to reach comp-server unknown error code.";
}
return list;
@ -61,70 +72,119 @@ bool R5Net::Client::PostServerHost(std::string& outMessage, std::string& outToke
std::string reqBodyStr = reqBody.dump();
auto res = m_HttpClient.Post("/servers/add", reqBodyStr.c_str(), reqBodyStr.length(), "application/json");
#ifdef DebugR5Net
std::cout << " [+R5Net+] Sending PostServerHost post now..\n";
#endif
if (!res)
httplib::Result res = m_HttpClient.Post("/servers/add", reqBodyStr.c_str(), reqBodyStr.length(), "application/json");
#ifdef DebugR5Net
std::cout << " [+R5Net+] PostServerHost replied with " << res->status << "\n";
#endif
if (res && res->status == 200) // STATUS_OK
{
outMessage = "Failed to reach comp-server";
outToken = "";
return false;
}
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (resBody["success"].is_boolean() && resBody["success"].get<bool>())
{
if (resBody["token"].is_string())
outToken = resBody["token"].get<std::string>();
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (resBody["success"].is_boolean() && resBody["success"].get<bool>())
{
if (resBody["token"].is_string())
outToken = resBody["token"].get<std::string>();
else
outToken = "";
return true;
}
else
outToken = "";
return true;
{
if (resBody["err"].is_string())
outMessage = resBody["err"].get<std::string>();
else
outMessage = "An unknown error occured!";
return false;
}
}
else
{
if (resBody["err"].is_string())
outMessage = resBody["err"].get<std::string>();
else
outMessage = "An unknown error occured!";
if (res)
outMessage = std::string("Failed to reach comp-server ") + std::to_string(res->status);
else
outMessage = "Failed to reach comp-server unknown error code.";
outToken = "";
return false;
}
return false;
}
bool R5Net::Client::GetServerByToken(ServerListing& outServer, std::string& outError, const std::string& token, const std::string& password)
bool R5Net::Client::GetServerByToken(ServerListing& outServer, std::string& outMessage, const std::string token, const std::string password)
{
nlohmann::json reqBody = nlohmann::json::object();
reqBody["token"] = token;
reqBody["password"] = password;
#ifdef DebugR5Net
std::cout << " [+R5Net+] Sending GetServerByToken post now...\n";
#endif
httplib::Result res = m_HttpClient.Post("/server/byToken", reqBody.dump().c_str(), reqBody.dump().length(), "application/json");
if (!res)
#ifdef DebugR5Net
std::cout << " [+R5Net+] GetServerByToken replied with " << res->status << "\n";
#endif
if (res && res->status == 200) // STATUS_OK
{
outError = "Failed to reach comp-server";
outServer = ServerListing{};
return false;
if (!res->body.empty())
{
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (res && resBody["success"].is_boolean() && resBody["success"])
{
outServer = ServerListing{
resBody["server"]["name"].get<std::string>(),
resBody["server"]["map"].get<std::string>(),
resBody["server"]["ip"].get<std::string>(),
resBody["server"]["port"].get<std::string>()
};
return true;
}
else
{
if (resBody["err"].is_string())
outMessage = resBody["err"].get<std::string>();
else
outMessage = "";
outServer = ServerListing{};
return false;
}
}
}
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (res && resBody["success"].is_boolean() && resBody["success"])
else
{
outServer = ServerListing{
resBody["server"]["name"].get<std::string>(),
resBody["server"]["map"].get<std::string>(),
resBody["server"]["ip"].get<std::string>(),
resBody["server"]["port"].get<std::string>()
};
return true;
}
else
{
if (resBody["err"].is_string())
outError = resBody["err"].get<std::string>();
else
outError = "";
if (res)
{
if (!res->body.empty())
{
nlohmann::json resBody = nlohmann::json::parse(res->body);
if (resBody["err"].is_string())
outMessage = resBody["err"].get<std::string>();
else
outMessage = "Failed to reach comp-server unknown error code.";
return false;
}
outMessage = std::string("Failed to reach comp-server ") + std::to_string(res->status);
return false;
}
outMessage = "failed to reach comp-server unknown error code.";
outServer = ServerListing{};
return false;
}

View File

@ -276,26 +276,21 @@ public:
MemoryAddress FollowNearCall(std::ptrdiff_t opcodeOffset = 0x1, std::ptrdiff_t nextInstructionOffset = 0x5)
{
// Skip E9 opcode.
std::uintptr_t skipOpCode = ptr + opcodeOffset;
// Get 4-byte long relative address.
std::int32_t relativeAddress = *reinterpret_cast<std::int32_t*>(skipOpCode);
// Get location of next instruction.
std::uintptr_t nextInstruction = ptr + nextInstructionOffset;
// Get function location via adding relative address to next instruction.
return MemoryAddress(nextInstruction + relativeAddress);
return ResolveRelativeAddress(opcodeOffset, nextInstructionOffset);
}
MemoryAddress FollowNearCallSelf(std::ptrdiff_t opcodeOffset = 0x1, std::ptrdiff_t nextInstructionOffset = 0x5)
{
// Skip E9 opcode.
std::uintptr_t skipOpCode = ptr + opcodeOffset;
return ResolveRelativeAddressSelf(opcodeOffset, nextInstructionOffset);
}
MemoryAddress ResolveRelativeAddressSelf(std::ptrdiff_t registerOffset = 0x0, std::ptrdiff_t nextInstructionOffset = 0x4)
{
// Skip register.
std::uintptr_t skipRegister = ptr + registerOffset;
// Get 4-byte long relative address.
std::int32_t relativeAddress = *reinterpret_cast<std::int32_t*>(skipOpCode);
std::int32_t relativeAddress = *reinterpret_cast<std::int32_t*>(skipRegister);
// Get location of next instruction.
std::uintptr_t nextInstruction = ptr + nextInstructionOffset;
@ -304,7 +299,22 @@ public:
ptr = nextInstruction + relativeAddress;
return *this;
}
MemoryAddress ResolveRelativeAddress(std::ptrdiff_t registerOffset = 0x0, std::ptrdiff_t nextInstructionOffset = 0x4)
{
// Skip register.
std::uintptr_t skipRegister = ptr + registerOffset;
// Get 4-byte long relative address.
std::int32_t relativeAddress = *reinterpret_cast<std::int32_t*>(skipRegister);
// Get location of next instruction.
std::uintptr_t nextInstruction = ptr + nextInstructionOffset;
// Get function location via adding relative address to next instruction.
return MemoryAddress(nextInstruction + relativeAddress);
}
private:
std::uintptr_t ptr = 0;
};
@ -339,14 +349,6 @@ public:
return ModuleSections();
}
void PrintSections()
{
for (ModuleSections& currentSection : moduleSections)
{
printf(" [+Module: %s+]%s, %p\n", moduleName.c_str(), currentSection.sectionName.c_str(), reinterpret_cast<void*>(currentSection.sectionStartAddress));
}
}
Module() = default;
Module(std::string moduleName) : moduleName(moduleName)
{

View File

@ -4,7 +4,6 @@
// Internals
BOOL FileExists(LPCTSTR szPath);
MODULEINFO GetModuleInfo(const char* szModule);
std::uint8_t* PatternScan(const char* module, const char* signature);
/////////////////////////////////////////////////////////////////////////////
// Utility