implemented a lot more binary opcodes

bumped versions
This commit is contained in:
David Anderson 2006-03-16 06:36:01 +00:00
parent e98fbc47e8
commit e067a980be
12 changed files with 259 additions and 37 deletions

View File

@ -31,6 +31,7 @@
#include "amxmodx.h" #include "amxmodx.h"
#include "debugger.h" #include "debugger.h"
#include "binlog.h"
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes) CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes)
{ {
@ -124,6 +125,9 @@ cell CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
// exec // exec
cell retVal; cell retVal;
#if defined BINLOG_ENABLED
g_BinLog.WriteOp(BinLog_CallPubFunc, (*iter).pPlugin->getId(), iter->func);
#endif
int err = amx_Exec(amx, &retVal, iter->func); int err = amx_Exec(amx, &retVal, iter->func);
// log runtime error, if any // log runtime error, if any
@ -284,6 +288,9 @@ cell CSPForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
// exec // exec
cell retVal; cell retVal;
#if defined BINLOG_ENABLED
g_BinLog.WriteOp(BinLog_CallPubFunc, pPlugin->getId(), m_Func);
#endif
int err = amx_Exec(m_Amx, &retVal, m_Func); int err = amx_Exec(m_Amx, &retVal, m_Func);
if (err != AMX_ERR_NONE) if (err != AMX_ERR_NONE)

View File

@ -462,8 +462,24 @@ int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params)
amx->error=AMX_ERR_NONE; amx->error=AMX_ERR_NONE;
#if defined BINLOG_ENABLED
binlogfuncs_t *logfuncs = (binlogfuncs_t *)amx->usertags[UT_BINLOGS];
if (logfuncs)
{
logfuncs->pfnLogNative(amx, index, (int)(params[0] / sizeof(cell)));
logfuncs->pfnLogParams(amx, params);
}
#endif //BINLOG_ENABLED
*result = f(amx,params); *result = f(amx,params);
#if defined BINLOG_ENABLED
if (logfuncs)
{
logfuncs->pfnLogReturn(amx, *result);
}
#endif
return amx->error; return amx->error;
} }
#endif /* defined AMX_INIT */ #endif /* defined AMX_INIT */

View File

