core/sourcemod.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 12 09:51:39 2006 +0000 (2006-11-12)
changeset 183 78488edd8873
parent 180 fe406c5f2aeb
child 209 fae1894d884c
permissions -rw-r--r--
rewrote forward API to use cached parameter pushing instead of immediate pushing
removed copy back cruft since it's no longer needed
removed PushCells() from API requirements, not needed
adjusted documentation and added TODO list to ForwardSys.cpp
various internal improvements
dvander@160
     1
#include <stdio.h>
dvander@160
     2
#include "sourcemod.h"
dvander@160
     3
#include "sourcemm_api.h"
dvander@160
     4
#include "systems/LibrarySys.h"
dvander@160
     5
#include "vm/sp_vm_engine.h"
dvander@160
     6
#include <sh_string.h>
dvander@176
     7
#include "PluginSys.h"
dvander@180
     8
#include "ForwardSys.h"
dvander@160
     9
dvander@160
    10
SourcePawnEngine g_SourcePawn;
dvander@160
    11
SourceModBase g_SourceMod;
dvander@160
    12
dvander@160
    13
ILibrary *g_pJIT = NULL;
dvander@160
    14
SourceHook::String g_BaseDir;
dvander@160
    15
ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn;
dvander@160
    16
IVirtualMachine *g_pVM;
dvander@160
    17
dvander@160
    18
typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *);
dvander@160
    19
typedef unsigned int (*GETEXPORTCOUNT)();
dvander@160
    20
typedef IVirtualMachine *(*GETEXPORT)(unsigned int);
dvander@160
    21
typedef void (*NOTIFYSHUTDOWN)();
dvander@160
    22
dvander@160
    23
void ShutdownJIT()
dvander@160
    24
{
dvander@160
    25
	NOTIFYSHUTDOWN notify = (NOTIFYSHUTDOWN)g_pJIT->GetSymbolAddress("NotifyShutdown");
dvander@160
    26
	if (notify)
dvander@160
    27
	{
dvander@160
    28
		notify();
dvander@160
    29
	}
dvander@160
    30
dvander@160
    31
	g_pJIT->CloseLibrary();
dvander@160
    32
}
dvander@160
    33
dvander@160
    34
bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
dvander@160
    35
{
dvander@160
    36
	//:TODO: we need a localinfo system!
dvander@160
    37
	g_BaseDir.assign(g_SMAPI->GetBaseDir());
dvander@160
    38
dvander@160
    39
	/* Attempt to load the JIT! */
dvander@160
    40
	char file[PLATFORM_MAX_PATH];
dvander@160
    41
	char myerror[255];
dvander@160
    42
	g_SMAPI->PathFormat(file, sizeof(file), "%s/addons/sourcemod/bin/sourcepawn.jit.x86.%s",
dvander@160
    43
		g_BaseDir.c_str(),
dvander@160
    44
		PLATFORM_LIB_EXT
dvander@160
    45
		);
dvander@160
    46
dvander@160
    47
	g_pJIT = g_LibSys.OpenLibrary(file, myerror, sizeof(myerror));
dvander@160
    48
	if (!g_pJIT)
dvander@160
    49
	{
dvander@160
    50
		if (error && err_max)
dvander@160
    51
		{
dvander@160
    52
			snprintf(error, err_max, "%s (failed to load bin/sourcepawn.jit.x86.%s)", 
dvander@160
    53
				myerror,
dvander@160
    54
				PLATFORM_LIB_EXT);
dvander@160
    55
		}
dvander@160
    56
		return false;
dvander@160
    57
	}
dvander@160
    58
dvander@160
    59
	int err;
dvander@160
    60
	GIVEENGINEPOINTER jit_init = (GIVEENGINEPOINTER)g_pJIT->GetSymbolAddress("GiveEnginePointer");
dvander@160
    61
	if (!jit_init)
dvander@160
    62
	{
dvander@160
    63
		ShutdownJIT();
dvander@160
    64
		if (error && err_max)
dvander@160
    65
		{
dvander@160
    66
			snprintf(error, err_max, "Failed to find GiveEnginePointer in JIT!");
dvander@160
    67
		}
dvander@160
    68
		return false;
dvander@160
    69
	}
dvander@160
    70
dvander@160
    71
	if ((err=jit_init(g_pSourcePawn)) != 0)
dvander@160
    72
	{
dvander@160
    73
		ShutdownJIT();
dvander@160
    74
		if (error && err_max)
dvander@160
    75
		{
dvander@160
    76
			snprintf(error, err_max, "GiveEnginePointer returned %d in the JIT", err);
dvander@160
    77
		}
dvander@160
    78
		return false;
dvander@160
    79
	}
dvander@160
    80
dvander@160
    81
	GETEXPORTCOUNT jit_getnum = (GETEXPORTCOUNT)g_pJIT->GetSymbolAddress("GetExportCount");
dvander@160
    82
	GETEXPORT jit_get = (GETEXPORT)g_pJIT->GetSymbolAddress("GetExport");
dvander@160
    83
	if (!jit_get)
dvander@160
    84
	{
dvander@160
    85
		ShutdownJIT();
dvander@160
    86
		if (error && err_max)
dvander@160
    87
		{
dvander@160
    88
			snprintf(error, err_max, "JIT is missing a necessary export!");
dvander@160
    89
		}
dvander@160
    90
		return false;
dvander@160
    91
	}
dvander@160
    92
dvander@160
    93
	unsigned int num = jit_getnum();
dvander@160
    94
	if (!num || ((g_pVM=jit_get(0)) == NULL))
dvander@160
    95
	{
dvander@160
    96
		ShutdownJIT();
dvander@160
    97
		if (error && err_max)
dvander@160
    98
		{
dvander@160
    99
			snprintf(error, err_max, "JIT did not export any virtual machines!");
dvander@160
   100
		}
dvander@160
   101
		return false;
dvander@160
   102
	}
dvander@160
   103
dvander@176
   104
	unsigned int api = g_pVM->GetAPIVersion();
dvander@176
   105
	if (api != SOURCEPAWN_VM_API_VERSION)
dvander@176
   106
	{
dvander@176
   107
		ShutdownJIT();
dvander@176
   108
		if (error && err_max)
dvander@176
   109
		{
dvander@176
   110
			snprintf(error, err_max, "JIT is not a compatible version");
dvander@176
   111
		}
dvander@176
   112
		return false;
dvander@176
   113
	}
dvander@176
   114
dvander@176
   115
	g_SMAPI->PathFormat(file, sizeof(file), "%s/addons/sourcemod/plugins/test.smx", g_BaseDir.c_str());
dvander@176
   116
	IPlugin *pPlugin = g_PluginMngr.LoadPlugin(file, false, PluginType_Global, error, err_max);
dvander@177
   117
	IPluginFunction *func = pPlugin->GetFunctionByName("Test");
dvander@180
   118
	IPluginFunction *func2 = pPlugin->GetFunctionByName("Test2");
dvander@177
   119
	cell_t result = 2;
dvander@177
   120
	cell_t val = 6;
dvander@180
   121
	ParamType types[] = {Param_Cell, Param_CellByRef};
dvander@180
   122
	va_list ap = va_start(ap, late);
dvander@180
   123
	CForward *fwd = CForward::CreateForward(NULL, ET_Custom, 2, types, ap);
dvander@180
   124
	fwd->AddFunction(func);
dvander@180
   125
	fwd->AddFunction(func2);
dvander@180
   126
	fwd->PushCell(1);
dvander@183
   127
	fwd->PushCellByRef(&val, 0);
dvander@180
   128
	fwd->Execute(&result, NULL);
dvander@176
   129
	g_PluginMngr.UnloadPlugin(pPlugin);
dvander@176
   130
dvander@160
   131
	return true;
dvander@160
   132
}