2012-03-06 02:44:24 +01:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2012-05-11 16:03:59 +02:00
2012-03-06 02:44:24 +01:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2012-05-11 16:03:59 +02:00
2012-03-06 02:44:24 +01:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
/*
* This file is based on WME Lite .
* http : //dead-code.org/redir.php?target=wmelite
* Copyright ( c ) 2011 Jan Nedoma
*/
# include "engines/wintermute/dcgf.h"
2012-06-02 02:05:11 +02:00
# include "engines/wintermute/Base/scriptables/ScValue.h"
# include "engines/wintermute/Base/scriptables/ScScript.h"
# include "engines/wintermute/Base/BGame.h"
# include "engines/wintermute/Base/scriptables/ScEngine.h"
# include "engines/wintermute/Base/scriptables/ScStack.h"
2012-03-06 02:44:24 +01:00
namespace WinterMute {
IMPLEMENT_PERSISTENT ( CScScript , false )
//////////////////////////////////////////////////////////////////////////
CScScript : : CScScript ( CBGame * inGame , CScEngine * Engine ) : CBBase ( inGame ) {
2012-04-28 01:00:14 +03:00
_buffer = NULL ;
_bufferSize = _iP = 0 ;
_filename = NULL ;
_currentLine = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_symbols = NULL ;
_numSymbols = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_engine = Engine ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_globals = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_scopeStack = NULL ;
_callStack = NULL ;
_thisStack = NULL ;
_stack = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_operand = NULL ;
_reg1 = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_functions = NULL ;
_numFunctions = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_methods = NULL ;
_numMethods = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_events = NULL ;
_numEvents = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_externals = NULL ;
_numExternals = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_state = SCRIPT_FINISHED ;
_origState = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_waitObject = NULL ;
_waitTime = 0 ;
_waitFrozen = false ;
_waitScript = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_timeSlice = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_thread = false ;
_methodThread = false ;
_threadEvent = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_freezable = true ;
_owner = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_unbreakable = false ;
_parentScript = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_tracingMode = false ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
CScScript : : ~ CScScript ( ) {
Cleanup ( ) ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : InitScript ( ) {
2012-04-28 01:00:14 +03:00
TScriptHeader * Header = ( TScriptHeader * ) _buffer ;
2012-03-06 02:44:24 +01:00
if ( Header - > magic ! = SCRIPT_MAGIC ) {
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " File '%s' is not a valid compiled script " , _filename ) ;
2012-03-06 02:44:24 +01:00
Cleanup ( ) ;
return E_FAIL ;
}
if ( Header - > version > SCRIPT_VERSION ) {
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " Script '%s' has a wrong version %d.%d (expected %d.%d) " , _filename , Header - > version / 256 , Header - > version % 256 , SCRIPT_VERSION / 256 , SCRIPT_VERSION % 256 ) ;
2012-03-06 02:44:24 +01:00
Cleanup ( ) ;
return E_FAIL ;
}
InitTables ( ) ;
// init stacks
2012-04-28 01:00:14 +03:00
_scopeStack = new CScStack ( Game ) ;
_callStack = new CScStack ( Game ) ;
_thisStack = new CScStack ( Game ) ;
_stack = new CScStack ( Game ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_operand = new CScValue ( Game ) ;
_reg1 = new CScValue ( Game ) ;
2012-03-06 02:44:24 +01:00
// skip to the beginning
2012-04-28 01:00:14 +03:00
_iP = Header - > code_start ;
_currentLine = 0 ;
2012-03-06 02:44:24 +01:00
// init breakpoints
2012-04-28 01:00:14 +03:00
_engine - > RefreshScriptBreakpoints ( this ) ;
2012-03-06 02:44:24 +01:00
// ready to rumble...
2012-04-28 01:00:14 +03:00
_state = SCRIPT_RUNNING ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : InitTables ( ) {
2012-04-28 01:00:14 +03:00
uint32 OrigIP = _iP ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
TScriptHeader * Header = ( TScriptHeader * ) _buffer ;
2012-03-06 02:44:24 +01:00
2012-05-11 16:46:09 +02:00
int32 i ;
2012-03-06 02:44:24 +01:00
// load symbol table
2012-04-28 01:00:14 +03:00
_iP = Header - > symbol_table ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_numSymbols = GetDWORD ( ) ;
_symbols = new char * [ _numSymbols ] ;
for ( i = 0 ; i < _numSymbols ; i + + ) {
2012-03-06 02:44:24 +01:00
uint32 index = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_symbols [ index ] = GetString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load functions table
2012-04-28 01:00:14 +03:00
_iP = Header - > func_table ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_numFunctions = GetDWORD ( ) ;
_functions = new TFunctionPos [ _numFunctions ] ;
for ( i = 0 ; i < _numFunctions ; i + + ) {
_functions [ i ] . pos = GetDWORD ( ) ;
_functions [ i ] . name = GetString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load events table
2012-04-28 01:00:14 +03:00
_iP = Header - > event_table ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_numEvents = GetDWORD ( ) ;
_events = new TEventPos [ _numEvents ] ;
for ( i = 0 ; i < _numEvents ; i + + ) {
_events [ i ] . pos = GetDWORD ( ) ;
_events [ i ] . name = GetString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load externals
if ( Header - > version > = 0x0101 ) {
2012-04-28 01:00:14 +03:00
_iP = Header - > externals_table ;
_numExternals = GetDWORD ( ) ;
_externals = new TExternalFunction [ _numExternals ] ;
for ( i = 0 ; i < _numExternals ; i + + ) {
_externals [ i ] . dll_name = GetString ( ) ;
_externals [ i ] . name = GetString ( ) ;
_externals [ i ] . call_type = ( TCallType ) GetDWORD ( ) ;
_externals [ i ] . returns = ( TExternalType ) GetDWORD ( ) ;
_externals [ i ] . nu_params = GetDWORD ( ) ;
if ( _externals [ i ] . nu_params > 0 ) {
_externals [ i ] . params = new TExternalType [ _externals [ i ] . nu_params ] ;
for ( int j = 0 ; j < _externals [ i ] . nu_params ; j + + ) {
_externals [ i ] . params [ j ] = ( TExternalType ) GetDWORD ( ) ;
2012-03-06 02:44:24 +01:00
}
}
}
}
// load method table
2012-04-28 01:00:14 +03:00
_iP = Header - > method_table ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_numMethods = GetDWORD ( ) ;
_methods = new TMethodPos [ _numMethods ] ;
for ( i = 0 ; i < _numMethods ; i + + ) {
_methods [ i ] . pos = GetDWORD ( ) ;
_methods [ i ] . name = GetString ( ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_iP = OrigIP ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
2012-05-11 14:16:50 +02:00
HRESULT CScScript : : Create ( const char * Filename , byte * Buffer , uint32 Size , CBScriptHolder * Owner ) {
2012-03-06 02:44:24 +01:00
Cleanup ( ) ;
2012-04-28 01:00:14 +03:00
_thread = false ;
_methodThread = false ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
delete [ ] _threadEvent ;
_threadEvent = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_filename = new char [ strlen ( Filename ) + 1 ] ;
if ( _filename ) strcpy ( _filename , Filename ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_buffer = new byte [ Size ] ;
if ( ! _buffer ) return E_FAIL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
memcpy ( _buffer , Buffer , Size ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_bufferSize = Size ;
2012-03-06 02:44:24 +01:00
HRESULT res = InitScript ( ) ;
if ( FAILED ( res ) ) return res ;
// establish global variables table
2012-04-28 01:00:14 +03:00
_globals = new CScValue ( Game ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_owner = Owner ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : CreateThread ( CScScript * Original , uint32 InitIP , const char * EventName ) {
Cleanup ( ) ;
2012-04-28 01:00:14 +03:00
_thread = true ;
_methodThread = false ;
_threadEvent = new char [ strlen ( EventName ) + 1 ] ;
if ( _threadEvent ) strcpy ( _threadEvent , EventName ) ;
2012-03-06 02:44:24 +01:00
// copy filename
2012-04-28 01:00:14 +03:00
_filename = new char [ strlen ( Original - > _filename ) + 1 ] ;
if ( _filename ) strcpy ( _filename , Original - > _filename ) ;
2012-03-06 02:44:24 +01:00
// copy buffer
2012-04-28 01:00:14 +03:00
_buffer = new byte [ Original - > _bufferSize ] ;
if ( ! _buffer ) return E_FAIL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
memcpy ( _buffer , Original - > _buffer , Original - > _bufferSize ) ;
_bufferSize = Original - > _bufferSize ;
2012-03-06 02:44:24 +01:00
// initialize
HRESULT res = InitScript ( ) ;
if ( FAILED ( res ) ) return res ;
// copy globals
2012-04-28 01:00:14 +03:00
_globals = Original - > _globals ;
2012-03-06 02:44:24 +01:00
// skip to the beginning of the event
2012-04-28 01:00:14 +03:00
_iP = InitIP ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_timeSlice = Original - > _timeSlice ;
_freezable = Original - > _freezable ;
_owner = Original - > _owner ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_engine = Original - > _engine ;
_parentScript = Original ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : CreateMethodThread ( CScScript * Original , const char * MethodName ) {
uint32 IP = Original - > GetMethodPos ( MethodName ) ;
if ( IP = = 0 ) return E_FAIL ;
Cleanup ( ) ;
2012-04-28 01:00:14 +03:00
_thread = true ;
_methodThread = true ;
_threadEvent = new char [ strlen ( MethodName ) + 1 ] ;
if ( _threadEvent ) strcpy ( _threadEvent , MethodName ) ;
2012-03-06 02:44:24 +01:00
// copy filename
2012-04-28 01:00:14 +03:00
_filename = new char [ strlen ( Original - > _filename ) + 1 ] ;
if ( _filename ) strcpy ( _filename , Original - > _filename ) ;
2012-03-06 02:44:24 +01:00
// copy buffer
2012-04-28 01:00:14 +03:00
_buffer = new byte [ Original - > _bufferSize ] ;
if ( ! _buffer ) return E_FAIL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
memcpy ( _buffer , Original - > _buffer , Original - > _bufferSize ) ;
_bufferSize = Original - > _bufferSize ;
2012-03-06 02:44:24 +01:00
// initialize
HRESULT res = InitScript ( ) ;
if ( FAILED ( res ) ) return res ;
// copy globals
2012-04-28 01:00:14 +03:00
_globals = Original - > _globals ;
2012-03-06 02:44:24 +01:00
// skip to the beginning of the event
2012-04-28 01:00:14 +03:00
_iP = IP ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_timeSlice = Original - > _timeSlice ;
_freezable = Original - > _freezable ;
_owner = Original - > _owner ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_engine = Original - > _engine ;
_parentScript = Original ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
void CScScript : : Cleanup ( ) {
2012-04-28 01:00:14 +03:00
if ( _buffer ) delete [ ] _buffer ;
_buffer = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _filename ) delete [ ] _filename ;
_filename = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _symbols ) delete [ ] _symbols ;
_symbols = NULL ;
_numSymbols = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _globals & & ! _thread ) delete _globals ;
_globals = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _scopeStack ) delete _scopeStack ;
_scopeStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _callStack ) delete _callStack ;
_callStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _thisStack ) delete _thisStack ;
_thisStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _stack ) delete _stack ;
_stack = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _functions ) delete [ ] _functions ;
_functions = NULL ;
_numFunctions = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _methods ) delete [ ] _methods ;
_methods = NULL ;
_numMethods = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _events ) delete [ ] _events ;
_events = NULL ;
_numEvents = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _externals ) {
for ( int i = 0 ; i < _numExternals ; i + + ) {
if ( _externals [ i ] . nu_params > 0 ) delete [ ] _externals [ i ] . params ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
delete [ ] _externals ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_externals = NULL ;
_numExternals = 0 ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
delete _operand ;
delete _reg1 ;
_operand = NULL ;
_reg1 = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
delete [ ] _threadEvent ;
_threadEvent = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_waitObject = NULL ;
_waitTime = 0 ;
_waitFrozen = false ;
_waitScript = NULL ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_parentScript = NULL ; // ref only
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : GetDWORD ( ) {
2012-04-28 01:00:14 +03:00
uint32 ret = * ( uint32 * ) ( _buffer + _iP ) ;
_iP + = sizeof ( uint32 ) ;
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
double CScScript : : GetFloat ( ) {
2012-04-28 01:00:14 +03:00
double ret = * ( double * ) ( _buffer + _iP ) ;
_iP + = sizeof ( double ) ;
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
char * CScScript : : GetString ( ) {
2012-04-28 01:00:14 +03:00
char * ret = ( char * ) ( _buffer + _iP ) ;
while ( * ( char * ) ( _buffer + _iP ) ! = ' \0 ' ) _iP + + ;
_iP + + ; // string terminator
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : ExecuteInstruction ( ) {
HRESULT ret = S_OK ;
uint32 dw ;
2012-06-01 13:51:06 +02:00
const char * str = NULL ;
2012-03-06 02:44:24 +01:00
//CScValue* op = new CScValue(Game);
2012-04-28 01:00:14 +03:00
_operand - > Cleanup ( ) ;
2012-03-06 02:44:24 +01:00
CScValue * op1 ;
CScValue * op2 ;
uint32 inst = GetDWORD ( ) ;
switch ( inst ) {
case II_DEF_VAR :
2012-04-28 01:00:14 +03:00
_operand - > SetNULL ( ) ;
2012-03-06 02:44:24 +01:00
dw = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP < 0 ) {
_globals - > SetProp ( _symbols [ dw ] , _operand ) ;
if ( Game - > GetDebugMgr ( ) - > _enabled )
Game - > GetDebugMgr ( ) - > OnVariableInit ( WME_DBGVAR_SCRIPT , this , NULL , _globals - > GetProp ( _symbols [ dw ] ) , _symbols [ dw ] ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_scopeStack - > GetTop ( ) - > SetProp ( _symbols [ dw ] , _operand ) ;
if ( Game - > GetDebugMgr ( ) - > _enabled )
Game - > GetDebugMgr ( ) - > OnVariableInit ( WME_DBGVAR_SCOPE , this , _scopeStack - > GetTop ( ) , _scopeStack - > GetTop ( ) - > GetProp ( _symbols [ dw ] ) , _symbols [ dw ] ) ;
2012-03-06 02:44:24 +01:00
}
break ;
case II_DEF_GLOB_VAR :
case II_DEF_CONST_VAR : {
dw = GetDWORD ( ) ;
2012-06-22 14:10:08 +02:00
/* char *Temp = _symbols[dw]; // TODO delete */
2012-03-06 02:44:24 +01:00
// only create global var if it doesn't exist
2012-04-28 01:00:14 +03:00
if ( ! _engine - > _globals - > PropExists ( _symbols [ dw ] ) ) {
_operand - > SetNULL ( ) ;
_engine - > _globals - > SetProp ( _symbols [ dw ] , _operand , false , inst = = II_DEF_CONST_VAR ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( Game - > GetDebugMgr ( ) - > _enabled )
Game - > GetDebugMgr ( ) - > OnVariableInit ( WME_DBGVAR_GLOBAL , this , NULL , _engine - > _globals - > GetProp ( _symbols [ dw ] ) , _symbols [ dw ] ) ;
2012-03-06 02:44:24 +01:00
}
break ;
}
case II_RET :
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP > = 0 & & _callStack - > _sP > = 0 ) {
Game - > GetDebugMgr ( ) - > OnScriptShutdownScope ( this , _scopeStack - > GetTop ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_scopeStack - > Pop ( ) ;
_iP = ( uint32 ) _callStack - > Pop ( ) - > GetInt ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP < 0 ) Game - > GetDebugMgr ( ) - > OnScriptChangeScope ( this , NULL ) ;
else Game - > GetDebugMgr ( ) - > OnScriptChangeScope ( this , _scopeStack - > GetTop ( ) ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
if ( _thread ) {
_state = SCRIPT_THREAD_FINISHED ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
if ( _numEvents = = 0 & & _numMethods = = 0 ) _state = SCRIPT_FINISHED ;
else _state = SCRIPT_PERSISTENT ;
2012-03-06 02:44:24 +01:00
}
}
break ;
case II_RET_EVENT :
2012-04-28 01:00:14 +03:00
_state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
break ;
case II_CALL :
dw = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_operand - > SetInt ( _iP ) ;
_callStack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_iP = dw ;
2012-03-06 02:44:24 +01:00
break ;
case II_CALL_BY_EXP : {
// push var
// push string
2012-04-28 01:00:14 +03:00
str = _stack - > Pop ( ) - > GetString ( ) ;
2012-03-06 02:44:24 +01:00
char * MethodName = new char [ strlen ( str ) + 1 ] ;
strcpy ( MethodName , str ) ;
2012-04-28 01:00:14 +03:00
CScValue * var = _stack - > Pop ( ) ;
if ( var - > _type = = VAL_VARIABLE_REF ) var = var - > _valRef ;
2012-03-06 02:44:24 +01:00
HRESULT res = E_FAIL ;
bool TriedNative = false ;
// we are already calling this method, try native
2012-04-28 01:00:14 +03:00
if ( _thread & & _methodThread & & strcmp ( MethodName , _threadEvent ) = = 0 & & var - > _type = = VAL_NATIVE & & _owner = = var - > GetNative ( ) ) {
2012-03-06 02:44:24 +01:00
TriedNative = true ;
2012-04-28 01:00:14 +03:00
res = var - > _valNative - > ScCallMethod ( this , _stack , _thisStack , MethodName ) ;
2012-03-06 02:44:24 +01:00
}
if ( FAILED ( res ) ) {
if ( var - > IsNative ( ) & & var - > GetNative ( ) - > CanHandleMethod ( MethodName ) ) {
2012-04-28 01:00:14 +03:00
if ( ! _unbreakable ) {
_waitScript = var - > GetNative ( ) - > InvokeMethodThread ( MethodName ) ;
if ( ! _waitScript ) {
_stack - > CorrectParams ( 0 ) ;
2012-03-06 02:44:24 +01:00
RuntimeError ( " Error invoking method '%s'. " , MethodName ) ;
2012-04-28 01:00:14 +03:00
_stack - > PushNULL ( ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_state = SCRIPT_WAITING_SCRIPT ;
_waitScript - > CopyParameters ( _stack ) ;
2012-03-06 02:44:24 +01:00
}
} else {
// can call methods in unbreakable mode
2012-04-28 01:00:14 +03:00
_stack - > CorrectParams ( 0 ) ;
2012-03-06 02:44:24 +01:00
RuntimeError ( " Cannot call method '%s'. Ignored. " , MethodName ) ;
2012-04-28 01:00:14 +03:00
_stack - > PushNULL ( ) ;
2012-03-06 02:44:24 +01:00
}
delete [ ] MethodName ;
break ;
}
/*
CScValue * val = var - > GetProp ( MethodName ) ;
if ( val ) {
dw = GetFuncPos ( val - > GetString ( ) ) ;
if ( dw = = 0 ) {
TExternalFunction * f = GetExternal ( val - > GetString ( ) ) ;
if ( f ) {
2012-04-28 01:00:14 +03:00
ExternalCall ( _stack , _thisStack , f ) ;
2012-03-06 02:44:24 +01:00
}
else {
// not an internal nor external, try for native function
2012-04-28 01:00:14 +03:00
Game - > ExternalCall ( this , _stack , _thisStack , val - > GetString ( ) ) ;
2012-03-06 02:44:24 +01:00
}
}
else {
2012-04-28 01:00:14 +03:00
_operand - > SetInt ( _iP ) ;
_callStack - > Push ( _operand ) ;
_iP = dw ;
2012-03-06 02:44:24 +01:00
}
}
*/
else {
res = E_FAIL ;
2012-04-28 01:00:14 +03:00
if ( var - > _type = = VAL_NATIVE & & ! TriedNative ) res = var - > _valNative - > ScCallMethod ( this , _stack , _thisStack , MethodName ) ;
2012-03-06 02:44:24 +01:00
if ( FAILED ( res ) ) {
2012-04-28 01:00:14 +03:00
_stack - > CorrectParams ( 0 ) ;
2012-03-06 02:44:24 +01:00
RuntimeError ( " Call to undefined method '%s'. Ignored. " , MethodName ) ;
2012-04-28 01:00:14 +03:00
_stack - > PushNULL ( ) ;
2012-03-06 02:44:24 +01:00
}
}
}
delete [ ] MethodName ;
}
break ;
case II_EXTERNAL_CALL : {
uint32 SymbolIndex = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
TExternalFunction * f = GetExternal ( _symbols [ SymbolIndex ] ) ;
2012-03-06 02:44:24 +01:00
if ( f ) {
2012-04-28 01:00:14 +03:00
ExternalCall ( _stack , _thisStack , f ) ;
} else Game - > ExternalCall ( this , _stack , _thisStack , _symbols [ SymbolIndex ] ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_SCOPE :
2012-04-28 01:00:14 +03:00
_operand - > SetNULL ( ) ;
_scopeStack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP < 0 ) Game - > GetDebugMgr ( ) - > OnScriptChangeScope ( this , NULL ) ;
else Game - > GetDebugMgr ( ) - > OnScriptChangeScope ( this , _scopeStack - > GetTop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CORRECT_STACK :
dw = GetDWORD ( ) ; // params expected
2012-04-28 01:00:14 +03:00
_stack - > CorrectParams ( dw ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CREATE_OBJECT :
2012-04-28 01:00:14 +03:00
_operand - > SetObject ( ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_EMPTY :
2012-04-28 01:00:14 +03:00
_stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_VAR : {
2012-04-28 01:00:14 +03:00
CScValue * var = GetVar ( _symbols [ GetDWORD ( ) ] ) ;
if ( false & & /*var->_type==VAL_OBJECT ||*/ var - > _type = = VAL_NATIVE ) {
_operand - > SetReference ( var ) ;
_stack - > Push ( _operand ) ;
} else _stack - > Push ( var ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_PUSH_VAR_REF : {
2012-04-28 01:00:14 +03:00
CScValue * var = GetVar ( _symbols [ GetDWORD ( ) ] ) ;
_operand - > SetReference ( var ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_POP_VAR : {
2012-04-28 01:00:14 +03:00
char * VarName = _symbols [ GetDWORD ( ) ] ;
2012-03-06 02:44:24 +01:00
CScValue * var = GetVar ( VarName ) ;
if ( var ) {
2012-04-28 01:00:14 +03:00
CScValue * val = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( ! val ) {
RuntimeError ( " Script stack corruption detected. Please report this script at WME bug reports forum. " ) ;
var - > SetNULL ( ) ;
} else {
2012-04-28 01:00:14 +03:00
if ( val - > GetType ( ) = = VAL_VARIABLE_REF ) val = val - > _valRef ;
if ( val - > _type = = VAL_NATIVE ) var - > SetValue ( val ) ;
2012-03-06 02:44:24 +01:00
else {
var - > Copy ( val ) ;
}
}
2012-04-28 01:00:14 +03:00
if ( Game - > GetDebugMgr ( ) - > _enabled )
2012-03-06 02:44:24 +01:00
Game - > GetDebugMgr ( ) - > OnVariableChangeValue ( var , val ) ;
}
break ;
}
case II_PUSH_VAR_THIS :
2012-04-28 01:00:14 +03:00
_stack - > Push ( _thisStack - > GetTop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_INT :
2012-04-28 01:00:14 +03:00
_stack - > PushInt ( ( int ) GetDWORD ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_FLOAT :
2012-04-28 01:00:14 +03:00
_stack - > PushFloat ( GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_BOOL :
2012-04-28 01:00:14 +03:00
_stack - > PushBool ( GetDWORD ( ) ! = 0 ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_STRING :
2012-04-28 01:00:14 +03:00
_stack - > PushString ( GetString ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_NULL :
2012-04-28 01:00:14 +03:00
_stack - > PushNULL ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_THIS_FROM_STACK :
2012-04-28 01:00:14 +03:00
_operand - > SetReference ( _stack - > GetTop ( ) ) ;
_thisStack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_THIS :
2012-04-28 01:00:14 +03:00
_operand - > SetReference ( GetVar ( _symbols [ GetDWORD ( ) ] ) ) ;
_thisStack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_THIS :
2012-04-28 01:00:14 +03:00
_thisStack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_BY_EXP : {
2012-04-28 01:00:14 +03:00
str = _stack - > Pop ( ) - > GetString ( ) ;
CScValue * val = _stack - > Pop ( ) - > GetProp ( str ) ;
if ( val ) _stack - > Push ( val ) ;
else _stack - > PushNULL ( ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_POP_BY_EXP : {
2012-04-28 01:00:14 +03:00
str = _stack - > Pop ( ) - > GetString ( ) ;
CScValue * var = _stack - > Pop ( ) ;
CScValue * val = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( val = = NULL ) {
RuntimeError ( " Script stack corruption detected. Please report this script at WME bug reports forum. " ) ;
var - > SetNULL ( ) ;
} else var - > SetProp ( str , val ) ;
2012-04-28 01:00:14 +03:00
if ( Game - > GetDebugMgr ( ) - > _enabled )
2012-03-06 02:44:24 +01:00
Game - > GetDebugMgr ( ) - > OnVariableChangeValue ( var , NULL ) ;
break ;
}
case II_PUSH_REG1 :
2012-04-28 01:00:14 +03:00
_stack - > Push ( _reg1 ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_REG1 :
2012-04-28 01:00:14 +03:00
_reg1 - > Copy ( _stack - > Pop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_JMP :
2012-04-28 01:00:14 +03:00
_iP = GetDWORD ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_JMP_FALSE : {
dw = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
//if(!_stack->Pop()->GetBool()) _iP = dw;
CScValue * Val = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( ! Val ) {
RuntimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
} else {
2012-04-28 01:00:14 +03:00
if ( ! Val - > GetBool ( ) ) _iP = dw ;
2012-03-06 02:44:24 +01:00
}
break ;
}
case II_ADD :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( op1 - > IsNULL ( ) | | op2 - > IsNULL ( ) ) _operand - > SetNULL ( ) ;
2012-03-06 02:44:24 +01:00
else if ( op1 - > GetType ( ) = = VAL_STRING | | op2 - > GetType ( ) = = VAL_STRING ) {
2012-05-11 14:16:50 +02:00
char * tempStr = new char [ strlen ( op1 - > GetString ( ) ) + strlen ( op2 - > GetString ( ) ) + 1 ] ;
strcpy ( tempStr , op1 - > GetString ( ) ) ;
strcat ( tempStr , op2 - > GetString ( ) ) ;
2012-06-13 21:09:42 +02:00
_operand - > SetString ( tempStr ) ;
2012-05-11 14:16:50 +02:00
delete [ ] tempStr ;
2012-03-06 02:44:24 +01:00
} else if ( op1 - > GetType ( ) = = VAL_INT & & op2 - > GetType ( ) = = VAL_INT )
2012-04-28 01:00:14 +03:00
_operand - > SetInt ( op1 - > GetInt ( ) + op2 - > GetInt ( ) ) ;
else _operand - > SetFloat ( op1 - > GetFloat ( ) + op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_SUB :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( op1 - > IsNULL ( ) | | op2 - > IsNULL ( ) ) _operand - > SetNULL ( ) ;
2012-03-06 02:44:24 +01:00
else if ( op1 - > GetType ( ) = = VAL_INT & & op2 - > GetType ( ) = = VAL_INT )
2012-04-28 01:00:14 +03:00
_operand - > SetInt ( op1 - > GetInt ( ) - op2 - > GetInt ( ) ) ;
else _operand - > SetFloat ( op1 - > GetFloat ( ) - op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_MUL :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
if ( op1 - > IsNULL ( ) | | op2 - > IsNULL ( ) ) _operand - > SetNULL ( ) ;
2012-03-06 02:44:24 +01:00
else if ( op1 - > GetType ( ) = = VAL_INT & & op2 - > GetType ( ) = = VAL_INT )
2012-04-28 01:00:14 +03:00
_operand - > SetInt ( op1 - > GetInt ( ) * op2 - > GetInt ( ) ) ;
else _operand - > SetFloat ( op1 - > GetFloat ( ) * op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_DIV :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op2 - > GetFloat ( ) = = 0.0f ) RuntimeError ( " Division by zero. " ) ;
2012-04-28 01:00:14 +03:00
if ( op1 - > IsNULL ( ) | | op2 - > IsNULL ( ) | | op2 - > GetFloat ( ) = = 0.0f ) _operand - > SetNULL ( ) ;
else _operand - > SetFloat ( op1 - > GetFloat ( ) / op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_MODULO :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op2 - > GetInt ( ) = = 0 ) RuntimeError ( " Division by zero. " ) ;
2012-04-28 01:00:14 +03:00
if ( op1 - > IsNULL ( ) | | op2 - > IsNULL ( ) | | op2 - > GetInt ( ) = = 0 ) _operand - > SetNULL ( ) ;
else _operand - > SetInt ( op1 - > GetInt ( ) % op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_NOT :
2012-04-28 01:00:14 +03:00
op1 = _stack - > Pop ( ) ;
//if(op1->IsNULL()) _operand->SetNULL();
if ( op1 - > IsNULL ( ) ) _operand - > SetBool ( true ) ;
else _operand - > SetBool ( ! op1 - > GetBool ( ) ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_AND :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op1 = = NULL | | op2 = = NULL ) {
RuntimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( false ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetBool ( ) & & op2 - > GetBool ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_OR :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op1 = = NULL | | op2 = = NULL ) {
RuntimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( false ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetBool ( ) | | op2 - > GetBool ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_EQ :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-04-28 01:00:14 +03:00
if ( ( op1 - > IsNULL ( ) & & ! op2 - > IsNULL ( ) ) | | ( ! op1 - > IsNULL ( ) & & op2 - > IsNULL ( ) ) ) _operand - > SetBool ( false ) ;
2012-03-06 02:44:24 +01:00
else if ( op1 - > IsNative ( ) & & op2 - > IsNative ( ) ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetNative ( ) = = op2 - > GetNative ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else if ( op1 - > GetType ( ) = = VAL_STRING | | op2 - > GetType ( ) = = VAL_STRING ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( scumm_stricmp ( op1 - > GetString ( ) , op2 - > GetString ( ) ) = = 0 ) ;
2012-03-06 02:44:24 +01:00
}
else if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) = = op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetInt ( ) = = op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
}
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) = = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_NE :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-04-28 01:00:14 +03:00
if ( ( op1 - > IsNULL ( ) & & ! op2 - > IsNULL ( ) ) | | ( ! op1 - > IsNULL ( ) & & op2 - > IsNULL ( ) ) ) _operand - > SetBool ( true ) ;
2012-03-06 02:44:24 +01:00
else if ( op1 - > IsNative ( ) & & op2 - > IsNative ( ) ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetNative ( ) ! = op2 - > GetNative ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else if ( op1 - > GetType ( ) = = VAL_STRING | | op2 - > GetType ( ) = = VAL_STRING ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( scumm_stricmp ( op1 - > GetString ( ) , op2 - > GetString ( ) ) ! = 0 ) ;
2012-03-06 02:44:24 +01:00
}
else if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) ! = op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetInt ( ) ! = op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
}
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) ! = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_L :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) < op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
else _operand - > SetBool ( op1 - > GetInt ( ) < op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) < 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_G :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) > op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
else _operand - > SetBool ( op1 - > GetInt ( ) > op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) > 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_LE :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) < = op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
else _operand - > SetBool ( op1 - > GetInt ( ) < = op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) < = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_GE :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
if ( op1 - > GetType ( ) = = VAL_FLOAT & & op2 - > GetType ( ) = = VAL_FLOAT ) {
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( op1 - > GetFloat ( ) > = op2 - > GetFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
else _operand - > SetBool ( op1 - > GetInt ( ) > = op2 - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-04-28 01:00:14 +03:00
_operand - > SetBool ( CScValue : : Compare ( op1 , op2 ) > = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_STRICT_EQ :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
//_operand->SetBool(op1->GetType()==op2->GetType() && op1->GetFloat()==op2->GetFloat());
_operand - > SetBool ( CScValue : : CompareStrict ( op1 , op2 ) = = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_STRICT_NE :
2012-04-28 01:00:14 +03:00
op2 = _stack - > Pop ( ) ;
op1 = _stack - > Pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
//_operand->SetBool(op1->GetType()!=op2->GetType() || op1->GetFloat()!=op2->GetFloat());
_operand - > SetBool ( CScValue : : CompareStrict ( op1 , op2 ) ! = 0 ) ;
_stack - > Push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_DBG_LINE : {
int NewLine = GetDWORD ( ) ;
2012-04-28 01:00:14 +03:00
if ( NewLine ! = _currentLine ) {
_currentLine = NewLine ;
if ( Game - > GetDebugMgr ( ) - > _enabled ) {
Game - > GetDebugMgr ( ) - > OnScriptChangeLine ( this , _currentLine ) ;
for ( int i = 0 ; i < _breakpoints . GetSize ( ) ; i + + ) {
if ( _breakpoints [ i ] = = _currentLine ) {
2012-03-06 02:44:24 +01:00
Game - > GetDebugMgr ( ) - > OnScriptHitBreakpoint ( this ) ;
Sleep ( 0 ) ;
break ;
}
}
2012-04-28 01:00:14 +03:00
if ( _tracingMode ) {
2012-03-06 02:44:24 +01:00
Game - > GetDebugMgr ( ) - > OnScriptHitBreakpoint ( this ) ;
Sleep ( 0 ) ;
break ;
}
}
}
break ;
}
default :
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x) \n " , inst , _filename , _currentLine , _iP - sizeof ( uint32 ) ) ;
_state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
ret = E_FAIL ;
} // switch(instruction)
//delete op;
return ret ;
}
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : GetFuncPos ( const char * Name ) {
2012-04-28 01:00:14 +03:00
for ( int i = 0 ; i < _numFunctions ; i + + ) {
if ( strcmp ( Name , _functions [ i ] . name ) = = 0 ) return _functions [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : GetMethodPos ( const char * Name ) {
2012-04-28 01:00:14 +03:00
for ( int i = 0 ; i < _numMethods ; i + + ) {
if ( strcmp ( Name , _methods [ i ] . name ) = = 0 ) return _methods [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
CScValue * CScScript : : GetVar ( char * Name ) {
CScValue * ret = NULL ;
// scope locals
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP > = 0 ) {
if ( _scopeStack - > GetTop ( ) - > PropExists ( Name ) ) ret = _scopeStack - > GetTop ( ) - > GetProp ( Name ) ;
2012-03-06 02:44:24 +01:00
}
// script globals
if ( ret = = NULL ) {
2012-04-28 01:00:14 +03:00
if ( _globals - > PropExists ( Name ) ) ret = _globals - > GetProp ( Name ) ;
2012-03-06 02:44:24 +01:00
}
// engine globals
if ( ret = = NULL ) {
2012-04-28 01:00:14 +03:00
if ( _engine - > _globals - > PropExists ( Name ) ) ret = _engine - > _globals - > GetProp ( Name ) ;
2012-03-06 02:44:24 +01:00
}
if ( ret = = NULL ) {
//RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", Name);
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d) " , Name , _filename , _currentLine ) ;
2012-03-06 02:44:24 +01:00
CScValue * Val = new CScValue ( Game ) ;
2012-04-28 01:00:14 +03:00
CScValue * Scope = _scopeStack - > GetTop ( ) ;
2012-03-06 02:44:24 +01:00
if ( Scope ) {
Scope - > SetProp ( Name , Val ) ;
2012-04-28 01:00:14 +03:00
ret = _scopeStack - > GetTop ( ) - > GetProp ( Name ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_globals - > SetProp ( Name , Val ) ;
ret = _globals - > GetProp ( Name ) ;
2012-03-06 02:44:24 +01:00
}
delete Val ;
}
return ret ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : WaitFor ( CBObject * Object ) {
2012-04-28 01:00:14 +03:00
if ( _unbreakable ) {
2012-03-06 02:44:24 +01:00
RuntimeError ( " Script cannot be interrupted. " ) ;
return S_OK ;
}
2012-04-28 01:00:14 +03:00
_state = SCRIPT_WAITING ;
_waitObject = Object ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : WaitForExclusive ( CBObject * Object ) {
2012-04-28 01:00:14 +03:00
_engine - > ResetObject ( Object ) ;
2012-03-06 02:44:24 +01:00
return WaitFor ( Object ) ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : Sleep ( uint32 Duration ) {
2012-04-28 01:00:14 +03:00
if ( _unbreakable ) {
2012-03-06 02:44:24 +01:00
RuntimeError ( " Script cannot be interrupted. " ) ;
return S_OK ;
}
2012-04-28 01:00:14 +03:00
_state = SCRIPT_SLEEPING ;
if ( Game - > _state = = GAME_FROZEN ) {
_waitTime = CBPlatform : : GetTime ( ) + Duration ;
_waitFrozen = true ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_waitTime = Game - > _timer + Duration ;
_waitFrozen = false ;
2012-03-06 02:44:24 +01:00
}
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : Finish ( bool IncludingThreads ) {
2012-04-28 01:00:14 +03:00
if ( _state ! = SCRIPT_FINISHED & & IncludingThreads ) {
_state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
FinishThreads ( ) ;
2012-04-28 01:00:14 +03:00
} else _state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : Run ( ) {
2012-04-28 01:00:14 +03:00
_state = SCRIPT_RUNNING ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////
void CScScript : : RuntimeError ( LPCSTR fmt , . . . ) {
char buff [ 256 ] ;
va_list va ;
va_start ( va , fmt ) ;
vsprintf ( buff , fmt , va ) ;
va_end ( va ) ;
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " Runtime error. Script '%s', line %d " , _filename , _currentLine ) ;
2012-03-06 02:44:24 +01:00
Game - > LOG ( 0 , " %s " , buff ) ;
2012-04-28 01:00:14 +03:00
if ( ! Game - > _suppressScriptErrors )
2012-03-06 02:44:24 +01:00
Game - > QuickMessage ( " Script runtime error. View log for details. " ) ;
}
//////////////////////////////////////////////////////////////////////////
2012-06-22 20:06:12 +02:00
HRESULT CScScript : : persist ( CBPersistMgr * persistMgr ) {
2012-03-06 02:44:24 +01:00
2012-06-22 13:56:51 +02:00
persistMgr - > transfer ( TMEMBER ( Game ) ) ;
2012-03-06 02:44:24 +01:00
// buffer
2012-06-22 13:56:51 +02:00
if ( persistMgr - > _saving ) {
2012-04-28 01:00:14 +03:00
if ( _state ! = SCRIPT_PERSISTENT & & _state ! = SCRIPT_FINISHED & & _state ! = SCRIPT_THREAD_FINISHED ) {
2012-06-22 13:56:51 +02:00
persistMgr - > transfer ( TMEMBER ( _bufferSize ) ) ;
persistMgr - > putBytes ( _buffer , _bufferSize ) ;
2012-03-06 02:44:24 +01:00
} else {
// don't save idle/finished scripts
int bufferSize = 0 ;
2012-06-22 13:56:51 +02:00
persistMgr - > transfer ( TMEMBER ( bufferSize ) ) ;
2012-03-06 02:44:24 +01:00
}
} else {
2012-06-22 13:56:51 +02:00
persistMgr - > transfer ( TMEMBER ( _bufferSize ) ) ;
2012-04-28 01:00:14 +03:00
if ( _bufferSize > 0 ) {
_buffer = new byte [ _bufferSize ] ;
2012-06-22 13:56:51 +02:00
persistMgr - > getBytes ( _buffer , _bufferSize ) ;
2012-03-06 02:44:24 +01:00
InitTables ( ) ;
2012-04-28 01:00:14 +03:00
} else _buffer = NULL ;
2012-03-06 02:44:24 +01:00
}
2012-06-22 13:56:51 +02:00
persistMgr - > transfer ( TMEMBER ( _callStack ) ) ;
persistMgr - > transfer ( TMEMBER ( _currentLine ) ) ;
persistMgr - > transfer ( TMEMBER ( _engine ) ) ;
persistMgr - > transfer ( TMEMBER ( _filename ) ) ;
persistMgr - > transfer ( TMEMBER ( _freezable ) ) ;
persistMgr - > transfer ( TMEMBER ( _globals ) ) ;
persistMgr - > transfer ( TMEMBER ( _iP ) ) ;
persistMgr - > transfer ( TMEMBER ( _scopeStack ) ) ;
persistMgr - > transfer ( TMEMBER ( _stack ) ) ;
persistMgr - > transfer ( TMEMBER_INT ( _state ) ) ;
persistMgr - > transfer ( TMEMBER ( _operand ) ) ;
persistMgr - > transfer ( TMEMBER_INT ( _origState ) ) ;
persistMgr - > transfer ( TMEMBER ( _owner ) ) ;
persistMgr - > transfer ( TMEMBER ( _reg1 ) ) ;
persistMgr - > transfer ( TMEMBER ( _thread ) ) ;
persistMgr - > transfer ( TMEMBER ( _threadEvent ) ) ;
persistMgr - > transfer ( TMEMBER ( _thisStack ) ) ;
persistMgr - > transfer ( TMEMBER ( _timeSlice ) ) ;
persistMgr - > transfer ( TMEMBER ( _waitObject ) ) ;
persistMgr - > transfer ( TMEMBER ( _waitScript ) ) ;
persistMgr - > transfer ( TMEMBER ( _waitTime ) ) ;
persistMgr - > transfer ( TMEMBER ( _waitFrozen ) ) ;
persistMgr - > transfer ( TMEMBER ( _methodThread ) ) ;
persistMgr - > transfer ( TMEMBER ( _methodThread ) ) ;
persistMgr - > transfer ( TMEMBER ( _unbreakable ) ) ;
persistMgr - > transfer ( TMEMBER ( _parentScript ) ) ;
if ( ! persistMgr - > _saving ) _tracingMode = false ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
CScScript * CScScript : : InvokeEventHandler ( const char * EventName , bool Unbreakable ) {
2012-04-28 01:00:14 +03:00
//if(_state!=SCRIPT_PERSISTENT) return NULL;
2012-03-06 02:44:24 +01:00
uint32 pos = GetEventPos ( EventName ) ;
if ( ! pos ) return NULL ;
2012-04-28 01:00:14 +03:00
CScScript * thread = new CScScript ( Game , _engine ) ;
2012-03-06 02:44:24 +01:00
if ( thread ) {
HRESULT ret = thread - > CreateThread ( this , pos , EventName ) ;
if ( SUCCEEDED ( ret ) ) {
2012-04-28 01:00:14 +03:00
thread - > _unbreakable = Unbreakable ;
_engine - > _scripts . Add ( thread ) ;
2012-03-06 02:44:24 +01:00
Game - > GetDebugMgr ( ) - > OnScriptEventThreadInit ( thread , this , EventName ) ;
return thread ;
} else {
delete thread ;
return NULL ;
}
} else return NULL ;
}
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : GetEventPos ( const char * Name ) {
2012-04-28 01:00:14 +03:00
for ( int i = _numEvents - 1 ; i > = 0 ; i - - ) {
if ( scumm_stricmp ( Name , _events [ i ] . name ) = = 0 ) return _events [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
2012-05-11 14:16:50 +02:00
bool CScScript : : CanHandleEvent ( const char * EventName ) {
2012-03-06 02:44:24 +01:00
return GetEventPos ( EventName ) ! = 0 ;
}
//////////////////////////////////////////////////////////////////////////
2012-05-11 14:16:50 +02:00
bool CScScript : : CanHandleMethod ( const char * MethodName ) {
2012-03-06 02:44:24 +01:00
return GetMethodPos ( MethodName ) ! = 0 ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : Pause ( ) {
2012-04-28 01:00:14 +03:00
if ( _state = = SCRIPT_PAUSED ) {
Game - > LOG ( 0 , " Attempting to pause a paused script ('%s', line %d) " , _filename , _currentLine ) ;
2012-03-06 02:44:24 +01:00
return E_FAIL ;
}
2012-04-28 01:00:14 +03:00
if ( ! _freezable | | _state = = SCRIPT_PERSISTENT ) return S_OK ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_origState = _state ;
_state = SCRIPT_PAUSED ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : Resume ( ) {
2012-04-28 01:00:14 +03:00
if ( _state ! = SCRIPT_PAUSED ) return S_OK ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_state = _origState ;
2012-03-06 02:44:24 +01:00
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
CScScript : : TExternalFunction * CScScript : : GetExternal ( char * Name ) {
2012-04-28 01:00:14 +03:00
for ( int i = 0 ; i < _numExternals ; i + + ) {
if ( strcmp ( Name , _externals [ i ] . name ) = = 0 ) return & _externals [ i ] ;
2012-03-06 02:44:24 +01:00
}
return NULL ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : ExternalCall ( CScStack * Stack , CScStack * ThisStack , CScScript : : TExternalFunction * Function ) {
# ifndef __WIN32__
Game - > LOG ( 0 , " External functions are not supported on this platform. " ) ;
Stack - > CorrectParams ( 0 ) ;
Stack - > PushNULL ( ) ;
return E_FAIL ;
# else
bool Success = false ;
HMODULE hDll = LoadLibrary ( Function - > dll_name ) ;
if ( hDll ) {
FARPROC pFunc = GetProcAddress ( hDll , Function - > name ) ;
if ( pFunc ) {
int i ;
Success = true ;
2012-04-28 01:00:14 +03:00
Stack - > CorrectParams ( Function - > nu_params ) ;
2012-03-06 02:44:24 +01:00
CBDynBuffer * Buffer = new CBDynBuffer ( Game , 20 * sizeof ( uint32 ) ) ;
2012-04-28 01:00:14 +03:00
for ( i = 0 ; i < Function - > nu_params ; i + + ) {
2012-03-06 02:44:24 +01:00
CScValue * Val = Stack - > Pop ( ) ;
switch ( Function - > params [ i ] ) {
case TYPE_BOOL :
Buffer - > PutDWORD ( ( uint32 ) Val - > GetBool ( ) ) ;
break ;
case TYPE_LONG :
Buffer - > PutDWORD ( Val - > GetInt ( ) ) ;
break ;
case TYPE_BYTE :
2012-05-11 16:03:59 +02:00
Buffer - > PutDWORD ( ( byte ) Val - > GetInt ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case TYPE_STRING :
if ( Val - > IsNULL ( ) ) Buffer - > PutDWORD ( 0 ) ;
else Buffer - > PutDWORD ( ( uint32 ) Val - > GetString ( ) ) ;
break ;
case TYPE_MEMBUFFER :
if ( Val - > IsNULL ( ) ) Buffer - > PutDWORD ( 0 ) ;
else Buffer - > PutDWORD ( ( uint32 ) Val - > GetMemBuffer ( ) ) ;
break ;
case TYPE_FLOAT : {
float f = Val - > GetFloat ( ) ;
Buffer - > PutDWORD ( * ( ( uint32 * ) & f ) ) ;
break ;
}
case TYPE_DOUBLE : {
double d = Val - > GetFloat ( ) ;
uint32 * pd = ( uint32 * ) & d ;
Buffer - > PutDWORD ( pd [ 0 ] ) ;
Buffer - > PutDWORD ( pd [ 1 ] ) ;
break ;
}
}
}
// call
uint32 ret ;
bool StackCorrupted = false ;
switch ( Function - > call_type ) {
case CALL_CDECL :
2012-04-28 01:00:14 +03:00
ret = Call_cdecl ( Buffer - > _buffer , Buffer - > GetSize ( ) , ( uint32 ) pFunc , & StackCorrupted ) ;
2012-03-06 02:44:24 +01:00
break ;
default :
2012-04-28 01:00:14 +03:00
ret = Call_stdcall ( Buffer - > _buffer , Buffer - > GetSize ( ) , ( uint32 ) pFunc , & StackCorrupted ) ;
2012-03-06 02:44:24 +01:00
}
delete Buffer ;
// return
switch ( Function - > returns ) {
case TYPE_BOOL :
2012-05-11 16:03:59 +02:00
Stack - > PushBool ( ( byte ) ret ! = 0 ) ;
2012-03-06 02:44:24 +01:00
break ;
case TYPE_LONG :
Stack - > PushInt ( ret ) ;
break ;
case TYPE_BYTE :
2012-05-11 16:03:59 +02:00
Stack - > PushInt ( ( byte ) ret ) ;
2012-03-06 02:44:24 +01:00
break ;
break ;
case TYPE_STRING :
Stack - > PushString ( ( char * ) ret ) ;
break ;
case TYPE_MEMBUFFER : {
CSXMemBuffer * Buf = new CSXMemBuffer ( Game , ( void * ) ret ) ;
Stack - > PushNative ( Buf , false ) ;
}
break ;
case TYPE_FLOAT : {
uint32 dw = GetST0 ( ) ;
Stack - > PushFloat ( * ( ( float * ) & dw ) ) ;
break ;
}
case TYPE_DOUBLE :
Stack - > PushFloat ( GetST0Double ( ) ) ;
break ;
default :
Stack - > PushNULL ( ) ;
}
if ( StackCorrupted ) RuntimeError ( " Warning: Stack corrupted after calling '%s' in '%s' \n Check parameters and/or calling convention. " , Function - > name , Function - > dll_name ) ;
} else RuntimeError ( " Exported function '%s' not found in '%s' " , Function - > name , Function - > dll_name ) ;
} else RuntimeError ( " Error loading DLL '%s' " , Function - > dll_name ) ;
if ( ! Success ) {
Stack - > CorrectParams ( 0 ) ;
Stack - > PushNULL ( ) ;
}
if ( hDll ) FreeLibrary ( hDll ) ;
return Success ? S_OK : E_FAIL ;
# endif
}
# ifdef __WIN32__
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : Call_cdecl ( const void * args , size_t sz , uint32 func , bool * StackCorrupt ) {
uint32 rc ; // here's our return value...
uint32 OrigESP ;
bool StkCorrupt = false ;
__asm {
mov OrigESP , esp
mov ecx , sz // get size of buffer
mov esi , args // get buffer
sub esp , ecx // allocate stack space
mov edi , esp // start of destination stack frame
shr ecx , 2 // make it dwords
rep movsd // copy params to real stack
call [ func ] // call the function
mov rc , eax // save the return value
add esp , sz // restore the stack pointer
cmp esp , OrigESP
jz finish
mov esp , OrigESP
mov StkCorrupt , 1
finish :
}
if ( StackCorrupt ) * StackCorrupt = StkCorrupt ;
return rc ;
}
//////////////////////////////////////////////////////////////////////////
uint32 CScScript : : Call_stdcall ( const void * args , size_t sz , uint32 func , bool * StackCorrupt ) {
uint32 rc ; // here's our return value...
uint32 OrigESP ;
bool StkCorrupt = false ;
__asm {
mov OrigESP , esp
mov ecx , sz // get size of buffer
mov esi , args // get buffer
sub esp , ecx // allocate stack space
mov edi , esp // start of destination stack frame
shr ecx , 2 // make it dwords
rep movsd // copy it
call [ func ] // call the function
mov rc , eax // save the return value
cmp esp , OrigESP
jz finish
mov esp , OrigESP
mov StkCorrupt , 1
finish :
}
if ( StackCorrupt ) * StackCorrupt = StkCorrupt ;
return rc ;
}
//////////////////////////////////////////////////////////////////////////
__declspec ( naked ) uint32 CScScript : : GetST0 ( void ) {
uint32 f ; // temp var
__asm {
fstp uint32 ptr [ f ] // pop ST0 into f
mov eax , uint32 ptr [ f ] // copy into eax
ret // done
}
}
//////////////////////////////////////////////////////////////////////////
double CScScript : : GetST0Double ( void ) {
double d ; // temp var
__asm {
fstp qword ptr [ d ] // get ST0 into d
}
return d ;
}
# endif
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : CopyParameters ( CScStack * Stack ) {
int i ;
int NumParams = Stack - > Pop ( ) - > GetInt ( ) ;
for ( i = NumParams - 1 ; i > = 0 ; i - - ) {
2012-04-28 01:00:14 +03:00
_stack - > Push ( Stack - > GetAt ( i ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_stack - > PushInt ( NumParams ) ;
2012-03-06 02:44:24 +01:00
for ( i = 0 ; i < NumParams ; i + + ) Stack - > Pop ( ) ;
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : FinishThreads ( ) {
2012-04-28 01:00:14 +03:00
for ( int i = 0 ; i < _engine - > _scripts . GetSize ( ) ; i + + ) {
CScScript * Scr = _engine - > _scripts [ i ] ;
if ( Scr - > _thread & & Scr - > _state ! = SCRIPT_FINISHED & & Scr - > _owner = = _owner & & scumm_stricmp ( Scr - > _filename , _filename ) = = 0 )
2012-03-06 02:44:24 +01:00
Scr - > Finish ( true ) ;
}
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
// IWmeDebugScript interface implementation
int CScScript : : DbgGetLine ( ) {
2012-04-28 01:00:14 +03:00
return _currentLine ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
const char * CScScript : : DbgGetFilename ( ) {
2012-04-28 01:00:14 +03:00
return _filename ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : DbgSendScript ( IWmeDebugClient * Client ) {
2012-04-28 01:00:14 +03:00
if ( _methodThread ) Client - > OnScriptMethodThreadInit ( this , _parentScript , _threadEvent ) ;
else if ( _thread ) Client - > OnScriptEventThreadInit ( this , _parentScript , _threadEvent ) ;
2012-03-06 02:44:24 +01:00
else Client - > OnScriptInit ( this ) ;
return DbgSendVariables ( Client ) ;
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
HRESULT CScScript : : DbgSendVariables ( IWmeDebugClient * Client ) {
// send script globals
2012-04-28 01:00:14 +03:00
_globals - > DbgSendVariables ( Client , WME_DBGVAR_SCRIPT , this , 0 ) ;
2012-03-06 02:44:24 +01:00
// send scope variables
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP > = 0 ) {
for ( int i = 0 ; i < = _scopeStack - > _sP ; i + + ) {
2012-06-22 14:10:08 +02:00
// CScValue *Scope = _scopeStack->GetAt(i);
2012-03-06 02:44:24 +01:00
//Scope->DbgSendVariables(Client, WME_DBGVAR_SCOPE, this, (unsigned int)Scope);
}
}
return S_OK ;
}
//////////////////////////////////////////////////////////////////////////
TScriptState CScScript : : DbgGetState ( ) {
2012-04-28 01:00:14 +03:00
return _state ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
int CScScript : : DbgGetNumBreakpoints ( ) {
2012-04-28 01:00:14 +03:00
return _breakpoints . GetSize ( ) ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
int CScScript : : DbgGetBreakpoint ( int Index ) {
2012-04-28 01:00:14 +03:00
if ( Index > = 0 & & Index < _breakpoints . GetSize ( ) ) return _breakpoints [ Index ] ;
2012-03-06 02:44:24 +01:00
else return - 1 ;
}
//////////////////////////////////////////////////////////////////////////
bool CScScript : : DbgSetTracingMode ( bool IsTracing ) {
2012-04-28 01:00:14 +03:00
_tracingMode = IsTracing ;
2012-03-06 02:44:24 +01:00
return true ;
}
//////////////////////////////////////////////////////////////////////////
bool CScScript : : DbgGetTracingMode ( ) {
2012-04-28 01:00:14 +03:00
return _tracingMode ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
void CScScript : : AfterLoad ( ) {
2012-04-28 01:00:14 +03:00
if ( _buffer = = NULL ) {
byte * buffer = _engine - > GetCompiledScript ( _filename , & _bufferSize ) ;
2012-03-06 02:44:24 +01:00
if ( ! buffer ) {
2012-04-28 01:00:14 +03:00
Game - > LOG ( 0 , " Error reinitializing script '%s' after load. Script will be terminated. " , _filename ) ;
_state = SCRIPT_ERROR ;
2012-03-06 02:44:24 +01:00
return ;
}
2012-04-28 01:00:14 +03:00
_buffer = new byte [ _bufferSize ] ;
memcpy ( _buffer , buffer , _bufferSize ) ;
2012-03-06 02:44:24 +01:00
InitTables ( ) ;
}
}
} // end of namespace WinterMute