Whoa! Merged in Pawn! (Small 3.0)

Removed debug handling (will add back in soon)
Ported all amx_Exec()s to forward systems
Deprecated AMX Mod module support (incompatible with Pawn anyway!)
Deprecated many file natives (unused)
Deprecated some functionality of pause/unpause
Fixed some memory deallocation bugs (thanks fysh)
Bumped module API version to 3 (no new M/SDK yet!)
Bumped AMX Mod X version to 1.5!
Merged in CVector changes
This commit is contained in:
David Anderson 2005-07-25 06:03:43 +00:00
parent 955aa04b41
commit 4609cb409b
32 changed files with 1501 additions and 2582 deletions

View File

@ -396,17 +396,11 @@ void EventsMngr::parseValue(const char *sz)
void EventsMngr::executeEvents() void EventsMngr::executeEvents()
{ {
int err;
if (!m_ParseFun) if (!m_ParseFun)
{ {
return; return;
} }
#ifdef ENABLEEXEPTIONS
try
{
#endif // #ifdef ENABLEEXEPTIONS
for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter) for (ClEventVecIter iter = m_ParseFun->begin(); iter; ++iter)
{ {
if ( (*iter).m_Done ) if ( (*iter).m_Done )
@ -414,22 +408,9 @@ void EventsMngr::executeEvents()
(*iter).m_Done = false; (*iter).m_Done = false;
continue; continue;
} }
(*iter).m_Stamp = (float)*m_Timer; (*iter).m_Stamp = (float)*m_Timer;
executeForwards((*iter).m_Func, m_ParseVault ? m_ParseVault[0].iValue : 0);
if ((err = amx_Exec((*iter).m_Plugin->getAMX(), NULL, (*iter).m_Func, 1, m_ParseVault ? m_ParseVault[0].iValue : 0)) != AMX_ERR_NONE)
{
LogError((*iter).m_Plugin->getAMX(), err, "");
} }
}
#ifdef ENABLEEXEPTIONS
}
catch( ... )
{
AMXXLOG_Log( "[AMXX] fatal error at event execution");
}
#endif // #ifdef ENABLEEXEPTIONS
m_CurrentMsgType = -1; m_CurrentMsgType = -1;
m_ParseFun = NULL; m_ParseFun = NULL;

View File

@ -71,7 +71,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
if (iter->pPlugin->isExecutable(iter->func)) if (iter->pPlugin->isExecutable(iter->func))
{ {
// handle strings & arrays // handle strings & arrays
int i; int i, ax=0;
for (i = 0; i < m_NumParams; ++i) for (i = 0; i < m_NumParams; ++i)
{ {
if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX) if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX)
@ -80,7 +80,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
amx_Allot(iter->pPlugin->getAMX(), amx_Allot(iter->pPlugin->getAMX(),
(m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast<const char*>(params[i]))+1 : STRINGEX_MAXLENGTH, (m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast<const char*>(params[i]))+1 : STRINGEX_MAXLENGTH,
&realParams[i], &tmp); &realParams[i], &tmp);
amx_SetString(tmp, (const char *)(params[i]), 0, 0); amx_SetStringOld(tmp, (const char *)(params[i]), 0, 0);
physAddrs[i] = tmp; physAddrs[i] = tmp;
} }
else if (m_ParamTypes[i] == FP_ARRAY) else if (m_ParamTypes[i] == FP_ARRAY)
@ -105,9 +105,14 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
realParams[i] = params[i]; realParams[i] = params[i];
} }
} }
//Push the parameters in reverse order. Weird, unfriendly part of Small 3.0!
for (i=m_NumParams-1; i>=0; i--)
{
amx_Push(iter->pPlugin->getAMX(), realParams[i]);
}
// exec // exec
cell retVal; cell retVal;
int err = amx_Execv(iter->pPlugin->getAMX(), &retVal, iter->func, m_NumParams, realParams); int err = amx_Exec(iter->pPlugin->getAMX(), &retVal, iter->func);
// log runtime error, if any // log runtime error, if any
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
LogError(iter->pPlugin->getAMX(), err, ""); LogError(iter->pPlugin->getAMX(), err, "");
@ -122,7 +127,7 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
else if (m_ParamTypes[i] == FP_STRINGEX) else if (m_ParamTypes[i] == FP_STRINGEX)
{ {
// copy back // copy back
amx_GetString(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
amx_Release(iter->pPlugin->getAMX(), realParams[i]); amx_Release(iter->pPlugin->getAMX(), realParams[i]);
} }
else if (m_ParamTypes[i] == FP_ARRAY) else if (m_ParamTypes[i] == FP_ARRAY)
@ -216,7 +221,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
amx_Allot(m_Amx, amx_Allot(m_Amx,
(m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast<const char*>(params[i]))+1 : STRINGEX_MAXLENGTH, (m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast<const char*>(params[i]))+1 : STRINGEX_MAXLENGTH,
&realParams[i], &tmp); &realParams[i], &tmp);
amx_SetString(tmp, (const char *)(params[i]), 0, 0); amx_SetStringOld(tmp, (const char *)(params[i]), 0, 0);
physAddrs[i] = tmp; physAddrs[i] = tmp;
} }
else if (m_ParamTypes[i] == FP_ARRAY) else if (m_ParamTypes[i] == FP_ARRAY)
@ -241,10 +246,11 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
realParams[i] = params[i]; realParams[i] = params[i];
} }
} }
for (i=m_NumParams-1; i>=0; i--)
amx_Push(m_Amx, realParams[i]);
// exec // exec
cell retVal; cell retVal;
int err = amx_Execv(m_Amx, &retVal, m_Func, m_NumParams, realParams); int err = amx_Exec(m_Amx, &retVal, m_Func);
// log runtime error, if any // log runtime error, if any
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)
@ -260,7 +266,7 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
else if (m_ParamTypes[i] == FP_STRINGEX) else if (m_ParamTypes[i] == FP_STRINGEX)
{ {
// copy back // copy back
amx_GetString(reinterpret_cast<char*>(params[i]), physAddrs[i], 0); amx_GetStringOld(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
amx_Release(m_Amx, realParams[i]); amx_Release(m_Amx, realParams[i]);
} }
else if (m_ParamTypes[i] == FP_ARRAY) else if (m_ParamTypes[i] == FP_ARRAY)

View File

@ -151,7 +151,6 @@ LogEventsMngr::CLogEvent* LogEventsMngr::registerLogEvent( CPluginMngr::CPlugin*
void LogEventsMngr::executeLogEvents() void LogEventsMngr::executeLogEvents()
{ {
int err;
bool valid; bool valid;
for(CLogEvent* a = logevents[ logArgc ]; a ; a = a->next) for(CLogEvent* a = logevents[ logArgc ]; a ; a = a->next)
{ {
@ -171,8 +170,7 @@ void LogEventsMngr::executeLogEvents()
if (valid) if (valid)
{ {
if ((err = amx_Exec(a->plugin->getAMX(), NULL , a->func , 0)) != AMX_ERR_NONE) executeForwards(a->func);
LogError(a->plugin->getAMX(), err, "");
} }
} }
} }

View File

@ -51,7 +51,7 @@ MenuMngr::~MenuMngr()
int MenuMngr::findMenuId(const char* name, AMX* amx) int MenuMngr::findMenuId(const char* name, AMX* amx)
{ {
for( MenuIdEle* b = headid; b ; b = b->next) { for( MenuIdEle* b = headid; b ; b = b->next) {
if ( (!b->amx || amx == b->amx) && strstr(name,b->name.c_str()) ) if ( (!amx || !b->amx || amx == b->amx) && strstr(name,b->name.c_str()) )
return b->id; return b->id;
} }
return 0; return 0;

View File

@ -35,11 +35,6 @@
#define FAR #define FAR
#endif #endif
// Old
typedef int (FAR *QUERYMOD)(module_info_s**);
typedef int (FAR *ATTACHMOD)(pfnamx_engine_g*,pfnmodule_engine_g*);
typedef int (FAR *DETACHMOD)(void);
// New // New
typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/); typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/);
typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/); typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo*/);
@ -47,81 +42,6 @@ typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/);
typedef int (FAR *DETACHMOD_NEW)(void); typedef int (FAR *DETACHMOD_NEW)(void);
typedef void (FAR *PLUGINSLOADED_NEW)(void); typedef void (FAR *PLUGINSLOADED_NEW)(void);
// Old
// These functions are needed since Small Abstract Machine 2.5.0
int wamx_FindPublic(AMX *amx, char *name, int *index)
{ return amx_FindPublic(amx, name, index); }
int wamx_FindPubVar(AMX *amx, char *varname, cell *amx_addr)
{ return amx_FindPubVar(amx, varname, amx_addr); }
int wamx_GetString(char *dest, cell *source)
{ return amx_GetString(dest, source, 0); }
AMX_NATIVE_INFO *wamx_NativeInfo(char *name, AMX_NATIVE func)
{ return amx_NativeInfo(name, func); }
int wamx_SetString(cell *dest, char *source, int pack)
{ return amx_SetString(dest, source, pack, 0); }
pfnamx_engine_g engAmxFunc = {
amx_Align16,
amx_Align32,
amx_Allot,
amx_Callback,
amx_Clone,
amx_Debug,
amx_Exec,
amx_Execv,
wamx_FindPublic,
wamx_FindPubVar,
amx_FindTagId,
amx_Flags,
amx_GetAddr,
amx_GetPublic,
amx_GetPubVar,
wamx_GetString,
amx_GetTag,
amx_GetUserData,
amx_Init,
amx_InitJIT,
amx_MemInfo,
amx_NameLength,
wamx_NativeInfo,
amx_NumPublics,
amx_NumPubVars,
amx_NumTags,
amx_RaiseError,
amx_Register,
amx_Release,
amx_SetCallback,
amx_SetDebugHook,
wamx_SetString,
amx_SetUserData,
amx_StrLen,
};
pfnmodule_engine_g engModuleFunc = {
add_amxnatives,
build_pathname,
copy_amxmemory,
format_amxstring,
get_amxaddr,
get_amxscript,
get_amxscriptname,
get_amxstring,
get_modname,
load_amxscript,
print_srvconsole,
report_error,
set_amxnatives,
set_amxstring,
amxstring_len,
unload_amxscript,
alloc_amxmemory,
free_amxmemory,
};
// ***************************************************** // *****************************************************
// class CModule // class CModule
// ***************************************************** // *****************************************************
@ -150,8 +70,6 @@ void CModule::clear(bool clearFilename)
if (clearFilename) if (clearFilename)
m_Filename.assign("unknown"); m_Filename.assign("unknown");
// old
m_InfoOld = NULL;
// new // new
m_Amxx = false; m_Amxx = false;
m_InfoNew.author = "unknown"; m_InfoNew.author = "unknown";
@ -220,17 +138,11 @@ bool CModule::attachModule()
m_Status = MODULE_BADLOAD; m_Status = MODULE_BADLOAD;
return false; return false;
} }
} else {
m_Status = MODULE_BADLOAD;
} }
else
{
// old
ATTACHMOD AttachFunc = (ATTACHMOD)DLPROC(m_Handle, "AMX_Attach");
if (AttachFunc) return false;
(*AttachFunc)(&engAmxFunc,&engModuleFunc);
m_Status = MODULE_LOADED;
return true;
}
} }
bool CModule::queryModule() bool CModule::queryModule()
@ -291,46 +203,11 @@ bool CModule::queryModule()
return true; return true;
} }
else else
{
// old interface not 64 bit compatible
#if SMALL_CELL_SIZE == 64
m_Status = MODULE_NOT64BIT;
return false;
#else
// Try old interface
QUERYMOD queryFunc_Old = (QUERYMOD)DLPROC(m_Handle,"AMX_Query"); // check what version
if (!queryFunc_Old)
{ {
m_Status = MODULE_NOQUERY; m_Status = MODULE_NOQUERY;
m_Amxx = false;
return false; return false;
} }
(*queryFunc_Old)(&m_InfoOld);
if (!m_InfoOld)
{
m_Status = MODULE_NOINFO;
return false;
}
if (m_InfoOld->ivers != AMX_INTERFACE_VERSION)
{
m_Status = MODULE_OLD;
return false;
}
// Check for attach
if (!DLPROC(m_Handle, "AMX_Attach"))
{
m_Status = MODULE_NOATTACH;
return false;
}
m_InfoOld->serial = (long int)this;
m_Status = MODULE_QUERY;
return true;
#endif
}
} }
bool CModule::detachModule() bool CModule::detachModule()
@ -350,12 +227,6 @@ bool CModule::detachModule()
g_ModuleCallReason = ModuleCall_NotCalled; g_ModuleCallReason = ModuleCall_NotCalled;
} }
} }
else
{
DETACHMOD detachFunc_Old = (DETACHMOD)DLPROC(m_Handle, "AMX_Detach");
if (detachFunc_Old)
(*detachFunc_Old)();
}
#ifndef FAKEMETA #ifndef FAKEMETA
if (IsMetamod()) if (IsMetamod())
{ {

View File

@ -66,14 +66,13 @@ struct amxx_module_info_s
#define AMXX_PARAM 2 /* Invalid parameter */ #define AMXX_PARAM 2 /* Invalid parameter */
#define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */ #define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */
#define AMXX_INTERFACE_VERSION 2 #define AMXX_INTERFACE_VERSION 3
class CModule class CModule
{ {
String m_Filename; // Filename String m_Filename; // Filename
bool m_Metamod; // Using metamod? bool m_Metamod; // Using metamod?
bool m_Amxx; // Using new module interface? bool m_Amxx; // Using new module interface?
module_info_s* m_InfoOld; // module info (old module interface)
amxx_module_info_s m_InfoNew; // module info (new module interface) amxx_module_info_s m_InfoNew; // module info (new module interface)
DLHANDLE m_Handle; // handle DLHANDLE m_Handle; // handle
MODULE_STATUS m_Status; // status MODULE_STATUS m_Status; // status
@ -93,14 +92,13 @@ public:
#endif #endif
const char* getStatus() const; const char* getStatus() const;
inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); } inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); }
inline const char* getAuthor() const { return m_Amxx ? (m_InfoNew.author) : (m_InfoOld ? m_InfoOld->author : "unknown"); } inline const char* getAuthor() const { return m_InfoNew.author; }
inline const char* getVersion() const { return m_Amxx ? (m_InfoNew.version) : (m_InfoOld ? m_InfoOld->version : "unknown"); } inline const char* getVersion() const { return m_InfoNew.version; }
inline const char* getName() const { return m_Amxx ? (m_InfoNew.name) : (m_InfoOld ? m_InfoOld->name : "unknown"); } inline const char* getName() const { return m_InfoNew.name; }
inline module_info_s* getInfo() const { return m_InfoOld; } // old
inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new inline const amxx_module_info_s* getInfoNew() const { return &m_InfoNew; } // new
inline int getStatusValue() { return m_Status; } inline int getStatusValue() { return m_Status; }
inline bool operator==( const char* fname ) { return !strcmp( m_Filename.c_str() , fname ); } inline bool operator==( const char* fname ) { return !strcmp( m_Filename.c_str() , fname ); }
inline bool isReloadable() { return m_Amxx ? ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)) : ( (m_Status==MODULE_LOADED) && (m_InfoOld->type==RELOAD_MODULE)); } inline bool isReloadable() { return ((m_Status == MODULE_LOADED) && (m_InfoNew.reload != 0)); }
inline bool isAmxx() const { return m_Amxx; } inline bool isAmxx() const { return m_Amxx; }
inline const char *getMissingFunc() const { return m_MissingFunc; } inline const char *getMissingFunc() const { return m_MissingFunc; }
inline const char *getFilename() { return m_Filename.c_str(); } inline const char *getFilename() { return m_Filename.c_str(); }

View File

@ -172,38 +172,12 @@ CPluginMngr::CPlugin::CPlugin(int i, const char* p,const char* n, char* e, int d
paused_fun = 0; paused_fun = 0;
next = 0; next = 0;
id = i; id = i;
m_PauseFwd = registerSPForwardByName(&amx, "plugin_pause");
m_UnpauseFwd = registerSPForwardByName(&amx, "plugin_unpause");
} }
CPluginMngr::CPlugin::~CPlugin( ) CPluginMngr::CPlugin::~CPlugin( )
{ {
AMX_DBG *pDbg = (AMX_DBG *)amx.userdata[0];
if (pDbg)
{
if (pDbg->files)
{
for (int i=0; i<pDbg->numFiles; i++)
{
if (pDbg->files[i])
{
free(pDbg->files[i]);
pDbg->files[i] = NULL;
}
}
free(pDbg->files);
}
AMX_TRACE *pTrace = pDbg->head;
AMX_TRACE *pNext = NULL;
while (pTrace)
{
pNext = pTrace->next;
free(pTrace);
pTrace = pNext;
}
free(pDbg);
amx.userdata[0] = NULL;
}
unload_amxscript( &amx, &code ); unload_amxscript( &amx, &code );
} }
@ -232,16 +206,8 @@ void CPluginMngr::CPlugin::pausePlugin()
if (isValid()) if (isValid())
{ {
// call plugin_pause if provided // call plugin_pause if provided
int func; if (m_PauseFwd != -1)
cell retval; executeForwards(m_PauseFwd);
if (amx_FindPublic(&amx, "plugin_pause", &func) == AMX_ERR_NONE)
{
if (isExecutable(func))
{
amx_Exec(&amx, &retval, func, 0);
}
}
setStatus(ps_paused); setStatus(ps_paused);
} }
@ -256,14 +222,7 @@ void CPluginMngr::CPlugin::unpausePlugin()
setStatus(ps_running); setStatus(ps_running);
// call plugin_unpause if provided // call plugin_unpause if provided
int func; if (m_UnpauseFwd != -1)
cell retval; executeForwards(m_UnpauseFwd);
if (amx_FindPublic(&amx, "plugin_unpause", &func) == AMX_ERR_NONE)
{
if (isExecutable(func))
{
amx_Exec(&amx, &retval, func, 0);
}
}
} }
} }

View File

@ -64,6 +64,8 @@ public:
String title; String title;
String author; String author;
String errorMsg; String errorMsg;
int m_PauseFwd;
int m_UnpauseFwd;
int paused_fun; int paused_fun;
int status; int status;
CPlugin* next; CPlugin* next;
@ -88,8 +90,8 @@ public:
inline void setError( const char* n ) { errorMsg.assign(n); } inline void setError( const char* n ) { errorMsg.assign(n); }
inline bool isValid() const { return ((status != ps_bad_load) && (status != ps_locked)); } inline bool isValid() const { return ((status != ps_bad_load) && (status != ps_locked)); }
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() && !isFunctionPaused(id)); } inline bool isExecutable(int id) const { return (isValid() && !isPaused()); }
void pausePlugin(); void pausePlugin();
void unpausePlugin(); void unpausePlugin();
void pauseFunction( int id ); void pauseFunction( int id );

View File

@ -48,7 +48,8 @@ template <class T> class CVector
return false; return false;
if (m_Data) if (m_Data)
{ {
memcpy(newData, m_Data, m_Size * sizeof(T)); for (size_t i=0; i<m_CurrentUsedSize; i++)
newData[i] = m_Data[i];
delete [] m_Data; delete [] m_Data;
} }
m_Data = newData; m_Data = newData;
@ -74,7 +75,9 @@ template <class T> class CVector
return false; return false;
if (m_Data) if (m_Data)
{ {
memcpy(newData, m_Data, (m_Size < size) ? (m_Size * sizeof(T)) : (size * sizeof(T))); size_t end = (m_Size < size) ? (m_Size) : size;
for (size_t i=0; i<end; i++)
newData[i] = m_Data[i];
delete [] m_Data; delete [] m_Data;
} }
if (m_Size < size) if (m_Size < size)
@ -251,10 +254,11 @@ public:
CVector<T>(const CVector<T> & other) CVector<T>(const CVector<T> & other)
{ {
// copy data // copy data
m_Data = new T [other.m_Size]; m_Data = new T [other.m_CurrentUsedSize];
m_Size = other.m_Size; m_Size = other.m_CurrentUsedSize;
m_CurrentUsedSize = other.m_CurrentUsedSize; m_CurrentUsedSize = other.m_CurrentUsedSize;
memcpy(m_Data, other.m_Data, m_CurrentUsedSize * sizeof(T)); for (size_t i=0; i<other.m_CurrentUsedSize; i++)
m_Data[i] = other.m_Data[i];
} }
~CVector<T>() ~CVector<T>()

