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
*/
2012-07-21 18:19:07 +02:00
# include "engines/wintermute/base/scriptables/script_value.h"
# include "engines/wintermute/base/scriptables/script.h"
# include "engines/wintermute/base/base_game.h"
# include "engines/wintermute/base/scriptables/script_engine.h"
# include "engines/wintermute/base/scriptables/script_stack.h"
2012-06-26 23:08:25 +02:00
# include "common/memstream.h"
2012-03-06 02:44:24 +01:00
namespace WinterMute {
2012-07-21 21:01:47 +02:00
IMPLEMENT_PERSISTENT ( ScScript , false )
2012-03-06 02:44:24 +01:00
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
ScScript : : ScScript ( BaseGame * inGame , ScEngine * Engine ) : BaseClass ( inGame ) {
2012-04-28 01:00:14 +03:00
_buffer = NULL ;
_bufferSize = _iP = 0 ;
2012-06-26 23:08:25 +02:00
_scriptStream = NULL ;
2012-04-28 01:00:14 +03:00
_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
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
ScScript : : ~ ScScript ( ) {
2012-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-21 21:01:47 +02:00
void ScScript : : readHeader ( ) {
2012-06-27 15:15:46 +02:00
uint32 oldPos = _scriptStream - > pos ( ) ;
_scriptStream - > seek ( 0 ) ;
2012-06-26 23:08:25 +02:00
_header . magic = _scriptStream - > readUint32LE ( ) ;
_header . version = _scriptStream - > readUint32LE ( ) ;
_header . code_start = _scriptStream - > readUint32LE ( ) ;
_header . func_table = _scriptStream - > readUint32LE ( ) ;
_header . symbol_table = _scriptStream - > readUint32LE ( ) ;
_header . event_table = _scriptStream - > readUint32LE ( ) ;
_header . externals_table = _scriptStream - > readUint32LE ( ) ;
_header . method_table = _scriptStream - > readUint32LE ( ) ;
2012-06-27 15:15:46 +02:00
_scriptStream - > seek ( oldPos ) ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : initScript ( ) {
2012-06-27 15:15:46 +02:00
if ( ! _scriptStream ) {
_scriptStream = new Common : : MemoryReadStream ( _buffer , _bufferSize ) ;
}
readHeader ( ) ;
2012-06-26 23:08:25 +02:00
if ( _header . magic ! = SCRIPT_MAGIC ) {
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " File '%s' is not a valid compiled script " , _filename ) ;
2012-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-07-09 03:27:21 +02:00
return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
}
2012-06-26 23:08:25 +02:00
if ( _header . version > SCRIPT_VERSION ) {
2012-07-18 18:25:09 +02:00
_gameRef - > 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-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-07-09 03:27:21 +02:00
return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 00:11:20 +02:00
initTables ( ) ;
2012-03-06 02:44:24 +01:00
// init stacks
2012-07-21 21:01:47 +02:00
_scopeStack = new ScStack ( _gameRef ) ;
_callStack = new ScStack ( _gameRef ) ;
_thisStack = new ScStack ( _gameRef ) ;
_stack = new ScStack ( _gameRef ) ;
2012-03-06 02:44:24 +01:00
2012-07-21 21:01:47 +02:00
_operand = new ScValue ( _gameRef ) ;
_reg1 = new ScValue ( _gameRef ) ;
2012-03-06 02:44:24 +01:00
// skip to the beginning
2012-06-26 23:08:25 +02:00
_iP = _header . code_start ;
_scriptStream - > seek ( _iP ) ;
2012-04-28 01:00:14 +03:00
_currentLine = 0 ;
2012-03-06 02:44:24 +01:00
// init breakpoints
2012-07-08 23:51:47 +02: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
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : initTables ( ) {
2012-04-28 01:00:14 +03:00
uint32 OrigIP = _iP ;
2012-03-06 02:44:24 +01:00
2012-06-27 15:15:46 +02:00
readHeader ( ) ;
2012-03-06 02:44:24 +01:00
// load symbol table
2012-06-26 23:08:25 +02:00
_iP = _header . symbol_table ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_numSymbols = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_symbols = new char * [ _numSymbols ] ;
2012-06-26 23:08:25 +02:00
for ( uint32 i = 0 ; i < _numSymbols ; i + + ) {
2012-07-09 00:11:20 +02:00
uint32 index = getDWORD ( ) ;
_symbols [ index ] = getString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load functions table
2012-06-26 23:08:25 +02:00
_iP = _header . func_table ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_numFunctions = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_functions = new TFunctionPos [ _numFunctions ] ;
2012-06-26 23:08:25 +02:00
for ( uint32 i = 0 ; i < _numFunctions ; i + + ) {
2012-07-09 00:11:20 +02:00
_functions [ i ] . pos = getDWORD ( ) ;
_functions [ i ] . name = getString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load events table
2012-06-26 23:08:25 +02:00
_iP = _header . event_table ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_numEvents = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_events = new TEventPos [ _numEvents ] ;
2012-06-26 23:08:25 +02:00
for ( uint32 i = 0 ; i < _numEvents ; i + + ) {
2012-07-09 00:11:20 +02:00
_events [ i ] . pos = getDWORD ( ) ;
_events [ i ] . name = getString ( ) ;
2012-03-06 02:44:24 +01:00
}
// load externals
2012-06-26 23:08:25 +02:00
if ( _header . version > = 0x0101 ) {
_iP = _header . externals_table ;
2012-04-28 01:00:14 +03:00
2012-07-09 00:11:20 +02:00
_numExternals = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_externals = new TExternalFunction [ _numExternals ] ;
2012-06-26 23:08:25 +02:00
for ( uint32 i = 0 ; i < _numExternals ; i + + ) {
2012-07-09 00:11:20 +02:00
_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 ( ) ;
2012-04-28 01:00:14 +03:00
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 + + ) {
2012-07-09 00:11:20 +02:00
_externals [ i ] . params [ j ] = ( TExternalType ) getDWORD ( ) ;
2012-03-06 02:44:24 +01:00
}
}
}
}
// load method table
2012-06-26 23:08:25 +02:00
_iP = _header . method_table ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_numMethods = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
_methods = new TMethodPos [ _numMethods ] ;
2012-06-26 23:08:25 +02:00
for ( uint32 i = 0 ; i < _numMethods ; i + + ) {
2012-07-09 00:11:20 +02:00
_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
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : create ( const char * filename , byte * buffer , uint32 size , BaseScriptHolder * owner ) {
2012-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-03-06 02:44:24 +01:00
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-07-04 13:15:47 +02:00
_filename = new char [ strlen ( filename ) + 1 ] ;
if ( _filename ) strcpy ( _filename , filename ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_buffer = new byte [ size ] ;
2012-07-09 03:27:21 +02:00
if ( ! _buffer ) return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
memcpy ( _buffer , buffer , size ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_bufferSize = size ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:31:56 +02:00
bool res = initScript ( ) ;
2012-07-09 03:27:21 +02:00
if ( DID_FAIL ( res ) ) return res ;
2012-03-06 02:44:24 +01:00
// establish global variables table
2012-07-21 21:01:47 +02:00
_globals = new ScValue ( _gameRef ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_owner = owner ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : createThread ( ScScript * original , uint32 initIP , const char * eventName ) {
2012-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_thread = true ;
_methodThread = false ;
2012-07-09 00:11:20 +02:00
_threadEvent = new char [ strlen ( eventName ) + 1 ] ;
if ( _threadEvent ) strcpy ( _threadEvent , eventName ) ;
2012-03-06 02:44:24 +01:00
// copy filename
2012-07-09 00:11:20 +02: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-07-09 00:11:20 +02:00
_buffer = new byte [ original - > _bufferSize ] ;
2012-07-09 03:27:21 +02:00
if ( ! _buffer ) return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
memcpy ( _buffer , original - > _buffer , original - > _bufferSize ) ;
_bufferSize = original - > _bufferSize ;
2012-03-06 02:44:24 +01:00
// initialize
2012-07-18 18:31:56 +02:00
bool res = initScript ( ) ;
2012-07-09 03:27:21 +02:00
if ( DID_FAIL ( res ) ) return res ;
2012-03-06 02:44:24 +01:00
// copy globals
2012-07-09 00:11:20 +02:00
_globals = original - > _globals ;
2012-03-06 02:44:24 +01:00
// skip to the beginning of the event
2012-07-09 00:11:20 +02:00
_iP = initIP ;
2012-06-26 23:08:25 +02:00
_scriptStream - > seek ( _iP ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_timeSlice = original - > _timeSlice ;
_freezable = original - > _freezable ;
_owner = original - > _owner ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_engine = original - > _engine ;
_parentScript = original ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : createMethodThread ( ScScript * original , const char * methodName ) {
2012-07-09 00:11:20 +02:00
uint32 ip = original - > getMethodPos ( methodName ) ;
2012-07-09 03:27:21 +02:00
if ( ip = = 0 ) return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
2012-06-26 00:41:05 +02:00
cleanup ( ) ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_thread = true ;
_methodThread = true ;
2012-07-09 00:11:20 +02:00
_threadEvent = new char [ strlen ( methodName ) + 1 ] ;
if ( _threadEvent ) strcpy ( _threadEvent , methodName ) ;
2012-03-06 02:44:24 +01:00
// copy filename
2012-07-09 00:11:20 +02: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-07-09 00:11:20 +02:00
_buffer = new byte [ original - > _bufferSize ] ;
2012-07-09 03:27:21 +02:00
if ( ! _buffer ) return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
memcpy ( _buffer , original - > _buffer , original - > _bufferSize ) ;
_bufferSize = original - > _bufferSize ;
2012-03-06 02:44:24 +01:00
// initialize
2012-07-18 18:31:56 +02:00
bool res = initScript ( ) ;
2012-07-09 03:27:21 +02:00
if ( DID_FAIL ( res ) ) return res ;
2012-03-06 02:44:24 +01:00
// copy globals
2012-07-09 00:11:20 +02:00
_globals = original - > _globals ;
2012-03-06 02:44:24 +01:00
// skip to the beginning of the event
2012-07-09 00:11:20 +02:00
_iP = ip ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_timeSlice = original - > _timeSlice ;
_freezable = original - > _freezable ;
_owner = original - > _owner ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
_engine = original - > _engine ;
_parentScript = original ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
void ScScript : : cleanup ( ) {
2012-07-25 21:05:03 +02:00
if ( _buffer ) delete [ ] _buffer ;
2012-04-28 01:00:14 +03:00
_buffer = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-25 21:05:03 +02:00
if ( _filename ) delete [ ] _filename ;
2012-04-28 01:00:14 +03:00
_filename = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-25 21:05:03 +02:00
if ( _symbols ) delete [ ] _symbols ;
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
if ( _globals & & ! _thread ) delete _globals ;
_globals = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
delete _scopeStack ;
2012-04-28 01:00:14 +03:00
_scopeStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
delete _callStack ;
2012-04-28 01:00:14 +03:00
_callStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
delete _thisStack ;
2012-04-28 01:00:14 +03:00
_thisStack = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
delete _stack ;
2012-04-28 01:00:14 +03:00
_stack = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-25 21:05:03 +02:00
if ( _functions ) delete [ ] _functions ;
2012-04-28 01:00:14 +03:00
_functions = NULL ;
_numFunctions = 0 ;
2012-03-06 02:44:24 +01:00
2012-07-25 21:05:03 +02:00
if ( _methods ) delete [ ] _methods ;
2012-04-28 01:00:14 +03:00
_methods = NULL ;
_numMethods = 0 ;
2012-03-06 02:44:24 +01:00
2012-07-25 21:05:03 +02:00
if ( _events ) delete [ ] _events ;
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
if ( _externals ) {
2012-07-09 02:50:15 +02:00
for ( uint32 i = 0 ; i < _numExternals ; i + + ) {
2012-07-25 21:05:03 +02:00
if ( _externals [ i ] . nu_params > 0 ) delete [ ] _externals [ i ] . params ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:05:03 +02: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-06-27 23:32:57 +02:00
delete _scriptStream ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
uint32 ScScript : : getDWORD ( ) {
2012-07-09 02:50:15 +02:00
_scriptStream - > seek ( ( int32 ) _iP ) ;
2012-06-26 23:08:25 +02:00
uint32 ret = _scriptStream - > readUint32LE ( ) ;
2012-04-28 01:00:14 +03:00
_iP + = sizeof ( uint32 ) ;
2012-06-26 23:08:25 +02:00
// assert(oldRet == ret);
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
double ScScript : : getFloat ( ) {
2012-06-26 23:08:25 +02:00
_scriptStream - > seek ( ( int32 ) _iP ) ;
byte buffer [ 8 ] ;
_scriptStream - > read ( buffer , 8 ) ;
# ifdef SCUMM_BIG_ENDIAN
// TODO: For lack of a READ_LE_UINT64
SWAP ( buffer [ 0 ] , buffer [ 7 ] ) ;
SWAP ( buffer [ 1 ] , buffer [ 6 ] ) ;
SWAP ( buffer [ 2 ] , buffer [ 5 ] ) ;
SWAP ( buffer [ 3 ] , buffer [ 4 ] ) ;
# endif
double ret = * ( double * ) ( buffer ) ;
_iP + = 8 ; // Hardcode the double-size used originally.
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
char * ScScript : : getString ( ) {
2012-04-28 01:00:14 +03:00
char * ret = ( char * ) ( _buffer + _iP ) ;
while ( * ( char * ) ( _buffer + _iP ) ! = ' \0 ' ) _iP + + ;
_iP + + ; // string terminator
2012-06-26 23:08:25 +02:00
_scriptStream - > seek ( _iP ) ;
2012-03-06 02:44:24 +01:00
return ret ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : executeInstruction ( ) {
2012-07-18 18:31:56 +02:00
bool ret = STATUS_OK ;
2012-03-06 02:44:24 +01:00
uint32 dw ;
2012-06-01 13:51:06 +02:00
const char * str = NULL ;
2012-03-06 02:44:24 +01:00
2012-07-21 21:01:47 +02:00
//ScValue* op = new ScValue(_gameRef);
2012-06-26 00:41:05 +02:00
_operand - > cleanup ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-21 21:01:47 +02:00
ScValue * op1 ;
ScValue * op2 ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
uint32 inst = getDWORD ( ) ;
2012-03-06 02:44:24 +01:00
switch ( inst ) {
case II_DEF_VAR :
2012-07-03 05:37:08 +02:00
_operand - > setNULL ( ) ;
2012-07-09 00:11:20 +02:00
dw = getDWORD ( ) ;
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP < 0 ) {
2012-07-03 05:37:08 +02:00
_globals - > setProp ( _symbols [ dw ] , _operand ) ;
2012-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled )
_gameRef - > getDebugMgr ( ) - > onVariableInit ( WME_DBGVAR_SCRIPT , this , NULL , _globals - > getProp ( _symbols [ dw ] ) , _symbols [ dw ] ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-03 05:37:08 +02:00
_scopeStack - > getTop ( ) - > setProp ( _symbols [ dw ] , _operand ) ;
2012-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled )
_gameRef - > 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 : {
2012-07-09 00:11:20 +02:00
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-07-03 05:37:08 +02: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-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled )
_gameRef - > 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 ) {
2012-07-18 18:25:09 +02:00
_gameRef - > getDebugMgr ( ) - > onScriptShutdownScope ( this , _scopeStack - > getTop ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
_scopeStack - > pop ( ) ;
2012-07-03 05:37:08 +02:00
_iP = ( uint32 ) _callStack - > pop ( ) - > getInt ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
if ( _scopeStack - > _sP < 0 ) _gameRef - > getDebugMgr ( ) - > onScriptChangeScope ( this , NULL ) ;
else _gameRef - > 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 :
2012-07-09 00:11:20 +02:00
dw = getDWORD ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:37:08 +02:00
_operand - > setInt ( _iP ) ;
2012-07-03 05:08:59 +02:00
_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-07-03 05:37:08 +02:00
str = _stack - > pop ( ) - > getString ( ) ;
2012-03-06 02:44:24 +01:00
char * MethodName = new char [ strlen ( str ) + 1 ] ;
strcpy ( MethodName , str ) ;
2012-07-21 21:01:47 +02:00
ScValue * var = _stack - > pop ( ) ;
2012-04-28 01:00:14 +03:00
if ( var - > _type = = VAL_VARIABLE_REF ) var = var - > _valRef ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:31:56 +02:00
bool res = STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
bool TriedNative = false ;
// we are already calling this method, try native
2012-07-03 05:37:08 +02: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-06-25 16:44:44 +02:00
res = var - > _valNative - > scCallMethod ( this , _stack , _thisStack , MethodName ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 03:27:21 +02:00
if ( DID_FAIL ( res ) ) {
2012-07-03 05:37:08 +02:00
if ( var - > isNative ( ) & & var - > getNative ( ) - > canHandleMethod ( MethodName ) ) {
2012-04-28 01:00:14 +03:00
if ( ! _unbreakable ) {
2012-07-03 05:37:08 +02:00
_waitScript = var - > getNative ( ) - > invokeMethodThread ( MethodName ) ;
2012-04-28 01:00:14 +03:00
if ( ! _waitScript ) {
2012-07-03 05:08:59 +02:00
_stack - > correctParams ( 0 ) ;
2012-07-09 00:11:20 +02:00
runtimeError ( " Error invoking method '%s'. " , MethodName ) ;
2012-07-03 05:08:59 +02:00
_stack - > pushNULL ( ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-04-28 01:00:14 +03:00
_state = SCRIPT_WAITING_SCRIPT ;
2012-07-09 00:11:20 +02:00
_waitScript - > copyParameters ( _stack ) ;
2012-03-06 02:44:24 +01:00
}
} else {
// can call methods in unbreakable mode
2012-07-03 05:08:59 +02:00
_stack - > correctParams ( 0 ) ;
2012-07-09 00:11:20 +02:00
runtimeError ( " Cannot call method '%s'. Ignored. " , MethodName ) ;
2012-07-03 05:08:59 +02:00
_stack - > pushNULL ( ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:05:03 +02:00
delete [ ] MethodName ;
2012-03-06 02:44:24 +01:00
break ;
}
/*
2012-07-21 21:01:47 +02:00
ScValue * val = var - > getProp ( MethodName ) ;
2012-07-25 21:21:55 +02:00
if ( val ) {
2012-07-03 05:37:08 +02:00
dw = GetFuncPos ( val - > getString ( ) ) ;
2012-07-25 21:21:55 +02:00
if ( dw = = 0 ) {
2012-07-03 05:37:08 +02:00
TExternalFunction * f = GetExternal ( val - > getString ( ) ) ;
2012-07-25 21:21:55 +02:00
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-07-18 18:25:09 +02:00
_gameRef - > ExternalCall ( this , _stack , _thisStack , val - > getString ( ) ) ;
2012-03-06 02:44:24 +01:00
}
}
else {
2012-07-03 05:37:08 +02:00
_operand - > setInt ( _iP ) ;
2012-04-28 01:00:14 +03:00
_callStack - > Push ( _operand ) ;
_iP = dw ;
2012-03-06 02:44:24 +01:00
}
}
*/
else {
2012-07-09 03:27:21 +02:00
res = STATUS_FAILED ;
2012-06-25 16:44:44 +02:00
if ( var - > _type = = VAL_NATIVE & & ! TriedNative ) res = var - > _valNative - > scCallMethod ( this , _stack , _thisStack , MethodName ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
if ( DID_FAIL ( res ) ) {
2012-07-03 05:08:59 +02:00
_stack - > correctParams ( 0 ) ;
2012-07-09 00:11:20 +02:00
runtimeError ( " Call to undefined method '%s'. Ignored. " , MethodName ) ;
2012-07-03 05:08:59 +02:00
_stack - > pushNULL ( ) ;
2012-03-06 02:44:24 +01:00
}
}
}
2012-07-25 21:05:03 +02:00
delete [ ] MethodName ;
2012-03-06 02:44:24 +01:00
}
break ;
case II_EXTERNAL_CALL : {
2012-07-09 00:11:20 +02:00
uint32 SymbolIndex = getDWORD ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
TExternalFunction * f = getExternal ( _symbols [ SymbolIndex ] ) ;
2012-03-06 02:44:24 +01:00
if ( f ) {
2012-07-09 00:11:20 +02:00
externalCall ( _stack , _thisStack , f ) ;
2012-07-18 18:25:09 +02:00
} else _gameRef - > ExternalCall ( this , _stack , _thisStack , _symbols [ SymbolIndex ] ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_SCOPE :
2012-07-03 05:37:08 +02:00
_operand - > setNULL ( ) ;
2012-07-03 05:08:59 +02:00
_scopeStack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
if ( _scopeStack - > _sP < 0 ) _gameRef - > getDebugMgr ( ) - > onScriptChangeScope ( this , NULL ) ;
else _gameRef - > getDebugMgr ( ) - > onScriptChangeScope ( this , _scopeStack - > getTop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CORRECT_STACK :
2012-07-09 00:11:20 +02:00
dw = getDWORD ( ) ; // params expected
2012-07-03 05:08:59 +02:00
_stack - > correctParams ( dw ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CREATE_OBJECT :
2012-07-03 05:37:08 +02:00
_operand - > setObject ( ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_EMPTY :
2012-07-03 05:08:59 +02:00
_stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_VAR : {
2012-07-21 21:01:47 +02:00
ScValue * var = getVar ( _symbols [ getDWORD ( ) ] ) ;
2012-04-28 01:00:14 +03:00
if ( false & & /*var->_type==VAL_OBJECT ||*/ var - > _type = = VAL_NATIVE ) {
2012-07-03 05:37:08 +02:00
_operand - > setReference ( var ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
} else _stack - > push ( var ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_PUSH_VAR_REF : {
2012-07-21 21:01:47 +02:00
ScValue * var = getVar ( _symbols [ getDWORD ( ) ] ) ;
2012-07-03 05:37:08 +02:00
_operand - > setReference ( var ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_POP_VAR : {
2012-07-09 00:11:20 +02:00
char * VarName = _symbols [ getDWORD ( ) ] ;
2012-07-21 21:01:47 +02:00
ScValue * var = getVar ( VarName ) ;
2012-03-06 02:44:24 +01:00
if ( var ) {
2012-07-21 21:01:47 +02:00
ScValue * val = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( ! val ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script stack corruption detected. Please report this script at WME bug reports forum. " ) ;
2012-07-03 05:37:08 +02:00
var - > setNULL ( ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-03 05:37:08 +02: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 {
2012-07-03 05:37:08 +02:00
var - > copy ( val ) ;
2012-03-06 02:44:24 +01:00
}
}
2012-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled )
_gameRef - > getDebugMgr ( ) - > onVariableChangeValue ( var , val ) ;
2012-03-06 02:44:24 +01:00
}
break ;
}
case II_PUSH_VAR_THIS :
2012-07-03 05:08:59 +02:00
_stack - > push ( _thisStack - > getTop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_INT :
2012-07-09 00:11:20 +02:00
_stack - > pushInt ( ( int ) getDWORD ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_FLOAT :
2012-07-09 00:11:20 +02:00
_stack - > pushFloat ( getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_BOOL :
2012-07-09 00:11:20 +02:00
_stack - > pushBool ( getDWORD ( ) ! = 0 ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_STRING :
2012-07-09 00:11:20 +02:00
_stack - > pushString ( getString ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_NULL :
2012-07-03 05:08:59 +02:00
_stack - > pushNULL ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_THIS_FROM_STACK :
2012-07-03 05:37:08 +02:00
_operand - > setReference ( _stack - > getTop ( ) ) ;
2012-07-03 05:08:59 +02:00
_thisStack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_THIS :
2012-07-09 00:11:20 +02:00
_operand - > setReference ( getVar ( _symbols [ getDWORD ( ) ] ) ) ;
2012-07-03 05:08:59 +02:00
_thisStack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_THIS :
2012-07-03 05:08:59 +02:00
_thisStack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_PUSH_BY_EXP : {
2012-07-03 05:37:08 +02:00
str = _stack - > pop ( ) - > getString ( ) ;
2012-07-21 21:01:47 +02:00
ScValue * val = _stack - > pop ( ) - > getProp ( str ) ;
2012-07-03 05:08:59 +02:00
if ( val ) _stack - > push ( val ) ;
else _stack - > pushNULL ( ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_POP_BY_EXP : {
2012-07-03 05:37:08 +02:00
str = _stack - > pop ( ) - > getString ( ) ;
2012-07-21 21:01:47 +02:00
ScValue * var = _stack - > pop ( ) ;
ScValue * val = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( val = = NULL ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script stack corruption detected. Please report this script at WME bug reports forum. " ) ;
2012-07-03 05:37:08 +02:00
var - > setNULL ( ) ;
} else var - > setProp ( str , val ) ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled )
_gameRef - > getDebugMgr ( ) - > onVariableChangeValue ( var , NULL ) ;
2012-03-06 02:44:24 +01:00
break ;
}
case II_PUSH_REG1 :
2012-07-03 05:08:59 +02:00
_stack - > push ( _reg1 ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_POP_REG1 :
2012-07-03 05:37:08 +02:00
_reg1 - > copy ( _stack - > pop ( ) ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_JMP :
2012-07-09 00:11:20 +02:00
_iP = getDWORD ( ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_JMP_FALSE : {
2012-07-09 00:11:20 +02:00
dw = getDWORD ( ) ;
2012-07-25 21:21:55 +02:00
//if (!_stack->pop()->getBool()) _iP = dw;
2012-07-21 21:01:47 +02:00
ScValue * val = _stack - > pop ( ) ;
2012-07-09 00:11:20 +02:00
if ( ! val ) {
runtimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-09 00:11:20 +02:00
if ( ! val - > getBool ( ) ) _iP = dw ;
2012-03-06 02:44:24 +01:00
}
break ;
}
case II_ADD :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
if ( op1 - > isNULL ( ) | | op2 - > isNULL ( ) )
_operand - > setNULL ( ) ;
2012-07-03 05:37:08 +02:00
else if ( op1 - > getType ( ) = = VAL_STRING | | op2 - > getType ( ) = = VAL_STRING ) {
char * tempStr = new char [ strlen ( op1 - > getString ( ) ) + strlen ( op2 - > getString ( ) ) + 1 ] ;
strcpy ( tempStr , op1 - > getString ( ) ) ;
strcat ( tempStr , op2 - > getString ( ) ) ;
_operand - > setString ( tempStr ) ;
2012-07-25 21:05:03 +02:00
delete [ ] tempStr ;
2012-07-03 05:37:08 +02:00
} else if ( op1 - > getType ( ) = = VAL_INT & & op2 - > getType ( ) = = VAL_INT )
_operand - > setInt ( op1 - > getInt ( ) + op2 - > getInt ( ) ) ;
else _operand - > setFloat ( op1 - > getFloat ( ) + op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_SUB :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
if ( op1 - > isNULL ( ) | | op2 - > isNULL ( ) )
_operand - > setNULL ( ) ;
2012-07-03 05:37:08 +02:00
else if ( op1 - > getType ( ) = = VAL_INT & & op2 - > getType ( ) = = VAL_INT )
_operand - > setInt ( op1 - > getInt ( ) - op2 - > getInt ( ) ) ;
else _operand - > setFloat ( op1 - > getFloat ( ) - op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_MUL :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:37:08 +02:00
if ( op1 - > isNULL ( ) | | op2 - > isNULL ( ) ) _operand - > setNULL ( ) ;
else if ( op1 - > getType ( ) = = VAL_INT & & op2 - > getType ( ) = = VAL_INT )
_operand - > setInt ( op1 - > getInt ( ) * op2 - > getInt ( ) ) ;
else _operand - > setFloat ( op1 - > getFloat ( ) * op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_DIV :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
if ( op2 - > getFloat ( ) = = 0.0f )
runtimeError ( " Division by zero. " ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:37:08 +02: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-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_MODULO :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
if ( op2 - > getInt ( ) = = 0 )
runtimeError ( " Division by zero. " ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
if ( op1 - > isNULL ( ) | | op2 - > isNULL ( ) | | op2 - > getInt ( ) = = 0 )
_operand - > setNULL ( ) ;
2012-07-03 05:37:08 +02:00
else _operand - > setInt ( op1 - > getInt ( ) % op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_NOT :
2012-07-03 05:08:59 +02:00
op1 = _stack - > pop ( ) ;
2012-07-25 21:21:55 +02:00
//if (op1->isNULL()) _operand->setNULL();
2012-07-03 05:37:08 +02:00
if ( op1 - > isNULL ( ) ) _operand - > setBool ( true ) ;
else _operand - > setBool ( ! op1 - > getBool ( ) ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_AND :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op1 = = NULL | | op2 = = NULL ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
2012-07-03 05:37:08 +02:00
_operand - > setBool ( false ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getBool ( ) & & op2 - > getBool ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_OR :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
if ( op1 = = NULL | | op2 = = NULL ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script corruption detected. Did you use '=' instead of '==' for comparison? " ) ;
2012-07-03 05:37:08 +02:00
_operand - > setBool ( false ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getBool ( ) | | op2 - > getBool ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_EQ :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( ( op1 - > isNULL ( ) & & ! op2 - > isNULL ( ) ) | | ( ! op1 - > isNULL ( ) & & op2 - > isNULL ( ) ) ) _operand - > setBool ( false ) ;
else if ( op1 - > isNative ( ) & & op2 - > isNative ( ) ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getNative ( ) = = op2 - > getNative ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:21:55 +02:00
else if ( op1 - > getType ( ) = = VAL_STRING | | op2 - > getType ( ) = = VAL_STRING ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( scumm_stricmp ( op1 - > getString ( ) , op2 - > getString ( ) ) = = 0 ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:21:55 +02:00
else if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) = = op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getInt ( ) = = op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
}
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) = = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_NE :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( ( op1 - > isNULL ( ) & & ! op2 - > isNULL ( ) ) | | ( ! op1 - > isNULL ( ) & & op2 - > isNULL ( ) ) ) _operand - > setBool ( true ) ;
else if ( op1 - > isNative ( ) & & op2 - > isNative ( ) ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getNative ( ) ! = op2 - > getNative ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:21:55 +02:00
else if ( op1 - > getType ( ) = = VAL_STRING | | op2 - > getType ( ) = = VAL_STRING ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( scumm_stricmp ( op1 - > getString ( ) , op2 - > getString ( ) ) ! = 0 ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-25 21:21:55 +02:00
else if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) ! = op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
else {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getInt ( ) ! = op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
}
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) ! = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_L :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) < op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:37:08 +02:00
else _operand - > setBool ( op1 - > getInt ( ) < op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) < 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_G :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) > op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:37:08 +02:00
else _operand - > setBool ( op1 - > getInt ( ) > op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) > 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_LE :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) < = op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:37:08 +02:00
else _operand - > setBool ( op1 - > getInt ( ) < = op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) < = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_GE :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
/*
2012-07-25 21:21:55 +02:00
if ( op1 - > getType ( ) = = VAL_FLOAT & & op2 - > getType ( ) = = VAL_FLOAT ) {
2012-07-03 05:37:08 +02:00
_operand - > setBool ( op1 - > getFloat ( ) > = op2 - > getFloat ( ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:37:08 +02:00
else _operand - > setBool ( op1 - > getInt ( ) > = op2 - > getInt ( ) ) ;
2012-03-06 02:44:24 +01:00
*/
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compare ( op1 , op2 ) > = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_STRICT_EQ :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:37:08 +02:00
//_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat());
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compareStrict ( op1 , op2 ) = = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_CMP_STRICT_NE :
2012-07-03 05:08:59 +02:00
op2 = _stack - > pop ( ) ;
op1 = _stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:37:08 +02:00
//_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat());
2012-07-21 21:01:47 +02:00
_operand - > setBool ( ScValue : : compareStrict ( op1 , op2 ) ! = 0 ) ;
2012-07-03 05:08:59 +02:00
_stack - > push ( _operand ) ;
2012-03-06 02:44:24 +01:00
break ;
case II_DBG_LINE : {
2012-07-09 00:11:20 +02:00
int newLine = getDWORD ( ) ;
if ( newLine ! = _currentLine ) {
_currentLine = newLine ;
2012-07-18 18:25:09 +02:00
if ( _gameRef - > getDebugMgr ( ) - > _enabled ) {
_gameRef - > getDebugMgr ( ) - > onScriptChangeLine ( this , _currentLine ) ;
2012-07-09 04:50:38 +02:00
for ( int i = 0 ; i < _breakpoints . getSize ( ) ; i + + ) {
2012-04-28 01:00:14 +03:00
if ( _breakpoints [ i ] = = _currentLine ) {
2012-07-18 18:25:09 +02:00
_gameRef - > getDebugMgr ( ) - > onScriptHitBreakpoint ( this ) ;
2012-07-09 00:11:20 +02:00
sleep ( 0 ) ;
2012-03-06 02:44:24 +01:00
break ;
}
}
2012-04-28 01:00:14 +03:00
if ( _tracingMode ) {
2012-07-18 18:25:09 +02:00
_gameRef - > getDebugMgr ( ) - > onScriptHitBreakpoint ( this ) ;
2012-07-09 00:11:20 +02:00
sleep ( 0 ) ;
2012-03-06 02:44:24 +01:00
break ;
}
}
}
break ;
}
default :
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x) \n " , inst , _filename , _currentLine , _iP - sizeof ( uint32 ) ) ;
2012-04-28 01:00:14 +03:00
_state = SCRIPT_FINISHED ;
2012-07-09 03:27:21 +02:00
ret = STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
} // switch(instruction)
//delete op;
return ret ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
uint32 ScScript : : getFuncPos ( const char * name ) {
2012-07-09 02:50:15 +02:00
for ( uint32 i = 0 ; i < _numFunctions ; i + + ) {
2012-07-09 00:11:20 +02:00
if ( strcmp ( name , _functions [ i ] . name ) = = 0 )
return _functions [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
uint32 ScScript : : getMethodPos ( const char * name ) {
2012-07-09 02:50:15 +02:00
for ( uint32 i = 0 ; i < _numMethods ; i + + ) {
2012-07-09 00:11:20 +02:00
if ( strcmp ( name , _methods [ i ] . name ) = = 0 )
return _methods [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
ScValue * ScScript : : getVar ( char * name ) {
ScValue * ret = NULL ;
2012-03-06 02:44:24 +01:00
// scope locals
2012-04-28 01:00:14 +03:00
if ( _scopeStack - > _sP > = 0 ) {
2012-07-09 00:11:20 +02:00
if ( _scopeStack - > getTop ( ) - > propExists ( name ) )
ret = _scopeStack - > getTop ( ) - > getProp ( name ) ;
2012-03-06 02:44:24 +01:00
}
// script globals
if ( ret = = NULL ) {
2012-07-09 00:11:20 +02:00
if ( _globals - > propExists ( name ) )
ret = _globals - > getProp ( name ) ;
2012-03-06 02:44:24 +01:00
}
// engine globals
if ( ret = = NULL ) {
2012-07-09 00:11:20 +02:00
if ( _engine - > _globals - > propExists ( name ) )
ret = _engine - > _globals - > getProp ( name ) ;
2012-03-06 02:44:24 +01:00
}
if ( ret = = NULL ) {
2012-07-03 04:31:32 +02:00
//RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", name);
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d) " , name , _filename , _currentLine ) ;
2012-07-21 21:01:47 +02:00
ScValue * val = new ScValue ( _gameRef ) ;
ScValue * scope = _scopeStack - > getTop ( ) ;
2012-07-09 00:11:20 +02:00
if ( scope ) {
scope - > setProp ( name , val ) ;
2012-07-03 05:37:08 +02:00
ret = _scopeStack - > getTop ( ) - > getProp ( name ) ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-09 00:11:20 +02:00
_globals - > setProp ( name , val ) ;
2012-07-03 05:37:08 +02:00
ret = _globals - > getProp ( name ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 00:11:20 +02:00
delete val ;
2012-03-06 02:44:24 +01:00
}
return ret ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : waitFor ( BaseObject * object ) {
2012-04-28 01:00:14 +03:00
if ( _unbreakable ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script cannot be interrupted. " ) ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_state = SCRIPT_WAITING ;
2012-07-09 00:11:20 +02:00
_waitObject = object ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : waitForExclusive ( BaseObject * object ) {
2012-07-09 00:11:20 +02:00
_engine - > resetObject ( object ) ;
return waitFor ( object ) ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : sleep ( uint32 duration ) {
2012-04-28 01:00:14 +03:00
if ( _unbreakable ) {
2012-07-09 00:11:20 +02:00
runtimeError ( " Script cannot be interrupted. " ) ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
2012-04-28 01:00:14 +03:00
_state = SCRIPT_SLEEPING ;
2012-07-18 18:25:09 +02:00
if ( _gameRef - > _state = = GAME_FROZEN ) {
2012-07-23 03:01:05 +02:00
_waitTime = g_system - > getMillis ( ) + duration ;
2012-04-28 01:00:14 +03:00
_waitFrozen = true ;
2012-03-06 02:44:24 +01:00
} else {
2012-07-18 18:25:09 +02:00
_waitTime = _gameRef - > _timer + duration ;
2012-04-28 01:00:14 +03:00
_waitFrozen = false ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : finish ( bool includingThreads ) {
2012-07-09 00:11:20 +02:00
if ( _state ! = SCRIPT_FINISHED & & includingThreads ) {
2012-04-28 01:00:14 +03:00
_state = SCRIPT_FINISHED ;
2012-07-09 00:11:20 +02:00
finishThreads ( ) ;
2012-04-28 01:00:14 +03:00
} else _state = SCRIPT_FINISHED ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : run ( ) {
2012-04-28 01:00:14 +03:00
_state = SCRIPT_RUNNING ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
void ScScript : : runtimeError ( const char * fmt , . . . ) {
2012-03-06 02:44:24 +01:00
char buff [ 256 ] ;
va_list va ;
va_start ( va , fmt ) ;
vsprintf ( buff , fmt , va ) ;
va_end ( va ) ;
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " Runtime error. Script '%s', line %d " , _filename , _currentLine ) ;
_gameRef - > LOG ( 0 , " %s " , buff ) ;
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
if ( ! _gameRef - > _suppressScriptErrors )
_gameRef - > quickMessage ( " Script runtime error. View log for details. " ) ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : persist ( BasePersistenceManager * persistMgr ) {
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
persistMgr - > transfer ( TMEMBER ( _gameRef ) ) ;
2012-03-06 02:44:24 +01:00
// buffer
2012-07-23 03:42:27 +02:00
if ( persistMgr - > getIsSaving ( ) ) {
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-06-26 23:08:25 +02:00
_scriptStream = new Common : : MemoryReadStream ( _buffer , _bufferSize ) ;
2012-07-09 00:11:20 +02:00
initTables ( ) ;
2012-06-27 15:15:46 +02:00
} else {
_buffer = NULL ;
_scriptStream = 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 ) ) ;
2012-07-23 03:42:27 +02:00
if ( ! persistMgr - > getIsSaving ( ) ) _tracingMode = false ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
ScScript * ScScript : : invokeEventHandler ( const char * eventName , bool unbreakable ) {
2012-07-25 21:21:55 +02:00
//if (_state!=SCRIPT_PERSISTENT) return NULL;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
uint32 pos = getEventPos ( eventName ) ;
2012-03-06 02:44:24 +01:00
if ( ! pos ) return NULL ;
2012-07-21 21:01:47 +02:00
ScScript * thread = new ScScript ( _gameRef , _engine ) ;
2012-03-06 02:44:24 +01:00
if ( thread ) {
2012-07-18 18:31:56 +02:00
bool ret = thread - > createThread ( this , pos , eventName ) ;
2012-07-09 03:27:21 +02:00
if ( DID_SUCCEED ( ret ) ) {
2012-07-09 00:11:20 +02:00
thread - > _unbreakable = unbreakable ;
2012-07-09 04:50:38 +02:00
_engine - > _scripts . add ( thread ) ;
2012-07-18 18:25:09 +02:00
_gameRef - > getDebugMgr ( ) - > onScriptEventThreadInit ( thread , this , eventName ) ;
2012-03-06 02:44:24 +01:00
return thread ;
} else {
delete thread ;
return NULL ;
}
} else return NULL ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
uint32 ScScript : : getEventPos ( const char * name ) {
2012-04-28 01:00:14 +03:00
for ( int i = _numEvents - 1 ; i > = 0 ; i - - ) {
2012-07-03 04:31:32 +02:00
if ( scumm_stricmp ( name , _events [ i ] . name ) = = 0 ) return _events [ i ] . pos ;
2012-03-06 02:44:24 +01:00
}
return 0 ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : canHandleEvent ( const char * eventName ) {
2012-07-09 00:11:20 +02:00
return getEventPos ( eventName ) ! = 0 ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : canHandleMethod ( const char * methodName ) {
2012-07-09 00:11:20 +02:00
return getMethodPos ( methodName ) ! = 0 ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : pause ( ) {
2012-04-28 01:00:14 +03:00
if ( _state = = SCRIPT_PAUSED ) {
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " Attempting to pause a paused script ('%s', line %d) " , _filename , _currentLine ) ;
2012-07-09 03:27:21 +02:00
return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 03:27:21 +02:00
if ( ! _freezable | | _state = = SCRIPT_PERSISTENT ) return STATUS_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
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : resume ( ) {
2012-07-09 03:27:21 +02:00
if ( _state ! = SCRIPT_PAUSED ) return STATUS_OK ;
2012-03-06 02:44:24 +01:00
2012-04-28 01:00:14 +03:00
_state = _origState ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
ScScript : : TExternalFunction * ScScript : : getExternal ( char * name ) {
2012-07-09 02:50:15 +02:00
for ( uint32 i = 0 ; i < _numExternals ; i + + ) {
2012-07-09 00:11:20 +02:00
if ( strcmp ( name , _externals [ i ] . name ) = = 0 )
return & _externals [ i ] ;
2012-03-06 02:44:24 +01:00
}
return NULL ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : externalCall ( ScStack * stack , ScStack * thisStack , ScScript : : TExternalFunction * function ) {
2012-03-06 02:44:24 +01:00
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " External functions are not supported on this platform. " ) ;
2012-07-03 05:08:59 +02:00
stack - > correctParams ( 0 ) ;
stack - > pushNULL ( ) ;
2012-07-09 03:27:21 +02:00
return STATUS_FAILED ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : copyParameters ( ScStack * stack ) {
2012-03-06 02:44:24 +01:00
int i ;
2012-07-03 05:37:08 +02:00
int NumParams = stack - > pop ( ) - > getInt ( ) ;
2012-03-06 02:44:24 +01:00
for ( i = NumParams - 1 ; i > = 0 ; i - - ) {
2012-07-03 05:08:59 +02:00
_stack - > push ( stack - > getAt ( i ) ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-03 05:08:59 +02:00
_stack - > pushInt ( NumParams ) ;
2012-03-06 02:44:24 +01:00
2012-07-03 05:08:59 +02:00
for ( i = 0 ; i < NumParams ; i + + ) stack - > pop ( ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : finishThreads ( ) {
2012-07-09 04:50:38 +02:00
for ( int i = 0 ; i < _engine - > _scripts . getSize ( ) ; i + + ) {
2012-07-21 21:01:47 +02:00
ScScript * scr = _engine - > _scripts [ i ] ;
2012-07-09 00:11:20 +02:00
if ( scr - > _thread & & scr - > _state ! = SCRIPT_FINISHED & & scr - > _owner = = _owner & & scumm_stricmp ( scr - > _filename , _filename ) = = 0 )
scr - > finish ( true ) ;
2012-03-06 02:44:24 +01:00
}
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
// IWmeDebugScript interface implementation
2012-07-21 21:01:47 +02:00
int ScScript : : dbgGetLine ( ) {
2012-04-28 01:00:14 +03:00
return _currentLine ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
const char * ScScript : : dbgGetFilename ( ) {
2012-04-28 01:00:14 +03:00
return _filename ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : dbgSendScript ( IWmeDebugClient * client ) {
2012-07-09 00:11:20 +02:00
if ( _methodThread ) client - > onScriptMethodThreadInit ( this , _parentScript , _threadEvent ) ;
else if ( _thread ) client - > onScriptEventThreadInit ( this , _parentScript , _threadEvent ) ;
else client - > onScriptInit ( this ) ;
2012-03-06 02:44:24 +01:00
2012-07-09 00:11:20 +02:00
return dbgSendVariables ( client ) ;
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : dbgSendVariables ( IWmeDebugClient * client ) {
2012-03-06 02:44:24 +01:00
// send script globals
2012-07-09 00:23:31 +02: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-07-21 21:01:47 +02:00
// ScValue *Scope = _scopeStack->GetAt(i);
2012-03-06 02:44:24 +01:00
//Scope->DbgSendVariables(Client, WME_DBGVAR_SCOPE, this, (unsigned int)Scope);
}
}
2012-07-09 03:27:21 +02:00
return STATUS_OK ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
TScriptState ScScript : : dbgGetState ( ) {
2012-04-28 01:00:14 +03:00
return _state ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
int ScScript : : dbgGetNumBreakpoints ( ) {
2012-07-09 04:50:38 +02:00
return _breakpoints . getSize ( ) ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
int ScScript : : dbgGetBreakpoint ( int index ) {
2012-07-09 04:50:38 +02:00
if ( index > = 0 & & index < _breakpoints . getSize ( ) ) return _breakpoints [ index ] ;
2012-03-06 02:44:24 +01:00
else return - 1 ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : dbgSetTracingMode ( bool isTracing ) {
2012-07-09 00:11:20 +02:00
_tracingMode = isTracing ;
2012-03-06 02:44:24 +01:00
return true ;
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
bool ScScript : : dbgGetTracingMode ( ) {
2012-04-28 01:00:14 +03:00
return _tracingMode ;
2012-03-06 02:44:24 +01:00
}
//////////////////////////////////////////////////////////////////////////
2012-07-21 21:01:47 +02:00
void ScScript : : afterLoad ( ) {
2012-04-28 01:00:14 +03:00
if ( _buffer = = NULL ) {
2012-07-08 23:51:47 +02:00
byte * buffer = _engine - > getCompiledScript ( _filename , & _bufferSize ) ;
2012-03-06 02:44:24 +01:00
if ( ! buffer ) {
2012-07-18 18:25:09 +02:00
_gameRef - > LOG ( 0 , " Error reinitializing script '%s' after load. Script will be terminated. " , _filename ) ;
2012-04-28 01:00:14 +03:00
_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
2012-06-27 15:15:46 +02:00
delete _scriptStream ;
_scriptStream = new Common : : MemoryReadStream ( _buffer , _bufferSize ) ;
2012-07-09 00:11:20 +02:00
initTables ( ) ;
2012-03-06 02:44:24 +01:00
}
}
} // end of namespace WinterMute