bool BasePersistenceManager::readHeader(const Common::String &filename) {
	cleanup();

	_saving = false;

	_loadStream = g_system->getSavefileManager()->openForLoading(filename);
	//_buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &_bufferSize);
	if (_loadStream) {
		uint32 magic;
		magic = getDWORD();

		if (magic != DCGF_MAGIC) {
			cleanup();
			return STATUS_FAILED;
		}

		magic = getDWORD();

		if (magic == SAVE_MAGIC || magic == SAVE_MAGIC_2) {
			_savedVerMajor = _loadStream->readByte();
			_savedVerMinor = _loadStream->readByte();
			_savedExtMajor = _loadStream->readByte();
			_savedExtMinor = _loadStream->readByte();

			if (magic == SAVE_MAGIC_2) {
				_savedVerBuild = (byte)getDWORD();
				_savedName = getStringObj();

				// load thumbnail
				_thumbnailDataSize = getDWORD();
				if (_thumbnailDataSize > 0) {
					_thumbnailData = new byte[_thumbnailDataSize];
					if (_thumbnailData) {
						getBytes(_thumbnailData, _thumbnailDataSize);
					} else {
						_thumbnailDataSize = 0;
					}
				}
			} else {
				_savedVerBuild = 35;    // last build with ver1 savegames
			}

			uint32 dataOffset = getDWORD();

			_savedDescription = getString();
			_savedTimestamp = getTimeDate();
			_savedPlayTime = _loadStream->readUint32LE();

			_offset = dataOffset;

			return STATUS_OK;
		}
	}

	cleanup();
	return STATUS_FAILED;
}
Exemplo n.º 2
0
bool ScScript::executeInstruction() {
	bool ret = STATUS_OK;

	uint32 dw;
	const char *str = nullptr;

	//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 == nullptr) {
			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 == nullptr || op2 == nullptr) {
			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 == nullptr || op2 == nullptr) {
			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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
int RegistryObject::getInt(const char* pszSubKey, const char* pszValue)
{
   return static_cast<int>(getDWORD(pszSubKey,pszValue));
}