@ -336,6 +336,7 @@ enum {
#define UT_NATIVE 3 #define UT_NATIVE 3
#define UT_OPTIMIZER 2 #define UT_OPTIMIZER 2
#define UT_BROWSEHOOK 1 #define UT_BROWSEHOOK 1
#define UT_BINLOGS 0
typedef void (*BROWSEHOOK)(AMX *amx, cell *oplist, cell *cip); typedef void (*BROWSEHOOK)(AMX *amx, cell *oplist, cell *cip);
@ -440,6 +441,15 @@ int AMXAPI amx_GetStringOld(char *dest,const cell *source,int use_wchar);
#endif #endif
#endif #endif
#if defined BINLOG_ENABLED
typedef struct tagBINLOG
{
void (*pfnLogNative)(AMX *amx, int native, int params);
void (*pfnLogReturn)(AMX *amx, cell retval);
void (*pfnLogParams)(AMX *amx, cell *params);
} binlogfuncs_t;
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -67,7 +67,7 @@
#include "amxxlog.h" #include "amxxlog.h"
#define AMXXLOG_Log g_log.Log #define AMXXLOG_Log g_log.Log
#define AMX_VERSION "1.70" #define AMX_VERSION "1.71"
extern AMX_NATIVE_INFO core_Natives[]; extern AMX_NATIVE_INFO core_Natives[];
extern AMX_NATIVE_INFO time_Natives[]; extern AMX_NATIVE_INFO time_Natives[];

View File

@ -5,6 +5,7 @@
#if defined BINLOG_ENABLED #if defined BINLOG_ENABLED
BinLog g_BinLog; BinLog g_BinLog;
int g_binlog_level = 0;
bool BinLog::Open() bool BinLog::Open()
{ {
@ -51,7 +52,7 @@ bool BinLog::Open()
void BinLog::Close() void BinLog::Close()
{ {
//dummy function - logs are not kept open WriteOp(BinLog_End, -1);
} }
void BinLog::WriteOp(BinLogOp op, int plug, ...) void BinLog::WriteOp(BinLogOp op, int plug, ...)
@ -85,9 +86,89 @@ void BinLog::WriteOp(BinLogOp op, int plug, ...)
fwrite(vers, sizeof(char), c+1, fp); fwrite(vers, sizeof(char), c+1, fp);
break; break;
} }
case BinLog_NativeCall:
{
int native = va_arg(ap, int);
int params = va_arg(ap, int);
fwrite(&native, sizeof(int), 1, fp);
fwrite(&params, sizeof(int), 1, fp);
break;
}
case BinLog_NativeRet:
{
cell retval = va_arg(ap, cell);
fwrite(&retval, sizeof(cell), 1, fp);
break;
}
case BinLog_NativeError:
{
int err = va_arg(ap, int);
const char *msg = va_arg(ap, const char *);
short len = (short)strlen(msg);
fwrite(&err, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(msg, sizeof(char), len+1, fp);
break;
}
case BinLog_CallPubFunc:
{
int num = va_arg(ap, int);
fwrite(&num, sizeof(int), 1, fp);
break;
}
case BinLog_SetLine:
{
int line = va_arg(ap, int);
fwrite(&line, sizeof(int), 1, fp);
break;
}
case BinLog_FormatString:
{
int param = va_arg(ap, int);
int maxlen = va_arg(ap, int);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&param, sizeof(int), 1, fp);
fwrite(&maxlen, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
case BinLog_NativeParams:
{
cell *params = va_arg(ap, cell *);
cell num = params[0] / sizeof(cell);
fwrite(&num, sizeof(cell), 1, fp);
for (cell i=1; i<=num; i++)
fwrite(&(params[i]), sizeof(cell), 1, fp);
break;
}
case BinLog_GetString:
{
cell addr = va_arg(ap, cell);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&addr, sizeof(cell), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
case BinLog_SetString:
{
cell addr = va_arg(ap, cell);
int maxlen = va_arg(ap, int);
const char *str = va_arg(ap, const char *);
short len = (short)strlen(str);
fwrite(&addr, sizeof(cell), 1, fp);
fwrite(&maxlen, sizeof(int), 1, fp);
fwrite(&len, sizeof(short), 1, fp);
fwrite(str, sizeof(char), len+1, fp);
break;
}
}; };
va_end(ap); va_end(ap);
fclose(fp);
} }
void BinLog::CacheAllPlugins() void BinLog::CacheAllPlugins()

View File

@ -12,30 +12,30 @@
/** /**
* Format of binlog: * Format of binlog:
* int32_t magic * uint32 magic
* int16_t version * uint16 version
* int8_t sizeof(time_t) * uint8 sizeof(time_t)
* [ * [
* uint8 operation code
* time_t realtime * time_t realtime
* float gametime * float gametime
* int8_t operation code * int32 plugin id
* int16_t plugin id
* <extra info> * <extra info>
* ] * ]
* Format of bindb: * Format of bindb:
* int32_t magic * uint32 magic
* int16_t version * uint16 version
* int32_t num plugins * uint32 num plugins
* [ * [
* int8_t status codes * uint8 status codes
* str[int8_t] filename * str[int8] filename
* int32_t num natives * uint32 num natives
* int32_t num publics * uint32 num publics
* [ * [
* str[int8_t] native name * str[uint8] native name
* ] * ]
* [ * [
* str[int8_t] public name * str[uint8] public name
* ] * ]
*/ */
@ -43,10 +43,16 @@ enum BinLogOp
{ {
BinLog_Start=1, BinLog_Start=1,
BinLog_End, BinLog_End,
BinLog_NativeCall, //<int16_t native id> BinLog_NativeCall, //<int32 native id> <int32_t num_params>
BinLog_CallPubFunc, //<int16_t public id> BinLog_NativeError, //<int32 errornum> <str[int16] string>
BinLog_SetLine, //<int16_t line no#> BinLog_NativeRet, //<cell value>
BinLog_CallPubFunc, //<int32 public id>
BinLog_SetLine, //<int32 line no#>
BinLog_Registered, //<string title> <string version> BinLog_Registered, //<string title> <string version>
BinLog_FormatString, //<int32 param#> <int32 maxlen> <str[int16] string>
BinLog_NativeParams, //<int32 num> <cell ...>
BinLog_GetString, //<cell addr> <string[int16]>
BinLog_SetString, //<cell addr> <int maxlen> <string[int16]>
}; };
class BinLog class BinLog
@ -61,8 +67,9 @@ private:
String m_logfile; String m_logfile;
}; };
extern BinLog g_BinLog;
extern int g_binlog_level;
#endif //BINLOG_ENABLED #endif //BINLOG_ENABLED
extern BinLog g_BinLog;
#endif //_INCLUDE_BINLOG_H #endif //_INCLUDE_BINLOG_H

