extensions/sdktools/vcaller.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sun Oct 13 14:16:08 2013 -0400 (2013-10-13)
changeset 4144 353e86f4c6ab
parent 4142 0a4da1ca54c9
child 4346 a2f9c923d545
permissions -rw-r--r--
Added engine support for Insurgency (bug 5951, r=asherkin).
faluco@1031
     1
/**
ds@2863
     2
 * vim: set ts=4 sw=4 tw=99 noet :
ds@1330
     3
 * =============================================================================
dvander@1233
     4
 * SourceMod SDKTools Extension
ds@2863
     5
 * Copyright (C) 2004-2009 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
faluco@1031
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1233
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1233
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1233
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
faluco@1031
    28
 */
faluco@1031
    29
dvander@950
    30
#include "extension.h"
dvander@950
    31
#include "vcallbuilder.h"
ds@1240
    32
#include "vglobals.h"
dvander@950
    33
dvander@950
    34
enum SDKLibrary
dvander@950
    35
{
dvander@950
    36
	SDKLibrary_Server,	/**< server.dll/server_i486.so */
dvander@950
    37
	SDKLibrary_Engine,	/**< engine.dll/engine_*.so */
dvander@950
    38
};
dvander@950
    39
dvander@950
    40
enum SDKPassMethod
dvander@950
    41
{
dvander@950
    42
	SDKPass_Pointer,		/**< Pass as a pointer */
dvander@950
    43
	SDKPass_Plain,			/**< Pass as plain data */
dvander@950
    44
	SDKPass_ByValue,		/**< Pass an object by value */
dvander@950
    45
	SDKPass_ByRef,			/**< Pass an object by reference */
dvander@950
    46
};
dvander@950
    47
ds@1042
    48
int s_vtbl_index = -1;
dvander@950
    49
void *s_call_addr = NULL;
dvander@950
    50
ValveCallType s_vcalltype = ValveCall_Static;
dvander@950
    51
bool s_has_return = false;
dvander@950
    52
ValvePassInfo s_return;
dvander@950
    53
unsigned int s_numparams = 0;
dvander@950
    54
ValvePassInfo s_params[SP_MAX_EXEC_PARAMS];
dvander@950
    55
dvander@950
    56
inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &type, unsigned int &flags)
dvander@950
    57
{
ds@1135
    58
	if (method == SDKPass_Pointer || method == SDKPass_ByRef)
dvander@950
    59
	{
dvander@950
    60
		type = PassType_Basic;
dvander@950
    61
		if (vtype == Valve_POD
dvander@954
    62
			|| vtype == Valve_Float
dvander@954
    63
			|| vtype == Valve_Bool)
dvander@950
    64
		{
ds@1135
    65
			flags = PASSFLAG_BYVAL | PASSFLAG_ASPOINTER;
dvander@950
    66
		} else {
dvander@950
    67
			flags = PASSFLAG_BYVAL;
dvander@950
    68
		}
dvander@950
    69
	} else if (method == SDKPass_Plain) {
dvander@950
    70
		type = PassType_Basic;
dvander@950
    71
		flags = PASSFLAG_BYVAL;
dvander@950
    72
	} else if (method == SDKPass_ByValue) {
dvander@950
    73
		if (vtype == Valve_Vector
dvander@950
    74
			|| vtype == Valve_QAngle)
dvander@950
    75
		{
dvander@950
    76
			type = PassType_Object;
dvander@950
    77
		} else {
dvander@950
    78
			type = PassType_Basic;
dvander@950
    79
		}
dvander@950
    80
		flags = PASSFLAG_BYVAL;
dvander@950
    81
	}
dvander@950
    82
}
dvander@950
    83
dvander@950
    84
static cell_t StartPrepSDKCall(IPluginContext *pContext, const cell_t *params)
dvander@950
    85
{
dvander@950
    86
	s_numparams = 0;
ds@1042
    87
	s_vtbl_index = -1;
dvander@950
    88
	s_call_addr = NULL;
dvander@950
    89
	s_has_return = false;
dvander@950
    90
	s_vcalltype = (ValveCallType)params[1];
dvander@950
    91
dvander@950
    92
	return 1;
dvander@950
    93
}
dvander@950
    94
