2019-05-15 14:52:37 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#define WRAPPER __declspec(naked)
|
|
|
|
#define DEPRECATED __declspec(deprecated)
|
|
|
|
#define EAXJMP(a) { _asm mov eax, a _asm jmp eax }
|
|
|
|
#define VARJMP(a) { _asm jmp a }
|
|
|
|
#define WRAPARG(a) UNREFERENCED_PARAMETER(a)
|
|
|
|
|
2020-03-27 19:53:47 +00:00
|
|
|
#include <string.h> //memset
|
2019-07-02 18:28:20 +00:00
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PATCH_CALL,
|
|
|
|
PATCH_JUMP,
|
|
|
|
PATCH_NOTHING,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
III_10 = 1,
|
|
|
|
III_11,
|
|
|
|
III_STEAM,
|
|
|
|
VC_10,
|
|
|
|
VC_11,
|
|
|
|
VC_STEAM
|
|
|
|
};
|
|
|
|
|
|
|
|
extern int gtaversion;
|
|
|
|
|
2019-07-02 18:28:20 +00:00
|
|
|
class StaticPatcher
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
using Patcher = void(*)();
|
|
|
|
|
|
|
|
Patcher m_func;
|
|
|
|
StaticPatcher *m_next;
|
|
|
|
static StaticPatcher *ms_head;
|
|
|
|
|
|
|
|
void Run() { m_func(); }
|
|
|
|
public:
|
|
|
|
StaticPatcher(Patcher func);
|
|
|
|
static void Apply();
|
|
|
|
};
|
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
template<typename T>
|
|
|
|
inline T AddressByVersion(uint32_t addressIII10, uint32_t addressIII11, uint32_t addressIIISteam, uint32_t addressvc10, uint32_t addressvc11, uint32_t addressvcSteam)
|
|
|
|
{
|
|
|
|
if(gtaversion == -1){
|
|
|
|
if(*(uint32_t*)0x5C1E75 == 0xB85548EC) gtaversion = III_10;
|
|
|
|
else if(*(uint32_t*)0x5C2135 == 0xB85548EC) gtaversion = III_11;
|
|
|
|
else if(*(uint32_t*)0x5C6FD5 == 0xB85548EC) gtaversion = III_STEAM;
|
|
|
|
else if(*(uint32_t*)0x667BF5 == 0xB85548EC) gtaversion = VC_10;
|
|
|
|
else if(*(uint32_t*)0x667C45 == 0xB85548EC) gtaversion = VC_11;
|
|
|
|
else if(*(uint32_t*)0x666BA5 == 0xB85548EC) gtaversion = VC_STEAM;
|
|
|
|
else gtaversion = 0;
|
|
|
|
}
|
|
|
|
switch(gtaversion){
|
|
|
|
case III_10:
|
|
|
|
return (T)addressIII10;
|
|
|
|
case III_11:
|
|
|
|
return (T)addressIII11;
|
|
|
|
case III_STEAM:
|
|
|
|
return (T)addressIIISteam;
|
|
|
|
case VC_10:
|
|
|
|
return (T)addressvc10;
|
|
|
|
case VC_11:
|
|
|
|
return (T)addressvc11;
|
|
|
|
case VC_STEAM:
|
|
|
|
return (T)addressvcSteam;
|
|
|
|
default:
|
|
|
|
return (T)0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
is10(void)
|
|
|
|
{
|
|
|
|
return gtaversion == III_10 || gtaversion == VC_10;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isIII(void)
|
|
|
|
{
|
|
|
|
return gtaversion >= III_10 && gtaversion <= III_STEAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
isVC(void)
|
|
|
|
{
|
|
|
|
return gtaversion >= VC_10 && gtaversion <= VC_STEAM;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define PTRFROMCALL(addr) (uint32_t)(*(uint32_t*)((uint32_t)addr+1) + (uint32_t)addr + 5)
|
|
|
|
#define INTERCEPT(saved, func, a) \
|
|
|
|
{ \
|
|
|
|
saved = PTRFROMCALL(a); \
|
|
|
|
InjectHook(a, func); \
|
|
|
|
}
|
|
|
|
|
2020-03-27 19:53:47 +00:00
|
|
|
void InjectHook_internal(uint32 address, uint32 hook, int type);
|
|
|
|
void Protect_internal(uint32 address, uint32 size);
|
|
|
|
void Unprotect_internal(void);
|
|
|
|
|
2019-05-15 14:52:37 +00:00
|
|
|
template<typename T, typename AT> inline void
|
|
|
|
Patch(AT address, T value)
|
|
|
|
{
|
2020-03-27 19:53:47 +00:00
|
|
|
Protect_internal((uint32)address, sizeof(T));
|
2019-05-15 14:52:37 +00:00
|
|
|
*(T*)address = value;
|
2020-03-27 19:53:47 +00:00
|
|
|
Unprotect_internal();
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename AT> inline void
|
|
|
|
Nop(AT address, unsigned int nCount)
|
|
|
|
{
|
2020-03-27 19:53:47 +00:00
|
|
|
Protect_internal((uint32)address, nCount);
|
2019-05-15 14:52:37 +00:00
|
|
|
memset((void*)address, 0x90, nCount);
|
2020-03-27 19:53:47 +00:00
|
|
|
Unprotect_internal();
|
2019-06-21 15:28:55 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 20:20:28 +00:00
|
|
|
template <typename T> inline void
|
|
|
|
InjectHook(uintptr_t address, T hook, unsigned int nType = PATCH_NOTHING)
|
2019-05-15 14:52:37 +00:00
|
|
|
{
|
2020-03-27 20:20:28 +00:00
|
|
|
InjectHook_internal(address, reinterpret_cast<uintptr_t>((void *&)hook), nType);
|
2019-05-15 14:52:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void ExtractCall(void *dst, uint32_t a)
|
|
|
|
{
|
|
|
|
*(uint32_t*)dst = (uint32_t)(*(uint32_t*)(a+1) + a + 5);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
inline void InterceptCall(void *dst, T func, uint32_t a)
|
|
|
|
{
|
|
|
|
ExtractCall(dst, a);
|
|
|
|
InjectHook(a, func);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
inline void InterceptVmethod(void *dst, T func, uint32_t a)
|
|
|
|
{
|
|
|
|
*(uint32_t*)dst = *(uint32_t*)a;
|
|
|
|
Patch(a, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STARTPATCHES static StaticPatcher Patcher([](){
|
|
|
|
#define ENDPATCHES });
|