Add `FUNCTION_AT` and `VAR_AT` macros (#416)
* add FUNCTION_AT and VAR_AT macros * fix build issues oops * fix formatting * add PREDEFINED_VAR_AT * change func name * fixup formatting * update to use DEFINED_VAR_AT
This commit is contained in:
parent
6aaac4cd45
commit
32165afe41
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Returns true if this is a command
|
||||
// Output : bool
|
||||
|
|
|
@ -65,6 +65,9 @@ __dllLoadCallback::__dllLoadCallback(
|
|||
|
||||
void __fileAutohook::Dispatch()
|
||||
{
|
||||
for (__autovar* var : vars)
|
||||
var->Dispatch();
|
||||
|
||||
for (__autohook* hook : hooks)
|
||||
hook->Dispatch();
|
||||
}
|
||||
|
@ -114,6 +117,42 @@ bool ManualHook::Dispatch(LPVOID addr, LPVOID* orig)
|
|||
return false;
|
||||
}
|
||||
|
||||
uintptr_t ParseDLLOffsetString(const char* pAddrString)
|
||||
{
|
||||
// in the format server.dll + 0xDEADBEEF
|
||||
int iDllNameEnd = 0;
|
||||
for (; !isspace(pAddrString[iDllNameEnd]) && pAddrString[iDllNameEnd] != '+'; iDllNameEnd++)
|
||||
;
|
||||
|
||||
char* pModuleName = new char[iDllNameEnd + 1];
|
||||
memcpy(pModuleName, pAddrString, iDllNameEnd);
|
||||
pModuleName[iDllNameEnd] = '\0';
|
||||
|
||||
// get the module address
|
||||
const HMODULE pModuleAddr = GetModuleHandleA(pModuleName);
|
||||
|
||||
if (!pModuleAddr)
|
||||
return 0;
|
||||
|
||||
// get the offset string
|
||||
uintptr_t iOffset = 0;
|
||||
|
||||
int iOffsetBegin = iDllNameEnd;
|
||||
int iOffsetEnd = strlen(pAddrString);
|
||||
|
||||
// seek until we hit the start of the number offset
|
||||
for (; !(pAddrString[iOffsetBegin] >= '0' && pAddrString[iOffsetBegin] <= '9') && pAddrString[iOffsetBegin]; iOffsetBegin++)
|
||||
;
|
||||
|
||||
bool bIsHex = pAddrString[iOffsetBegin] == '0' && (pAddrString[iOffsetBegin + 1] == 'X' || pAddrString[iOffsetBegin + 1] == 'x');
|
||||
if (bIsHex)
|
||||
iOffset = std::stoi(pAddrString + iOffsetBegin + 2, 0, 16);
|
||||
else
|
||||
iOffset = std::stoi(pAddrString + iOffsetBegin);
|
||||
|
||||
return ((uintptr_t)pModuleAddr + iOffset);
|
||||
}
|
||||
|
||||
// dll load callback stuff
|
||||
// this allows for code to register callbacks to be run as soon as a dll is loaded, mainly to allow for patches to be made on dll load
|
||||
struct DllLoadCallback
|
||||
|
|
|
@ -63,16 +63,20 @@ class __dllLoadCallback
|
|||
|
||||
// new macro hook stuff
|
||||
class __autohook;
|
||||
class __autovar;
|
||||
|
||||
class __fileAutohook
|
||||
{
|
||||
public:
|
||||
std::vector<__autohook*> hooks;
|
||||
std::vector<__autovar*> vars;
|
||||
|
||||
void Dispatch();
|
||||
void DispatchForModule(const char* pModuleName);
|
||||
};
|
||||
|
||||
uintptr_t ParseDLLOffsetString(const char* pAddrString);
|
||||
|
||||
// initialise autohooks for this file
|
||||
#define AUTOHOOK_INIT() \
|
||||
namespace \
|
||||
|
@ -187,39 +191,7 @@ class __autohook
|
|||
|
||||
case OFFSET_STRING:
|
||||
{
|
||||
// in the format server.dll + 0xDEADBEEF
|
||||
int iDllNameEnd = 0;
|
||||
for (; !isspace(pAddrString[iDllNameEnd]) && pAddrString[iDllNameEnd] != '+'; iDllNameEnd++)
|
||||
;
|
||||
|
||||
char* pModuleName = new char[iDllNameEnd + 1];
|
||||
memcpy(pModuleName, pAddrString, iDllNameEnd);
|
||||
pModuleName[iDllNameEnd] = '\0';
|
||||
|
||||
// get the module address
|
||||
const HMODULE pModuleAddr = GetModuleHandleA(pModuleName);
|
||||
|
||||
if (!pModuleAddr)
|
||||
break;
|
||||
|
||||
// get the offset string
|
||||
uintptr_t iOffset = 0;
|
||||
|
||||
int iOffsetBegin = iDllNameEnd;
|
||||
int iOffsetEnd = strlen(pAddrString);
|
||||
|
||||
// seek until we hit the start of the number offset
|
||||
for (; !(pAddrString[iOffsetBegin] >= '0' && pAddrString[iOffsetBegin] <= '9') && pAddrString[iOffsetBegin]; iOffsetBegin++)
|
||||
;
|
||||
|
||||
bool bIsHex =
|
||||
pAddrString[iOffsetBegin] == '0' && (pAddrString[iOffsetBegin + 1] == 'X' || pAddrString[iOffsetBegin + 1] == 'x');
|
||||
if (bIsHex)
|
||||
iOffset = std::stoi(pAddrString + iOffsetBegin + 2, 0, 16);
|
||||
else
|
||||
iOffset = std::stoi(pAddrString + iOffsetBegin);
|
||||
|
||||
targetAddr = (LPVOID)((uintptr_t)pModuleAddr + iOffset);
|
||||
targetAddr = (LPVOID)ParseDLLOffsetString(pAddrString);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -309,3 +281,51 @@ class ManualHook
|
|||
|
||||
void MakeHook(LPVOID pTarget, LPVOID pDetour, void* ppOriginal, const char* pFuncName = "");
|
||||
#define MAKEHOOK(pTarget, pDetour, ppOriginal) MakeHook(pTarget, pDetour, ppOriginal, __STR(pDetour))
|
||||
|
||||
class __autovar
|
||||
{
|
||||
public:
|
||||
char* m_pAddrString;
|
||||
void** m_pTarget;
|
||||
|
||||
public:
|
||||
__autovar(__fileAutohook* pAutohook, const char* pAddrString, void** pTarget)
|
||||
{
|
||||
m_pTarget = pTarget;
|
||||
|
||||
const int iAddrStrlen = strlen(pAddrString) + 1;
|
||||
m_pAddrString = new char[iAddrStrlen];
|
||||
memcpy(m_pAddrString, pAddrString, iAddrStrlen);
|
||||
|
||||
pAutohook->vars.push_back(this);
|
||||
}
|
||||
|
||||
void Dispatch()
|
||||
{
|
||||
*m_pTarget = (void*)ParseDLLOffsetString(m_pAddrString);
|
||||
}
|
||||
};
|
||||
|
||||
// VAR_AT(engine.dll+0x404, ConVar*, Cvar_host_timescale)
|
||||
#define VAR_AT(addrString, type, name) \
|
||||
type name; \
|
||||
namespace \
|
||||
{ \
|
||||
__autovar CONCAT2(__autovar, __LINE__)(&__FILEAUTOHOOK, __STR(addrString), (void**)&name); \
|
||||
}
|
||||
|
||||
// FUNCTION_AT(engine.dll + 0xDEADBEEF, void, __fastcall, SomeFunc, (void* a1))
|
||||
#define FUNCTION_AT(addrString, type, callingConvention, name, args) \
|
||||
type(*callingConvention name) args; \
|
||||
namespace \
|
||||
{ \
|
||||
__autovar CONCAT2(__autovar, __LINE__)(&__FILEAUTOHOOK, __STR(addrString), (void**)&name); \
|
||||
}
|
||||
|
||||
// int* g_pSomeInt;
|
||||
// DEFINED_VAR_AT(engine.dll + 0x5005, g_pSomeInt)
|
||||
#define DEFINED_VAR_AT(addrString, name) \
|
||||
namespace \
|
||||
{ \
|
||||
__autovar CONCAT2(__autovar, __LINE__)(&__FILEAUTOHOOK, __STR(addrString), (void**)&name); \
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include "shared/misccommands.h"
|
||||
#include "r2engine.h"
|
||||
#include "core/tier0.h"
|
||||
|
||||
AUTOHOOK_INIT()
|
||||
|
||||
// clang-format off
|
||||
AUTOHOOK(Host_Init, engine.dll + 0x155EA0,
|
||||
void, __fastcall, (bool bDedicated))
|
||||
|
@ -24,6 +26,7 @@ void, __fastcall, (bool bDedicated))
|
|||
else
|
||||
R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "exec autoexec_ns_client", R2::cmd_source_t::kCommandSrcCode);
|
||||
}
|
||||
|
||||
ON_DLL_LOAD("engine.dll", Host_Init, (CModule module))
|
||||
{
|
||||
AUTOHOOK_DISPATCH()
|
||||
|
|
|
@ -18,10 +18,10 @@ namespace R2
|
|||
CHostState* g_pHostState;
|
||||
} // namespace R2
|
||||
|
||||
ConVar* Cvar_hostport;
|
||||
std::string sLastMode;
|
||||
|
||||
void (*_fastcall _Cmd_Exec_f)(const CCommand& arg, bool bOnlyIfExists, bool bUseWhitelists);
|
||||
VAR_AT(engine.dll + 0x13FA6070, ConVar*, Cvar_hostport);
|
||||
FUNCTION_AT(engine.dll + 0x1232C0, void, __fastcall, _Cmd_Exec_f, (const CCommand& arg, bool bOnlyIfExists, bool bUseWhitelists));
|
||||
|
||||
void ServerStartingOrChangingMap()
|
||||
{
|
||||
|
@ -194,7 +194,4 @@ ON_DLL_LOAD_RELIESON("engine.dll", HostState, ConVar, (CModule module))
|
|||
AUTOHOOK_DISPATCH()
|
||||
|
||||
g_pHostState = module.Offset(0x7CF180).As<CHostState*>();
|
||||
Cvar_hostport = module.Offset(0x13FA6070).As<ConVar*>();
|
||||
|
||||
_Cmd_Exec_f = module.Offset(0x1232C0).As<void (*__fastcall)(const CCommand&, bool, bool)>();
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ AUTOHOOK_INIT()
|
|||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
const char* (*GetCurrentPlaylistName)();
|
||||
void (*SetCurrentPlaylist)(const char* pPlaylistName);
|
||||
void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
|
||||
const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
|
||||
DEFINED_VAR_AT(engine.dll + 0x18C640, GetCurrentPlaylistName);
|
||||
DEFINED_VAR_AT(engine.dll + 0x18EB20, SetCurrentPlaylist);
|
||||
DEFINED_VAR_AT(engine.dll + 0x18ED00, SetPlaylistVarOverride);
|
||||
DEFINED_VAR_AT(engine.dll + 0x18C680, GetCurrentPlaylistVar);
|
||||
} // namespace R2
|
||||
|
||||
ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
|
||||
|
@ -104,11 +104,6 @@ ON_DLL_LOAD_RELIESON("engine.dll", PlaylistHooks, (ConCommand, ConVar), (CModule
|
|||
{
|
||||
AUTOHOOK_DISPATCH()
|
||||
|
||||
R2::GetCurrentPlaylistName = module.Offset(0x18C640).As<const char* (*)()>();
|
||||
R2::SetCurrentPlaylist = module.Offset(0x18EB20).As<void (*)(const char*)>();
|
||||
R2::SetPlaylistVarOverride = module.Offset(0x18ED00).As<void (*)(const char*, const char*)>();
|
||||
R2::GetCurrentPlaylistVar = module.Offset(0x18C680).As<const char* (*)(const char*, bool)>();
|
||||
|
||||
// playlist is the name of the command on respawn servers, but we already use setplaylist so can't get rid of it
|
||||
RegisterConCommand("playlist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
|
||||
RegisterConCommand("setplaylist", ConCommand_playlist, "Sets the current playlist", FCVAR_NONE);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// use the R2 namespace for game funcs
|
||||
namespace R2
|
||||
{
|
||||
extern const char* (*GetCurrentPlaylistName)();
|
||||
extern void (*SetCurrentPlaylist)(const char* pPlaylistName);
|
||||
extern void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
|
||||
extern const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
|
||||
inline const char* (*GetCurrentPlaylistName)();
|
||||
inline void (*SetCurrentPlaylist)(const char* pPlaylistName);
|
||||
inline void (*SetPlaylistVarOverride)(const char* pVarName, const char* pValue);
|
||||
inline const char* (*GetCurrentPlaylistVar)(const char* pVarName, bool bUseOverrides);
|
||||
} // namespace R2
|
||||
|
|
Loading…
Reference in New Issue