Added a new ValveCallType that allows for arbitrary |this| parameters, as well as associated features in gamedata and for reading/writing memory (bug 3520, r=dvander, sr=fyren).
This commit is contained in:
parent
ead6ca73e5
commit
18865c44c8
@ -63,6 +63,9 @@ static char g_GameName[256] = {'$', '\0'};
|
|||||||
#define PSTATE_GAMEDEFS_CRC 9
|
#define PSTATE_GAMEDEFS_CRC 9
|
||||||
#define PSTATE_GAMEDEFS_CRC_BINARY 10
|
#define PSTATE_GAMEDEFS_CRC_BINARY 10
|
||||||
#define PSTATE_GAMEDEFS_CUSTOM 11
|
#define PSTATE_GAMEDEFS_CUSTOM 11
|
||||||
|
#define PSTATE_GAMEDEFS_ADDRESSES 12
|
||||||
|
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS 13
|
||||||
|
#define PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ 14
|
||||||
|
|
||||||
#if defined PLATFORM_WINDOWS
|
#if defined PLATFORM_WINDOWS
|
||||||
#define PLATFORM_NAME "windows"
|
#define PLATFORM_NAME "windows"
|
||||||
@ -132,6 +135,7 @@ CGameConfig::CGameConfig(const char *file)
|
|||||||
m_pOffsets = sm_trie_create();
|
m_pOffsets = sm_trie_create();
|
||||||
m_pProps = sm_trie_create();
|
m_pProps = sm_trie_create();
|
||||||
m_pKeys = sm_trie_create();
|
m_pKeys = sm_trie_create();
|
||||||
|
m_pAddresses = new KTrie<AddressConf>();
|
||||||
m_pSigs = sm_trie_create();
|
m_pSigs = sm_trie_create();
|
||||||
m_pStrings = new BaseStringTable(512);
|
m_pStrings = new BaseStringTable(512);
|
||||||
m_RefCount = 0;
|
m_RefCount = 0;
|
||||||
@ -145,6 +149,7 @@ CGameConfig::~CGameConfig()
|
|||||||
sm_trie_destroy(m_pOffsets);
|
sm_trie_destroy(m_pOffsets);
|
||||||
sm_trie_destroy(m_pProps);
|
sm_trie_destroy(m_pProps);
|
||||||
sm_trie_destroy(m_pKeys);
|
sm_trie_destroy(m_pKeys);
|
||||||
|
delete m_pAddresses;
|
||||||
sm_trie_destroy(m_pSigs);
|
sm_trie_destroy(m_pSigs);
|
||||||
delete m_pStrings;
|
delete m_pStrings;
|
||||||
}
|
}
|
||||||
@ -212,6 +217,10 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
m_ParseState = PSTATE_GAMEDEFS_CRC;
|
m_ParseState = PSTATE_GAMEDEFS_CRC;
|
||||||
bShouldBeReadingDefault = false;
|
bShouldBeReadingDefault = false;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(name, "Addresses") == 0)
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name);
|
ITextListener_SMC **pListen = g_GameConfigs.m_customHandlers.retrieve(name);
|
||||||
@ -293,12 +302,41 @@ SMCResult CGameConfig::ReadSMC_NewSection(const SMCStates *states, const char *n
|
|||||||
return m_CustomHandler->ReadSMC_NewSection(states, name);
|
return m_CustomHandler->ReadSMC_NewSection(states, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES:
|
||||||
|
{
|
||||||
|
m_Address[0] = '\0';
|
||||||
|
m_AddressSignature[0] = '\0';
|
||||||
|
m_AddressReadCount = 0;
|
||||||
|
|
||||||
|
strncopy(m_Address, name, sizeof(m_Address));
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
|
||||||
|
{
|
||||||
|
if (strcmp(name, PLATFORM_NAME) == 0)
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strcmp(name, "linux") != 0 && strcmp(name, "windows") != 0)
|
||||||
|
{
|
||||||
|
g_Logger.LogError("[SM] Error while parsing Address section for \"%s\" (%s):", m_Address, m_CurFile);
|
||||||
|
g_Logger.LogError("[SM] Unrecognized platform \"%s\"", name);
|
||||||
|
}
|
||||||
|
m_IgnoreLevel = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* No sub-sections allowed:
|
/* No sub-sections allowed:
|
||||||
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
case PSTATE_GAMEDEFS_OFFSETS_OFFSET:
|
||||||
case PSTATE_GAMEDEFS_KEYS:
|
case PSTATE_GAMEDEFS_KEYS:
|
||||||
case PSTATE_GAMEDEFS_SUPPORTED:
|
case PSTATE_GAMEDEFS_SUPPORTED:
|
||||||
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
case PSTATE_GAMEDEFS_SIGNATURES_SIG:
|
||||||
case PSTATE_GAMEDEFS_CRC_BINARY:
|
case PSTATE_GAMEDEFS_CRC_BINARY:
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ:
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -376,6 +414,21 @@ SMCResult CGameConfig::ReadSMC_KeyValue(const SMCStates *states, const char *key
|
|||||||
bShouldBeReadingDefault = true;
|
bShouldBeReadingDefault = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS || m_ParseState == PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ) {
|
||||||
|
if (strcmp(key, "read") == 0) {
|
||||||
|
int limit = sizeof(m_AddressRead)/sizeof(m_AddressRead[0]);
|
||||||
|
if (m_AddressReadCount < limit)
|
||||||
|
{
|
||||||
|
m_AddressRead[m_AddressReadCount] = atoi(value);
|
||||||
|
m_AddressReadCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_Logger.LogError("[SM] Error parsing Address \"%s\", does not support more than %d read offsets (gameconf \"%s\")", m_Address, limit, m_CurFile);
|
||||||
|
}
|
||||||
|
} else if (strcmp(key, "signature") == 0) {
|
||||||
|
strncopy(m_AddressSignature, value, sizeof(m_AddressSignature));
|
||||||
|
}
|
||||||
} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
|
} else if (m_ParseState == PSTATE_GAMEDEFS_CUSTOM) {
|
||||||
return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
|
return m_CustomHandler->ReadSMC_KeyValue(states, key, value);
|
||||||
}
|
}
|
||||||
@ -548,6 +601,36 @@ skip_find:
|
|||||||
sm_trie_replace(m_pSigs, m_offset, final_addr);
|
sm_trie_replace(m_pSigs, m_offset, final_addr);
|
||||||
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
|
m_ParseState = PSTATE_GAMEDEFS_SIGNATURES;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES:
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS:
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES;
|
||||||
|
|
||||||
|
if (m_Address[0] == '\0')
|
||||||
|
{
|
||||||
|
g_Logger.LogError("[SM] Address sections must have names (gameconf \"%s\")", m_CurFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (m_AddressSignature[0] == '\0')
|
||||||
|
{
|
||||||
|
g_Logger.LogError("[SM] Address section for \"%s\" did not specify a signature (gameconf \"%s\")", m_Address, m_CurFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressConf addrConf(m_AddressSignature, sizeof(m_AddressSignature), m_AddressReadCount, m_AddressRead);
|
||||||
|
m_pAddresses->replace(m_Address, addrConf);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PSTATE_GAMEDEFS_ADDRESSES_ADDRESS_READ:
|
||||||
|
{
|
||||||
|
m_ParseState = PSTATE_GAMEDEFS_ADDRESSES_ADDRESS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,6 +772,7 @@ bool CGameConfig::Reparse(char *error, size_t maxlength)
|
|||||||
sm_trie_clear(m_pOffsets);
|
sm_trie_clear(m_pOffsets);
|
||||||
sm_trie_clear(m_pProps);
|
sm_trie_clear(m_pProps);
|
||||||
sm_trie_clear(m_pKeys);
|
sm_trie_clear(m_pKeys);
|
||||||
|
m_pAddresses->clear();
|
||||||
|
|
||||||
char path[PLATFORM_MAX_PATH];
|
char path[PLATFORM_MAX_PATH];
|
||||||
|
|
||||||
@ -837,6 +921,53 @@ const char *CGameConfig::GetKeyValue(const char *key)
|
|||||||
return m_pStrings->GetString((int)obj);
|
return m_pStrings->GetString((int)obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
|
||||||
|
#define VALID_MINIMUM_MEMORY_ADDRESS 0x10000
|
||||||
|
|
||||||
|
bool CGameConfig::GetAddress(const char *key, void **retaddr)
|
||||||
|
{
|
||||||
|
AddressConf *addrConf;
|
||||||
|
|
||||||
|
addrConf = m_pAddresses->retrieve(key);
|
||||||
|
if (!addrConf)
|
||||||
|
{
|
||||||
|
*retaddr = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *addr;
|
||||||
|
if (!GetMemSig(addrConf->signatureName, &addr))
|
||||||
|
{
|
||||||
|
*retaddr = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < addrConf->readCount; ++i)
|
||||||
|
{
|
||||||
|
int offset = addrConf->read[i];
|
||||||
|
|
||||||
|
//NULLs in the middle of an indirection chain are bad, end NULL is ok
|
||||||
|
if (addr == NULL || reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
*retaddr = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addr = *(reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(addr) + offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
*retaddr = addr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGameConfig::AddressConf::AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read)
|
||||||
|
{
|
||||||
|
unsigned readLimit = min(readCount, sizeof(this->read) / sizeof(this->read[0]));
|
||||||
|
|
||||||
|
strncopy(signatureName, sigName, sizeof(signatureName) / sizeof(signatureName[0]));
|
||||||
|
this->readCount = readLimit;
|
||||||
|
memcpy(&this->read[0], read, sizeof(this->read[0])*readLimit);
|
||||||
|
}
|
||||||
|
|
||||||
SendProp *CGameConfig::GetSendProp(const char *key)
|
SendProp *CGameConfig::GetSendProp(const char *key)
|
||||||
{
|
{
|
||||||
SendProp *pProp;
|
SendProp *pProp;
|
||||||
|
@ -65,6 +65,7 @@ public: //IGameConfig
|
|||||||
bool GetOffset(const char *key, int *value);
|
bool GetOffset(const char *key, int *value);
|
||||||
SendProp *GetSendProp(const char *key);
|
SendProp *GetSendProp(const char *key);
|
||||||
bool GetMemSig(const char *key, void **addr);
|
bool GetMemSig(const char *key, void **addr);
|
||||||
|
bool GetAddress(const char *key, void **addr);
|
||||||
public:
|
public:
|
||||||
void IncRefCount();
|
void IncRefCount();
|
||||||
unsigned int DecRefCount();
|
unsigned int DecRefCount();
|
||||||
@ -93,6 +94,24 @@ private:
|
|||||||
/* Custom Sections */
|
/* Custom Sections */
|
||||||
unsigned int m_CustomLevel;
|
unsigned int m_CustomLevel;
|
||||||
ITextListener_SMC *m_CustomHandler;
|
ITextListener_SMC *m_CustomHandler;
|
||||||
|
|
||||||
|
/* Support for reading Addresses */
|
||||||
|
struct AddressConf
|
||||||
|
{
|
||||||
|
char signatureName[64];
|
||||||
|
int readCount;
|
||||||
|
int read[8];
|
||||||
|
|
||||||
|
AddressConf(char *sigName, unsigned sigLength, unsigned readCount, int *read);
|
||||||
|
|
||||||
|
AddressConf() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
char m_Address[64];
|
||||||
|
char m_AddressSignature[64];
|
||||||
|
int m_AddressReadCount;
|
||||||
|
int m_AddressRead[8];
|
||||||
|
KTrie<AddressConf> *m_pAddresses;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameConfigManager :
|
class GameConfigManager :
|
||||||
|
@ -673,6 +673,77 @@ static cell_t RequireFeature(IPluginContext *pContext, const cell_t *params)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum NumberType
|
||||||
|
{
|
||||||
|
NumberType_Int8,
|
||||||
|
NumberType_Int16,
|
||||||
|
NumberType_Int32
|
||||||
|
};
|
||||||
|
|
||||||
|
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
|
||||||
|
#define VALID_MINIMUM_MEMORY_ADDRESS 0x10000
|
||||||
|
|
||||||
|
static cell_t LoadFromAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
|
|
||||||
|
if (addr == NULL)
|
||||||
|
{
|
||||||
|
pContext->ThrowNativeError("Address cannot be null");
|
||||||
|
}
|
||||||
|
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
|
||||||
|
}
|
||||||
|
NumberType size = static_cast<NumberType>(params[2]);
|
||||||
|
|
||||||
|
switch(size)
|
||||||
|
{
|
||||||
|
case NumberType_Int8:
|
||||||
|
return *reinterpret_cast<uint8_t*>(addr);
|
||||||
|
case NumberType_Int16:
|
||||||
|
return *reinterpret_cast<uint16_t*>(addr);
|
||||||
|
case NumberType_Int32:
|
||||||
|
return *reinterpret_cast<uint32_t*>(addr);
|
||||||
|
default:
|
||||||
|
pContext->ThrowNativeError("Invalid number types %d", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static cell_t StoreToAddress(IPluginContext *pContext, const cell_t *params)
|
||||||
|
{
|
||||||
|
void *addr = reinterpret_cast<void*>(params[1]);
|
||||||
|
|
||||||
|
if (addr == NULL)
|
||||||
|
{
|
||||||
|
pContext->ThrowNativeError("Address cannot be null");
|
||||||
|
}
|
||||||
|
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
|
||||||
|
{
|
||||||
|
pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
|
||||||
|
}
|
||||||
|
cell_t data = params[2];
|
||||||
|
|
||||||
|
NumberType size = static_cast<NumberType>(params[3]);
|
||||||
|
|
||||||
|
switch(size)
|
||||||
|
{
|
||||||
|
case NumberType_Int8:
|
||||||
|
*reinterpret_cast<uint8_t*>(addr) = data;
|
||||||
|
case NumberType_Int16:
|
||||||
|
*reinterpret_cast<uint16_t*>(addr) = data;
|
||||||
|
case NumberType_Int32:
|
||||||
|
*reinterpret_cast<uint32_t*>(addr) = data;
|
||||||
|
default:
|
||||||
|
pContext->ThrowNativeError("Invalid number types %d", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
REGISTER_NATIVES(coreNatives)
|
REGISTER_NATIVES(coreNatives)
|
||||||
{
|
{
|
||||||
{"AutoExecConfig", AutoExecConfig},
|
{"AutoExecConfig", AutoExecConfig},
|
||||||
@ -699,6 +770,8 @@ REGISTER_NATIVES(coreNatives)
|
|||||||
{"VerifyCoreVersion", VerifyCoreVersion},
|
{"VerifyCoreVersion", VerifyCoreVersion},
|
||||||
{"GetFeatureStatus", GetFeatureStatus},
|
{"GetFeatureStatus", GetFeatureStatus},
|
||||||
{"RequireFeature", RequireFeature},
|
{"RequireFeature", RequireFeature},
|
||||||
|
{"LoadFromAddress", LoadFromAddress},
|
||||||
|
{"StoreToAddress", StoreToAddress},
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,6 +128,35 @@ static cell_t smn_GameConfGetKeyValue(IPluginContext *pCtx, const cell_t *params
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static cell_t smn_GameConfGetAddress(IPluginContext *pCtx, const cell_t *params)
|
||||||
|
{
|
||||||
|
Handle_t hndl = static_cast<Handle_t>(params[1]);
|
||||||
|
HandleError herr;
|
||||||
|
HandleSecurity sec;
|
||||||
|
IGameConfig *gc;
|
||||||
|
|
||||||
|
sec.pOwner = NULL;
|
||||||
|
sec.pIdentity = g_pCoreIdent;
|
||||||
|
|
||||||
|
if ((herr=g_HandleSys.ReadHandle(hndl, g_GameConfigsType, &sec, (void **)&gc))
|
||||||
|
!= HandleError_None)
|
||||||
|
{
|
||||||
|
return pCtx->ThrowNativeError("Invalid game config handle %x (error %d)", hndl, herr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *key;
|
||||||
|
void* val;
|
||||||
|
pCtx->LocalToString(params[2], &key);
|
||||||
|
|
||||||
|
if (!gc->GetAddress(key, &val))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (cell_t)val;
|
||||||
|
}
|
||||||
|
|
||||||
static GameConfigsNatives s_GameConfigsNatives;
|
static GameConfigsNatives s_GameConfigsNatives;
|
||||||
|
|
||||||
REGISTER_NATIVES(gameconfignatives)
|
REGISTER_NATIVES(gameconfignatives)
|
||||||
@ -135,5 +164,6 @@ REGISTER_NATIVES(gameconfignatives)
|
|||||||
{"LoadGameConfigFile", smn_LoadGameConfigFile},
|
{"LoadGameConfigFile", smn_LoadGameConfigFile},
|
||||||
{"GameConfGetOffset", smn_GameConfGetOffset},
|
{"GameConfGetOffset", smn_GameConfGetOffset},
|
||||||
{"GameConfGetKeyValue", smn_GameConfGetKeyValue},
|
{"GameConfGetKeyValue", smn_GameConfGetKeyValue},
|
||||||
|
{"GameConfGetAddress", smn_GameConfGetAddress},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
@ -250,7 +250,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
|||||||
|
|
||||||
unsigned char *ptr = vc->stk_get();
|
unsigned char *ptr = vc->stk_get();
|
||||||
|
|
||||||
unsigned int numparams = (unsigned)params[0];
|
const unsigned int numparams = (unsigned)params[0];
|
||||||
unsigned int startparam = 2;
|
unsigned int startparam = 2;
|
||||||
/* Do we need to write a thispointer? */
|
/* Do we need to write a thispointer? */
|
||||||
|
|
||||||
@ -308,6 +308,25 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
|||||||
*(void **)ptr = g_EntList;
|
*(void **)ptr = g_EntList;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ValveCall_Raw:
|
||||||
|
{
|
||||||
|
//params[startparam] is an address to a pointer to THIS
|
||||||
|
//params following this are params to the method we will invoke later
|
||||||
|
if (startparam > numparams)
|
||||||
|
{
|
||||||
|
vc->stk_put(ptr);
|
||||||
|
return pContext->ThrowNativeError("Expected a ThisPtr address, it wasn't found");
|
||||||
|
}
|
||||||
|
|
||||||
|
//note: varargs pawn args are passed by-ref
|
||||||
|
cell_t *cell;
|
||||||
|
pContext->LocalToPhysAddr(params[startparam], &cell);
|
||||||
|
void *thisptr = reinterpret_cast<void*>(*cell);
|
||||||
|
|
||||||
|
*(void **)ptr = thisptr;
|
||||||
|
startparam++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ enum ValveCallType
|
|||||||
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
|
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
|
||||||
ValveCall_GameRules, /**< Thiscall (CGameRules implicit first paramater) */
|
ValveCall_GameRules, /**< Thiscall (CGameRules implicit first paramater) */
|
||||||
ValveCall_EntityList, /**< Thiscall (CGlobalEntityList implicit first paramater) */
|
ValveCall_EntityList, /**< Thiscall (CGlobalEntityList implicit first paramater) */
|
||||||
|
ValveCall_Raw, /**< Thiscall (address explicit first parameter) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,6 +57,7 @@ enum SDKCallType
|
|||||||
SDKCall_Player, /**< CBasePlayer call */
|
SDKCall_Player, /**< CBasePlayer call */
|
||||||
SDKCall_GameRules, /**< CGameRules call */
|
SDKCall_GameRules, /**< CGameRules call */
|
||||||
SDKCall_EntityList, /**< CGlobalEntityList call */
|
SDKCall_EntityList, /**< CGlobalEntityList call */
|
||||||
|
SDKCall_Raw, /**< Raw Address call */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SDKLibrary
|
enum SDKLibrary
|
||||||
|
@ -386,6 +386,16 @@ native GameConfGetOffset(Handle:gc, const String:key[]);
|
|||||||
*/
|
*/
|
||||||
native bool:GameConfGetKeyValue(Handle:gc, const String:key[], String:buffer[], maxlen);
|
native bool:GameConfGetKeyValue(Handle:gc, const String:key[], String:buffer[], maxlen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds an address calculation in a GameConfig file,
|
||||||
|
* performs LoadFromAddress on it as appropriate, then returns the final address.
|
||||||
|
*
|
||||||
|
* @param gameconf GameConfig Handle, or INVALID_HANDLE to use sdktools.games.txt.
|
||||||
|
* @param name Name of the property to find.
|
||||||
|
* @return An address calculated on success, or 0 on failure.
|
||||||
|
*/
|
||||||
|
native Address:GameConfGetAddress(Handle:gameconf, const String:name[]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the operating system's "tick count," which is a number of
|
* Returns the operating system's "tick count," which is a number of
|
||||||
* milliseconds since the operating system loaded. This can be used
|
* milliseconds since the operating system loaded. This can be used
|
||||||
@ -630,6 +640,41 @@ native FeatureStatus:GetFeatureStatus(FeatureType:type, const String:name[]);
|
|||||||
native RequireFeature(FeatureType:type, const String:name[],
|
native RequireFeature(FeatureType:type, const String:name[],
|
||||||
const String:fmt[]="", any:...);
|
const String:fmt[]="", any:...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents how many bytes we can read from an address with one load
|
||||||
|
*/
|
||||||
|
enum NumberType
|
||||||
|
{
|
||||||
|
NumberType_Int8,
|
||||||
|
NumberType_Int16,
|
||||||
|
NumberType_Int32
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Address
|
||||||
|
{
|
||||||
|
Address_Null = 0, //a typical invalid result when an address lookup fails
|
||||||
|
Address_MinimumValid = 0x10000 //addresses below this value are considered invalid to use for Load/Store
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load up to 4 bytes from a memory address.
|
||||||
|
*
|
||||||
|
* @param addr Address to a memory location.
|
||||||
|
* @param size How many bytes should be read.
|
||||||
|
* @return The value that is stored at that address.
|
||||||
|
*/
|
||||||
|
native LoadFromAddress(Address:addr, NumberType:size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store up to 4 bytes to a memory address.
|
||||||
|
*
|
||||||
|
* @param addr Address to a memory location.
|
||||||
|
* @param data Value to store at the address.
|
||||||
|
* @param size How many bytes should be written.
|
||||||
|
* @noreturn
|
||||||
|
*/
|
||||||
|
native StoreToAddress(Address:addr, data, NumberType:size);
|
||||||
|
|
||||||
#include <helpers>
|
#include <helpers>
|
||||||
#include <entity>
|
#include <entity>
|
||||||
#include <entity_prop_stocks>
|
#include <entity_prop_stocks>
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define SMINTERFACE_GAMECONFIG_NAME "IGameConfigManager"
|
#define SMINTERFACE_GAMECONFIG_NAME "IGameConfigManager"
|
||||||
#define SMINTERFACE_GAMECONFIG_VERSION 5
|
#define SMINTERFACE_GAMECONFIG_VERSION 6
|
||||||
|
|
||||||
class SendProp;
|
class SendProp;
|
||||||
|
|
||||||
@ -89,6 +89,15 @@ namespace SourceMod
|
|||||||
* address is NULL.
|
* address is NULL.
|
||||||
*/
|
*/
|
||||||
virtual bool GetMemSig(const char *key, void **addr) =0;
|
virtual bool GetMemSig(const char *key, void **addr) =0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the value of an address from the "Address" section.
|
||||||
|
*
|
||||||
|
* @param key Key to retrieve from the Address section.
|
||||||
|
* @param addr Pointer to store the memory address.
|
||||||
|
* @return True on success, false on failure.
|
||||||
|
*/
|
||||||
|
virtual bool GetAddress(const char *key, void **addr) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user