dvander@950
    95
static cell_t PrepSDKCall_SetVirtual(IPluginContext *pContext, const cell_t *params)
dvander@950
    96
{
dvander@950
    97
	s_vtbl_index = params[1];
dvander@950
    98
dvander@950
    99
	return 1;
dvander@950
   100
}
dvander@950
   101
dvander@950
   102
static cell_t PrepSDKCall_SetSignature(IPluginContext *pContext, const cell_t *params)
dvander@950
   103
{
dvander@950
   104
	void *addrInBase = NULL;
dvander@950
   105
	if (params[1] == SDKLibrary_Server)
dvander@950
   106
	{
faluco@1560
   107
		addrInBase = (void *)g_SMAPI->GetServerFactory(false);
dvander@950
   108
	} else if (params[1] == SDKLibrary_Engine) {
faluco@1560
   109
		addrInBase = (void *)g_SMAPI->GetEngineFactory(false);
dvander@950
   110
	}
dvander@950
   111
	if (addrInBase == NULL)
dvander@950
   112
	{
dvander@950
   113
		return 0;
dvander@950
   114
	}
dvander@950
   115
dvander@950
   116
	char *sig;
dvander@950
   117
	pContext->LocalToString(params[2], &sig);
dvander@950
   118
ds@3027
   119
#if defined PLATFORM_POSIX
dvander@950
   120
	if (sig[0] == '@')
dvander@950
   121
	{
dvander@950
   122
		Dl_info info;
dvander@950
   123
		if (dladdr(addrInBase, &info) == 0)
dvander@950
   124
		{
dvander@950
   125
			return 0;
dvander@950
   126
		}
dvander@950
   127
		void *handle = dlopen(info.dli_fname, RTLD_NOW);
dvander@950
   128
		if (!handle)
dvander@950
   129
		{
dvander@950
   130
			return 0;
dvander@950
   131
		}
skamonkey@4141
   132
#if SOURCE_ENGINE == SE_CSS            \
skamonkey@4141
   133
	|| SOURCE_ENGINE == SE_HL2DM       \
skamonkey@4141
   134
	|| SOURCE_ENGINE == SE_DODS        \
skamonkey@4141
   135
	|| SOURCE_ENGINE == SE_SDK2013     \
skamonkey@4141
   136
	|| SOURCE_ENGINE == SE_TF2         \
skamonkey@4141
   137
	|| SOURCE_ENGINE == SE_LEFT4DEAD   \
skamonkey@4141
   138
	|| SOURCE_ENGINE == SE_LEFT4DEAD2  \
skamonkey@4141
   139
	|| SOURCE_ENGINE == SE_NUCLEARDAWN \
skamonkey@4142
   140
	|| SOURCE_ENGINE == SE_BLADE       \
skamonkey@4144
   141
	|| SOURCE_ENGINE == SE_INSURGENCY  \
skamonkey@4141
   142
	|| SOURCE_ENGINE == SE_CSGO
ds@2863
   143
		s_call_addr = memutils->ResolveSymbol(handle, &sig[1]);
ds@2863
   144
#else
dvander@950
   145
		s_call_addr = dlsym(handle, &sig[1]);
ds@2863
   146
#endif
dvander@950
   147
		dlclose(handle);
dvander@950
   148
dvander@950
   149
		return (s_call_addr != NULL) ? 1 : 0;
dvander@950
   150
	}
dvander@950
   151
#endif
dvander@950
   152
dvander@950
   153
	s_call_addr = memutils->FindPattern(addrInBase, sig, params[3]);
dvander@950
   154
dvander@950
   155
	return (s_call_addr != NULL) ? 1 : 0;
dvander@950
   156
}
dvander@950
   157
dvander@950
   158
