From 6c64c00f6b4e3be5f0cf21ef411cea0775b32627 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 16 Jun 2007 15:40:22 +0000 Subject: [PATCH] added by-address calling --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40959 --- extensions/sdktools/vcallbuilder.cpp | 119 +++++++++++++++++++++++++++ extensions/sdktools/vcallbuilder.h | 6 ++ extensions/sdktools/vcaller.cpp | 2 + extensions/sdktools/vdecoder.cpp | 10 +-- 4 files changed, 132 insertions(+), 5 deletions(-) diff --git a/extensions/sdktools/vcallbuilder.cpp b/extensions/sdktools/vcallbuilder.cpp index f6d5a79c..fbaadd9b 100644 --- a/extensions/sdktools/vcallbuilder.cpp +++ b/extensions/sdktools/vcallbuilder.cpp @@ -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; istackSize += 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; ivparams[i] = params[i]; + vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset; + } + + return vc; +} + ValveCall *CreateValveVCall(unsigned int vtableIdx, ValveCallType vcalltype, const ValvePassInfo *retInfo, diff --git a/extensions/sdktools/vcallbuilder.h b/extensions/sdktools/vcallbuilder.h index ee728bd4..e12d4a6b 100644 --- a/extensions/sdktools/vcallbuilder.h +++ b/extensions/sdktools/vcallbuilder.h @@ -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_ diff --git a/extensions/sdktools/vcaller.cpp b/extensions/sdktools/vcaller.cpp index 70583aae..a3b26b63 100644 --- a/extensions/sdktools/vcaller.cpp +++ b/extensions/sdktools/vcaller.cpp @@ -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) diff --git a/extensions/sdktools/vdecoder.cpp b/extensions/sdktools/vdecoder.cpp index 4c95b06c..4764a206 100644 --- a/extensions/sdktools/vdecoder.cpp +++ b/extensions/sdktools/vdecoder.cpp @@ -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]),