View File

@ -31,6 +31,7 @@
#include "amxmodx.h" #include "amxmodx.h"
#include "debugger.h" #include "debugger.h"
#include "binlog.h"
#if !defined WIN32 && !defined _WIN32 #if !defined WIN32 && !defined _WIN32
#define _snprintf snprintf #define _snprintf snprintf
@ -307,6 +308,19 @@ void Debugger::StepI()
{ {
assert(m_Top >= 0 && m_Top < (int)m_pCalls.size()); assert(m_Top >= 0 && m_Top < (int)m_pCalls.size());
#if defined BINLOG_ENABLED
if (g_binlog_level & 32)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(m_pAmx);
if (pl)
{
long line;
dbg_LookupLine(m_pAmxDbg, m_pAmx->cip, &line);
g_BinLog.WriteOp(BinLog_SetLine, pl->getId(), (int)(line + 1));
}
}
#endif
m_pCalls[m_Top]->StepI(m_pAmx->frm, m_pAmx->cip); m_pCalls[m_Top]->StepI(m_pAmx->frm, m_pAmx->cip);
} }

View File

@ -304,6 +304,7 @@ int C_Spawn(edict_t *pent)
{ {
LOG_ERROR(PLID, "Binary log failed to open."); LOG_ERROR(PLID, "Binary log failed to open.");
} }
g_binlog_level = atoi(get_localinfo("bin_logging", "17"));
#endif #endif
// ###### Load AMX scripts // ###### Load AMX scripts
@ -581,6 +582,10 @@ void C_ServerDeactivate_Post()
} }
#endif // MEMORY_TEST #endif // MEMORY_TEST
#if defined BINLOG_ENABLED
g_BinLog.Close();
#endif
g_initialized = false; g_initialized = false;
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);

View File