BIN
amxmodx/JIT/amxexecn.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxexecn.obj Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxjitsn.o Executable file

Binary file not shown.

BIN
amxmodx/JIT/amxjitsn.obj Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* Abstract Machine for the Small compiler /* Pawn Abstract Machine (for the Pawn language)
* *
* Copyright (c) ITB CompuPhase, 1997-2004 * Copyright (c) ITB CompuPhase, 1997-2005
* *
* This software is provided "as-is", without any express or implied warranty. * This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from * In no event will the authors be held liable for any damages arising from
@ -21,20 +21,34 @@
* Version: $Id$ * Version: $Id$
*/ */
#if defined __linux__ #if defined FREEBSD && !defined __FreeBSD__
#define __FreeBSD__
#endif
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
#include <sclinux.h> #include <sclinux.h>
#endif #endif
#ifndef AMX_H_INCLUDED #ifndef AMX_H_INCLUDED
#define AMX_H_INCLUDED #define AMX_H_INCLUDED
#if defined __LCC__ || defined __DMC__ || defined __linux__ #if defined HAVE_STDINT_H
#include <stdint.h> #include <stdint.h>
#else
#if defined __LCC__ || defined __DMC__ || defined LINUX
#if defined HAVE_INTTYPES_H
#include <inttypes.h>
#else
#include <stdint.h>
#endif
#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
/* The ISO C99 defines the int16_t and int_32t types. If the compiler got /* The ISO C99 defines the int16_t and int_32t types. If the compiler got
* here, these types are probably undefined. * here, these types are probably undefined.
*/ */
#if defined __FreeBSD__ #if defined __MACH__
#include <ppc/types.h>
typedef unsigned short int uint16_t;
typedef unsigned long int uint32_t;
#elif defined __FreeBSD__
#include <inttypes.h> #include <inttypes.h>
#else #else
typedef short int int16_t; typedef short int int16_t;
@ -46,29 +60,59 @@
typedef long int int32_t; typedef long int int32_t;
typedef unsigned long int uint32_t; typedef unsigned long int uint32_t;
#endif #endif
// evilspy's fix for mingw #if defined __WIN32__ || defined _WIN32 || defined WIN32
#if defined __GNUC__
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define HAVE_I64
#elif defined __WIN32__ || defined _WIN32 || defined WIN32
typedef __int64 int64_t; typedef __int64 int64_t;
typedef unsigned __int64 uint64_t; typedef unsigned __int64 uint64_t;
#define HAVE_I64 #define HAVE_I64
#elif defined __GNUC__
typedef long long int64_t;
typedef unsigned long long uint64_t;
#define HAVE_I64
#endif #endif
#endif #endif
#endif #endif
#define HAVE_STDINT_H
#endif
#if defined _LP64 || defined WIN64 || defined _WIN64
#if !defined __64BIT__
#define __64BIT__
#endif
#endif
#if HAVE_ALLOCA_H
#include <alloca.h>
#endif
#if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */ #if defined __WIN32__ || defined _WIN32 || defined WIN32 /* || defined __MSDOS__ */
#if !defined alloca #if !defined alloca
#define alloca(n) _alloca(n) #define alloca(n) _alloca(n)
#endif #endif
#endif #endif
#if !defined arraysize
#define arraysize(array) (sizeof(array) / sizeof((array)[0]))
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if PAWN_CELL_SIZE==32
#define REAL float
#elif PAWN_CELL_SIZE==64
#define REAL double
#else
#error Unsupported cell size
#endif
#if defined PAWN_DLL
#if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL __stdcall
#endif
#if !defined AMXAPI
#define AMXAPI __stdcall
#endif
#endif
/* calling convention for native functions */ /* calling convention for native functions */
#if !defined AMX_NATIVE_CALL #if !defined AMX_NATIVE_CALL
#define AMX_NATIVE_CALL #define AMX_NATIVE_CALL
@ -79,6 +123,8 @@ extern "C" {
#define AMXAPI __stdcall #define AMXAPI __stdcall
#elif defined CDECL #elif defined CDECL
#define AMXAPI __cdecl #define AMXAPI __cdecl
#elif defined GCC_HASCLASSVISIBILITY
#define AMXAPI __attribute__ ((visibility("default")))
#else #else
#define AMXAPI #define AMXAPI
#endif #endif
@ -96,46 +142,36 @@ extern "C" {
* 5 (tagnames table) 4 * 5 (tagnames table) 4
* 6 (reformatted header) 6 * 6 (reformatted header) 6
* 7 (name table, opcodes SYMTAG & SYSREQ.D) 7 * 7 (name table, opcodes SYMTAG & SYSREQ.D) 7
* 8 (opcode STMT, renewed debug interface) 8
*/ */
#define CUR_FILE_VERSION 7 /* current file version; also the current AMX version */ #define CUR_FILE_VERSION 8 /* current file version; also the current AMX version */
#define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */ #define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */
#define MIN_AMX_VERSION 7 /* minimum AMX version needed to support the current file format */ #define MIN_AMX_VERSION 8 /* minimum AMX version needed to support the current file format */
#if defined BIT16 #if !defined PAWN_CELL_SIZE
#define SMALL_CELL_SIZE 16 /* for backward compatibility */ #define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */
#endif #endif
#if !defined SMALL_CELL_SIZE #if PAWN_CELL_SIZE==16
#define SMALL_CELL_SIZE 32 /* by default, use 32-bit cells */
#endif
#if SMALL_CELL_SIZE==16
typedef uint16_t ucell; typedef uint16_t ucell;
typedef int16_t cell; typedef int16_t cell;
#elif SMALL_CELL_SIZE==32 #elif PAWN_CELL_SIZE==32
typedef uint32_t ucell; typedef uint32_t ucell;
typedef int32_t cell; typedef int32_t cell;
#elif SMALL_CELL_SIZE==64 #elif PAWN_CELL_SIZE==64
typedef uint64_t ucell; typedef uint64_t ucell;
typedef int64_t cell; typedef int64_t cell;
#else #else
#error Unsupported cell size (SMALL_CELL_SIZE) #error Unsupported cell size (PAWN_CELL_SIZE)
#endif #endif
#if SMALL_CELL_SIZE==32 #define UNPACKEDMAX ((1L << (sizeof(cell)-1)*8) - 1)
#define REAL float #define UNLIMITED (~1u >> 1)
#elif SMALL_CELL_SIZE==64
#define REAL double
#else
#error Unsupported cell size
#endif
#define UNPACKEDMAX ((1 << (sizeof(cell)-1)*8) - 1)
struct tagAMX; struct tagAMX;
typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params); typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params);
typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index, typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index,
cell *result, cell *params); cell *result, cell *params);
typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx); typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx);
typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode);
#if !defined _FAR #if !defined _FAR
#define _FAR #define _FAR
#endif #endif
@ -149,7 +185,7 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode);
/* Some compilers do not support the #pragma align, which should be fine. Some /* Some compilers do not support the #pragma align, which should be fine. Some
* compilers give a warning on unknown #pragmas, which is not so fine... * compilers give a warning on unknown #pragmas, which is not so fine...
*/ */
#if defined SN_TARGET_PS2 || defined __GNUC__ #if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN
#define AMX_NO_ALIGN #define AMX_NO_ALIGN
#endif #endif
@ -160,8 +196,10 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode);
#endif #endif
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined __linux__ #if defined LINUX || defined __FreeBSD__
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
#elif defined MACOS && defined __MWERKS__
#pragma options align=mac68k
#else #else
#pragma pack(push) #pragma pack(push)
#pragma pack(1) /* structures must be packed (byte-aligned) */ #pragma pack(1) /* structures must be packed (byte-aligned) */
@ -171,10 +209,10 @@ typedef int (AMXAPI *AMX_DEBUGCALL)(struct tagAMX *amx, int mode);
#endif #endif
#endif #endif
typedef struct { typedef struct tagAMX_NATIVE_INFO {
const char _FAR *name PACKED; const char _FAR *name PACKED;
AMX_NATIVE func PACKED; AMX_NATIVE func PACKED;
} AMX_NATIVE_INFO; } PACKED AMX_NATIVE_INFO;
#define AMX_USERNUM 4 #define AMX_USERNUM 4
#define sEXPMAX 19 /* maximum name length for file version <= 6 */ #define sEXPMAX 19 /* maximum name length for file version <= 6 */
@ -182,14 +220,19 @@ typedef struct {
typedef struct tagAMX_FUNCSTUB { typedef struct tagAMX_FUNCSTUB {
ucell address PACKED; ucell address PACKED;
const char name[sEXPMAX+1] PACKED; char name[sEXPMAX+1] PACKED;
} AMX_FUNCSTUB; } PACKED AMX_FUNCSTUB;
typedef struct tagFUNCSTUBNT {
ucell address PACKED;
ucell nameofs PACKED; //we need this for amxx to be backwards comaptible
} PACKED AMX_FUNCSTUBNT;
/* The AMX structure is the internal structure for many functions. Not all /* The AMX structure is the internal structure for many functions. Not all
* fields are valid at all times; many fields are cached in local variables. * fields are valid at all times; many fields are cached in local variables.
*/ */
typedef struct tagAMX { typedef struct tagAMX {
unsigned char _FAR *base PACKED; /* points to the AMX header ("amxhdr") plus the code, optionally also the data */ unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */
unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */ unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */
AMX_CALLBACK callback PACKED; AMX_CALLBACK callback PACKED;
AMX_DEBUG debug PACKED; /* debug callback */ AMX_DEBUG debug PACKED; /* debug callback */
@ -201,18 +244,13 @@ typedef struct tagAMX {
cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */ cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */
cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */ cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */
int flags PACKED; /* current status, see amx_Flags() */ int flags PACKED; /* current status, see amx_Flags() */
/* for assertions and debug hook */
cell curline PACKED;
cell curfile PACKED;
int dbgcode PACKED;
cell dbgaddr PACKED;
cell dbgparam PACKED;
char _FAR *dbgname PACKED;
/* user data */ /* user data */
long usertags[AMX_USERNUM] PACKED; long usertags[AMX_USERNUM] PACKED;
void _FAR *userdata[AMX_USERNUM] PACKED; void _FAR *userdata[AMX_USERNUM] PACKED;
/* native functions can raise an error */ /* native functions can raise an error */
int error PACKED; int error PACKED;
/* passing parameters requires a "count" field */
int paramcount;
/* the sleep opcode needs to store the full AMX status */ /* the sleep opcode needs to store the full AMX status */
cell pri PACKED; cell pri PACKED;
cell alt PACKED; cell alt PACKED;
@ -222,7 +260,7 @@ typedef struct tagAMX {
/* support variables for the JIT */ /* support variables for the JIT */
int reloc_size PACKED; /* required temporary buffer for relocations */ int reloc_size PACKED; /* required temporary buffer for relocations */
long code_size PACKED; /* estimated memory footprint of the native code */ long code_size PACKED; /* estimated memory footprint of the native code */
} AMX; } PACKED AMX;
/* The AMX_HEADER structure is both the memory format as the file format. The /* The AMX_HEADER structure is both the memory format as the file format. The
* structure is used internaly. * structure is used internaly.
@ -244,27 +282,12 @@ typedef struct tagAMX_HEADER {
int32_t libraries PACKED; /* offset to the table of libraries */ int32_t libraries PACKED; /* offset to the table of libraries */
int32_t pubvars PACKED; /* the "public variables" table */ int32_t pubvars PACKED; /* the "public variables" table */
int32_t tags PACKED; /* the "public tagnames" table */ int32_t tags PACKED; /* the "public tagnames" table */
int32_t nametable PACKED; /* name table, file version 7 only */ int32_t nametable PACKED; /* name table */
} AMX_HEADER PACKED; } PACKED AMX_HEADER;
//This is always the same for us
#define AMX_MAGIC 0xf1e0 #define AMX_MAGIC 0xf1e0
//double linked list for stack
typedef struct tagAMX_TRACE
{
cell line PACKED;
cell file PACKED;
struct tagAMX_TRACE *next PACKED;
struct tagAMX_TRACE *prev PACKED;
} AMX_TRACE PACKED;
typedef struct tagAMX_DBG
{
int32_t numFiles PACKED; /* number of chars in array */
char **files PACKED; /* array of files */
AMX_TRACE *head PACKED; /* begin of link list */
AMX_TRACE *tail PACKED; /* end of link list */
} AMX_DBG PACKED;
enum { enum {
AMX_ERR_NONE, AMX_ERR_NONE,
/* reserve the first 15 error codes for exit codes of the abstract machine */ /* reserve the first 15 error codes for exit codes of the abstract machine */
@ -280,6 +303,7 @@ enum {
AMX_ERR_NATIVE, /* native function failed */ AMX_ERR_NATIVE, /* native function failed */
AMX_ERR_DIVIDE, /* divide by zero */ AMX_ERR_DIVIDE, /* divide by zero */
AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */ AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */
AMX_ERR_INVSTATE, /* invalid state for this access */
AMX_ERR_MEMORY = 16, /* out of memory */ AMX_ERR_MEMORY = 16, /* out of memory */
AMX_ERR_FORMAT, /* invalid file format */ AMX_ERR_FORMAT, /* invalid file format */
@ -292,29 +316,17 @@ enum {
AMX_ERR_INIT_JIT, /* cannot initialize the JIT */ AMX_ERR_INIT_JIT, /* cannot initialize the JIT */
AMX_ERR_PARAMS, /* parameter error */ AMX_ERR_PARAMS, /* parameter error */
AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */ AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */
}; AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */
enum {
DBG_INIT, /* query/initialize */
DBG_FILE, /* file number in curfile, filename in name */
DBG_LINE, /* line number in curline, file number in curfile */
DBG_SYMBOL, /* address in dbgaddr, class/type in dbgparam */
DBG_CLRSYM, /* stack address below which locals should be removed. stack address in stk */
DBG_CALL, /* function call, address jumped to in dbgaddr */
DBG_RETURN, /* function returns */
DBG_TERMINATE, /* program ends, code address in dbgaddr, reason in dbgparam */
DBG_SRANGE, /* symbol size and dimensions (arrays); level in dbgaddr (!); length in dbgparam */
DBG_SYMTAG, /* tag of the most recent symbol (if non-zero), tag in dbgparam */
}; };
/* AMX_FLAG_CHAR16 0x01 no longer used */ /* AMX_FLAG_CHAR16 0x01 no longer used */
#define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */ #define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */
#define AMX_FLAG_COMPACT 0x04 /* compact encoding */ #define AMX_FLAG_COMPACT 0x04 /* compact encoding */
#define AMX_FLAG_BIGENDIAN 0x08 /* big endian encoding */ #define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */
#define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking */ #define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */
#define AMX_FLAG_LINEOPS 0x20 /* line ops are parsed by the JIT [loadtime only flag] */ #define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */
#define AMX_FLAG_TRACED 0x40 /* the file has already been traced */ #define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */
#define AMX_FLAG_BROWSE 0x4000 /* browsing/relocating or executing */ #define AMX_FLAG_BROWSE 0x4000 /* busy browsing */
#define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */ #define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */
#define AMX_EXEC_MAIN -1 /* start at program entry point */ #define AMX_EXEC_MAIN -1 /* start at program entry point */
@ -322,16 +334,18 @@ enum {
#define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24)) #define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24))
#define AMX_EXPANDMARGIN 64 #if !defined AMX_COMPACTMARGIN
#define AMX_COMPACTMARGIN 64
#endif
/* for native functions that use floating point parameters, the following /* for native functions that use floating point parameters, the following
* two macros are convenient for casting a "cell" into a "float" type _without_ * two macros are convenient for casting a "cell" into a "float" type _without_
* changing the bit pattern * changing the bit pattern
*/ */
#if SMALL_CELL_SIZE==32 #if PAWN_CELL_SIZE==32
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
#define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */ #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */
#elif SMALL_CELL_SIZE==64 #elif PAWN_CELL_SIZE==64
#define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */
#define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */ #define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */
#else #else
@ -345,7 +359,7 @@ enum {
amx_StrLen(amx_cstr_, &amx_length_); \ amx_StrLen(amx_cstr_, &amx_length_); \
if (amx_length_ > 0 && \ if (amx_length_ > 0 && \
((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \ ((result) = (void*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \
amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1); \ amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_); \
else (result) = NULL; \ else (result) = NULL; \
} while (0) } while (0)
@ -354,23 +368,11 @@ uint32_t * AMXAPI amx_Align32(uint32_t *v);
#if defined _I64_MAX || defined HAVE_I64 #if defined _I64_MAX || defined HAVE_I64
uint64_t * AMXAPI amx_Align64(uint64_t *v); uint64_t * AMXAPI amx_Align64(uint64_t *v);
#endif #endif
#if SMALL_CELL_SIZE==32
#define amx_AlignCell amx_Align32
#elif SMALL_CELL_SIZE==64
#define amx_AlignCell amx_Align64
#else
#error Unsupported cell size
#endif
int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr); int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr);
int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params); int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params);
int AMXAPI amx_Cleanup(AMX *amx); int AMXAPI amx_Cleanup(AMX *amx);
int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data); int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data);
int AMXAPI amx_Debug(AMX *amx); /* default debug procedure, does nothing */ int AMXAPI amx_Exec(AMX *amx, cell *retval, int index);
int AMXAPI amx_DebugCall(AMX *amx, int mode);
int AMXAPI amx_Exec(AMX *amx, cell *retval, int index, int numparams, ...);
int AMXAPI amx_Execv(AMX *amx, cell *retval, int index, int numparams, cell params[]);
int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index); int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index);
int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index); int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index);
int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr); int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr);
@ -380,7 +382,7 @@ int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr);
int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname); int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname); int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname);
int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr); int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr);
int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar); int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size);
int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id); int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id);
int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr); int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr);
int AMXAPI amx_Init(AMX *amx, void *program); int AMXAPI amx_Init(AMX *amx, void *program);
@ -392,25 +394,44 @@ int AMXAPI amx_NumNatives(AMX *amx, int *number);
int AMXAPI amx_NumPublics(AMX *amx, int *number); int AMXAPI amx_NumPublics(AMX *amx, int *number);
int AMXAPI amx_NumPubVars(AMX *amx, int *number); int AMXAPI amx_NumPubVars(AMX *amx, int *number);
int AMXAPI amx_NumTags(AMX *amx, int *number); int AMXAPI amx_NumTags(AMX *amx, int *number);
int AMXAPI amx_Push(AMX *amx, cell value);
int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells);
int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar);
int AMXAPI amx_RaiseError(AMX *amx, int error); int AMXAPI amx_RaiseError(AMX *amx, int error);
int AMXAPI amx_Register(AMX *amx, AMX_NATIVE_INFO *nativelist, int number); int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number);
int AMXAPI amx_Release(AMX *amx, cell amx_addr); int AMXAPI amx_Release(AMX *amx, cell amx_addr);
int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback);
int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug); int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug);
int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar); int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size);
int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr); int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr);
int AMXAPI amx_StrLen(cell *cstring, int *length); int AMXAPI amx_StrLen(const cell *cstring, int *length);
int AMXAPI amx_UTF8Check(const char *string, int *length);
int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value); int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value);
int AMXAPI amx_UTF8Len(const cell *cstr, int *length);
int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value);
int AMXAPI amx_UTF8Check(const char *string);
int AMXAPI amx_GetLibraries(AMX *amx); int AMXAPI amx_GetLibraries(AMX *amx);
const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len); const char *AMXAPI amx_GetLibrary(AMX *amx, int index, char *buffer, int len);
int AMXAPI amx_SetStringOld(cell *dest,const char *source,int pack,int use_wchar);
int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar);
//no longer used! void amx_NullNativeTable(AMX *amx); #if PAWN_CELL_SIZE==16
#define amx_AlignCell(v) amx_Align16(v)
#elif PAWN_CELL_SIZE==32
#define amx_AlignCell(v) amx_Align32(v)
#elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64)
#define amx_AlignCell(v) amx_Align64(v)
#else
#error Unsupported cell size
#endif
#define amx_RegisterFunc(amx, name, func) \
amx_Register((amx), amx_NativeInfo((name),(func)), 1);
#if !defined AMX_NO_ALIGN #if !defined AMX_NO_ALIGN
#if defined __linux__ #if defined LINUX || defined __FreeBSD__
#pragma pack() /* reset default packing */ #pragma pack() /* reset default packing */
#elif defined MACOS && defined __MWERKS__
#pragma options align=reset
#else #else
#pragma pack(pop) /* reset previous packing */ #pragma pack(pop) /* reset previous packing */
#endif #endif

