Committed new register_native system
This commit is contained in:
		| @@ -34,6 +34,9 @@ | |||||||
| #include "CForward.h" | #include "CForward.h" | ||||||
| #include "CFile.h" | #include "CFile.h" | ||||||
| #include "amx.h" | #include "amx.h" | ||||||
|  | #include "natives.h" | ||||||
|  |  | ||||||
|  | extern const char *no_function; | ||||||
|  |  | ||||||
| CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug) {	 | CPluginMngr::CPlugin* CPluginMngr::loadPlugin(const char* path, const char* name, char* error, int debug) {	 | ||||||
| 	CPlugin** a = &head; | 	CPlugin** a = &head; | ||||||
| @@ -49,6 +52,25 @@ void CPluginMngr::unloadPlugin( CPlugin** a ) { | |||||||
| 	--pCounter; | 	--pCounter; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void CPluginMngr::Finalize() | ||||||
|  | { | ||||||
|  | 	if (m_Finalized) | ||||||
|  | 		return; | ||||||
|  | 	pNatives = BuildNativeTable(); | ||||||
|  |  | ||||||
|  | 	CPlugin *a = head; | ||||||
|  | 	while (a) | ||||||
|  | 	{ | ||||||
|  | 		if (a->getStatusCode() == ps_running) | ||||||
|  | 		{ | ||||||
|  | 			amx_Register(a->getAMX(), pNatives, -1); | ||||||
|  | 			a->Finalize(); | ||||||
|  | 		} | ||||||
|  | 		a=a->next; | ||||||
|  | 	} | ||||||
|  | 	m_Finalized = true; | ||||||
|  | } | ||||||
|  |  | ||||||
| int  CPluginMngr::loadPluginsFromFile( const char* filename ) | int  CPluginMngr::loadPluginsFromFile( const char* filename ) | ||||||
| { | { | ||||||
| 	char file[256]; | 	char file[256]; | ||||||
| @@ -102,6 +124,12 @@ void CPluginMngr::clear() { | |||||||
| 	CPlugin**a = &head;	 | 	CPlugin**a = &head;	 | ||||||
| 	while ( *a ) | 	while ( *a ) | ||||||
| 		unloadPlugin(a); | 		unloadPlugin(a); | ||||||
|  | 	m_Finalized = false; | ||||||
|  | 	if (pNatives) | ||||||
|  | 	{ | ||||||
|  | 		delete [] pNatives; | ||||||
|  | 		pNatives = NULL; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| CPluginMngr::CPlugin* CPluginMngr::findPluginFast(AMX *amx)  | CPluginMngr::CPlugin* CPluginMngr::findPluginFast(AMX *amx)  | ||||||
| @@ -191,6 +219,31 @@ CPluginMngr::CPlugin::~CPlugin( ) | |||||||
| 	unload_amxscript( &amx, &code ); | 	unload_amxscript( &amx, &code ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void CPluginMngr::CPlugin::Finalize() | ||||||
|  | { | ||||||
|  | 	char buffer[128]; | ||||||
|  |  | ||||||
|  | 	int old_status = status; | ||||||
|  | 	if (CheckModules(&amx, buffer)) | ||||||
|  | 	{ | ||||||
|  | 		if ( amx_Register(&amx, core_Natives, -1) != AMX_ERR_NONE ) | ||||||
|  | 		{ | ||||||
|  | 			status = ps_bad_load; | ||||||
|  | 			sprintf(buffer, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function); | ||||||
|  | 			errorMsg.assign(buffer); | ||||||
|  | 			amx.error = AMX_ERR_NOTFOUND; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		status = ps_bad_load; | ||||||
|  | 		errorMsg.assign(buffer); | ||||||
|  | 		amx.error = AMX_ERR_NOTFOUND; | ||||||
|  | 	} | ||||||
|  | 	if (old_status != status) | ||||||
|  | 	{ | ||||||
|  | 		AMXXLOG_Log("[AMXX] Plugin \"%s\" failed to load: %s", name.c_str(), errorMsg.c_str()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| void CPluginMngr::CPlugin::pauseFunction( int id ) {  | void CPluginMngr::CPlugin::pauseFunction( int id ) {  | ||||||
| 	if (isValid()){ | 	if (isValid()){ | ||||||
| 		paused_fun |= (1<<id); | 		paused_fun |= (1<<id); | ||||||
|   | |||||||
| @@ -93,6 +93,7 @@ public: | |||||||
| 		inline bool isPaused() const { return ( (status == ps_paused) || (status == ps_stopped)); } | 		inline bool isPaused() const { return ( (status == ps_paused) || (status == ps_stopped)); } | ||||||
| 		//inline bool isFunctionPaused( int id ) const { return (paused_fun & (1<<id)) ? true : false; 	} | 		//inline bool isFunctionPaused( int id ) const { return (paused_fun & (1<<id)) ? true : false; 	} | ||||||
| 		inline bool isExecutable(int id) const { return (isValid() && !isPaused());	} | 		inline bool isExecutable(int id) const { return (isValid() && !isPaused());	} | ||||||
|  | 		void Finalize(); | ||||||
| 		void pausePlugin(); | 		void pausePlugin(); | ||||||
| 		void unpausePlugin(); | 		void unpausePlugin(); | ||||||
| 		void pauseFunction( int id ); | 		void pauseFunction( int id ); | ||||||
| @@ -108,9 +109,12 @@ private: | |||||||
|  |  | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	CPluginMngr() { head = 0; pCounter = 0; } | 	CPluginMngr() { head = 0; pCounter = 0; pNatives = NULL; m_Finalized=false;} | ||||||
| 	~CPluginMngr() { clear(); } | 	~CPluginMngr() { clear(); } | ||||||
|  |  | ||||||
|  | 	bool m_Finalized; | ||||||
|  | 	AMX_NATIVE_INFO *pNatives; | ||||||
|  |  | ||||||
| 	// Interface | 	// Interface | ||||||
|  |  | ||||||
| 	CPlugin* loadPlugin(const char* path, const char* name, char* error, int debug); | 	CPlugin* loadPlugin(const char* path, const char* name, char* error, int debug); | ||||||
| @@ -121,6 +125,7 @@ public: | |||||||
| 	CPlugin* findPlugin(int index); | 	CPlugin* findPlugin(int index); | ||||||
| 	CPlugin* findPlugin(const char* name); | 	CPlugin* findPlugin(const char* name); | ||||||
| 	inline int getPluginsNum() const { return pCounter; } | 	inline int getPluginsNum() const { return pCounter; } | ||||||
|  | 	void Finalize(); | ||||||
| 	void clear(); | 	void clear(); | ||||||
|  |  | ||||||
| 	class iterator { | 	class iterator { | ||||||
|   | |||||||
							
								
								
									
										101
									
								
								amxmodx/CStack.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										101
									
								
								amxmodx/CStack.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | /* AMX Mod X | ||||||
|  | * | ||||||
|  | * by the AMX Mod X Development Team | ||||||
|  | *  originally developed by OLO | ||||||
|  | * | ||||||
|  | * | ||||||
|  | *  This program is free software; you can redistribute it and/or modify it | ||||||
|  | *  under the terms of the GNU General Public License as published by the | ||||||
|  | *  Free Software Foundation; either version 2 of the License, or (at | ||||||
|  | *  your option) any later version. | ||||||
|  | * | ||||||
|  | *  This program is distributed in the hope that it will be useful, but | ||||||
|  | *  WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||||
|  | *  General Public License for more details. | ||||||
|  | * | ||||||
|  | *  You should have received a copy of the GNU General Public License | ||||||
|  | *  along with this program; if not, write to the Free Software Foundation, | ||||||
|  | *  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||||
|  | * | ||||||
|  | *  In addition, as a special exception, the author gives permission to | ||||||
|  | *  link the code of this program with the Half-Life Game Engine ("HL | ||||||
|  | *  Engine") and Modified Game Libraries ("MODs") developed by Valve, | ||||||
|  | *  L.L.C ("Valve"). You must obey the GNU General Public License in all | ||||||
|  | *  respects for all of the code used other than the HL Engine and MODs | ||||||
|  | *  from Valve. If you modify this file, you may extend this exception | ||||||
|  | *  to your version of the file, but you are not obligated to do so. If | ||||||
|  | *  you do not wish to do so, delete this exception statement from your | ||||||
|  | *  version. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | //by David "BAILOPAN" Anderson | ||||||
|  | #ifndef _INCLUDE_CSTACK_H | ||||||
|  | #define _INCLUDE_CSTACK_H | ||||||
|  |  | ||||||
|  | template <class T> | ||||||
|  | class CStack | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	struct CStackItem | ||||||
|  | 	{ | ||||||
|  | 	public: | ||||||
|  | 		T item; | ||||||
|  | 		CStackItem *prev; | ||||||
|  | 	}; | ||||||
|  | public: | ||||||
|  | 	CStack() | ||||||
|  | 	{ | ||||||
|  | 		mSize = 0; | ||||||
|  | 		mStack = NULL; | ||||||
|  | 	} | ||||||
|  | 	~CStack() | ||||||
|  | 	{ | ||||||
|  | 		CStackItem *p, *t; | ||||||
|  | 		p = mStack; | ||||||
|  | 		while (p) | ||||||
|  | 		{ | ||||||
|  | 			t = p->prev; | ||||||
|  | 			delete p; | ||||||
|  | 			p = t; | ||||||
|  | 		} | ||||||
|  | 		mStack = NULL; | ||||||
|  | 	} | ||||||
|  | 	bool empty() | ||||||
|  | 	{ | ||||||
|  | 		return (mSize==0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void push(const T & v) | ||||||
|  | 	{ | ||||||
|  | 		CStackItem *p = new CStackItem; | ||||||
|  | 		p->item = v; | ||||||
|  | 		p->prev = mStack; | ||||||
|  | 		mStack = p; | ||||||
|  | 		mSize++; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void pop() | ||||||
|  | 	{ | ||||||
|  | 		CStackItem *p = mStack; | ||||||
|  | 		mStack = p->prev; | ||||||
|  | 		delete p; | ||||||
|  | 		mSize--; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	T & top() | ||||||
|  | 	{ | ||||||
|  | 		return mStack->item; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	size_t size() | ||||||
|  | 	{ | ||||||
|  | 		return mSize; | ||||||
|  | 	} | ||||||
|  | private: | ||||||
|  | 	CStackItem *mStack; | ||||||
|  | 	size_t mSize; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif //_INCLUDE_CQUEUE_H | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								amxmodx/JIT/natives-x86.o
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								amxmodx/JIT/natives-x86.o
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								amxmodx/JIT/natives-x86.obj
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								amxmodx/JIT/natives-x86.obj
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -1747,8 +1747,9 @@ static const void * const amx_opcodelist[] = { | |||||||
|  |  | ||||||
|   if (amx->callback==NULL) |   if (amx->callback==NULL) | ||||||
|     return AMX_ERR_CALLBACK; |     return AMX_ERR_CALLBACK; | ||||||
|   if ((amx->flags & AMX_FLAG_NTVREG)==0) |   if (!(amx->flags & AMX_FLAG_PRENIT)) | ||||||
|     return AMX_ERR_NOTFOUND; | 	if ((amx->flags & AMX_FLAG_NTVREG)==0) | ||||||
|  | 		return AMX_ERR_NOTFOUND; | ||||||
|   if ((amx->flags & AMX_FLAG_RELOC)==0) |   if ((amx->flags & AMX_FLAG_RELOC)==0) | ||||||
|     return AMX_ERR_INIT; |     return AMX_ERR_INIT; | ||||||
|   assert((amx->flags & AMX_FLAG_BROWSE)==0); |   assert((amx->flags & AMX_FLAG_BROWSE)==0); | ||||||
| @@ -2678,8 +2679,9 @@ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) | |||||||
|  |  | ||||||
|   if (amx->callback==NULL) |   if (amx->callback==NULL) | ||||||
|     return AMX_ERR_CALLBACK; |     return AMX_ERR_CALLBACK; | ||||||
|   if ((amx->flags & AMX_FLAG_NTVREG)==0) |   if (!(amx->flags & AMX_FLAG_PRENIT)) | ||||||
|     return AMX_ERR_NOTFOUND; | 	if ((amx->flags & AMX_FLAG_NTVREG)==0) | ||||||
|  | 		return AMX_ERR_NOTFOUND; | ||||||
|   if ((amx->flags & AMX_FLAG_RELOC)==0) |   if ((amx->flags & AMX_FLAG_RELOC)==0) | ||||||
|     return AMX_ERR_INIT; |     return AMX_ERR_INIT; | ||||||
|   assert((amx->flags & AMX_FLAG_BROWSE)==0); |   assert((amx->flags & AMX_FLAG_BROWSE)==0); | ||||||
|   | |||||||
| @@ -320,6 +320,7 @@ enum { | |||||||
| #define AMX_FLAG_COMPACT  0x04  /* compact encoding */ | #define AMX_FLAG_COMPACT  0x04  /* compact encoding */ | ||||||
| #define AMX_FLAG_BYTEOPC  0x08  /* opcode is a byte (not a cell) */ | #define AMX_FLAG_BYTEOPC  0x08  /* opcode is a byte (not a cell) */ | ||||||
| #define AMX_FLAG_NOCHECKS 0x10  /* no array bounds checking; no STMT opcode */ | #define AMX_FLAG_NOCHECKS 0x10  /* no array bounds checking; no STMT opcode */ | ||||||
|  | #define AMX_FLAG_PRENIT	 0x100	/* pre-initialized, do not check natives */ | ||||||
| #define AMX_FLAG_NTVREG 0x1000  /* all native functions are registered */ | #define AMX_FLAG_NTVREG 0x1000  /* all native functions are registered */ | ||||||
| #define AMX_FLAG_JITC   0x2000  /* abstract machine is JIT compiled */ | #define AMX_FLAG_JITC   0x2000  /* abstract machine is JIT compiled */ | ||||||
| #define AMX_FLAG_BROWSE 0x4000  /* busy browsing */ | #define AMX_FLAG_BROWSE 0x4000  /* busy browsing */ | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
| #include "amxmodx.h" | #include "amxmodx.h" | ||||||
| #include "fakemeta.h" | #include "fakemeta.h" | ||||||
| #include "newmenus.h" | #include "newmenus.h" | ||||||
|  | #include "natives.h" | ||||||
|  |  | ||||||
| plugin_info_t Plugin_info = { | plugin_info_t Plugin_info = { | ||||||
|   META_INTERFACE_VERSION, // ifvers |   META_INTERFACE_VERSION, // ifvers | ||||||
| @@ -266,6 +267,7 @@ int	C_Spawn( edict_t *pent ) { | |||||||
|  |  | ||||||
|   //  ###### Load AMX scripts |   //  ###### Load AMX scripts | ||||||
|   g_plugins.loadPluginsFromFile( get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini") ); |   g_plugins.loadPluginsFromFile( get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini") ); | ||||||
|  |   g_plugins.Finalize(); | ||||||
|  |  | ||||||
|   // Register forwards |   // Register forwards | ||||||
|   FF_PluginInit = registerForward("plugin_init", ET_IGNORE, FP_DONE); |   FF_PluginInit = registerForward("plugin_init", ET_IGNORE, FP_DONE); | ||||||
| @@ -454,6 +456,7 @@ void C_ServerDeactivate_Post() { | |||||||
|   g_vault.clear(); |   g_vault.clear(); | ||||||
|   g_xvars.clear(); |   g_xvars.clear(); | ||||||
|   g_plugins.clear(); |   g_plugins.clear(); | ||||||
|  |   ClearPluginLibraries(); | ||||||
|   char file[256]; |   char file[256]; | ||||||
|   g_langMngr.Save(build_pathname_r(file, sizeof(file)-1, "%s/languages.dat", get_localinfo("amxx_datadir", "addons/amxmodx/data"))); |   g_langMngr.Save(build_pathname_r(file, sizeof(file)-1, "%s/languages.dat", get_localinfo("amxx_datadir", "addons/amxmodx/data"))); | ||||||
|   g_langMngr.SaveCache(build_pathname_r(file, sizeof(file)-1, "%s/dictionary.cache", get_localinfo("amxx_datadir", "addons/amxmodx/data"))); |   g_langMngr.SaveCache(build_pathname_r(file, sizeof(file)-1, "%s/dictionary.cache", get_localinfo("amxx_datadir", "addons/amxmodx/data"))); | ||||||
|   | |||||||
| @@ -41,6 +41,7 @@ | |||||||
| #include "amxxfile.h" | #include "amxxfile.h" | ||||||
| #include "amxdbg.h" | #include "amxdbg.h" | ||||||
| #include "newmenus.h" | #include "newmenus.h" | ||||||
|  | #include "natives.h" | ||||||
|  |  | ||||||
| CList<CModule,const char*> g_modules; | CList<CModule,const char*> g_modules; | ||||||
| CList<CScript,AMX*> g_loadedscripts; | CList<CScript,AMX*> g_loadedscripts; | ||||||
| @@ -439,7 +440,25 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64 | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	g_loadedscripts.put( aa ); | 	g_loadedscripts.put( aa ); | ||||||
| 	return set_amxnatives(amx,error); |  | ||||||
|  |     set_amxnatives(amx,error); | ||||||
|  |  | ||||||
|  | 	if (g_plugins.m_Finalized) | ||||||
|  | 	{ | ||||||
|  | 		amx_Register(amx, g_plugins.pNatives, -1); | ||||||
|  | 		if (CheckModules(amx, error)) | ||||||
|  | 		{ | ||||||
|  | 			if ( amx_Register(amx, core_Natives, -1) != AMX_ERR_NONE ) | ||||||
|  | 			{ | ||||||
|  | 				sprintf(error, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function); | ||||||
|  | 				return (amx->error = AMX_ERR_NOTFOUND); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			return (amx->error = AMX_ERR_NOTFOUND); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return (amx->error = AMX_ERR_NONE); | ||||||
| } | } | ||||||
|  |  | ||||||
| const char *StrCaseStr(const char *as, const char *bs) | const char *StrCaseStr(const char *as, const char *bs) | ||||||
| @@ -519,6 +538,8 @@ int CheckModules(AMX *amx, char error[128]) | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		if (!found) | ||||||
|  | 			found = LibraryExists(buffer); | ||||||
| 		if (!found) | 		if (!found) | ||||||
| 		{ | 		{ | ||||||
| 			sprintf(error, "Module \"%s\" required for plugin.  Check modules.ini.", buffer); | 			sprintf(error, "Module \"%s\" required for plugin.  Check modules.ini.", buffer); | ||||||
| @@ -546,19 +567,24 @@ int set_amxnatives(AMX* amx,char error[128]) | |||||||
| 	amx_Register(amx, time_Natives, -1); | 	amx_Register(amx, time_Natives, -1); | ||||||
| 	amx_Register(amx, vault_Natives, -1); | 	amx_Register(amx, vault_Natives, -1); | ||||||
| 	amx_Register(amx, g_NewMenuNatives, -1); | 	amx_Register(amx, g_NewMenuNatives, -1); | ||||||
|  | 	amx_Register(amx, g_NativeNatives, -1); | ||||||
|  |  | ||||||
| 	if (CheckModules(amx, error)) | 	//we're not actually gonna check these here anymore | ||||||
|  | 	amx->flags |= AMX_FLAG_PRENIT; | ||||||
|  |  | ||||||
|  | 	int idx; | ||||||
|  | 	cell retval; | ||||||
|  | 	if (amx_FindPublic(amx, "plugin_natives", &idx)==AMX_ERR_NONE) | ||||||
| 	{ | 	{ | ||||||
| 		if ( amx_Register(amx, core_Natives, -1) != AMX_ERR_NONE ) | 		if (amx_Exec(amx, &retval, idx)!=AMX_ERR_NONE) | ||||||
| 		{ | 		{ | ||||||
| 			sprintf(error, "Plugin uses an unknown function (name \"%s\") - check your modules.ini.", no_function); | 			//someday clear libraries that this added | ||||||
| 			return (amx->error = AMX_ERR_NATIVE); |  | ||||||
| 		} | 		} | ||||||
| 		 |  | ||||||
| 		return AMX_ERR_NONE; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return (amx->error = AMX_ERR_NATIVE); | 	amx->flags &= ~(AMX_FLAG_PRENIT); | ||||||
|  |  | ||||||
|  | 	return (amx->error = AMX_ERR_NONE); | ||||||
| } | } | ||||||
|  |  | ||||||
| int unload_amxscript(AMX* amx, void** program) | int unload_amxscript(AMX* amx, void** program) | ||||||
|   | |||||||
| @@ -48,5 +48,6 @@ | |||||||
| #define RELOAD_MODULE 0 | #define RELOAD_MODULE 0 | ||||||
| #define STATIC_MODULE 1 | #define STATIC_MODULE 1 | ||||||
|  |  | ||||||
|  | int CheckModules(AMX *amx, char error[128]); | ||||||
|  |  | ||||||
| #endif // __MODULES_H__ | #endif // __MODULES_H__ | ||||||
|   | |||||||
| @@ -319,7 +319,7 @@ | |||||||
| 			<Tool | 			<Tool | ||||||
| 				Name="VCLinkerTool" | 				Name="VCLinkerTool" | ||||||
| 				AdditionalOptions="/MACHINE:I386" | 				AdditionalOptions="/MACHINE:I386" | ||||||
| 				AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj" | 				AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj ..\JIT\natives-x86.obj" | ||||||
| 				OutputFile="jitdebug/amxmodx_mm.dll" | 				OutputFile="jitdebug/amxmodx_mm.dll" | ||||||
| 				Version="0.1" | 				Version="0.1" | ||||||
| 				LinkIncremental="1" | 				LinkIncremental="1" | ||||||
| @@ -659,6 +659,9 @@ | |||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\modules.cpp"> | 				RelativePath="..\modules.cpp"> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath="..\natives.cpp"> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\newmenus.cpp"> | 				RelativePath="..\newmenus.cpp"> | ||||||
| 			</File> | 			</File> | ||||||
| @@ -772,6 +775,9 @@ | |||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\CQueue.h"> | 				RelativePath="..\CQueue.h"> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath="..\CStack.h"> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\CString.h"> | 				RelativePath="..\CString.h"> | ||||||
| 			</File> | 			</File> | ||||||
| @@ -796,6 +802,9 @@ | |||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\modules.h"> | 				RelativePath="..\modules.h"> | ||||||
| 			</File> | 			</File> | ||||||
|  | 			<File | ||||||
|  | 				RelativePath="..\natives.h"> | ||||||
|  | 			</File> | ||||||
| 			<File | 			<File | ||||||
| 				RelativePath="..\newmenus.h"> | 				RelativePath="..\newmenus.h"> | ||||||
| 			</File> | 			</File> | ||||||
|   | |||||||
							
								
								
									
										85
									
								
								amxmodx/natives-amd64.asm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										85
									
								
								amxmodx/natives-amd64.asm
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
|  | ; (C)2005 by David "BAILOPAN" Anderson			 ; | ||||||
|  | ; register_native functions for amd64			 ;;;;;; | ||||||
|  | ; Based on the concept by Julien "dJeyL" Laurent	  ; | ||||||
|  | ; Thanks to T(+)rget for pushing me to implement this ; | ||||||
|  | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
|  |  | ||||||
|  | ;;Licensed under the GNU General Public License, version 2 | ||||||
|  | ;;This is a portion of AMX Mod X  | ||||||
|  | ;; and is maintained by the AMX Mod X development team. | ||||||
|  |  | ||||||
|  | ;;Initializes the global variable | ||||||
|  |  | ||||||
|  | BITS 64 | ||||||
|  |  | ||||||
|  | section .text | ||||||
|  |  | ||||||
|  | global amxx_DynaInit, _amxx_DynaInit | ||||||
|  | ;void amxx_DynaInit(void *ptr); | ||||||
|  | amxx_DynaInit: | ||||||
|  | _amxx_DynaInit: | ||||||
|  | 	mov		rax, rdi			;get pointer, first param is in rdi | ||||||
|  | 	mov		[GLOBAL_GATE], rax	;store | ||||||
|  | 	 | ||||||
|  | 	mov		rax, 1 | ||||||
|  | 	ret | ||||||
|  | 	 | ||||||
|  | ;;Assembles the gateway function | ||||||
|  | global amxx_DynaMake, _amxx_DynaMake | ||||||
|  | ;int amxx_DynaMake(char *buffer, int id); | ||||||
|  | amxx_DynaMake: | ||||||
|  | _amxx_DynaMake: | ||||||
|  | 	;we're not damaging the stack I think so we should be safe with no prologue | ||||||
|  | 	 | ||||||
|  | 	;save these two we're about to destroy them | ||||||
|  | 	push	rsi		;push id | ||||||
|  | 	push	rdi		;push buffer | ||||||
|  | 	 | ||||||
|  | 	mov		rsi, _amxx_DynaFuncStart | ||||||
|  | 	mov		rcx, _amxx_DynaFuncEnd - _amxx_DynaFuncStart | ||||||
|  | 	cld		;clear direction flag (just in case) | ||||||
|  | 	rep		movsb | ||||||
|  | 	 | ||||||
|  | 	pop		rdi		;get buffer as destination | ||||||
|  | 	pop		rax		;get id | ||||||
|  | 	;align us to mov rsi, 1234... - on x86-64 this is 2 bytes after the differential | ||||||
|  | 	add		rdi, (_amxx_DynaMoveOffset-_amxx_DynaFuncStart) + 2 | ||||||
|  | 	mov		[rdi], qword rax | ||||||
|  | 	 | ||||||
|  | 	mov		rax, 1 | ||||||
|  | 	ret | ||||||
|  |  | ||||||
|  | ;;The gateway function we will re-assemble | ||||||
|  | ;; This is similar to dJeyL's but a tad more elegant, as it's written in pure assembly | ||||||
|  | ;; and NASM > GAS :') | ||||||
|  | global amxx_DynaFunc, _amxx_DynaFunc | ||||||
|  | ;int amxx_DynaFunc(AMX *amx, cell *params); | ||||||
|  | amxx_DynaFunc: | ||||||
|  | _amxx_DynaFunc: | ||||||
|  | _amxx_DynaFuncStart: | ||||||
|  | 	push	rbp | ||||||
|  | 	mov		rbp, rsp | ||||||
|  | 	 | ||||||
|  | 	;we're given an amx and params... we're also hardcoded for this though: | ||||||
|  | 	mov		rdx, rsi	;move 2nd param to 3rd  | ||||||
|  | 	mov		rsi, rdi	;move 1st param to 2nd | ||||||
|  | 	;this old trick, we'll move in the real pointer in a bit. | ||||||
|  | _amxx_DynaMoveOffset: | ||||||
|  | 	mov		rsi, qword 1234567812345678h | ||||||
|  | 	call	[GLOBAL_GATE]		;pass through teh global gateway. | ||||||
|  | 	 | ||||||
|  | 	pop		rbp | ||||||
|  | 	ret | ||||||
|  | _amxx_DynaFuncEnd: | ||||||
|  |  | ||||||
|  | ;;Just returns the buffer size required | ||||||
|  | global _amxx_DynaCodesize, amxx_DynaCodesize | ||||||
|  | ;int amxx_DynaCodesize() | ||||||
|  | amxx_DynaCodesize: | ||||||
|  | _amxx_DynaCodesize: | ||||||
|  | 	; on x86 is this 17 bytes | ||||||
|  | 	mov		rax, _amxx_DynaFuncEnd - _amxx_DynaFuncStart | ||||||
|  | 	ret | ||||||
|  | 	 | ||||||
|  | GLOBAL_GATE		DQ		0 | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
| ; (C)2005 by David "BAILOPAN" Anderson 			 ; | ; (C)2005 by David "BAILOPAN" Anderson			 ; | ||||||
| ; register_native functions for x86    			 ;;;;;; | ; register_native functions for x86				 ;;;;;; | ||||||
| ; Based on the concept by Julien "dJeyL" Laurent      ; | ; Based on the concept by Julien "dJeyL" Laurent	  ; | ||||||
| ; Thanks to T(+)rget for pushing me to implement this ; | ; Thanks to T(+)rget for pushing me to implement this ; | ||||||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
|  |  | ||||||
| @@ -11,6 +11,8 @@ | |||||||
|  |  | ||||||
| ;;Initializes the global variable | ;;Initializes the global variable | ||||||
|  |  | ||||||
|  | section .text | ||||||
|  |  | ||||||
| global amxx_DynaInit, _amxx_DynaInit | global amxx_DynaInit, _amxx_DynaInit | ||||||
| ;void amxx_DynaInit(void *ptr); | ;void amxx_DynaInit(void *ptr); | ||||||
| amxx_DynaInit: | amxx_DynaInit: | ||||||
| @@ -43,8 +45,8 @@ _amxx_DynaMake: | |||||||
| 	rep		movsb | 	rep		movsb | ||||||
| 	 | 	 | ||||||
| 	mov		edi, [ebp+8]	;get buffer again | 	mov		edi, [ebp+8]	;get buffer again | ||||||
| 	;align us to mov eax, 1234 | 	;align us to mov eax, 1234 - on x86 this is 4 bytes | ||||||
| 	add		edi, _amxx_DynaMoveOffset + 1 | 	add		edi, (_amxx_DynaMoveOffset-_amxx_DynaFuncStart) + 1 | ||||||
| 	mov		eax, [ebp+12] | 	mov		eax, [ebp+12] | ||||||
| 	mov		[edi], eax | 	mov		[edi], eax | ||||||
| 	 | 	 | ||||||
| @@ -73,6 +75,7 @@ _amxx_DynaMoveOffset: | |||||||
| 	push	dword [ebp+8]		;push amx | 	push	dword [ebp+8]		;push amx | ||||||
| 	push	eax					;push the id | 	push	eax					;push the id | ||||||
| 	call	[GLOBAL_GATE]		;pass through teh global gateway. | 	call	[GLOBAL_GATE]		;pass through teh global gateway. | ||||||
|  | 	add		esp, 12				;reset stack oops | ||||||
| 	 | 	 | ||||||
| 	pop		ebp | 	pop		ebp | ||||||
| 	ret | 	ret | ||||||
| @@ -86,6 +89,7 @@ _amxx_DynaCodesize: | |||||||
| 	push	ebp | 	push	ebp | ||||||
| 	mov		ebp, esp | 	mov		ebp, esp | ||||||
| 	 | 	 | ||||||
|  | 	; on x86 is this 17 bytes | ||||||
| 	mov		eax, _amxx_DynaFuncEnd - _amxx_DynaFuncStart | 	mov		eax, _amxx_DynaFuncEnd - _amxx_DynaFuncStart | ||||||
| 	 | 	 | ||||||
| 	pop		ebp | 	pop		ebp | ||||||
|   | |||||||
							
								
								
									
										397
									
								
								amxmodx/natives.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										397
									
								
								amxmodx/natives.cpp
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,397 @@ | |||||||
|  | #include "amxmodx.h" | ||||||
|  | #include "CStack.h" | ||||||
|  | #include "natives.h" | ||||||
|  |  | ||||||
|  | CVector<regnative *> g_RegNatives; | ||||||
|  | CStack<regnative *> g_NativeStack; | ||||||
|  | CVector<String> g_Libraries; | ||||||
|  | static char g_errorStr[512] = {0}; | ||||||
|  | static int g_errorNum = 0; | ||||||
|  | bool g_Initialized = false; | ||||||
|  |  | ||||||
|  | int amxx_DynaCallback(int idx, AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (idx < 0 || idx >= (int)g_RegNatives.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Invalid dynamic native called"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	regnative *pNative = g_RegNatives[idx]; | ||||||
|  | 	int numParams = params[0] / sizeof(cell); | ||||||
|  |  | ||||||
|  | 	if (numParams > CALLFUNC_MAXPARAMS) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Called dynanative with too many parameters (%d)", CALLFUNC_MAXPARAMS); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	//parameter stack | ||||||
|  | 	pNative->caller = amx; | ||||||
|  |  | ||||||
|  | 	CPluginMngr::CPlugin *pPlugin = g_plugins.findPluginFast(amx); | ||||||
|  |  | ||||||
|  | 	int err = 0; | ||||||
|  | 	cell ret = 0; | ||||||
|  | 	g_errorNum = 0; | ||||||
|  | 	g_NativeStack.push(pNative); | ||||||
|  | 	if (pNative->style == 0) | ||||||
|  | 	{ | ||||||
|  | 		amx_Push(pNative->amx, numParams); | ||||||
|  | 		amx_Push(pNative->amx, pPlugin->getId()); | ||||||
|  | 		for (int i=numParams; i>=1; i--) | ||||||
|  | 			pNative->params[i] = params[i]; | ||||||
|  | 	} else if (pNative->style == 1) { | ||||||
|  | 		//use dJeyL's system .. very clever! | ||||||
|  | 		for (int i=numParams; i>=1; i--) | ||||||
|  | 			amx_Push(pNative->amx, params[i]); | ||||||
|  | 	} | ||||||
|  | 	if ( (err=amx_Exec(pNative->amx, &ret, pNative->func)) != AMX_ERR_NONE) | ||||||
|  | 	{ | ||||||
|  | 		g_NativeStack.pop(); | ||||||
|  | 		LogError(pNative->amx, err, ""); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	if (g_errorNum) | ||||||
|  | 	{ | ||||||
|  | 		g_NativeStack.pop(); | ||||||
|  | 		LogError(amx, g_errorNum, g_errorStr); | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | 	g_NativeStack.pop(); | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AMX_NATIVE_INFO *BuildNativeTable() | ||||||
|  | { | ||||||
|  | 	if (g_RegNatives.size() < 1) | ||||||
|  | 		return NULL; | ||||||
|  |  | ||||||
|  | 	AMX_NATIVE_INFO *pNatives = new AMX_NATIVE_INFO[g_RegNatives.size() + 1]; | ||||||
|  |  | ||||||
|  | 	AMX_NATIVE_INFO info; | ||||||
|  | 	regnative *pNative; | ||||||
|  | 	for (size_t i=0; i<g_RegNatives.size(); i++) | ||||||
|  | 	{ | ||||||
|  | 		pNative = g_RegNatives[i]; | ||||||
|  | 		info.name = pNative->name.c_str(); | ||||||
|  | 		info.func = reinterpret_cast<AMX_NATIVE>(pNative->pfn); | ||||||
|  | 		pNatives[i] = info; | ||||||
|  | 	} | ||||||
|  | 	pNatives[g_RegNatives.size()].name = NULL; | ||||||
|  | 	pNatives[g_RegNatives.size()].func = NULL; | ||||||
|  |  | ||||||
|  | 	//this needs to be deleted | ||||||
|  | 	return pNatives; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static cell AMX_NATIVE_CALL log_error(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	int len; | ||||||
|  | 	char *err = format_amxstring(amx, params, 2, len); | ||||||
|  |  | ||||||
|  | 	_snprintf(g_errorStr, sizeof(g_errorStr), "%s", err); | ||||||
|  | 	g_errorNum = params[1]; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //get_string(param, dest[], len) | ||||||
|  | static cell AMX_NATIVE_CALL get_string(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	int len; | ||||||
|  | 	char *str = get_amxstring(pNative->caller, pNative->params[p], 0, len); | ||||||
|  | 	return set_amxstring(amx, params[2], str, params[3]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //set_string(param, source[], maxlen) | ||||||
|  | static cell AMX_NATIVE_CALL set_string(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	int len; | ||||||
|  | 	char *str = get_amxstring(amx, params[2], 0, len); | ||||||
|  |  | ||||||
|  | 	return set_amxstring(pNative->caller, pNative->params[p], str, params[3]); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //get a byvalue parameter | ||||||
|  | //get_param(num) | ||||||
|  | static cell AMX_NATIVE_CALL get_param(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	return pNative->params[p]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //get_param_byref(num) | ||||||
|  | static cell AMX_NATIVE_CALL get_param_byref(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	cell *addr = get_amxaddr(pNative->caller, pNative->params[p]); | ||||||
|  |  | ||||||
|  | 	return addr[0]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //set_param_byref(num, val) | ||||||
|  | static cell AMX_NATIVE_CALL set_param_byref(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	cell *addr = get_amxaddr(pNative->caller, pNative->params[p]); | ||||||
|  |  | ||||||
|  | 	addr[0] = params[2]; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //get_array(param, dest[], size) | ||||||
|  | static cell AMX_NATIVE_CALL get_array(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	cell *source = get_amxaddr(pNative->caller, pNative->params[p]); | ||||||
|  | 	cell *dest = get_amxaddr(amx, params[2]); | ||||||
|  |  | ||||||
|  | 	int size = params[3]; | ||||||
|  |  | ||||||
|  | 	while (size-->0) | ||||||
|  | 		*dest = *source; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //set_array(param, source[], size) | ||||||
|  | static cell AMX_NATIVE_CALL set_array(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	int p = params[1]; | ||||||
|  |  | ||||||
|  | 	cell *dest = get_amxaddr(pNative->caller, pNative->params[p]); | ||||||
|  | 	cell *source = get_amxaddr(amx, params[2]); | ||||||
|  |  | ||||||
|  | 	int size = params[3]; | ||||||
|  |  | ||||||
|  | 	while (size-->0) | ||||||
|  | 		*dest = *source; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //This is basically right from dJeyL's lib_convert function | ||||||
|  | //This awesome hack modifies the stack frame to have an address offset | ||||||
|  | // that will align to the other plugin's memory. | ||||||
|  | //I've no idea how he thought of this, but it's great.  No idea how well it works. | ||||||
|  | static cell AMX_NATIVE_CALL param_convert(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_NativeStack.size()) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Not currently in a dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	regnative *pNative = g_NativeStack.top(); | ||||||
|  | 	if (pNative->style != 1) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, AMX_ERR_NATIVE, "Wrong style of dynamic native"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	cell p = params[1]; | ||||||
|  |  | ||||||
|  | 	AMX *caller = pNative->caller; | ||||||
|  |  | ||||||
|  | 	unsigned char *data =amx->base+(int)((AMX_HEADER *)amx->base)->dat; | ||||||
|  | 	unsigned char *realdata = caller->base+(int)((AMX_HEADER *)caller->base)->dat; | ||||||
|  |  | ||||||
|  | 	* (cell *)(data+(int)amx->frm+(p+2)*sizeof(cell)) -= (cell)data-(cell)realdata; | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static cell AMX_NATIVE_CALL register_library(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	int len; | ||||||
|  | 	char *lib = get_amxstring(amx, params[1], 0, len); | ||||||
|  |  | ||||||
|  | 	AddPluginLibrary(lib); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //register_native(const name[], const handler[]) | ||||||
|  | static cell AMX_NATIVE_CALL register_native(AMX *amx, cell *params) | ||||||
|  | { | ||||||
|  | 	if (!g_Initialized) | ||||||
|  | 		amxx_DynaInit(static_cast<void *>(amxx_DynaCallback)); | ||||||
|  |  | ||||||
|  | 	g_Initialized = true; | ||||||
|  |  | ||||||
|  | 	int len; | ||||||
|  | 	char *name = get_amxstring(amx, params[1], 0, len); | ||||||
|  | 	char *func = get_amxstring(amx, params[2], 1, len); | ||||||
|  |  | ||||||
|  | 	int idx, err; | ||||||
|  | 	if ( (err=amx_FindPublic(amx, func, &idx)) != AMX_ERR_NONE) | ||||||
|  | 	{ | ||||||
|  | 		LogError(amx, err, "Function \"%s\" was not found", func); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	regnative *pNative = new regnative; | ||||||
|  | 	pNative->amx = amx; | ||||||
|  | 	pNative->func = idx; | ||||||
|  | 	 | ||||||
|  | 	//we'll apply a safety buffer too | ||||||
|  | 	//make our function | ||||||
|  | 	int size = amxx_DynaCodesize(); | ||||||
|  | #ifndef __linux__ | ||||||
|  | 	DWORD temp; | ||||||
|  | 	pNative->pfn = new char[size + 10]; | ||||||
|  | 	VirtualProtect(pNative->pfn, size+10, PAGE_EXECUTE_READWRITE, &temp); | ||||||
|  | #else | ||||||
|  | 	pNative->pfn = (unsigned char *)memalign(sysconf(_SC_PAGESIZE), amx->code_size); | ||||||
|  | 	mprotect((void *)pNative->pfn, size+10, PROT_READ|PROT_WRITE|PROT_EXEC); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	int id = (int)g_RegNatives.size(); | ||||||
|  | 	 | ||||||
|  | 	amxx_DynaMake(pNative->pfn, id); | ||||||
|  | 	pNative->func = idx; | ||||||
|  | 	pNative->style = params[3]; | ||||||
|  |  | ||||||
|  | 	g_RegNatives.push_back(pNative); | ||||||
|  |  | ||||||
|  | 	pNative->name.assign(name); | ||||||
|  |  | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool LibraryExists(const char *name) | ||||||
|  | { | ||||||
|  | 	for (size_t i=0; i<g_Libraries.size(); i++) | ||||||
|  | 	{ | ||||||
|  | 		if (stricmp(g_Libraries[i].c_str(), name)==0) | ||||||
|  | 			return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AddPluginLibrary(const char *name) | ||||||
|  | { | ||||||
|  | 	String f(name); | ||||||
|  | 	g_Libraries.push_back(f); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ClearPluginLibraries() | ||||||
|  | { | ||||||
|  | 	g_Libraries.clear(); | ||||||
|  |  | ||||||
|  | 	for (size_t i=0; i<g_RegNatives.size(); i++) | ||||||
|  | 	{ | ||||||
|  | 		delete g_RegNatives[i]->pfn; | ||||||
|  | 		delete g_RegNatives[i]; | ||||||
|  | 	} | ||||||
|  | 	g_RegNatives.clear(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AMX_NATIVE_INFO g_NativeNatives[] = { | ||||||
|  | 	{"register_native",	register_native}, | ||||||
|  | 	{"log_error",		log_error}, | ||||||
|  | 	{"register_library",register_library}, | ||||||
|  | 	{"get_string",		get_string}, | ||||||
|  | 	{"set_string",		set_string}, | ||||||
|  | 	{"get_param",		get_param}, | ||||||
|  | 	{"get_param_byref",	get_param_byref}, | ||||||
|  | 	{"set_param_byref",	set_param_byref}, | ||||||
|  | 	{"get_array",		set_array}, | ||||||
|  | 	{"set_array",		set_array}, | ||||||
|  | 	//these are dummy functions for floats ;p | ||||||
|  | 	{"get_param_f",		get_param}, | ||||||
|  | 	{"get_float_byref",	get_param_byref}, | ||||||
|  | 	{"set_float_byref", set_param_byref}, | ||||||
|  | 	{"get_array_f",		get_array}, | ||||||
|  | 	{"set_array_f",		set_array}, | ||||||
|  | 	{"param_convert",	param_convert}, | ||||||
|  | 	////////////////////////// | ||||||
|  | 	{NULL,				NULL}, | ||||||
|  | }; | ||||||
							
								
								
									
										39
									
								
								amxmodx/natives.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										39
									
								
								amxmodx/natives.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | #ifndef _INCLUDE_NATIVES_H | ||||||
|  | #define _INCLUDE_NATIVES_H | ||||||
|  |  | ||||||
|  | //only 16 for now sorry | ||||||
|  | #define CALLFUNC_MAXPARAMS 16 | ||||||
|  |  | ||||||
|  | #define CALLFUNC_FLAG_BYREF			1 | ||||||
|  | #define CALLFUNC_FLAG_BYREF_REUSED	2 | ||||||
|  |  | ||||||
|  | #define N_CELL		1 | ||||||
|  | #define	N_ARRAY		2 | ||||||
|  | #define N_BYREF		3 | ||||||
|  | #define	N_VARARG	4 | ||||||
|  |  | ||||||
|  | struct regnative | ||||||
|  | { | ||||||
|  | 	AMX *amx; | ||||||
|  | 	String name; | ||||||
|  | 	char *pfn; | ||||||
|  | 	int func; | ||||||
|  | 	AMX *caller; | ||||||
|  | 	int style; | ||||||
|  | 	cell params[CALLFUNC_MAXPARAMS]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | extern "C" void amxx_DynaInit(void *ptr); | ||||||
|  | extern "C" void amxx_DynaMake(char *buffer, int id); | ||||||
|  | extern "C" int amxx_DynaFunc(AMX *amx, cell *params); | ||||||
|  | extern "C" int amxx_DynaCodesize(); | ||||||
|  |  | ||||||
|  | AMX_NATIVE_INFO *BuildNativeTable(); | ||||||
|  | void AddPluginLibrary(const char *name); | ||||||
|  | void ClearPluginLibraries(); | ||||||
|  | bool LibraryExists(const char *name); | ||||||
|  |  | ||||||
|  | //I couldn't resist :) | ||||||
|  | extern AMX_NATIVE_INFO g_NativeNatives[]; | ||||||
|  |  | ||||||
|  | #endif //_INCLUDE_NATIVES_H | ||||||
		Reference in New Issue
	
	Block a user