diff options
author | Willem Jan Palenstijn | 2012-09-04 22:17:23 +0200 |
---|---|---|
committer | Willem Jan Palenstijn | 2012-09-04 22:17:23 +0200 |
commit | b4090ead4d4334e08725323ff72fd355c93b63d5 (patch) | |
tree | 4eb58e5698b1cfd1a89d2b038f929071264ffeb9 /engines/wintermute/base/scriptables | |
parent | df80820184c90a87511f0cabdca4addb9fa13a66 (diff) | |
download | scummvm-rg350-b4090ead4d4334e08725323ff72fd355c93b63d5.tar.gz scummvm-rg350-b4090ead4d4334e08725323ff72fd355c93b63d5.tar.bz2 scummvm-rg350-b4090ead4d4334e08725323ff72fd355c93b63d5.zip |
WINTERMUTE: Convert CRLF to LF
Diffstat (limited to 'engines/wintermute/base/scriptables')
23 files changed, 7027 insertions, 7027 deletions
diff --git a/engines/wintermute/base/scriptables/dcscript.h b/engines/wintermute/base/scriptables/dcscript.h index 6810fdf665..4aae897dc2 100644 --- a/engines/wintermute/base/scriptables/dcscript.h +++ b/engines/wintermute/base/scriptables/dcscript.h @@ -1,141 +1,141 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_DCSCRIPT_H
-#define WINTERMUTE_DCSCRIPT_H
-
-namespace Wintermute {
-
-#define SCRIPT_MAGIC 0xDEC0ADDE
-#define SCRIPT_VERSION 0x0102
-
-// value types
-typedef enum {
- VAL_NULL,
- VAL_STRING,
- VAL_INT,
- VAL_BOOL,
- VAL_FLOAT,
- VAL_OBJECT,
- VAL_NATIVE,
- VAL_VARIABLE_REF
-} TValType;
-
-
-// script states
-typedef enum {
- SCRIPT_RUNNING,
- SCRIPT_WAITING,
- SCRIPT_SLEEPING,
- SCRIPT_FINISHED,
- SCRIPT_PERSISTENT,
- SCRIPT_ERROR,
- SCRIPT_PAUSED,
- SCRIPT_WAITING_SCRIPT,
- SCRIPT_THREAD_FINISHED
-} TScriptState;
-
-// opcodes
-typedef enum {
- II_DEF_VAR = 0,
- II_DEF_GLOB_VAR,
- II_RET,
- II_RET_EVENT,
- II_CALL,
- II_CALL_BY_EXP,
- II_EXTERNAL_CALL,
- II_SCOPE,
- II_CORRECT_STACK,
- II_CREATE_OBJECT,
- II_POP_EMPTY,
- II_PUSH_VAR,
- II_PUSH_VAR_REF,
- II_POP_VAR,
- II_PUSH_VAR_THIS, // push current this on stack
- II_PUSH_INT,
- II_PUSH_BOOL,
- II_PUSH_FLOAT,
- II_PUSH_STRING,
- II_PUSH_NULL,
- II_PUSH_THIS_FROM_STACK,
- II_PUSH_THIS,
- II_POP_THIS,
- II_PUSH_BY_EXP,
- II_POP_BY_EXP,
- II_JMP,
- II_JMP_FALSE,
- II_ADD,
- II_SUB,
- II_MUL,
- II_DIV,
- II_MODULO,
- II_NOT,
- II_AND,
- II_OR,
- II_CMP_EQ,
- II_CMP_NE,
- II_CMP_L,
- II_CMP_G,
- II_CMP_LE,
- II_CMP_GE,
- II_CMP_STRICT_EQ,
- II_CMP_STRICT_NE,
- II_DBG_LINE,
- II_POP_REG1,
- II_PUSH_REG1,
- II_DEF_CONST_VAR
-} TInstruction;
-
-// external data types
-typedef enum {
- TYPE_VOID = 0,
- TYPE_BOOL,
- TYPE_LONG,
- TYPE_BYTE,
- TYPE_STRING,
- TYPE_FLOAT,
- TYPE_DOUBLE,
- TYPE_MEMBUFFER
-} TExternalType;
-
-
-// call types
-typedef enum {
- CALL_STDCALL = 0,
- CALL_CDECL,
- CALL_THISCALL
-} TCallType;
-
-// element types
-typedef enum {
- ELEMENT_STRING = 0
-} TElementType;
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_DCSCRIPT_H +#define WINTERMUTE_DCSCRIPT_H + +namespace Wintermute { + +#define SCRIPT_MAGIC 0xDEC0ADDE +#define SCRIPT_VERSION 0x0102 + +// value types +typedef enum { + VAL_NULL, + VAL_STRING, + VAL_INT, + VAL_BOOL, + VAL_FLOAT, + VAL_OBJECT, + VAL_NATIVE, + VAL_VARIABLE_REF +} TValType; + + +// script states +typedef enum { + SCRIPT_RUNNING, + SCRIPT_WAITING, + SCRIPT_SLEEPING, + SCRIPT_FINISHED, + SCRIPT_PERSISTENT, + SCRIPT_ERROR, + SCRIPT_PAUSED, + SCRIPT_WAITING_SCRIPT, + SCRIPT_THREAD_FINISHED +} TScriptState; + +// opcodes +typedef enum { + II_DEF_VAR = 0, + II_DEF_GLOB_VAR, + II_RET, + II_RET_EVENT, + II_CALL, + II_CALL_BY_EXP, + II_EXTERNAL_CALL, + II_SCOPE, + II_CORRECT_STACK, + II_CREATE_OBJECT, + II_POP_EMPTY, + II_PUSH_VAR, + II_PUSH_VAR_REF, + II_POP_VAR, + II_PUSH_VAR_THIS, // push current this on stack + II_PUSH_INT, + II_PUSH_BOOL, + II_PUSH_FLOAT, + II_PUSH_STRING, + II_PUSH_NULL, + II_PUSH_THIS_FROM_STACK, + II_PUSH_THIS, + II_POP_THIS, + II_PUSH_BY_EXP, + II_POP_BY_EXP, + II_JMP, + II_JMP_FALSE, + II_ADD, + II_SUB, + II_MUL, + II_DIV, + II_MODULO, + II_NOT, + II_AND, + II_OR, + II_CMP_EQ, + II_CMP_NE, + II_CMP_L, + II_CMP_G, + II_CMP_LE, + II_CMP_GE, + II_CMP_STRICT_EQ, + II_CMP_STRICT_NE, + II_DBG_LINE, + II_POP_REG1, + II_PUSH_REG1, + II_DEF_CONST_VAR +} TInstruction; + +// external data types +typedef enum { + TYPE_VOID = 0, + TYPE_BOOL, + TYPE_LONG, + TYPE_BYTE, + TYPE_STRING, + TYPE_FLOAT, + TYPE_DOUBLE, + TYPE_MEMBUFFER +} TExternalType; + + +// call types +typedef enum { + CALL_STDCALL = 0, + CALL_CDECL, + CALL_THISCALL +} TCallType; + +// element types +typedef enum { + ELEMENT_STRING = 0 +} TElementType; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp index 269ea1ea03..9469bd46a7 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -1,1467 +1,1467 @@ -/* 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.
-
- * 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.
-
- * 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/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"
-#include "common/memstream.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(ScScript, false)
-
-//////////////////////////////////////////////////////////////////////////
-ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) {
- _buffer = NULL;
- _bufferSize = _iP = 0;
- _scriptStream = NULL;
- _filename = NULL;
- _currentLine = 0;
-
- _symbols = NULL;
- _numSymbols = 0;
-
- _engine = engine;
-
- _globals = NULL;
-
- _scopeStack = NULL;
- _callStack = NULL;
- _thisStack = NULL;
- _stack = NULL;
-
- _operand = NULL;
- _reg1 = NULL;
-
- _functions = NULL;
- _numFunctions = 0;
-
- _methods = NULL;
- _numMethods = 0;
-
- _events = NULL;
- _numEvents = 0;
-
- _externals = NULL;
- _numExternals = 0;
-
- _state = SCRIPT_FINISHED;
- _origState = SCRIPT_FINISHED;
-
- _waitObject = NULL;
- _waitTime = 0;
- _waitFrozen = false;
- _waitScript = NULL;
-
- _timeSlice = 0;
-
- _thread = false;
- _methodThread = false;
- _threadEvent = NULL;
-
- _freezable = true;
- _owner = NULL;
-
- _unbreakable = false;
- _parentScript = NULL;
-
- _tracingMode = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScScript::~ScScript() {
- cleanup();
-}
-
-void ScScript::readHeader() {
- uint32 oldPos = _scriptStream->pos();
- _scriptStream->seek(0);
- _header.magic = _scriptStream->readUint32LE();
- _header.version = _scriptStream->readUint32LE();
- _header.codeStart = _scriptStream->readUint32LE();
- _header.funcTable = _scriptStream->readUint32LE();
- _header.symbolTable = _scriptStream->readUint32LE();
- _header.eventTable = _scriptStream->readUint32LE();
- _header.externalsTable = _scriptStream->readUint32LE();
- _header.methodTable = _scriptStream->readUint32LE();
- _scriptStream->seek(oldPos);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::initScript() {
- if (!_scriptStream) {
- _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
- }
- readHeader();
-
- if (_header.magic != SCRIPT_MAGIC) {
- _gameRef->LOG(0, "File '%s' is not a valid compiled script", _filename);
- cleanup();
- return STATUS_FAILED;
- }
-
- if (_header.version > SCRIPT_VERSION) {
- _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);
- cleanup();
- return STATUS_FAILED;
- }
-
- initTables();
-
- // init stacks
- _scopeStack = new ScStack(_gameRef);
- _callStack = new ScStack(_gameRef);
- _thisStack = new ScStack(_gameRef);
- _stack = new ScStack(_gameRef);
-
- _operand = new ScValue(_gameRef);
- _reg1 = new ScValue(_gameRef);
-
-
- // skip to the beginning
- _iP = _header.codeStart;
- _scriptStream->seek(_iP);
- _currentLine = 0;
-
- // ready to rumble...
- _state = SCRIPT_RUNNING;
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::initTables() {
- uint32 origIP = _iP;
-
- readHeader();
- // load symbol table
- _iP = _header.symbolTable;
-
- _numSymbols = getDWORD();
- _symbols = new char*[_numSymbols];
- for (uint32 i = 0; i < _numSymbols; i++) {
- uint32 index = getDWORD();
- _symbols[index] = getString();
- }
-
- // load functions table
- _iP = _header.funcTable;
-
- _numFunctions = getDWORD();
- _functions = new TFunctionPos[_numFunctions];
- for (uint32 i = 0; i < _numFunctions; i++) {
- _functions[i].pos = getDWORD();
- _functions[i].name = getString();
- }
-
-
- // load events table
- _iP = _header.eventTable;
-
- _numEvents = getDWORD();
- _events = new TEventPos[_numEvents];
- for (uint32 i = 0; i < _numEvents; i++) {
- _events[i].pos = getDWORD();
- _events[i].name = getString();
- }
-
-
- // load externals
- if (_header.version >= 0x0101) {
- _iP = _header.externalsTable;
-
- _numExternals = getDWORD();
- _externals = new TExternalFunction[_numExternals];
- for (uint32 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();
- }
- }
- }
- }
-
- // load method table
- _iP = _header.methodTable;
-
- _numMethods = getDWORD();
- _methods = new TMethodPos[_numMethods];
- for (uint32 i = 0; i < _numMethods; i++) {
- _methods[i].pos = getDWORD();
- _methods[i].name = getString();
- }
-
-
- _iP = origIP;
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner) {
- cleanup();
-
- _thread = false;
- _methodThread = false;
-
- delete[] _threadEvent;
- _threadEvent = NULL;
-
- _filename = new char[strlen(filename) + 1];
- if (_filename) {
- strcpy(_filename, filename);
- }
-
- _buffer = new byte [size];
- if (!_buffer) {
- return STATUS_FAILED;
- }
-
- memcpy(_buffer, buffer, size);
-
- _bufferSize = size;
-
- bool res = initScript();
- if (DID_FAIL(res)) {
- return res;
- }
-
- // establish global variables table
- _globals = new ScValue(_gameRef);
-
- _owner = owner;
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::createThread(ScScript *original, uint32 initIP, const Common::String &eventName) {
- cleanup();
-
- _thread = true;
- _methodThread = false;
- _threadEvent = new char[eventName.size() + 1];
- if (_threadEvent) {
- strcpy(_threadEvent, eventName.c_str());
- }
-
- // copy filename
- _filename = new char[strlen(original->_filename) + 1];
- if (_filename) {
- strcpy(_filename, original->_filename);
- }
-
- // copy buffer
- _buffer = new byte [original->_bufferSize];
- if (!_buffer) {
- return STATUS_FAILED;
- }
-
- memcpy(_buffer, original->_buffer, original->_bufferSize);
- _bufferSize = original->_bufferSize;
-
- // initialize
- bool res = initScript();
- if (DID_FAIL(res)) {
- return res;
- }
-
- // copy globals
- _globals = original->_globals;
-
- // skip to the beginning of the event
- _iP = initIP;
- _scriptStream->seek(_iP);
-
- _timeSlice = original->_timeSlice;
- _freezable = original->_freezable;
- _owner = original->_owner;
-
- _engine = original->_engine;
- _parentScript = original;
-
- return STATUS_OK;
-}
-
-
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::createMethodThread(ScScript *original, const Common::String &methodName) {
- uint32 ip = original->getMethodPos(methodName);
- if (ip == 0) {
- return STATUS_FAILED;
- }
-
- cleanup();
-
- _thread = true;
- _methodThread = true;
- _threadEvent = new char[methodName.size() + 1];
- if (_threadEvent) {
- strcpy(_threadEvent, methodName.c_str());
- }
-
- // copy filename
- _filename = new char[strlen(original->_filename) + 1];
- if (_filename) {
- strcpy(_filename, original->_filename);
- }
-
- // copy buffer
- _buffer = new byte [original->_bufferSize];
- if (!_buffer) {
- return STATUS_FAILED;
- }
-
- memcpy(_buffer, original->_buffer, original->_bufferSize);
- _bufferSize = original->_bufferSize;
-
- // initialize
- bool res = initScript();
- if (DID_FAIL(res)) {
- return res;
- }
-
- // copy globals
- _globals = original->_globals;
-
- // skip to the beginning of the event
- _iP = ip;
-
- _timeSlice = original->_timeSlice;
- _freezable = original->_freezable;
- _owner = original->_owner;
-
- _engine = original->_engine;
- _parentScript = original;
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScScript::cleanup() {
- if (_buffer) {
- delete[] _buffer;
- }
- _buffer = NULL;
-
- if (_filename) {
- delete[] _filename;
- }
- _filename = NULL;
-
- if (_symbols) {
- delete[] _symbols;
- }
- _symbols = NULL;
- _numSymbols = 0;
-
- if (_globals && !_thread) {
- delete _globals;
- }
- _globals = NULL;
-
- delete _scopeStack;
- _scopeStack = NULL;
-
- delete _callStack;
- _callStack = NULL;
-
- delete _thisStack;
- _thisStack = NULL;
-
- delete _stack;
- _stack = NULL;
-
- if (_functions) {
- delete[] _functions;
- }
- _functions = NULL;
- _numFunctions = 0;
-
- if (_methods) {
- delete[] _methods;
- }
- _methods = NULL;
- _numMethods = 0;
-
- if (_events) {
- delete[] _events;
- }
- _events = NULL;
- _numEvents = 0;
-
-
- if (_externals) {
- for (uint32 i = 0; i < _numExternals; i++) {
- if (_externals[i].nu_params > 0) {
- delete[] _externals[i].params;
- }
- }
- delete[] _externals;
- }
- _externals = NULL;
- _numExternals = 0;
-
- delete _operand;
- delete _reg1;
- _operand = NULL;
- _reg1 = NULL;
-
- delete[] _threadEvent;
- _threadEvent = NULL;
-
- _state = SCRIPT_FINISHED;
-
- _waitObject = NULL;
- _waitTime = 0;
- _waitFrozen = false;
- _waitScript = NULL;
-
- _parentScript = NULL; // ref only
-
- delete _scriptStream;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-uint32 ScScript::getDWORD() {
- _scriptStream->seek((int32)_iP);
- uint32 ret = _scriptStream->readUint32LE();
- _iP += sizeof(uint32);
-// assert(oldRet == ret);
- return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////
-double ScScript::getFloat() {
- _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.
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-char *ScScript::getString() {
- char *ret = (char *)(_buffer + _iP);
- while (*(char *)(_buffer + _iP) != '\0') {
- _iP++;
- }
- _iP++; // string terminator
- _scriptStream->seek(_iP);
-
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::executeInstruction() {
- bool ret = STATUS_OK;
-
- uint32 dw;
- const char *str = NULL;
-
- //ScValue* op = new ScValue(_gameRef);
- _operand->cleanup();
-
- ScValue *op1;
- ScValue *op2;
-
- uint32 inst = getDWORD();
- switch (inst) {
-
- case II_DEF_VAR:
- _operand->setNULL();
- dw = getDWORD();
- if (_scopeStack->_sP < 0) {
- _globals->setProp(_symbols[dw], _operand);
- } else {
- _scopeStack->getTop()->setProp(_symbols[dw], _operand);
- }
-
- break;
-
- case II_DEF_GLOB_VAR:
- case II_DEF_CONST_VAR: {
- dw = getDWORD();
- /* char *temp = _symbols[dw]; // TODO delete */
- // only create global var if it doesn't exist
- if (!_engine->_globals->propExists(_symbols[dw])) {
- _operand->setNULL();
- _engine->_globals->setProp(_symbols[dw], _operand, false, inst == II_DEF_CONST_VAR);
- }
- break;
- }
-
- case II_RET:
- if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) {
- _scopeStack->pop();
- _iP = (uint32)_callStack->pop()->getInt();
- } else {
- if (_thread) {
- _state = SCRIPT_THREAD_FINISHED;
- } else {
- if (_numEvents == 0 && _numMethods == 0) {
- _state = SCRIPT_FINISHED;
- } else {
- _state = SCRIPT_PERSISTENT;
- }
- }
- }
-
- break;
-
- case II_RET_EVENT:
- _state = SCRIPT_FINISHED;
- break;
-
-
- case II_CALL:
- dw = getDWORD();
-
- _operand->setInt(_iP);
- _callStack->push(_operand);
-
- _iP = dw;
-
- break;
-
- case II_CALL_BY_EXP: {
- // push var
- // push string
- str = _stack->pop()->getString();
- char *methodName = new char[strlen(str) + 1];
- strcpy(methodName, str);
-
- ScValue *var = _stack->pop();
- if (var->_type == VAL_VARIABLE_REF) {
- var = var->_valRef;
- }
-
- bool res = STATUS_FAILED;
- bool triedNative = false;
-
- // we are already calling this method, try native
- if (_thread && _methodThread && strcmp(methodName, _threadEvent) == 0 && var->_type == VAL_NATIVE && _owner == var->getNative()) {
- triedNative = true;
- res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
- }
-
- if (DID_FAIL(res)) {
- if (var->isNative() && var->getNative()->canHandleMethod(methodName)) {
- if (!_unbreakable) {
- _waitScript = var->getNative()->invokeMethodThread(methodName);
- if (!_waitScript) {
- _stack->correctParams(0);
- runtimeError("Error invoking method '%s'.", methodName);
- _stack->pushNULL();
- } else {
- _state = SCRIPT_WAITING_SCRIPT;
- _waitScript->copyParameters(_stack);
- }
- } else {
- // can call methods in unbreakable mode
- _stack->correctParams(0);
- runtimeError("Cannot call method '%s'. Ignored.", methodName);
- _stack->pushNULL();
- }
- delete[] methodName;
- break;
- }
- /*
- ScValue* val = var->getProp(MethodName);
- if (val){
- dw = GetFuncPos(val->getString());
- if (dw==0){
- TExternalFunction* f = GetExternal(val->getString());
- if (f){
- ExternalCall(_stack, _thisStack, f);
- }
- else{
- // not an internal nor external, try for native function
- _gameRef->ExternalCall(this, _stack, _thisStack, val->getString());
- }
- }
- else{
- _operand->setInt(_iP);
- _callStack->Push(_operand);
- _iP = dw;
- }
- }
- */
- else {
- res = STATUS_FAILED;
- if (var->_type == VAL_NATIVE && !triedNative) {
- res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
- }
-
- if (DID_FAIL(res)) {
- _stack->correctParams(0);
- runtimeError("Call to undefined method '%s'. Ignored.", methodName);
- _stack->pushNULL();
- }
- }
- }
- delete[] methodName;
- }
- break;
-
- case II_EXTERNAL_CALL: {
- uint32 symbolIndex = getDWORD();
-
- TExternalFunction *f = getExternal(_symbols[symbolIndex]);
- if (f) {
- externalCall(_stack, _thisStack, f);
- } else {
- _gameRef->externalCall(this, _stack, _thisStack, _symbols[symbolIndex]);
- }
-
- break;
- }
- case II_SCOPE:
- _operand->setNULL();
- _scopeStack->push(_operand);
- break;
-
- case II_CORRECT_STACK:
- dw = getDWORD(); // params expected
- _stack->correctParams(dw);
- break;
-
- case II_CREATE_OBJECT:
- _operand->setObject();
- _stack->push(_operand);
- break;
-
- case II_POP_EMPTY:
- _stack->pop();
- break;
-
- case II_PUSH_VAR: {
- ScValue *var = getVar(_symbols[getDWORD()]);
- if (false && /*var->_type==VAL_OBJECT ||*/ var->_type == VAL_NATIVE) {
- _operand->setReference(var);
- _stack->push(_operand);
- } else {
- _stack->push(var);
- }
- break;
- }
-
- case II_PUSH_VAR_REF: {
- ScValue *var = getVar(_symbols[getDWORD()]);
- _operand->setReference(var);
- _stack->push(_operand);
- break;
- }
-
- case II_POP_VAR: {
- char *varName = _symbols[getDWORD()];
- ScValue *var = getVar(varName);
- if (var) {
- ScValue *val = _stack->pop();
- if (!val) {
- runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
- var->setNULL();
- } else {
- if (val->getType() == VAL_VARIABLE_REF) {
- val = val->_valRef;
- }
- if (val->_type == VAL_NATIVE) {
- var->setValue(val);
- } else {
- var->copy(val);
- }
- }
- }
-
- break;
- }
-
- case II_PUSH_VAR_THIS:
- _stack->push(_thisStack->getTop());
- break;
-
- case II_PUSH_INT:
- _stack->pushInt((int)getDWORD());
- break;
-
- case II_PUSH_FLOAT:
- _stack->pushFloat(getFloat());
- break;
-
-
- case II_PUSH_BOOL:
- _stack->pushBool(getDWORD() != 0);
-
- break;
-
- case II_PUSH_STRING:
- _stack->pushString(getString());
- break;
-
- case II_PUSH_NULL:
- _stack->pushNULL();
- break;
-
- case II_PUSH_THIS_FROM_STACK:
- _operand->setReference(_stack->getTop());
- _thisStack->push(_operand);
- break;
-
- case II_PUSH_THIS:
- _operand->setReference(getVar(_symbols[getDWORD()]));
- _thisStack->push(_operand);
- break;
-
- case II_POP_THIS:
- _thisStack->pop();
- break;
-
- case II_PUSH_BY_EXP: {
- str = _stack->pop()->getString();
- ScValue *val = _stack->pop()->getProp(str);
- if (val) {
- _stack->push(val);
- } else {
- _stack->pushNULL();
- }
-
- break;
- }
-
- case II_POP_BY_EXP: {
- str = _stack->pop()->getString();
- ScValue *var = _stack->pop();
- ScValue *val = _stack->pop();
-
- if (val == NULL) {
- runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
- var->setNULL();
- } else {
- var->setProp(str, val);
- }
-
- break;
- }
-
- case II_PUSH_REG1:
- _stack->push(_reg1);
- break;
-
- case II_POP_REG1:
- _reg1->copy(_stack->pop());
- break;
-
- case II_JMP:
- _iP = getDWORD();
- break;
-
- case II_JMP_FALSE: {
- dw = getDWORD();
- //if (!_stack->pop()->getBool()) _iP = dw;
- ScValue *val = _stack->pop();
- if (!val) {
- runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
- } else {
- if (!val->getBool()) {
- _iP = dw;
- }
- }
- break;
- }
-
- case II_ADD:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- if (op1->isNULL() || op2->isNULL()) {
- _operand->setNULL();
- } 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);
- delete[] tempStr;
- } else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
- _operand->setInt(op1->getInt() + op2->getInt());
- } else {
- _operand->setFloat(op1->getFloat() + op2->getFloat());
- }
-
- _stack->push(_operand);
-
- break;
-
- case II_SUB:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- 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());
- }
-
- _stack->push(_operand);
-
- break;
-
- case II_MUL:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- 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());
- }
-
- _stack->push(_operand);
-
- break;
-
- case II_DIV:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- if (op2->getFloat() == 0.0f) {
- runtimeError("Division by zero.");
- }
-
- if (op1->isNULL() || op2->isNULL() || op2->getFloat() == 0.0f) {
- _operand->setNULL();
- } else {
- _operand->setFloat(op1->getFloat() / op2->getFloat());
- }
-
- _stack->push(_operand);
-
- break;
-
- case II_MODULO:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- if (op2->getInt() == 0) {
- runtimeError("Division by zero.");
- }
-
- if (op1->isNULL() || op2->isNULL() || op2->getInt() == 0) {
- _operand->setNULL();
- } else {
- _operand->setInt(op1->getInt() % op2->getInt());
- }
-
- _stack->push(_operand);
-
- break;
-
- case II_NOT:
- op1 = _stack->pop();
- //if (op1->isNULL()) _operand->setNULL();
- if (op1->isNULL()) {
- _operand->setBool(true);
- } else {
- _operand->setBool(!op1->getBool());
- }
- _stack->push(_operand);
-
- break;
-
- case II_AND:
- op2 = _stack->pop();
- op1 = _stack->pop();
- if (op1 == NULL || op2 == NULL) {
- runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
- _operand->setBool(false);
- } else {
- _operand->setBool(op1->getBool() && op2->getBool());
- }
- _stack->push(_operand);
- break;
-
- case II_OR:
- op2 = _stack->pop();
- op1 = _stack->pop();
- if (op1 == NULL || op2 == NULL) {
- runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
- _operand->setBool(false);
- } else {
- _operand->setBool(op1->getBool() || op2->getBool());
- }
- _stack->push(_operand);
- break;
-
- case II_CMP_EQ:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(false);
- else if (op1->isNative() && op2->isNative()){
- _operand->setBool(op1->getNative() == op2->getNative());
- }
- else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){
- _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())==0);
- }
- else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() == op2->getFloat());
- }
- else{
- _operand->setBool(op1->getInt() == op2->getInt());
- }
- */
-
- _operand->setBool(ScValue::compare(op1, op2) == 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_NE:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(true);
- else if (op1->isNative() && op2->isNative()){
- _operand->setBool(op1->getNative() != op2->getNative());
- }
- else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){
- _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())!=0);
- }
- else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() != op2->getFloat());
- }
- else{
- _operand->setBool(op1->getInt() != op2->getInt());
- }
- */
-
- _operand->setBool(ScValue::compare(op1, op2) != 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_L:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() < op2->getFloat());
- }
- else _operand->setBool(op1->getInt() < op2->getInt());
- */
-
- _operand->setBool(ScValue::compare(op1, op2) < 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_G:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() > op2->getFloat());
- }
- else _operand->setBool(op1->getInt() > op2->getInt());
- */
-
- _operand->setBool(ScValue::compare(op1, op2) > 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_LE:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() <= op2->getFloat());
- }
- else _operand->setBool(op1->getInt() <= op2->getInt());
- */
-
- _operand->setBool(ScValue::compare(op1, op2) <= 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_GE:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- /*
- if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
- _operand->setBool(op1->getFloat() >= op2->getFloat());
- }
- else _operand->setBool(op1->getInt() >= op2->getInt());
- */
-
- _operand->setBool(ScValue::compare(op1, op2) >= 0);
- _stack->push(_operand);
- break;
-
- case II_CMP_STRICT_EQ:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- //_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat());
- _operand->setBool(ScValue::compareStrict(op1, op2) == 0);
- _stack->push(_operand);
-
- break;
-
- case II_CMP_STRICT_NE:
- op2 = _stack->pop();
- op1 = _stack->pop();
-
- //_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat());
- _operand->setBool(ScValue::compareStrict(op1, op2) != 0);
- _stack->push(_operand);
- break;
-
- case II_DBG_LINE: {
- int newLine = getDWORD();
- if (newLine != _currentLine) {
- _currentLine = newLine;
- }
- break;
-
- }
- default:
- _gameRef->LOG(0, "Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x)\n", inst, _filename, _currentLine, _iP - sizeof(uint32));
- _state = SCRIPT_FINISHED;
- ret = STATUS_FAILED;
- } // switch(instruction)
-
- //delete op;
-
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-uint32 ScScript::getFuncPos(const Common::String &name) {
- for (uint32 i = 0; i < _numFunctions; i++) {
- if (name == _functions[i].name) {
- return _functions[i].pos;
- }
- }
- return 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-uint32 ScScript::getMethodPos(const Common::String &name) {
- for (uint32 i = 0; i < _numMethods; i++) {
- if (name == _methods[i].name) {
- return _methods[i].pos;
- }
- }
- return 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScScript::getVar(char *name) {
- ScValue *ret = NULL;
-
- // scope locals
- if (_scopeStack->_sP >= 0) {
- if (_scopeStack->getTop()->propExists(name)) {
- ret = _scopeStack->getTop()->getProp(name);
- }
- }
-
- // script globals
- if (ret == NULL) {
- if (_globals->propExists(name)) {
- ret = _globals->getProp(name);
- }
- }
-
- // engine globals
- if (ret == NULL) {
- if (_engine->_globals->propExists(name)) {
- ret = _engine->_globals->getProp(name);
- }
- }
-
- if (ret == NULL) {
- //RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", name);
- _gameRef->LOG(0, "Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d)", name, _filename, _currentLine);
- ScValue *val = new ScValue(_gameRef);
- ScValue *scope = _scopeStack->getTop();
- if (scope) {
- scope->setProp(name, val);
- ret = _scopeStack->getTop()->getProp(name);
- } else {
- _globals->setProp(name, val);
- ret = _globals->getProp(name);
- }
- delete val;
- }
-
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::waitFor(BaseObject *object) {
- if (_unbreakable) {
- runtimeError("Script cannot be interrupted.");
- return STATUS_OK;
- }
-
- _state = SCRIPT_WAITING;
- _waitObject = object;
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::waitForExclusive(BaseObject *object) {
- _engine->resetObject(object);
- return waitFor(object);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::sleep(uint32 duration) {
- if (_unbreakable) {
- runtimeError("Script cannot be interrupted.");
- return STATUS_OK;
- }
-
- _state = SCRIPT_SLEEPING;
- if (_gameRef->_state == GAME_FROZEN) {
- _waitTime = g_system->getMillis() + duration;
- _waitFrozen = true;
- } else {
- _waitTime = _gameRef->_timer + duration;
- _waitFrozen = false;
- }
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::finish(bool includingThreads) {
- if (_state != SCRIPT_FINISHED && includingThreads) {
- _state = SCRIPT_FINISHED;
- finishThreads();
- } else {
- _state = SCRIPT_FINISHED;
- }
-
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::run() {
- _state = SCRIPT_RUNNING;
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////
-void ScScript::runtimeError(const char *fmt, ...) {
- char buff[256];
- va_list va;
-
- va_start(va, fmt);
- vsprintf(buff, fmt, va);
- va_end(va);
-
- _gameRef->LOG(0, "Runtime error. Script '%s', line %d", _filename, _currentLine);
- _gameRef->LOG(0, " %s", buff);
-
- if (!_gameRef->_suppressScriptErrors) {
- _gameRef->quickMessage("Script runtime error. View log for details.");
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::persist(BasePersistenceManager *persistMgr) {
-
- persistMgr->transfer(TMEMBER(_gameRef));
-
- // buffer
- if (persistMgr->getIsSaving()) {
- if (_state != SCRIPT_PERSISTENT && _state != SCRIPT_FINISHED && _state != SCRIPT_THREAD_FINISHED) {
- persistMgr->transfer(TMEMBER(_bufferSize));
- persistMgr->putBytes(_buffer, _bufferSize);
- } else {
- // don't save idle/finished scripts
- int bufferSize = 0;
- persistMgr->transfer(TMEMBER(bufferSize));
- }
- } else {
- persistMgr->transfer(TMEMBER(_bufferSize));
- if (_bufferSize > 0) {
- _buffer = new byte[_bufferSize];
- persistMgr->getBytes(_buffer, _bufferSize);
- _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
- initTables();
- } else {
- _buffer = NULL;
- _scriptStream = NULL;
- }
- }
-
- 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->getIsSaving()) {
- _tracingMode = false;
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unbreakable) {
- //if (_state!=SCRIPT_PERSISTENT) return NULL;
-
- uint32 pos = getEventPos(eventName);
- if (!pos) {
- return NULL;
- }
-
- ScScript *thread = new ScScript(_gameRef, _engine);
- if (thread) {
- bool ret = thread->createThread(this, pos, eventName);
- if (DID_SUCCEED(ret)) {
- thread->_unbreakable = unbreakable;
- _engine->_scripts.add(thread);
- return thread;
- } else {
- delete thread;
- return NULL;
- }
- } else {
- return NULL;
- }
-
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-uint32 ScScript::getEventPos(const Common::String &name) {
- for (int i = _numEvents - 1; i >= 0; i--) {
- if (scumm_stricmp(name.c_str(), _events[i].name) == 0) {
- return _events[i].pos;
- }
- }
- return 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::canHandleEvent(const Common::String &eventName) {
- return getEventPos(eventName) != 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::canHandleMethod(const Common::String &methodName) {
- return getMethodPos(methodName) != 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::pause() {
- if (_state == SCRIPT_PAUSED) {
- _gameRef->LOG(0, "Attempting to pause a paused script ('%s', line %d)", _filename, _currentLine);
- return STATUS_FAILED;
- }
-
- if (!_freezable || _state == SCRIPT_PERSISTENT) {
- return STATUS_OK;
- }
-
- _origState = _state;
- _state = SCRIPT_PAUSED;
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::resume() {
- if (_state != SCRIPT_PAUSED) {
- return STATUS_OK;
- }
-
- _state = _origState;
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScScript::TExternalFunction *ScScript::getExternal(char *name) {
- for (uint32 i = 0; i < _numExternals; i++) {
- if (strcmp(name, _externals[i].name) == 0) {
- return &_externals[i];
- }
- }
- return NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function) {
-
- _gameRef->LOG(0, "External functions are not supported on this platform.");
- stack->correctParams(0);
- stack->pushNULL();
- return STATUS_FAILED;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::copyParameters(ScStack *stack) {
- int i;
- int numParams = stack->pop()->getInt();
- for (i = numParams - 1; i >= 0; i--) {
- _stack->push(stack->getAt(i));
- }
- _stack->pushInt(numParams);
-
- for (i = 0; i < numParams; i++) {
- stack->pop();
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScScript::finishThreads() {
- for (uint32 i = 0; i < _engine->_scripts.size(); i++) {
- ScScript *scr = _engine->_scripts[i];
- if (scr->_thread && scr->_state != SCRIPT_FINISHED && scr->_owner == _owner && scumm_stricmp(scr->_filename, _filename) == 0) {
- scr->finish(true);
- }
- }
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// IWmeDebugScript interface implementation
-int ScScript::dbgGetLine() {
- return _currentLine;
-}
-
-//////////////////////////////////////////////////////////////////////////
-const char *ScScript::dbgGetFilename() {
- return _filename;
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ScScript::afterLoad() {
- if (_buffer == NULL) {
- byte *buffer = _engine->getCompiledScript(_filename, &_bufferSize);
- if (!buffer) {
- _gameRef->LOG(0, "Error reinitializing script '%s' after load. Script will be terminated.", _filename);
- _state = SCRIPT_ERROR;
- return;
- }
-
- _buffer = new byte [_bufferSize];
- memcpy(_buffer, buffer, _bufferSize);
-
- delete _scriptStream;
- _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
-
- initTables();
- }
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/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" +#include "common/memstream.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(ScScript, false) + +////////////////////////////////////////////////////////////////////////// +ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) { + _buffer = NULL; + _bufferSize = _iP = 0; + _scriptStream = NULL; + _filename = NULL; + _currentLine = 0; + + _symbols = NULL; + _numSymbols = 0; + + _engine = engine; + + _globals = NULL; + + _scopeStack = NULL; + _callStack = NULL; + _thisStack = NULL; + _stack = NULL; + + _operand = NULL; + _reg1 = NULL; + + _functions = NULL; + _numFunctions = 0; + + _methods = NULL; + _numMethods = 0; + + _events = NULL; + _numEvents = 0; + + _externals = NULL; + _numExternals = 0; + + _state = SCRIPT_FINISHED; + _origState = SCRIPT_FINISHED; + + _waitObject = NULL; + _waitTime = 0; + _waitFrozen = false; + _waitScript = NULL; + + _timeSlice = 0; + + _thread = false; + _methodThread = false; + _threadEvent = NULL; + + _freezable = true; + _owner = NULL; + + _unbreakable = false; + _parentScript = NULL; + + _tracingMode = false; +} + + +////////////////////////////////////////////////////////////////////////// +ScScript::~ScScript() { + cleanup(); +} + +void ScScript::readHeader() { + uint32 oldPos = _scriptStream->pos(); + _scriptStream->seek(0); + _header.magic = _scriptStream->readUint32LE(); + _header.version = _scriptStream->readUint32LE(); + _header.codeStart = _scriptStream->readUint32LE(); + _header.funcTable = _scriptStream->readUint32LE(); + _header.symbolTable = _scriptStream->readUint32LE(); + _header.eventTable = _scriptStream->readUint32LE(); + _header.externalsTable = _scriptStream->readUint32LE(); + _header.methodTable = _scriptStream->readUint32LE(); + _scriptStream->seek(oldPos); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::initScript() { + if (!_scriptStream) { + _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize); + } + readHeader(); + + if (_header.magic != SCRIPT_MAGIC) { + _gameRef->LOG(0, "File '%s' is not a valid compiled script", _filename); + cleanup(); + return STATUS_FAILED; + } + + if (_header.version > SCRIPT_VERSION) { + _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); + cleanup(); + return STATUS_FAILED; + } + + initTables(); + + // init stacks + _scopeStack = new ScStack(_gameRef); + _callStack = new ScStack(_gameRef); + _thisStack = new ScStack(_gameRef); + _stack = new ScStack(_gameRef); + + _operand = new ScValue(_gameRef); + _reg1 = new ScValue(_gameRef); + + + // skip to the beginning + _iP = _header.codeStart; + _scriptStream->seek(_iP); + _currentLine = 0; + + // ready to rumble... + _state = SCRIPT_RUNNING; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::initTables() { + uint32 origIP = _iP; + + readHeader(); + // load symbol table + _iP = _header.symbolTable; + + _numSymbols = getDWORD(); + _symbols = new char*[_numSymbols]; + for (uint32 i = 0; i < _numSymbols; i++) { + uint32 index = getDWORD(); + _symbols[index] = getString(); + } + + // load functions table + _iP = _header.funcTable; + + _numFunctions = getDWORD(); + _functions = new TFunctionPos[_numFunctions]; + for (uint32 i = 0; i < _numFunctions; i++) { + _functions[i].pos = getDWORD(); + _functions[i].name = getString(); + } + + + // load events table + _iP = _header.eventTable; + + _numEvents = getDWORD(); + _events = new TEventPos[_numEvents]; + for (uint32 i = 0; i < _numEvents; i++) { + _events[i].pos = getDWORD(); + _events[i].name = getString(); + } + + + // load externals + if (_header.version >= 0x0101) { + _iP = _header.externalsTable; + + _numExternals = getDWORD(); + _externals = new TExternalFunction[_numExternals]; + for (uint32 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(); + } + } + } + } + + // load method table + _iP = _header.methodTable; + + _numMethods = getDWORD(); + _methods = new TMethodPos[_numMethods]; + for (uint32 i = 0; i < _numMethods; i++) { + _methods[i].pos = getDWORD(); + _methods[i].name = getString(); + } + + + _iP = origIP; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner) { + cleanup(); + + _thread = false; + _methodThread = false; + + delete[] _threadEvent; + _threadEvent = NULL; + + _filename = new char[strlen(filename) + 1]; + if (_filename) { + strcpy(_filename, filename); + } + + _buffer = new byte [size]; + if (!_buffer) { + return STATUS_FAILED; + } + + memcpy(_buffer, buffer, size); + + _bufferSize = size; + + bool res = initScript(); + if (DID_FAIL(res)) { + return res; + } + + // establish global variables table + _globals = new ScValue(_gameRef); + + _owner = owner; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::createThread(ScScript *original, uint32 initIP, const Common::String &eventName) { + cleanup(); + + _thread = true; + _methodThread = false; + _threadEvent = new char[eventName.size() + 1]; + if (_threadEvent) { + strcpy(_threadEvent, eventName.c_str()); + } + + // copy filename + _filename = new char[strlen(original->_filename) + 1]; + if (_filename) { + strcpy(_filename, original->_filename); + } + + // copy buffer + _buffer = new byte [original->_bufferSize]; + if (!_buffer) { + return STATUS_FAILED; + } + + memcpy(_buffer, original->_buffer, original->_bufferSize); + _bufferSize = original->_bufferSize; + + // initialize + bool res = initScript(); + if (DID_FAIL(res)) { + return res; + } + + // copy globals + _globals = original->_globals; + + // skip to the beginning of the event + _iP = initIP; + _scriptStream->seek(_iP); + + _timeSlice = original->_timeSlice; + _freezable = original->_freezable; + _owner = original->_owner; + + _engine = original->_engine; + _parentScript = original; + + return STATUS_OK; +} + + + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::createMethodThread(ScScript *original, const Common::String &methodName) { + uint32 ip = original->getMethodPos(methodName); + if (ip == 0) { + return STATUS_FAILED; + } + + cleanup(); + + _thread = true; + _methodThread = true; + _threadEvent = new char[methodName.size() + 1]; + if (_threadEvent) { + strcpy(_threadEvent, methodName.c_str()); + } + + // copy filename + _filename = new char[strlen(original->_filename) + 1]; + if (_filename) { + strcpy(_filename, original->_filename); + } + + // copy buffer + _buffer = new byte [original->_bufferSize]; + if (!_buffer) { + return STATUS_FAILED; + } + + memcpy(_buffer, original->_buffer, original->_bufferSize); + _bufferSize = original->_bufferSize; + + // initialize + bool res = initScript(); + if (DID_FAIL(res)) { + return res; + } + + // copy globals + _globals = original->_globals; + + // skip to the beginning of the event + _iP = ip; + + _timeSlice = original->_timeSlice; + _freezable = original->_freezable; + _owner = original->_owner; + + _engine = original->_engine; + _parentScript = original; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void ScScript::cleanup() { + if (_buffer) { + delete[] _buffer; + } + _buffer = NULL; + + if (_filename) { + delete[] _filename; + } + _filename = NULL; + + if (_symbols) { + delete[] _symbols; + } + _symbols = NULL; + _numSymbols = 0; + + if (_globals && !_thread) { + delete _globals; + } + _globals = NULL; + + delete _scopeStack; + _scopeStack = NULL; + + delete _callStack; + _callStack = NULL; + + delete _thisStack; + _thisStack = NULL; + + delete _stack; + _stack = NULL; + + if (_functions) { + delete[] _functions; + } + _functions = NULL; + _numFunctions = 0; + + if (_methods) { + delete[] _methods; + } + _methods = NULL; + _numMethods = 0; + + if (_events) { + delete[] _events; + } + _events = NULL; + _numEvents = 0; + + + if (_externals) { + for (uint32 i = 0; i < _numExternals; i++) { + if (_externals[i].nu_params > 0) { + delete[] _externals[i].params; + } + } + delete[] _externals; + } + _externals = NULL; + _numExternals = 0; + + delete _operand; + delete _reg1; + _operand = NULL; + _reg1 = NULL; + + delete[] _threadEvent; + _threadEvent = NULL; + + _state = SCRIPT_FINISHED; + + _waitObject = NULL; + _waitTime = 0; + _waitFrozen = false; + _waitScript = NULL; + + _parentScript = NULL; // ref only + + delete _scriptStream; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 ScScript::getDWORD() { + _scriptStream->seek((int32)_iP); + uint32 ret = _scriptStream->readUint32LE(); + _iP += sizeof(uint32); +// assert(oldRet == ret); + return ret; +} + +////////////////////////////////////////////////////////////////////////// +double ScScript::getFloat() { + _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. + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +char *ScScript::getString() { + char *ret = (char *)(_buffer + _iP); + while (*(char *)(_buffer + _iP) != '\0') { + _iP++; + } + _iP++; // string terminator + _scriptStream->seek(_iP); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::executeInstruction() { + bool ret = STATUS_OK; + + uint32 dw; + const char *str = NULL; + + //ScValue* op = new ScValue(_gameRef); + _operand->cleanup(); + + ScValue *op1; + ScValue *op2; + + uint32 inst = getDWORD(); + switch (inst) { + + case II_DEF_VAR: + _operand->setNULL(); + dw = getDWORD(); + if (_scopeStack->_sP < 0) { + _globals->setProp(_symbols[dw], _operand); + } else { + _scopeStack->getTop()->setProp(_symbols[dw], _operand); + } + + break; + + case II_DEF_GLOB_VAR: + case II_DEF_CONST_VAR: { + dw = getDWORD(); + /* char *temp = _symbols[dw]; // TODO delete */ + // only create global var if it doesn't exist + if (!_engine->_globals->propExists(_symbols[dw])) { + _operand->setNULL(); + _engine->_globals->setProp(_symbols[dw], _operand, false, inst == II_DEF_CONST_VAR); + } + break; + } + + case II_RET: + if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) { + _scopeStack->pop(); + _iP = (uint32)_callStack->pop()->getInt(); + } else { + if (_thread) { + _state = SCRIPT_THREAD_FINISHED; + } else { + if (_numEvents == 0 && _numMethods == 0) { + _state = SCRIPT_FINISHED; + } else { + _state = SCRIPT_PERSISTENT; + } + } + } + + break; + + case II_RET_EVENT: + _state = SCRIPT_FINISHED; + break; + + + case II_CALL: + dw = getDWORD(); + + _operand->setInt(_iP); + _callStack->push(_operand); + + _iP = dw; + + break; + + case II_CALL_BY_EXP: { + // push var + // push string + str = _stack->pop()->getString(); + char *methodName = new char[strlen(str) + 1]; + strcpy(methodName, str); + + ScValue *var = _stack->pop(); + if (var->_type == VAL_VARIABLE_REF) { + var = var->_valRef; + } + + bool res = STATUS_FAILED; + bool triedNative = false; + + // we are already calling this method, try native + if (_thread && _methodThread && strcmp(methodName, _threadEvent) == 0 && var->_type == VAL_NATIVE && _owner == var->getNative()) { + triedNative = true; + res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName); + } + + if (DID_FAIL(res)) { + if (var->isNative() && var->getNative()->canHandleMethod(methodName)) { + if (!_unbreakable) { + _waitScript = var->getNative()->invokeMethodThread(methodName); + if (!_waitScript) { + _stack->correctParams(0); + runtimeError("Error invoking method '%s'.", methodName); + _stack->pushNULL(); + } else { + _state = SCRIPT_WAITING_SCRIPT; + _waitScript->copyParameters(_stack); + } + } else { + // can call methods in unbreakable mode + _stack->correctParams(0); + runtimeError("Cannot call method '%s'. Ignored.", methodName); + _stack->pushNULL(); + } + delete[] methodName; + break; + } + /* + ScValue* val = var->getProp(MethodName); + if (val){ + dw = GetFuncPos(val->getString()); + if (dw==0){ + TExternalFunction* f = GetExternal(val->getString()); + if (f){ + ExternalCall(_stack, _thisStack, f); + } + else{ + // not an internal nor external, try for native function + _gameRef->ExternalCall(this, _stack, _thisStack, val->getString()); + } + } + else{ + _operand->setInt(_iP); + _callStack->Push(_operand); + _iP = dw; + } + } + */ + else { + res = STATUS_FAILED; + if (var->_type == VAL_NATIVE && !triedNative) { + res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName); + } + + if (DID_FAIL(res)) { + _stack->correctParams(0); + runtimeError("Call to undefined method '%s'. Ignored.", methodName); + _stack->pushNULL(); + } + } + } + delete[] methodName; + } + break; + + case II_EXTERNAL_CALL: { + uint32 symbolIndex = getDWORD(); + + TExternalFunction *f = getExternal(_symbols[symbolIndex]); + if (f) { + externalCall(_stack, _thisStack, f); + } else { + _gameRef->externalCall(this, _stack, _thisStack, _symbols[symbolIndex]); + } + + break; + } + case II_SCOPE: + _operand->setNULL(); + _scopeStack->push(_operand); + break; + + case II_CORRECT_STACK: + dw = getDWORD(); // params expected + _stack->correctParams(dw); + break; + + case II_CREATE_OBJECT: + _operand->setObject(); + _stack->push(_operand); + break; + + case II_POP_EMPTY: + _stack->pop(); + break; + + case II_PUSH_VAR: { + ScValue *var = getVar(_symbols[getDWORD()]); + if (false && /*var->_type==VAL_OBJECT ||*/ var->_type == VAL_NATIVE) { + _operand->setReference(var); + _stack->push(_operand); + } else { + _stack->push(var); + } + break; + } + + case II_PUSH_VAR_REF: { + ScValue *var = getVar(_symbols[getDWORD()]); + _operand->setReference(var); + _stack->push(_operand); + break; + } + + case II_POP_VAR: { + char *varName = _symbols[getDWORD()]; + ScValue *var = getVar(varName); + if (var) { + ScValue *val = _stack->pop(); + if (!val) { + runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum."); + var->setNULL(); + } else { + if (val->getType() == VAL_VARIABLE_REF) { + val = val->_valRef; + } + if (val->_type == VAL_NATIVE) { + var->setValue(val); + } else { + var->copy(val); + } + } + } + + break; + } + + case II_PUSH_VAR_THIS: + _stack->push(_thisStack->getTop()); + break; + + case II_PUSH_INT: + _stack->pushInt((int)getDWORD()); + break; + + case II_PUSH_FLOAT: + _stack->pushFloat(getFloat()); + break; + + + case II_PUSH_BOOL: + _stack->pushBool(getDWORD() != 0); + + break; + + case II_PUSH_STRING: + _stack->pushString(getString()); + break; + + case II_PUSH_NULL: + _stack->pushNULL(); + break; + + case II_PUSH_THIS_FROM_STACK: + _operand->setReference(_stack->getTop()); + _thisStack->push(_operand); + break; + + case II_PUSH_THIS: + _operand->setReference(getVar(_symbols[getDWORD()])); + _thisStack->push(_operand); + break; + + case II_POP_THIS: + _thisStack->pop(); + break; + + case II_PUSH_BY_EXP: { + str = _stack->pop()->getString(); + ScValue *val = _stack->pop()->getProp(str); + if (val) { + _stack->push(val); + } else { + _stack->pushNULL(); + } + + break; + } + + case II_POP_BY_EXP: { + str = _stack->pop()->getString(); + ScValue *var = _stack->pop(); + ScValue *val = _stack->pop(); + + if (val == NULL) { + runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum."); + var->setNULL(); + } else { + var->setProp(str, val); + } + + break; + } + + case II_PUSH_REG1: + _stack->push(_reg1); + break; + + case II_POP_REG1: + _reg1->copy(_stack->pop()); + break; + + case II_JMP: + _iP = getDWORD(); + break; + + case II_JMP_FALSE: { + dw = getDWORD(); + //if (!_stack->pop()->getBool()) _iP = dw; + ScValue *val = _stack->pop(); + if (!val) { + runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?"); + } else { + if (!val->getBool()) { + _iP = dw; + } + } + break; + } + + case II_ADD: + op2 = _stack->pop(); + op1 = _stack->pop(); + + if (op1->isNULL() || op2->isNULL()) { + _operand->setNULL(); + } 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); + delete[] tempStr; + } else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) { + _operand->setInt(op1->getInt() + op2->getInt()); + } else { + _operand->setFloat(op1->getFloat() + op2->getFloat()); + } + + _stack->push(_operand); + + break; + + case II_SUB: + op2 = _stack->pop(); + op1 = _stack->pop(); + + 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()); + } + + _stack->push(_operand); + + break; + + case II_MUL: + op2 = _stack->pop(); + op1 = _stack->pop(); + + 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()); + } + + _stack->push(_operand); + + break; + + case II_DIV: + op2 = _stack->pop(); + op1 = _stack->pop(); + + if (op2->getFloat() == 0.0f) { + runtimeError("Division by zero."); + } + + if (op1->isNULL() || op2->isNULL() || op2->getFloat() == 0.0f) { + _operand->setNULL(); + } else { + _operand->setFloat(op1->getFloat() / op2->getFloat()); + } + + _stack->push(_operand); + + break; + + case II_MODULO: + op2 = _stack->pop(); + op1 = _stack->pop(); + + if (op2->getInt() == 0) { + runtimeError("Division by zero."); + } + + if (op1->isNULL() || op2->isNULL() || op2->getInt() == 0) { + _operand->setNULL(); + } else { + _operand->setInt(op1->getInt() % op2->getInt()); + } + + _stack->push(_operand); + + break; + + case II_NOT: + op1 = _stack->pop(); + //if (op1->isNULL()) _operand->setNULL(); + if (op1->isNULL()) { + _operand->setBool(true); + } else { + _operand->setBool(!op1->getBool()); + } + _stack->push(_operand); + + break; + + case II_AND: + op2 = _stack->pop(); + op1 = _stack->pop(); + if (op1 == NULL || op2 == NULL) { + runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?"); + _operand->setBool(false); + } else { + _operand->setBool(op1->getBool() && op2->getBool()); + } + _stack->push(_operand); + break; + + case II_OR: + op2 = _stack->pop(); + op1 = _stack->pop(); + if (op1 == NULL || op2 == NULL) { + runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?"); + _operand->setBool(false); + } else { + _operand->setBool(op1->getBool() || op2->getBool()); + } + _stack->push(_operand); + break; + + case II_CMP_EQ: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(false); + else if (op1->isNative() && op2->isNative()){ + _operand->setBool(op1->getNative() == op2->getNative()); + } + else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){ + _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())==0); + } + else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() == op2->getFloat()); + } + else{ + _operand->setBool(op1->getInt() == op2->getInt()); + } + */ + + _operand->setBool(ScValue::compare(op1, op2) == 0); + _stack->push(_operand); + break; + + case II_CMP_NE: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(true); + else if (op1->isNative() && op2->isNative()){ + _operand->setBool(op1->getNative() != op2->getNative()); + } + else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){ + _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())!=0); + } + else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() != op2->getFloat()); + } + else{ + _operand->setBool(op1->getInt() != op2->getInt()); + } + */ + + _operand->setBool(ScValue::compare(op1, op2) != 0); + _stack->push(_operand); + break; + + case II_CMP_L: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() < op2->getFloat()); + } + else _operand->setBool(op1->getInt() < op2->getInt()); + */ + + _operand->setBool(ScValue::compare(op1, op2) < 0); + _stack->push(_operand); + break; + + case II_CMP_G: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() > op2->getFloat()); + } + else _operand->setBool(op1->getInt() > op2->getInt()); + */ + + _operand->setBool(ScValue::compare(op1, op2) > 0); + _stack->push(_operand); + break; + + case II_CMP_LE: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() <= op2->getFloat()); + } + else _operand->setBool(op1->getInt() <= op2->getInt()); + */ + + _operand->setBool(ScValue::compare(op1, op2) <= 0); + _stack->push(_operand); + break; + + case II_CMP_GE: + op2 = _stack->pop(); + op1 = _stack->pop(); + + /* + if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){ + _operand->setBool(op1->getFloat() >= op2->getFloat()); + } + else _operand->setBool(op1->getInt() >= op2->getInt()); + */ + + _operand->setBool(ScValue::compare(op1, op2) >= 0); + _stack->push(_operand); + break; + + case II_CMP_STRICT_EQ: + op2 = _stack->pop(); + op1 = _stack->pop(); + + //_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat()); + _operand->setBool(ScValue::compareStrict(op1, op2) == 0); + _stack->push(_operand); + + break; + + case II_CMP_STRICT_NE: + op2 = _stack->pop(); + op1 = _stack->pop(); + + //_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat()); + _operand->setBool(ScValue::compareStrict(op1, op2) != 0); + _stack->push(_operand); + break; + + case II_DBG_LINE: { + int newLine = getDWORD(); + if (newLine != _currentLine) { + _currentLine = newLine; + } + break; + + } + default: + _gameRef->LOG(0, "Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x)\n", inst, _filename, _currentLine, _iP - sizeof(uint32)); + _state = SCRIPT_FINISHED; + ret = STATUS_FAILED; + } // switch(instruction) + + //delete op; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 ScScript::getFuncPos(const Common::String &name) { + for (uint32 i = 0; i < _numFunctions; i++) { + if (name == _functions[i].name) { + return _functions[i].pos; + } + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 ScScript::getMethodPos(const Common::String &name) { + for (uint32 i = 0; i < _numMethods; i++) { + if (name == _methods[i].name) { + return _methods[i].pos; + } + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScScript::getVar(char *name) { + ScValue *ret = NULL; + + // scope locals + if (_scopeStack->_sP >= 0) { + if (_scopeStack->getTop()->propExists(name)) { + ret = _scopeStack->getTop()->getProp(name); + } + } + + // script globals + if (ret == NULL) { + if (_globals->propExists(name)) { + ret = _globals->getProp(name); + } + } + + // engine globals + if (ret == NULL) { + if (_engine->_globals->propExists(name)) { + ret = _engine->_globals->getProp(name); + } + } + + if (ret == NULL) { + //RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", name); + _gameRef->LOG(0, "Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d)", name, _filename, _currentLine); + ScValue *val = new ScValue(_gameRef); + ScValue *scope = _scopeStack->getTop(); + if (scope) { + scope->setProp(name, val); + ret = _scopeStack->getTop()->getProp(name); + } else { + _globals->setProp(name, val); + ret = _globals->getProp(name); + } + delete val; + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::waitFor(BaseObject *object) { + if (_unbreakable) { + runtimeError("Script cannot be interrupted."); + return STATUS_OK; + } + + _state = SCRIPT_WAITING; + _waitObject = object; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::waitForExclusive(BaseObject *object) { + _engine->resetObject(object); + return waitFor(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::sleep(uint32 duration) { + if (_unbreakable) { + runtimeError("Script cannot be interrupted."); + return STATUS_OK; + } + + _state = SCRIPT_SLEEPING; + if (_gameRef->_state == GAME_FROZEN) { + _waitTime = g_system->getMillis() + duration; + _waitFrozen = true; + } else { + _waitTime = _gameRef->_timer + duration; + _waitFrozen = false; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::finish(bool includingThreads) { + if (_state != SCRIPT_FINISHED && includingThreads) { + _state = SCRIPT_FINISHED; + finishThreads(); + } else { + _state = SCRIPT_FINISHED; + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::run() { + _state = SCRIPT_RUNNING; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////// +void ScScript::runtimeError(const char *fmt, ...) { + char buff[256]; + va_list va; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + _gameRef->LOG(0, "Runtime error. Script '%s', line %d", _filename, _currentLine); + _gameRef->LOG(0, " %s", buff); + + if (!_gameRef->_suppressScriptErrors) { + _gameRef->quickMessage("Script runtime error. View log for details."); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::persist(BasePersistenceManager *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + // buffer + if (persistMgr->getIsSaving()) { + if (_state != SCRIPT_PERSISTENT && _state != SCRIPT_FINISHED && _state != SCRIPT_THREAD_FINISHED) { + persistMgr->transfer(TMEMBER(_bufferSize)); + persistMgr->putBytes(_buffer, _bufferSize); + } else { + // don't save idle/finished scripts + int bufferSize = 0; + persistMgr->transfer(TMEMBER(bufferSize)); + } + } else { + persistMgr->transfer(TMEMBER(_bufferSize)); + if (_bufferSize > 0) { + _buffer = new byte[_bufferSize]; + persistMgr->getBytes(_buffer, _bufferSize); + _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize); + initTables(); + } else { + _buffer = NULL; + _scriptStream = NULL; + } + } + + 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->getIsSaving()) { + _tracingMode = false; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unbreakable) { + //if (_state!=SCRIPT_PERSISTENT) return NULL; + + uint32 pos = getEventPos(eventName); + if (!pos) { + return NULL; + } + + ScScript *thread = new ScScript(_gameRef, _engine); + if (thread) { + bool ret = thread->createThread(this, pos, eventName); + if (DID_SUCCEED(ret)) { + thread->_unbreakable = unbreakable; + _engine->_scripts.add(thread); + return thread; + } else { + delete thread; + return NULL; + } + } else { + return NULL; + } + +} + + +////////////////////////////////////////////////////////////////////////// +uint32 ScScript::getEventPos(const Common::String &name) { + for (int i = _numEvents - 1; i >= 0; i--) { + if (scumm_stricmp(name.c_str(), _events[i].name) == 0) { + return _events[i].pos; + } + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::canHandleEvent(const Common::String &eventName) { + return getEventPos(eventName) != 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::canHandleMethod(const Common::String &methodName) { + return getMethodPos(methodName) != 0; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::pause() { + if (_state == SCRIPT_PAUSED) { + _gameRef->LOG(0, "Attempting to pause a paused script ('%s', line %d)", _filename, _currentLine); + return STATUS_FAILED; + } + + if (!_freezable || _state == SCRIPT_PERSISTENT) { + return STATUS_OK; + } + + _origState = _state; + _state = SCRIPT_PAUSED; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::resume() { + if (_state != SCRIPT_PAUSED) { + return STATUS_OK; + } + + _state = _origState; + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +ScScript::TExternalFunction *ScScript::getExternal(char *name) { + for (uint32 i = 0; i < _numExternals; i++) { + if (strcmp(name, _externals[i].name) == 0) { + return &_externals[i]; + } + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function) { + + _gameRef->LOG(0, "External functions are not supported on this platform."); + stack->correctParams(0); + stack->pushNULL(); + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::copyParameters(ScStack *stack) { + int i; + int numParams = stack->pop()->getInt(); + for (i = numParams - 1; i >= 0; i--) { + _stack->push(stack->getAt(i)); + } + _stack->pushInt(numParams); + + for (i = 0; i < numParams; i++) { + stack->pop(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScScript::finishThreads() { + for (uint32 i = 0; i < _engine->_scripts.size(); i++) { + ScScript *scr = _engine->_scripts[i]; + if (scr->_thread && scr->_state != SCRIPT_FINISHED && scr->_owner == _owner && scumm_stricmp(scr->_filename, _filename) == 0) { + scr->finish(true); + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// IWmeDebugScript interface implementation +int ScScript::dbgGetLine() { + return _currentLine; +} + +////////////////////////////////////////////////////////////////////////// +const char *ScScript::dbgGetFilename() { + return _filename; +} + +////////////////////////////////////////////////////////////////////////// +void ScScript::afterLoad() { + if (_buffer == NULL) { + byte *buffer = _engine->getCompiledScript(_filename, &_bufferSize); + if (!buffer) { + _gameRef->LOG(0, "Error reinitializing script '%s' after load. Script will be terminated.", _filename); + _state = SCRIPT_ERROR; + return; + } + + _buffer = new byte [_bufferSize]; + memcpy(_buffer, buffer, _bufferSize); + + delete _scriptStream; + _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize); + + initTables(); + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h index 4daeacd026..0616bce58a 100644 --- a/engines/wintermute/base/scriptables/script.h +++ b/engines/wintermute/base/scriptables/script.h @@ -1,174 +1,174 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SCSCRIPT_H
-#define WINTERMUTE_SCSCRIPT_H
-
-
-#include "engines/wintermute/base/base.h"
-#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
-#include "engines/wintermute/coll_templ.h"
-
-namespace Wintermute {
-class BaseScriptHolder;
-class BaseObject;
-class ScEngine;
-class ScStack;
-class ScScript : public BaseClass {
-public:
- BaseArray<int> _breakpoints;
- bool _tracingMode;
-
- ScScript *_parentScript;
- bool _unbreakable;
- bool finishThreads();
- bool copyParameters(ScStack *stack);
-
- void afterLoad();
-private:
- ScValue *_operand;
- ScValue *_reg1;
-public:
- bool _freezable;
- bool resume();
- bool pause();
- bool canHandleEvent(const Common::String &eventName);
- bool canHandleMethod(const Common::String &methodName);
- bool createThread(ScScript *original, uint32 initIP, const Common::String &eventName);
- bool createMethodThread(ScScript *original, const Common::String &methodName);
- ScScript *invokeEventHandler(const Common::String &eventName, bool unbreakable = false);
- uint32 _timeSlice;
- DECLARE_PERSISTENT(ScScript, BaseClass)
- void runtimeError(const char *fmt, ...);
- bool run();
- bool finish(bool includingThreads = false);
- bool sleep(uint32 duration);
- bool waitForExclusive(BaseObject *object);
- bool waitFor(BaseObject *object);
- uint32 _waitTime;
- bool _waitFrozen;
- BaseObject *_waitObject;
- ScScript *_waitScript;
- TScriptState _state;
- TScriptState _origState;
- ScValue *getVar(char *name);
- uint32 getFuncPos(const Common::String &name);
- uint32 getEventPos(const Common::String &name);
- uint32 getMethodPos(const Common::String &name);
- typedef struct {
- uint32 magic;
- uint32 version;
- uint32 codeStart;
- uint32 funcTable;
- uint32 symbolTable;
- uint32 eventTable;
- uint32 externalsTable;
- uint32 methodTable;
- } TScriptHeader;
-
- TScriptHeader _header;
-
- typedef struct {
- char *name;
- uint32 pos;
- } TFunctionPos;
-
- typedef struct {
- char *name;
- uint32 pos;
- } TMethodPos;
-
- typedef struct {
- char *name;
- uint32 pos;
- } TEventPos;
-
- typedef struct {
- char *name;
- char *dll_name;
- TCallType call_type;
- TExternalType returns;
- int nu_params;
- TExternalType *params;
- } TExternalFunction;
-
-
- ScStack *_callStack;
- ScStack *_thisStack;
- ScStack *_scopeStack;
- ScStack *_stack;
- ScValue *_globals;
- ScEngine *_engine;
- int _currentLine;
- bool executeInstruction();
- char *getString();
- uint32 getDWORD();
- double getFloat();
- void cleanup();
- bool create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner);
- uint32 _iP;
-private:
- void readHeader();
- uint32 _bufferSize;
- byte *_buffer;
-public:
- Common::SeekableReadStream *_scriptStream;
- ScScript(BaseGame *inGame, ScEngine *engine);
- virtual ~ScScript();
- char *_filename;
- bool _thread;
- bool _methodThread;
- char *_threadEvent;
- BaseScriptHolder *_owner;
- ScScript::TExternalFunction *getExternal(char *name);
- bool externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function);
-private:
- char **_symbols;
- uint32 _numSymbols;
- TFunctionPos *_functions;
- TMethodPos *_methods;
- TEventPos *_events;
- uint32 _numExternals;
- TExternalFunction *_externals;
- uint32 _numFunctions;
- uint32 _numMethods;
- uint32 _numEvents;
-
- bool initScript();
- bool initTables();
-
-
-// IWmeDebugScript interface implementation
-public:
- virtual int dbgGetLine();
- virtual const char *dbgGetFilename();
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SCSCRIPT_H +#define WINTERMUTE_SCSCRIPT_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView +#include "engines/wintermute/coll_templ.h" + +namespace Wintermute { +class BaseScriptHolder; +class BaseObject; +class ScEngine; +class ScStack; +class ScScript : public BaseClass { +public: + BaseArray<int> _breakpoints; + bool _tracingMode; + + ScScript *_parentScript; + bool _unbreakable; + bool finishThreads(); + bool copyParameters(ScStack *stack); + + void afterLoad(); +private: + ScValue *_operand; + ScValue *_reg1; +public: + bool _freezable; + bool resume(); + bool pause(); + bool canHandleEvent(const Common::String &eventName); + bool canHandleMethod(const Common::String &methodName); + bool createThread(ScScript *original, uint32 initIP, const Common::String &eventName); + bool createMethodThread(ScScript *original, const Common::String &methodName); + ScScript *invokeEventHandler(const Common::String &eventName, bool unbreakable = false); + uint32 _timeSlice; + DECLARE_PERSISTENT(ScScript, BaseClass) + void runtimeError(const char *fmt, ...); + bool run(); + bool finish(bool includingThreads = false); + bool sleep(uint32 duration); + bool waitForExclusive(BaseObject *object); + bool waitFor(BaseObject *object); + uint32 _waitTime; + bool _waitFrozen; + BaseObject *_waitObject; + ScScript *_waitScript; + TScriptState _state; + TScriptState _origState; + ScValue *getVar(char *name); + uint32 getFuncPos(const Common::String &name); + uint32 getEventPos(const Common::String &name); + uint32 getMethodPos(const Common::String &name); + typedef struct { + uint32 magic; + uint32 version; + uint32 codeStart; + uint32 funcTable; + uint32 symbolTable; + uint32 eventTable; + uint32 externalsTable; + uint32 methodTable; + } TScriptHeader; + + TScriptHeader _header; + + typedef struct { + char *name; + uint32 pos; + } TFunctionPos; + + typedef struct { + char *name; + uint32 pos; + } TMethodPos; + + typedef struct { + char *name; + uint32 pos; + } TEventPos; + + typedef struct { + char *name; + char *dll_name; + TCallType call_type; + TExternalType returns; + int nu_params; + TExternalType *params; + } TExternalFunction; + + + ScStack *_callStack; + ScStack *_thisStack; + ScStack *_scopeStack; + ScStack *_stack; + ScValue *_globals; + ScEngine *_engine; + int _currentLine; + bool executeInstruction(); + char *getString(); + uint32 getDWORD(); + double getFloat(); + void cleanup(); + bool create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner); + uint32 _iP; +private: + void readHeader(); + uint32 _bufferSize; + byte *_buffer; +public: + Common::SeekableReadStream *_scriptStream; + ScScript(BaseGame *inGame, ScEngine *engine); + virtual ~ScScript(); + char *_filename; + bool _thread; + bool _methodThread; + char *_threadEvent; + BaseScriptHolder *_owner; + ScScript::TExternalFunction *getExternal(char *name); + bool externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function); +private: + char **_symbols; + uint32 _numSymbols; + TFunctionPos *_functions; + TMethodPos *_methods; + TEventPos *_events; + uint32 _numExternals; + TExternalFunction *_externals; + uint32 _numFunctions; + uint32 _numMethods; + uint32 _numEvents; + + bool initScript(); + bool initTables(); + + +// IWmeDebugScript interface implementation +public: + virtual int dbgGetLine(); + virtual const char *dbgGetFilename(); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp index 02f6080958..20e2ccadd1 100644 --- a/engines/wintermute/base/scriptables/script_engine.cpp +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -1,610 +1,610 @@ -/* 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.
-
- * 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.
-
- * 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/base/scriptables/script_engine.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_ext_math.h"
-#include "engines/wintermute/base/base_engine.h"
-#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/sound/base_sound.h"
-#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/utils/utils.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(ScEngine, true)
-
-#define COMPILER_DLL "dcscomp.dll"
-//////////////////////////////////////////////////////////////////////////
-ScEngine::ScEngine(BaseGame *inGame) : BaseClass(inGame) {
- _gameRef->LOG(0, "Initializing scripting engine...");
-
- if (_compilerAvailable) {
- _gameRef->LOG(0, " Script compiler bound successfuly");
- } else {
- _gameRef->LOG(0, " Script compiler is NOT available");
- }
-
- _globals = new ScValue(_gameRef);
-
-
- // register 'Game' as global variable
- if (!_globals->propExists("Game")) {
- ScValue val(_gameRef);
- val.setNative(_gameRef, true);
- _globals->setProp("Game", &val);
- }
-
- // register 'Math' as global variable
- if (!_globals->propExists("Math")) {
- ScValue val(_gameRef);
- val.setNative(_gameRef->_mathClass, true);
- _globals->setProp("Math", &val);
- }
-
- // prepare script cache
- for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
- _cachedScripts[i] = NULL;
- }
-
- _currentScript = NULL;
-
- _isProfiling = false;
- _profilingStartTime = 0;
-
- //EnableProfiling();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScEngine::~ScEngine() {
- _gameRef->LOG(0, "Shutting down scripting engine");
-
- disableProfiling();
-
- cleanup();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::cleanup() {
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (!_scripts[i]->_thread && _scripts[i]->_owner) {
- _scripts[i]->_owner->removeScript(_scripts[i]);
- }
- delete _scripts[i];
- _scripts.remove_at(i);
- i--;
- }
-
- _scripts.clear();
-
- delete _globals;
- _globals = NULL;
-
- emptyScriptCache();
-
- _currentScript = NULL; // ref only
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-byte *ScEngine::loadFile(void *data, char *filename, uint32 *size) {
- return BaseFileManager::getEngineInstance()->readWholeFile(filename, size);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::closeFile(void *data, byte *buffer) {
- delete[] buffer;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::parseElement(void *data, int line, int type, void *elementData) {
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) {
- byte *compBuffer;
- uint32 compSize;
-
- // get script from cache
- compBuffer = getCompiledScript(filename, &compSize);
- if (!compBuffer) {
- return NULL;
- }
-
- // add new script
- ScScript *script = new ScScript(_gameRef, this);
- bool ret = script->create(filename, compBuffer, compSize, owner);
- if (DID_FAIL(ret)) {
- _gameRef->LOG(ret, "Error running script '%s'...", filename);
- delete script;
- return NULL;
- } else {
- // publish the "self" pseudo-variable
- ScValue val(_gameRef);
- if (owner) {
- val.setNative(owner, true);
- } else {
- val.setNULL();
- }
-
- script->_globals->setProp("self", &val);
- script->_globals->setProp("this", &val);
-
- _scripts.add(script);
-
- return script;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache) {
- // is script in cache?
- if (!ignoreCache) {
- for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
- if (_cachedScripts[i] && scumm_stricmp(_cachedScripts[i]->_filename.c_str(), filename) == 0) {
- _cachedScripts[i]->_timestamp = g_system->getMillis();
- *outSize = _cachedScripts[i]->_size;
- return _cachedScripts[i]->_buffer;
- }
- }
- }
-
- // nope, load it
- byte *compBuffer;
- uint32 compSize;
-
- uint32 size;
-
- byte *buffer = BaseEngine::instance().getFileManager()->readWholeFile(filename, &size);
- if (!buffer) {
- _gameRef->LOG(0, "ScEngine::GetCompiledScript - error opening script '%s'", filename);
- return NULL;
- }
-
- // needs to be compiled?
- if (FROM_LE_32(*(uint32 *)buffer) == SCRIPT_MAGIC) {
- compBuffer = buffer;
- compSize = size;
- } else {
- if (!_compilerAvailable) {
- _gameRef->LOG(0, "ScEngine::GetCompiledScript - script '%s' needs to be compiled but compiler is not available", filename);
- delete[] buffer;
- return NULL;
- }
- // This code will never be called, since _compilerAvailable is const false.
- // It's only here in the event someone would want to reinclude the compiler.
- error("Script needs compilation, ScummVM does not contain a WME compiler");
- }
-
- byte *ret = NULL;
-
- // add script to cache
- CScCachedScript *cachedScript = new CScCachedScript(filename, compBuffer, compSize);
- if (cachedScript) {
- int index = 0;
- uint32 minTime = g_system->getMillis();
- for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
- if (_cachedScripts[i] == NULL) {
- index = i;
- break;
- } else if (_cachedScripts[i]->_timestamp <= minTime) {
- minTime = _cachedScripts[i]->_timestamp;
- index = i;
- }
- }
-
- if (_cachedScripts[index] != NULL) {
- delete _cachedScripts[index];
- }
- _cachedScripts[index] = cachedScript;
-
- ret = cachedScript->_buffer;
- *outSize = cachedScript->_size;
- }
-
-
- // cleanup
- delete[] buffer;
-
- return ret;
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::tick() {
- if (_scripts.size() == 0) {
- return STATUS_OK;
- }
-
-
- // resolve waiting scripts
- for (uint32 i = 0; i < _scripts.size(); i++) {
-
- switch (_scripts[i]->_state) {
- case SCRIPT_WAITING: {
- /*
- bool obj_found=false;
- for(int j=0; j<_gameRef->_regObjects.size(); j++)
- {
- if (_gameRef->_regObjects[j] == _scripts[i]->_waitObject)
- {
- if (_gameRef->_regObjects[j]->IsReady()) _scripts[i]->Run();
- obj_found = true;
- break;
- }
- }
- if (!obj_found) _scripts[i]->finish(); // _waitObject no longer exists
- */
- if (_gameRef->validObject(_scripts[i]->_waitObject)) {
- if (_scripts[i]->_waitObject->isReady()) {
- _scripts[i]->run();
- }
- } else {
- _scripts[i]->finish();
- }
- break;
- }
-
- case SCRIPT_SLEEPING: {
- if (_scripts[i]->_waitFrozen) {
- if (_scripts[i]->_waitTime <= g_system->getMillis()) {
- _scripts[i]->run();
- }
- } else {
- if (_scripts[i]->_waitTime <= _gameRef->_timer) {
- _scripts[i]->run();
- }
- }
- break;
- }
-
- case SCRIPT_WAITING_SCRIPT: {
- if (!isValidScript(_scripts[i]->_waitScript) || _scripts[i]->_waitScript->_state == SCRIPT_ERROR) {
- // fake return value
- _scripts[i]->_stack->pushNULL();
- _scripts[i]->_waitScript = NULL;
- _scripts[i]->run();
- } else {
- if (_scripts[i]->_waitScript->_state == SCRIPT_THREAD_FINISHED) {
- // copy return value
- _scripts[i]->_stack->push(_scripts[i]->_waitScript->_stack->pop());
- _scripts[i]->run();
- _scripts[i]->_waitScript->finish();
- _scripts[i]->_waitScript = NULL;
- }
- }
- break;
- }
- default:
- break;
- } // switch
- } // for each script
-
-
- // execute scripts
- for (uint32 i = 0; i < _scripts.size(); i++) {
-
- // skip paused scripts
- if (_scripts[i]->_state == SCRIPT_PAUSED) {
- continue;
- }
-
- // time sliced script
- if (_scripts[i]->_timeSlice > 0) {
- uint32 startTime = g_system->getMillis();
- while (_scripts[i]->_state == SCRIPT_RUNNING && g_system->getMillis() - startTime < _scripts[i]->_timeSlice) {
- _currentScript = _scripts[i];
- _scripts[i]->executeInstruction();
- }
- if (_isProfiling && _scripts[i]->_filename) {
- addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime);
- }
- }
-
- // normal script
- else {
- uint32 startTime = 0;
- bool isProfiling = _isProfiling;
- if (isProfiling) {
- startTime = g_system->getMillis();
- }
-
- while (_scripts[i]->_state == SCRIPT_RUNNING) {
- _currentScript = _scripts[i];
- _scripts[i]->executeInstruction();
- }
- if (isProfiling && _scripts[i]->_filename) {
- addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime);
- }
- }
- _currentScript = NULL;
- }
-
- removeFinishedScripts();
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::tickUnbreakable() {
- // execute unbreakable scripts
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (!_scripts[i]->_unbreakable) {
- continue;
- }
-
- while (_scripts[i]->_state == SCRIPT_RUNNING) {
- _currentScript = _scripts[i];
- _scripts[i]->executeInstruction();
- }
- _scripts[i]->finish();
- _currentScript = NULL;
- }
- removeFinishedScripts();
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::removeFinishedScripts() {
- // remove finished scripts
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR) {
- if (!_scripts[i]->_thread && _scripts[i]->_owner) {
- _scripts[i]->_owner->removeScript(_scripts[i]);
- }
-
- delete _scripts[i];
- _scripts.remove_at(i);
- i--;
- }
- }
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-int ScEngine::getNumScripts(int *running, int *waiting, int *persistent) {
- int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0;
-
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i]->_state == SCRIPT_FINISHED) {
- continue;
- }
- switch (_scripts[i]->_state) {
- case SCRIPT_RUNNING:
- case SCRIPT_SLEEPING:
- case SCRIPT_PAUSED:
- numRunning++;
- break;
- case SCRIPT_WAITING:
- numWaiting++;
- break;
- case SCRIPT_PERSISTENT:
- numPersistent++;
- break;
- default:
- warning("ScEngine::GetNumScripts - unhandled enum");
- break;
- }
- numTotal++;
- }
- if (running) {
- *running = numRunning;
- }
- if (waiting) {
- *waiting = numWaiting;
- }
- if (persistent) {
- *persistent = numPersistent;
- }
-
- return numTotal;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::emptyScriptCache() {
- for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
- if (_cachedScripts[i]) {
- delete _cachedScripts[i];
- _cachedScripts[i] = NULL;
- }
- }
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::resetObject(BaseObject *Object) {
- // terminate all scripts waiting for this object
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i]->_state == SCRIPT_WAITING && _scripts[i]->_waitObject == Object) {
- if (!_gameRef->_compatKillMethodThreads) {
- resetScript(_scripts[i]);
- }
-
- bool isThread = _scripts[i]->_methodThread || _scripts[i]->_thread;
- _scripts[i]->finish(!isThread); // 1.9b1 - top-level script kills its threads as well
- }
- }
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::resetScript(ScScript *script) {
- // terminate all scripts waiting for this script
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) {
- _scripts[i]->finish();
- }
- }
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::persist(BasePersistenceManager *persistMgr) {
- if (!persistMgr->getIsSaving()) {
- cleanup();
- }
-
- persistMgr->transfer(TMEMBER(_gameRef));
- persistMgr->transfer(TMEMBER(_currentScript));
- persistMgr->transfer(TMEMBER(_globals));
- _scripts.persist(persistMgr);
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::editorCleanup() {
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) {
- delete _scripts[i];
- _scripts.remove_at(i);
- i--;
- }
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::pauseAll() {
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i] != _currentScript) {
- _scripts[i]->pause();
- }
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::resumeAll() {
- for (uint32 i = 0; i < _scripts.size(); i++) {
- _scripts[i]->resume();
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::isValidScript(ScScript *script) {
- for (uint32 i = 0; i < _scripts.size(); i++) {
- if (_scripts[i] == script) {
- return true;
- }
- }
- return false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScEngine::clearGlobals(bool includingNatives) {
- _globals->CleanProps(includingNatives);
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::addScriptTime(const char *filename, uint32 time) {
- if (!_isProfiling) {
- return;
- }
-
- AnsiString fileName = filename;
- fileName.toLowercase();
- _scriptTimes[fileName] += time;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::enableProfiling() {
- if (_isProfiling) {
- return;
- }
-
- // destroy old data, if any
- _scriptTimes.clear();
-
- _profilingStartTime = g_system->getMillis();
- _isProfiling = true;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::disableProfiling() {
- if (!_isProfiling) {
- return;
- }
-
- dumpStats();
- _isProfiling = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScEngine::dumpStats() {
- error("DumpStats not ported to ScummVM yet");
- /* uint32 totalTime = g_system->getMillis() - _profilingStartTime;
-
- typedef std::vector <std::pair<uint32, std::string> > TimeVector;
- TimeVector times;
-
- ScriptTimes::iterator it;
- for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) {
- times.push_back(std::pair<uint32, std::string> (it->_value, it->_key));
- }
- std::sort(times.begin(), times.end());
-
-
- TimeVector::reverse_iterator tit;
-
- _gameRef->LOG(0, "***** Script profiling information: *****");
- _gameRef->LOG(0, " %-40s %fs", "Total execution time", (float)totalTime / 1000);
-
- for (tit = times.rbegin(); tit != times.rend(); ++tit) {
- _gameRef->LOG(0, " %-40s %fs (%f%%)", tit->second.c_str(), (float)tit->first / 1000, (float)tit->first / (float)totalTime * 100);
- }*/
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/scriptables/script_engine.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_ext_math.h" +#include "engines/wintermute/base/base_engine.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/utils/utils.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(ScEngine, true) + +#define COMPILER_DLL "dcscomp.dll" +////////////////////////////////////////////////////////////////////////// +ScEngine::ScEngine(BaseGame *inGame) : BaseClass(inGame) { + _gameRef->LOG(0, "Initializing scripting engine..."); + + if (_compilerAvailable) { + _gameRef->LOG(0, " Script compiler bound successfuly"); + } else { + _gameRef->LOG(0, " Script compiler is NOT available"); + } + + _globals = new ScValue(_gameRef); + + + // register 'Game' as global variable + if (!_globals->propExists("Game")) { + ScValue val(_gameRef); + val.setNative(_gameRef, true); + _globals->setProp("Game", &val); + } + + // register 'Math' as global variable + if (!_globals->propExists("Math")) { + ScValue val(_gameRef); + val.setNative(_gameRef->_mathClass, true); + _globals->setProp("Math", &val); + } + + // prepare script cache + for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { + _cachedScripts[i] = NULL; + } + + _currentScript = NULL; + + _isProfiling = false; + _profilingStartTime = 0; + + //EnableProfiling(); +} + + +////////////////////////////////////////////////////////////////////////// +ScEngine::~ScEngine() { + _gameRef->LOG(0, "Shutting down scripting engine"); + + disableProfiling(); + + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::cleanup() { + for (uint32 i = 0; i < _scripts.size(); i++) { + if (!_scripts[i]->_thread && _scripts[i]->_owner) { + _scripts[i]->_owner->removeScript(_scripts[i]); + } + delete _scripts[i]; + _scripts.remove_at(i); + i--; + } + + _scripts.clear(); + + delete _globals; + _globals = NULL; + + emptyScriptCache(); + + _currentScript = NULL; // ref only + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +byte *ScEngine::loadFile(void *data, char *filename, uint32 *size) { + return BaseFileManager::getEngineInstance()->readWholeFile(filename, size); +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::closeFile(void *data, byte *buffer) { + delete[] buffer; +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::parseElement(void *data, int line, int type, void *elementData) { +} + + +////////////////////////////////////////////////////////////////////////// +ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) { + byte *compBuffer; + uint32 compSize; + + // get script from cache + compBuffer = getCompiledScript(filename, &compSize); + if (!compBuffer) { + return NULL; + } + + // add new script + ScScript *script = new ScScript(_gameRef, this); + bool ret = script->create(filename, compBuffer, compSize, owner); + if (DID_FAIL(ret)) { + _gameRef->LOG(ret, "Error running script '%s'...", filename); + delete script; + return NULL; + } else { + // publish the "self" pseudo-variable + ScValue val(_gameRef); + if (owner) { + val.setNative(owner, true); + } else { + val.setNULL(); + } + + script->_globals->setProp("self", &val); + script->_globals->setProp("this", &val); + + _scripts.add(script); + + return script; + } +} + + +////////////////////////////////////////////////////////////////////////// +byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache) { + // is script in cache? + if (!ignoreCache) { + for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { + if (_cachedScripts[i] && scumm_stricmp(_cachedScripts[i]->_filename.c_str(), filename) == 0) { + _cachedScripts[i]->_timestamp = g_system->getMillis(); + *outSize = _cachedScripts[i]->_size; + return _cachedScripts[i]->_buffer; + } + } + } + + // nope, load it + byte *compBuffer; + uint32 compSize; + + uint32 size; + + byte *buffer = BaseEngine::instance().getFileManager()->readWholeFile(filename, &size); + if (!buffer) { + _gameRef->LOG(0, "ScEngine::GetCompiledScript - error opening script '%s'", filename); + return NULL; + } + + // needs to be compiled? + if (FROM_LE_32(*(uint32 *)buffer) == SCRIPT_MAGIC) { + compBuffer = buffer; + compSize = size; + } else { + if (!_compilerAvailable) { + _gameRef->LOG(0, "ScEngine::GetCompiledScript - script '%s' needs to be compiled but compiler is not available", filename); + delete[] buffer; + return NULL; + } + // This code will never be called, since _compilerAvailable is const false. + // It's only here in the event someone would want to reinclude the compiler. + error("Script needs compilation, ScummVM does not contain a WME compiler"); + } + + byte *ret = NULL; + + // add script to cache + CScCachedScript *cachedScript = new CScCachedScript(filename, compBuffer, compSize); + if (cachedScript) { + int index = 0; + uint32 minTime = g_system->getMillis(); + for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { + if (_cachedScripts[i] == NULL) { + index = i; + break; + } else if (_cachedScripts[i]->_timestamp <= minTime) { + minTime = _cachedScripts[i]->_timestamp; + index = i; + } + } + + if (_cachedScripts[index] != NULL) { + delete _cachedScripts[index]; + } + _cachedScripts[index] = cachedScript; + + ret = cachedScript->_buffer; + *outSize = cachedScript->_size; + } + + + // cleanup + delete[] buffer; + + return ret; +} + + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::tick() { + if (_scripts.size() == 0) { + return STATUS_OK; + } + + + // resolve waiting scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + + switch (_scripts[i]->_state) { + case SCRIPT_WAITING: { + /* + bool obj_found=false; + for(int j=0; j<_gameRef->_regObjects.size(); j++) + { + if (_gameRef->_regObjects[j] == _scripts[i]->_waitObject) + { + if (_gameRef->_regObjects[j]->IsReady()) _scripts[i]->Run(); + obj_found = true; + break; + } + } + if (!obj_found) _scripts[i]->finish(); // _waitObject no longer exists + */ + if (_gameRef->validObject(_scripts[i]->_waitObject)) { + if (_scripts[i]->_waitObject->isReady()) { + _scripts[i]->run(); + } + } else { + _scripts[i]->finish(); + } + break; + } + + case SCRIPT_SLEEPING: { + if (_scripts[i]->_waitFrozen) { + if (_scripts[i]->_waitTime <= g_system->getMillis()) { + _scripts[i]->run(); + } + } else { + if (_scripts[i]->_waitTime <= _gameRef->_timer) { + _scripts[i]->run(); + } + } + break; + } + + case SCRIPT_WAITING_SCRIPT: { + if (!isValidScript(_scripts[i]->_waitScript) || _scripts[i]->_waitScript->_state == SCRIPT_ERROR) { + // fake return value + _scripts[i]->_stack->pushNULL(); + _scripts[i]->_waitScript = NULL; + _scripts[i]->run(); + } else { + if (_scripts[i]->_waitScript->_state == SCRIPT_THREAD_FINISHED) { + // copy return value + _scripts[i]->_stack->push(_scripts[i]->_waitScript->_stack->pop()); + _scripts[i]->run(); + _scripts[i]->_waitScript->finish(); + _scripts[i]->_waitScript = NULL; + } + } + break; + } + default: + break; + } // switch + } // for each script + + + // execute scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + + // skip paused scripts + if (_scripts[i]->_state == SCRIPT_PAUSED) { + continue; + } + + // time sliced script + if (_scripts[i]->_timeSlice > 0) { + uint32 startTime = g_system->getMillis(); + while (_scripts[i]->_state == SCRIPT_RUNNING && g_system->getMillis() - startTime < _scripts[i]->_timeSlice) { + _currentScript = _scripts[i]; + _scripts[i]->executeInstruction(); + } + if (_isProfiling && _scripts[i]->_filename) { + addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime); + } + } + + // normal script + else { + uint32 startTime = 0; + bool isProfiling = _isProfiling; + if (isProfiling) { + startTime = g_system->getMillis(); + } + + while (_scripts[i]->_state == SCRIPT_RUNNING) { + _currentScript = _scripts[i]; + _scripts[i]->executeInstruction(); + } + if (isProfiling && _scripts[i]->_filename) { + addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime); + } + } + _currentScript = NULL; + } + + removeFinishedScripts(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::tickUnbreakable() { + // execute unbreakable scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + if (!_scripts[i]->_unbreakable) { + continue; + } + + while (_scripts[i]->_state == SCRIPT_RUNNING) { + _currentScript = _scripts[i]; + _scripts[i]->executeInstruction(); + } + _scripts[i]->finish(); + _currentScript = NULL; + } + removeFinishedScripts(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::removeFinishedScripts() { + // remove finished scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR) { + if (!_scripts[i]->_thread && _scripts[i]->_owner) { + _scripts[i]->_owner->removeScript(_scripts[i]); + } + + delete _scripts[i]; + _scripts.remove_at(i); + i--; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int ScEngine::getNumScripts(int *running, int *waiting, int *persistent) { + int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0; + + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i]->_state == SCRIPT_FINISHED) { + continue; + } + switch (_scripts[i]->_state) { + case SCRIPT_RUNNING: + case SCRIPT_SLEEPING: + case SCRIPT_PAUSED: + numRunning++; + break; + case SCRIPT_WAITING: + numWaiting++; + break; + case SCRIPT_PERSISTENT: + numPersistent++; + break; + default: + warning("ScEngine::GetNumScripts - unhandled enum"); + break; + } + numTotal++; + } + if (running) { + *running = numRunning; + } + if (waiting) { + *waiting = numWaiting; + } + if (persistent) { + *persistent = numPersistent; + } + + return numTotal; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::emptyScriptCache() { + for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) { + if (_cachedScripts[i]) { + delete _cachedScripts[i]; + _cachedScripts[i] = NULL; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::resetObject(BaseObject *Object) { + // terminate all scripts waiting for this object + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i]->_state == SCRIPT_WAITING && _scripts[i]->_waitObject == Object) { + if (!_gameRef->_compatKillMethodThreads) { + resetScript(_scripts[i]); + } + + bool isThread = _scripts[i]->_methodThread || _scripts[i]->_thread; + _scripts[i]->finish(!isThread); // 1.9b1 - top-level script kills its threads as well + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::resetScript(ScScript *script) { + // terminate all scripts waiting for this script + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) { + _scripts[i]->finish(); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::persist(BasePersistenceManager *persistMgr) { + if (!persistMgr->getIsSaving()) { + cleanup(); + } + + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_currentScript)); + persistMgr->transfer(TMEMBER(_globals)); + _scripts.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::editorCleanup() { + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) { + delete _scripts[i]; + _scripts.remove_at(i); + i--; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::pauseAll() { + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i] != _currentScript) { + _scripts[i]->pause(); + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::resumeAll() { + for (uint32 i = 0; i < _scripts.size(); i++) { + _scripts[i]->resume(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::isValidScript(ScScript *script) { + for (uint32 i = 0; i < _scripts.size(); i++) { + if (_scripts[i] == script) { + return true; + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool ScEngine::clearGlobals(bool includingNatives) { + _globals->CleanProps(includingNatives); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void ScEngine::addScriptTime(const char *filename, uint32 time) { + if (!_isProfiling) { + return; + } + + AnsiString fileName = filename; + fileName.toLowercase(); + _scriptTimes[fileName] += time; +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::enableProfiling() { + if (_isProfiling) { + return; + } + + // destroy old data, if any + _scriptTimes.clear(); + + _profilingStartTime = g_system->getMillis(); + _isProfiling = true; +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::disableProfiling() { + if (!_isProfiling) { + return; + } + + dumpStats(); + _isProfiling = false; +} + + +////////////////////////////////////////////////////////////////////////// +void ScEngine::dumpStats() { + error("DumpStats not ported to ScummVM yet"); + /* uint32 totalTime = g_system->getMillis() - _profilingStartTime; + + typedef std::vector <std::pair<uint32, std::string> > TimeVector; + TimeVector times; + + ScriptTimes::iterator it; + for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) { + times.push_back(std::pair<uint32, std::string> (it->_value, it->_key)); + } + std::sort(times.begin(), times.end()); + + + TimeVector::reverse_iterator tit; + + _gameRef->LOG(0, "***** Script profiling information: *****"); + _gameRef->LOG(0, " %-40s %fs", "Total execution time", (float)totalTime / 1000); + + for (tit = times.rbegin(); tit != times.rend(); ++tit) { + _gameRef->LOG(0, " %-40s %fs (%f%%)", tit->second.c_str(), (float)tit->first / 1000, (float)tit->first / (float)totalTime * 100); + }*/ +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_engine.h b/engines/wintermute/base/scriptables/script_engine.h index f526353368..1a023326eb 100644 --- a/engines/wintermute/base/scriptables/script_engine.h +++ b/engines/wintermute/base/scriptables/script_engine.h @@ -1,135 +1,135 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SCENGINE_H
-#define WINTERMUTE_SCENGINE_H
-
-#include "engines/wintermute/persistent.h"
-#include "engines/wintermute/coll_templ.h"
-#include "engines/wintermute/base/base.h"
-
-namespace Wintermute {
-
-#define MAX_CACHED_SCRIPTS 20
-class ScScript;
-class ScValue;
-class BaseObject;
-class BaseScriptHolder;
-class ScEngine : public BaseClass {
-public:
- class CScCachedScript {
- public:
- CScCachedScript(const char *filename, byte *buffer, uint32 size) {
- _timestamp = g_system->getMillis();
- _buffer = new byte[size];
- if (_buffer) {
- memcpy(_buffer, buffer, size);
- }
- _size = size;
- _filename = filename;
- };
-
- ~CScCachedScript() {
- if (_buffer) {
- delete[] _buffer;
- }
- };
-
- uint32 _timestamp;
- byte *_buffer;
- uint32 _size;
- Common::String _filename;
- };
-
- class CScBreakpoint {
- public:
- CScBreakpoint(const char *filename) {
- _filename = filename;
- }
-
- ~CScBreakpoint() {
- _lines.clear();
- }
-
- Common::String _filename;
- BaseArray<int> _lines;
- };
-
-public:
- bool clearGlobals(bool includingNatives = false);
- bool tickUnbreakable();
- bool removeFinishedScripts();
- bool isValidScript(ScScript *script);
-
- ScScript *_currentScript;
- bool resumeAll();
- bool pauseAll();
- void editorCleanup();
- bool resetObject(BaseObject *Object);
- bool resetScript(ScScript *script);
- bool emptyScriptCache();
- byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false);
- DECLARE_PERSISTENT(ScEngine, BaseClass)
- bool cleanup();
- int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL);
- bool tick();
- ScValue *_globals;
- ScScript *runScript(const char *filename, BaseScriptHolder *owner = NULL);
- static const bool _compilerAvailable = false;
-
- ScEngine(BaseGame *inGame);
- virtual ~ScEngine();
- static byte *loadFile(void *data, char *filename, uint32 *size);
- static void closeFile(void *data, byte *buffer);
- static void parseElement(void *data, int line, int type, void *elementData);
-
- BaseArray<ScScript *> _scripts;
-
- void enableProfiling();
- void disableProfiling();
- bool getIsProfiling() {
- return _isProfiling;
- }
-
- void addScriptTime(const char *filename, uint32 Time);
- void dumpStats();
-
-private:
-
- CScCachedScript *_cachedScripts[MAX_CACHED_SCRIPTS];
- bool _isProfiling;
- uint32 _profilingStartTime;
-
- typedef Common::HashMap<Common::String, uint32> ScriptTimes;
- ScriptTimes _scriptTimes;
-
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SCENGINE_H +#define WINTERMUTE_SCENGINE_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base.h" + +namespace Wintermute { + +#define MAX_CACHED_SCRIPTS 20 +class ScScript; +class ScValue; +class BaseObject; +class BaseScriptHolder; +class ScEngine : public BaseClass { +public: + class CScCachedScript { + public: + CScCachedScript(const char *filename, byte *buffer, uint32 size) { + _timestamp = g_system->getMillis(); + _buffer = new byte[size]; + if (_buffer) { + memcpy(_buffer, buffer, size); + } + _size = size; + _filename = filename; + }; + + ~CScCachedScript() { + if (_buffer) { + delete[] _buffer; + } + }; + + uint32 _timestamp; + byte *_buffer; + uint32 _size; + Common::String _filename; + }; + + class CScBreakpoint { + public: + CScBreakpoint(const char *filename) { + _filename = filename; + } + + ~CScBreakpoint() { + _lines.clear(); + } + + Common::String _filename; + BaseArray<int> _lines; + }; + +public: + bool clearGlobals(bool includingNatives = false); + bool tickUnbreakable(); + bool removeFinishedScripts(); + bool isValidScript(ScScript *script); + + ScScript *_currentScript; + bool resumeAll(); + bool pauseAll(); + void editorCleanup(); + bool resetObject(BaseObject *Object); + bool resetScript(ScScript *script); + bool emptyScriptCache(); + byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false); + DECLARE_PERSISTENT(ScEngine, BaseClass) + bool cleanup(); + int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL); + bool tick(); + ScValue *_globals; + ScScript *runScript(const char *filename, BaseScriptHolder *owner = NULL); + static const bool _compilerAvailable = false; + + ScEngine(BaseGame *inGame); + virtual ~ScEngine(); + static byte *loadFile(void *data, char *filename, uint32 *size); + static void closeFile(void *data, byte *buffer); + static void parseElement(void *data, int line, int type, void *elementData); + + BaseArray<ScScript *> _scripts; + + void enableProfiling(); + void disableProfiling(); + bool getIsProfiling() { + return _isProfiling; + } + + void addScriptTime(const char *filename, uint32 Time); + void dumpStats(); + +private: + + CScCachedScript *_cachedScripts[MAX_CACHED_SCRIPTS]; + bool _isProfiling; + uint32 _profilingStartTime; + + typedef Common::HashMap<Common::String, uint32> ScriptTimes; + ScriptTimes _scriptTimes; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp index c8d4f64ae9..5ed07f0da6 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -1,252 +1,252 @@ -/* 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.
-
- * 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.
-
- * 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/persistent.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/system/sys_instance.h"
-#include "engines/wintermute/base/scriptables/script_ext_array.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(SXArray, false)
-
-BaseScriptable *makeSXArray(BaseGame *inGame, ScStack *stack) {
- return new SXArray(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXArray::SXArray(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
- _length = 0;
- _values = new ScValue(_gameRef);
-
- int numParams = stack->pop()->getInt(0);
-
- if (numParams == 1) {
- _length = stack->pop()->getInt(0);
- } else if (numParams > 1) {
- _length = numParams;
- char paramName[20];
- for (int i = 0; i < numParams; i++) {
- sprintf(paramName, "%d", i);
- _values->setProp(paramName, stack->pop());
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXArray::SXArray(BaseGame *inGame) : BaseScriptable(inGame) {
- _length = 0;
- _values = new ScValue(_gameRef);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXArray::~SXArray() {
- delete _values;
- _values = NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-const char *SXArray::scToString() {
- char dummy[32768];
- strcpy(dummy, "");
- char propName[20];
- for (int i = 0; i < _length; i++) {
- sprintf(propName, "%d", i);
- ScValue *val = _values->getProp(propName);
- if (val) {
- if (strlen(dummy) + strlen(val->getString()) < 32768) {
- strcat(dummy, val->getString());
- }
- }
-
- if (i < _length - 1 && strlen(dummy) + 1 < 32768) {
- strcat(dummy, ",");
- }
- }
- _strRep = dummy;
- return _strRep.c_str();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // Push
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Push") == 0) {
- int numParams = stack->pop()->getInt(0);
- char paramName[20];
-
- for (int i = 0; i < numParams; i++) {
- _length++;
- sprintf(paramName, "%d", _length - 1);
- _values->setProp(paramName, stack->pop(), true);
- }
- stack->pushInt(_length);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Pop
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Pop") == 0) {
-
- stack->correctParams(0);
-
- if (_length > 0) {
- char paramName[20];
- sprintf(paramName, "%d", _length - 1);
- stack->push(_values->getProp(paramName));
- _values->deleteProp(paramName);
- _length--;
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXArray::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("array");
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Length
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
- _scValue->setInt(_length);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // [number]
- //////////////////////////////////////////////////////////////////////////
- else {
- char paramName[20];
- if (validNumber(name, paramName)) {
- return _values->getProp(paramName);
- } else {
- return _scValue;
- }
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXArray::scSetProperty(const char *name, ScValue *value) {
- //////////////////////////////////////////////////////////////////////////
- // Length
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Length") == 0) {
- int origLength = _length;
- _length = MAX(value->getInt(0), 0);
-
- char propName[20];
- if (_length < origLength) {
- for (int i = _length; i < origLength; i++) {
- sprintf(propName, "%d", i);
- _values->deleteProp(propName);
- }
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // [number]
- //////////////////////////////////////////////////////////////////////////
- else {
- char paramName[20];
- if (validNumber(name, paramName)) {
- int index = atoi(paramName);
- if (index >= _length) {
- _length = index + 1;
- }
- return _values->setProp(paramName, value);
- } else {
- return STATUS_FAILED;
- }
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXArray::persist(BasePersistenceManager *persistMgr) {
- BaseScriptable::persist(persistMgr);
-
- persistMgr->transfer(TMEMBER(_length));
- persistMgr->transfer(TMEMBER(_values));
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXArray::validNumber(const char *origStr, char *outStr) {
- bool isNumber = true;
- for (uint32 i = 0; i < strlen(origStr); i++) {
- if (!(origStr[i] >= '0' && origStr[i] <= '9')) {
- isNumber = false;
- break;
- }
- }
-
- if (isNumber) {
- int index = atoi(origStr);
- sprintf(outStr, "%d", index);
- return true;
- } else {
- return false;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool SXArray::push(ScValue *val) {
- char paramName[20];
- _length++;
- sprintf(paramName, "%d", _length - 1);
- _values->setProp(paramName, val, true);
- return STATUS_OK;
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/persistent.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/system/sys_instance.h" +#include "engines/wintermute/base/scriptables/script_ext_array.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(SXArray, false) + +BaseScriptable *makeSXArray(BaseGame *inGame, ScStack *stack) { + return new SXArray(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXArray::SXArray(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { + _length = 0; + _values = new ScValue(_gameRef); + + int numParams = stack->pop()->getInt(0); + + if (numParams == 1) { + _length = stack->pop()->getInt(0); + } else if (numParams > 1) { + _length = numParams; + char paramName[20]; + for (int i = 0; i < numParams; i++) { + sprintf(paramName, "%d", i); + _values->setProp(paramName, stack->pop()); + } + } +} + +////////////////////////////////////////////////////////////////////////// +SXArray::SXArray(BaseGame *inGame) : BaseScriptable(inGame) { + _length = 0; + _values = new ScValue(_gameRef); +} + + +////////////////////////////////////////////////////////////////////////// +SXArray::~SXArray() { + delete _values; + _values = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +const char *SXArray::scToString() { + char dummy[32768]; + strcpy(dummy, ""); + char propName[20]; + for (int i = 0; i < _length; i++) { + sprintf(propName, "%d", i); + ScValue *val = _values->getProp(propName); + if (val) { + if (strlen(dummy) + strlen(val->getString()) < 32768) { + strcat(dummy, val->getString()); + } + } + + if (i < _length - 1 && strlen(dummy) + 1 < 32768) { + strcat(dummy, ","); + } + } + _strRep = dummy; + return _strRep.c_str(); +} + + +////////////////////////////////////////////////////////////////////////// +bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // Push + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Push") == 0) { + int numParams = stack->pop()->getInt(0); + char paramName[20]; + + for (int i = 0; i < numParams; i++) { + _length++; + sprintf(paramName, "%d", _length - 1); + _values->setProp(paramName, stack->pop(), true); + } + stack->pushInt(_length); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Pop + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Pop") == 0) { + + stack->correctParams(0); + + if (_length > 0) { + char paramName[20]; + sprintf(paramName, "%d", _length - 1); + stack->push(_values->getProp(paramName)); + _values->deleteProp(paramName); + _length--; + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXArray::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("array"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Length + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Length") == 0) { + _scValue->setInt(_length); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // [number] + ////////////////////////////////////////////////////////////////////////// + else { + char paramName[20]; + if (validNumber(name, paramName)) { + return _values->getProp(paramName); + } else { + return _scValue; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXArray::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Length + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Length") == 0) { + int origLength = _length; + _length = MAX(value->getInt(0), 0); + + char propName[20]; + if (_length < origLength) { + for (int i = _length; i < origLength; i++) { + sprintf(propName, "%d", i); + _values->deleteProp(propName); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // [number] + ////////////////////////////////////////////////////////////////////////// + else { + char paramName[20]; + if (validNumber(name, paramName)) { + int index = atoi(paramName); + if (index >= _length) { + _length = index + 1; + } + return _values->setProp(paramName, value); + } else { + return STATUS_FAILED; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXArray::persist(BasePersistenceManager *persistMgr) { + BaseScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_length)); + persistMgr->transfer(TMEMBER(_values)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool SXArray::validNumber(const char *origStr, char *outStr) { + bool isNumber = true; + for (uint32 i = 0; i < strlen(origStr); i++) { + if (!(origStr[i] >= '0' && origStr[i] <= '9')) { + isNumber = false; + break; + } + } + + if (isNumber) { + int index = atoi(origStr); + sprintf(outStr, "%d", index); + return true; + } else { + return false; + } +} + +////////////////////////////////////////////////////////////////////////// +bool SXArray::push(ScValue *val) { + char paramName[20]; + _length++; + sprintf(paramName, "%d", _length - 1); + _values->setProp(paramName, val, true); + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h index 614f829950..d9805ef94f 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.h +++ b/engines/wintermute/base/scriptables/script_ext_array.h @@ -1,56 +1,56 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXARRAY_H
-#define WINTERMUTE_SXARRAY_H
-
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-class SXArray : public BaseScriptable {
-public:
- bool push(ScValue *val);
- bool validNumber(const char *origStr, char *outStr);
- DECLARE_PERSISTENT(SXArray, BaseScriptable)
- SXArray(BaseGame *inGame, ScStack *stack);
- SXArray(BaseGame *inGame);
- virtual ~SXArray();
- ScValue *scGetProperty(const char *name);
- bool scSetProperty(const char *name, ScValue *value);
- bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
- const char *scToString();
-private:
- int _length;
- ScValue *_values;
- Common::String _strRep;
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXARRAY_H +#define WINTERMUTE_SXARRAY_H + +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +class SXArray : public BaseScriptable { +public: + bool push(ScValue *val); + bool validNumber(const char *origStr, char *outStr); + DECLARE_PERSISTENT(SXArray, BaseScriptable) + SXArray(BaseGame *inGame, ScStack *stack); + SXArray(BaseGame *inGame); + virtual ~SXArray(); + ScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, ScValue *value); + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + const char *scToString(); +private: + int _length; + ScValue *_values; + Common::String _strRep; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp index 7726015081..11eead3b9c 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.cpp +++ b/engines/wintermute/base/scriptables/script_ext_date.cpp @@ -1,293 +1,293 @@ -/* 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.
-
- * 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.
-
- * 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/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script_ext_date.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(SXDate, false)
-
-BaseScriptable *makeSXDate(BaseGame *inGame, ScStack *stack) {
- return new SXDate(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXDate::SXDate(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
- stack->correctParams(6);
-
- memset(&_tm, 0, sizeof(_tm));
-
- ScValue *valYear = stack->pop();
- _tm.tm_year = valYear->getInt() - 1900;
- _tm.tm_mon = stack->pop()->getInt() - 1;
- _tm.tm_mday = stack->pop()->getInt();
- _tm.tm_hour = stack->pop()->getInt();
- _tm.tm_min = stack->pop()->getInt();
- _tm.tm_sec = stack->pop()->getInt();
-
- if (valYear->isNULL()) {
- g_system->getTimeAndDate(_tm);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXDate::~SXDate() {
-
-}
-
-//////////////////////////////////////////////////////////////////////////
-const char *SXDate::scToString() {
- // TODO: Make this more stringy, and less ISO 8601-like
- _strRep.format("%04d-%02d-%02d - %02d:%02d:%02d", _tm.tm_year, _tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec);
- return _strRep.c_str();
- //return asctime(&_tm);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // GetYear
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "GetYear") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_year + 1900);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetMonth
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetMonth") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_mon + 1);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetDate
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetDate") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_mday);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetHours
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetHours") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_hour);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetMinutes
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetMinutes") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_min);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetSeconds
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetSeconds") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_sec);
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GetWeekday
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetWeekday") == 0) {
- stack->correctParams(0);
- stack->pushInt(_tm.tm_wday);
- return STATUS_OK;
- }
-
-
- //////////////////////////////////////////////////////////////////////////
- // SetYear
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetYear") == 0) {
- stack->correctParams(1);
- _tm.tm_year = stack->pop()->getInt() - 1900;
- stack->pushNULL();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetMonth
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetMonth") == 0) {
- stack->correctParams(1);
- _tm.tm_mon = stack->pop()->getInt() - 1;
- stack->pushNULL();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetDate
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetDate") == 0) {
- stack->correctParams(1);
- _tm.tm_mday = stack->pop()->getInt();
- stack->pushNULL();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetHours
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetHours") == 0) {
- stack->correctParams(1);
- _tm.tm_hour = stack->pop()->getInt();
- stack->pushNULL();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetMinutes
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetMinutes") == 0) {
- stack->correctParams(1);
- _tm.tm_min = stack->pop()->getInt();
- stack->pushNULL();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetSeconds
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetSeconds") == 0) {
- stack->correctParams(1);
- _tm.tm_sec = stack->pop()->getInt();
- stack->pushNULL();
- return STATUS_OK;
- }
-
-
- //////////////////////////////////////////////////////////////////////////
- // SetCurrentTime
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetCurrentTime") == 0) {
- stack->correctParams(0);
- g_system->getTimeAndDate(_tm);
- stack->pushNULL();
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXDate::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("date");
- return _scValue;
- } else {
- return _scValue;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXDate::scSetProperty(const char *name, ScValue *value) {
- /*
- //////////////////////////////////////////////////////////////////////////
- // Name
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Name")==0){
- setName(value->getString());
- return STATUS_OK;
- }
-
- else*/ return STATUS_FAILED;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXDate::persist(BasePersistenceManager *persistMgr) {
-
- BaseScriptable::persist(persistMgr);
- persistMgr->transfer(TMEMBER(_tm.tm_year));
- persistMgr->transfer(TMEMBER(_tm.tm_mon));
- persistMgr->transfer(TMEMBER(_tm.tm_mday));
- persistMgr->transfer(TMEMBER(_tm.tm_hour));
- persistMgr->transfer(TMEMBER(_tm.tm_min));
- persistMgr->transfer(TMEMBER(_tm.tm_sec));
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-int SXDate::scCompare(BaseScriptable *Value) {
- TimeDate time1 = _tm;
- TimeDate time2 = ((SXDate *)Value)->_tm;
-
- if (time1.tm_year < time2.tm_year) {
- return -1;
- } else if (time1.tm_year == time2.tm_year) {
- if (time1.tm_mon < time2.tm_mon) {
- return -1;
- } else if (time1.tm_mon == time2.tm_mon) {
- if (time1.tm_mday < time2.tm_mday) {
- return -1;
- } else if (time1.tm_mday == time2.tm_mday) {
- if (time1.tm_hour < time2.tm_hour) {
- return -1;
- } else if (time1.tm_hour == time2.tm_hour) {
- if (time1.tm_min < time2.tm_min) {
- return -1;
- } else if (time1.tm_min == time2.tm_min) {
- if (time1.tm_sec < time2.tm_sec) {
- return -1;
- } else if (time1.tm_sec == time2.tm_sec) {
- return 0; // Equal
- } else {
- return 1; // Sec
- }
- } else {
- return 1; // Minute
- }
- } else {
- return 1; // Hour
- }
- } else {
- return 1; // Day
- }
- } else {
- return 1; // Month
- }
- } else {
- return 1; // Year
- }
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_ext_date.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(SXDate, false) + +BaseScriptable *makeSXDate(BaseGame *inGame, ScStack *stack) { + return new SXDate(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXDate::SXDate(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { + stack->correctParams(6); + + memset(&_tm, 0, sizeof(_tm)); + + ScValue *valYear = stack->pop(); + _tm.tm_year = valYear->getInt() - 1900; + _tm.tm_mon = stack->pop()->getInt() - 1; + _tm.tm_mday = stack->pop()->getInt(); + _tm.tm_hour = stack->pop()->getInt(); + _tm.tm_min = stack->pop()->getInt(); + _tm.tm_sec = stack->pop()->getInt(); + + if (valYear->isNULL()) { + g_system->getTimeAndDate(_tm); + } +} + + +////////////////////////////////////////////////////////////////////////// +SXDate::~SXDate() { + +} + +////////////////////////////////////////////////////////////////////////// +const char *SXDate::scToString() { + // TODO: Make this more stringy, and less ISO 8601-like + _strRep.format("%04d-%02d-%02d - %02d:%02d:%02d", _tm.tm_year, _tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec); + return _strRep.c_str(); + //return asctime(&_tm); +} + + +////////////////////////////////////////////////////////////////////////// +bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetYear + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetYear") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_year + 1900); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetMonth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetMonth") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_mon + 1); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetDate + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetDate") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_mday); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetHours + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHours") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_hour); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetMinutes + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetMinutes") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_min); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetSeconds + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetSeconds") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_sec); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // GetWeekday + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetWeekday") == 0) { + stack->correctParams(0); + stack->pushInt(_tm.tm_wday); + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // SetYear + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetYear") == 0) { + stack->correctParams(1); + _tm.tm_year = stack->pop()->getInt() - 1900; + stack->pushNULL(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetMonth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetMonth") == 0) { + stack->correctParams(1); + _tm.tm_mon = stack->pop()->getInt() - 1; + stack->pushNULL(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetDate + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetDate") == 0) { + stack->correctParams(1); + _tm.tm_mday = stack->pop()->getInt(); + stack->pushNULL(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetHours + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetHours") == 0) { + stack->correctParams(1); + _tm.tm_hour = stack->pop()->getInt(); + stack->pushNULL(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetMinutes + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetMinutes") == 0) { + stack->correctParams(1); + _tm.tm_min = stack->pop()->getInt(); + stack->pushNULL(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // SetSeconds + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetSeconds") == 0) { + stack->correctParams(1); + _tm.tm_sec = stack->pop()->getInt(); + stack->pushNULL(); + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // SetCurrentTime + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetCurrentTime") == 0) { + stack->correctParams(0); + g_system->getTimeAndDate(_tm); + stack->pushNULL(); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXDate::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("date"); + return _scValue; + } else { + return _scValue; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXDate::scSetProperty(const char *name, ScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name")==0){ + setName(value->getString()); + return STATUS_OK; + } + + else*/ return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool SXDate::persist(BasePersistenceManager *persistMgr) { + + BaseScriptable::persist(persistMgr); + persistMgr->transfer(TMEMBER(_tm.tm_year)); + persistMgr->transfer(TMEMBER(_tm.tm_mon)); + persistMgr->transfer(TMEMBER(_tm.tm_mday)); + persistMgr->transfer(TMEMBER(_tm.tm_hour)); + persistMgr->transfer(TMEMBER(_tm.tm_min)); + persistMgr->transfer(TMEMBER(_tm.tm_sec)); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int SXDate::scCompare(BaseScriptable *Value) { + TimeDate time1 = _tm; + TimeDate time2 = ((SXDate *)Value)->_tm; + + if (time1.tm_year < time2.tm_year) { + return -1; + } else if (time1.tm_year == time2.tm_year) { + if (time1.tm_mon < time2.tm_mon) { + return -1; + } else if (time1.tm_mon == time2.tm_mon) { + if (time1.tm_mday < time2.tm_mday) { + return -1; + } else if (time1.tm_mday == time2.tm_mday) { + if (time1.tm_hour < time2.tm_hour) { + return -1; + } else if (time1.tm_hour == time2.tm_hour) { + if (time1.tm_min < time2.tm_min) { + return -1; + } else if (time1.tm_min == time2.tm_min) { + if (time1.tm_sec < time2.tm_sec) { + return -1; + } else if (time1.tm_sec == time2.tm_sec) { + return 0; // Equal + } else { + return 1; // Sec + } + } else { + return 1; // Minute + } + } else { + return 1; // Hour + } + } else { + return 1; // Day + } + } else { + return 1; // Month + } + } else { + return 1; // Year + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h index 7cdf57e689..f6f04dd7e6 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.h +++ b/engines/wintermute/base/scriptables/script_ext_date.h @@ -1,54 +1,54 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXDATE_H
-#define WINTERMUTE_SXDATE_H
-
-#include "common/system.h"
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-class SXDate : public BaseScriptable {
-public:
- int scCompare(BaseScriptable *Value);
- DECLARE_PERSISTENT(SXDate, BaseScriptable)
- SXDate(BaseGame *inGame, ScStack *Stack);
- virtual ~SXDate();
- ScValue *scGetProperty(const char *name);
- bool scSetProperty(const char *name, ScValue *value);
- bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
- const char *scToString();
-private:
- TimeDate _tm;
- Common::String _strRep;
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXDATE_H +#define WINTERMUTE_SXDATE_H + +#include "common/system.h" +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +class SXDate : public BaseScriptable { +public: + int scCompare(BaseScriptable *Value); + DECLARE_PERSISTENT(SXDate, BaseScriptable) + SXDate(BaseGame *inGame, ScStack *Stack); + virtual ~SXDate(); + ScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, ScValue *value); + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + const char *scToString(); +private: + TimeDate _tm; + Common::String _strRep; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp index 53d551119d..ab574d464b 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.cpp +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -1,829 +1,829 @@ -/* 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.
-
- * 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.
-
- * 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/system/sys_class_registry.h"
-#include "engines/wintermute/system/sys_class.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script.h"
-#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/file/base_file.h"
-#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/platform_osystem.h"
-#include "engines/wintermute/base/scriptables/script_ext_file.h"
-
-// Note: This code is completely untested, as I have yet to find a game that uses SXFile.
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(SXFile, false)
-
-BaseScriptable *makeSXFile(BaseGame *inGame, ScStack *stack) {
- return new SXFile(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXFile::SXFile(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
- stack->correctParams(1);
- ScValue *val = stack->pop();
-
- _filename = NULL;
- if (!val->isNULL()) {
- BaseUtils::setString(&_filename, val->getString());
- }
-
- _readFile = NULL;
- _writeFile = NULL;
-
- _mode = 0;
- _textMode = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXFile::~SXFile() {
- cleanup();
-}
-
-//////////////////////////////////////////////////////////////////////////
-void SXFile::cleanup() {
- delete[] _filename;
- _filename = NULL;
- close();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void SXFile::close() {
- if (_readFile) {
- BaseFileManager::getEngineInstance()->closeFile(_readFile);
- _readFile = NULL;
- }
- if (_writeFile) {
- _writeFile->finalize();
- delete _writeFile;
- _writeFile = NULL;
- }
- _mode = 0;
- _textMode = false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-const char *SXFile::scToString() {
- if (_filename) {
- return _filename;
- } else {
- return "[file object]";
- }
-}
-
-#define FILE_BUFFER_SIZE 32768
-//////////////////////////////////////////////////////////////////////////
-bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // SetFilename
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "SetFilename") == 0) {
- stack->correctParams(1);
- const char *filename = stack->pop()->getString();
- cleanup();
- BaseUtils::setString(&_filename, filename);
- stack->pushNULL();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // OpenAsText / OpenAsBinary
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "OpenAsText") == 0 || strcmp(name, "OpenAsBinary") == 0) {
- stack->correctParams(1);
- close();
- _mode = stack->pop()->getInt(1);
- if (_mode < 1 || _mode > 3) {
- script->runtimeError("File.%s: invalid access mode. Setting read mode.", name);
- _mode = 1;
- }
- if (_mode == 1) {
- _readFile = BaseFileManager::getEngineInstance()->openFile(_filename);
- if (!_readFile) {
- //script->runtimeError("File.%s: Error opening file '%s' for reading.", Name, _filename);
- close();
- } else {
- _textMode = strcmp(name, "OpenAsText") == 0;
- }
- } else {
- if (strcmp(name, "OpenAsText") == 0) {
- if (_mode == 2) {
- _writeFile = openForWrite(_filename, false);
- } else {
- _writeFile = openForAppend(_filename, false);
- }
- } else {
- if (_mode == 2) {
- _writeFile = openForWrite(_filename, true);
- } else {
- _writeFile = openForAppend(_filename, true);
- }
- }
-
- if (!_writeFile) {
- //script->runtimeError("File.%s: Error opening file '%s' for writing.", Name, _filename);
- close();
- } else {
- _textMode = strcmp(name, "OpenAsText") == 0;
- }
- }
-
- if (_readFile || _writeFile) {
- stack->pushBool(true);
- } else {
- stack->pushBool(false);
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Close
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Close") == 0) {
- stack->correctParams(0);
- close();
- stack->pushNULL();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetPosition
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetPosition") == 0) {
- stack->correctParams(1);
- if (_mode == 0) {
- script->runtimeError("File.%s: File is not open", name);
- stack->pushBool(false);
- } else {
- int pos = stack->pop()->getInt();
- stack->pushBool(setPos(pos));
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Delete
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Delete") == 0) {
- stack->correctParams(0);
- close();
- error("SXFile-Method: \"Delete\" not supported");
- //stack->pushBool(BasePlatform::deleteFile(_filename) != false);
- stack->pushBool(false);
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Copy
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Copy") == 0) {
- stack->correctParams(2);
- /* const char *dest = */ stack->pop()->getString();
- /* bool overwrite = */ stack->pop()->getBool(true);
-
- close();
- error("SXFile-Method: Copy not supported");
- //stack->pushBool(BasePlatform::copyFile(_filename, Dest, !Overwrite) != false);
- stack->pushBool(false);
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadLine
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadLine") == 0) {
- stack->correctParams(0);
- if (!_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open in text mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- uint32 bufSize = FILE_BUFFER_SIZE;
- byte *buf = (byte *)malloc(bufSize);
- uint32 counter = 0;
- byte b;
- bool foundNewLine = false;
- bool ret = STATUS_FAILED;
- do {
- ret = _readFile->read(&b, 1);
- if (ret != 1) {
- break;
- }
-
- if (counter > bufSize) {
- buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
- bufSize += FILE_BUFFER_SIZE;
- }
- if (b == '\n') {
- buf[counter] = '\0';
- foundNewLine = true;
- break;
- } else if (b == 0x0D) {
- continue;
- } else {
- buf[counter] = b;
- counter++;
- }
- } while (DID_SUCCEED(ret));
-
- if (counter > bufSize) {
- buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
- bufSize += FILE_BUFFER_SIZE;
- }
- buf[counter] = '\0';
-
- if (!foundNewLine && counter == 0) {
- stack->pushNULL();
- } else {
- stack->pushString((char *)buf);
- }
-
- free(buf);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadText
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadText") == 0) {
- stack->correctParams(1);
- int textLen = stack->pop()->getInt();
-
- if (!_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open in text mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- uint32 bufSize = FILE_BUFFER_SIZE;
- byte *buf = (byte *)malloc(bufSize);
- uint32 counter = 0;
- byte b;
-
- bool ret = STATUS_FAILED;
- while (counter < (uint32)textLen) {
- ret = _readFile->read(&b, 1);
- if (ret != 1) {
- break;
- }
-
- if (counter > bufSize) {
- buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
- bufSize += FILE_BUFFER_SIZE;
- }
- if (b == 0x0D) {
- continue;
- } else {
- buf[counter] = b;
- counter++;
- }
- }
-
- if (counter > bufSize) {
- buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
- bufSize += FILE_BUFFER_SIZE;
- }
- buf[counter] = '\0';
-
- if (textLen > 0 && counter == 0) {
- stack->pushNULL();
- } else {
- stack->pushString((char *)buf);
- }
-
- free(buf);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteLine / WriteText
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteLine") == 0 || strcmp(name, "WriteText") == 0) {
- stack->correctParams(1);
- const char *line = stack->pop()->getString();
- if (!_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in text mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- Common::String writeLine;
- if (strcmp(name, "WriteLine") == 0) {
- writeLine = Common::String::format("%s\n", line);
- } else {
- writeLine = Common::String::format("%s", line);
- }
- _writeFile->writeString(writeLine);
- _writeFile->writeByte(0);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- //////////////////////////////////////////////////////////////////////////
- // ReadBool
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadBool") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- bool val;
- if (_readFile->read(&val, sizeof(bool)) == sizeof(bool)) {
- stack->pushBool(val);
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadByte
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadByte") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- byte val = _readFile->readByte();
- if (!_readFile->err()) {
- stack->pushInt(val);
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadShort
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadShort") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- int16 val = _readFile->readSint16LE();
- if (!_readFile->err()) {
- stack->pushInt(65536 + val);
- } else {
- stack->pushNULL();
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadInt / ReadLong
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadInt") == 0 || strcmp(name, "ReadLong") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- int32 val = _readFile->readSint32LE();
- if (!_readFile->err()) {
- stack->pushInt(val);
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadFloat
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadFloat") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- float val;
- (*(uint32 *)&val) = _readFile->readUint32LE();
- if (!_readFile->err()) {
- stack->pushFloat(val);
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadDouble
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadDouble") == 0) { // TODO: Solve reading a 8 byte double.
- error("SXFile::ReadDouble - Not endian safe yet");
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- double val;
- if (_readFile->read(&val, sizeof(double)) == sizeof(double)) {
- stack->pushFloat(val);
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ReadString
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ReadString") == 0) {
- stack->correctParams(0);
- if (_textMode || !_readFile) {
- script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
- stack->pushNULL();
- return STATUS_OK;
- }
- uint32 size = _readFile->readUint32LE();
- if (!_readFile->err()) {
- byte *str = new byte[size + 1];
- if (str) {
- if (_readFile->read(str, size) == size) {
- str[size] = '\0';
- stack->pushString((char *)str);
- }
- delete[] str;
- } else {
- stack->pushNULL();
- }
- } else {
- stack->pushNULL();
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteBool
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteBool") == 0) {
- stack->correctParams(1);
- bool val = stack->pop()->getBool();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- _writeFile->writeByte(val);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteByte
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteByte") == 0) {
- stack->correctParams(1);
- byte val = stack->pop()->getInt();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- _writeFile->writeByte(val);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteShort
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteShort") == 0) {
- stack->correctParams(1);
- int16 val = stack->pop()->getInt();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- _writeFile->writeSint16LE(val);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteInt / WriteLong
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteInt") == 0 || strcmp(name, "WriteLong") == 0) {
- stack->correctParams(1);
- int32 val = stack->pop()->getInt();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- _writeFile->writeSint32LE(val);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteFloat
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteFloat") == 0) {
- stack->correctParams(1);
- float val = stack->pop()->getFloat();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- uint32 *ptr = (uint32 *)&val;
- _writeFile->writeUint32LE(*ptr);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteDouble
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteDouble") == 0) {
- error("SXFile::WriteDouble - Not endian safe yet");
- stack->correctParams(1);
- /* double val = */ stack->pop()->getFloat();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
- //fwrite(&val, sizeof(val), 1, (FILE *)_writeFile);
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // WriteString
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "WriteString") == 0) {
- stack->correctParams(1);
- const char *val = stack->pop()->getString();
-
- if (_textMode || !_writeFile) {
- script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
- stack->pushBool(false);
- return STATUS_OK;
- }
-
- uint32 size = strlen(val);
- _writeFile->writeUint32LE(size);
- _writeFile->writeString(val);
-
- stack->pushBool(true);
-
- return STATUS_OK;
- } else {
- return BaseScriptable::scCallMethod(script, stack, thisStack, name);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXFile::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type (RO)
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("file");
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Filename (RO)
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Filename") == 0) {
- _scValue->setString(_filename);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Position (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Position") == 0) {
- _scValue->setInt(getPos());
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Length (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
- _scValue->setInt(getLength());
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // TextMode (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "TextMode") == 0) {
- _scValue->setBool(_textMode);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // AccessMode (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AccessMode") == 0) {
- _scValue->setInt(_mode);
- return _scValue;
- } else {
- return BaseScriptable::scGetProperty(name);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXFile::scSetProperty(const char *name, ScValue *value) {
- /*
- //////////////////////////////////////////////////////////////////////////
- // Length
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Length")==0){
- int origLength = _length;
- _length = max(value->getInt(0), 0);
-
- char propName[20];
- if (_length < OrigLength){
- for(int i=_length; i<OrigLength; i++){
- sprintf(PropName, "%d", i);
- _values->DeleteProp(PropName);
- }
- }
- return STATUS_OK;
- }
- else*/ return BaseScriptable::scSetProperty(name, value);
-}
-
-//////////////////////////////////////////////////////////////////////////
-uint32 SXFile::getPos() {
- if (_mode == 1 && _readFile) {
- return _readFile->pos();
- } else if ((_mode == 2 || _mode == 3) && _writeFile) {
- error("SXFile - getPos for WriteFile not supported");
- return 0;
-// return ftell((FILE *)_writeFile);
- } else {
- return 0;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool SXFile::setPos(uint32 pos, int whence) {
- if (_mode == 1 && _readFile) {
- return _readFile->seek(pos, whence);
- } else if ((_mode == 2 || _mode == 3) && _writeFile) {
- error("SXFile - seeking in WriteFile not supported");
- return false;
-// return fseek((FILE *)_writeFile, pos, (int)origin) == 0;
- } else {
- return false;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-uint32 SXFile::getLength() {
- if (_mode == 1 && _readFile) {
- return _readFile->size();
- } else if ((_mode == 2 || _mode == 3) && _writeFile) {
- error("SXFile - reading length for WriteFile not supported");
- return 0;
- /*
- uint32 currentPos = ftell((FILE *)_writeFile);
- fseek((FILE *)_writeFile, 0, SEEK_END);
- int ret = ftell((FILE *)_writeFile);
- fseek((FILE *)_writeFile, CurrentPos, SEEK_SET);
- return Ret;*/
- } else {
- return 0;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool SXFile::persist(BasePersistenceManager *persistMgr) {
-
- BaseScriptable::persist(persistMgr);
-
- persistMgr->transfer(TMEMBER(_filename));
- persistMgr->transfer(TMEMBER(_mode));
- persistMgr->transfer(TMEMBER(_textMode));
-
- uint32 pos = 0;
- if (persistMgr->getIsSaving()) {
- pos = getPos();
- persistMgr->transfer(TMEMBER(pos));
- } else {
- persistMgr->transfer(TMEMBER(pos));
-
- // try to re-open file if needed
- _writeFile = NULL;
- _readFile = NULL;
-
- if (_mode != 0) {
- // open for reading
- if (_mode == 1) {
- _readFile = BaseFileManager::getEngineInstance()->openFile(_filename);
- if (!_readFile) {
- close();
- }
- }
- // open for writing / appending
- else {
- if (_textMode) {
- if (_mode == 2) {
- _writeFile = openForWrite(_filename, false);
- } else {
- _writeFile = openForAppend(_filename, false);
- }
- } else {
- if (_mode == 2) {
- _writeFile = openForWrite(_filename, true);
- } else {
- _writeFile = openForAppend(_filename, true);
- }
- }
- if (_writeFile) {
- close();
- }
- }
- setPos(pos);
- }
- }
-
- return STATUS_OK;
-}
-
-// Should replace fopen(..., "wb+") and fopen(..., "w+")
-Common::WriteStream *SXFile::openForWrite(const Common::String &filename, bool binary) {
- error("SXFile::openForWrite - WriteFiles not supported");
-}
-
-// Should replace fopen(..., "ab+") and fopen(..., "a+")
-Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool binary) {
- error("SXFile::openForAppend - WriteFiles not supported");
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/system/sys_class_registry.h" +#include "engines/wintermute/system/sys_class.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/file/base_file.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/base/scriptables/script_ext_file.h" + +// Note: This code is completely untested, as I have yet to find a game that uses SXFile. + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(SXFile, false) + +BaseScriptable *makeSXFile(BaseGame *inGame, ScStack *stack) { + return new SXFile(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXFile::SXFile(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + _filename = NULL; + if (!val->isNULL()) { + BaseUtils::setString(&_filename, val->getString()); + } + + _readFile = NULL; + _writeFile = NULL; + + _mode = 0; + _textMode = false; +} + + +////////////////////////////////////////////////////////////////////////// +SXFile::~SXFile() { + cleanup(); +} + +////////////////////////////////////////////////////////////////////////// +void SXFile::cleanup() { + delete[] _filename; + _filename = NULL; + close(); +} + + +////////////////////////////////////////////////////////////////////////// +void SXFile::close() { + if (_readFile) { + BaseFileManager::getEngineInstance()->closeFile(_readFile); + _readFile = NULL; + } + if (_writeFile) { + _writeFile->finalize(); + delete _writeFile; + _writeFile = NULL; + } + _mode = 0; + _textMode = false; +} + +////////////////////////////////////////////////////////////////////////// +const char *SXFile::scToString() { + if (_filename) { + return _filename; + } else { + return "[file object]"; + } +} + +#define FILE_BUFFER_SIZE 32768 +////////////////////////////////////////////////////////////////////////// +bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetFilename + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetFilename") == 0) { + stack->correctParams(1); + const char *filename = stack->pop()->getString(); + cleanup(); + BaseUtils::setString(&_filename, filename); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // OpenAsText / OpenAsBinary + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "OpenAsText") == 0 || strcmp(name, "OpenAsBinary") == 0) { + stack->correctParams(1); + close(); + _mode = stack->pop()->getInt(1); + if (_mode < 1 || _mode > 3) { + script->runtimeError("File.%s: invalid access mode. Setting read mode.", name); + _mode = 1; + } + if (_mode == 1) { + _readFile = BaseFileManager::getEngineInstance()->openFile(_filename); + if (!_readFile) { + //script->runtimeError("File.%s: Error opening file '%s' for reading.", Name, _filename); + close(); + } else { + _textMode = strcmp(name, "OpenAsText") == 0; + } + } else { + if (strcmp(name, "OpenAsText") == 0) { + if (_mode == 2) { + _writeFile = openForWrite(_filename, false); + } else { + _writeFile = openForAppend(_filename, false); + } + } else { + if (_mode == 2) { + _writeFile = openForWrite(_filename, true); + } else { + _writeFile = openForAppend(_filename, true); + } + } + + if (!_writeFile) { + //script->runtimeError("File.%s: Error opening file '%s' for writing.", Name, _filename); + close(); + } else { + _textMode = strcmp(name, "OpenAsText") == 0; + } + } + + if (_readFile || _writeFile) { + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Close + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Close") == 0) { + stack->correctParams(0); + close(); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetPosition + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetPosition") == 0) { + stack->correctParams(1); + if (_mode == 0) { + script->runtimeError("File.%s: File is not open", name); + stack->pushBool(false); + } else { + int pos = stack->pop()->getInt(); + stack->pushBool(setPos(pos)); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Delete + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Delete") == 0) { + stack->correctParams(0); + close(); + error("SXFile-Method: \"Delete\" not supported"); + //stack->pushBool(BasePlatform::deleteFile(_filename) != false); + stack->pushBool(false); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Copy + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Copy") == 0) { + stack->correctParams(2); + /* const char *dest = */ stack->pop()->getString(); + /* bool overwrite = */ stack->pop()->getBool(true); + + close(); + error("SXFile-Method: Copy not supported"); + //stack->pushBool(BasePlatform::copyFile(_filename, Dest, !Overwrite) != false); + stack->pushBool(false); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadLine + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadLine") == 0) { + stack->correctParams(0); + if (!_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open in text mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + uint32 bufSize = FILE_BUFFER_SIZE; + byte *buf = (byte *)malloc(bufSize); + uint32 counter = 0; + byte b; + bool foundNewLine = false; + bool ret = STATUS_FAILED; + do { + ret = _readFile->read(&b, 1); + if (ret != 1) { + break; + } + + if (counter > bufSize) { + buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE); + bufSize += FILE_BUFFER_SIZE; + } + if (b == '\n') { + buf[counter] = '\0'; + foundNewLine = true; + break; + } else if (b == 0x0D) { + continue; + } else { + buf[counter] = b; + counter++; + } + } while (DID_SUCCEED(ret)); + + if (counter > bufSize) { + buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE); + bufSize += FILE_BUFFER_SIZE; + } + buf[counter] = '\0'; + + if (!foundNewLine && counter == 0) { + stack->pushNULL(); + } else { + stack->pushString((char *)buf); + } + + free(buf); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadText + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadText") == 0) { + stack->correctParams(1); + int textLen = stack->pop()->getInt(); + + if (!_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open in text mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + uint32 bufSize = FILE_BUFFER_SIZE; + byte *buf = (byte *)malloc(bufSize); + uint32 counter = 0; + byte b; + + bool ret = STATUS_FAILED; + while (counter < (uint32)textLen) { + ret = _readFile->read(&b, 1); + if (ret != 1) { + break; + } + + if (counter > bufSize) { + buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE); + bufSize += FILE_BUFFER_SIZE; + } + if (b == 0x0D) { + continue; + } else { + buf[counter] = b; + counter++; + } + } + + if (counter > bufSize) { + buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE); + bufSize += FILE_BUFFER_SIZE; + } + buf[counter] = '\0'; + + if (textLen > 0 && counter == 0) { + stack->pushNULL(); + } else { + stack->pushString((char *)buf); + } + + free(buf); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteLine / WriteText + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteLine") == 0 || strcmp(name, "WriteText") == 0) { + stack->correctParams(1); + const char *line = stack->pop()->getString(); + if (!_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in text mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + Common::String writeLine; + if (strcmp(name, "WriteLine") == 0) { + writeLine = Common::String::format("%s\n", line); + } else { + writeLine = Common::String::format("%s", line); + } + _writeFile->writeString(writeLine); + _writeFile->writeByte(0); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // ReadBool + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadBool") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + bool val; + if (_readFile->read(&val, sizeof(bool)) == sizeof(bool)) { + stack->pushBool(val); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadByte + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadByte") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + byte val = _readFile->readByte(); + if (!_readFile->err()) { + stack->pushInt(val); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadShort + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadShort") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + int16 val = _readFile->readSint16LE(); + if (!_readFile->err()) { + stack->pushInt(65536 + val); + } else { + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadInt / ReadLong + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadInt") == 0 || strcmp(name, "ReadLong") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + int32 val = _readFile->readSint32LE(); + if (!_readFile->err()) { + stack->pushInt(val); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadFloat + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadFloat") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + float val; + (*(uint32 *)&val) = _readFile->readUint32LE(); + if (!_readFile->err()) { + stack->pushFloat(val); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadDouble + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadDouble") == 0) { // TODO: Solve reading a 8 byte double. + error("SXFile::ReadDouble - Not endian safe yet"); + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + double val; + if (_readFile->read(&val, sizeof(double)) == sizeof(double)) { + stack->pushFloat(val); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ReadString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ReadString") == 0) { + stack->correctParams(0); + if (_textMode || !_readFile) { + script->runtimeError("File.%s: File must be open for reading in binary mode.", name); + stack->pushNULL(); + return STATUS_OK; + } + uint32 size = _readFile->readUint32LE(); + if (!_readFile->err()) { + byte *str = new byte[size + 1]; + if (str) { + if (_readFile->read(str, size) == size) { + str[size] = '\0'; + stack->pushString((char *)str); + } + delete[] str; + } else { + stack->pushNULL(); + } + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteBool + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteBool") == 0) { + stack->correctParams(1); + bool val = stack->pop()->getBool(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + _writeFile->writeByte(val); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteByte + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteByte") == 0) { + stack->correctParams(1); + byte val = stack->pop()->getInt(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + _writeFile->writeByte(val); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteShort + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteShort") == 0) { + stack->correctParams(1); + int16 val = stack->pop()->getInt(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + _writeFile->writeSint16LE(val); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteInt / WriteLong + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteInt") == 0 || strcmp(name, "WriteLong") == 0) { + stack->correctParams(1); + int32 val = stack->pop()->getInt(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + _writeFile->writeSint32LE(val); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteFloat + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteFloat") == 0) { + stack->correctParams(1); + float val = stack->pop()->getFloat(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + uint32 *ptr = (uint32 *)&val; + _writeFile->writeUint32LE(*ptr); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteDouble + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteDouble") == 0) { + error("SXFile::WriteDouble - Not endian safe yet"); + stack->correctParams(1); + /* double val = */ stack->pop()->getFloat(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + //fwrite(&val, sizeof(val), 1, (FILE *)_writeFile); + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WriteString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WriteString") == 0) { + stack->correctParams(1); + const char *val = stack->pop()->getString(); + + if (_textMode || !_writeFile) { + script->runtimeError("File.%s: File must be open for writing in binary mode.", name); + stack->pushBool(false); + return STATUS_OK; + } + + uint32 size = strlen(val); + _writeFile->writeUint32LE(size); + _writeFile->writeString(val); + + stack->pushBool(true); + + return STATUS_OK; + } else { + return BaseScriptable::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXFile::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("file"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Filename (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Filename") == 0) { + _scValue->setString(_filename); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Position (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Position") == 0) { + _scValue->setInt(getPos()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Length (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Length") == 0) { + _scValue->setInt(getLength()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TextMode (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TextMode") == 0) { + _scValue->setBool(_textMode); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccessMode (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AccessMode") == 0) { + _scValue->setInt(_mode); + return _scValue; + } else { + return BaseScriptable::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXFile::scSetProperty(const char *name, ScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Length + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Length")==0){ + int origLength = _length; + _length = max(value->getInt(0), 0); + + char propName[20]; + if (_length < OrigLength){ + for(int i=_length; i<OrigLength; i++){ + sprintf(PropName, "%d", i); + _values->DeleteProp(PropName); + } + } + return STATUS_OK; + } + else*/ return BaseScriptable::scSetProperty(name, value); +} + +////////////////////////////////////////////////////////////////////////// +uint32 SXFile::getPos() { + if (_mode == 1 && _readFile) { + return _readFile->pos(); + } else if ((_mode == 2 || _mode == 3) && _writeFile) { + error("SXFile - getPos for WriteFile not supported"); + return 0; +// return ftell((FILE *)_writeFile); + } else { + return 0; + } +} + +////////////////////////////////////////////////////////////////////////// +bool SXFile::setPos(uint32 pos, int whence) { + if (_mode == 1 && _readFile) { + return _readFile->seek(pos, whence); + } else if ((_mode == 2 || _mode == 3) && _writeFile) { + error("SXFile - seeking in WriteFile not supported"); + return false; +// return fseek((FILE *)_writeFile, pos, (int)origin) == 0; + } else { + return false; + } +} + +////////////////////////////////////////////////////////////////////////// +uint32 SXFile::getLength() { + if (_mode == 1 && _readFile) { + return _readFile->size(); + } else if ((_mode == 2 || _mode == 3) && _writeFile) { + error("SXFile - reading length for WriteFile not supported"); + return 0; + /* + uint32 currentPos = ftell((FILE *)_writeFile); + fseek((FILE *)_writeFile, 0, SEEK_END); + int ret = ftell((FILE *)_writeFile); + fseek((FILE *)_writeFile, CurrentPos, SEEK_SET); + return Ret;*/ + } else { + return 0; + } +} + +////////////////////////////////////////////////////////////////////////// +bool SXFile::persist(BasePersistenceManager *persistMgr) { + + BaseScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_filename)); + persistMgr->transfer(TMEMBER(_mode)); + persistMgr->transfer(TMEMBER(_textMode)); + + uint32 pos = 0; + if (persistMgr->getIsSaving()) { + pos = getPos(); + persistMgr->transfer(TMEMBER(pos)); + } else { + persistMgr->transfer(TMEMBER(pos)); + + // try to re-open file if needed + _writeFile = NULL; + _readFile = NULL; + + if (_mode != 0) { + // open for reading + if (_mode == 1) { + _readFile = BaseFileManager::getEngineInstance()->openFile(_filename); + if (!_readFile) { + close(); + } + } + // open for writing / appending + else { + if (_textMode) { + if (_mode == 2) { + _writeFile = openForWrite(_filename, false); + } else { + _writeFile = openForAppend(_filename, false); + } + } else { + if (_mode == 2) { + _writeFile = openForWrite(_filename, true); + } else { + _writeFile = openForAppend(_filename, true); + } + } + if (_writeFile) { + close(); + } + } + setPos(pos); + } + } + + return STATUS_OK; +} + +// Should replace fopen(..., "wb+") and fopen(..., "w+") +Common::WriteStream *SXFile::openForWrite(const Common::String &filename, bool binary) { + error("SXFile::openForWrite - WriteFiles not supported"); +} + +// Should replace fopen(..., "ab+") and fopen(..., "a+") +Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool binary) { + error("SXFile::openForAppend - WriteFiles not supported"); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h index 389974a48e..b91a53e695 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.h +++ b/engines/wintermute/base/scriptables/script_ext_file.h @@ -1,66 +1,66 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTES_SXFILE_H
-#define WINTERMUTES_SXFILE_H
-
-
-#include "engines/wintermute/base/base_scriptable.h"
-#include "common/stream.h"
-
-namespace Wintermute {
-
-class BaseFile;
-
-class SXFile : public BaseScriptable {
-public:
- DECLARE_PERSISTENT(SXFile, BaseScriptable)
- ScValue *scGetProperty(const char *name);
- bool scSetProperty(const char *name, ScValue *value);
- bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
- const char *scToString();
- SXFile(BaseGame *inGame, ScStack *Stack);
- virtual ~SXFile();
-private:
- Common::SeekableReadStream *_readFile;
- Common::WriteStream *_writeFile;
- int _mode; // 0..none, 1..read, 2..write, 3..append
- bool _textMode;
- void close();
- void cleanup();
- uint32 getPos();
- uint32 getLength();
- bool setPos(uint32 pos, int whence = SEEK_SET);
- char *_filename;
- Common::WriteStream *openForWrite(const Common::String &filename, bool binary);
- Common::WriteStream *openForAppend(const Common::String &filename, bool binary);
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTES_SXFILE_H +#define WINTERMUTES_SXFILE_H + + +#include "engines/wintermute/base/base_scriptable.h" +#include "common/stream.h" + +namespace Wintermute { + +class BaseFile; + +class SXFile : public BaseScriptable { +public: + DECLARE_PERSISTENT(SXFile, BaseScriptable) + ScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, ScValue *value); + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + const char *scToString(); + SXFile(BaseGame *inGame, ScStack *Stack); + virtual ~SXFile(); +private: + Common::SeekableReadStream *_readFile; + Common::WriteStream *_writeFile; + int _mode; // 0..none, 1..read, 2..write, 3..append + bool _textMode; + void close(); + void cleanup(); + uint32 getPos(); + uint32 getLength(); + bool setPos(uint32 pos, int whence = SEEK_SET); + char *_filename; + Common::WriteStream *openForWrite(const Common::String &filename, bool binary); + Common::WriteStream *openForAppend(const Common::String &filename, bool binary); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp index f7d0ba20b9..598b80cff3 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.cpp +++ b/engines/wintermute/base/scriptables/script_ext_math.cpp @@ -1,295 +1,295 @@ -/* 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.
-
- * 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.
-
- * 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/base/scriptables/script_ext_math.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/persistent.h"
-#include "common/math.h"
-#include <math.h>
-
-namespace Wintermute {
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-
-IMPLEMENT_PERSISTENT(SXMath, true)
-
-BaseScriptable *makeSXMath(BaseGame *inGame) {
- return new SXMath(inGame);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXMath::SXMath(BaseGame *inGame) : BaseScriptable(inGame) {
-
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXMath::~SXMath() {
-
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMath::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // Abs
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Abs") == 0) {
- stack->correctParams(1);
- stack->pushFloat(fabs(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Acos
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Acos") == 0) {
- stack->correctParams(1);
- stack->pushFloat(acos(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Asin
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Asin") == 0) {
- stack->correctParams(1);
- stack->pushFloat(asin(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Atan
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Atan") == 0) {
- stack->correctParams(1);
- stack->pushFloat(atan(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Atan2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Atan2") == 0) {
- stack->correctParams(2);
- double y = stack->pop()->getFloat();
- double x = stack->pop()->getFloat();
- stack->pushFloat(atan2(y, x));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Ceil
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Ceil") == 0) {
- stack->correctParams(1);
- stack->pushFloat(ceil(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Cos
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Cos") == 0) {
- stack->correctParams(1);
- stack->pushFloat(cos(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Cosh
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Cosh") == 0) {
- stack->correctParams(1);
- stack->pushFloat(cosh(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Exp
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Exp") == 0) {
- stack->correctParams(1);
- stack->pushFloat(exp(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Floor
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Floor") == 0) {
- stack->correctParams(1);
- stack->pushFloat(floor(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Log
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Log") == 0) {
- stack->correctParams(1);
- stack->pushFloat(log(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Log10
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Log10") == 0) {
- stack->correctParams(1);
- stack->pushFloat(log10(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Pow
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Pow") == 0) {
- stack->correctParams(2);
- double x = stack->pop()->getFloat();
- double y = stack->pop()->getFloat();
-
- stack->pushFloat(pow(x, y));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Sin
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Sin") == 0) {
- stack->correctParams(1);
- stack->pushFloat(sin(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Sinh
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Sinh") == 0) {
- stack->correctParams(1);
- stack->pushFloat(sinh(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Tan
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Tan") == 0) {
- stack->correctParams(1);
- stack->pushFloat(tan(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Tanh
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Tanh") == 0) {
- stack->correctParams(1);
- stack->pushFloat(tanh(degreeToRadian(stack->pop()->getFloat())));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Sqrt
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Sqrt") == 0) {
- stack->correctParams(1);
- stack->pushFloat(sqrt(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // DegToRad
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "DegToRad") == 0) {
- stack->correctParams(1);
- stack->pushFloat(degreeToRadian(stack->pop()->getFloat()));
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // RadToDeg
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "RadToDeg") == 0) {
- stack->correctParams(1);
- stack->pushFloat(radianToDegree(stack->pop()->getFloat()));
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXMath::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("math");
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // PI
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PI") == 0) {
- _scValue->setFloat(M_PI);
- return _scValue;
- } else {
- return _scValue;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-double SXMath::degreeToRadian(double value) {
- return value * (M_PI / 180.0f);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-double SXMath::radianToDegree(double value) {
- return value * (180.0f / M_PI);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMath::persist(BasePersistenceManager *persistMgr) {
-
- BaseScriptable::persist(persistMgr);
- return STATUS_OK;
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/scriptables/script_ext_math.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/persistent.h" +#include "common/math.h" +#include <math.h> + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +IMPLEMENT_PERSISTENT(SXMath, true) + +BaseScriptable *makeSXMath(BaseGame *inGame) { + return new SXMath(inGame); +} + +////////////////////////////////////////////////////////////////////////// +SXMath::SXMath(BaseGame *inGame) : BaseScriptable(inGame) { + +} + + +////////////////////////////////////////////////////////////////////////// +SXMath::~SXMath() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool SXMath::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // Abs + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Abs") == 0) { + stack->correctParams(1); + stack->pushFloat(fabs(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Acos + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Acos") == 0) { + stack->correctParams(1); + stack->pushFloat(acos(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Asin + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Asin") == 0) { + stack->correctParams(1); + stack->pushFloat(asin(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Atan + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Atan") == 0) { + stack->correctParams(1); + stack->pushFloat(atan(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Atan2 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Atan2") == 0) { + stack->correctParams(2); + double y = stack->pop()->getFloat(); + double x = stack->pop()->getFloat(); + stack->pushFloat(atan2(y, x)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Ceil + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Ceil") == 0) { + stack->correctParams(1); + stack->pushFloat(ceil(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Cos + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Cos") == 0) { + stack->correctParams(1); + stack->pushFloat(cos(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Cosh + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Cosh") == 0) { + stack->correctParams(1); + stack->pushFloat(cosh(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Exp + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Exp") == 0) { + stack->correctParams(1); + stack->pushFloat(exp(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Floor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Floor") == 0) { + stack->correctParams(1); + stack->pushFloat(floor(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Log + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Log") == 0) { + stack->correctParams(1); + stack->pushFloat(log(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Log10 + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Log10") == 0) { + stack->correctParams(1); + stack->pushFloat(log10(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Pow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Pow") == 0) { + stack->correctParams(2); + double x = stack->pop()->getFloat(); + double y = stack->pop()->getFloat(); + + stack->pushFloat(pow(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Sin + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Sin") == 0) { + stack->correctParams(1); + stack->pushFloat(sin(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Sinh + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Sinh") == 0) { + stack->correctParams(1); + stack->pushFloat(sinh(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Tan + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Tan") == 0) { + stack->correctParams(1); + stack->pushFloat(tan(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Tanh + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Tanh") == 0) { + stack->correctParams(1); + stack->pushFloat(tanh(degreeToRadian(stack->pop()->getFloat()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Sqrt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Sqrt") == 0) { + stack->correctParams(1); + stack->pushFloat(sqrt(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DegToRad + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DegToRad") == 0) { + stack->correctParams(1); + stack->pushFloat(degreeToRadian(stack->pop()->getFloat())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RadToDeg + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RadToDeg") == 0) { + stack->correctParams(1); + stack->pushFloat(radianToDegree(stack->pop()->getFloat())); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXMath::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("math"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PI + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PI") == 0) { + _scValue->setFloat(M_PI); + return _scValue; + } else { + return _scValue; + } +} + + +////////////////////////////////////////////////////////////////////////// +double SXMath::degreeToRadian(double value) { + return value * (M_PI / 180.0f); +} + + +////////////////////////////////////////////////////////////////////////// +double SXMath::radianToDegree(double value) { + return value * (180.0f / M_PI); +} + + +////////////////////////////////////////////////////////////////////////// +bool SXMath::persist(BasePersistenceManager *persistMgr) { + + BaseScriptable::persist(persistMgr); + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h index b195c0785d..f86d59fe7b 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.h +++ b/engines/wintermute/base/scriptables/script_ext_math.h @@ -1,53 +1,53 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXMATH_H
-#define WINTERMUTE_SXMATH_H
-
-
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-class SXMath : public BaseScriptable {
-public:
- DECLARE_PERSISTENT(SXMath, BaseScriptable)
- SXMath(BaseGame *inGame);
- virtual ~SXMath();
- virtual ScValue *scGetProperty(const char *name);
- virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
-
-private:
- double degreeToRadian(double value);
- double radianToDegree(double value);
-
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXMATH_H +#define WINTERMUTE_SXMATH_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +class SXMath : public BaseScriptable { +public: + DECLARE_PERSISTENT(SXMath, BaseScriptable) + SXMath(BaseGame *inGame); + virtual ~SXMath(); + virtual ScValue *scGetProperty(const char *name); + virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + +private: + double degreeToRadian(double value); + double radianToDegree(double value); + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp index eef1931d8b..5ed9bd5313 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp @@ -1,529 +1,529 @@ -/* 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.
-
- * 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.
-
- * 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/base/base_scriptable.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script_ext_mem_buffer.h"
-#include "common/file.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(SXMemBuffer, false)
-
-BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack) {
- return new SXMemBuffer(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXMemBuffer::SXMemBuffer(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
- stack->correctParams(1);
- _buffer = NULL;
- _size = 0;
-
- int newSize = stack->pop()->getInt();
- resize(MAX(0, newSize));
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXMemBuffer::SXMemBuffer(BaseGame *inGame, void *buffer) : BaseScriptable(inGame) {
- _size = 0;
- _buffer = buffer;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXMemBuffer::~SXMemBuffer() {
- cleanup();
-}
-
-//////////////////////////////////////////////////////////////////////////
-void *SXMemBuffer::scToMemBuffer() {
- return _buffer;
-}
-
-//////////////////////////////////////////////////////////////////////////
-void SXMemBuffer::cleanup() {
- if (_size) {
- free(_buffer);
- }
- _buffer = NULL;
- _size = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMemBuffer::resize(int newSize) {
- int oldSize = _size;
-
- if (_size == 0) {
- _buffer = malloc(newSize);
- if (_buffer) {
- _size = newSize;
- }
- } else {
- void *newBuf = realloc(_buffer, newSize);
- if (!newBuf) {
- if (newSize == 0) {
- _buffer = newBuf;
- _size = newSize;
- } else {
- return STATUS_FAILED;
- }
- } else {
- _buffer = newBuf;
- _size = newSize;
- }
- }
-
- if (_buffer && _size > oldSize) {
- memset((byte *)_buffer + oldSize, 0, _size - oldSize);
- }
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMemBuffer::checkBounds(ScScript *script, int start, int length) {
- if (_buffer == NULL) {
- script->runtimeError("Cannot use Set/Get methods on an uninitialized memory buffer");
- return false;
- }
- if (_size == 0) {
- return true;
- }
-
- if (start < 0 || length == 0 || start + length > _size) {
- script->runtimeError("Set/Get method call is out of bounds");
- return false;
- } else {
- return true;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-const char *SXMemBuffer::scToString() {
- return "[membuffer object]";
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMemBuffer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // SetSize
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "SetSize") == 0) {
- stack->correctParams(1);
- int newSize = stack->pop()->getInt();
- newSize = MAX(0, newSize);
- if (DID_SUCCEED(resize(newSize))) {
- stack->pushBool(true);
- } else {
- stack->pushBool(false);
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetBool
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetBool") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(bool))) {
- stack->pushNULL();
- } else {
- stack->pushBool(*(bool *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetByte
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetByte") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(byte))) {
- stack->pushNULL();
- } else {
- stack->pushInt(*(byte *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetShort
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetShort") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(short))) {
- stack->pushNULL();
- } else {
- stack->pushInt(65536 + * (short *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetInt / GetLong
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetInt") == 0 || strcmp(name, "GetLong") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(int))) {
- stack->pushNULL();
- } else {
- stack->pushInt(*(int *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetFloat
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetFloat") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(float))) {
- stack->pushNULL();
- } else {
- stack->pushFloat(*(float *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetDouble
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetDouble") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(double))) {
- stack->pushNULL();
- } else {
- stack->pushFloat(*(double *)((byte *)_buffer + start));
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetString
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetString") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- int length = stack->pop()->getInt();
-
- // find end of string
- if (length == 0 && start >= 0 && start < _size) {
- for (int i = start; i < _size; i++) {
- if (((char *)_buffer)[i] == '\0') {
- length = i - start;
- break;
- }
- }
- }
-
- if (!checkBounds(script, start, length)) {
- stack->pushNULL();
- } else {
- char *str = new char[length + 1];
- Common::strlcpy(str, (const char *)_buffer + start, length + 1);
- stack->pushString(str);
- delete[] str;
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetPointer
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetPointer") == 0) {
- stack->correctParams(1);
- int start = stack->pop()->getInt();
- if (!checkBounds(script, start, sizeof(void *))) {
- stack->pushNULL();
- } else {
- void *pointer = *(void **)((byte *)_buffer + start);
- SXMemBuffer *buf = new SXMemBuffer(_gameRef, pointer);
- stack->pushNative(buf, false);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetBool
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetBool") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- bool val = stack->pop()->getBool();
-
- if (!checkBounds(script, start, sizeof(bool))) {
- stack->pushBool(false);
- } else {
- *(bool *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetByte
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetByte") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- byte val = (byte)stack->pop()->getInt();
-
- if (!checkBounds(script, start, sizeof(byte))) {
- stack->pushBool(false);
- } else {
- *(byte *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetShort
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetShort") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- short val = (short)stack->pop()->getInt();
-
- if (!checkBounds(script, start, sizeof(short))) {
- stack->pushBool(false);
- } else {
- *(short *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetInt / SetLong
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetInt") == 0 || strcmp(name, "SetLong") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- int val = stack->pop()->getInt();
-
- if (!checkBounds(script, start, sizeof(int))) {
- stack->pushBool(false);
- } else {
- *(int *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetFloat
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetFloat") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- float val = (float)stack->pop()->getFloat();
-
- if (!checkBounds(script, start, sizeof(float))) {
- stack->pushBool(false);
- } else {
- *(float *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetDouble
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetDouble") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- double val = stack->pop()->getFloat();
-
- if (!checkBounds(script, start, sizeof(double))) {
- stack->pushBool(false);
- } else {
- *(double *)((byte *)_buffer + start) = val;
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetString
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetString") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- const char *val = stack->pop()->getString();
-
- if (!checkBounds(script, start, strlen(val) + 1)) {
- stack->pushBool(false);
- } else {
- memcpy((byte *)_buffer + start, val, strlen(val) + 1);
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetPointer
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetPointer") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- /* ScValue *val = */ stack->pop();
-
- if (!checkBounds(script, start, sizeof(void *))) {
- stack->pushBool(false);
- } else {
- /*
- int pointer = (int)Val->getMemBuffer();
- memcpy((byte *)_buffer+Start, &Pointer, sizeof(void*));
- stack->pushBool(true);
- */
- // TODO fix
- stack->pushBool(false);
-
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // DEBUG_Dump
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "DEBUG_Dump") == 0) {
- stack->correctParams(0);
- if (_buffer && _size) {
- warning("SXMemBuffer::ScCallMethod - DEBUG_Dump");
- Common::DumpFile f;
- f.open("buffer.bin");
- f.write(_buffer, _size);
- f.close();
- }
- stack->pushNULL();
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXMemBuffer::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type (RO)
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("membuffer");
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Size (RO)
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Size") == 0) {
- _scValue->setInt(_size);
- return _scValue;
- } else {
- return BaseScriptable::scGetProperty(name);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMemBuffer::scSetProperty(const char *name, ScValue *value) {
- /*
- //////////////////////////////////////////////////////////////////////////
- // Length
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Length")==0){
- int origLength = _length;
- _length = max(value->getInt(0), 0);
-
- char propName[20];
- if (_length < OrigLength){
- for(int i=_length; i<OrigLength; i++){
- sprintf(PropName, "%d", i);
- _values->DeleteProp(PropName);
- }
- }
- return STATUS_OK;
- }
- else*/ return BaseScriptable::scSetProperty(name, value);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) {
-
- BaseScriptable::persist(persistMgr);
-
- persistMgr->transfer(TMEMBER(_size));
-
- if (persistMgr->getIsSaving()) {
- if (_size > 0) {
- persistMgr->putBytes((byte *)_buffer, _size);
- }
- } else {
- if (_size > 0) {
- _buffer = malloc(_size);
- persistMgr->getBytes((byte *)_buffer, _size);
- } else {
- _buffer = NULL;
- }
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-int SXMemBuffer::scCompare(BaseScriptable *val) {
- if (_buffer == val->scToMemBuffer()) {
- return 0;
- } else {
- return 1;
- }
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/base_scriptable.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_ext_mem_buffer.h" +#include "common/file.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(SXMemBuffer, false) + +BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack) { + return new SXMemBuffer(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXMemBuffer::SXMemBuffer(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { + stack->correctParams(1); + _buffer = NULL; + _size = 0; + + int newSize = stack->pop()->getInt(); + resize(MAX(0, newSize)); +} + +////////////////////////////////////////////////////////////////////////// +SXMemBuffer::SXMemBuffer(BaseGame *inGame, void *buffer) : BaseScriptable(inGame) { + _size = 0; + _buffer = buffer; +} + + +////////////////////////////////////////////////////////////////////////// +SXMemBuffer::~SXMemBuffer() { + cleanup(); +} + +////////////////////////////////////////////////////////////////////////// +void *SXMemBuffer::scToMemBuffer() { + return _buffer; +} + +////////////////////////////////////////////////////////////////////////// +void SXMemBuffer::cleanup() { + if (_size) { + free(_buffer); + } + _buffer = NULL; + _size = 0; +} + +////////////////////////////////////////////////////////////////////////// +bool SXMemBuffer::resize(int newSize) { + int oldSize = _size; + + if (_size == 0) { + _buffer = malloc(newSize); + if (_buffer) { + _size = newSize; + } + } else { + void *newBuf = realloc(_buffer, newSize); + if (!newBuf) { + if (newSize == 0) { + _buffer = newBuf; + _size = newSize; + } else { + return STATUS_FAILED; + } + } else { + _buffer = newBuf; + _size = newSize; + } + } + + if (_buffer && _size > oldSize) { + memset((byte *)_buffer + oldSize, 0, _size - oldSize); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool SXMemBuffer::checkBounds(ScScript *script, int start, int length) { + if (_buffer == NULL) { + script->runtimeError("Cannot use Set/Get methods on an uninitialized memory buffer"); + return false; + } + if (_size == 0) { + return true; + } + + if (start < 0 || length == 0 || start + length > _size) { + script->runtimeError("Set/Get method call is out of bounds"); + return false; + } else { + return true; + } +} + +////////////////////////////////////////////////////////////////////////// +const char *SXMemBuffer::scToString() { + return "[membuffer object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool SXMemBuffer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetSize + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetSize") == 0) { + stack->correctParams(1); + int newSize = stack->pop()->getInt(); + newSize = MAX(0, newSize); + if (DID_SUCCEED(resize(newSize))) { + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetBool + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetBool") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(bool))) { + stack->pushNULL(); + } else { + stack->pushBool(*(bool *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetByte + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetByte") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(byte))) { + stack->pushNULL(); + } else { + stack->pushInt(*(byte *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetShort + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetShort") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(short))) { + stack->pushNULL(); + } else { + stack->pushInt(65536 + * (short *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetInt / GetLong + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetInt") == 0 || strcmp(name, "GetLong") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(int))) { + stack->pushNULL(); + } else { + stack->pushInt(*(int *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFloat + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFloat") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(float))) { + stack->pushNULL(); + } else { + stack->pushFloat(*(float *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetDouble + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetDouble") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(double))) { + stack->pushNULL(); + } else { + stack->pushFloat(*(double *)((byte *)_buffer + start)); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetString") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + int length = stack->pop()->getInt(); + + // find end of string + if (length == 0 && start >= 0 && start < _size) { + for (int i = start; i < _size; i++) { + if (((char *)_buffer)[i] == '\0') { + length = i - start; + break; + } + } + } + + if (!checkBounds(script, start, length)) { + stack->pushNULL(); + } else { + char *str = new char[length + 1]; + Common::strlcpy(str, (const char *)_buffer + start, length + 1); + stack->pushString(str); + delete[] str; + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetPointer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetPointer") == 0) { + stack->correctParams(1); + int start = stack->pop()->getInt(); + if (!checkBounds(script, start, sizeof(void *))) { + stack->pushNULL(); + } else { + void *pointer = *(void **)((byte *)_buffer + start); + SXMemBuffer *buf = new SXMemBuffer(_gameRef, pointer); + stack->pushNative(buf, false); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetBool + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetBool") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + bool val = stack->pop()->getBool(); + + if (!checkBounds(script, start, sizeof(bool))) { + stack->pushBool(false); + } else { + *(bool *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetByte + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetByte") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + byte val = (byte)stack->pop()->getInt(); + + if (!checkBounds(script, start, sizeof(byte))) { + stack->pushBool(false); + } else { + *(byte *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetShort + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetShort") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + short val = (short)stack->pop()->getInt(); + + if (!checkBounds(script, start, sizeof(short))) { + stack->pushBool(false); + } else { + *(short *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetInt / SetLong + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetInt") == 0 || strcmp(name, "SetLong") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + int val = stack->pop()->getInt(); + + if (!checkBounds(script, start, sizeof(int))) { + stack->pushBool(false); + } else { + *(int *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetFloat + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetFloat") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + float val = (float)stack->pop()->getFloat(); + + if (!checkBounds(script, start, sizeof(float))) { + stack->pushBool(false); + } else { + *(float *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetDouble + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetDouble") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + double val = stack->pop()->getFloat(); + + if (!checkBounds(script, start, sizeof(double))) { + stack->pushBool(false); + } else { + *(double *)((byte *)_buffer + start) = val; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetString") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + const char *val = stack->pop()->getString(); + + if (!checkBounds(script, start, strlen(val) + 1)) { + stack->pushBool(false); + } else { + memcpy((byte *)_buffer + start, val, strlen(val) + 1); + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetPointer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetPointer") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + /* ScValue *val = */ stack->pop(); + + if (!checkBounds(script, start, sizeof(void *))) { + stack->pushBool(false); + } else { + /* + int pointer = (int)Val->getMemBuffer(); + memcpy((byte *)_buffer+Start, &Pointer, sizeof(void*)); + stack->pushBool(true); + */ + // TODO fix + stack->pushBool(false); + + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DEBUG_Dump + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DEBUG_Dump") == 0) { + stack->correctParams(0); + if (_buffer && _size) { + warning("SXMemBuffer::ScCallMethod - DEBUG_Dump"); + Common::DumpFile f; + f.open("buffer.bin"); + f.write(_buffer, _size); + f.close(); + } + stack->pushNULL(); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXMemBuffer::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("membuffer"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Size (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Size") == 0) { + _scValue->setInt(_size); + return _scValue; + } else { + return BaseScriptable::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXMemBuffer::scSetProperty(const char *name, ScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Length + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Length")==0){ + int origLength = _length; + _length = max(value->getInt(0), 0); + + char propName[20]; + if (_length < OrigLength){ + for(int i=_length; i<OrigLength; i++){ + sprintf(PropName, "%d", i); + _values->DeleteProp(PropName); + } + } + return STATUS_OK; + } + else*/ return BaseScriptable::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) { + + BaseScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_size)); + + if (persistMgr->getIsSaving()) { + if (_size > 0) { + persistMgr->putBytes((byte *)_buffer, _size); + } + } else { + if (_size > 0) { + _buffer = malloc(_size); + persistMgr->getBytes((byte *)_buffer, _size); + } else { + _buffer = NULL; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int SXMemBuffer::scCompare(BaseScriptable *val) { + if (_buffer == val->scToMemBuffer()) { + return 0; + } else { + return 1; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h index 0a16167b58..d2662b3036 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h @@ -1,60 +1,60 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXMEMBUFFER_H
-#define WINTERMUTE_SXMEMBUFFER_H
-
-
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-class SXMemBuffer : public BaseScriptable {
-public:
- virtual int scCompare(BaseScriptable *Val);
- DECLARE_PERSISTENT(SXMemBuffer, BaseScriptable)
- ScValue *scGetProperty(const char *name);
- bool scSetProperty(const char *name, ScValue *value);
- bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
- const char *scToString();
- SXMemBuffer(BaseGame *inGame, ScStack *stack);
- SXMemBuffer(BaseGame *inGame, void *buffer);
- virtual ~SXMemBuffer();
- virtual void *scToMemBuffer();
-private:
- int _size;
-
- bool resize(int newSize);
- void *_buffer;
- void cleanup();
- bool checkBounds(ScScript *script, int start, int length);
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXMEMBUFFER_H +#define WINTERMUTE_SXMEMBUFFER_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +class SXMemBuffer : public BaseScriptable { +public: + virtual int scCompare(BaseScriptable *Val); + DECLARE_PERSISTENT(SXMemBuffer, BaseScriptable) + ScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, ScValue *value); + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + const char *scToString(); + SXMemBuffer(BaseGame *inGame, ScStack *stack); + SXMemBuffer(BaseGame *inGame, void *buffer); + virtual ~SXMemBuffer(); + virtual void *scToMemBuffer(); +private: + int _size; + + bool resize(int newSize); + void *_buffer; + void cleanup(); + bool checkBounds(ScScript *script, int start, int length); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_object.cpp b/engines/wintermute/base/scriptables/script_ext_object.cpp index 40c9b885cd..b87aac81f9 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.cpp +++ b/engines/wintermute/base/scriptables/script_ext_object.cpp @@ -1,67 +1,67 @@ -/* 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.
-
- * 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.
-
- * 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/base/scriptables/script_ext_object.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-
-namespace Wintermute {
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-IMPLEMENT_PERSISTENT(SXObject, false)
-
-BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack) {
- return new SXObject(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXObject::SXObject(BaseGame *inGame, ScStack *stack) : BaseObject(inGame) {
- int numParams = stack->pop()->getInt(0);
- for (int i = 0; i < numParams; i++) {
- addScript(stack->pop()->getString());
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXObject::~SXObject() {
-
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXObject::persist(BasePersistenceManager *persistMgr) {
- BaseObject::persist(persistMgr);
-
- return STATUS_OK;
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/scriptables/script_ext_object.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(SXObject, false) + +BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack) { + return new SXObject(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXObject::SXObject(BaseGame *inGame, ScStack *stack) : BaseObject(inGame) { + int numParams = stack->pop()->getInt(0); + for (int i = 0; i < numParams; i++) { + addScript(stack->pop()->getString()); + } +} + + +////////////////////////////////////////////////////////////////////////// +SXObject::~SXObject() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool SXObject::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_object.h b/engines/wintermute/base/scriptables/script_ext_object.h index 32aa00776e..c85d16d44e 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.h +++ b/engines/wintermute/base/scriptables/script_ext_object.h @@ -1,46 +1,46 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXOBJECT_H
-#define WINTERMUTE_SXOBJECT_H
-
-
-#include "engines/wintermute/base/base_object.h"
-
-namespace Wintermute {
-
-class SXObject : public BaseObject {
-public:
- DECLARE_PERSISTENT(SXObject, BaseObject)
- SXObject(BaseGame *inGame, ScStack *Stack);
- virtual ~SXObject();
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXOBJECT_H +#define WINTERMUTE_SXOBJECT_H + + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class SXObject : public BaseObject { +public: + DECLARE_PERSISTENT(SXObject, BaseObject) + SXObject(BaseGame *inGame, ScStack *Stack); + virtual ~SXObject(); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp index 9bcfe28bbf..8d87a92dc1 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.cpp +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -1,436 +1,436 @@ -/* 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.
-
- * 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.
-
- * 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/base/base_game.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/base/scriptables/script_ext_string.h"
-#include "engines/wintermute/base/scriptables/script_ext_array.h"
-#include "engines/wintermute/utils/string_util.h"
-#include "common/tokenizer.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(SXString, false)
-
-BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) {
- return new SXString(inGame, stack);
-}
-
-//////////////////////////////////////////////////////////////////////////
-SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
- _string = NULL;
- _capacity = 0;
-
- stack->correctParams(1);
- ScValue *val = stack->pop();
-
- if (val->isInt()) {
- _capacity = MAX(0, val->getInt());
- if (_capacity > 0) {
- _string = new char[_capacity];
- memset(_string, 0, _capacity);
- }
- } else {
- setStringVal(val->getString());
- }
-
- if (_capacity == 0) {
- setStringVal("");
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-SXString::~SXString() {
- if (_string) {
- delete[] _string;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void SXString::setStringVal(const char *val) {
- int len = strlen(val);
- if (len >= _capacity) {
- _capacity = len + 1;
- delete[] _string;
- _string = NULL;
- _string = new char[_capacity];
- memset(_string, 0, _capacity);
- }
- strcpy(_string, val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-const char *SXString::scToString() {
- if (_string) {
- return _string;
- } else {
- return "[null string]";
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void SXString::scSetString(const char *val) {
- setStringVal(val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // Substring
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Substring") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
- int end = stack->pop()->getInt();
-
- if (end < start) {
- BaseUtils::swap(&start, &end);
- }
-
- //try {
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
- //WideString subStr = str.substr(start, end - start + 1);
- WideString subStr(str.c_str() + start, end - start + 1);
-
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
- } else {
- stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
- }
- // } catch (std::exception &) {
- // stack->pushNULL();
- // }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Substr
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Substr") == 0) {
- stack->correctParams(2);
- int start = stack->pop()->getInt();
-
- ScValue *val = stack->pop();
- int len = val->getInt();
-
- if (!val->isNULL() && len <= 0) {
- stack->pushString("");
- return STATUS_OK;
- }
-
- if (val->isNULL()) {
- len = strlen(_string) - start;
- }
-
-// try {
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
-// WideString subStr = str.substr(start, len);
- WideString subStr(str.c_str() + start, len);
-
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
- } else {
- stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
- }
-// } catch (std::exception &) {
-// stack->pushNULL();
-// }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ToUpperCase
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ToUpperCase") == 0) {
- stack->correctParams(0);
-
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
- str.toUppercase();
-
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- stack->pushString(StringUtil::wideToUtf8(str).c_str());
- } else {
- stack->pushString(StringUtil::wideToAnsi(str).c_str());
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ToLowerCase
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ToLowerCase") == 0) {
- stack->correctParams(0);
-
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
- str.toLowercase();
-
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- stack->pushString(StringUtil::wideToUtf8(str).c_str());
- } else {
- stack->pushString(StringUtil::wideToAnsi(str).c_str());
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // IndexOf
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IndexOf") == 0) {
- stack->correctParams(2);
-
- const char *strToFind = stack->pop()->getString();
- int index = stack->pop()->getInt();
-
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
- WideString toFind;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- toFind = StringUtil::utf8ToWide(strToFind);
- } else {
- toFind = StringUtil::ansiToWide(strToFind);
- }
-
- int indexOf = StringUtil::indexOf(str, toFind, index);
- stack->pushInt(indexOf);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Split
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Split") == 0) {
- stack->correctParams(1);
- ScValue *val = stack->pop();
- char separators[MAX_PATH_LENGTH] = ",";
- if (!val->isNULL()) {
- strcpy(separators, val->getString());
- }
-
- SXArray *array = new SXArray(_gameRef);
- if (!array) {
- stack->pushNULL();
- return STATUS_OK;
- }
-
-
- WideString str;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- str = StringUtil::utf8ToWide(_string);
- } else {
- str = StringUtil::ansiToWide(_string);
- }
-
- WideString delims;
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- delims = StringUtil::utf8ToWide(separators);
- } else {
- delims = StringUtil::ansiToWide(separators);
- }
-
- Common::Array<WideString> parts;
-
-
-
- Common::StringTokenizer tokenizer(str, delims);
- while (!tokenizer.empty()) {
- Common::String str2 = tokenizer.nextToken();
- parts.push_back(str2);
- }
- // TODO: Clean this up
- /*do {
- pos = StringUtil::IndexOf(Common::String(str.c_str() + start), delims, start);
- //pos = str.find_first_of(delims, start);
- if (pos == start) {
- start = pos + 1;
- } else if (pos == str.size()) {
- parts.push_back(Common::String(str.c_str() + start));
- break;
- } else {
- parts.push_back(Common::String(str.c_str() + start, pos - start));
- start = pos + 1;
- }
- //start = str.find_first_not_of(delims, start);
- start = StringUtil::LastIndexOf(Common::String(str.c_str() + start), delims, start) + 1;
-
- } while (pos != str.size());*/
-
- for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) {
- WideString &part = (*it);
-
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- val = new ScValue(_gameRef, StringUtil::wideToUtf8(part).c_str());
- } else {
- val = new ScValue(_gameRef, StringUtil::wideToAnsi(part).c_str());
- }
-
- array->push(val);
- delete val;
- val = NULL;
- }
-
- stack->pushNative(array, false);
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *SXString::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type (RO)
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("string");
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Length (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Length") == 0) {
- if (_gameRef->_textEncoding == TEXT_UTF8) {
- WideString wstr = StringUtil::utf8ToWide(_string);
- _scValue->setInt(wstr.size());
- } else {
- _scValue->setInt(strlen(_string));
- }
-
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Capacity
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Capacity") == 0) {
- _scValue->setInt(_capacity);
- return _scValue;
- } else {
- return _scValue;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXString::scSetProperty(const char *name, ScValue *value) {
- //////////////////////////////////////////////////////////////////////////
- // Capacity
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Capacity") == 0) {
- int32 newCap = (uint32)value->getInt();
- if (newCap < (int32)(strlen(_string) + 1)) {
- _gameRef->LOG(0, "Warning: cannot lower string capacity");
- } else if (newCap != _capacity) {
- char *newStr = new char[newCap];
- if (newStr) {
- memset(newStr, 0, newCap);
- strcpy(newStr, _string);
- delete[] _string;
- _string = newStr;
- _capacity = newCap;
- }
- }
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool SXString::persist(BasePersistenceManager *persistMgr) {
-
- BaseScriptable::persist(persistMgr);
-
- persistMgr->transfer(TMEMBER(_capacity));
-
- if (persistMgr->getIsSaving()) {
- if (_capacity > 0) {
- persistMgr->putBytes((byte *)_string, _capacity);
- }
- } else {
- if (_capacity > 0) {
- _string = new char[_capacity];
- persistMgr->getBytes((byte *)_string, _capacity);
- } else {
- _string = NULL;
- }
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-int SXString::scCompare(BaseScriptable *val) {
- return strcmp(_string, ((SXString *)val)->_string);
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/base_game.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/base/scriptables/script_ext_string.h" +#include "engines/wintermute/base/scriptables/script_ext_array.h" +#include "engines/wintermute/utils/string_util.h" +#include "common/tokenizer.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(SXString, false) + +BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) { + return new SXString(inGame, stack); +} + +////////////////////////////////////////////////////////////////////////// +SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) { + _string = NULL; + _capacity = 0; + + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (val->isInt()) { + _capacity = MAX(0, val->getInt()); + if (_capacity > 0) { + _string = new char[_capacity]; + memset(_string, 0, _capacity); + } + } else { + setStringVal(val->getString()); + } + + if (_capacity == 0) { + setStringVal(""); + } +} + + +////////////////////////////////////////////////////////////////////////// +SXString::~SXString() { + if (_string) { + delete[] _string; + } +} + + +////////////////////////////////////////////////////////////////////////// +void SXString::setStringVal(const char *val) { + int len = strlen(val); + if (len >= _capacity) { + _capacity = len + 1; + delete[] _string; + _string = NULL; + _string = new char[_capacity]; + memset(_string, 0, _capacity); + } + strcpy(_string, val); +} + + +////////////////////////////////////////////////////////////////////////// +const char *SXString::scToString() { + if (_string) { + return _string; + } else { + return "[null string]"; + } +} + + +////////////////////////////////////////////////////////////////////////// +void SXString::scSetString(const char *val) { + setStringVal(val); +} + + +////////////////////////////////////////////////////////////////////////// +bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // Substring + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Substring") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + int end = stack->pop()->getInt(); + + if (end < start) { + BaseUtils::swap(&start, &end); + } + + //try { + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + + //WideString subStr = str.substr(start, end - start + 1); + WideString subStr(str.c_str() + start, end - start + 1); + + if (_gameRef->_textEncoding == TEXT_UTF8) { + stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); + } else { + stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); + } + // } catch (std::exception &) { + // stack->pushNULL(); + // } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Substr + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Substr") == 0) { + stack->correctParams(2); + int start = stack->pop()->getInt(); + + ScValue *val = stack->pop(); + int len = val->getInt(); + + if (!val->isNULL() && len <= 0) { + stack->pushString(""); + return STATUS_OK; + } + + if (val->isNULL()) { + len = strlen(_string) - start; + } + +// try { + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + +// WideString subStr = str.substr(start, len); + WideString subStr(str.c_str() + start, len); + + if (_gameRef->_textEncoding == TEXT_UTF8) { + stack->pushString(StringUtil::wideToUtf8(subStr).c_str()); + } else { + stack->pushString(StringUtil::wideToAnsi(subStr).c_str()); + } +// } catch (std::exception &) { +// stack->pushNULL(); +// } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ToUpperCase + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ToUpperCase") == 0) { + stack->correctParams(0); + + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + + str.toUppercase(); + + if (_gameRef->_textEncoding == TEXT_UTF8) { + stack->pushString(StringUtil::wideToUtf8(str).c_str()); + } else { + stack->pushString(StringUtil::wideToAnsi(str).c_str()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ToLowerCase + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ToLowerCase") == 0) { + stack->correctParams(0); + + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + + str.toLowercase(); + + if (_gameRef->_textEncoding == TEXT_UTF8) { + stack->pushString(StringUtil::wideToUtf8(str).c_str()); + } else { + stack->pushString(StringUtil::wideToAnsi(str).c_str()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IndexOf + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IndexOf") == 0) { + stack->correctParams(2); + + const char *strToFind = stack->pop()->getString(); + int index = stack->pop()->getInt(); + + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + + WideString toFind; + if (_gameRef->_textEncoding == TEXT_UTF8) { + toFind = StringUtil::utf8ToWide(strToFind); + } else { + toFind = StringUtil::ansiToWide(strToFind); + } + + int indexOf = StringUtil::indexOf(str, toFind, index); + stack->pushInt(indexOf); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Split + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Split") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + char separators[MAX_PATH_LENGTH] = ","; + if (!val->isNULL()) { + strcpy(separators, val->getString()); + } + + SXArray *array = new SXArray(_gameRef); + if (!array) { + stack->pushNULL(); + return STATUS_OK; + } + + + WideString str; + if (_gameRef->_textEncoding == TEXT_UTF8) { + str = StringUtil::utf8ToWide(_string); + } else { + str = StringUtil::ansiToWide(_string); + } + + WideString delims; + if (_gameRef->_textEncoding == TEXT_UTF8) { + delims = StringUtil::utf8ToWide(separators); + } else { + delims = StringUtil::ansiToWide(separators); + } + + Common::Array<WideString> parts; + + + + Common::StringTokenizer tokenizer(str, delims); + while (!tokenizer.empty()) { + Common::String str2 = tokenizer.nextToken(); + parts.push_back(str2); + } + // TODO: Clean this up + /*do { + pos = StringUtil::IndexOf(Common::String(str.c_str() + start), delims, start); + //pos = str.find_first_of(delims, start); + if (pos == start) { + start = pos + 1; + } else if (pos == str.size()) { + parts.push_back(Common::String(str.c_str() + start)); + break; + } else { + parts.push_back(Common::String(str.c_str() + start, pos - start)); + start = pos + 1; + } + //start = str.find_first_not_of(delims, start); + start = StringUtil::LastIndexOf(Common::String(str.c_str() + start), delims, start) + 1; + + } while (pos != str.size());*/ + + for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) { + WideString &part = (*it); + + if (_gameRef->_textEncoding == TEXT_UTF8) { + val = new ScValue(_gameRef, StringUtil::wideToUtf8(part).c_str()); + } else { + val = new ScValue(_gameRef, StringUtil::wideToAnsi(part).c_str()); + } + + array->push(val); + delete val; + val = NULL; + } + + stack->pushNative(array, false); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *SXString::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("string"); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Length (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Length") == 0) { + if (_gameRef->_textEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::utf8ToWide(_string); + _scValue->setInt(wstr.size()); + } else { + _scValue->setInt(strlen(_string)); + } + + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Capacity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Capacity") == 0) { + _scValue->setInt(_capacity); + return _scValue; + } else { + return _scValue; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXString::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Capacity + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Capacity") == 0) { + int32 newCap = (uint32)value->getInt(); + if (newCap < (int32)(strlen(_string) + 1)) { + _gameRef->LOG(0, "Warning: cannot lower string capacity"); + } else if (newCap != _capacity) { + char *newStr = new char[newCap]; + if (newStr) { + memset(newStr, 0, newCap); + strcpy(newStr, _string); + delete[] _string; + _string = newStr; + _capacity = newCap; + } + } + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SXString::persist(BasePersistenceManager *persistMgr) { + + BaseScriptable::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_capacity)); + + if (persistMgr->getIsSaving()) { + if (_capacity > 0) { + persistMgr->putBytes((byte *)_string, _capacity); + } + } else { + if (_capacity > 0) { + _string = new char[_capacity]; + persistMgr->getBytes((byte *)_string, _capacity); + } else { + _string = NULL; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int SXString::scCompare(BaseScriptable *val) { + return strcmp(_string, ((SXString *)val)->_string); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h index c2de3860ed..255b9c57eb 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.h +++ b/engines/wintermute/base/scriptables/script_ext_string.h @@ -1,58 +1,58 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SXSTRING_H
-#define WINTERMUTE_SXSTRING_H
-
-
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-class SXString : public BaseScriptable {
-public:
- virtual int scCompare(BaseScriptable *Val);
- DECLARE_PERSISTENT(SXString, BaseScriptable)
- ScValue *scGetProperty(const char *name);
- bool scSetProperty(const char *name, ScValue *value);
- bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
- void scSetString(const char *val);
- const char *scToString();
- void setStringVal(const char *val);
-
- SXString(BaseGame *inGame, ScStack *Stack);
- virtual ~SXString();
-
-private:
- char *_string;
- int _capacity;
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SXSTRING_H +#define WINTERMUTE_SXSTRING_H + + +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +class SXString : public BaseScriptable { +public: + virtual int scCompare(BaseScriptable *Val); + DECLARE_PERSISTENT(SXString, BaseScriptable) + ScValue *scGetProperty(const char *name); + bool scSetProperty(const char *name, ScValue *value); + bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name); + void scSetString(const char *val); + const char *scToString(); + void setStringVal(const char *val); + + SXString(BaseGame *inGame, ScStack *Stack); + virtual ~SXString(); + +private: + char *_string; + int _capacity; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp index d27748abe6..77367045c2 100644 --- a/engines/wintermute/base/scriptables/script_stack.cpp +++ b/engines/wintermute/base/scriptables/script_stack.cpp @@ -1,232 +1,232 @@ -/* 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.
-
- * 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.
-
- * 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/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/base_game.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(ScStack, false)
-
-//////////////////////////////////////////////////////////////////////////
-ScStack::ScStack(BaseGame *inGame) : BaseClass(inGame) {
- _sP = -1;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScStack::~ScStack() {
-
-#if _DEBUG
- //_gameRef->LOG(0, "STAT: Stack size: %d, SP=%d", _values.size(), _sP);
-#endif
-
- for (uint32 i = 0; i < _values.size(); i++) {
- delete _values[i];
- }
- _values.clear();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScStack::pop() {
- if (_sP < 0) {
- _gameRef->LOG(0, "Fatal: Stack underflow");
- return NULL;
- }
-
- return _values[_sP--];
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::push(ScValue *val) {
- _sP++;
-
- if (_sP < (int32)_values.size()) {
- _values[_sP]->cleanup();
- _values[_sP]->copy(val);
- } else {
- ScValue *copyVal = new ScValue(_gameRef);
- copyVal->copy(val);
- _values.add(copyVal);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScStack::getPushValue() {
- _sP++;
-
- if (_sP >= (int32)_values.size()) {
- ScValue *val = new ScValue(_gameRef);
- _values.add(val);
- }
- _values[_sP]->cleanup();
- return _values[_sP];
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScStack::getTop() {
- if (_sP < 0 || _sP >= (int32)_values.size()) {
- return NULL;
- } else {
- return _values[_sP];
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScStack::getAt(int index) {
- index = _sP - index;
- if (index < 0 || index >= (int32)_values.size()) {
- return NULL;
- } else {
- return _values[index];
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::correctParams(uint32 expectedParams) {
- uint32 nuParams = (uint32)pop()->getInt();
-
- if (expectedParams < nuParams) { // too many params
- while (expectedParams < nuParams) {
- //Pop();
- delete _values[_sP - expectedParams];
- _values.remove_at(_sP - expectedParams);
- nuParams--;
- _sP--;
- }
- } else if (expectedParams > nuParams) { // need more params
- while (expectedParams > nuParams) {
- //Push(null_val);
- ScValue *nullVal = new ScValue(_gameRef);
- nullVal->setNULL();
- _values.insert_at(_sP - nuParams + 1, nullVal);
- nuParams++;
- _sP++;
-
- if ((int32)_values.size() > _sP + 1) {
- delete _values[_values.size() - 1];
- _values.remove_at(_values.size() - 1);
- }
- }
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushNULL() {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setNULL();
- Push(val);
- delete val;
- */
- getPushValue()->setNULL();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushInt(int val) {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setInt(Val);
- Push(val);
- delete val;
- */
- getPushValue()->setInt(val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushFloat(double val) {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setFloat(Val);
- Push(val);
- delete val;
- */
- getPushValue()->setFloat(val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushBool(bool val) {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setBool(Val);
- Push(val);
- delete val;
- */
- getPushValue()->setBool(val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushString(const char *val) {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setString(Val);
- Push(val);
- delete val;
- */
- getPushValue()->setString(val);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScStack::pushNative(BaseScriptable *val, bool persistent) {
- /*
- ScValue* val = new ScValue(_gameRef);
- val->setNative(Val, Persistent);
- Push(val);
- delete val;
- */
-
- getPushValue()->setNative(val, persistent);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScStack::persist(BasePersistenceManager *persistMgr) {
-
- persistMgr->transfer(TMEMBER(_gameRef));
-
- persistMgr->transfer(TMEMBER(_sP));
- _values.persist(persistMgr);
-
- return STATUS_OK;
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/base_game.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(ScStack, false) + +////////////////////////////////////////////////////////////////////////// +ScStack::ScStack(BaseGame *inGame) : BaseClass(inGame) { + _sP = -1; +} + + +////////////////////////////////////////////////////////////////////////// +ScStack::~ScStack() { + +#if _DEBUG + //_gameRef->LOG(0, "STAT: Stack size: %d, SP=%d", _values.size(), _sP); +#endif + + for (uint32 i = 0; i < _values.size(); i++) { + delete _values[i]; + } + _values.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScStack::pop() { + if (_sP < 0) { + _gameRef->LOG(0, "Fatal: Stack underflow"); + return NULL; + } + + return _values[_sP--]; +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::push(ScValue *val) { + _sP++; + + if (_sP < (int32)_values.size()) { + _values[_sP]->cleanup(); + _values[_sP]->copy(val); + } else { + ScValue *copyVal = new ScValue(_gameRef); + copyVal->copy(val); + _values.add(copyVal); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScStack::getPushValue() { + _sP++; + + if (_sP >= (int32)_values.size()) { + ScValue *val = new ScValue(_gameRef); + _values.add(val); + } + _values[_sP]->cleanup(); + return _values[_sP]; +} + + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScStack::getTop() { + if (_sP < 0 || _sP >= (int32)_values.size()) { + return NULL; + } else { + return _values[_sP]; + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScStack::getAt(int index) { + index = _sP - index; + if (index < 0 || index >= (int32)_values.size()) { + return NULL; + } else { + return _values[index]; + } +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::correctParams(uint32 expectedParams) { + uint32 nuParams = (uint32)pop()->getInt(); + + if (expectedParams < nuParams) { // too many params + while (expectedParams < nuParams) { + //Pop(); + delete _values[_sP - expectedParams]; + _values.remove_at(_sP - expectedParams); + nuParams--; + _sP--; + } + } else if (expectedParams > nuParams) { // need more params + while (expectedParams > nuParams) { + //Push(null_val); + ScValue *nullVal = new ScValue(_gameRef); + nullVal->setNULL(); + _values.insert_at(_sP - nuParams + 1, nullVal); + nuParams++; + _sP++; + + if ((int32)_values.size() > _sP + 1) { + delete _values[_values.size() - 1]; + _values.remove_at(_values.size() - 1); + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushNULL() { + /* + ScValue* val = new ScValue(_gameRef); + val->setNULL(); + Push(val); + delete val; + */ + getPushValue()->setNULL(); +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushInt(int val) { + /* + ScValue* val = new ScValue(_gameRef); + val->setInt(Val); + Push(val); + delete val; + */ + getPushValue()->setInt(val); +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushFloat(double val) { + /* + ScValue* val = new ScValue(_gameRef); + val->setFloat(Val); + Push(val); + delete val; + */ + getPushValue()->setFloat(val); +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushBool(bool val) { + /* + ScValue* val = new ScValue(_gameRef); + val->setBool(Val); + Push(val); + delete val; + */ + getPushValue()->setBool(val); +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushString(const char *val) { + /* + ScValue* val = new ScValue(_gameRef); + val->setString(Val); + Push(val); + delete val; + */ + getPushValue()->setString(val); +} + + +////////////////////////////////////////////////////////////////////////// +void ScStack::pushNative(BaseScriptable *val, bool persistent) { + /* + ScValue* val = new ScValue(_gameRef); + val->setNative(Val, Persistent); + Push(val); + delete val; + */ + + getPushValue()->setNative(val, persistent); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScStack::persist(BasePersistenceManager *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER(_sP)); + _values.persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_stack.h b/engines/wintermute/base/scriptables/script_stack.h index 0e2adae518..86d246cf34 100644 --- a/engines/wintermute/base/scriptables/script_stack.h +++ b/engines/wintermute/base/scriptables/script_stack.h @@ -1,66 +1,66 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SCSTACK_H
-#define WINTERMUTE_SCSTACK_H
-
-
-#include "engines/wintermute/base/base.h"
-#include "engines/wintermute/coll_templ.h"
-#include "engines/wintermute/persistent.h"
-
-namespace Wintermute {
-
-class ScValue;
-class BaseScriptable;
-
-class ScStack : public BaseClass {
-public:
- ScValue *getAt(int Index);
- ScValue *getPushValue();
- DECLARE_PERSISTENT(ScStack, BaseClass)
- void pushNative(BaseScriptable *val, bool persistent);
- void pushString(const char *val);
- void pushBool(bool val);
- void pushInt(int val);
- void pushFloat(double val);
- void pushNULL();
- void correctParams(uint32 expectedParams);
- ScValue *getTop();
- void push(ScValue *val);
- ScValue *pop();
- ScStack(BaseGame *inGame);
- virtual ~ScStack();
- BaseArray<ScValue *> _values;
- int _sP;
-
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SCSTACK_H +#define WINTERMUTE_SCSTACK_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/persistent.h" + +namespace Wintermute { + +class ScValue; +class BaseScriptable; + +class ScStack : public BaseClass { +public: + ScValue *getAt(int Index); + ScValue *getPushValue(); + DECLARE_PERSISTENT(ScStack, BaseClass) + void pushNative(BaseScriptable *val, bool persistent); + void pushString(const char *val); + void pushBool(bool val); + void pushInt(int val); + void pushFloat(double val); + void pushNULL(); + void correctParams(uint32 expectedParams); + ScValue *getTop(); + void push(ScValue *val); + ScValue *pop(); + ScStack(BaseGame *inGame); + virtual ~ScStack(); + BaseArray<ScValue *> _values; + int _sP; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp index 03ca69ac7e..0bc7ab5807 100644 --- a/engines/wintermute/base/scriptables/script_value.cpp +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -1,995 +1,995 @@ -/* 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.
-
- * 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.
-
- * 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/platform_osystem.h"
-#include "engines/wintermute/base/base_dynamic_buffer.h"
-#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script.h"
-#include "engines/wintermute/utils/string_util.h"
-#include "engines/wintermute/base/base_scriptable.h"
-
-namespace Wintermute {
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-IMPLEMENT_PERSISTENT(ScValue, false)
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::ScValue(BaseGame *inGame) : BaseClass(inGame) {
- _type = VAL_NULL;
-
- _valBool = false;
- _valInt = 0;
- _valFloat = 0.0f;
- _valNative = NULL;
- _valString = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::ScValue(BaseGame *inGame, bool val) : BaseClass(inGame) {
- _type = VAL_BOOL;
- _valBool = val;
-
- _valInt = 0;
- _valFloat = 0.0f;
- _valNative = NULL;
- _valString = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::ScValue(BaseGame *inGame, int val) : BaseClass(inGame) {
- _type = VAL_INT;
- _valInt = val;
-
- _valFloat = 0.0f;
- _valBool = false;
- _valNative = NULL;
- _valString = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::ScValue(BaseGame *inGame, double val) : BaseClass(inGame) {
- _type = VAL_FLOAT;
- _valFloat = val;
-
- _valInt = 0;
- _valBool = false;
- _valNative = NULL;
- _valString = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::ScValue(BaseGame *inGame, const char *val) : BaseClass(inGame) {
- _type = VAL_STRING;
- _valString = NULL;
- setStringVal(val);
-
- _valBool = false;
- _valInt = 0;
- _valFloat = 0.0f;
- _valNative = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::cleanup(bool ignoreNatives) {
- deleteProps();
-
- if (_valString) {
- delete[] _valString;
- }
-
- if (!ignoreNatives) {
- if (_valNative && !_persistent) {
- _valNative->_refCount--;
- if (_valNative->_refCount <= 0) {
- delete _valNative;
- _valNative = NULL;
- }
- }
- }
-
-
- _type = VAL_NULL;
-
- _valBool = false;
- _valInt = 0;
- _valFloat = 0.0f;
- _valNative = NULL;
- _valString = NULL;
- _valRef = NULL;
- _persistent = false;
- _isConstVar = false;
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue::~ScValue() {
- cleanup();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *ScValue::getProp(const char *name) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getProp(name);
- }
-
- if (_type == VAL_STRING && strcmp(name, "Length") == 0) {
- _gameRef->_scValue->_type = VAL_INT;
-
- if (_gameRef->_textEncoding == TEXT_ANSI) {
- _gameRef->_scValue->setInt(strlen(_valString));
- } else {
- WideString wstr = StringUtil::utf8ToWide(_valString);
- _gameRef->_scValue->setInt(wstr.size());
- }
-
- return _gameRef->_scValue;
- }
-
- ScValue *ret = NULL;
-
- if (_type == VAL_NATIVE && _valNative) {
- ret = _valNative->scGetProperty(name);
- }
-
- if (ret == NULL) {
- _valIter = _valObject.find(name);
- if (_valIter != _valObject.end()) {
- ret = _valIter->_value;
- }
- }
- return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::deleteProp(const char *name) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->deleteProp(name);
- }
-
- _valIter = _valObject.find(name);
- if (_valIter != _valObject.end()) {
- delete _valIter->_value;
- _valIter->_value = NULL;
- }
-
- return STATUS_OK;
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProp(const char *name, ScValue *val, bool copyWhole, bool setAsConst) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->setProp(name, val);
- }
-
- bool ret = STATUS_FAILED;
- if (_type == VAL_NATIVE && _valNative) {
- ret = _valNative->scSetProperty(name, val);
- }
-
- if (DID_FAIL(ret)) {
- ScValue *newVal = NULL;
-
- _valIter = _valObject.find(name);
- if (_valIter != _valObject.end()) {
- newVal = _valIter->_value;
- }
- if (!newVal) {
- newVal = new ScValue(_gameRef);
- } else {
- newVal->cleanup();
- }
-
- newVal->copy(val, copyWhole);
- newVal->_isConstVar = setAsConst;
- _valObject[name] = newVal;
-
- if (_type != VAL_NATIVE) {
- _type = VAL_OBJECT;
- }
-
- /*
- _valIter = _valObject.find(Name);
- if (_valIter != _valObject.end()){
- delete _valIter->_value;
- _valIter->_value = NULL;
- }
- ScValue* val = new ScValue(_gameRef);
- val->Copy(Val, CopyWhole);
- val->_isConstVar = SetAsConst;
- _valObject[Name] = val;
-
- if (_type!=VAL_NATIVE) _type = VAL_OBJECT;
- */
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::propExists(const char *name) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->propExists(name);
- }
- _valIter = _valObject.find(name);
-
- return (_valIter != _valObject.end());
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::deleteProps() {
- _valIter = _valObject.begin();
- while (_valIter != _valObject.end()) {
- delete(ScValue *)_valIter->_value;
- _valIter++;
- }
- _valObject.clear();
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::CleanProps(bool includingNatives) {
- _valIter = _valObject.begin();
- while (_valIter != _valObject.end()) {
- if (!_valIter->_value->_isConstVar && (!_valIter->_value->isNative() || includingNatives)) {
- _valIter->_value->setNULL();
- }
- _valIter++;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isNULL() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isNULL();
- }
-
- return (_type == VAL_NULL);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isNative() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isNative();
- }
-
- return (_type == VAL_NATIVE);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isString() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isString();
- }
-
- return (_type == VAL_STRING);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isFloat() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isFloat();
- }
-
- return (_type == VAL_FLOAT);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isInt() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isInt();
- }
-
- return (_type == VAL_INT);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isBool() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isBool();
- }
-
- return (_type == VAL_BOOL);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::isObject() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->isObject();
- }
-
- return (_type == VAL_OBJECT);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-TValType ScValue::getTypeTolerant() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getType();
- }
-
- return _type;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setBool(bool val) {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setBool(val);
- return;
- }
-
- if (_type == VAL_NATIVE) {
- _valNative->scSetBool(val);
- return;
- }
-
- _valBool = val;
- _type = VAL_BOOL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setInt(int val) {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setInt(val);
- return;
- }
-
- if (_type == VAL_NATIVE) {
- _valNative->scSetInt(val);
- return;
- }
-
- _valInt = val;
- _type = VAL_INT;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setFloat(double val) {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setFloat(val);
- return;
- }
-
- if (_type == VAL_NATIVE) {
- _valNative->scSetFloat(val);
- return;
- }
-
- _valFloat = val;
- _type = VAL_FLOAT;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setString(const char *val) {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setString(val);
- return;
- }
-
- if (_type == VAL_NATIVE) {
- _valNative->scSetString(val);
- return;
- }
-
- setStringVal(val);
- if (_valString) {
- _type = VAL_STRING;
- } else {
- _type = VAL_NULL;
- }
-}
-
-void ScValue::setString(const Common::String &val) {
- setString(val.c_str());
-}
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setStringVal(const char *val) {
- if (_valString) {
- delete[] _valString;
- _valString = NULL;
- }
-
- if (val == NULL) {
- _valString = NULL;
- return;
- }
-
- _valString = new char [strlen(val) + 1];
- if (_valString) {
- strcpy(_valString, val);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setNULL() {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setNULL();
- return;
- }
-
- if (_valNative && !_persistent) {
- _valNative->_refCount--;
- if (_valNative->_refCount <= 0) {
- delete _valNative;
- }
- }
- _valNative = NULL;
- deleteProps();
-
- _type = VAL_NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setNative(BaseScriptable *val, bool persistent) {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setNative(val, persistent);
- return;
- }
-
- if (val == NULL) {
- setNULL();
- } else {
- if (_valNative && !_persistent) {
- _valNative->_refCount--;
- if (_valNative->_refCount <= 0) {
- if (_valNative != val) {
- delete _valNative;
- }
- _valNative = NULL;
- }
- }
-
- _type = VAL_NATIVE;
- _persistent = persistent;
-
- _valNative = val;
- if (_valNative && !_persistent) {
- _valNative->_refCount++;
- }
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setObject() {
- if (_type == VAL_VARIABLE_REF) {
- _valRef->setObject();
- return;
- }
-
- deleteProps();
- _type = VAL_OBJECT;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setReference(ScValue *val) {
- _valRef = val;
- _type = VAL_VARIABLE_REF;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::getBool(bool defaultVal) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getBool();
- }
-
- switch (_type) {
- case VAL_BOOL:
- return _valBool;
-
- case VAL_NATIVE:
- return _valNative->scToBool();
-
- case VAL_INT:
- return (_valInt != 0);
-
- case VAL_FLOAT:
- return (_valFloat != 0.0f);
-
- case VAL_STRING:
- return (scumm_stricmp(_valString, "1") == 0 || scumm_stricmp(_valString, "yes") == 0 || scumm_stricmp(_valString, "true") == 0);
-
- default:
- return defaultVal;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-int ScValue::getInt(int defaultVal) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getInt();
- }
-
- switch (_type) {
- case VAL_BOOL:
- return _valBool ? 1 : 0;
-
- case VAL_NATIVE:
- return _valNative->scToInt();
-
- case VAL_INT:
- return _valInt;
-
- case VAL_FLOAT:
- return (int)_valFloat;
-
- case VAL_STRING:
- return atoi(_valString);
-
- default:
- return defaultVal;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-double ScValue::getFloat(double defaultVal) {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getFloat();
- }
-
- switch (_type) {
- case VAL_BOOL:
- return _valBool ? 1.0f : 0.0f;
-
- case VAL_NATIVE:
- return _valNative->scToFloat();
-
- case VAL_INT:
- return (double)_valInt;
-
- case VAL_FLOAT:
- return _valFloat;
-
- case VAL_STRING:
- return atof(_valString);
-
- default:
- return defaultVal;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-void *ScValue::getMemBuffer() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getMemBuffer();
- }
-
- if (_type == VAL_NATIVE) {
- return _valNative->scToMemBuffer();
- } else {
- return (void *)NULL;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-const char *ScValue::getString() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getString();
- }
-
- switch (_type) {
- case VAL_OBJECT:
- setStringVal("[object]");
- break;
-
- case VAL_NULL:
- setStringVal("[null]");
- break;
-
- case VAL_NATIVE: {
- const char *strVal = _valNative->scToString();
- setStringVal(strVal);
- return strVal;
- break;
- }
-
- case VAL_BOOL:
- setStringVal(_valBool ? "yes" : "no");
- break;
-
- case VAL_INT: {
- char dummy[50];
- sprintf(dummy, "%d", _valInt);
- setStringVal(dummy);
- break;
- }
-
- case VAL_FLOAT: {
- char dummy[50];
- sprintf(dummy, "%f", _valFloat);
- setStringVal(dummy);
- break;
- }
-
- case VAL_STRING:
- break;
-
- default:
- setStringVal("");
- }
-
- return _valString;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-BaseScriptable *ScValue::getNative() {
- if (_type == VAL_VARIABLE_REF) {
- return _valRef->getNative();
- }
-
- if (_type == VAL_NATIVE) {
- return _valNative;
- } else {
- return NULL;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-TValType ScValue::getType() {
- return _type;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::copy(ScValue *orig, bool copyWhole) {
- _gameRef = orig->_gameRef;
-
- if (_valNative && !_persistent) {
- _valNative->_refCount--;
- if (_valNative->_refCount <= 0) {
- if (_valNative != orig->_valNative) {
- delete _valNative;
- }
- _valNative = NULL;
- }
- }
-
- if (orig->_type == VAL_VARIABLE_REF && orig->_valRef && copyWhole) {
- orig = orig->_valRef;
- }
-
- cleanup(true);
-
- _type = orig->_type;
- _valBool = orig->_valBool;
- _valInt = orig->_valInt;
- _valFloat = orig->_valFloat;
- setStringVal(orig->_valString);
-
- _valRef = orig->_valRef;
- _persistent = orig->_persistent;
-
- _valNative = orig->_valNative;
- if (_valNative && !_persistent) {
- _valNative->_refCount++;
- }
-//!!!! ref->native++
-
- // copy properties
- if (orig->_type == VAL_OBJECT && orig->_valObject.size() > 0) {
- orig->_valIter = orig->_valObject.begin();
- while (orig->_valIter != orig->_valObject.end()) {
- _valObject[orig->_valIter->_key] = new ScValue(_gameRef);
- _valObject[orig->_valIter->_key]->copy(orig->_valIter->_value);
- orig->_valIter++;
- }
- } else {
- _valObject.clear();
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-void ScValue::setValue(ScValue *val) {
- if (val->_type == VAL_VARIABLE_REF) {
- setValue(val->_valRef);
- return;
- }
-
- // if being assigned a simple type, preserve native state
- if (_type == VAL_NATIVE && (val->_type == VAL_INT || val->_type == VAL_STRING || val->_type == VAL_BOOL)) {
- switch (val->_type) {
- case VAL_INT:
- _valNative->scSetInt(val->getInt());
- break;
- case VAL_FLOAT:
- _valNative->scSetFloat(val->getFloat());
- break;
- case VAL_BOOL:
- _valNative->scSetBool(val->getBool());
- break;
- case VAL_STRING:
- _valNative->scSetString(val->getString());
- break;
- default:
- warning("ScValue::setValue - unhandled enum");
- break;
- }
- }
- // otherwise just copy everything
- else {
- copy(val);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::persist(BasePersistenceManager *persistMgr) {
- persistMgr->transfer(TMEMBER(_gameRef));
-
- persistMgr->transfer(TMEMBER(_persistent));
- persistMgr->transfer(TMEMBER(_isConstVar));
- persistMgr->transfer(TMEMBER_INT(_type));
- persistMgr->transfer(TMEMBER(_valBool));
- persistMgr->transfer(TMEMBER(_valFloat));
- persistMgr->transfer(TMEMBER(_valInt));
- persistMgr->transfer(TMEMBER(_valNative));
-
- int size;
- const char *str;
- if (persistMgr->getIsSaving()) {
- size = _valObject.size();
- persistMgr->transfer("", &size);
- _valIter = _valObject.begin();
- while (_valIter != _valObject.end()) {
- str = _valIter->_key.c_str();
- persistMgr->transfer("", &str);
- persistMgr->transfer("", &_valIter->_value);
-
- _valIter++;
- }
- } else {
- ScValue *val;
- persistMgr->transfer("", &size);
- for (int i = 0; i < size; i++) {
- persistMgr->transfer("", &str);
- persistMgr->transfer("", &val);
-
- _valObject[str] = val;
- delete[] str;
- }
- }
-
- persistMgr->transfer(TMEMBER(_valRef));
- persistMgr->transfer(TMEMBER(_valString));
-
- /*
- FILE* f = fopen("c:\\val.log", "a+");
- switch(_type)
- {
- case VAL_STRING:
- fprintf(f, "str %s\n", _valString);
- break;
-
- case VAL_INT:
- fprintf(f, "int %d\n", _valInt);
- break;
-
- case VAL_BOOL:
- fprintf(f, "bool %d\n", _valBool);
- break;
-
- case VAL_NULL:
- fprintf(f, "null\n");
- break;
-
- case VAL_NATIVE:
- fprintf(f, "native\n");
- break;
-
- case VAL_VARIABLE_REF:
- fprintf(f, "ref\n");
- break;
-
- case VAL_OBJECT:
- fprintf(f, "obj\n");
- break;
-
- case VAL_FLOAT:
- fprintf(f, "float\n");
- break;
-
- }
- fclose(f);
- */
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::saveAsText(BaseDynamicBuffer *buffer, int indent) {
- _valIter = _valObject.begin();
- while (_valIter != _valObject.end()) {
- buffer->putTextIndent(indent, "PROPERTY {\n");
- buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _valIter->_key.c_str());
- buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _valIter->_value->getString());
- buffer->putTextIndent(indent, "}\n\n");
-
- _valIter++;
- }
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// -1 ... left is less, 0 ... equals, 1 ... left is greater
-int ScValue::compare(ScValue *val1, ScValue *val2) {
- // both natives?
- if (val1->isNative() && val2->isNative()) {
- // same class?
- if (strcmp(val1->getNative()->getClassName(), val2->getNative()->getClassName()) == 0) {
- return val1->getNative()->scCompare(val2->getNative());
- } else {
- return strcmp(val1->getString(), val2->getString());
- }
- }
-
- // both objects?
- if (val1->isObject() && val2->isObject()) {
- return -1;
- }
-
-
- // null states
- if (val1->isNULL() && !val2->isNULL()) {
- return -1;
- } else if (!val1->isNULL() && val2->isNULL()) {
- return 1;
- } else if (val1->isNULL() && val2->isNULL()) {
- return 0;
- }
-
- // one of them is string? convert both to string
- if (val1->isString() || val2->isString()) {
- return strcmp(val1->getString(), val2->getString());
- }
-
- // one of them is float?
- if (val1->isFloat() || val2->isFloat()) {
- if (val1->getFloat() < val2->getFloat()) {
- return -1;
- } else if (val1->getFloat() > val2->getFloat()) {
- return 1;
- } else {
- return 0;
- }
- }
-
- // otherwise compare as int's
- if (val1->getInt() < val2->getInt()) {
- return -1;
- } else if (val1->getInt() > val2->getInt()) {
- return 1;
- } else {
- return 0;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-int ScValue::compareStrict(ScValue *val1, ScValue *val2) {
- if (val1->getTypeTolerant() != val2->getTypeTolerant()) {
- return -1;
- } else {
- return ScValue::compare(val1, val2);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProperty(const char *propName, int value) {
- ScValue *val = new ScValue(_gameRef, value);
- bool ret = DID_SUCCEED(setProp(propName, val));
- delete val;
- return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProperty(const char *propName, const char *value) {
- ScValue *val = new ScValue(_gameRef, value);
- bool ret = DID_SUCCEED(setProp(propName, val));
- delete val;
- return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProperty(const char *propName, double value) {
- ScValue *val = new ScValue(_gameRef, value);
- bool ret = DID_SUCCEED(setProp(propName, val));
- delete val;
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProperty(const char *propName, bool value) {
- ScValue *val = new ScValue(_gameRef, value);
- bool ret = DID_SUCCEED(setProp(propName, val));
- delete val;
- return ret;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool ScValue::setProperty(const char *propName) {
- ScValue *val = new ScValue(_gameRef);
- bool ret = DID_SUCCEED(setProp(propName, val));
- delete val;
- return ret;
-}
-
-} // end of namespace Wintermute
+/* 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. + + * 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. + + * 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/platform_osystem.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/base/base_scriptable.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(ScValue, false) + +////////////////////////////////////////////////////////////////////////// +ScValue::ScValue(BaseGame *inGame) : BaseClass(inGame) { + _type = VAL_NULL; + + _valBool = false; + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue::ScValue(BaseGame *inGame, bool val) : BaseClass(inGame) { + _type = VAL_BOOL; + _valBool = val; + + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue::ScValue(BaseGame *inGame, int val) : BaseClass(inGame) { + _type = VAL_INT; + _valInt = val; + + _valFloat = 0.0f; + _valBool = false; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue::ScValue(BaseGame *inGame, double val) : BaseClass(inGame) { + _type = VAL_FLOAT; + _valFloat = val; + + _valInt = 0; + _valBool = false; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue::ScValue(BaseGame *inGame, const char *val) : BaseClass(inGame) { + _type = VAL_STRING; + _valString = NULL; + setStringVal(val); + + _valBool = false; + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::cleanup(bool ignoreNatives) { + deleteProps(); + + if (_valString) { + delete[] _valString; + } + + if (!ignoreNatives) { + if (_valNative && !_persistent) { + _valNative->_refCount--; + if (_valNative->_refCount <= 0) { + delete _valNative; + _valNative = NULL; + } + } + } + + + _type = VAL_NULL; + + _valBool = false; + _valInt = 0; + _valFloat = 0.0f; + _valNative = NULL; + _valString = NULL; + _valRef = NULL; + _persistent = false; + _isConstVar = false; +} + + + +////////////////////////////////////////////////////////////////////////// +ScValue::~ScValue() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *ScValue::getProp(const char *name) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getProp(name); + } + + if (_type == VAL_STRING && strcmp(name, "Length") == 0) { + _gameRef->_scValue->_type = VAL_INT; + + if (_gameRef->_textEncoding == TEXT_ANSI) { + _gameRef->_scValue->setInt(strlen(_valString)); + } else { + WideString wstr = StringUtil::utf8ToWide(_valString); + _gameRef->_scValue->setInt(wstr.size()); + } + + return _gameRef->_scValue; + } + + ScValue *ret = NULL; + + if (_type == VAL_NATIVE && _valNative) { + ret = _valNative->scGetProperty(name); + } + + if (ret == NULL) { + _valIter = _valObject.find(name); + if (_valIter != _valObject.end()) { + ret = _valIter->_value; + } + } + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool ScValue::deleteProp(const char *name) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->deleteProp(name); + } + + _valIter = _valObject.find(name); + if (_valIter != _valObject.end()) { + delete _valIter->_value; + _valIter->_value = NULL; + } + + return STATUS_OK; +} + + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProp(const char *name, ScValue *val, bool copyWhole, bool setAsConst) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->setProp(name, val); + } + + bool ret = STATUS_FAILED; + if (_type == VAL_NATIVE && _valNative) { + ret = _valNative->scSetProperty(name, val); + } + + if (DID_FAIL(ret)) { + ScValue *newVal = NULL; + + _valIter = _valObject.find(name); + if (_valIter != _valObject.end()) { + newVal = _valIter->_value; + } + if (!newVal) { + newVal = new ScValue(_gameRef); + } else { + newVal->cleanup(); + } + + newVal->copy(val, copyWhole); + newVal->_isConstVar = setAsConst; + _valObject[name] = newVal; + + if (_type != VAL_NATIVE) { + _type = VAL_OBJECT; + } + + /* + _valIter = _valObject.find(Name); + if (_valIter != _valObject.end()){ + delete _valIter->_value; + _valIter->_value = NULL; + } + ScValue* val = new ScValue(_gameRef); + val->Copy(Val, CopyWhole); + val->_isConstVar = SetAsConst; + _valObject[Name] = val; + + if (_type!=VAL_NATIVE) _type = VAL_OBJECT; + */ + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::propExists(const char *name) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->propExists(name); + } + _valIter = _valObject.find(name); + + return (_valIter != _valObject.end()); +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::deleteProps() { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + delete(ScValue *)_valIter->_value; + _valIter++; + } + _valObject.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::CleanProps(bool includingNatives) { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + if (!_valIter->_value->_isConstVar && (!_valIter->_value->isNative() || includingNatives)) { + _valIter->_value->setNULL(); + } + _valIter++; + } +} + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isNULL() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isNULL(); + } + + return (_type == VAL_NULL); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isNative() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isNative(); + } + + return (_type == VAL_NATIVE); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isString() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isString(); + } + + return (_type == VAL_STRING); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isFloat() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isFloat(); + } + + return (_type == VAL_FLOAT); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isInt() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isInt(); + } + + return (_type == VAL_INT); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isBool() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isBool(); + } + + return (_type == VAL_BOOL); +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::isObject() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->isObject(); + } + + return (_type == VAL_OBJECT); +} + + +////////////////////////////////////////////////////////////////////////// +TValType ScValue::getTypeTolerant() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getType(); + } + + return _type; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setBool(bool val) { + if (_type == VAL_VARIABLE_REF) { + _valRef->setBool(val); + return; + } + + if (_type == VAL_NATIVE) { + _valNative->scSetBool(val); + return; + } + + _valBool = val; + _type = VAL_BOOL; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setInt(int val) { + if (_type == VAL_VARIABLE_REF) { + _valRef->setInt(val); + return; + } + + if (_type == VAL_NATIVE) { + _valNative->scSetInt(val); + return; + } + + _valInt = val; + _type = VAL_INT; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setFloat(double val) { + if (_type == VAL_VARIABLE_REF) { + _valRef->setFloat(val); + return; + } + + if (_type == VAL_NATIVE) { + _valNative->scSetFloat(val); + return; + } + + _valFloat = val; + _type = VAL_FLOAT; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setString(const char *val) { + if (_type == VAL_VARIABLE_REF) { + _valRef->setString(val); + return; + } + + if (_type == VAL_NATIVE) { + _valNative->scSetString(val); + return; + } + + setStringVal(val); + if (_valString) { + _type = VAL_STRING; + } else { + _type = VAL_NULL; + } +} + +void ScValue::setString(const Common::String &val) { + setString(val.c_str()); +} + +////////////////////////////////////////////////////////////////////////// +void ScValue::setStringVal(const char *val) { + if (_valString) { + delete[] _valString; + _valString = NULL; + } + + if (val == NULL) { + _valString = NULL; + return; + } + + _valString = new char [strlen(val) + 1]; + if (_valString) { + strcpy(_valString, val); + } +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setNULL() { + if (_type == VAL_VARIABLE_REF) { + _valRef->setNULL(); + return; + } + + if (_valNative && !_persistent) { + _valNative->_refCount--; + if (_valNative->_refCount <= 0) { + delete _valNative; + } + } + _valNative = NULL; + deleteProps(); + + _type = VAL_NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setNative(BaseScriptable *val, bool persistent) { + if (_type == VAL_VARIABLE_REF) { + _valRef->setNative(val, persistent); + return; + } + + if (val == NULL) { + setNULL(); + } else { + if (_valNative && !_persistent) { + _valNative->_refCount--; + if (_valNative->_refCount <= 0) { + if (_valNative != val) { + delete _valNative; + } + _valNative = NULL; + } + } + + _type = VAL_NATIVE; + _persistent = persistent; + + _valNative = val; + if (_valNative && !_persistent) { + _valNative->_refCount++; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setObject() { + if (_type == VAL_VARIABLE_REF) { + _valRef->setObject(); + return; + } + + deleteProps(); + _type = VAL_OBJECT; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setReference(ScValue *val) { + _valRef = val; + _type = VAL_VARIABLE_REF; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::getBool(bool defaultVal) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getBool(); + } + + switch (_type) { + case VAL_BOOL: + return _valBool; + + case VAL_NATIVE: + return _valNative->scToBool(); + + case VAL_INT: + return (_valInt != 0); + + case VAL_FLOAT: + return (_valFloat != 0.0f); + + case VAL_STRING: + return (scumm_stricmp(_valString, "1") == 0 || scumm_stricmp(_valString, "yes") == 0 || scumm_stricmp(_valString, "true") == 0); + + default: + return defaultVal; + } +} + + +////////////////////////////////////////////////////////////////////////// +int ScValue::getInt(int defaultVal) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getInt(); + } + + switch (_type) { + case VAL_BOOL: + return _valBool ? 1 : 0; + + case VAL_NATIVE: + return _valNative->scToInt(); + + case VAL_INT: + return _valInt; + + case VAL_FLOAT: + return (int)_valFloat; + + case VAL_STRING: + return atoi(_valString); + + default: + return defaultVal; + } +} + + +////////////////////////////////////////////////////////////////////////// +double ScValue::getFloat(double defaultVal) { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getFloat(); + } + + switch (_type) { + case VAL_BOOL: + return _valBool ? 1.0f : 0.0f; + + case VAL_NATIVE: + return _valNative->scToFloat(); + + case VAL_INT: + return (double)_valInt; + + case VAL_FLOAT: + return _valFloat; + + case VAL_STRING: + return atof(_valString); + + default: + return defaultVal; + } +} + +////////////////////////////////////////////////////////////////////////// +void *ScValue::getMemBuffer() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getMemBuffer(); + } + + if (_type == VAL_NATIVE) { + return _valNative->scToMemBuffer(); + } else { + return (void *)NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *ScValue::getString() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getString(); + } + + switch (_type) { + case VAL_OBJECT: + setStringVal("[object]"); + break; + + case VAL_NULL: + setStringVal("[null]"); + break; + + case VAL_NATIVE: { + const char *strVal = _valNative->scToString(); + setStringVal(strVal); + return strVal; + break; + } + + case VAL_BOOL: + setStringVal(_valBool ? "yes" : "no"); + break; + + case VAL_INT: { + char dummy[50]; + sprintf(dummy, "%d", _valInt); + setStringVal(dummy); + break; + } + + case VAL_FLOAT: { + char dummy[50]; + sprintf(dummy, "%f", _valFloat); + setStringVal(dummy); + break; + } + + case VAL_STRING: + break; + + default: + setStringVal(""); + } + + return _valString; +} + + +////////////////////////////////////////////////////////////////////////// +BaseScriptable *ScValue::getNative() { + if (_type == VAL_VARIABLE_REF) { + return _valRef->getNative(); + } + + if (_type == VAL_NATIVE) { + return _valNative; + } else { + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +TValType ScValue::getType() { + return _type; +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::copy(ScValue *orig, bool copyWhole) { + _gameRef = orig->_gameRef; + + if (_valNative && !_persistent) { + _valNative->_refCount--; + if (_valNative->_refCount <= 0) { + if (_valNative != orig->_valNative) { + delete _valNative; + } + _valNative = NULL; + } + } + + if (orig->_type == VAL_VARIABLE_REF && orig->_valRef && copyWhole) { + orig = orig->_valRef; + } + + cleanup(true); + + _type = orig->_type; + _valBool = orig->_valBool; + _valInt = orig->_valInt; + _valFloat = orig->_valFloat; + setStringVal(orig->_valString); + + _valRef = orig->_valRef; + _persistent = orig->_persistent; + + _valNative = orig->_valNative; + if (_valNative && !_persistent) { + _valNative->_refCount++; + } +//!!!! ref->native++ + + // copy properties + if (orig->_type == VAL_OBJECT && orig->_valObject.size() > 0) { + orig->_valIter = orig->_valObject.begin(); + while (orig->_valIter != orig->_valObject.end()) { + _valObject[orig->_valIter->_key] = new ScValue(_gameRef); + _valObject[orig->_valIter->_key]->copy(orig->_valIter->_value); + orig->_valIter++; + } + } else { + _valObject.clear(); + } +} + + +////////////////////////////////////////////////////////////////////////// +void ScValue::setValue(ScValue *val) { + if (val->_type == VAL_VARIABLE_REF) { + setValue(val->_valRef); + return; + } + + // if being assigned a simple type, preserve native state + if (_type == VAL_NATIVE && (val->_type == VAL_INT || val->_type == VAL_STRING || val->_type == VAL_BOOL)) { + switch (val->_type) { + case VAL_INT: + _valNative->scSetInt(val->getInt()); + break; + case VAL_FLOAT: + _valNative->scSetFloat(val->getFloat()); + break; + case VAL_BOOL: + _valNative->scSetBool(val->getBool()); + break; + case VAL_STRING: + _valNative->scSetString(val->getString()); + break; + default: + warning("ScValue::setValue - unhandled enum"); + break; + } + } + // otherwise just copy everything + else { + copy(val); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::persist(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER(_persistent)); + persistMgr->transfer(TMEMBER(_isConstVar)); + persistMgr->transfer(TMEMBER_INT(_type)); + persistMgr->transfer(TMEMBER(_valBool)); + persistMgr->transfer(TMEMBER(_valFloat)); + persistMgr->transfer(TMEMBER(_valInt)); + persistMgr->transfer(TMEMBER(_valNative)); + + int size; + const char *str; + if (persistMgr->getIsSaving()) { + size = _valObject.size(); + persistMgr->transfer("", &size); + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + str = _valIter->_key.c_str(); + persistMgr->transfer("", &str); + persistMgr->transfer("", &_valIter->_value); + + _valIter++; + } + } else { + ScValue *val; + persistMgr->transfer("", &size); + for (int i = 0; i < size; i++) { + persistMgr->transfer("", &str); + persistMgr->transfer("", &val); + + _valObject[str] = val; + delete[] str; + } + } + + persistMgr->transfer(TMEMBER(_valRef)); + persistMgr->transfer(TMEMBER(_valString)); + + /* + FILE* f = fopen("c:\\val.log", "a+"); + switch(_type) + { + case VAL_STRING: + fprintf(f, "str %s\n", _valString); + break; + + case VAL_INT: + fprintf(f, "int %d\n", _valInt); + break; + + case VAL_BOOL: + fprintf(f, "bool %d\n", _valBool); + break; + + case VAL_NULL: + fprintf(f, "null\n"); + break; + + case VAL_NATIVE: + fprintf(f, "native\n"); + break; + + case VAL_VARIABLE_REF: + fprintf(f, "ref\n"); + break; + + case VAL_OBJECT: + fprintf(f, "obj\n"); + break; + + case VAL_FLOAT: + fprintf(f, "float\n"); + break; + + } + fclose(f); + */ + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::saveAsText(BaseDynamicBuffer *buffer, int indent) { + _valIter = _valObject.begin(); + while (_valIter != _valObject.end()) { + buffer->putTextIndent(indent, "PROPERTY {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _valIter->_key.c_str()); + buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _valIter->_value->getString()); + buffer->putTextIndent(indent, "}\n\n"); + + _valIter++; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// -1 ... left is less, 0 ... equals, 1 ... left is greater +int ScValue::compare(ScValue *val1, ScValue *val2) { + // both natives? + if (val1->isNative() && val2->isNative()) { + // same class? + if (strcmp(val1->getNative()->getClassName(), val2->getNative()->getClassName()) == 0) { + return val1->getNative()->scCompare(val2->getNative()); + } else { + return strcmp(val1->getString(), val2->getString()); + } + } + + // both objects? + if (val1->isObject() && val2->isObject()) { + return -1; + } + + + // null states + if (val1->isNULL() && !val2->isNULL()) { + return -1; + } else if (!val1->isNULL() && val2->isNULL()) { + return 1; + } else if (val1->isNULL() && val2->isNULL()) { + return 0; + } + + // one of them is string? convert both to string + if (val1->isString() || val2->isString()) { + return strcmp(val1->getString(), val2->getString()); + } + + // one of them is float? + if (val1->isFloat() || val2->isFloat()) { + if (val1->getFloat() < val2->getFloat()) { + return -1; + } else if (val1->getFloat() > val2->getFloat()) { + return 1; + } else { + return 0; + } + } + + // otherwise compare as int's + if (val1->getInt() < val2->getInt()) { + return -1; + } else if (val1->getInt() > val2->getInt()) { + return 1; + } else { + return 0; + } +} + + +////////////////////////////////////////////////////////////////////////// +int ScValue::compareStrict(ScValue *val1, ScValue *val2) { + if (val1->getTypeTolerant() != val2->getTypeTolerant()) { + return -1; + } else { + return ScValue::compare(val1, val2); + } +} + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProperty(const char *propName, int value) { + ScValue *val = new ScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProperty(const char *propName, const char *value) { + ScValue *val = new ScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProperty(const char *propName, double value) { + ScValue *val = new ScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProperty(const char *propName, bool value) { + ScValue *val = new ScValue(_gameRef, value); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool ScValue::setProperty(const char *propName) { + ScValue *val = new ScValue(_gameRef); + bool ret = DID_SUCCEED(setProp(propName, val)); + delete val; + return ret; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h index af31014bac..bf7d9cd8a1 100644 --- a/engines/wintermute/base/scriptables/script_value.h +++ b/engines/wintermute/base/scriptables/script_value.h @@ -1,113 +1,113 @@ -/* 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.
-
- * 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.
-
- * 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
- */
-
-#ifndef WINTERMUTE_SCVALUE_H
-#define WINTERMUTE_SCVALUE_H
-
-
-#include "engines/wintermute/base/base.h"
-#include "engines/wintermute/persistent.h"
-#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
-#include "common/str.h"
-
-namespace Wintermute {
-
-class ScScript;
-class BaseScriptable;
-
-class ScValue : public BaseClass {
-public:
- static int compare(ScValue *val1, ScValue *val2);
- static int compareStrict(ScValue *val1, ScValue *val2);
- TValType getTypeTolerant();
- void cleanup(bool ignoreNatives = false);
- DECLARE_PERSISTENT(ScValue, BaseClass)
-
- bool _isConstVar;
- bool saveAsText(BaseDynamicBuffer *buffer, int indent);
- void setValue(ScValue *val);
- bool _persistent;
- bool propExists(const char *name);
- void copy(ScValue *orig, bool copyWhole = false);
- void setStringVal(const char *val);
- TValType getType();
- bool getBool(bool defaultVal = false);
- int getInt(int defaultVal = 0);
- double getFloat(double defaultVal = 0.0f);
- const char *getString();
- void *getMemBuffer();
- BaseScriptable *getNative();
- bool deleteProp(const char *name);
- void deleteProps();
- void CleanProps(bool includingNatives);
- void setBool(bool val);
- void setInt(int val);
- void setFloat(double val);
- void setString(const char *val);
- void setString(const Common::String &val);
- void setNULL();
- void setNative(BaseScriptable *val, bool persistent = false);
- void setObject();
- void setReference(ScValue *val);
- bool isNULL();
- bool isNative();
- bool isString();
- bool isBool();
- bool isFloat();
- bool isInt();
- bool isObject();
- bool setProp(const char *name, ScValue *val, bool copyWhole = false, bool setAsConst = false);
- ScValue *getProp(const char *name);
- BaseScriptable *_valNative;
- ScValue *_valRef;
-private:
- bool _valBool;
- int _valInt;
- double _valFloat;
- char *_valString;
-public:
- TValType _type;
- ScValue(BaseGame *inGame);
- ScValue(BaseGame *inGame, bool Val);
- ScValue(BaseGame *inGame, int Val);
- ScValue(BaseGame *inGame, double Val);
- ScValue(BaseGame *inGame, const char *Val);
- virtual ~ScValue();
- Common::HashMap<Common::String, ScValue *> _valObject;
- Common::HashMap<Common::String, ScValue *>::iterator _valIter;
-
- bool setProperty(const char *propName, int value);
- bool setProperty(const char *propName, const char *value);
- bool setProperty(const char *propName, double value);
- bool setProperty(const char *propName, bool value);
- bool setProperty(const char *propName);
-};
-
-} // end of namespace Wintermute
-
-#endif
+/* 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. + + * 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. + + * 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 + */ + +#ifndef WINTERMUTE_SCVALUE_H +#define WINTERMUTE_SCVALUE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView +#include "common/str.h" + +namespace Wintermute { + +class ScScript; +class BaseScriptable; + +class ScValue : public BaseClass { +public: + static int compare(ScValue *val1, ScValue *val2); + static int compareStrict(ScValue *val1, ScValue *val2); + TValType getTypeTolerant(); + void cleanup(bool ignoreNatives = false); + DECLARE_PERSISTENT(ScValue, BaseClass) + + bool _isConstVar; + bool saveAsText(BaseDynamicBuffer *buffer, int indent); + void setValue(ScValue *val); + bool _persistent; + bool propExists(const char *name); + void copy(ScValue *orig, bool copyWhole = false); + void setStringVal(const char *val); + TValType getType(); + bool getBool(bool defaultVal = false); + int getInt(int defaultVal = 0); + double getFloat(double defaultVal = 0.0f); + const char *getString(); + void *getMemBuffer(); + BaseScriptable *getNative(); + bool deleteProp(const char *name); + void deleteProps(); + void CleanProps(bool includingNatives); + void setBool(bool val); + void setInt(int val); + void setFloat(double val); + void setString(const char *val); + void setString(const Common::String &val); + void setNULL(); + void setNative(BaseScriptable *val, bool persistent = false); + void setObject(); + void setReference(ScValue *val); + bool isNULL(); + bool isNative(); + bool isString(); + bool isBool(); + bool isFloat(); + bool isInt(); + bool isObject(); + bool setProp(const char *name, ScValue *val, bool copyWhole = false, bool setAsConst = false); + ScValue *getProp(const char *name); + BaseScriptable *_valNative; + ScValue *_valRef; +private: + bool _valBool; + int _valInt; + double _valFloat; + char *_valString; +public: + TValType _type; + ScValue(BaseGame *inGame); + ScValue(BaseGame *inGame, bool Val); + ScValue(BaseGame *inGame, int Val); + ScValue(BaseGame *inGame, double Val); + ScValue(BaseGame *inGame, const char *Val); + virtual ~ScValue(); + Common::HashMap<Common::String, ScValue *> _valObject; + Common::HashMap<Common::String, ScValue *>::iterator _valIter; + + bool setProperty(const char *propName, int value); + bool setProperty(const char *propName, const char *value); + bool setProperty(const char *propName, double value); + bool setProperty(const char *propName, bool value); + bool setProperty(const char *propName); +}; + +} // end of namespace Wintermute + +#endif |