View File

@ -1,6 +1,6 @@
/* Core module for the Small AMX /* Core module for the Pawn AMX
* *
* Copyright (c) ITB CompuPhase, 1997-2004 * Copyright (c) ITB CompuPhase, 1997-2005
* *
* This software is provided "as-is", without any express or implied warranty. * This software is provided "as-is", without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from * In no event will the authors be held liable for any damages arising from
@ -34,14 +34,7 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <assert.h> #include <assert.h>
// this file does not include amxmodx.h, so we have to include the memory manager here
#ifdef MEMORY_TEST
#include "mmgr/mmgr.h"
#endif // MEMORY_TEST
#include "amx.h" #include "amx.h"
#if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows #if defined __WIN32__ || defined _WIN32 || defined WIN32 || defined _Windows
#include <windows.h> #include <windows.h>
#endif #endif
@ -60,14 +53,13 @@
# define _tcscpy strcpy # define _tcscpy strcpy
# define _tcsdup strdup # define _tcsdup strdup
# define _tcslen strlen # define _tcslen strlen
# define _stprintf sprintf
#endif #endif
#define CHARBITS (8*sizeof(char)) #define CHARBITS (8*sizeof(char))
typedef unsigned char uchar; typedef unsigned char uchar;
#if !defined NOPROPLIST #if !defined AMX_NOPROPLIST
typedef struct _property_list { typedef struct _property_list {
struct _property_list *next; struct _property_list *next;
cell id; cell id;
@ -76,7 +68,7 @@ typedef struct _property_list {
//??? safe AMX (owner of the property) //??? safe AMX (owner of the property)
} proplist; } proplist;
static proplist proproot = { NULL }; static proplist proproot = { NULL, 0, NULL, 0 };
static proplist *list_additem(proplist *root) static proplist *list_additem(proplist *root)
{ {
@ -142,15 +134,13 @@ static proplist *list_finditem(proplist *root,cell id,char *name,cell value,
} }
#endif #endif
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL numargs(AMX *amx, cell *params) static cell AMX_NATIVE_CALL numargs(AMX *amx, cell *params)
{ {
AMX_HEADER *hdr; AMX_HEADER *hdr;
uchar *data; uchar *data;
cell bytes; cell bytes;
(void)params;
hdr=(AMX_HEADER *)amx->base; hdr=(AMX_HEADER *)amx->base;
data=amx->data ? amx->data : amx->base+(int)hdr->dat; data=amx->data ? amx->data : amx->base+(int)hdr->dat;
/* the number of bytes is on the stack, at "frm + 2*cell" */ /* the number of bytes is on the stack, at "frm + 2*cell" */
@ -190,18 +180,16 @@ static cell AMX_NATIVE_CALL setarg(AMX *amx, cell *params)
/* adjust the address in "value" in case of an array access */ /* adjust the address in "value" in case of an array access */
value+=params[2]*sizeof(cell); value+=params[2]*sizeof(cell);
/* verify the address */ /* verify the address */
if (value<0 || (value>=amx->hea && value<amx->stk)) if (value<0 || value>=amx->hea && value<amx->stk)
return 0; return 0;
/* set the value indirectly */ /* set the value indirectly */
* (cell *)(data+(int)value) = params[3]; * (cell *)(data+(int)value) = params[3];
return 1; return 1;
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL heapspace(AMX *amx,cell *params) static cell AMX_NATIVE_CALL heapspace(AMX *amx,cell *params)
{ {
(void)params;
return amx->stk - amx->hea; return amx->stk - amx->hea;
} }
@ -220,142 +208,22 @@ static cell AMX_NATIVE_CALL funcidx(AMX *amx,cell *params)
return 0; return 0;
} /* if */ } /* if */
amx_GetString(name,cstr,0); amx_GetString(name,cstr,0,UNLIMITED);
err=amx_FindPublic(amx,name,&index); err=amx_FindPublic(amx,name,&index);
if (err!=AMX_ERR_NONE) if (err!=AMX_ERR_NONE)
index=-1; /* this is not considered a fatal error */ index=-1; /* this is not considered a fatal error */
return index; return index;
} }
int amx_StrPack(cell *dest,cell *source)
{
int len;
amx_StrLen(source,&len);
if ((ucell)*source>UNPACKEDMAX) {
/* source string is already packed */
while (len >= 0) {
*dest++ = *source++;
len-=sizeof(cell);
} /* while */
} else {
/* pack string, from bottom up */
cell c;
int i;
for (c=0,i=0; i<len; i++) {
assert((*source & ~0xffL)==0);
c=(c<<CHARBITS) | *source++;
if (i%sizeof(cell) == sizeof(cell)-1) {
*dest++=c;
c=0;
} /* if */
} /* for */
if (i%sizeof(cell) != 0) /* store remaining packed characters */
*dest=c << (sizeof(cell)-i%sizeof(cell))*CHARBITS;
else
*dest=0; /* store full cell of zeros */
} /* if */
return AMX_ERR_NONE;
}
int amx_StrUnpack(cell *dest,cell *source)
{
if ((ucell)*source>UNPACKEDMAX) {
/* unpack string, from top down (so string can be unpacked in place) */
cell c;
int i,len;
amx_StrLen(source,&len);
dest[len]=0;
for (i=len-1; i>=0; i--) {
c=source[i/sizeof(cell)] >> (sizeof(cell)-i%sizeof(cell)-1)*CHARBITS;
dest[i]=c & UCHAR_MAX;
} /* for */
} else {
/* source string is already unpacked */
while ((*dest++ = *source++) != 0)
/* nothing */;
} /* if */
return AMX_ERR_NONE;
}
static int verify_addr(AMX *amx,cell addr)
{
int err;
cell *cdest;
err=amx_GetAddr(amx,addr,&cdest);
if (err!=AMX_ERR_NONE)
amx_RaiseError(amx,err);
return err;
}
static cell AMX_NATIVE_CALL core_strlen(AMX *amx,cell *params)
{
cell *cptr;
int len = 0;
if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
amx_StrLen(cptr,&len);
return len;
}
static cell AMX_NATIVE_CALL strpack(AMX *amx,cell *params)
{
cell *cdest,*csrc;
int len,needed,err;
size_t lastaddr;
/* calculate number of cells needed for (packed) destination */
amx_GetAddr(amx,params[2],&csrc);
amx_StrLen(csrc,&len);
needed=(len+sizeof(cell))/sizeof(cell); /* # of cells needed */
assert(needed>0);
lastaddr=(size_t)(params[1]+sizeof(cell)*needed-1);
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
return 0;
amx_GetAddr(amx,params[1],&cdest);
err=amx_StrPack(cdest,csrc);
if (err!=AMX_ERR_NONE)
return amx_RaiseError(amx,err);
return len;
}
static cell AMX_NATIVE_CALL strunpack(AMX *amx,cell *params)
{
cell *cdest,*csrc;
int len,err;
size_t lastaddr;
/* calculate number of cells needed for (packed) destination */
amx_GetAddr(amx,params[2],&csrc);
amx_StrLen(csrc,&len);
assert(len>=0);
lastaddr=(size_t)(params[1]+sizeof(cell)*(len+1)-1);
if (verify_addr(amx,(cell)lastaddr)!=AMX_ERR_NONE)
return 0;
amx_GetAddr(amx,params[1],&cdest);
err=amx_StrUnpack(cdest,csrc);
if (err!=AMX_ERR_NONE)
return amx_RaiseError(amx,err);
return len;
}
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params) static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params)
{ {
union { union {
cell c; cell c;
#if SMALL_CELL_SIZE==16 #if PAWN_CELL_SIZE==16
uchar b[2]; uchar b[2];
#elif SMALL_CELL_SIZE==32 #elif PAWN_CELL_SIZE==32
uchar b[4]; uchar b[4];
#elif SMALL_CELL_SIZE==64 #elif PAWN_CELL_SIZE==64
uchar b[8]; uchar b[8];
#else #else
#error Unsupported cell size #error Unsupported cell size
@ -363,20 +231,21 @@ static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params)
} value; } value;
uchar t; uchar t;
(void)amx;
assert((size_t)params[0]==sizeof(cell)); assert((size_t)params[0]==sizeof(cell));
value.c = params[1]; value.c = params[1];
#if SMALL_CELL_SIZE==16 #if PAWN_CELL_SIZE==16
t = value.b[0]; t = value.b[0];
value.b[0] = value.b[1]; value.b[0] = value.b[1];
value.b[1] = t; value.b[1] = t;
#elif SMALL_CELL_SIZE==32 #elif PAWN_CELL_SIZE==32
t = value.b[0]; t = value.b[0];
value.b[0] = value.b[3]; value.b[0] = value.b[3];
value.b[3] = t; value.b[3] = t;
t = value.b[1]; t = value.b[1];
value.b[1] = value.b[2]; value.b[1] = value.b[2];
value.b[2] = t; value.b[2] = t;
#elif SMALL_CELL_SIZE==64 #elif PAWN_CELL_SIZE==64
t = value.b[0]; t = value.b[0];
value.b[0] = value.b[7]; value.b[0] = value.b[7];
value.b[7] = t; value.b[7] = t;
@ -395,11 +264,9 @@ static cell AMX_NATIVE_CALL swapchars(AMX *amx,cell *params)
return value.c; return value.c;
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params) static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params)
{ {
(void)amx;
#if defined __WIN32__ || defined _WIN32 || defined WIN32 #if defined __WIN32__ || defined _WIN32 || defined WIN32
return (cell)CharLower((LPTSTR)params[1]); return (cell)CharLower((LPTSTR)params[1]);
#elif defined _Windows #elif defined _Windows
@ -409,11 +276,9 @@ static cell AMX_NATIVE_CALL core_tolower(AMX *amx,cell *params)
#endif #endif
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params) static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params)
{ {
(void)amx;
#if defined __WIN32__ || defined _WIN32 || defined WIN32 #if defined __WIN32__ || defined _WIN32 || defined WIN32
return (cell)CharUpper((LPTSTR)params[1]); return (cell)CharUpper((LPTSTR)params[1]);
#elif defined _Windows #elif defined _Windows
@ -423,19 +288,15 @@ static cell AMX_NATIVE_CALL core_toupper(AMX *amx,cell *params)
#endif #endif
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL core_min(AMX *amx,cell *params) static cell AMX_NATIVE_CALL core_min(AMX *amx,cell *params)
{ {
(void)amx;
return params[1] <= params[2] ? params[1] : params[2]; return params[1] <= params[2] ? params[1] : params[2];
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
static cell AMX_NATIVE_CALL core_max(AMX *amx,cell *params) static cell AMX_NATIVE_CALL core_max(AMX *amx,cell *params)
{ {
(void)amx;
return params[1] >= params[2] ? params[1] : params[2]; return params[1] >= params[2] ? params[1] : params[2];
} }
@ -451,7 +312,7 @@ static cell AMX_NATIVE_CALL core_clamp(AMX *amx,cell *params)
return value; return value;
} }
#if !defined NOPROPLIST #if !defined AMX_NOPROPLIST
static char *MakePackedString(cell *cptr) static char *MakePackedString(cell *cptr)
{ {
int len; int len;
@ -459,10 +320,21 @@ static char *MakePackedString(cell *cptr)
amx_StrLen(cptr,&len); amx_StrLen(cptr,&len);
dest=(char *)malloc(len+sizeof(cell)); dest=(char *)malloc(len+sizeof(cell));
amx_GetString(dest,cptr,0); amx_GetString(dest,cptr,0,UNLIMITED);
return dest; return dest;
} }
static int verify_addr(AMX *amx,cell addr)
{
int err;
cell *cdest;
err=amx_GetAddr(amx,addr,&cdest);
if (err!=AMX_ERR_NONE)
amx_RaiseError(amx,err);
return err;
}
static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params) static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params)
{ {
cell *cstr; cell *cstr;
@ -480,7 +352,7 @@ static cell AMX_NATIVE_CALL getproperty(AMX *amx,cell *params)
return 0; return 0;
} /* if */ } /* if */
amx_GetAddr(amx,params[4],&cstr); amx_GetAddr(amx,params[4],&cstr);
amx_SetString(cstr,item->name,1,0); amx_SetString(cstr,item->name,1,0,UNLIMITED);
} /* if */ } /* if */
free(name); free(name);
return (item!=NULL) ? item->value : 0; return (item!=NULL) ? item->value : 0;
@ -545,12 +417,14 @@ static cell AMX_NATIVE_CALL existproperty(AMX *amx,cell *params)
} }
#endif #endif
#if !defined AMX_NORANDOM
/* This routine comes from the book "Inner Loops" by Rick Booth, Addison-Wesley /* This routine comes from the book "Inner Loops" by Rick Booth, Addison-Wesley
* (ISBN 0-201-47960-5). This is a "multiplicative congruential random number * (ISBN 0-201-47960-5). This is a "multiplicative congruential random number
* generator" that has been extended to 31-bits (the standard C version returns * generator" that has been extended to 31-bits (the standard C version returns
* only 15-bits). * only 15-bits).
*/ */
static unsigned long IL_StandardRandom_seed = 0L; #define INITIAL_SEED 0xcaa938dbL
static unsigned long IL_StandardRandom_seed = INITIAL_SEED; /* always use a non-zero seed */
#define IL_RMULT 1103515245L #define IL_RMULT 1103515245L
#if defined __BORLANDC__ || defined __WATCOMC__ #if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused #pragma argsused
@ -562,7 +436,7 @@ static cell AMX_NATIVE_CALL core_random(AMX *amx,cell *params)
/* one-time initialization (or, mostly one-time) */ /* one-time initialization (or, mostly one-time) */
#if !defined SN_TARGET_PS2 && !defined _WIN32_WCE #if !defined SN_TARGET_PS2 && !defined _WIN32_WCE
if (IL_StandardRandom_seed == 0L) if (IL_StandardRandom_seed == INITIAL_SEED)
IL_StandardRandom_seed=(unsigned long)time(NULL); IL_StandardRandom_seed=(unsigned long)time(NULL);
#endif #endif
@ -579,6 +453,7 @@ static cell AMX_NATIVE_CALL core_random(AMX *amx,cell *params)
result %= params[1]; result %= params[1];
return (cell)result; return (cell)result;
} }
#endif
AMX_NATIVE_INFO core_Natives[] = { AMX_NATIVE_INFO core_Natives[] = {
@ -587,22 +462,13 @@ AMX_NATIVE_INFO core_Natives[] = {
{ "setarg", setarg }, { "setarg", setarg },
{ "heapspace", heapspace }, { "heapspace", heapspace },
{ "funcidx", funcidx }, { "funcidx", funcidx },
{ "strlen", core_strlen },
{ "strpack", strpack },
{ "strunpack", strunpack },
{ "swapchars", swapchars }, { "swapchars", swapchars },
{ "tolower", core_tolower }, { "tolower", core_tolower },
{ "toupper", core_toupper }, { "toupper", core_toupper },
{ "random", core_random },
{ "min", core_min }, { "min", core_min },
{ "max", core_max }, { "max", core_max },
{ "clamp", core_clamp }, { "clamp", core_clamp },
#if !defined NOPROPLIST { "random", core_random },
{ "getproperty", getproperty },
{ "setproperty", setproperty },
{ "deleteproperty",delproperty },
{ "existproperty", existproperty },
#endif
{ NULL, NULL } /* terminator */ { NULL, NULL } /* terminator */
}; };
@ -611,12 +477,10 @@ int AMXEXPORT amx_CoreInit(AMX *amx)
return amx_Register(amx, core_Natives, -1); return amx_Register(amx, core_Natives, -1);
} }
#if defined __BORLANDC__ || defined __WATCOMC__
#pragma argsused
#endif
int AMXEXPORT amx_CoreCleanup(AMX *amx) int AMXEXPORT amx_CoreCleanup(AMX *amx)
{ {
#if !defined NOPROPLIST (void)amx;
#if !defined AMX_NOPROPLIST
//??? delete only the properties owned by the AMX //??? delete only the properties owned by the AMX
while (proproot.next!=NULL) while (proproot.next!=NULL)
list_delete(&proproot,proproot.next); list_delete(&proproot,proproot.next);

86
amxmodx/amxdefn.asm Executable file
View File

@ -0,0 +1,86 @@
; Definition of the AMX structure for assembler syntax (NASM)
struc amx_s
_base: resd 1
_dataseg: resd 1
_callback: resd 1
_debug: resd 1
_cip: resd 1
_frm: resd 1
_hea: resd 1
_hlw: resd 1
_stk: resd 1
_stp: resd 1
_flags: resd 1
_usertags: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata: resd 4 ; 4 = AMX_USERNUM (#define'd in amx.h)
_error: resd 1
_paramcount: resd 1
_pri: resd 1
_alt: resd 1
_reset_stk: resd 1
_reset_hea: resd 1
_syscall_d: resd 1
%ifdef JIT
; the two fields below are for the JIT; they do not exist in
; the non-JIT version of the abstract machine
_reloc_size: resd 1 ; memory block for relocations
_code_size: resd 1 ; memory size of the native code
%endif
endstruc
struc amxhead_s
_size: resd 1 ; size of the "file"
_magic: resw 1 ; signature
_file_version: resb 1; file format version
_amx_version: resb 1 ; required version of the AMX
_h_flags: resw 1
_defsize: resw 1 ; size of one public/native function entry
_cod: resd 1 ; initial value of COD - code block
_dat: resd 1 ; initial value of DAT - data block
_h_hea: resd 1 ; initial value of HEA - start of the heap
_h_stp: resd 1 ; initial value of STP - stack top
_h_cip: resd 1 ; initial value of CIP - the instruction pointer
_publics: resd 1 ; offset to the "public functions" table
_natives: resd 1 ; offset to the "native functions" table
_libraries: resd 1 ; offset to the "library" table
_pubvars: resd 1 ; offset to the "public variables" table
_tags: resd 1 ; offset to the "public tagnames" table
_nametable: resd 1 ; offset to the name table, file version 7 only
endstruc
AMX_ERR_NONE EQU 0
AMX_ERR_EXIT EQU 1
AMX_ERR_ASSERT EQU 2
AMX_ERR_STACKERR EQU 3
AMX_ERR_BOUNDS EQU 4
AMX_ERR_MEMACCESS EQU 5
AMX_ERR_INVINSTR EQU 6
AMX_ERR_STACKLOW EQU 7
AMX_ERR_HEAPLOW EQU 8
AMX_ERR_CALLBACK EQU 9
AMX_ERR_NATIVE EQU 10
AMX_ERR_DIVIDE EQU 11 ; for catching divide errors
AMX_ERR_SLEEP EQU 12
AMX_ERR_MEMORY EQU 16
AMX_ERR_FORMAT EQU 17
AMX_ERR_VERSION EQU 18
AMX_ERR_NOTFOUND EQU 19
AMX_ERR_INDEX EQU 20
AMX_ERR_DEBUG EQU 21
AMX_ERR_INIT EQU 22
AMX_ERR_USERDATA EQU 23
AMX_ERR_INIT_JIT EQU 24
AMX_ERR_PARAMS EQU 25
AMX_ERR_DOMAIN EQU 26
AMX_ERR_GENERAL EQU 27
AMX_FLAG_DEBUG EQU 0002h ; symbolic info. available
AMX_FLAG_COMPACT EQU 0004h
AMX_FLAG_BYTEOPC EQU 0008h
AMX_FLAG_NOCHECKS EQU 0010h
AMX_FLAG_BROWSE EQU 4000h
AMX_FLAG_RELOC EQU 8000h ; jump/call addresses relocated

View File

@ -1,4 +1,4 @@
; AMXEXECN.ASM Abstract Machine for the "Small" language ; AMXEXECN.ASM Abstract Machine for the "Pawn" language
; ;
;Some notes: ;Some notes:
@ -25,7 +25,7 @@
; ;
;Copyright and license of use, please read ;Copyright and license of use, please read
;----------------------------------------- ;-----------------------------------------
;The assembler implementation of the abstract machine for the Small language, ;The assembler implementation of the abstract machine for the Pawn language,
;specifically the file AMXEXEC.ASM, is copyright (c) 1998-2000 by Marc Peter. ;specifically the file AMXEXEC.ASM, is copyright (c) 1998-2000 by Marc Peter.
; ;
;Permission is hereby granted, without written agreement and without paid ;Permission is hereby granted, without written agreement and without paid
@ -56,6 +56,8 @@
; ;
;History (list of changes) ;History (list of changes)
;------------------------- ;-------------------------
; 17 february 2005 by Thiadmer Riemersms
; Addition of the BREAK opcode, removal of the older debugging opcode table.
; 6 march 2004 by Thiadmer Riemersma ; 6 march 2004 by Thiadmer Riemersma
; Corrected a bug in OP_FILL, where a cell preceding the array would ; Corrected a bug in OP_FILL, where a cell preceding the array would
; be overwritten (zero'ed out). This bug was brought to my attention ; be overwritten (zero'ed out). This bug was brought to my attention
@ -95,92 +97,7 @@
%endif %endif
%endmacro %endmacro
%include "amxdefn.asm"
; I could not get NASM's structure definition to work (it appears to confuse
; ENDSTRUC with "end segment"). So the definition below uses constants for
; the field offsets.
;amx_s STRUC
_base EQU 00h ;DD ?
_dataseg EQU 04h ;DD ?
_callback EQU 08h ;DD ?
_debug EQU 0ch ;DD ?
_cip EQU 10h ;DD ?
_frm EQU 14h ;DD ?
_hea EQU 18h ;DD ?
_hlw EQU 1ch ;DD ?
_stk EQU 20h ;DD ?
_stp EQU 24h ;DD ?
_flags EQU 28h ;DD ?
_curline EQU 2ch ;DD ?
_curfile EQU 30h ;DD ?
_dbgcode EQU 34h ;DD ?
_dbgaddr EQU 38h ;DD ?
_dbgparam EQU 3ch ;DD ?
_dbgname EQU 40h ;DD ?
_usertags1 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags2 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags3 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags4 EQU 44h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata1 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata2 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata3 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata4 EQU 54h ;DD 4 DUP (?) ; 4 = AMX_USERNUM (#define'd in amx.h)
_error EQU 64h ;DD ?
_pri EQU 68h ;DD ?
_alt EQU 6ch ;DD ?
_reset_stk EQU 70h ;DD ?
_reset_hea EQU 74h ;DD ?
_syscall_d EQU 78h ;DD ?
; the two fields below are for the JIT; they do not exist in
; the non-JIT version of the abstract machine
; _reloc_size EQU 7ch ;DD ? ; memory block for relocations
; _code_size EQU 80h ;DD ? ; memory size of the native code
;amx_s ENDS
AMX_ERR_NONE EQU 0
AMX_ERR_EXIT EQU 1
AMX_ERR_ASSERT EQU 2
AMX_ERR_STACKERR EQU 3
AMX_ERR_BOUNDS EQU 4
AMX_ERR_MEMACCESS EQU 5
AMX_ERR_INVINSTR EQU 6
AMX_ERR_STACKLOW EQU 7
AMX_ERR_HEAPLOW EQU 8
AMX_ERR_CALLBACK EQU 9
AMX_ERR_NATIVE EQU 10
AMX_ERR_DIVIDE EQU 11 ; MP: added for catching divide errors
AMX_ERR_SLEEP EQU 12 ; (TR)
AMX_ERR_MEMORY EQU 16
AMX_ERR_FORMAT EQU 17
AMX_ERR_VERSION EQU 18
AMX_ERR_NOTFOUND EQU 19
AMX_ERR_INDEX EQU 20
AMX_ERR_DEBUG EQU 21
AMX_ERR_INIT EQU 22
AMX_ERR_USERDATA EQU 23
AMX_ERR_INIT_JIT EQU 24
AMX_ERR_PARAMS EQU 25
AMX_ERR_DOMAIN EQU 26
DBG_INIT EQU 0
DBG_FILE EQU 1
DBG_LINE EQU 2
DBG_SYMBOL EQU 3
DBG_CLRSYM EQU 4
DBG_CALL EQU 5
DBG_RETURN EQU 6
DBG_TERMINATE EQU 7
DBG_SRANGE EQU 8 ; (TR)
DBG_SYMTAG EQU 9 ; (TR)
AMX_FLAG_CHAR16 EQU 0001h ; characters are 16-bit
AMX_FLAG_DEBUG EQU 0002h ; symbolic info. available
AMX_FLAG_LINEOPS EQU 0020h ; line op information
AMX_FLAG_TRACED EQU 0040h ;
AMX_FLAG_BROWSE EQU 4000h
AMX_FLAG_RELOC EQU 8000h ; jump/call addresses relocated
;#define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v ) ;#define PUSH(v) ( stk-=sizeof(cell), *(cell *)(data+(int)stk)=v )
%macro _PUSH 1 %macro _PUSH 1
@ -659,29 +576,6 @@ OP_POP_ALT:
;good ;good
OP_STACK: OP_STACK:
mov edx,ecx
add ecx,[esi+4]
_CHKMARGIN
_CHKSTACK
mov ebp,amx
test DWORD [ebp+_flags],AMX_FLAG_DEBUG
jz short op_stk_goon
; update several structure fields and call the debug hook
mov DWORD [ebp+_dbgcode],DBG_CLRSYM
mov [ebp+_stk],ecx
push eax
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax ; pass parameter via the stack
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop eax
op_stk_goon:
add esi,8
GO_ON
OP_STACK_nodebug:
mov edx,ecx mov edx,ecx
add ecx,[esi+4] add ecx,[esi+4]
_CHKMARGIN _CHKMARGIN
@ -711,35 +605,6 @@ OP_PROC:
GO_ON GO_ON
OP_RET: OP_RET:
_POP ebx
_POP esi
cmp esi,code ; verify ESI>=code
jb err_memaccess
cmp esi,codesiz ; verify ESI<codesiz ("end-of-code" pointer)
jae err_memaccess
mov frm,ebx
add ebx,edi
mov ebp,amx
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_ret_goon
; update several structure fields and call the debug hook
mov DWORD [ebp+_dbgcode],DBG_RETURN
mov [ebp+_dbgparam],eax
push eax
mov [ebp+_stk],ecx ; store STK
mov eax,hea
mov [ebp+_hea],eax ; store HEA
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop eax
op_ret_goon:
GO_ON
OP_RET_nodebug:
_POP ebx _POP ebx
_POP esi _POP esi
cmp esi,code ; verify ESI>=code cmp esi,code ; verify ESI>=code
@ -760,107 +625,17 @@ OP_RETN:
jae err_memaccess jae err_memaccess
mov frm,ebx mov frm,ebx
add ebx,edi add ebx,edi
mov ebp,amx
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_retn_goon
; update several structure fields and call the debug hook
mov DWORD [ebp+_dbgcode],DBG_RETURN
mov [ebp+_dbgparam],eax
push eax
mov [ebp+_stk],ecx ; store STK
mov eax,hea
mov [ebp+_hea],eax ; store HEA
mov eax,ebp ; parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
; also send the DBG_CLRSYM code
mov eax,[edi+ecx]
lea ecx,[ecx+eax+4]
mov DWORD [ebp+_dbgcode],DBG_CLRSYM
mov [ebp+_stk],ecx
mov eax,ebp ; parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop eax
; ECX already adjusted
GO_ON
op_retn_goon:
mov ebp,[edi+ecx] mov ebp,[edi+ecx]
lea ecx,[ecx+ebp+4] lea ecx,[ecx+ebp+4]
GO_ON GO_ON
OP_RETN_nodebug:
_POP ebx
_POP esi
cmp esi,code ; verify ESI>=code
jb err_memaccess
cmp esi,codesiz ; verify ESI<codesiz ("end-of-code" pointer)
jae err_memaccess
mov frm,ebx
mov ebp,[edi+ecx]
add ebx,edi
lea ecx,[ecx+ebp+4]
GO_ON
;good
OP_CALL: OP_CALL:
lea ebp,[esi+8]
mov esi,[esi+4]
_PUSH ebp
mov ebp,amx
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_call_goon
; update several structure fields and call the debug hook
push eax
mov eax,[esp+24] ; this is "code", but ESP moved
mov [ebp+_dbgaddr],esi
sub [ebp+_dbgaddr],eax ; dbgaddr = cip - code
mov DWORD [ebp+_dbgcode],DBG_CALL
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop eax
op_call_goon:
GO_ON
OP_CALL_nodebug:
lea ebp,[esi+8] lea ebp,[esi+8]
mov esi,[esi+4] mov esi,[esi+4]
_PUSH ebp _PUSH ebp
GO_ON GO_ON
OP_CALL_PRI: OP_CALL_PRI:
lea ebp,[esi+4]
mov esi,eax
add esi,code ; cip = PRI + code
_PUSH ebp
mov ebp,amx
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_calli_goon
; update several structure fields and call the debug hook
mov [ebp+_dbgaddr],eax ; dbgaddr = PRI (== cip - code)
mov DWORD [ebp+_dbgcode],DBG_CALL
push eax
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop eax
op_calli_goon:
GO_ON
OP_CALL_PRI_nodebug:
lea ebp,[esi+4] lea ebp,[esi+4]
mov esi,eax mov esi,eax
add esi,code ; cip = PRI + code add esi,code ; cip = PRI + code
@ -941,13 +716,13 @@ OP_JSLESS:
;good ;good
OP_JSLEQ: OP_JSLEQ:
cmp eax,edx cmp eax,edx
jle short jump_taken jle near jump_taken
add esi,8 add esi,8
GO_ON GO_ON
OP_JSGRTR: OP_JSGRTR:
cmp eax,edx cmp eax,edx
jg short jump_taken jg near jump_taken
add esi,8 add esi,8
GO_ON GO_ON
@ -1350,12 +1125,11 @@ OP_CMPS:
_VERIFYADDRESS eax ; PRI _VERIFYADDRESS eax ; PRI
_VERIFYADDRESS edx ; ALT _VERIFYADDRESS edx ; ALT
mov ebp,eax mov ebp,eax
add ebp,[esi+4] add ebp,[esi+4] ; size in bytes
dec ebp dec ebp ; EBP = PRI + size - 1
_VERIFYADDRESS ebp ; PRI + size - 1 _VERIFYADDRESS ebp ; PRI + size - 1
mov ebp,edx sub ebp,eax ; EBP = size - 1
add ebp,[esi+4] add ebp,edx ; EBP = ALT + size - 1
dec ebp
_VERIFYADDRESS ebp ; ALT + size - 1 _VERIFYADDRESS ebp ; ALT + size - 1
push ecx push ecx
@ -1422,19 +1196,6 @@ OP_HALT:
mov eax,esi ; EAX=CIP mov eax,esi ; EAX=CIP
sub eax,code sub eax,code
mov [ebp+_cip],eax mov [ebp+_cip],eax
; optionally call the debug hook
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short halt_goon
mov DWORD [ebp+_dbgcode],DBG_TERMINATE
mov [ebp+_dbgaddr],eax
mov [ebp+_dbgparam],ebx
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
halt_goon:
mov eax,ebx ; return the parameter of the HALT opcode mov eax,ebx ; return the parameter of the HALT opcode
jmp _return jmp _return
@ -1549,159 +1310,21 @@ OP_FILE:
OP_LINE: OP_LINE:
add esi,12 add esi,12
mov ebp,amx
push eax
push edx
mov eax,[esi-8] ; get curline
mov edx,[esi-4] ; get curfile
mov [ebp+_curline],eax
mov [ebp+_curfile],edx
pop edx
pop eax
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short line_goon
; update several structure fields
mov [ebp+_pri],eax
mov [ebp+_alt],edx ; EAX and EDX are now free to use
mov eax,frm
mov edx,hea
mov [ebp+_frm],eax ; store values in AMX structure (STK, FRM & HEA)
mov [ebp+_hea],edx
mov [ebp+_stk],ecx
mov eax,esi
sub eax,code ; EAX = CIP (relative to start of code segment)
mov [ebp+_cip],eax
; call the debugger hook
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
cmp eax,AMX_ERR_NONE
je short line_noabort ; continue running
mov [ebp+_dbgcode],eax ; save EAX (error code) before restoring all regs
_RESTOREREGS ; abort run, but restore stack first
mov eax,[ebp+_dbgcode] ; get error code in EAX back again
jmp _return ; return error code
line_noabort:
_RESTOREREGS
mov eax,[ebp+_pri] ; restore PRI and ALT
mov edx,[ebp+_alt]
line_goon:
GO_ON
OP_LINE_nodebug:
add esi,12
mov ebp,amx
push eax
push edx
mov eax,[esi-8] ; get curline
mov edx,[esi-4] ; get curfile
mov [ebp+_curline],eax
mov [ebp+_curfile],edx
pop edx
pop eax
GO_ON GO_ON
OP_SYMBOL: OP_SYMBOL:
mov ebp,amx
test DWORD [ebp+_flags],AMX_FLAG_DEBUG
jz short op_symbol_goon
push eax
push edx
mov eax,[esi+8] ; address
mov edx,[esi+12] ; flags
mov [ebp+_dbgaddr],eax
mov [ebp+_dbgparam],edx
mov DWORD [ebp+_dbgcode],DBG_SYMBOL
mov eax,esi
add eax,16 ; start of symbol name
mov [ebp+_dbgname],eax
mov edx,[esp+8] ; this is FRM, but offset by two PUSH'es
mov [ebp+_frm],edx
mov eax,ebp ; parameter of the debugger hook
_SAVEREGS
push eax
call [ebp+_debug] ; call debugger hook
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop edx
pop eax
op_symbol_goon:
add esi,[esi+4]
add esi,8 ; skip "fixed" part
GO_ON
OP_SYMBOL_nodebug:
add esi,[esi+4] add esi,[esi+4]
add esi,8 ; skip "fixed" part add esi,8 ; skip "fixed" part
GO_ON GO_ON
OP_SRANGE: OP_SRANGE:
mov ebp,amx
add esi,12
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_srange_goon
push eax
push edx
mov eax,[esi-8] ; get dimensions
mov edx,[esi-4] ; get size
mov [ebp+_dbgaddr],eax
mov [ebp+_dbgparam],edx
mov DWORD [ebp+_dbgcode],DBG_SRANGE
mov edx,frm
mov [ebp+_frm],edx
mov [ebp+_stk],ecx ; store values in AMX structure (STK & FRM)
; call the debugger hook
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop edx
pop eax
op_srange_goon:
GO_ON
OP_SRANGE_nodebug:
add esi,12 add esi,12
GO_ON GO_ON
OP_SYMTAG: OP_SYMTAG:
mov ebp,amx
add esi,8
test DWORD [ebp+_flags], AMX_FLAG_DEBUG
jz short op_symtag_goon
mov ebp,amx
push eax
push edx
mov eax,[esi-4] ; get tag
mov edx,frm
mov DWORD [ebp+_dbgcode],DBG_SRANGE
mov [ebp+_dbgparam],eax
mov [ebp+_frm],edx
mov [ebp+_stk],ecx ; store values in AMX structure (STK & FRM)
; call the debugger hook
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
_RESTOREREGS
pop edx
pop eax
op_symtag_goon:
GO_ON
OP_SYMTAG_nodebug: ; (TR)
add esi,8 add esi,8
GO_ON GO_ON
@ -1759,6 +1382,45 @@ OP_PUSHADDR:
OP_NOP: OP_NOP:
add esi,4
GO_ON
OP_BREAK:
mov ebp,amx ; get amx into ebp
add esi,4
cmp DWORD [ebp+_debug], 0
jnz break_calldebug
GO_ON ; debug hook not active, ignore
break_calldebug:
; store the status in the AMX (FRM, STK, HEA, CIP, and PRI + ALT)
mov [ebp+_pri],eax
mov [ebp+_alt],edx ; EAX and EDX are now free to use
mov eax,frm
mov edx,hea
mov [ebp+_frm],eax ; store values in AMX structure (STK, FRM & HEA)
mov [ebp+_hea],edx
mov [ebp+_stk],ecx
mov eax,esi
sub eax,code ; EAX = CIP (relative to start of code segment)
mov [ebp+_cip],eax
; call the debug hook
mov eax,ebp ; 1st parm: amx
_SAVEREGS
push eax
call [ebp+_debug] ; call debug function
_DROPARGS 4 ; remove arguments from stack
cmp eax,AMX_ERR_NONE
je short break_noabort; continue running
mov [ebp+_error],eax ; save EAX (error code) before restoring all regs
_RESTOREREGS ; abort run, but restore stack first
mov eax,[ebp+_error] ; get error code in EAX back again
jmp _return ; return error code
break_noabort:
_RESTOREREGS
mov eax,[ebp+_pri] ; restore PRI and ALT
mov edx,[ebp+_alt]
GO_ON GO_ON
@ -1796,7 +1458,7 @@ err_divide:
_return: _return:
; save a few paraneters, mostly for the "sleep"function ; save a few parameters, mostly for the "sleep"function
mov ebp,amx ; get amx into ebp mov ebp,amx ; get amx into ebp
mov [ebp+_pri],eax ; store values in AMX structure (PRI, ALT) mov [ebp+_pri],eax ; store values in AMX structure (PRI, ALT)
mov [ebp+_alt],edx ; store values in AMX structure (PRI, ALT) mov [ebp+_alt],edx ; store values in AMX structure (PRI, ALT)
@ -1967,144 +1629,5 @@ _amx_opcodelist DD OP_INVALID
DD OP_NOP DD OP_NOP
DD OP_SYSREQ_D DD OP_SYSREQ_D
DD OP_SYMTAG DD OP_SYMTAG
DD OP_BREAK
GLOBAL amx_opcodelist_nodebug
GLOBAL _amx_opcodelist_nodebug
amx_opcodelist_nodebug:
_amx_opcodelist_nodebug DD OP_INVALID
DD OP_LOAD_PRI
DD OP_LOAD_ALT
DD OP_LOAD_S_PRI
DD OP_LOAD_S_ALT
DD OP_LREF_PRI
DD OP_LREF_ALT
DD OP_LREF_S_PRI
DD OP_LREF_S_ALT
DD OP_LOAD_I
DD OP_LODB_I
DD OP_CONST_PRI
DD OP_CONST_ALT
DD OP_ADDR_PRI
DD OP_ADDR_ALT
DD OP_STOR_PRI
DD OP_STOR_ALT
DD OP_STOR_S_PRI
DD OP_STOR_S_ALT
DD OP_SREF_PRI
DD OP_SREF_ALT
DD OP_SREF_S_PRI
DD OP_SREF_S_ALT
DD OP_STOR_I
DD OP_STRB_I
DD OP_LIDX
DD OP_LIDX_B
DD OP_IDXADDR
DD OP_IDXADDR_B
DD OP_ALIGN_PRI
DD OP_ALIGN_ALT
DD OP_LCTRL
DD OP_SCTRL
DD OP_MOVE_PRI
DD OP_MOVE_ALT
DD OP_XCHG
DD OP_PUSH_PRI
DD OP_PUSH_ALT
DD OP_PUSH_R_PRI
DD OP_PUSH_C
DD OP_PUSH
DD OP_PUSH_S
DD OP_POP_PRI
DD OP_POP_ALT
DD OP_STACK_nodebug
DD OP_HEAP
DD OP_PROC
DD OP_RET_nodebug
DD OP_RETN_nodebug
DD OP_CALL_nodebug
DD OP_CALL_PRI_nodebug
DD OP_JUMP
DD OP_JREL
DD OP_JZER
DD OP_JNZ
DD OP_JEQ
DD OP_JNEQ
DD OP_JLESS
DD OP_JLEQ
DD OP_JGRTR
DD OP_JGEQ
DD OP_JSLESS
DD OP_JSLEQ
DD OP_JSGRTR
DD OP_JSGEQ
DD OP_SHL
DD OP_SHR
DD OP_SSHR
DD OP_SHL_C_PRI
DD OP_SHL_C_ALT
DD OP_SHR_C_PRI
DD OP_SHR_C_ALT
DD OP_SMUL
DD OP_SDIV
DD OP_SDIV_ALT
DD OP_UMUL
DD OP_UDIV
DD OP_UDIV_ALT
DD OP_ADD
DD OP_SUB
DD OP_SUB_ALT
DD OP_AND
DD OP_OR
DD OP_XOR
DD OP_NOT
DD OP_NEG
DD OP_INVERT
DD OP_ADD_C
DD OP_SMUL_C
DD OP_ZERO_PRI
DD OP_ZERO_ALT
DD OP_ZERO
DD OP_ZERO_S
DD OP_SIGN_PRI
DD OP_SIGN_ALT
DD OP_EQ
DD OP_NEQ
DD OP_LESS
DD OP_LEQ
DD OP_GRTR
DD OP_GEQ
DD OP_SLESS
DD OP_SLEQ
DD OP_SGRTR
DD OP_SGEQ
DD OP_EQ_C_PRI
DD OP_EQ_C_ALT
DD OP_INC_PRI
DD OP_INC_ALT
DD OP_INC
DD OP_INC_S
DD OP_INC_I
DD OP_DEC_PRI
DD OP_DEC_ALT
DD OP_DEC
DD OP_DEC_S
DD OP_DEC_I
DD OP_MOVS
DD OP_CMPS
DD OP_FILL
DD OP_HALT
DD OP_BOUNDS
DD OP_SYSREQ_PRI
DD OP_SYSREQ_C
DD OP_FILE
DD OP_LINE_nodebug
DD OP_SYMBOL_nodebug
DD OP_SRANGE_nodebug
DD OP_JUMP_PRI
DD OP_SWITCH
DD OP_CASETBL
DD OP_SWAP_PRI
DD OP_SWAP_ALT
DD OP_PUSHADDR
DD OP_NOP
DD OP_SYSREQ_D
DD OP_SYMTAG_nodebug

View File

@ -1,4 +1,5 @@
; JIT.ASM: Just-In-Time compiler for the Abstract Machine of the "Small"language ; AMXJITSN.ASM: Just-In-Time compiler for the Abstract Machine of the "Pawn"
; scripting language
; (C) 1999-2000, Marc Peter; beta version; provided AS IS WITHOUT ANY WARRANTIES ; (C) 1999-2000, Marc Peter; beta version; provided AS IS WITHOUT ANY WARRANTIES
; I reached >155 million instr./sec on my AMD K6-2/366 with the Hanoi "bench" ; I reached >155 million instr./sec on my AMD K6-2/366 with the Hanoi "bench"
@ -20,18 +21,54 @@
; step. ; step.
; NOTE 3: ; NOTE 3:
; During execution of the compiled code with amx_exec_asm() the x86 processor's ; During execution of the compiled code with amx_exec_jit() the x86 processor's
; stack is switched into the data section of the abstract machine. This means ; stack is switched into the data section of the abstract machine. This means
; that there should always be enough memory left between HEA and STK to provide ; that there should always be enough memory left between HEA and STK to provide
; stack space for occurring interrupts! (see the STACKRESERVE variable) ; stack space for occurring interrupts! (see the STACKRESERVE variable)
; NOTE 4: ; NOTE 4:
; Although the Small compiler doesn't generate the LCTRL, SCTRL and CALL.I ; Although the Pawn compiler doesn't generate the LCTRL, SCTRL and CALL.I
; instructions, I have to tell that they don't work as expected in a JIT ; instructions, I have to tell that they don't work as expected in a JIT
; compiled program, because there is no easy way of transforming AMX code ; compiled program, because there is no easy way of transforming AMX code
; addresses and JIT translated ones. This might be fixed in a future version. ; addresses and JIT translated ones. This might be fixed in a future version.
; NX ("No eXecute") and XD (eXecution Denied) bits
; (by Thiadmer Riemersma)
;
; AMD defined a bit "No eXecute" for the page table entries (for its 64-bit
; processors) and Intel came with the same design, but calling it differently.
; The purpose is to make "buffer overrun" security holes impossible, or at least
; very, very difficult, by marking the stack and the heap as memory regions
; such that an attempt to execute processor instructions will cause a processor
; exception (of course, a buffer overrun that is not explictly handled will then
; crash the application --instead of executing the rogue code).
;
; For JIT compilers, this has the impact that you are not allowed to execute the
; code that the JIT has generated. To do that, you must adjust the attributes
; for the memory page. For Microsoft Windows, you can use VirtualAlloc() to
; allocate a memory block with the appropriate fags; on Linux (with a recent
; kernel), you would use vmalloc_exec(). Microsoft Windows also offers the
; function VirtualProtect() to change the page attributes of an existing memory
; block, but there are caveats in its use: if the block spans multiple pages,
; these pages must be consecutive, and if there are blocks of memory in a page
; unrelated to the JIT, their page attributes will change too.
;
; The JIT compiler itself requires only read-write access (this is the default
; for a memory block that you allocate). The execution of the JIT-compiled code
; requires full access to the memory block: read, write and execute. It needs
; write access, because the SYSREQ.C opcode is patched to SYSREQ.D after the
; first lookup (this is an optimization, look up the address of the native
; function only once). For processors that do not support the NX/XD bit,
; execution of code is implicitly supported if read access is supported.
;
; During compilation, the JIT compiler requires write-access to its own code
; segment: the JIT-compiler patches P-code parameters into its own code segment
; during compilation. This is handled in the support code for amx_InitJIT.
;
;
; CALLING CONVENTIONS
; (by Thiadmer Riemersma)
; ;
; CALLING CONVENTIONS (by Thiadmer Riemersma)
; This version is the JIT that uses the "stack calling convention". In the ; This version is the JIT that uses the "stack calling convention". In the
; original implementation, this meant __cdecl; both for the calling convention ; original implementation, this meant __cdecl; both for the calling convention
; for the _asm_runJIT routine itself as for the callback functions. ; for the _asm_runJIT routine itself as for the callback functions.
@ -41,13 +78,13 @@
; macro, hence STDECL.) ; macro, hence STDECL.)
; Revision History ; Revision History
;------------------ ; ----------------
; 16 September 2004 by David "BAILOPAN" Anderson ; 17 february 2005 by Thiadmer Riemersms
; Implemented a compile time toggleable debug hook on OP_CALL and OP_RET. ; Addition of the BREAK opcode, removal of the older debugging opcode
; NOTE: JIT has not had debug hooks since 1999. ; table. There should now be some debug support (if enabled during the
; 8 September 2004 by David "BAILOPAN" Anderson ; build of the JIT compiler), but not enough to run a debugger: the JIT
; Changed OP_LINE call to be compile-time toggle-able between compiling ; compiler does not keep a list that relates the code addresses of the
; line ops or not. ; P-code versus the native code.
; 29 June 2004 by G.W.M. Vissers ; 29 June 2004 by G.W.M. Vissers
; Translated the thing into NASM. The actual generation of the code is ; Translated the thing into NASM. The actual generation of the code is
; put into the data section because the code modifies itself whereas the ; put into the data section because the code modifies itself whereas the
@ -94,8 +131,8 @@
; hanoi bench. ; hanoi bench.
; 1999/08/05 MP ; 1999/08/05 MP
; * fixed OP_LINE in the case of NODBGCALLS==1, where no compiled address ; * fixed OP_LINE in the case of NODBGCALLS==1, where no compiled address
; was stored for the LINE byte code (I.e. SWITCH would jump to totally ; was stored for the LINE byte code (i.e. SWITCH would jump to totally
; wrong addresses.) The same fix was applied to OP_FILL, OP_FILE and ; wrong addresses). The same fix was applied to OP_FILL, OP_FILE and
; OP_SCTRL (for the no-op case). ; OP_SCTRL (for the no-op case).
; 1999/08/04 MP ; 1999/08/04 MP
; * updated with 4 new opcodes (SRANGE does nothing at the moment; 2dim. ; * updated with 4 new opcodes (SRANGE does nothing at the moment; 2dim.
@ -107,6 +144,16 @@
; to compute the destination address: It searches backwards now. ; to compute the destination address: It searches backwards now.
; 1999/07/08 MP - initial revision ; 1999/07/08 MP - initial revision
;
; Support for the BREAK opcode (callback to the debugger): 0 = no, all other
; values = yes. Beware that the compiled code runs slower when this is enabled,
; and that debug support is still fairly minimal.
;
; GWMV: to generate LINE opcode, %define DEBUGSUPPORT
;
%undef DEBUGSUPPORT
; ;
; If this is set to 1 the JIT generates relocatable code for case tables, too. ; If this is set to 1 the JIT generates relocatable code for case tables, too.
; If set to 0, a faster variant for switch (using absolute addresses) is ; If set to 0, a faster variant for switch (using absolute addresses) is
@ -128,116 +175,14 @@
; ;
; This variable controls the generation of memory range checks at run-time. ; This variable controls the generation of memory range checks at run-time.
; You should set this to 0, only when you are sure that there are no range ; You should set this to 0, only when you are sure that there are no range
; violations in your Small programs and you really need those 5% speed gain. ; violations in your Pawn programs and you really need those 5% speed gain.
; ;
; GWMV: To disable runtime checks, %undef it, instread of setting it to zero ; GWMV: To disable runtime checks, %undef it, instread of setting it to zero
; ;
%define DORUNTIMECHECKS %define DORUNTIMECHECKS
%define JIT 1
struc amx_s %include "amxdefn.asm"
_base: resd 1
_dataseg: resd 1
_callback: resd 1
_debug: resd 1
_cip: resd 1
_frm: resd 1
_hea: resd 1
_hlw: resd 1
_stk: resd 1
_stp: resd 1
_flags: resd 1
_curline: resd 1
_curfile: resd 1
_dbgcode: resd 1
_dbgaddr: resd 1
_dbgparam: resd 1
_dbgname: resd 1
;usertags and userdata are 16 bytes on AMX Mod X
_usertags1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_usertags4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata1: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata2: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata3: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_userdata4: resd 1 ; 4 = AMX_USERNUM (#define'd in amx.h)
_error: resd 1
_pri: resd 1
_alt: resd 1
_reset_stk: resd 1
_reset_hea: resd 1
_syscall_d: resd 1
; the two fields below are for the JIT
; they are included in the non-JIT version for AMX Mod X
; this is to make sure that the structs match universally!
_reloc_size: resd 1 ; memory block for relocations
_code_size: resd 1 ; memory size of the native code
endstruc
struc amxhead_s
_size: resd 1 ; size of the "file"
_magic: resw 1 ; signature
_file_version: resb 1 ;file format version
_amx_version: resb 1 ; required version of the AMX
_h_flags: resw 1
_defsize: resw 1 ; size of one public/native function entry
_cod: resd 1 ; initial value of COD - code block
_dat: resd 1 ; initial value of DAT - data block
_h_hea: resd 1 ; initial value of HEA - start of the heap
_h_stp: resd 1 ; initial value of STP - stack top
_h_cip: resd 1 ; initial value of CIP - the instruction pointer
_publics: resd 1 ; offset to the "public functions" table
_natives: resd 1 ; offset to the "native functions" table
_libraries: resd 1 ; offset to the "library" table
_pubvars: resd 1 ; offset to the "public variables" table
_tags: resd 1 ; offset to the "public tagnames" table
endstruc
AMX_ERR_NONE equ 0
AMX_ERR_EXIT equ 1
AMX_ERR_ASSERT equ 2
AMX_ERR_STACKERR equ 3
AMX_ERR_BOUNDS equ 4
AMX_ERR_MEMACCESS equ 5
AMX_ERR_INVINSTR equ 6
AMX_ERR_STACKLOW equ 7
AMX_ERR_HEAPLOW equ 8
AMX_ERR_CALLBACK equ 9
AMX_ERR_NATIVE equ 10
AMX_ERR_DIVIDE equ 11 ; MP: added for catching divide errors
AMX_ERR_SLEEP equ 12 ; (TR) go into sleep mode
AMX_ERR_MEMORY equ 16
AMX_ERR_FORMAT equ 17
AMX_ERR_VERSION equ 18
AMX_ERR_NOTFOUND equ 19
AMX_ERR_INDEX equ 20
AMX_ERR_DEBUG equ 21
AMX_ERR_INIT equ 22
AMX_ERR_USERDATA equ 23
AMX_ERR_INIT_JIT equ 24
AMX_ERR_PARAMS equ 25
AMX_ERR_DOMAIN equ 26
DBG_INIT equ 0
DBG_FILE equ 1
DBG_LINE equ 2
DBG_SYMBOL equ 3
DBG_CLRSYM equ 4
DBG_CALL equ 5
DBG_RETURN equ 6
DBG_TERMINATE equ 7
DBG_SRANGE equ 8
DBG_SYMTAG equ 9
AMX_FLAG_CHAR16 equ 0001h ; characters are 16-bit
AMX_FLAG_DEBUG equ 0002h ; symbolic info. available
AMX_FLAG_LINEOPS equ 0020h ; line ops should be parsed [load time only flag] - ~dvander
AMX_FLAG_BROWSE equ 4000h
AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
; GWMV: ; GWMV:
; Nasm can't do the next as equivalence statements, since the value of ; Nasm can't do the next as equivalence statements, since the value of
@ -269,7 +214,7 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
; ;
; For determining the biggest native code section generated for ONE Small ; For determining the biggest native code section generated for ONE Pawn
; opcode. (See the following macro and the PUBLIC function getMaxCodeSize().) ; opcode. (See the following macro and the PUBLIC function getMaxCodeSize().)
; ;
; GWMV: Do NOT see the following macro. See CHECKCODESIZE instead. ; GWMV: Do NOT see the following macro. See CHECKCODESIZE instead.
@ -278,14 +223,6 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
; ;
; This is the work horse of the whole JIT: It actually copies the code. ; This is the work horse of the whole JIT: It actually copies the code.
; Notes from ~dvander (with help of dJeyL)
; This takes a source and ending address pointer in the assembled JIT code.
; Then it subtracts them and copies the code in between.
; The last parameter is the number of bytes the opcode is so it can jump
; to the next one.
; Also note that the "in between" code is NEVER executed during the compile
; phase of the JIT. It's only assembled in memory, and copied into the
; final output bytecode by this function.
%macro GO_ON 2-3 4 %macro GO_ON 2-3 4
mov esi, %1 ;get source address of JIT code mov esi, %1 ;get source address of JIT code
mov ecx,%2-%1 ;get number of bytes to copy mov ecx,%2-%1 ;get number of bytes to copy
@ -300,9 +237,7 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
; GWMV: ; GWMV:
; Nasm can't handle the determination of the maximum code size as was done ; Nasm can't handle the determination of the maximum code size as was done
; in the Masm implementation, since it only does two passes. This macro is ; in the Masm implementation, since it only does two passes. This macro is
; called *after* the code for each Small instruction. ; called *after* the code for each Pawn instruction.
; Notes by ~dvander: This just substracts a label's ip from the current ip.
; Therefore you get an instant size check - see RELOC
%macro CHECKCODESIZE 1 %macro CHECKCODESIZE 1
%if MAXCODESIZE < $-%1 %if MAXCODESIZE < $-%1
%assign MAXCODESIZE $-%1 %assign MAXCODESIZE $-%1
@ -310,14 +245,9 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
%endmacro %endmacro
; ;
; Modify the argument of an x86 instruction with the Small opcode's parameter ; Modify the argument of an x86 instruction with the Pawn opcode's parameter
; before copying the code. ; before copying the code.
; ;
; Notes by ~dvander (thanks to dJeyL) - this will take an address and modify
; the dword at it. Since the JIT copies already assembled code, you see
; things like "call 12345678h". This is an arbitrary value as putval
; will modify it in memory and then GO_ON will add it to the program.
; It is important to get the putval address right - it's in bytes.
%macro putval 1 %macro putval 1
mov eax,[ebx+4] mov eax,[ebx+4]
mov dword [%1],eax mov dword [%1],eax
@ -326,12 +256,7 @@ AMX_FLAG_RELOC equ 8000h ; jump/call addresses relocated
; ;
; Add an entry to the table of addresses which have to be relocated after the ; Add an entry to the table of addresses which have to be relocated after the
; code compilation is done. ; code compilation is done.
; Notes by ~dvander: This is sort of what amx_BrowseRelocate() does, although ;
; relocation is actually done after code generation (this just adds to a
; table). Like putval, this takes in an address and marks it to be
; rewritten. It is a good idea to just use labels to find relocation
; offsets (see OP_CALL and OP_RETN). After code generation, this table
; is browsed and the correct threaded jumps are placed.
%macro RELOC 1-2 ; adr, dest %macro RELOC 1-2 ; adr, dest
mov ebp,[reloc_num] mov ebp,[reloc_num]
%if %0 < 2 %if %0 < 2
@ -356,7 +281,7 @@ section .text
global asm_runJIT, _asm_runJIT global asm_runJIT, _asm_runJIT
global amx_exec_asm, _amx_exec_asm global amx_exec_jit, _amx_exec_jit
global getMaxCodeSize, _getMaxCodeSize global getMaxCodeSize, _getMaxCodeSize
@ -481,7 +406,7 @@ reloc_done:
ret ret
; GWMV: ; GWMV:
; The code below modifies itself to store the arguments to the Small opcodes ; The code below modifies itself to store the arguments to the Pawn opcodes
; in the compiled code. This is fine, but the .text section in an ELF executable ; in the compiled code. This is fine, but the .text section in an ELF executable
; is usually marked read-only, that's why this code is in the .data section. ; is usually marked read-only, that's why this code is in the .data section.
@ -817,7 +742,7 @@ OP_ALIGN_PRI:
CHECKCODESIZE j_align_pri CHECKCODESIZE j_align_pri
OP_ALIGN_ALT: OP_ALIGN_ALT:
;nop ;nop;
mov eax,4 mov eax,4
sub eax,[ebx+4] sub eax,[ebx+4]
mov dword [j_align_alt+1],eax mov dword [j_align_alt+1],eax
@ -1073,119 +998,22 @@ OP_RET:
;good ;good
OP_RETN: OP_RETN:
;nop; ;nop;
;save registers
push eax
push ebp
;get .amx flags
mov ebp,[amxhead]
mov eax,[ebp+_h_flags]
;check to see if the flag has line ops
and eax,AMX_FLAG_DEBUG
cmp eax,AMX_FLAG_DEBUG
;restore registers
pop ebp
pop eax
;if so, skip down to debug compiler
jmp _go_jit_retn_debug
_go_jit_retn_nodebug:
GO_ON j_retn_nodebug, _go_jit_retn_go
j_retn_nodebug:
jmp [jit_retn]
CHECKCODESIZE j_retn_nodebug
_go_jit_retn_go:
jmp _go_jit_retn_end
_go_jit_retn_debug:
GO_ON j_retn, OP_CALL GO_ON j_retn, OP_CALL
j_retn: j_retn:
push ebp
push eax
push edx
;get AMX
mov ebp,amx
;get debug call ptr
mov eax,[ebp+_userdata2]
;check validity
mov edx, dword 0
cmp eax, edx
je _go_jit_skip_debug
xchg esp,esi ;switch stack
push 1 ;param 2 mode 1 = pop
push ebp ;param 1 - amx
call eax ;indirect debug call
add esp, 8 ;restore stack
xchg esp,esi ;return to AMX stack
mov ebp,amx ;restore AMX [necessary?]
_go_jit_skip_debug:
pop edx
pop eax
pop ebp
jmp [jit_retn] jmp [jit_retn]
CHECKCODESIZE j_retn CHECKCODESIZE j_retn
_go_jit_retn_end:
;good ;good
OP_CALL: OP_CALL:
;nop; ;nop;
;save registers
push eax
push ebp
;get .amx flags
mov ebp,[amxhead]
mov eax,[ebp+_h_flags]
;check to see if the flag has line ops
and eax,AMX_FLAG_DEBUG
cmp eax,AMX_FLAG_DEBUG
;restore registers
pop ebp
pop eax
;if so, skip down to debug compiler
jmp _go_jit_debug
_go_jit_nodebug:
RELOC 1 RELOC 1
GO_ON j_call_nodebug, _j_call_go_on, 8
j_call_nodebug:
db 0e8h, 0, 0, 0, 0
CHECKCODESIZE j_call_nodebug
_j_call_go_on:
jmp _opcall_end
_go_jit_debug:
;thanks to Julien "dJeyL" Laurent for code relocation explanation
RELOC _go_jit_reloc-j_call+1
GO_ON j_call, OP_CALL_I, 8 GO_ON j_call, OP_CALL_I, 8
j_call: j_call:
; save some registers ;call 12345678h ; tasm chokes on this out of a sudden
push ebp
push eax
push edx
; get AMX
mov ebp,amx
; get debug call pointer
mov eax,[ebp+_userdata2]
; check to see if it's valid
mov edx, dword 0
cmp eax,edx
je _go_jit_skip_call
xchg esp,esi ;switch to caller stack
push 2 ;param mode=2, push
push ebp ;param amx
call eax ;indirect call
add esp, 8 ;restore stack
xchg esp,esi ;return to AMX stack
mov ebp,amx ;restore AMX [necessary?]
_go_jit_skip_call:
;restore original registers
pop edx
pop eax
pop ebp
_go_jit_reloc:
db 0e8h, 0, 0, 0, 0 db 0e8h, 0, 0, 0, 0
CHECKCODESIZE j_call CHECKCODESIZE j_call
_opcall_end:
OP_CALL_I: OP_CALL_I:
;nop; ;nop;
@ -1857,39 +1685,12 @@ OP_FILE: ;opcode is simply ignored
OP_LINE: OP_LINE:
;nop; ;nop;
;~dvander - opline is now variable on compile time :]
;save registers
push eax
push ebp
;get .amx flags
mov ebp,[amxhead]
mov eax,[ebp+_h_flags]
;check to see if the flag has line ops
and eax,AMX_FLAG_LINEOPS
cmp eax,AMX_FLAG_LINEOPS
;restore registers
pop ebp
pop eax
;if so, skip down to debug compiler
je _go_debug
mov [ebx],edi ; no line number support: ignore opcode mov [ebx],edi ; no line number support: ignore opcode
add ebx,12 ; move on to next opcode add ebx,12 ; move on to next opcode
cmp ebx,[end_code] cmp ebx,[end_code]
jae code_gen_done jae code_gen_done
jmp dword [ebx] ; go on with the next opcode jmp dword [ebx] ; go on with the next opcode
_go_debug:
putval j_line+6
mov eax,[ebx+8]
mov [j_line_sm],eax
GO_ON j_line, OP_SYMBOL, 12
j_line:
call [jit_line]
DD 0 ; space for curline
j_line_sm DD 0 ; space for curfile
CHECKCODESIZE j_line
OP_SYMBOL: ;ignored OP_SYMBOL: ;ignored
mov [ebx],edi mov [ebx],edi
mov eax,[ebx+4] ; get size mov eax,[ebx+4] ; get size
@ -2019,6 +1820,23 @@ OP_SYMTAG: ;ignored (TR)
jmp dword [ebx] ; go on with the next opcode jmp dword [ebx] ; go on with the next opcode
OP_BREAK:
%ifndef DEBUGSUPPORT
mov [ebx],edi ; no line number support: ignore opcode
add ebx,4 ; move on to next opcode
cmp ebx,[end_code]
jae code_gen_done
jmp DWORD [ebx] ; go on with the next opcode
%else
GO_ON j_break, OP_INVALID
j_break:
mov ebp,amx
cmp DWORD [ebp+_debug], 0
je $+4 ; jump around the "call" statement
call [jit_break]
CHECKCODESIZE j_break
%endif
OP_INVALID: ; break from the compiler with an error code OP_INVALID: ; break from the compiler with an error code
mov eax,AMX_ERR_INVINSTR mov eax,AMX_ERR_INVINSTR
pop esi pop esi
@ -2032,12 +1850,12 @@ section .text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ; ; ;
;cell asm_exec( cell *regs, cell *retval, cell stp, cell hea ); ;cell amx_exec( cell *regs, cell *retval, cell stp, cell hea );
; eax edx ebx ecx ; ; eax edx ebx ecx ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
amx_exec_asm: amx_exec_jit:
_amx_exec_asm: _amx_exec_jit:
push edi push edi
push esi push esi
push ebp push ebp
@ -2338,20 +2156,39 @@ JIT_OP_SYSREQ_D: ; (TR)
ret ret
JIT_OP_LINE: JIT_OP_BREAK:
pop ecx ; get return address %ifdef DEBUGSUPPORT
mov ebp,amx mov ecx,esp ; get STK into ECX
push eax mov ebp,amx ; get amx into EBP
push edx
mov eax,[ecx] ; get curline sub ecx,edi ; correct STK
mov edx,[ecx+4] ; get curfile
add ecx,8 ; skip curline & curfile mov [ebp+_pri],eax ; store values in AMX structure: PRI,
mov [ebp+_curline],eax ; store curline mov [ebp+_alt],edx ; ALT,
mov [ebp+_curfile],edx ; store curfile mov [ebp+_stk],ecx ; STK,
mov ecx,hea ; HEA,
mov ebx,frm ; and FRM
mov [ebp+_hea],ecx
mov [ebp+_frm],ebx ; EBX & ECX are invalid by now
;??? storing CIP is not very useful, because the code changed (during JIT compile)
xchg esp,esi ; switch to caller stack
push ebp ; 1st param: amx
call [ebp+_debug]
_DROPARGS 4 ; remove args from stack
xchg esp,esi ; switch back to AMX stack
cmp eax,AMX_ERR_NONE
jne _return_popstack; return error code, if any
mov ebp,amx ; get amx into EBP
mov eax,[ebp+_pri] ; restore values
mov edx,[ebp+_alt] ; ALT,
mov edx,alt ; restore ALT
mov ebx,frm ; restore FRM
add ebx,edi ; relocate frame
%endif
ret
pop edx
pop eax
jmp ecx ; jump back
JIT_OP_SWITCH: JIT_OP_SWITCH:
pop ebp ; pop return address = table address pop ebp ; pop return address = table address
@ -2370,9 +2207,10 @@ JIT_OP_SWITCH:
jmp ebp jmp ebp
%endif %endif
; The caller of asm_runJIT() can determine the maximum size of the compiled ; The caller of asm_runJIT() can determine the maximum size of the compiled
; code by multiplying the result of this function by the number of opcodes in ; code by multiplying the result of this function by the number of opcodes in
; Small module. ; Pawn module.
; ;
; unsigned long getMaxCodeSize_(); ; unsigned long getMaxCodeSize_();
; ;
@ -2414,17 +2252,17 @@ jit_fill DD JIT_OP_FILL
jit_bounds DD JIT_OP_BOUNDS jit_bounds DD JIT_OP_BOUNDS
jit_sysreq DD JIT_OP_SYSREQ jit_sysreq DD JIT_OP_SYSREQ
jit_sysreq_d DD JIT_OP_SYSREQ_D jit_sysreq_d DD JIT_OP_SYSREQ_D
jit_line DD JIT_OP_LINE jit_break DD JIT_OP_BREAK
jit_switch DD JIT_OP_SWITCH jit_switch DD JIT_OP_SWITCH
; ;
; The table for the browser/relocator function. ; The table for the browser/relocator function.
; ;
global amx_opcodelist, _amx_opcodelist global amx_opcodelist_jit, _amx_opcodelist_jit
amx_opcodelist: amx_opcodelist_jit:
_amx_opcodelist: _amx_opcodelist_jit:
DD OP_INVALID DD OP_INVALID
DD OP_LOAD_PRI DD OP_LOAD_PRI
DD OP_LOAD_ALT DD OP_LOAD_ALT
@ -2562,3 +2400,6 @@ _amx_opcodelist:
DD OP_NOP ; TR DD OP_NOP ; TR
DD OP_SYSREQ_D ; TR DD OP_SYSREQ_D ; TR
DD OP_SYMTAG ; TR DD OP_SYMTAG ; TR
DD OP_BREAK ; TR
END

View File

@ -353,7 +353,7 @@ static cell AMX_NATIVE_CALL is_linux_server(AMX *amx, cell *params)
static cell AMX_NATIVE_CALL is_amd64_server(AMX *amx, cell *params) static cell AMX_NATIVE_CALL is_amd64_server(AMX *amx, cell *params)
{ {
#if SMALL_CELL_SIZE==64 #if PAWN_CELL_SIZE==64
return 1; return 1;
#else #else
return 0; return 0;
@ -794,9 +794,10 @@ static cell AMX_NATIVE_CALL register_menucmd(AMX *amx, cell *params) /* 3 param
int ilen, idx; int ilen, idx;
char* sptemp = get_amxstring(amx,params[3],0,ilen); char* sptemp = get_amxstring(amx,params[3],0,ilen);
if(amx_FindPublic(amx, sptemp ,&idx)!=AMX_ERR_NONE) { idx = registerSPForwardByName(amx, sptemp, FP_CELL, FP_CELL, FP_DONE);
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",sptemp,plugin->getName() ); if (idx == -1)
amx_RaiseError(amx,AMX_ERR_NATIVE); {
LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", sptemp);
return 0; return 0;
} }
@ -870,9 +871,10 @@ static cell AMX_NATIVE_CALL register_concmd(AMX *amx, cell *params) /* 4 param *
CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx );
int i, idx = 0; int i, idx = 0;
char* temp = get_amxstring(amx,params[2],0, i ); char* temp = get_amxstring(amx,params[2],0, i );
if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); if (idx == -1)
amx_RaiseError(amx,AMX_ERR_NATIVE); {
LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp);
return 0; return 0;
} }
temp = get_amxstring(amx,params[1],0, i ); temp = get_amxstring(amx,params[1],0, i );
@ -897,9 +899,10 @@ static cell AMX_NATIVE_CALL register_clcmd(AMX *amx, cell *params) /* 4 param */
CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx );
int i, idx = 0; int i, idx = 0;
char* temp = get_amxstring(amx,params[2],0, i ); char* temp = get_amxstring(amx,params[2],0, i );
if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); if(idx==-1)
amx_RaiseError(amx,AMX_ERR_NATIVE); {
LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp);
return 0; return 0;
} }
temp = get_amxstring(amx,params[1],0, i ); temp = get_amxstring(amx,params[1],0, i );
@ -922,9 +925,10 @@ static cell AMX_NATIVE_CALL register_srvcmd(AMX *amx, cell *params) /* 2 param *
CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx ); CPluginMngr::CPlugin* plugin = g_plugins.findPluginFast( amx );
int i, idx = 0; int i, idx = 0;
char* temp = get_amxstring(amx,params[2],0, i ); char* temp = get_amxstring(amx,params[2],0, i );
if(amx_FindPublic(amx, temp ,&idx)!=AMX_ERR_NONE) { idx = registerSPForwardByName(amx, temp, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",temp,plugin->getName() ); if (idx==-1)
amx_RaiseError(amx,AMX_ERR_NATIVE); {
LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp);
return 0; return 0;
} }
temp = get_amxstring(amx,params[1],0, i ); temp = get_amxstring(amx,params[1],0, i );
@ -1023,10 +1027,10 @@ static cell AMX_NATIVE_CALL register_event(AMX *amx, cell *params) /* 2 param */
} }
sTemp = get_amxstring(amx,params[2],0,len); sTemp = get_amxstring(amx,params[2],0,len);
iFunction = registerSPForwardByName(amx, sTemp, FP_CELL, FP_DONE);
if ( amx_FindPublic(amx, sTemp , &iFunction) != AMX_ERR_NONE){ if (iFunction==-1)
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")",sTemp,plugin->getName() ); {
amx_RaiseError(amx,AMX_ERR_NATIVE); LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", sTemp);
return 0; return 0;
} }
@ -1874,20 +1878,9 @@ static cell AMX_NATIVE_CALL pause(AMX *amx, cell *params) /* 3 param */
CPluginMngr::CPlugin *plugin = 0; CPluginMngr::CPlugin *plugin = 0;
if ( flags & 2 ) { // pause function if ( flags & 2 )
if (flags&4){ //look out side the plugin { // pause function
temp = get_amxstring(amx,params[3],0,ilen); AMXXLOG_Log("[AMXX] This usage of the native pause() has been deprecated!");
plugin = g_plugins.findPlugin(temp);
}
else plugin = g_plugins.findPluginFast(amx);
if ( !plugin ) return 0; // plugin not found
temp = get_amxstring(amx,params[2],0,ilen);
int err, index;
if ((err = amx_FindPublic( plugin->getAMX(), temp , &index) )!= AMX_ERR_NONE){
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", temp,plugin->getName() );
return 0;
}
plugin->pauseFunction( index );
return 1; return 1;
} }
else if (flags&4){ else if (flags&4){
@ -1915,24 +1908,11 @@ static cell AMX_NATIVE_CALL unpause(AMX *amx, cell *params) /* 3 param */
char* sptemp = get_amxstring(amx,params[1],0,ilen); char* sptemp = get_amxstring(amx,params[1],0,ilen);
int flags = UTIL_ReadFlags(sptemp); int flags = UTIL_ReadFlags(sptemp);
CPluginMngr::CPlugin *plugin = 0; CPluginMngr::CPlugin *plugin = 0;
if (flags&2) { if (flags&2)
if (flags&4){ {
sptemp = get_amxstring(amx,params[3],0,ilen); AMXXLOG_Log("[AMXX] This usage of the native pause() has been deprecated!");
plugin = g_plugins.findPlugin(sptemp);
}
else
plugin = g_plugins.findPluginFast(amx);
if ( !plugin ) return 0;
sptemp = get_amxstring(amx,params[2],0,ilen);
int err, index;
if ((err = amx_FindPublic(plugin->getAMX(), sptemp , &index) )!= AMX_ERR_NONE){
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", sptemp,plugin->getName() );
return 0;
}
plugin->unpauseFunction( index );
return 1; return 1;
} } else if (flags&4) {
else if (flags&4){
sptemp = get_amxstring(amx,params[2],0,ilen); sptemp = get_amxstring(amx,params[2],0,ilen);
plugin = g_plugins.findPlugin(sptemp); plugin = g_plugins.findPlugin(sptemp);
} }
@ -2298,10 +2278,10 @@ static cell AMX_NATIVE_CALL register_logevent(AMX *amx, cell *params)
char* temp = get_amxstring(amx,params[1],0, a ); char* temp = get_amxstring(amx,params[1],0, a );
if (amx_FindPublic(amx, temp , &iFunc) != AMX_ERR_NONE){ iFunc = registerSPForwardByName(amx, temp, FP_DONE);
AMXXLOG_Log("[AMXX] Function is not present (function \"%s\") (plugin \"%s\")", if (iFunc == -1)
temp,plugin->getName() ); {
amx_RaiseError(amx,AMX_ERR_NATIVE); LogError(amx, AMX_ERR_NOTFOUND, "Function \"%s\" was not found", temp);
return 0; return 0;
} }
@ -2458,30 +2438,21 @@ static cell AMX_NATIVE_CALL get_module(AMX *amx, cell *params)
set_amxstring(amx, params[4], info && info->author ? info->author : "unk", params[5]); set_amxstring(amx, params[4], info && info->author ? info->author : "unk", params[5]);
set_amxstring(amx, params[6], info && info->version ? info->version : "unk", params[7]); set_amxstring(amx, params[6], info && info->version ? info->version : "unk", params[7]);
} }
else
{
module_info_s *info = (*moduleIter).getInfo();
set_amxstring(amx, params[2], info && info->name ? info->name : "unk", params[3]);
set_amxstring(amx, params[4], info && info->author ? info->author : "unk", params[5]);
set_amxstring(amx, params[6], info && info->version ? info->version : "unk", params[7]);
}
// compatibility problem possible // compatibility problem possible
int numParams = params[0] / sizeof(cell); int numParams = params[0] / sizeof(cell);
if (numParams < 8) if (numParams < 8)
{ {
CPluginMngr::CPlugin *curPlugin = g_plugins.findPluginFast(amx); LogError(amx, AMX_ERR_NATIVE, "Call to incompatible version");
AMXXLOG_Log("[AMXX] get_module: call to a previous version (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); return 0;
amx_RaiseError(amx, AMX_ERR_NATIVE);
} }
// set status // set status
cell *addr; cell *addr;
if (amx_GetAddr(amx, params[8], &addr) != AMX_ERR_NONE) if (amx_GetAddr(amx, params[8], &addr) != AMX_ERR_NONE)
{ {
CPluginMngr::CPlugin *curPlugin = g_plugins.findPluginFast(amx); LogError(amx, AMX_ERR_NATIVE, "Invalid reference plugin");
AMXXLOG_Log("[AMXX] get_module: invalid reference (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); return 0;
amx_RaiseError(amx, AMX_ERR_NATIVE);
} }
*addr = (cell)(*moduleIter).getStatusValue(); *addr = (cell)(*moduleIter).getStatusValue();
@ -2526,8 +2497,7 @@ static cell AMX_NATIVE_CALL callfunc_begin(AMX *amx, cell *params)
if (g_CallFunc_Plugin) if (g_CallFunc_Plugin)
{ {
// scripter's fault // scripter's fault
AMXXLOG_Log("[AMXX] callfunc_begin called without callfunc_end (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); LogError(amx, AMX_ERR_NATIVE, "callfunc_begin called without callfunc_end");
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
@ -2608,8 +2578,7 @@ static cell AMX_NATIVE_CALL callfunc_end(AMX *amx, cell *params)
if (!g_CallFunc_Plugin) if (!g_CallFunc_Plugin)
{ {
// scripter's fault // scripter's fault
AMXXLOG_Log("[AMXX] callfunc_end called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); LogError(amx, AMX_ERR_NATIVE, "callfunc_end called without callfunc_begin");
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
@ -2633,9 +2602,13 @@ static cell AMX_NATIVE_CALL callfunc_end(AMX *amx, cell *params)
g_CallFunc_CurParam = 0; g_CallFunc_CurParam = 0;
// actual call // actual call
if ((err = amx_Execv(plugin->getAMX(), &retVal, func, curParam, gparams)) != AMX_ERR_NONE) // Pawn - push parameters in reverse order
for (int i=curParam-1; i>=0; i--)
{
amx_Push(amx, gparams[i]);
}
if ((err = amx_Exec(plugin->getAMX(), &retVal, func) != AMX_ERR_NONE))
{ {
LogError(amx, err, "");
return 0; return 0;
} }
@ -2672,8 +2645,7 @@ static cell AMX_NATIVE_CALL callfunc_push_byval(AMX *amx, cell *params)
if (!g_CallFunc_Plugin) if (!g_CallFunc_Plugin)
{ {
// scripter's fault // scripter's fault
AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin");
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
@ -2698,15 +2670,13 @@ static cell AMX_NATIVE_CALL callfunc_push_byref(AMX *amx, cell *params)
if (!g_CallFunc_Plugin) if (!g_CallFunc_Plugin)
{ {
// scripter's fault // scripter's fault
AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin");
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS) if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS)
{ {
AMXXLOG_Log("[AMXX] callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS);
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
@ -2756,15 +2726,13 @@ static cell AMX_NATIVE_CALL callfunc_push_str(AMX *amx, cell *params)
if (!g_CallFunc_Plugin) if (!g_CallFunc_Plugin)
{ {
// scripter's fault // scripter's fault
AMXXLOG_Log("[AMXX] callfunc_push_xxx called without callfunc_begin (plugin \"%s\", line %d)", curPlugin->getName(), amx->curline); LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx called without callfunc_begin");
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS) if (g_CallFunc_CurParam == CALLFUNC_MAXPARAMS)
{ {
AMXXLOG_Log("[AMXX] callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS); LogError(amx, AMX_ERR_NATIVE, "callfunc_push_xxx: maximal parameters num: %d", CALLFUNC_MAXPARAMS);
amx_RaiseError(amx, AMX_ERR_NATIVE);
return 0; return 0;
} }
@ -2799,7 +2767,7 @@ static cell AMX_NATIVE_CALL callfunc_push_str(AMX *amx, cell *params)
// copy it to the allocated memory // copy it to the allocated memory
// we assume it's unpacked // we assume it's unpacked
// :NOTE: 4th parameter use_wchar since Small Abstract Machine 2.5.0 // :NOTE: 4th parameter use_wchar since Small Abstract Machine 2.5.0
amx_SetString(phys_addr, str, 0, 0); amx_SetString(phys_addr, str, 0, 0, 0);
// push the address and set the reference flag so that memory is released after function call. // push the address and set the reference flag so that memory is released after function call.
g_CallFunc_ParamInfo[g_CallFunc_CurParam].flags = CALLFUNC_FLAG_BYREF; g_CallFunc_ParamInfo[g_CallFunc_CurParam].flags = CALLFUNC_FLAG_BYREF;

View File

@ -68,7 +68,7 @@
#include "amxxlog.h" #include "amxxlog.h"
#define AMXXLOG_Log g_log.Log #define AMXXLOG_Log g_log.Log
#define AMX_VERSION "1.10-RC1" #define AMX_VERSION "1.50-RC1"
extern AMX_NATIVE_INFO core_Natives[]; extern AMX_NATIVE_INFO core_Natives[];
extern AMX_NATIVE_INFO time_Natives[]; extern AMX_NATIVE_INFO time_Natives[];
@ -244,7 +244,6 @@ enum CountModulesMode
int countModules(CountModulesMode mode); int countModules(CountModulesMode mode);
void modules_callPluginsLoaded(); void modules_callPluginsLoaded();
int add_amxnatives(module_info_s* info,AMX_NATIVE_INFO*natives);
cell* get_amxaddr(AMX *amx,cell amx_addr); cell* get_amxaddr(AMX *amx,cell amx_addr);
char* build_pathname(char *fmt, ... ); char* build_pathname(char *fmt, ... );
char* build_pathname_r(char *buffer, size_t maxlen, char *fmt, ...); char* build_pathname_r(char *buffer, size_t maxlen, char *fmt, ...);
@ -280,6 +279,7 @@ extern ModuleCallReason g_ModuleCallReason; // modules.cpp
extern CModule *g_CurrentlyCalledModule; // modules.cpp extern CModule *g_CurrentlyCalledModule; // modules.cpp
extern const char *g_LastRequestedFunc; // modules.cpp extern const char *g_LastRequestedFunc; // modules.cpp
void Module_CacheFunctions(); void Module_CacheFunctions();
void Module_UncacheFunctions();
void *Module_ReqFnptr(const char *funcName); // modules.cpp void *Module_ReqFnptr(const char *funcName); // modules.cpp
@ -297,6 +297,7 @@ extern int FF_PluginLog;
extern int FF_PluginEnd; extern int FF_PluginEnd;
extern int FF_InconsistentFile; extern int FF_InconsistentFile;
extern int FF_ClientAuthorized; extern int FF_ClientAuthorized;
extern bool g_coloredmenus;
#ifdef FAKEMETA #ifdef FAKEMETA
extern CFakeMeta g_FakeMeta; extern CFakeMeta g_FakeMeta;

View File

@ -364,19 +364,6 @@ static cell AMX_NATIVE_CALL amx_fclose(AMX *amx, cell *params)
} }
} }
static cell AMX_NATIVE_CALL amx_fgetc(AMX *amx, cell *params)
{
unsigned int id = params[1] - 1;
if (id >= FileList.size() || FileList.at(id) == NULL)
return 0;
FILE *fp = FileList.at(id);
if (fp) {
return fgetc(fp);
} else {
return -1;
}
}
static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params)
{ {
unsigned int id = params[1] - 1; unsigned int id = params[1] - 1;
@ -394,6 +381,20 @@ static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params)
return -1; return -1;
} }
#ifdef UNUSED
static cell AMX_NATIVE_CALL amx_fgetc(AMX *amx, cell *params)
{
unsigned int id = params[1] - 1;
if (id >= FileList.size() || FileList.at(id) == NULL)
return 0;
FILE *fp = FileList.at(id);
if (fp) {
return fgetc(fp);
} else {
return -1;
}
}
static cell AMX_NATIVE_CALL amx_fwrite(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_fwrite(AMX *amx, cell *params)
{ {
unsigned int id = params[1] - 1; unsigned int id = params[1] - 1;
@ -506,6 +507,7 @@ static cell AMX_NATIVE_CALL amx_ftell(AMX *amx, cell *params)
} }
return -1; return -1;
} }
#endif //UNUSED
static cell AMX_NATIVE_CALL amx_filesize(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_filesize(AMX *amx, cell *params)
{ {
@ -521,6 +523,7 @@ static cell AMX_NATIVE_CALL amx_filesize(AMX *amx, cell *params)
return -1; return -1;
} }
#ifdef UNUSED
static cell AMX_NATIVE_CALL amx_fgetl(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_fgetl(AMX *amx, cell *params)
{ {
unsigned int id = params[1] - 1; unsigned int id = params[1] - 1;
@ -636,6 +639,7 @@ static cell AMX_NATIVE_CALL amx_fputf(AMX *amx, cell *params)
} }
return -1; return -1;
} }
#endif //UNUSED
static cell AMX_NATIVE_CALL amx_build_pathname(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_build_pathname(AMX *amx, cell *params)
{ {
@ -723,8 +727,10 @@ AMX_NATIVE_INFO file_Natives[] = {
//Sanji's File Natives //Sanji's File Natives
{ "fopen", amx_fopen }, { "fopen", amx_fopen },
{ "fclose", amx_fclose }, { "fclose", amx_fclose },
{ "fgetc", amx_fgetc },
{ "fread", amx_fread }, { "fread", amx_fread },
{ "filesize", amx_filesize },
#ifdef UNUSED
{ "fgetc", amx_fgetc },
{ "fwrite", amx_fwrite }, { "fwrite", amx_fwrite },
{ "feof", amx_feof }, { "feof", amx_feof },
{ "fseek", amx_fseek }, { "fseek", amx_fseek },
@ -733,16 +739,16 @@ AMX_NATIVE_INFO file_Natives[] = {
{ "fflush", amx_fflush }, { "fflush", amx_fflush },
{ "fscanf", amx_fscanf }, { "fscanf", amx_fscanf },
{ "ftell", amx_ftell }, { "ftell", amx_ftell },
{ "filesize", amx_filesize },
{ "fgetl", amx_fgetl }, { "fgetl", amx_fgetl },
{ "fgeti", amx_fgeti }, { "fgeti", amx_fgeti },
{ "fgets", amx_fgets }, { "fgets", amx_fgets },
{ "fputs", amx_fputs }, { "fputs", amx_fputs },
{ "fputl", amx_fputl }, { "fputl", amx_fputl },
{ "fputi", amx_fputi }, { "fputi", amx_fputi },
{ "unlink", delete_file },
{ "fgetf", amx_fgetf }, { "fgetf", amx_fgetf },
{ "fputf", amx_fputf }, { "fputf", amx_fputf },
#endif
{ "unlink", delete_file },
{ "build_pathname", amx_build_pathname}, { "build_pathname", amx_build_pathname},
{ "dir_exists", dir_exists }, { "dir_exists", dir_exists },
{ "open_dir", amx_open_dir }, { "open_dir", amx_open_dir },

View File

@ -96,7 +96,7 @@ static cell AMX_NATIVE_CALL n_floatstr(AMX *amx,cell *params)
return 0; return 0;
/* Now convert the Small String into a C type null terminated string */ /* Now convert the Small String into a C type null terminated string */
amx_GetString(szSource, pString, 0); amx_GetStringOld(szSource, pString, 0);
/* Now convert this to a float. */ /* Now convert this to a float. */
fNum = (REAL)atof(szSource); fNum = (REAL)atof(szSource);

View File

@ -90,6 +90,7 @@ float g_auth_time;
bool g_initialized = false; bool g_initialized = false;
bool g_IsNewMM = false; bool g_IsNewMM = false;
bool g_NeedsP = false; bool g_NeedsP = false;
bool g_coloredmenus;
#ifdef MEMORY_TEST #ifdef MEMORY_TEST
float g_next_memreport_time; float g_next_memreport_time;
@ -605,7 +606,6 @@ void C_ClientCommand( edict_t *pEntity ) {
CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity); CPlayer *pPlayer = GET_PLAYER_POINTER(pEntity);
META_RES result = MRES_IGNORED; META_RES result = MRES_IGNORED;
cell ret = 0; cell ret = 0;
int err;
const char* cmd = CMD_ARGV(0); const char* cmd = CMD_ARGV(0);
const char* arg = CMD_ARGV(1); const char* arg = CMD_ARGV(1);
@ -665,10 +665,7 @@ void C_ClientCommand( edict_t *pEntity ) {
if ( (*aa).matchCommandLine( cmd , arg ) && if ( (*aa).matchCommandLine( cmd , arg ) &&
(*aa).getPlugin()->isExecutable( (*aa).getFunction() ) ) (*aa).getPlugin()->isExecutable( (*aa).getFunction() ) )
{ {
ret = executeForwards((*aa).getFunction(), pPlayer->index, (*aa).getFlags(), (*aa).getId());
if ((err =amx_Exec((*aa).getPlugin()->getAMX(), &ret , (*aa).getFunction() , 3, pPlayer->index, (*aa).getFlags(),(*aa).getId() )) != AMX_ERR_NONE)
LogError((*aa).getPlugin()->getAMX(), err, "");
if ( ret & 2 ) result = MRES_SUPERCEDE; if ( ret & 2 ) result = MRES_SUPERCEDE;
if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE); if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE);
} }
@ -695,33 +692,19 @@ void C_ClientCommand( edict_t *pEntity ) {
int menuid = pPlayer->menu; int menuid = pPlayer->menu;
pPlayer->menu = 0; pPlayer->menu = 0;
#ifdef ENABLEEXEPTIONS
try{
#endif
MenuMngr::iterator a = g_menucmds.begin(); MenuMngr::iterator a = g_menucmds.begin();
while( a ) while( a )
{ {
if ( (*a).matchCommand( menuid , bit_key ) && (*a).getPlugin()->isExecutable( (*a).getFunction() ) ) if ( (*a).matchCommand( menuid , bit_key ) && (*a).getPlugin()->isExecutable( (*a).getFunction() ) )
{ {
ret = executeForwards((*a).getFunction(), pPlayer->index, pressed_key);
if ( ( err = amx_Exec((*a).getPlugin()->getAMX(), &ret ,(*a).getFunction() , 2, pPlayer->index,pressed_key)) != AMX_ERR_NONE)
LogError((*a).getPlugin()->getAMX(), err, "");
if ( ret & 2 ) result = MRES_SUPERCEDE; if ( ret & 2 ) result = MRES_SUPERCEDE;
if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE); if ( ret & 1 ) RETURN_META(MRES_SUPERCEDE);
} }
++a; ++a;
} }
#ifdef ENABLEEXEPTIONS
}
catch( ... )
{
AMXXLOG_Log( "[AMXX] Fatal error at menu commmand execution");
}
#endif
} }
} }
/* check for PLUGIN_HANDLED_MAIN and block hl call if needed */ /* check for PLUGIN_HANDLED_MAIN and block hl call if needed */
@ -898,35 +881,6 @@ void C_WriteEntity_Post(int iValue) {
} }
void C_MessageEnd_Post(void) { void C_MessageEnd_Post(void) {
g_events.executeEvents(); g_events.executeEvents();
#if 0 // ######### this is done by call above
EventsMngr::iterator a = g_events.begin();
int err;
#ifdef ENABLEEXEPTIONS
try
{
#endif
while ( a )
{
if ((err = amx_Exec((*a).getPlugin()->getAMX(), NULL , (*a).getFunction() , 1, mPlayerIndex /*g_events.getArgInteger(0)*/ )) != AMX_ERR_NONE)
LogError((*a).getPlugin()->getAMX(), err, "");
++a;
}
#ifdef ENABLEEXEPTIONS
}
catch( ... )
{
AMXXLOG_Log( "[AMXX] Fatal error at event execution");
}
#endif
#endif
if (endfunction) (*endfunction)(NULL); if (endfunction) (*endfunction)(NULL);
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
@ -1134,6 +1088,13 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
a = &gameDir[i]; a = &gameDir[i];
g_mod_name.assign(a); g_mod_name.assign(a);
if (g_mod_name.compare("cstrike")==0 ||
g_mod_name.compare("czero")==0 ||
g_mod_name.compare("dod")==0)
g_coloredmenus = true;
else
g_coloredmenus = false;
// ###### Print short GPL // ###### Print short GPL
print_srvconsole( "\n AMX Mod X version %s Copyright (c) 2004-2005 AMX Mod X Development Team \n" print_srvconsole( "\n AMX Mod X version %s Copyright (c) 2004-2005 AMX Mod X Development Team \n"
" AMX Mod X comes with ABSOLUTELY NO WARRANTY; for details type `amxx gpl'.\n", AMX_VERSION); " AMX Mod X comes with ABSOLUTELY NO WARRANTY; for details type `amxx gpl'.\n", AMX_VERSION);
@ -1194,6 +1155,8 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) {
g_log.CloseFile(); g_log.CloseFile();
Module_UncacheFunctions();
return(TRUE); return(TRUE);
} }

View File

@ -95,7 +95,7 @@ void free_amxmemory(void **ptr)
int load_amxscript(AMX *amx, void **program, const char *filename, char error[64], int debug) int load_amxscript(AMX *amx, void **program, const char *filename, char error[64], int debug)
{ {
*error = 0; *error = 0;
CAmxxReader reader(filename, SMALL_CELL_SIZE / 8); CAmxxReader reader(filename, PAWN_CELL_SIZE / 8);
if (reader.GetStatus() == CAmxxReader::Err_None) if (reader.GetStatus() == CAmxxReader::Err_None)
{ {
size_t bufSize = reader.GetBufferSize(); size_t bufSize = reader.GetBufferSize();
@ -153,24 +153,35 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
return (amx->error = AMX_ERR_FORMAT); return (amx->error = AMX_ERR_FORMAT);
} }
if ( (int)CVAR_GET_FLOAT("amx_debug") >= 2 || debug)
{
//automatic debug mode
hdr->flags |= AMX_FLAG_LINEOPS;
hdr->flags |= AMX_FLAG_DEBUG;
}
int err; int err;
memset(amx, 0, sizeof(*amx)); memset(amx, 0, sizeof(*amx));
if ((int)CVAR_GET_FLOAT("amx_debug") >= 2 || debug)
{
if ((amx->flags & AMX_FLAG_DEBUG) != 0)
{
//:TODO: debug support
}
} else {
#ifdef JIT
//if (hdr->file_version == CUR_FILE_VERSION)
amx->flags |= AMX_FLAG_JITC;
#endif
}
if ((err = amx_Init( amx, *program )) != AMX_ERR_NONE) if ((err = amx_Init( amx, *program )) != AMX_ERR_NONE)
{ {
sprintf(error,"Load error %d (invalid file format or version)", err); sprintf(error,"Load error %d (invalid file format or version)", err);
return (amx->error = AMX_ERR_INIT); return (amx->error = AMX_ERR_INIT);
} }
LOG_MESSAGE(PLID, "AMX: %p FLAGS: %d\n", amx, amx->flags);
#ifdef JIT #ifdef JIT
void *np = new char[ amx->code_size ]; if (amx->flags & AMX_FLAG_JITC)
void *rt = new char[ amx->reloc_size ]; {
char *np = new char[ amx->code_size ];
char *rt = new char[ amx->reloc_size ];
if ( !np || (!rt && amx->reloc_size > 0) ) if ( !np || (!rt && amx->reloc_size > 0) )
{ {
delete[] np; delete[] np;
@ -179,7 +190,7 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
return (amx->error = AMX_ERR_INIT); return (amx->error = AMX_ERR_INIT);
} }
if ( (err = amx_InitJIT(amx, rt, np)) == AMX_ERR_NONE ) if ( (err = amx_InitJIT(amx, (void *)rt, (void *)np)) == AMX_ERR_NONE )
{ {
//amx->base = (unsigned char FAR *)realloc( np, amx->code_size ); //amx->base = (unsigned char FAR *)realloc( np, amx->code_size );
#ifndef __linux__ #ifndef __linux__
@ -193,7 +204,8 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
memcpy( amx->base , np , amx->code_size ); memcpy( amx->base , np , amx->code_size );
delete[] np; delete[] np;
delete[] rt; delete[] rt;
delete[] *program; char *prg = (char *)(*program);
delete[] *prg;
(*program) = amx->base; (*program) = amx->base;
if ( *program == 0 ){ if ( *program == 0 ){
strcpy(error,"Failed to allocate memory"); strcpy(error,"Failed to allocate memory");
@ -207,6 +219,7 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
sprintf(error, "Failed to initialize plugin (%d)", err); sprintf(error, "Failed to initialize plugin (%d)", err);
return (amx->error = AMX_ERR_INIT_JIT); return (amx->error = AMX_ERR_INIT_JIT);
} }
}
#endif #endif
@ -219,7 +232,6 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
} }
g_loadedscripts.put( aa ); g_loadedscripts.put( aa );
amx->sysreq_d = 0;
return set_amxnatives(amx,error); return set_amxnatives(amx,error);
} }
@ -345,7 +357,8 @@ int unload_amxscript(AMX* amx, void** program)
{ {
CList<CScript,AMX*>::iterator a = g_loadedscripts.find( amx ); CList<CScript,AMX*>::iterator a = g_loadedscripts.find( amx );
if ( a ) a.remove(); if ( a ) a.remove();
delete[] *program; char *prg = (char *)*program;
delete[] *prg;
*program = 0; *program = 0;
return AMX_ERR_NONE; return AMX_ERR_NONE;
} }
@ -469,27 +482,6 @@ char* build_pathname_addons(char *fmt, ... )
return string; return string;
} }
int add_amxnatives(module_info_s* info,AMX_NATIVE_INFO*natives)
{
CList<CModule,const char *>::iterator a = g_modules.begin();
while ( a )
{
if ( (*a).getInfo() == info )
{
AMX_NATIVE_INFO** aa = new AMX_NATIVE_INFO*(natives);
if ( aa == 0 ) return AMX_ERR_NATIVE;
(*a).m_Natives.put( aa );
return AMX_ERR_NONE;
}
++a;
}
return AMX_ERR_NATIVE;
}
bool validFile(const char* file) bool validFile(const char* file)
{ {
const char* a = 0; const char* a = 0;
@ -505,7 +497,7 @@ bool validFile(const char* file)
void ConvertModuleName(const char *pathString, String &path) void ConvertModuleName(const char *pathString, String &path)
{ {
#if SMALL_CELL_SIZE==64 #if PAWN_CELL_SIZE==64
char *ptr = strstr(pathString, "i386"); char *ptr = strstr(pathString, "i386");
if (ptr) if (ptr)
{ {
@ -600,7 +592,7 @@ void ConvertModuleName(const char *pathString, String &path)
} }
} }
#endif //__linux__ #endif //__linux__
#endif //SMALL_CELL_SIZE==64 #endif //PAWN_CELL_SIZE==64
} }
int loadModules(const char* filename, PLUG_LOADTIME now) int loadModules(const char* filename, PLUG_LOADTIME now)
@ -931,9 +923,13 @@ int MNF_AddNatives(AMX_NATIVE_INFO* natives)
const char *MNF_GetModname(void) const char *MNF_GetModname(void)
{ {
// :TODO: Do we have to do this?? // :TODO: Do we have to do this??
// I dunno who wrote the above comment but no
#if 0
static char buffer[64]; static char buffer[64];
strcpy(buffer, g_mod_name.c_str()); strcpy(buffer, g_mod_name.c_str());
return buffer; return buffer;
#endif
return g_mod_name.c_str();
} }
AMX *MNF_GetAmxScript(int id) AMX *MNF_GetAmxScript(int id)
@ -1169,13 +1165,17 @@ REAL MNF_CellToReal(cell x)
return *(REAL*)&x; return *(REAL*)&x;
} }
#ifdef __linux__
#define _vsnprintf vsnprintf
#endif
void MNF_Log(const char *fmt, ...) void MNF_Log(const char *fmt, ...)
{ {
// :TODO: Overflow possible here
char msg[3072]; char msg[3072];
va_list arglst; va_list arglst;
va_start(arglst, fmt); va_start(arglst, fmt);
vsprintf(msg, fmt, arglst); _vsnprintf(msg, sizeof(msg)-1, fmt, arglst);
//vsprintf(msg, fmt, arglst);
va_end(arglst); va_end(arglst);
AMXXLOG_Log("%s", msg); AMXXLOG_Log("%s", msg);
} }
@ -1220,7 +1220,7 @@ void GenericError(AMX *amx, int err, int line, char buf[], const char *file)
geterr = NULL; geterr = NULL;
else else
geterr = amx_errs[err]; geterr = amx_errs[err];
if (!(amx->flags & AMX_FLAG_LINEOPS)) if (!(amx->flags & AMX_FLAG_DEBUG))
{ {
if (geterr == NULL) if (geterr == NULL)
{ {
@ -1250,7 +1250,7 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
{ {
//does this plugin have debug info? //does this plugin have debug info?
va_list arg; va_list arg;
AMX_DBG *dbg = (AMX_DBG *)(amx->userdata[0]); //AMX_DBG *dbg = (AMX_DBG *)(amx->userdata[0]);
static char buf[1024]; static char buf[1024];
static char vbuf[1024]; static char vbuf[1024];
*buf = 0; *buf = 0;
@ -1259,7 +1259,7 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
va_start(arg, fmt); va_start(arg, fmt);
vsprintf(vbuf, fmt, arg); vsprintf(vbuf, fmt, arg);
va_end(arg); va_end(arg);
#if 0
if (!dbg || !(dbg->tail)) if (!dbg || !(dbg->tail))
{ {
if (dbg && amx->curfile < dbg->numFiles && amx->curfile >= 0) if (dbg && amx->curfile < dbg->numFiles && amx->curfile >= 0)
@ -1313,6 +1313,8 @@ void LogError(AMX *amx, int err, const char *fmt, ...)
t = dbg->tail; t = dbg->tail;
} }
} }
#endif
amx_RaiseError(amx, err);
} }
void MNF_MergeDefinitionFile(const char *file) void MNF_MergeDefinitionFile(const char *file)
@ -1386,7 +1388,7 @@ const char *g_LastRequestedFunc = NULL;
#define REGISTER_FUNC(name, func) \ #define REGISTER_FUNC(name, func) \
{ \ { \
pFunc = new func_s; \ pFunc = new func_s; \
pFunc->pfn = func; \ pFunc->pfn = (void *)func; \
pFunc->desc = name; \ pFunc->desc = name; \
g_functions.put(pFunc); \ g_functions.put(pFunc); \
} }
@ -1398,6 +1400,16 @@ void MNF_RegisterFunction(void *pfn, const char *description)
REGISTER_FUNC(description, pfn); REGISTER_FUNC(description, pfn);
} }
void Module_UncacheFunctions()
{
g_functions.clear();
}
int amx_Execv()
{
return AMX_ERR_NOTFOUND;
}
void Module_CacheFunctions() void Module_CacheFunctions()
{ {
func_s *pFunc; func_s *pFunc;
@ -1430,7 +1442,7 @@ void Module_CacheFunctions()
// other amx stuff // other amx stuff
REGISTER_FUNC("amx_Exec", amx_Exec) REGISTER_FUNC("amx_Exec", amx_Exec)
REGISTER_FUNC("amx_Execv", amx_Execv) REGISTER_FUNC("amx_Execv", amx_Execv) //I HOPE NO ONE USES THIS!!!!
REGISTER_FUNC("amx_Allot", amx_Allot) REGISTER_FUNC("amx_Allot", amx_Allot)
REGISTER_FUNC("amx_FindPublic", amx_FindPublic) REGISTER_FUNC("amx_FindPublic", amx_FindPublic)
REGISTER_FUNC("amx_FindNative", amx_FindNative) REGISTER_FUNC("amx_FindNative", amx_FindNative)

View File

@ -45,135 +45,8 @@
#undef C_DLLEXPORT #undef C_DLLEXPORT
#define C_DLLEXPORT extern "C" DLLEXPORT #define C_DLLEXPORT extern "C" DLLEXPORT
#define AMX_INTERFACE_VERSION 6
#define RELOAD_MODULE 0 #define RELOAD_MODULE 0
#define STATIC_MODULE 1 #define STATIC_MODULE 1
struct module_info_s {
const char* name;
const char* author;
const char* version;
int ivers;
int type;
long int serial;
};
// Small scripting language
struct pfnamx_engine_g {
uint16_t* (*pfnamx_Align16)(uint16_t *); // value
uint32_t* (*pfnamx_Align32)(uint32_t *); // value
int (*pfnamx_Allot)(AMX*, int, cell*, cell**); // amx, length, amx_addr, phys_addr
int (*pfnamx_Callback)(AMX*, cell , cell*, cell*); // amx, index,result,params
int (*pfnamx_Clone)(AMX*, AMX*, void*); // amxClone, amxSrc, data
int (*pfnamx_Debug)(AMX*); // default debug procedure, does nothing // amx
int (*pfnamx_Exec)(AMX*, cell*, int , int , ...); // amx, return val, index, num_params, ...
int (*pfnamx_Execv)(AMX*, cell*, int , int, cell[]); // amx, return val, index, num_params, param[]
int (*pfnamx_FindPublic)(AMX*, char*, int*); // amx, func name, index
int (*pfnamx_FindPubVar)(AMX*, char*, cell*); // anx, var name, amx_addr
int (*pfnamx_FindTagId)(AMX*, cell , char*); // amx. tag_id, tagname
int (*pfnamx_Flags)(AMX*,uint16_t *); // amx, flags
int (*pfnamx_GetAddr)(AMX*,cell ,cell**); // amx, amx_addr, phys_addr
int (*pfnamx_GetPublic)(AMX*, int , char*); // amx, index, funcname
int (*pfnamx_GetPubVar)(AMX*, int , char*, cell*); // amx, index, varname, amx_addr
int (*pfnamx_GetString)(char*dest,cell*); // dest, source
int (*pfnamx_GetTag)(AMX*, int , char*, cell*); // amx, index, tagname, tag_id
int (*pfnamx_GetUserData)(AMX*, long , void **); // amx, tag, ptr
int (*pfnamx_Init)(AMX*, void *); // amx, program
int (*pfnamx_InitJIT)(AMX*, void *, void *); // amx, reloc_table, native_code
int (*pfnamx_MemInfo)(AMX*, long*, long*, long*); // amx, codesize, datasize, stackheap
int (*pfnamx_NameLength)(AMX*, int*); // amx, length
AMX_NATIVE_INFO * (*pfnamx_NativeInfo)(char*,AMX_NATIVE ); // name, func
int (*pfnamx_NumPublics)(AMX*, int*); // amx, number
int (*pfnamx_NumPubVars)(AMX*, int*); // amx, number
int (*pfnamx_NumTags)(AMX*, int*); // amx, number
int (*pfnamx_RaiseError)(AMX*, int ); // amx, error
int (*pfnamx_Register)(AMX*, AMX_NATIVE_INFO*, int ); // amx, nativelist, number
int (*pfnamx_Release)(AMX*, cell ); // amx, amx_addr
int (*pfnamx_SetCallback)(AMX*, AMX_CALLBACK ); // amx, callback
int (*pfnamx_SetDebugHook)(AMX*, AMX_DEBUG ); // amx, debug
int (*pfnamx_SetString)(cell*, char*, int ); // dest, source, pack
int (*pfnamx_SetUserData)(AMX*, long , void*); // amx, tag, prt
int (*pfnamx_StrLen)(cell*, int*); // amx, cstring, length
};
extern pfnamx_engine_g* g_engAmxFunc;
#define AMX_ALIGN16 (*g_engAmxFunc->pfnamx_Align16)
#define AMX_ALIGN32 (*g_engAmxFunc->pfnamx_Align32)
#define AMX_ALLOT (*g_engAmxFunc->pfnamx_Allot)
#define AMX_CALLBACK (*g_engAmxFunc->pfnamx_Callback)
#define AMX_CLONE (*g_engAmxFunc->pfnamx_Clone)
#define AMX_DEBUG (*g_engAmxFunc->pfnamx_Debug)
#define AMX_EXEC (*g_engAmxFunc->pfnamx_Exec)
#define AMX_EXECV (*g_engAmxFunc->pfnamx_Execv)
#define AMX_FINDPUBLIC (*g_engAmxFunc->pfnamx_FindPublic)
#define AMX_FINDPUBVAR (*g_engAmxFunc->pfnamx_FindPubVar)
#define AMX_FINDTAGID (*g_engAmxFunc->pfnamx_FindTagId)
#define AMX_FLAGS (*g_engAmxFunc->pfnamx_Flags)
#define AMX_GETADDR (*g_engAmxFunc->pfnamx_GetAddr)
#define AMX_GETPUBLIC (*g_engAmxFunc->pfnamx_GetPublic)
#define AMX_GETPUBVAR (*g_engAmxFunc->pfnamx_GetPubVar)
#define AMX_GETSTRING (*g_engAmxFunc->pfnamx_GetString)
#define AMX_GETTAG (*g_engAmxFunc->pfnamx_GetTag)
#define AMX_GETUSERDATA (*g_engAmxFunc->pfnamx_GetUserData)
#define AMX_INIT (*g_engAmxFunc->pfnamx_Init)
#define AMX_INITJIT (*g_engAmxFunc->pfnamx_InitJIT)
#define AMX_MEMINFO (*g_engAmxFunc->pfnamx_MemInfo)
#define AMX_NAMELENGTH (*g_engAmxFunc->pfnamx_NameLength)
#define AMX_NATIVEINFO (*g_engAmxFunc->pfnamx_NativeInfo)
#define AMX_NUMPUBLICS (*g_engAmxFunc->pfnamx_NumPublics)
#define AMX_NUMPUBVARS (*g_engAmxFunc->pfnamx_NumPubVars)
#define AMX_NUMTAGS (*g_engAmxFunc->pfnamx_NumTags)
#define AMX_RAISEERROR (*g_engAmxFunc->pfnamx_RaiseError)
#define AMX_REGISTER (*g_engAmxFunc->pfnamx_Register)
#define AMX_RELEASE (*g_engAmxFunc->pfnamx_Release)
#define AMX_SETCALLBACK (*g_engAmxFunc->pfnamx_SetCallback)
#define AMX_SETDEBUGHOOK (*g_engAmxFunc->pfnamx_SetDebugHook)
#define AMX_SETSTRING (*g_engAmxFunc->pfnamx_SetString)
#define AMX_SETUSERDATA (*g_engAmxFunc->pfnamx_SetUserData)
#define AMX_STRLEN (*g_engAmxFunc->pfnamx_StrLen)
// Modules API
struct pfnmodule_engine_g {
int (*pfnadd_amxnatives)(module_info_s*,AMX_NATIVE_INFO*); // list
char* (*pfnbuild_pathname)(char*, ...); // format, ....
void (*pfncopy_amxmemory)(cell*,cell*,int); // dest, src, len
char* (*pfnformat_amxstring)(AMX*, cell*, int ,int& ); // amx, format, start pos, len
cell* (*pfnget_amxaddr)(AMX*,cell ); // amx, cell
AMX* (*pfnget_amxscript)(int, void**,const char**); // id, code, name
const char* (*pfnget_amxscriptname)(AMX* amx); // amx
char* (*pfnget_amxstring)(AMX*,cell,int, int&); // amx, src, buffer (0-3), len
void (*pfnget_modname)(char*); // modname
int (*pfnload_amxscript)(AMX*, void**, const char*, char[64], int); // amx, code, path, error info
void (*pfnprint_console)(char*, ...); // format, ....
void (*pfnreport_error)(int code, char*, ... );
int (*pfnset_amxnatives)(AMX*,char[64]); // amx, error info
int (*pfnset_amxstring)(AMX*,cell ,const char*,int); // amx, dest, string, maxlen
int (*pfnamxstring_length)(cell*); // src
int (*pfnunload_amxscript)(AMX* amx,void**); // amx, code
void* (*pfnalloc_amxmemory)(void**,int size);
void (*pfnfree_amxmemory)(void**);
};
extern pfnmodule_engine_g* g_engModuleFunc;
#define ADD_AMXNATIVES (*g_engModuleFunc->pfnadd_amxnatives)
#define AMXSTRING_LENGTH (*g_engModuleFunc->pfnamxstring_length)
#define BUILD_PATHNAME (*g_engModuleFunc->pfnbuild_pathname)
#define COPY_AMXMEMORY (*g_engModuleFunc->pfncopy_amxmemory)
#define FORMAT_AMXSTRING (*g_engModuleFunc->pfnformat_amxstring)
#define GET_AMXADDR (*g_engModuleFunc->pfnget_amxaddr)
#define GET_AMXSCRIPT (*g_engModuleFunc->pfnget_amxscript)
#define GET_AMXSCRIPTNAME (*g_engModuleFunc->pfnget_amxscriptname)
#define GET_AMXSTRING (*g_engModuleFunc->pfnget_amxstring)
#define GET_MODNAME (*g_engModuleFunc->pfnget_modname)
#define LOAD_AMXSCRIPT (*g_engModuleFunc->pfnload_amxscript)
#define PRINT_CONSOLE (*g_engModuleFunc->pfnprint_console)
#define REPORT_ERROR (*g_engModuleFunc->pfnreport_error)
#define SET_AMXNATIVES (*g_engModuleFunc->pfnset_amxnatives)
#define SET_AMXSTRING (*g_engModuleFunc->pfnset_amxstring)
#define UNLOAD_AMXSCRIPT (*g_engModuleFunc->pfnunload_amxscript)
#define ALLOC_AMXMEMORY (*g_engModuleFunc->pfnalloc_amxmemory)
#define FREE_AMXMEMORY (*g_engModuleFunc->pfnfree_amxmemory)
#endif // __MODULES_H__ #endif // __MODULES_H__

View File

@ -300,7 +300,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\pm_shared&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\dlls&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\engine&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\common&quot;;C:\Files\Programming\metamod\metamod" AdditionalIncludeDirectories="&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\pm_shared&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\dlls&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\engine&quot;;&quot;C:\Hry\Half-Life\SDK\Multiplayer Source\common&quot;;C:\Files\Programming\metamod\metamod"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;PAWN_CELL_SIZE=32;ASM32;JIT"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="5" RuntimeLibrary="5"
StructMemberAlignment="3" StructMemberAlignment="3"
@ -319,7 +319,7 @@
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386" AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="..\jit\jits.obj ..\zlib\zlib.lib" AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj"
OutputFile="jitdebug/amxmodx_mm.dll" OutputFile="jitdebug/amxmodx_mm.dll"
Version="0.1" Version="0.1"
LinkIncremental="1" LinkIncremental="1"
@ -371,7 +371,8 @@
InlineFunctionExpansion="1" InlineFunctionExpansion="1"
FavorSizeOrSpeed="1" FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..\..\metamod\metamod,..\..\hlsdk\sourcecode\common,..\..\hlsdk\sourcecode\engine,..\..\hlsdk\sourcecode\dlls,..\..\hlsdk\sourcecode\pm_shared,..\extra\include" AdditionalIncludeDirectories="..\..\metamod\metamod,..\..\hlsdk\sourcecode\common,..\..\hlsdk\sourcecode\engine,..\..\hlsdk\sourcecode\dlls,..\..\hlsdk\sourcecode\pm_shared,..\extra\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT;ASM32;PAWN_CELL_SIZE=32"
IgnoreStandardIncludePath="FALSE"
StringPooling="TRUE" StringPooling="TRUE"
RuntimeLibrary="4" RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE" EnableFunctionLevelLinking="TRUE"
@ -389,7 +390,7 @@
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386" AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="..\jit\jits.obj ..\zlib\zlib.lib" AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj"
OutputFile="jitrelease/amxmodx_mm.dll" OutputFile="jitrelease/amxmodx_mm.dll"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="TRUE" SuppressStartupBanner="TRUE"
@ -649,6 +650,9 @@
<File <File
RelativePath="..\md5.cpp"> RelativePath="..\md5.cpp">
</File> </File>
<File
RelativePath="..\menus.cpp">
</File>
<File <File
RelativePath="..\meta_api.cpp"> RelativePath="..\meta_api.cpp">
</File> </File>
@ -780,6 +784,9 @@
<File <File
RelativePath="..\md5.h"> RelativePath="..\md5.h">
</File> </File>
<File
RelativePath="..\menus.h">
</File>
<File <File
RelativePath="..\modules.h"> RelativePath="..\modules.h">
</File> </File>

View File

@ -150,14 +150,14 @@ void amx_command(){
print_srvconsole( "%s %s\n", Plugin_info.name, Plugin_info.version); print_srvconsole( "%s %s\n", Plugin_info.name, Plugin_info.version);
print_srvconsole( "Authors: %s (%s)\n", "Felix \"SniperBeamer\" Geyer, David \"BAILOPAN\" Anderson, Pavol \"PM OnoTo\" Marko, Jonny \"Got His Gun\" Bergstrom, and Lukasz \"SidLuke\" Wlasinski.", Plugin_info.url); print_srvconsole( "Authors: %s (%s)\n", "Felix \"SniperBeamer\" Geyer, David \"BAILOPAN\" Anderson, Pavol \"PM OnoTo\" Marko, Jonny \"Got His Gun\" Bergstrom, and Lukasz \"SidLuke\" Wlasinski.", Plugin_info.url);
print_srvconsole( "Compiled: %s\n", __DATE__ ", " __TIME__); print_srvconsole( "Compiled: %s\n", __DATE__ ", " __TIME__);
#ifdef JIT #if defined JIT && !defined ASM32
print_srvconsole( "Core mode: JIT\n"); print_srvconsole( "Core mode: JIT Only\n");
#else #elif !defined JIT && defined ASM32
#ifdef ASM32 print_srvconsole( "Core mode: ASM32 Only\n");
print_srvconsole( "Core mode: ASM\n"); #elif defined JIT && defined ASM32
print_srvconsole( "Core mode: JIT+ASM32\n");
#else #else
print_srvconsole( "Core mode: Normal\n"); print_srvconsole( "Core mode: Normal\n");
#endif
#endif #endif
} }
else if (!strcmp(cmd,"modules")) else if (!strcmp(cmd,"modules"))
@ -264,15 +264,9 @@ void amx_command(){
void plugin_srvcmd() void plugin_srvcmd()
{ {
cell ret = 0; cell ret = 0;
int err;
const char* cmd = CMD_ARGV(0); const char* cmd = CMD_ARGV(0);
#ifdef ENABLEEXEPTIONS
try{
#endif
CmdMngr::iterator a = g_commands.srvcmdbegin(); CmdMngr::iterator a = g_commands.srvcmdbegin();
while ( a ) while ( a )
@ -280,23 +274,9 @@ void plugin_srvcmd()
if ( (*a).matchCommand( cmd ) && if ( (*a).matchCommand( cmd ) &&
(*a).getPlugin()->isExecutable( (*a).getFunction() ) ) (*a).getPlugin()->isExecutable( (*a).getFunction() ) )
{ {
cell ret = executeForwards((*a).getFunction(), g_srvindex, (*a).getFlags(), (*a).getId());
if ((err = amx_Exec( (*a).getPlugin()->getAMX(), &ret , (*a).getFunction()
, 3 , g_srvindex , (*a).getFlags() , (*a).getId() )) != AMX_ERR_NONE)
{
LogError((*a).getPlugin()->getAMX(), err, "");
}
if ( ret ) break; if ( ret ) break;
} }
++a; ++a;
} }
#ifdef ENABLEEXEPTIONS
}catch( ... )
{
AMXXLOG_Log( "[AMXX] fatal error at forward function execution");
}
#endif
} }

View File

@ -471,7 +471,7 @@ static cell AMX_NATIVE_CALL amx_strtok(AMX *amx, cell *params)
char token = params[6]; char token = params[6];
//trim //trim
int trim = params[7]; int trim = params[7];
for (i=0; i<len; i++) for (i=0; i<(unsigned int)len; i++)
{ {
if (trim && !done_flag) if (trim && !done_flag)
{ {
@ -521,7 +521,7 @@ static cell AMX_NATIVE_CALL strbreak(AMX *amx, cell *params) /* 5 param */
int LeftMax = params[3]; int LeftMax = params[3];
int RightMax = params[5]; int RightMax = params[5];
for (i=0; i<l; i++) { for (i=0; i<(unsigned int)l; i++) {
if (string[i] == '"' && !quote_flag) { if (string[i] == '"' && !quote_flag) {
quote_flag = true; quote_flag = true;
} else if (string[i] == '"' && quote_flag) { } else if (string[i] == '"' && quote_flag) {
@ -603,6 +603,14 @@ static cell AMX_NATIVE_CALL amx_ucfirst(AMX *amx, cell *params)
return 1; return 1;
} }
static cell AMX_NATIVE_CALL amx_strlen(AMX *amx, cell *params)
{
int len;
char *str = get_amxstring(amx, params[1], 0, len);
return strlen(str);
}
static cell AMX_NATIVE_CALL amx_trim(AMX *amx, cell *params) static cell AMX_NATIVE_CALL amx_trim(AMX *amx, cell *params)
{ {
cell *asdf = get_amxaddr(amx, params[1]); cell *asdf = get_amxaddr(amx, params[1]);
@ -668,5 +676,6 @@ AMX_NATIVE_INFO string_Natives[] = {
{ "trim", amx_trim }, { "trim", amx_trim },
{ "ucfirst", amx_ucfirst }, { "ucfirst", amx_ucfirst },
{ "strtok", amx_strtok }, { "strtok", amx_strtok },
{ "strlen", amx_strlen },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,0,0 FILEVERSION 1,5,0,1
PRODUCTVERSION 1,1,0,0 PRODUCTVERSION 1,5,0,1
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -45,12 +45,12 @@ BEGIN
BEGIN BEGIN
VALUE "Comments", "AMX Mod X" VALUE "Comments", "AMX Mod X"
VALUE "FileDescription", "AMX Mod X" VALUE "FileDescription", "AMX Mod X"
VALUE "FileVersion", "1.10-RC1" VALUE "FileVersion", "1.50"
VALUE "InternalName", "amxmodx" VALUE "InternalName", "amxmodx"
VALUE "LegalCopyright", "Copyright (c) 2004-2005, AMX Mod X Dev Team" VALUE "LegalCopyright", "Copyright (c) 2004-2005, AMX Mod X Dev Team"
VALUE "OriginalFilename", "amxmodx_mm.dll" VALUE "OriginalFilename", "amxmodx_mm.dll"
VALUE "ProductName", "AMX Mod X" VALUE "ProductName", "AMX Mod X"
VALUE "ProductVersion", "1.10-RC1" VALUE "ProductVersion", "1.50-RC1"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"