@ -45,6 +45,7 @@
#include "natives.h" #include "natives.h"
#include "debugger.h" #include "debugger.h"
#include "optimizer.h" #include "optimizer.h"
#include "binlog.h"
CList<CModule, const char*> g_modules; CList<CModule, const char*> g_modules;
CList<CScript, AMX*> g_loadedscripts; CList<CScript, AMX*> g_loadedscripts;
@ -125,6 +126,38 @@ void free_amxmemory(void **ptr)
*ptr = 0; *ptr = 0;
} }
#if defined BINLOG_ENABLED
void BinLog_LogNative(AMX *amx, int native, int params)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_NativeCall, pl->getId(), native, params);
}
void BinLog_LogReturn(AMX *amx, cell retval)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_NativeRet, pl->getId(), retval);
}
void BinLog_LogParams(AMX *amx, cell *params)
{
if (g_binlog_level & 8)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_NativeParams, pl->getId(), params);
}
}
static binlogfuncs_t logfuncs =
{
BinLog_LogNative,
BinLog_LogReturn,
BinLog_LogParams
};
#endif
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;
@ -251,6 +284,10 @@ int load_amxscript(AMX *amx, void **program, const char *filename, char error[64
Handler *pHandler = new Handler(amx); Handler *pHandler = new Handler(amx);
amx->userdata[UD_HANDLER] = (void *)pHandler; amx->userdata[UD_HANDLER] = (void *)pHandler;
#if defined BINLOG_ENABLED
amx->usertags[UT_BINLOGS] = (void *)&logfuncs;
#endif
if (will_be_debugged) if (will_be_debugged)
{ {
amx->flags |= AMX_FLAG_DEBUG; amx->flags |= AMX_FLAG_DEBUG;
@ -1399,6 +1436,12 @@ extern "C" void LogError(AMX *amx, int err, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
#if defined BINLOG_ENABLED
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_NativeError, pl->getId(), err, msg_buffer);
#endif
//give the plugin first chance to handle any sort of error //give the plugin first chance to handle any sort of error
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER]; Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];

View File

@ -668,17 +668,17 @@
OmitFramePointers="TRUE" OmitFramePointers="TRUE"
OptimizeForProcessor="0" OptimizeForProcessor="0"
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;ASM32;PAWN_CELL_SIZE=32" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;amxmodx_EXPORTS;JIT;ASM32;PAWN_CELL_SIZE=32;BINLOG_ENABLED"
IgnoreStandardIncludePath="FALSE" IgnoreStandardIncludePath="FALSE"
StringPooling="TRUE" StringPooling="TRUE"
RuntimeLibrary="4" RuntimeLibrary="4"
EnableFunctionLevelLinking="TRUE" EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="2" UsePrecompiledHeader="2"
PrecompiledHeaderThrough="amxmodx.h" PrecompiledHeaderThrough="amxmodx.h"
PrecompiledHeaderFile=".\jitrelease/amxmodx.pch" PrecompiledHeaderFile=".\jitreleasebinlog/amxmodx.pch"
AssemblerListingLocation=".\jitrelease/" AssemblerListingLocation=".\jitreleasebinlog/"
ObjectFile=".\jitrelease/" ObjectFile=".\jitreleasebinlog/"
ProgramDataBaseFileName=".\jitrelease/" ProgramDataBaseFileName=".\jitreleasebinlog/"
WarningLevel="3" WarningLevel="3"
SuppressStartupBanner="TRUE" SuppressStartupBanner="TRUE"
DebugInformationFormat="3" DebugInformationFormat="3"
@ -689,16 +689,16 @@
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalOptions="/MACHINE:I386" AdditionalOptions="/MACHINE:I386"
AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj ..\JIT\natives-x86.obj" AdditionalDependencies="..\zlib\zlib.lib ..\JIT\amxjitsn.obj ..\JIT\amxexecn.obj ..\JIT\natives-x86.obj"
OutputFile="jitrelease/amxmodx_mm.dll" OutputFile="jitreleasebinlog/amxmodx_mm.dll"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="TRUE" SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="..\extra\lib_win32" AdditionalLibraryDirectories="..\extra\lib_win32"
IgnoreDefaultLibraryNames="MSVCRT" IgnoreDefaultLibraryNames="MSVCRT"
ModuleDefinitionFile="" ModuleDefinitionFile=""
GenerateDebugInformation="TRUE" GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\jitrelease/amxmodx_mm.pdb" ProgramDatabaseFile=".\jitreleasebinlog/amxmodx_mm.pdb"
GenerateMapFile="TRUE" GenerateMapFile="TRUE"
ImportLibrary=".\jitrelease/amxx_mm.lib"/> ImportLibrary=".\jitreleasebinlog/amxx_mm.lib"/>
<Tool <Tool
Name="VCMIDLTool" Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG" PreprocessorDefinitions="NDEBUG"

View File

@ -32,6 +32,7 @@
#include <ctype.h> #include <ctype.h>
#include "amxmodx.h" #include "amxmodx.h"
#include "format.h" #include "format.h"
#include "binlog.h"
const char* stristr(const char* str, const char* substr) const char* stristr(const char* str, const char* substr)
{ {
@ -57,7 +58,18 @@ const char* stristr(const char* str, const char* substr)
char* format_amxstring(AMX *amx, cell *params, int parm, int& len) char* format_amxstring(AMX *amx, cell *params, int parm, int& len)
{ {
#if !defined BINLOG_ENABLED
return g_langMngr.FormatAmxString(amx, params, parm, len); return g_langMngr.FormatAmxString(amx, params, parm, len);
#else
char *ans = g_langMngr.FormatAmxString(amx, params, parm, len);
if (g_binlog_level & 4)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_FormatString, pl->getId(), parm, len, ans);
}
return ans;
#endif
} }
int amxstring_len(cell* a) int amxstring_len(cell* a)
@ -79,6 +91,15 @@ int set_amxstring(AMX *amx, cell amx_addr, const char *source, int max)
{ {
register cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr)); register cell* dest = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
register cell* start = dest; register cell* start = dest;
#if defined BINLOG_ENABLED
if (g_binlog_level & 2)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_SetString, pl->getId(), amx_addr, max, source);
}
#endif
while (max-- && *source) while (max-- && *source)
*dest++ = (cell)*source++; *dest++ = (cell)*source++;
@ -93,12 +114,21 @@ extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, in
register cell *source = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr)); register cell *source = (cell *)(amx->base + (int)(((AMX_HEADER *)amx->base)->dat + amx_addr));
register char *dest = destination; register char *dest = destination;
char *start = dest; char *start = dest;
while (maxlen-- && *source) while (maxlen-- && *source)
*dest++=(char)(*source++); *dest++=(char)(*source++);
*dest = '\0'; *dest = '\0';
#if defined BINLOG_ENABLED
if (g_binlog_level & 2)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_GetString, pl->getId(), amx_addr, destination);
}
#endif
return dest - start; return dest - start;
} }
@ -112,6 +142,15 @@ char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len)
while ((*dest++=(char)(*source++))); while ((*dest++=(char)(*source++)));
len = --dest - start; len = --dest - start;
#if defined BINLOG_ENABLED
if (g_binlog_level & 2)
{
CPluginMngr::CPlugin *pl = g_plugins.findPluginFast(amx);
if (pl)
g_BinLog.WriteOp(BinLog_GetString, pl->getId(), amx_addr, start);
}
#endif
return start; return start;
} }
@ -279,7 +318,7 @@ static cell AMX_NATIVE_CALL numtostr(AMX *amx, cell *params) /* 3 param */
{ {
char szTemp[32]; char szTemp[32];
sprintf(szTemp, "%d", (int)params[1]); sprintf(szTemp, "%d", (int)params[1]);
return set_amxstring(amx, params[2], szTemp, params[3]); return set_amxstring(amx, params[2], szTemp, params[3]);
} }
@ -757,7 +796,7 @@ do_copy:
i++; i++;
const char *start = had_quotes ? &(string[beg+1]) : &(string[beg]); const char *start = had_quotes ? &(string[beg+1]) : &(string[beg]);
size_t _end = had_quotes ? (i==len-1 ? 1 : 2) : 0; size_t _end = had_quotes ? (i==len-1 ? 1 : 2) : 0;
size_t end = (pos - _end > LeftMax) ? LeftMax : pos - _end; size_t end = (pos - _end > (size_t)LeftMax) ? (size_t)LeftMax : pos - _end;
size_t to_go = end-beg; size_t to_go = end-beg;
if (end && to_go) if (end && to_go)
{ {
@ -765,7 +804,7 @@ do_copy:
*left++ = (cell)*start++; *left++ = (cell)*start++;
} }
*left = '\0'; *left = '\0';
end = (len-i+1 > RightMax) ? RightMax : len-i+1; end = (len-i+1 > (size_t)RightMax) ? (size_t)RightMax : len-i+1;
if (end) if (end)
{ {
start = &(string[i]); start = &(string[i]);

View File

@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,0,0 FILEVERSION 1,7,1,0
PRODUCTVERSION 1,7,0,0 PRODUCTVERSION 1,7,1,0
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.70" VALUE "FileVersion", "1.71"
VALUE "InternalName", "amxmodx" VALUE "InternalName", "amxmodx"
VALUE "LegalCopyright", "Copyright (c) 2004-2006, AMX Mod X Dev Team" VALUE "LegalCopyright", "Copyright (c) 2004-2006, 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.70" VALUE "ProductVersion", "1.71"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"