Committed new register_native system
This commit is contained in:
parent
34acc54cc9
commit
abfca025d5
|
@ -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,6 +1747,7 @@ 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_PRENIT))
|
||||||
if ((amx->flags & AMX_FLAG_NTVREG)==0)
|
if ((amx->flags & AMX_FLAG_NTVREG)==0)
|
||||||
return AMX_ERR_NOTFOUND;
|
return AMX_ERR_NOTFOUND;
|
||||||
if ((amx->flags & AMX_FLAG_RELOC)==0)
|
if ((amx->flags & AMX_FLAG_RELOC)==0)
|
||||||
|
@ -2678,6 +2679,7 @@ 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_PRENIT))
|
||||||
if ((amx->flags & AMX_FLAG_NTVREG)==0)
|
if ((amx->flags & AMX_FLAG_NTVREG)==0)
|
||||||
return AMX_ERR_NOTFOUND;
|
return AMX_ERR_NOTFOUND;
|
||||||
if ((amx->flags & AMX_FLAG_RELOC)==0)
|
if ((amx->flags & AMX_FLAG_RELOC)==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;
|
amx->flags &= ~(AMX_FLAG_PRENIT);
|
||||||
}
|
|
||||||
|
|
||||||
return (amx->error = AMX_ERR_NATIVE);
|
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
|
|
@ -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
|
Loading…
Reference in New Issue
Block a user