Files
Client/CryptoSource/ScriptEngine-MCF File/VirtualMachine.cpp
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

680 lines
17 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "VirtualMachine.h"
#include "IntermediateCode.h"
#include "SymbolTable.h"
#include "RelocTable.h"
#include <map>
#include <string>
#include <stdarg.h>
#include <fstream>
#include <set>
#include "GMMemory.h"
typedef unsigned char byte;
static const int xor_key_value = 0x82fac623;
///////////////////////////////////////////////////////////////////////////////////
//
CVirtualMachine::ALLOCATED * pAllocatedPtrs = NULL;
void RegisterAllocatedMemory( void * p )
{
pAllocatedPtrs->insert( p );
// CompilerMessage2( "[[[Register Allocated Memory : %d]]]", int(p) );
}
void UnregisterAllocatedMemory( void * p )
{
pAllocatedPtrs->erase( p );
// CompilerMessage2( "[[[Unregister Allocated Memory : %d]]]", int(p) );
}
///////////////////////////////////////////////////////////////////////////////////
//
ScriptFunc::ScriptFunc( void * pfunc, long type )
: pFunc( pfunc ), Type( type )
{}
CVirtualMachine::CVirtualMachine()
: m_pBuffer( NULL )
, m_pGlobalVars( NULL )
, m_pStringBuffer( NULL )
, m_pCodeBuffer( NULL )
, m_iCodeSize( 0 )
, m_pFunctionMap( new FUNCMAP )
, m_pRelocation( new CRelocTable )
, m_bRelocated( false )
, m_pAllocatedPtrs( new ALLOCATED )
, m_pSysVarBuffer( new char[32] )
{
pAllocatedPtrs = m_pAllocatedPtrs;
}
CVirtualMachine::~CVirtualMachine()
{
Destroy();
delete m_pFunctionMap;
delete m_pRelocation;
delete m_pAllocatedPtrs;
delete [] m_pSysVarBuffer;
}
///////////////////////////////////////////////////////////////////////////////////
//
void Data_XOR( char * pDataBuf, unsigned size, int keyValue )
{
int * pIntData = (int*)pDataBuf;
int IntDataSize = size/sizeof(int);
for( int i = 0; i < IntDataSize; i++ )
{
pIntData[i] = pIntData[i] ^ keyValue;
}
}
///////////////////////////////////////////////////////////////////////////////////
//
void File_XOR( const char * szSrcFilename, const char * szDstFilename, int keyValue )
{
fstream infile( szSrcFilename, ios_base::in | ios_base::binary );
if( !infile.is_open() )
{
ErrorMessage2( "È­ÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.(At File_XOR) : %s", szSrcFilename );
}
fstream outfile( szDstFilename, ios_base::out | ios_base::binary );
if( !outfile.is_open() )
{
ErrorMessage2( "È­ÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.(At File_XOR) : %s", szDstFilename );
}
infile.seekg( 0, ios_base::end );
unsigned filesize = infile.tellg();
infile.seekg( 0, ios_base::beg );
char * pDataBuf = new char[ filesize ];
infile.read( pDataBuf, filesize );
Data_XOR( pDataBuf, filesize, keyValue );
outfile.write( pDataBuf, filesize );
delete [] pDataBuf;
}
///////////////////////////////////////////////////////////////////////////////////
//
void CVirtualMachine::Create( const char * szFilename )
{
ifstream file( szFilename, ios::binary | ios::in );
if( !file.is_open() )
ErrorMessage2( "ÁöÁ¤ÇÑ È­ÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù. (At CVirtualMachine::Create) : %s", szFilename );
file.seekg( 0, ios_base::end );
unsigned filesize = file.tellg();
file.seekg( 0, ios_base::beg );
char * pBuf = new char[filesize];
int xor_key_valueT = xor_key_value^0x601f1ac4;
file.read( pBuf, filesize );
Data_XOR( pBuf, filesize, xor_key_valueT );
Create( pBuf, filesize );
delete [] pBuf;
file.close();
/*
Destroy();
ifstream file( szFilename, ios::binary | ios::in );
if( !file.is_open() )
ErrorMessage2( "ÁöÁ¤ÇÑ È­ÀÏÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù. (At CVirtualMachine::Create) : %s", szFilename );
m_pRelocation->Create( file );
int GlobalVarBufferSize, StringBufferSize, TotalBufferSize;
file.read( (char*)&GlobalVarBufferSize, sizeof(int) );
file.read( (char*)&StringBufferSize, sizeof(int) );
file.read( (char*)&m_iCodeSize, sizeof(int) );
TotalBufferSize = GlobalVarBufferSize + StringBufferSize + m_iCodeSize;
m_pGlobalVars = m_pBuffer = new char[TotalBufferSize];
m_pStringBuffer = ((byte*)m_pGlobalVars) + GlobalVarBufferSize;
m_pCodeBuffer = ((byte*)m_pStringBuffer) + StringBufferSize;
memset( m_pGlobalVars, 0, GlobalVarBufferSize );
file.read( (char*)m_pStringBuffer, StringBufferSize );
file.read( (char*)m_pCodeBuffer, m_iCodeSize );
long FuncMapSize;
file.read( (char*)&FuncMapSize, sizeof(long) );
string str;
char endChar;
long type, offset;
for( int i = 0; i < FuncMapSize; i++ )
{
file >> str;
file.read( &endChar, 1 );
file.read( (char*)&type, sizeof(long) );
file.read( (char*)&offset, sizeof(long) );
offset += long( m_pCodeBuffer );
m_pFunctionMap->insert( FUNCMAP::value_type( str, FUNCINFO( type, (void*)offset ) ) );
}
file.read( (char*)m_pSysVarOffset, sizeof(int)*4 );
file.close();
m_pRelocation->Relocate( m_pGlobalVars, m_pStringBuffer, m_pCodeBuffer );
m_bRelocated = true;
SetSysVars();
*/
}
#define READ_INT( p, var ) { var = *((int*)p); p += sizeof(int); }
#define READ_LONG( p, var ) { var = *((long*)p); p += sizeof(long); }
#define READ_CHAR( p, var ) { var = *p; p += sizeof(char); }
const char * ReadLine( const char * szBuf, char * szOut, char endChar = '\0' )
{
const char * p = szBuf;
char * pDst = szOut;
while( *p != endChar )
{
*pDst = *p;
p++, pDst++;
}
*pDst = '\0';
return p + 1;
}
void CVirtualMachine::Create( const void * pDataBuf, unsigned DataSize )
{
Destroy();
const char * pData = (const char*)m_pRelocation->Create( pDataBuf, DataSize );
int GlobalVarBufferSize, StringBufferSize, TotalBufferSize;
READ_INT( pData, GlobalVarBufferSize );
READ_INT( pData, StringBufferSize );
READ_INT( pData, m_iCodeSize );
TotalBufferSize = GlobalVarBufferSize + StringBufferSize + m_iCodeSize;
m_pGlobalVars = m_pBuffer = new char[TotalBufferSize];
m_pStringBuffer = ((byte*)m_pGlobalVars) + GlobalVarBufferSize;
m_pCodeBuffer = ((byte*)m_pStringBuffer) + StringBufferSize;
memset( m_pGlobalVars, 0, GlobalVarBufferSize );
memcpy( m_pStringBuffer, pData, StringBufferSize );
pData += StringBufferSize;
memcpy( m_pCodeBuffer, pData, m_iCodeSize );
pData += m_iCodeSize;
long FuncMapSize;
READ_LONG( pData, FuncMapSize );
long type, offset;
for( int i = 0; i < FuncMapSize; i++ )
{
char szStr[256];
pData = ReadLine( pData, szStr, '\n' );
READ_LONG( pData, type );
READ_LONG( pData, offset );
offset += long( m_pCodeBuffer );
m_pFunctionMap->insert( FUNCMAP::value_type( szStr, FUNCINFO( type, (void*)offset ) ) );
}
memcpy( m_pSysVarOffset, pData, sizeof(int)*4 );
pData += sizeof(int)*4;
m_pRelocation->Relocate( m_pGlobalVars, m_pStringBuffer, m_pCodeBuffer );
m_bRelocated = true;
SetSysVars();
}
void CVirtualMachine::Create( CIntermediateCode & IMCode, CSymbolTable & SymbolTable )
{
Destroy();
m_iCodeSize = IMCode.Addressing( 0 );
int GlobalVarsSize = SymbolTable.GetGlobalVarSize();
int StringBufferSize = SymbolTable.GetStringBufferSize();
int BufSize = GlobalVarsSize + StringBufferSize + m_iCodeSize;
m_pGlobalVars = m_pBuffer = new char[ BufSize ];
memset( m_pGlobalVars, 0, GlobalVarsSize );
m_pStringBuffer = (char*)m_pBuffer + GlobalVarsSize;
SymbolTable.StringBuffer( m_pStringBuffer );
m_pCodeBuffer = (char*)m_pStringBuffer + StringBufferSize;
if( IMCode.ToMachineCode( m_pCodeBuffer, m_pRelocation ) != m_iCodeSize )
ScriptSystemError( "°è»êµÈ ÄÚµå »çÀÌÁî¿Í ½ÇÁ¦ ÄÚµå »çÀÌÁî°¡ ´Ù¸¨´Ï´Ù.( at CVirtualMachine::Create )" );
//¸®·ÎÄÉÀ̼Ç
m_pRelocation->Relocate( m_pGlobalVars, m_pStringBuffer, m_pCodeBuffer );
m_bRelocated = true;
//ÇÔ¼ö Å×ÀÌºí ¸¸µé±â
typedef CIntermediateCode::FUNCTABLE FUNCTABLE;
FUNCTABLE & funcTable = IMCode.GetFuncTable();
byte * pCode = (byte*)m_pCodeBuffer;
for( FUNCTABLE::iterator i = funcTable.begin(); i != funcTable.end(); i++ )
{
const char * pFuncName = SymbolTable.GetNameOfFunc( i->first );
SFuncType FuncType = SymbolTable.GetTypeOfFunc( i->first );
void * pFunc = pCode + i->second;
m_pFunctionMap->insert( FUNCMAP::value_type( pFuncName, FUNCINFO( FuncType, pFunc ) ) );
}
m_pSysVarOffset[0] = SymbolTable.GetOffsetOfVar( SymbolTable.FindVar( SYSVAR_FLOATUNIT ) );
m_pSysVarOffset[1] = SymbolTable.GetOffsetOfVar( SymbolTable.FindVar( SYSVAR_TRUE ) );
m_pSysVarOffset[2] = SymbolTable.GetOffsetOfVar( SymbolTable.FindVar( SYSVAR_FALSE ) );
m_pSysVarOffset[3] = SymbolTable.GetOffsetOfVar( SymbolTable.FindVar( SYSVAR_CONVBUFFER ) );
SetSysVars();
}
void CVirtualMachine::SetSysVars()
{
int * pVarBuffer = (int*)m_pGlobalVars;
float floatunit = 1.0f;
pVarBuffer[ m_pSysVarOffset[0]/4 ] = *((int*)&floatunit); //0x3f800000
pVarBuffer[ m_pSysVarOffset[1]/4 ] = (int)strcpy( m_pSysVarBuffer, "true" );
pVarBuffer[ m_pSysVarOffset[2]/4 ] = (int)strcpy( m_pSysVarBuffer + 5, "false" );
pVarBuffer[ m_pSysVarOffset[3]/4 ] = int(m_pSysVarBuffer + 11);
}
void CVirtualMachine::Destroy()
{
delete [] m_pBuffer;
m_pBuffer = m_pGlobalVars = m_pStringBuffer = m_pCodeBuffer = NULL;
m_iCodeSize = 0;
m_pFunctionMap->clear();
m_pRelocation->Destroy();
for( ALLOCATED::iterator i = m_pAllocatedPtrs->begin(); i != m_pAllocatedPtrs->end(); i++ )
{
free( *i );
// CompilerMessage2( "[[[free : %d]]]", int(*i) );
}
m_pAllocatedPtrs->clear();
}
///////////////////////////////////////////////////////////////////////////////////
// È­ÀÏ Æ÷¸Ë
// 1. Àü¿ª º¯¼ö Relocation °³¼ö(int)
// 2. ¹®ÀÚ¿­ »ó¼ö Relocation °³¼ö(int)
// 3. Àü¿ª º¯¼ö Relocation Table
// 4. ¹®ÀÚ¿­ »ó¼ö Relocation Table
// 5. Àü¿ªº¯¼ö ¹öÆÛ Å©±â(int)
// 6. ¹®ÀÚ¿­ ¹öÆÛ Å©±â(int)
// 7. ÄÚµå ¹öÆÛ Å©±â(int)
// 8. ¹®ÀÚ¿­ ¹öÆÛ
// 9. ÄÚµå ¹öÆÛ
// 10. ÇÔ¼ö¸Ê »çÀÌÁî
// 11. < ¹®ÀÚ¿­, ÇÔ¼ö ŸÀÔ(long), ¿ÀÇÁ¼Â(long) > * »çÀÌÁî
///////////////////////////////////////////////////////////////////////////////////
bool CVirtualMachine::Save( const char * szFilename )
{
if( m_pBuffer == NULL || m_pGlobalVars == NULL || m_pStringBuffer == NULL || m_pCodeBuffer == NULL )
{
return false;
}
ofstream file( szFilename, ios::binary | ios::out );
if( !file.is_open() )
{
return false;
}
if( m_bRelocated )
{
m_pRelocation->Unlocate( m_pGlobalVars, m_pStringBuffer, m_pCodeBuffer );
m_bRelocated = false;
}
m_pRelocation->Save( file );
int GlobalVarBufferSize = ((byte*)m_pStringBuffer) - ((byte*)m_pGlobalVars);
int StringBufferSize = ((byte*)m_pCodeBuffer) - ((byte*)m_pStringBuffer);
file.write( (const char*)&GlobalVarBufferSize, sizeof(int) );
file.write( (const char*)&StringBufferSize, sizeof(int) );
file.write( (const char*)&m_iCodeSize, sizeof(int) );
file.write( (const char*)m_pStringBuffer, StringBufferSize );
file.write( (const char*)m_pCodeBuffer, m_iCodeSize );
int FuncMapSize = m_pFunctionMap->size();
file.write( (const char*)&FuncMapSize, sizeof(int) );
for( FUNCMAP::iterator it = m_pFunctionMap->begin(); it != m_pFunctionMap->end(); it++ )
{
file << it->first << '\n';
file.write( (const char*)&it->second.first.m_data, sizeof(long) );
long offset = long( it->second.second ) - long(m_pCodeBuffer);
file.write( (const char*)&offset, sizeof(long) );
}
file.write( (const char*)m_pSysVarOffset, sizeof(int)*4 );
file.close();
m_pRelocation->Relocate( m_pGlobalVars, m_pStringBuffer, m_pCodeBuffer );
char tempFilename[256];
sprintf( tempFilename, "%s+", szFilename );
int xor_key_valueT = xor_key_value^0x601f1ac4;
File_XOR( szFilename, tempFilename, xor_key_valueT );
remove( szFilename );
rename( tempFilename, szFilename );
return true;
}
void CVirtualMachine::Execute()
{
void * pCodeBuffer = m_pCodeBuffer;
__asm call pCodeBuffer;
}
SFuncType MakeFuncType( eDataType returnType, va_list args )
{
SFuncType type;
type.SetReturnType( returnType );
for( int i = 0; i < 7; i++ )
{
eDataType dataType = va_arg( args, eDataType );
if( dataType == T_VOID )
break;
type.SetArgType( i, dataType );
}
return type;
}
void * GetFuncPtr( CVirtualMachine::FUNCMAP & funcMap, const char * szFuncName, SFuncType funcType )
{
typedef CVirtualMachine::FUNCMAP::iterator iterator;
pair< iterator, iterator > result = funcMap.equal_range( szFuncName );
while( result.first != result.second )
{
SFuncType ftype = result.first->second.first;
if( ftype == funcType )
{
return result.first->second.second;
}
result.first++;
}
return NULL;
}
union long_byte
{
long longValue;
char byteValue[4];
};
///////////////////////////////////////////////////////////////////////////////////
//NativeÇÔ¼ö¸¦ ½ºÅ©¸³Æ®¿¡ ¹ÙÀεå ÇÏ´Â ¹æ½Ä
//
//ÇöÀç ¹æ½Ä : ÇÔ¼ö¸¦ µÎ ¹ø °ÅÄ¡°Ô ÇÑ´Ù. ( ½ÇÇà ¼Óµµ´Â Á» ´õ ´À¸®Áö¸¸ ´õ °£´ÜÇÏ´Ù. )
// 1-1. ¼±¾ð¸¸ ÀÖ°í, Á¤Àǰ¡ ¾ø´Â ÇÔ¼öµé¸¸ ÇÔ¼ö Äڵ忡¼­ óÀ½ ºÎºÐ¿¡ 5¹ÙÀÌÆ® ÀÌ»óÀÇ °ø¹é(nop)¸¦ ¸¸µé¾îµÐ´Ù.
// 1-2. RegisterFunctionÀÌ È£ÃâµÆÀ» ¶§ 1-1¿¡¼­ ¸¸µé¾îµÐ °ø¹é ºÎºÐ¿¡ call <native function>°ú ret¸¦ Áý¾î³Ö´Â´Ù.
// ¾ó¸¶³ª ´À¸°°¡? ¸ðµç ÇÔ¼ö¿¡ nop°¡ 2°³ ÀÌ»ó Ãß°¡µÇ°í, native call´Â ÀÌÁß È£ÃâÀÌ µÈ´Ù.
// Empty FunctionÀ» Á¦°ÅÇÑ´Ù.
//
//´Ù¸¥ ´ë¾È : µî·ÏÇÏ·Á´Â ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ¸ðµç ºÎºÐÀÇ ÇÔ¼ö ÁÖ¼Ò¸¦ ¹Ù²Û´Ù.( ½ÇÇà ¼Óµµ´Â ºü¸£³ª º¹ÀâÇÏ´Ù. )
// 2-1. ¸ðµç ÇÔ¼ö È£Ã⠺κÐÀ» Relocation Tableó·³ call table¿¡ ÀúÀåÇØµÐ´Ù.
// 2-2. RegisterFunctionÀÌ È£ÃâµÇ¾úÀ» ¶§ call tableÀ» ÂüÁ¶Çؼ­ callÇϰí ÀÖ´Â ºÎºÐÀ» ÀüºÎ ¹Ù²Û´Ù.
// call table˼? map< string, pair< SFuncType, vector<int> > >
///////////////////////////////////////////////////////////////////////////////////
void CVirtualMachine::RegisterFunction( ANY_FUNCTION FuncPtr, eDataType returnType, const char * szFuncName, ... )
{
va_list args;
va_start( args, szFuncName );
RegisterFunction( FuncPtr, returnType, szFuncName, args );
}
void CVirtualMachine::RegisterFunction( ANY_FUNCTION FuncPtr, eDataType returnType, const char * szFuncName, va_list args )
{
SFuncType funcType = MakeFuncType( returnType, args );
byte * pFunc = (byte*)GetFuncPtr( *m_pFunctionMap, szFuncName, funcType );
if( pFunc == NULL )
ErrorMessage2( "ÇÔ¼ö µî·Ï¿¡ ½ÇÆÐÇß½À´Ï´Ù. ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø¾ú½À´Ï´Ù. : %s", funcType.ToString( szFuncName ) );
if( pFunc[3] != 0x90 ) //nop°¡ ¾Æ´Ò ¶§
ScriptSystemError( "RegisterFunction Error!!( at CVirtualMachine::RegisterFunction )" );
int nArg = funcType.GetArgCount();
pFunc += 3;
for( int i = 0; i < nArg; i++ )
{
*(pFunc++) = 0xff;
*(pFunc++) = 0x75;
*(pFunc++) = 0xff & (8+4*i);
}
*(pFunc++) = 0xe8;
long_byte FuncOffset;
FuncOffset.longValue = long(FuncPtr) - long(pFunc+4);
*(pFunc++) = FuncOffset.byteValue[0];
*(pFunc++) = FuncOffset.byteValue[1];
*(pFunc++) = FuncOffset.byteValue[2];
*(pFunc++) = FuncOffset.byteValue[3];
}
ScriptFunc CVirtualMachine::GetScriptFunction( eDataType returnType, const char * szFuncName, ... )
{
va_list args;
va_start( args, szFuncName );
return GetScriptFunction( returnType, szFuncName, args );
}
ScriptFunc CVirtualMachine::GetScriptFunction( eDataType returnType, const char * szFuncName, va_list args )
{
SFuncType funcType = MakeFuncType( returnType, args );
void * pFunc = GetFuncPtr( *m_pFunctionMap, szFuncName, funcType );
if( pFunc == NULL )
ErrorMessage2( "½ºÅ©¸³Æ® ÇÔ¼ö¸¦ ¾ò¾î¿À´Âµ¥ ½ÇÆÐÇß½À´Ï´Ù. ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø¾ú½À´Ï´Ù. : %s", funcType.ToString( szFuncName ) );
return ScriptFunc( pFunc, funcType.m_data );
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func )
{
__asm call Func.pFunc;
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData arg1 )
{
__asm
{
push arg1;
call Func.pFunc;
add esp, 4;
}
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData arg1, AnyData arg2 )
{
__asm
{
push arg2;
push arg1;
call Func.pFunc;
add esp, 8;
}
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData arg1, AnyData arg2, AnyData arg3 )
{
__asm
{
push arg3;
push arg2;
push arg1;
call Func.pFunc;
add esp, 12;
}
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData arg1, AnyData arg2, AnyData arg3, AnyData arg4 )
{
__asm
{
push arg4;
push arg3;
push arg2;
push arg1;
call Func.pFunc;
add esp, 16;
}
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData args[], int nArgs )
{
for( int i = nArgs - 1; i >= 0; i-- )
__asm push args[i];
__asm call Func.pFunc;
nArgs *= 4;
__asm add esp, nArgs;
}
void * CVirtualMachine::CallScriptFunction( ScriptFunc Func, AnyData arg0, AnyData arg1, AnyData arg2, AnyData arg3, AnyData arg4,
AnyData arg5, AnyData arg6, AnyData arg7, AnyData arg8, AnyData arg9,
AnyData arg10, AnyData arg11, AnyData arg12, AnyData arg13, AnyData arg14,
AnyData arg15, AnyData arg16, AnyData arg17, AnyData arg18, AnyData arg19,
AnyData arg20, AnyData arg21, AnyData arg22, AnyData arg23, AnyData arg24,
AnyData arg25, AnyData arg26, AnyData arg27, AnyData arg28, AnyData arg29,
AnyData arg30, AnyData arg31, AnyData arg32, AnyData arg33, AnyData arg34 )
{
__asm
{
push arg34;
push arg33;
push arg32;
push arg31;
push arg30;
push arg29;
push arg28;
push arg27;
push arg26;
push arg25;
push arg24;
push arg23;
push arg22;
push arg21;
push arg20;
push arg19;
push arg18;
push arg17;
push arg16;
push arg15;
push arg14;
push arg13;
push arg12;
push arg11;
push arg10;
push arg9;
push arg8;
push arg7;
push arg6;
push arg5;
push arg4;
push arg3;
push arg2;
push arg1;
push arg0;
call Func.pFunc;
add esp, 140;
}
}
/*
int CVirtualMachine::CallScriptFunction( ScriptFunc Func, va_list args )
{
int nArgs = SFuncType( Func.Type ).GetArgCount();
for( int i = 0; i < nArgs; i++ )
{
AnyData data = va_arg( args, AnyData );
__asm push data;
}
void * pFunc = Func.pFunc;
int n = nArgs * 4;
__asm
{
call pFunc;
add esp, n;
}
}
int CVirtualMachine::CallScriptFunction( ScriptFunc Func, ... )
{
va_list args;
va_start( args, Func );
return CallScriptFunction( Func, args );
}
*/