added by-address calling

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40959
This commit is contained in:
David Anderson 2007-06-16 15:40:22 +00:00
parent 2617bdae50
commit 6c64c00f6b
4 changed files with 132 additions and 5 deletions

View File

@ -32,6 +32,125 @@ void ValveCall::stk_put(unsigned char *ptr)
stk.push(ptr);
}
ValveCall *CreateValveCall(void *addr,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams)
{
if (numParams > 32)
{
return NULL;
}
ValveCall *vc = new ValveCall;
size_t size = 0;
vc->stackSize = 0;
/* Get return information - encode only*/
PassInfo retBuf;
size_t retBufSize = 0;
if (retInfo)
{
if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf)) == 0)
{
delete vc;
return NULL;
}
retBufSize = size;
}
/* Get thisinfo if needed */
ValvePassInfo thisbuf;
ValvePassInfo *thisinfo = NULL;
CallConvention cv = CallConv_Cdecl;
if (vcalltype != ValveCall_Static)
{
thisinfo = &thisbuf;
thisinfo->type = PassType_Basic;
if (vcalltype == ValveCall_Entity)
{
thisinfo->vtype = Valve_CBaseEntity;
thisinfo->decflags |= VDECODE_FLAG_ALLOWWORLD;
} else if (vcalltype == ValveCall_Player) {
thisinfo->vtype = Valve_CBasePlayer;
thisinfo->decflags = 0;
}
thisinfo->encflags = 0;
thisinfo->flags = PASSFLAG_BYVAL;
thisinfo->offset = 0;
vc->stackSize += sizeof(void *);
cv = CallConv_ThisCall;
}
/* Get parameter info */
PassInfo paramBuf[32];
for (unsigned int i=0; i<numParams; i++)
{
if ((size = ValveParamToBinParam(params[i].vtype, params[i].type, params[i].flags, &paramBuf[i])) == 0)
{
delete vc;
return NULL;
}
vc->stackSize += size;
}
/* Now we can try creating the call */
if ((vc->call = g_pBinTools->CreateCall(addr,
cv,
(retInfo ? &retBuf : NULL),
paramBuf,
numParams))
== NULL)
{
if (!vc->call)
{
delete vc;
return NULL;
}
}
/* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
vc->vparams = new ValvePassInfo[numParams + 2];
/* We've got the call and everything is encoded.
* It's time to save the valve specific information and helper variables.
*/
if (retInfo)
{
/* Allocate and copy */
vc->retinfo = &(vc->vparams[numParams]);
*vc->retinfo = *retInfo;
vc->retinfo->offset = 0;
/* Allocate stack space */
vc->retbuf = new unsigned char[retBufSize];
} else {
vc->retinfo = NULL;
vc->retbuf = NULL;
}
if (thisinfo)
{
/* Allocate and copy */
vc->thisinfo = &(vc->vparams[numParams + 1]);
*vc->thisinfo = *thisinfo;
vc->thisinfo->offset = 0;
} else {
vc->thisinfo = NULL;
}
/* Now, save info about each parameter. */
for (unsigned int i=0; i<numParams; i++)
{
/* Copy */
vc->vparams[i] = params[i];
vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
}
return vc;
}
ValveCall *CreateValveVCall(unsigned int vtableIdx,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,

View File

@ -55,4 +55,10 @@ ValveCall *CreateValveVCall(unsigned int vtableIdx,
const ValvePassInfo *params,
unsigned int numParams);
ValveCall *CreateValveCall(void *addr,
ValveCallType vcalltype,
const ValvePassInfo *retInfo,
const ValvePassInfo *params,
unsigned int numParams);
#endif //_INCLUDE_SOURCEMOD_VALVE_CALLER_H_

View File

@ -181,6 +181,8 @@ static cell_t EndPrepSDKCall(IPluginContext *pContext, const cell_t *params)
if (s_vtbl_index)
{
vc = CreateValveVCall(s_vtbl_index, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
} else if (s_call_addr) {
vc = CreateValveCall(s_call_addr, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
}
if (!vc)

View File

@ -255,8 +255,8 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
if (type == PassType_Basic)
{
/* Store the object in the next N bytes, and store
* a pointer to that object right beforehand.
*/
* a pointer to that object right beforehand.
*/
QAngle **realPtr = (QAngle **)buffer;
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
@ -282,9 +282,9 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
}
/* Use placement new to initialize the object cleanly
* This has no destructor so we don't need to do
* DestroyValveParam() or something :]
*/
* This has no destructor so we don't need to do
* DestroyValveParam() or something :]
*/
QAngle *v = new (mem) QAngle(
sp_ctof(addr[0]),
sp_ctof(addr[1]),