3 * =============================================================================
4 * SourceMod SDKTools Extension
5 * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 * =============================================================================
8 * This program is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, version 3.0, as published by the
10 * Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
20 * As a special exception, AlliedModders LLC gives you permission to link the
21 * code of this program (as well as its derivative works) to "Half-Life 2," the
22 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 * by the Valve Corporation. You must obey the GNU General Public License in
24 * all respects for all other code used. Additionally, AlliedModders LLC grants
25 * this exception to all derivative works. AlliedModders LLC defines further
26 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 * or <http://www.sourcemod.net/license.php>.
32 #include "vcallbuilder.h"
33 #include "extension.h"
35 ValveCall::ValveCall()
44 ValveCall::~ValveCall()
48 unsigned char *ptr = stk.front();
60 unsigned char *ValveCall::stk_get()
65 ptr = new unsigned char[stackSize];
73 void ValveCall::stk_put(unsigned char *ptr)
78 ValveCall *CreateValveCall(void *addr,
79 ValveCallType vcalltype,
80 const ValvePassInfo *retInfo,
81 const ValvePassInfo *params,
82 unsigned int numParams)
89 ValveCall *vc = new ValveCall;
96 /* Get return information - encode only */
98 size_t retBufSize = 0;
99 bool retbuf_needs_extra;
102 if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
107 retBufSize = retBuf.size;
110 /* Get parameter info */
111 PassInfo paramBuf[32];
114 size_t extraSize = 0;
115 for (unsigned int i=0; i<numParams; i++)
118 if ((size = ValveParamToBinParam(params[i].vtype,
133 normSize += paramBuf[i].size;
134 extraSize += sizes[i];
138 /* Get thisinfo if needed */
139 ValvePassInfo thisbuf;
140 ValvePassInfo *thisinfo = NULL;
141 CallConvention cv = CallConv_Cdecl;
142 if (vcalltype != ValveCall_Static)
145 thisinfo->type = PassType_Basic;
148 case ValveCall_Entity:
149 thisinfo->vtype = Valve_CBaseEntity;
150 thisinfo->flags = PASSFLAG_BYVAL;
151 thisinfo->decflags |= VDECODE_FLAG_ALLOWWORLD;
153 case ValveCall_Player:
154 thisinfo->vtype = Valve_CBasePlayer;
155 thisinfo->flags = PASSFLAG_BYVAL;
156 thisinfo->decflags = 0;
159 thisinfo->vtype = Valve_POD;
160 thisinfo->flags = PASSFLAG_ASPOINTER;
161 thisinfo->decflags = 0;
164 thisinfo->encflags = 0;
165 thisinfo->offset = 0;
166 normSize += sizeof(void *);
167 cv = CallConv_ThisCall;
170 /* Now we can try creating the call */
171 if ((vc->call = g_pBinTools->CreateCall(addr,
173 (retInfo ? &retBuf : NULL),
185 /* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
186 vc->vparams = new ValvePassInfo[numParams + 2];
188 /* We've got the call and everything is encoded.
189 * It's time to save the valve specific information and helper variables.
193 /* Allocate and copy */
194 vc->retinfo = &(vc->vparams[numParams]);
195 *vc->retinfo = *retInfo;
196 vc->retinfo->offset = 0;
197 vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
198 /* Allocate stack space */
199 vc->retbuf = new unsigned char[retBufSize];
207 /* Allocate and copy */
208 vc->thisinfo = &(vc->vparams[numParams + 1]);
209 *vc->thisinfo = *thisinfo;
210 vc->thisinfo->offset = 0;
211 vc->thisinfo->obj_offset = 0;
216 /* Now, save info about each parameter. */
217 size_t last_extra_offset = 0;
218 for (unsigned int i=0; i<numParams; i++)
221 vc->vparams[i] = params[i];
222 vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
223 vc->vparams[i].obj_offset = last_extra_offset;
224 last_extra_offset += sizes[i];
227 vc->stackSize = normSize + extraSize;
228 vc->stackEnd = normSize;
233 ValveCall *CreateValveVCall(unsigned int vtableIdx,
234 ValveCallType vcalltype,
235 const ValvePassInfo *retInfo,
236 const ValvePassInfo *params,
237 unsigned int numParams)
244 ValveCall *vc = new ValveCall;
246 vc->type = vcalltype;
251 /* Get return information - encode only */
253 size_t retBufSize = 0;
254 bool retbuf_needs_extra;
257 if ((size = ValveParamToBinParam(retInfo->vtype, retInfo->type, retInfo->flags, &retBuf, retbuf_needs_extra)) == 0)
262 retBufSize = retBuf.size;
265 /* Get parameter info */
266 PassInfo paramBuf[32];
269 size_t extraSize = 0;
270 for (unsigned int i=0; i<numParams; i++)
273 if ((size = ValveParamToBinParam(params[i].vtype,
288 normSize += paramBuf[i].size;
289 extraSize += sizes[i];
292 /* Now we can try creating the call */
293 if ((vc->call = g_pBinTools->CreateVCall(vtableIdx,
296 (retInfo ? &retBuf : NULL),
308 /* Allocate extra space for thisptr AND ret buffer, even if we don't use it */
309 vc->vparams = new ValvePassInfo[numParams + 2];
311 /* We've got the call and everything is encoded.
312 * It's time to save the valve specific information and helper variables.
316 /* Allocate and copy */
317 vc->retinfo = &(vc->vparams[numParams]);
318 *vc->retinfo = *retInfo;
319 vc->retinfo->offset = 0;
320 vc->retinfo->obj_offset = retbuf_needs_extra ? sizeof(void *) : 0;
321 /* Allocate stack space */
322 vc->retbuf = new unsigned char[retBufSize];
328 /* Save the this info for the dynamic decoder */
329 vc->thisinfo = &(vc->vparams[numParams + 1]);
330 vc->thisinfo->type = PassType_Basic;
333 case ValveCall_Entity:
334 vc->thisinfo->vtype = Valve_CBaseEntity;
335 vc->thisinfo->flags = PASSFLAG_BYVAL;
336 vc->thisinfo->decflags = VDECODE_FLAG_ALLOWWORLD;
338 case ValveCall_Player:
339 vc->thisinfo->vtype = Valve_CBasePlayer;
340 vc->thisinfo->flags = PASSFLAG_BYVAL;
341 vc->thisinfo->decflags = 0;
344 vc->thisinfo->vtype = Valve_POD;
345 vc->thisinfo->flags = PASSFLAG_ASPOINTER;
346 vc->thisinfo->decflags = 0;
349 vc->thisinfo->encflags = 0;
350 vc->thisinfo->offset = 0;
351 vc->thisinfo->obj_offset = 0;
352 normSize += sizeof(void *);
354 /* Now, save info about each parameter. */
355 size_t last_extra_offset = 0;
356 for (unsigned int i=0; i<numParams; i++)
359 vc->vparams[i] = params[i];
360 vc->vparams[i].offset = vc->call->GetParamInfo(i)->offset;
361 vc->vparams[i].obj_offset = last_extra_offset;
362 last_extra_offset += sizes[i];
365 vc->stackSize = normSize + extraSize;
366 vc->stackEnd = normSize;