static cell_t PrepSDKCall_SetFromConf(IPluginContext *pContext, const cell_t *params)
dvander@950
   159
{
dvander@950
   160
	IGameConfig *conf;
dvander@950
   161
dvander@950
   162
	if (params[1] == BAD_HANDLE)
dvander@950
   163
	{
dvander@950
   164
		conf = g_pGameConf;
dvander@950
   165
	} else {
dvander@950
   166
		HandleError err;
dvander@950
   167
		if ((conf = gameconfs->ReadHandle(params[1], pContext->GetIdentity(), &err)) == NULL)
dvander@950
   168
		{
dvander@950
   169
			return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
dvander@950
   170
		}
dvander@950
   171
	}
dvander@950
   172
	
dvander@950
   173
	char *key;
dvander@950
   174
	pContext->LocalToString(params[3], &key);
dvander@950
   175
dvander@950
   176
	if (params[2] == 0)
dvander@950
   177
	{
dvander@950
   178
		return conf->GetOffset(key, &s_vtbl_index) ? 1 : 0;
dvander@950
   179
	} else if (params[2] == 1) {
dvander@950
   180
		bool result = conf->GetMemSig(key, &s_call_addr) ? 1 : 0;
dvander@950
   181
		return (result && s_call_addr != NULL) ? 1 : 0;
dvander@950
   182
	}
dvander@950
   183
dvander@950
   184
	return 0;
dvander@950
   185
}
dvander@950
   186
dvander@950
   187
static cell_t PrepSDKCall_SetReturnInfo(IPluginContext *pContext, const cell_t *params)
dvander@950
   188
{
dvander@950
   189
	s_has_return = true;
dvander@950
   190
	s_return.vtype = (ValveType)params[1];
dvander@950
   191
	DecodePassMethod(s_return.vtype, (SDKPassMethod)params[2], s_return.type, s_return.flags);
dvander@950
   192
	s_return.decflags = params[3];
dvander@950
   193
	s_return.encflags = params[4];
dvander@950
   194
dvander@950
   195
	return 1;
dvander@950
   196
}
dvander@950
   197
dvander@950
   198
static cell_t PrepSDKCall_AddParameter(IPluginContext *pContext, const cell_t *params)
dvander@950
   199
{
dvander@950
   200
	if (s_numparams >= SP_MAX_EXEC_PARAMS)
dvander@950
   201
	{
dvander@950
   202
		return pContext->ThrowNativeError("Parameter limit for SDK calls reached");
dvander@950
   203
	}
dvander@950
   204
dvander@950
   205
	ValvePassInfo *info = &s_params[s_numparams++];
dvander@950
   206
	info->vtype = (ValveType)params[1];
ds@1135
   207
	SDKPassMethod method = (SDKPassMethod)params[2];
ds@1135
   208
	DecodePassMethod(info->vtype, method, info->type, info->flags);
dvander@954
   209
	info->decflags = params[3] | VDECODE_FLAG_BYREF;
dvander@950
   210
	info->encflags = params[4];
dvander@950
   211
ds@1135
   212
	/* Since SDKPass_ByRef acts like SDKPass_Pointer we can't allow NULL, just in case */
ds@1135
   213
	if (method == SDKPass_ByRef)
ds@1135
   214
	{
ds@1135
   215
		info->decflags &= ~VDECODE_FLAG_ALLOWNULL;
ds@1135
   216
	}
ds@1135
   217
dvander@950
   218
	return 1;
dvander@950
   219
}
dvander@950
   220
dvander@950
   221
static cell_t EndPrepSDKCall(IPluginContext *pContext, const cell_t *params)
dvander@950
   222
{
dvander@950
   223
	ValveCall *vc = NULL;
ds@1042
   224
	if (s_vtbl_index > -1)
dvander@950
   225
	{
dvander@950
   226
		vc = CreateValveVCall(s_vtbl_index, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
dvander@953
   227
	} else if (s_call_addr) {
dvander@953
   228
		vc = CreateValveCall(s_call_addr, s_vcalltype, s_has_return ? &s_return : NULL, s_params, s_numparams);
dvander@950
   229
	}
dvander@950
   230
dvander@950
   231
	if (!vc)
dvander@950
   232
	{
dvander@950
   233
		return BAD_HANDLE;
dvander@950
   234
	}
dvander@950
   235
dvander@968
   236
	if (vc->thisinfo)
dvander@968
   237
	{
dvander@968
   238
		vc->thisinfo->decflags |= VDECODE_FLAG_BYREF;
dvander@968
   239
	}
dvander@968
   240
dvander@950
   241
	Handle_t hndl = handlesys->CreateHandle(g_CallHandle, vc, pContext->GetIdentity(), myself->GetIdentity(), NULL);
dvander@950
   242
	if (!hndl)
dvander@950
   243
	{
dvander@950
   244
		delete vc;
dvander@950
   245
	}
dvander@950
   246
dvander@950
   247
	return hndl;
dvander@950
   248
}
dvander@950
   249
dvander@950
   250
static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
dvander@950
   251
{
dvander@950
   252
	ValveCall *vc;
dvander@950
   253
	HandleError err;
dvander@950
   254
	HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
dvander@950
   255
dvander@950
   256
	if ((err = handlesys->ReadHandle(params[1], g_CallHandle, &sec, (void **)&vc)) != HandleError_None)
dvander@950
   257
	{
dvander@950
   258
		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", params[1], err);
dvander@950
   259
	}
dvander@950
   260
dvander@950
   261
	unsigned char *ptr = vc->stk_get();
dvander@950
   262
downtown1@2901
   263
	const unsigned int numparams = (unsigned)params[0];
dvander@950
   264
	unsigned int startparam = 2;
dvander@950
   265
	/* Do we need to write a thispointer?  */
dvander@950
   266
ds@1065
   267
	if (vc->thisinfo)
dvander@950
   268
	{
ds@1065
   269
		switch (vc->type)
dvander@950
   270
		{
ds@1065
   271
		case ValveCall_Entity:
ds@1065
   272
		case ValveCall_Player:
ds@1065
   273
			{
ds@1065
   274
				if (startparam > numparams)
ds@1065
   275
				{
ds@1065
   276
					vc->stk_put(ptr);
ds@1065
   277
					return pContext->ThrowNativeError("Expected 1 parameter for entity pointer; found none");
ds@1065
   278
				}
ds@1065
   279
ds@1065
   280
				if (DecodeValveParam(pContext, 
ds@1065
   281
					params[startparam],
ds@1065
   282
					vc,
ds@1065
   283
					vc->thisinfo,
ds@1065
   284
					ptr) == Data_Fail)
ds@1065
   285
				{
ds@1065
   286
					vc->stk_put(ptr);
ds@1065
   287
					return 0;
ds@1065
   288
				}
ds@1065
   289
				startparam++;
ds@1065
   290
			}
ds@1065
   291
			break;
ds@1065
   292
		case ValveCall_GameRules:
ds@1065
   293
			{
ds@1065
   294
				if (g_pGameRules == NULL)
ds@1065
   295
				{
ds@1065
   296
					vc->stk_put(ptr);
ds@1065
   297
					return pContext->ThrowNativeError("GameRules unsupported or not available; file a bug report");
ds@1065
   298
				}
ds@1065
   299
ds@1065
   300
				void *gamerules = *g_pGameRules;
ds@1065
   301
ds@1065
   302
				if (gamerules == NULL)
ds@1065
   303
				{
ds@1065
   304
					vc->stk_put(ptr);
ds@1065
   305
					return pContext->ThrowNativeError("GameRules not available before map is loaded");
ds@1065
   306
				}
ds@1065
   307
				*(void **)ptr = gamerules;
ds@1065
   308
			}
ds@1065
   309
			break;
ds@1240
   310
		case ValveCall_EntityList:
ds@1240
   311
			{
ds@1240
   312
				if (g_EntList == NULL)
ds@1240
   313
				{
ds@1240
   314
					vc->stk_put(ptr);
ds@1240
   315
					return pContext->ThrowNativeError("EntityList unsupported or not available; file a bug report");
ds@1240
   316
				}
ds@1240
   317
ds@1240
   318
				*(void **)ptr = g_EntList;
ds@1240
   319
			}
ds@1240
   320
			break;
downtown1@2901
   321
		case ValveCall_Raw:
downtown1@2901
   322
			{
downtown1@2901
   323
				//params[startparam] is an address to a pointer to THIS
downtown1@2901
   324
				//params following this are params to the method we will invoke later
downtown1@2901
   325
				if (startparam > numparams)
downtown1@2901
   326
				{
downtown1@2901
   327
					vc->stk_put(ptr);
downtown1@2901
   328
					return pContext->ThrowNativeError("Expected a ThisPtr address, it wasn't found");
downtown1@2901
   329
				}
downtown1@2901
   330
downtown1@2901
   331
				//note: varargs pawn args are passed by-ref
downtown1@2901
   332
				cell_t *cell;
downtown1@2901
   333
				pContext->LocalToPhysAddr(params[startparam], &cell);
downtown1@2901
   334
				void *thisptr = reinterpret_cast<void*>(*cell);
downtown1@2901
   335
downtown1@2901
   336
				*(void **)ptr = thisptr;
downtown1@2901
   337
				startparam++;
downtown1@2901
   338
			}
downtown1@2901
   339
			break;
dvander@950
   340
		}
dvander@950
   341
	}
dvander@950
   342
dvander@950
   343
	/* See if we need to skip any more parameters */
dvander@950
   344
	unsigned int retparam = startparam;
dvander@950
   345
	if (vc->retinfo)
dvander@950
   346
	{
dvander@950
   347
		if (vc->retinfo->vtype == Valve_String)
dvander@950
   348
		{
dvander@950
   349
			startparam += 2;
dvander@950
   350
		} else if (vc->retinfo->vtype == Valve_Vector
dvander@950
   351
					|| vc->retinfo->vtype == Valve_QAngle)
dvander@950
   352
		{
dvander@950
   353
			startparam += 1;
dvander@950
   354
		}
dvander@950
   355
	}
dvander@950
   356
dvander@950
   357
	unsigned int callparams = vc->call->GetParamCount();
dvander@950
   358
	bool will_copyback = false;
dvander@950
   359
	for (unsigned int i=0; i<callparams; i++)
dvander@950
   360
	{
dvander@950
   361
		unsigned int p = startparam + i;
dvander@950
   362
		if (p > numparams)
dvander@950
   363
		{
dvander@950
   364
			vc->stk_put(ptr);
dvander@950
   365
			return pContext->ThrowNativeError("Expected %dth parameter, found none", p);
dvander@950
   366
		}
dvander@950
   367
		if (DecodeValveParam(pContext,
dvander@950
   368
			params[p],
dvander@987
   369
			vc,
dvander@954
   370
			&(vc->vparams[i]),
dvander@987
   371
			ptr) == Data_Fail)
dvander@950
   372
		{
dvander@950
   373
			vc->stk_put(ptr);
dvander@950
   374
			return 0;
dvander@950
   375
		}
dvander@950
   376
		if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
dvander@950
   377
		{
dvander@950
   378
			will_copyback = true;
dvander@950
   379
		}
dvander@950
   380
	}
dvander@950
   381
dvander@950
   382
	/* Make the actual call */
dvander@950
   383
	vc->call->Execute(ptr, vc->retbuf);
dvander@950
   384
dvander@950
   385
	/* Do we need to copy anything back? */
dvander@950
   386
	if (will_copyback)
dvander@950
   387
	{
dvander@950
   388
		for (unsigned int i=0; i<callparams; i++)
dvander@950
   389
		{
dvander@950
   390
			if (vc->vparams[i].encflags & VENCODE_FLAG_COPYBACK)
dvander@950
   391
			{
dvander@950
   392
				if (EncodeValveParam(pContext, 
ds@1130
   393
					params[startparam + i], 
dvander@987
   394
					vc,
dvander@954
   395
					&vc->vparams[i],
dvander@987
   396
					ptr) == Data_Fail)
dvander@950
   397
				{
dvander@950
   398
					vc->stk_put(ptr);
dvander@950
   399
					return 0;
dvander@950
   400
				}
dvander@950
   401
			}
dvander@950
   402
		}
dvander@950
   403
	}
dvander@950
   404
dvander@950
   405
	/* Save stack once and for all */
dvander@950
   406
	vc->stk_put(ptr);
dvander@950
   407
dvander@950
   408
	/* Figure out how to decode the return information */
dvander@950
   409
	if (vc->retinfo)
dvander@950
   410
	{
dvander@950
   411
		if (vc->retinfo->vtype == Valve_String)
dvander@950
   412
		{
dvander@950
   413
			if (numparams < 3)
dvander@950
   414
			{
dvander@950
   415
				return pContext->ThrowNativeError("Expected arguments (2,3) for string storage");
dvander@950
   416
			}
dvander@950
   417
			cell_t *addr;
dvander@950
   418
			size_t written;
dvander@950
   419
			pContext->LocalToPhysAddr(params[retparam+1], &addr);
dvander@950
   420
			pContext->StringToLocalUTF8(params[retparam], *addr, *(char **)vc->retbuf, &written);
dvander@950
   421
			return (cell_t)written;
dvander@950
   422
		} else if (vc->retinfo->vtype == Valve_Vector
dvander@950
   423
					|| vc->retinfo->vtype == Valve_QAngle)
dvander@950
   424
		{
dvander@950
   425
			if (numparams < 2)
dvander@950
   426
			{
dvander@950
   427
				return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
dvander@950
   428
			}
dvander@987
   429
			if (EncodeValveParam(pContext, params[retparam], vc, vc->retinfo, vc->retbuf)
dvander@950
   430
				== Data_Fail)
dvander@950
   431
			{
dvander@950
   432
				return 0;
dvander@950
   433
			}
dvander@950
   434
		} else if (vc->retinfo->vtype == Valve_CBaseEntity
dvander@950
   435
					|| vc->retinfo->vtype == Valve_CBasePlayer)
dvander@950
   436
		{
dvander@950
   437
			CBaseEntity *pEntity = *(CBaseEntity **)(vc->retbuf);
dvander@950
   438
			if (!pEntity)
dvander@950
   439
			{
dvander@950
   440
				return -1;
dvander@950
   441
			}
dvander@950
   442
			edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
dvander@950
   443
			if (!pEdict || pEdict->IsFree())
dvander@950
   444
			{
dvander@950
   445
				return -1;
dvander@950
   446
			}
ds@2400
   447
			return IndexOfEdict(pEdict);
dvander@950
   448
		} else if (vc->retinfo->vtype == Valve_Edict) {
dvander@950
   449
			edict_t *pEdict = *(edict_t **)(vc->retbuf);
dvander@950
   450
			if (!pEdict || pEdict->IsFree())
dvander@950
   451
			{
dvander@950
   452
				return -1;
dvander@950
   453
			}
ds@2400
   454
			return IndexOfEdict(pEdict);
dvander@954
   455
		} else if (vc->retinfo->vtype == Valve_Bool) {
dvander@954
   456
			bool *addr = (bool  *)vc->retbuf;
ds@1135
   457
			if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
dvander@954
   458
			{
dvander@954
   459
				addr = *(bool **)addr;
dvander@954
   460
			}
dvander@954
   461
			return *addr ? 1 : 0;
dvander@950
   462
		} else {
dvander@950
   463
			cell_t *addr = (cell_t *)vc->retbuf;
ds@1135
   464
			if (vc->retinfo->flags & PASSFLAG_ASPOINTER)
dvander@950
   465
			{
dvander@950
   466
				addr = *(cell_t **)addr;
dvander@950
   467
			}
dvander@950
   468
			return *addr;
dvander@950
   469
		}
dvander@950
   470
	}
dvander@950
   471
dvander@950
   472
	return 0;
dvander@950
   473
}
dvander@950
   474
dvander@950
   475
sp_nativeinfo_t g_CallNatives[] = 
dvander@950
   476
{
dvander@950
   477
	{"StartPrepSDKCall",			StartPrepSDKCall},
dvander@950
   478
	{"PrepSDKCall_SetVirtual",		PrepSDKCall_SetVirtual},
dvander@950
   479
	{"PrepSDKCall_SetSignature",	PrepSDKCall_SetSignature},
dvander@950
   480
	{"PrepSDKCall_SetFromConf",		PrepSDKCall_SetFromConf},
dvander@950
   481
	{"PrepSDKCall_SetReturnInfo",	PrepSDKCall_SetReturnInfo},
dvander@950
   482
	{"PrepSDKCall_AddParameter",	PrepSDKCall_AddParameter},
dvander@950
   483
	{"EndPrepSDKCall",				EndPrepSDKCall},
dvander@950
   484
	{"SDKCall",						SDKCall},
dvander@950
   485
	{NULL,							NULL},
dvander@950
   486
};