diff options
author | Filippos Karapetis | 2008-04-20 14:47:37 +0000 |
---|---|---|
committer | Filippos Karapetis | 2008-04-20 14:47:37 +0000 |
commit | 7ca439f410ac1c46a387567b30271ae4e4a2ed30 (patch) | |
tree | 4d4154169b074293581ad6a11ee821290418f4fb /engines/m4/script.cpp | |
parent | d0590a09eac68d5cde64d37fb2e5bbd1471a676a (diff) | |
download | scummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.tar.gz scummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.tar.bz2 scummvm-rg350-7ca439f410ac1c46a387567b30271ae4e4a2ed30.zip |
Initial import of the work in progress M4 engine
svn-id: r31600
Diffstat (limited to 'engines/m4/script.cpp')
-rw-r--r-- | engines/m4/script.cpp | 1406 |
1 files changed, 1406 insertions, 0 deletions
diff --git a/engines/m4/script.cpp b/engines/m4/script.cpp new file mode 100644 index 0000000000..e7026a381d --- /dev/null +++ b/engines/m4/script.cpp @@ -0,0 +1,1406 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/system.h" + +#include "m4/m4.h" +#include "m4/script.h" +#include "m4/resource.h" + +namespace M4 { + +enum OpcodeType { + opRet = 0, + opCall, + opCallKernel, + opPush, + opPush0, + opPush1, + opPushNeg1, + opPop, + opMov, + opAdd, + opSub, + opInc, + opDec, + opCmp, + opJmp, + opJmpByTable, + opJz, + opJnz, + opJe, + opJne, + opJl, + opJle, + opJg, + opJge, + opXor, + opShl, + opShr, + + opDebug, + + opInvalid +}; + +const char *opcodeNames[] = { + "opRet", + "opCall", + "opCallKernel", + "opPush", + "opPush0", + "opPush1", + "opPushNeg1", + "opPop", + "opMov", + "opAdd", + "opSub", + "opInc", + "opDec", + "opCmp", + "opJmp", + "opJmpByTable", + "opJz", + "opJnz", + "opJe", + "opJne", + "opJl", + "opJle", + "opJg", + "opJge", + "opXor", + "opShl", + "opShr", + "opDebug", + "opInvalid" +}; + +StringTable::StringTable() : _stringsData(NULL) { +} + +StringTable::~StringTable() { + if (_stringsData) + delete[] _stringsData; +} + +void StringTable::load(Common::File *fd) { + int stringSize = fd->readUint32LE(); + int stringCount = fd->readUint32LE(); + _stringsData = new char[stringSize]; + fd->read(_stringsData, stringSize); + char *stringPtr = _stringsData; + for (int i = 0; i < stringCount; i++) { + _strings.push_back((const char*)stringPtr); + stringPtr += strlen(stringPtr) + 1; + } +} + +SeriesStreamBreakList::~SeriesStreamBreakList() { +} + +void SeriesStreamBreakList::load(Common::File *fd) { + uint32 count = fd->readUint32LE(); + printf("SeriesStreamBreakList::load() count = %d\n", count); + for (uint32 i = 0; i < count; i++) { + SeriesStreamBreakItem *item = new SeriesStreamBreakItem(); + item->frameNum = fd->readUint32LE(); + item->digiName = _inter->loadGlobalString(fd); + item->digiChannel = fd->readUint32LE(); + item->digiVolume = fd->readUint32LE(); + item->trigger = fd->readUint32LE(); + item->flags = fd->readUint32LE(); + item->variable.type = kGameVar; + item->variable.value = fd->readUint32LE(); + item->value = fd->readUint32LE(); + _items.push_back(item); + + printf("%02d: frameNum = %d; digiName = %s; digiChannel = %d; digiVolume = %d; trigger = %d; flags = %d; variable = %d; value = %d\n", + i, item->frameNum, item->digiName, item->digiChannel, item->digiVolume, item->trigger, item->flags, item->variable.value, item->value); + + } +} + +SaidArray::~SaidArray() { +} + +void SaidArray::load(Common::File *fd) { + uint32 count = fd->readUint32LE(); + printf("SaidArray::load() count = %d\n", count); + for (uint32 i = 0; i < count; i++) { + SaidArrayItem *item = new SaidArrayItem(); + item->itemName = _inter->loadGlobalString(fd); + item->digiNameLook = _inter->loadGlobalString(fd); + item->digiNameTake = _inter->loadGlobalString(fd); + item->digiNameGear = _inter->loadGlobalString(fd); + _items.push_back(item); + + printf("itemName = %s; digiNameLook = %s; digiNameTake = %s; digiNameGear = %s\n", + item->itemName, item->digiNameLook, item->digiNameTake, item->digiNameGear); + + } +} + +ParserArray::~ParserArray() { +} + +void ParserArray::load(Common::File *fd) { + uint32 count = fd->readUint32LE(); + printf("ParserArray::load() count = %d\n", count); + for (uint32 i = 0; i < count; i++) { + ParserArrayItem *item = new ParserArrayItem(); + item->w0 = _inter->loadGlobalString(fd); + item->w1 = _inter->loadGlobalString(fd); + item->trigger = fd->readUint32LE(); + item->testVariable.type = kGameVar; + item->testVariable.value = fd->readUint32LE(); + item->testValue = fd->readUint32LE(); + item->variable.type = kGameVar; + item->variable.value = fd->readUint32LE(); + item->value = fd->readUint32LE(); + _items.push_back(item); + + printf("w0 = %s; w1 = %s; trigger = %d; testVariable = %d; testValue = %d; variable = %d; value = %d\n", + item->w0, item->w1, item->trigger, item->testVariable.value, item->testValue, item->variable.value, item->value); + + } +} + +ScriptFunction::ScriptFunction(ScriptInterpreter *inter) : _inter(inter) { +} + +ScriptFunction::~ScriptFunction() { + if (_code) + delete _code; +} + +void ScriptFunction::load(Common::File *fd) { + printf("ScriptFunction::load()\n"); + uint32 size = fd->readUint32LE(); + printf("ScriptFunction::load() size = %d\n", size); + _code = fd->readStream(size); +} + +void ScriptFunction::jumpAbsolute(uint32 ofs) { + _code->seek(ofs); +} + +void ScriptFunction::jumpRelative(int32 ofs) { + _code->seek(ofs, SEEK_CUR); +} + +byte ScriptFunction::readByte() { + return _code->readByte(); +} + +uint32 ScriptFunction::readUint32() { + return _code->readUint32LE(); +} + + +ScriptInterpreter::ScriptInterpreter(M4Engine *vm) : _scriptFile(NULL), _vm(vm) { + initScriptKernel(); + _dataCache = new ScriptDataCache(this); + _runningFunction = NULL; +} + +ScriptInterpreter::~ScriptInterpreter() { + close(); + delete _dataCache; +} + +void ScriptInterpreter::open(const char *filename) { + if (_scriptFile) + close(); + _scriptFile = new Common::File(); + _scriptFile->open(filename); + if (!_scriptFile->isOpen()) + error("ScriptInterpreter::open() Error opening %s.", filename); + + _scriptFile->readUint32LE(); // skip magic for now + uint32 version = _scriptFile->readUint32LE(); + if (version != kScriptFileVersion) { + error("ScriptInterpreter::open() DAT file version mismatch; requested %li, got %i\n", kScriptFileVersion, version); + } + + int functionCount = _scriptFile->readUint32LE(); + printf("functionCount = %d\n", functionCount); + for (int i = 0; i < functionCount; i++) { + uint32 offset = _scriptFile->readUint32LE(); + printf("func(%d) offset = %08X\n", i, offset); + uint32 len = _scriptFile->readUint32LE(); + if (len > 0) { + char *funcName = new char[len + 1]; + _scriptFile->read(funcName, len); + funcName[len] = '\0'; + printf("func(%d) name = %s\n", i, funcName); + _functionNames[Common::String(funcName)] = _functions.size(); + // DEBUG + _scriptFunctionNames.push_back(Common::String(funcName)); + delete[] funcName; + } + _functions.push_back(new ScriptFunctionEntry(offset)); + } + + int dataCount = _scriptFile->readUint32LE(); + printf("dataCount = %d\n", dataCount); + for (int i = 0; i < dataCount; i++) { + uint32 offset = _scriptFile->readUint32LE(); + ScriptDataType type = (ScriptDataType)_scriptFile->readUint32LE(); + printf("data(%d) offset = %08X; type = %d\n", i, offset, type); + _data.push_back(new ScriptDataEntry(offset, type)); + } + + _globalVarCount = _scriptFile->readUint32LE(); + printf("_globalVarCount = %d\n", _globalVarCount); + + uint32 stringOfs = _scriptFile->readUint32LE(); + _scriptFile->seek(stringOfs); + _constStrings.load(_scriptFile); + + for (int i = 0; i < ARRAYSIZE(_globalVars); i++) { + _globalVars[i].type = kInteger; + _globalVars[i].value = 0; + } + + memset(_logicGlobals, 0, sizeof(_logicGlobals)); + + memset(_registers, 0, sizeof(_registers)); + memset(_stack, 0, sizeof(_stack)); + _stackPtr = 0; + +} + +void ScriptInterpreter::close() { + if (_scriptFile) { + delete _scriptFile; + } +} + +void ScriptInterpreter::initScriptKernel() { + +#include "m4/scripttab.h" + + _kernelFunctions = kernelFunctions; + _kernelFunctionsMax = ARRAYSIZE(kernelFunctions) + 1; + + _kernelVars = kernelVars; + _kernelVarsMax = ARRAYSIZE(kernelVars) + 1; + +} + + +ScriptFunction *ScriptInterpreter::loadFunction(uint32 index) { + //GONE WHILE DEBUGGING assert(index < _functions.size()); + if (index >= _functions.size()) return NULL; + ScriptFunction *scriptFunction; + scriptFunction = _functions[index]->func; + if (!scriptFunction) { + scriptFunction = new ScriptFunction(this); + _scriptFile->seek(_functions[index]->offset); + scriptFunction->load(_scriptFile); + _functions[index]->func = scriptFunction; + } + return scriptFunction; +} + +ScriptFunction *ScriptInterpreter::loadFunction(const Common::String &name) { + FunctionNameMap::iterator iter = _functionNames.find(name); + if (iter == _functionNames.end()) { + printf("ScriptInterpreter::loadFunction() Function '%s' not found!\n", name.c_str()); + return NULL; + } + uint32 funcIndex = (*iter)._value; + printf("ScriptInterpreter::loadFunction() index('%s') = %d\n", name.c_str(), funcIndex); + return loadFunction(funcIndex); +} + +void ScriptInterpreter::unloadFunctions() { + for (uint32 i = 0; i < _functions.size(); i++) { + if (_functions[i]->func) { + delete _functions[i]->func; + _functions[i]->func = NULL; + } + } +} + +int ScriptInterpreter::runFunction(ScriptFunction *scriptFunction) { + bool done = false; + + int oldLocalStackPtr = _localStackPtr; + ScriptFunction *oldRunningFunction = _runningFunction; + + // TODO: Also initialize _localStackPtr + + _runningFunction = scriptFunction; + _runningFunction->jumpAbsolute(0); + while (!done) { + byte opcode = _runningFunction->readByte(); + done = !execOpcode(opcode); + fflush(stdout); + } + + _localStackPtr = oldLocalStackPtr; + _runningFunction = oldRunningFunction; + + return 0; +} + +void ScriptInterpreter::push(const ScriptValue &value) { + if (_stackPtr == ARRAYSIZE(_stack)) + error("ScriptInterpreter::push() Stack overflow!\n"); + _stack[_stackPtr++] = value; +} + +void ScriptInterpreter::pop(ScriptValue &value) { + if (_stackPtr == 0) + error("ScriptInterpreter::pop() Stack underflow!\n"); + value = _stack[_stackPtr--]; +} + +void ScriptInterpreter::dumpStack() { + printf("ScriptInterpreter::dumpStack()\n"); + for (int i = 0; i < _stackPtr; i++) { + printf("%03d. type = %02d; value = %d\n", i, _stack[i].type, _stack[i].value); + } +} + +void ScriptInterpreter::dumpRegisters() { + printf("ScriptInterpreter::dumpRegisters()\n"); + for (int i = 0; i < ARRAYSIZE(_registers); i++) { + printf("%03d. type = %02d; value = %d\n", i, _registers[i].type, _registers[i].value); + } +} + +void ScriptInterpreter::dumpGlobalVars() { + printf("ScriptInterpreter::dumpGlobalVars()\n"); + for (int i = 0; i < ARRAYSIZE(_globalVars); i++) { + if (_globalVars[i].type != -1) + printf("%03d. type = %02d; value = %d\n", i, _globalVars[i].type, _globalVars[i].value); + } +} + +int ScriptInterpreter::toInteger(const ScriptValue &value) { + + switch (value.type) { + + case kInteger: + return value.value; + + default: + printf("ScriptInterpreter::toInteger() Invalid type %d!\n", value.type); + return 0; + + } + +} + +const char *ScriptInterpreter::toString(const ScriptValue &value) { + + switch (value.type) { + + case kInteger: + return NULL; + + case kConstString: + return _constStrings[value.value]; + + default: + printf("ScriptInterpreter::toString() Invalid type %d!\n", value.type); + return NULL; + + } + +} + +const char *ScriptInterpreter::loadGlobalString(Common::File *fd) { + uint32 index = fd->readUint32LE(); + if (index != 0xFFFFFFFF) + return getGlobalString(index); + else + return NULL; +} + +void ScriptInterpreter::test() { +} + +void ScriptInterpreter::loadValue(ScriptValue &value) { + + value.type = (ScriptValueType)_runningFunction->readByte(); + + switch (value.type) { + + case kGameVar: + case kInteger: + case kConstString: + case kDataRef: + case kLogicVar: + case kLogicVarRef: + case kKernelVar: + value.value = _runningFunction->readUint32(); + break; + + case kRegister: + value.value = _runningFunction->readByte(); + break; + + default: + printf("ScriptInterpreter::loadValue() Invalid value type %d!\n", value.type); + + } + +} + +void ScriptInterpreter::copyValue(ScriptValue &destValue, ScriptValue &sourceValue) { + + if (sourceValue.type == -1) { + printf("ScriptInterpreter::copyValue() Trying to read uninitialized value!\n"); + } + + switch (destValue.type) { + + case kGameVar: + _globalVars[destValue.value] = sourceValue; + break; + + case kRegister: + _registers[destValue.value] = sourceValue; + break; + + case kLogicVar: + // TODO: Move to own method + if (sourceValue.type == kInteger) { + _logicGlobals[destValue.value] = sourceValue.value; + } else { + printf("ScriptInterpreter::copyValue() Invalid source value type %d!\n", sourceValue.type); + } + break; + + case kKernelVar: + setKernelVar(destValue.value, sourceValue); + break; + + default: + printf("ScriptInterpreter::copyValue() Invalid dest value type %d!\n", destValue.type); + + } + +} + +void ScriptInterpreter::derefValue(ScriptValue &value) { + + switch (value.type) { + + case kGameVar: + value = _globalVars[value.value]; + break; + + case kInteger: + case kConstString: + case kDataRef: + case kLogicVarRef: + // These need no dereferencing + break; + + case kRegister: + value = _registers[value.value]; + break; + + case kLogicVar: + // TODO: Move to own method + value = _logicGlobals[value.value]; + break; + + case kKernelVar: + getKernelVar(value.value, value); + break; + + default: + printf("ScriptInterpreter::derefValue() Invalid value type %d!\n", value.type); + + } + +} + +void ScriptInterpreter::callKernelFunction(uint32 index) { + + printf("ScriptInterpreter::callKernelFunction() index = %d\n", index); + + if (index > _kernelFunctionsMax) { + printf("ScriptInterpreter::callKernelFunction() Invalid kernel functionindex (%d)\n", index); + return; + } + + printf("ScriptInterpreter::callKernelFunction() name = %s\n", _kernelFunctions[index].desc); + + int args = (this->*(_kernelFunctions[index].proc))(); + // Now remove values from the stack if the function used any + if (args > 4) + _stackPtr -= args - 4; + + printf("-------------\n"); + +} + +ScriptValue ScriptInterpreter::getArg(uint32 index) { + if (index < 4) { + return _registers[index]; + } else { + index -= 4; + return _stack[_stackPtr - index - 1]; + } +} + +void ScriptInterpreter::dumpArgs(uint32 count) { + printf("ScriptInterpreter::dumpArgs() "); + for (uint32 i = 0; i < count; i++) { + ScriptValue argValue = getArg(i); + if (argValue.type == kConstString) { + printf("'%s'", toString(argValue)); + } else { + printf("%d", argValue.value); + } + if (i + 1 < count) + printf(", "); + } + printf("\n"); +} + +void ScriptInterpreter::callFunction(uint32 index) { + // NOTE: This is a temporary hack for script functions not yet in the m4.dat + if (index == 0xFFFFFFFF) + return; + printf("ScriptInterpreter::callFunction() index = %d [%s]\n", index, _scriptFunctionNames[index].c_str()); + fflush(stdout); + ScriptFunction *subFunction = loadFunction(index); + if (!subFunction) { + // This *should* never happen since the linker checks this + printf("ScriptInterpreter::callFunction() Function %d could not be loaded!\n", index); + return; + } + runFunction(subFunction); +} + +bool ScriptInterpreter::execOpcode(byte opcode) { + + printf("opcode = %d (%s)\n", opcode, opcodeNames[opcode]); + + ScriptValue value1, value2, value3; + uint32 temp; + + /* TODO: Put all opcodes into separate functions and into an array + (but only after all needed opcodes are known and frozen) + */ + + switch (opcode) { + + case opRet: + return false; + + case opPush: + loadValue(value1); + derefValue(value1); + push(value1); + return true; + + case opPush0: + push(ScriptValue(0)); + return true; + + case opPush1: + push(ScriptValue(1)); + return true; + + case opPushNeg1: + push(ScriptValue(-1)); + return true; + + case opPop: + loadValue(value1); + pop(value2); + copyValue(value1, value2); + return true; + + case opMov: + loadValue(value1); + loadValue(value2); + derefValue(value2); + copyValue(value1, value2); + return true; + + // Possibly join all jump variants into one opcode + + case opJmp: + temp = _runningFunction->readUint32(); + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + return true; + + case opJl: + temp = _runningFunction->readUint32(); + if (_cmpFlags < 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJle: + temp = _runningFunction->readUint32(); + if (_cmpFlags <= 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJg: + temp = _runningFunction->readUint32(); + if (_cmpFlags > 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJge: + temp = _runningFunction->readUint32(); + if (_cmpFlags >= 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJz: + temp = _runningFunction->readUint32(); + if (_cmpFlags == 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJnz: + temp = _runningFunction->readUint32(); + if (_cmpFlags != 0) { + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + } + return true; + + case opJmpByTable: + temp = _runningFunction->readUint32(); + printf("-> index = %d\n", _registers[0].value); + _runningFunction->jumpRelative(_registers[0].value * 4); + temp = _runningFunction->readUint32(); + printf("-> ofs = %08X\n", temp); + _runningFunction->jumpAbsolute(temp); + return true; + + case opCmp: + loadValue(value1); + loadValue(value2); + derefValue(value1); + derefValue(value2); + if (value1.type != kInteger || value2.type != kInteger) + warning("ScriptInterpreter::execOpcode() Trying to compare non-integer values (%d, %d, line %d)!\n", value1.type, value2.type, _lineNum); + _cmpFlags = value1.value - value2.value; + printf("-> cmp %d, %d\n", value1.value, value2.value); + printf("-> _cmpFlags = %d\n", _cmpFlags); + return true; + + case opCall: + temp = _runningFunction->readUint32(); + callFunction(temp); + return true; + + case opCallKernel: + temp = _runningFunction->readUint32(); + callKernelFunction(temp); + return true; + + case opInc: + loadValue(value1); + value2 = value1; + derefValue(value2); + value2.value++; + copyValue(value1, value2); + return true; + + case opDec: + loadValue(value1); + value2 = value1; + derefValue(value2); + value2.value--; + copyValue(value1, value2); + return true; + + case opAdd: + loadValue(value1); + value3 = value1; + loadValue(value2); + derefValue(value3); + derefValue(value2); + value3.value += value2.value; + copyValue(value1, value3); + return true; + + case opSub: + loadValue(value1); + value3 = value1; + loadValue(value2); + derefValue(value3); + derefValue(value2); + value3.value -= value2.value; + copyValue(value1, value3); + return true; + + case opDebug: + _lineNum = (int)_runningFunction->readUint32(); + return true; + + default: + printf("Invalid opcode %d!\n", opcode); + return false; + + } + + return false; + +} + +// Kernel functions + +#define STRING(arg) (toString(getArg(arg))) +#define INTEGER(arg) (toInteger(getArg(arg))) +#define DATA(arg, T) (toData<T>(getArg(arg))) +#define RETURN(value) (_registers[0] = (value)) + +int ScriptInterpreter::o1_handleStreamBreak() { + return 0; +} + +int ScriptInterpreter::o1_handlePlayBreak() { + return 0; +} + +int ScriptInterpreter::o1_dispatchTriggerOnSoundState() { + return 0; +} + +int ScriptInterpreter::o1_getTicks() { + return 0; +} + +int ScriptInterpreter::o1_setSoundVolume() { + return 0; +} + +int ScriptInterpreter::o1_getSoundStatus() { + return 0; +} + +int ScriptInterpreter::o1_getSoundDuration() { + return 0; +} + +int ScriptInterpreter::o1_setSeriesFrameRate() { + return 0; +} + +int ScriptInterpreter::o1_terminateMachine() { + return 0; +} + +int ScriptInterpreter::o1_sendWoodScriptMessage() { + return 0; +} + +int ScriptInterpreter::o1_runConversation() { + return 0; +} + +int ScriptInterpreter::o1_exportConversationValue() { + return 0; +} + +int ScriptInterpreter::o1_exportConversationPointer() { + return 0; +} + +int ScriptInterpreter::o1_playBreakSeries() { + return 0; +} + +int ScriptInterpreter::o1_hideWalker() { + return 0; +} + +int ScriptInterpreter::o1_showWalker() { + return 0; +} + +int ScriptInterpreter::o1_walk() { + return 0; +} + +int ScriptInterpreter::o1_overrideCrunchTime() { + return 0; +} + +int ScriptInterpreter::o1_addBlockingRect() { + return 0; +} + +int ScriptInterpreter::o1_setPlayerCommandsAllowed() { + return 0; +} + +int ScriptInterpreter::o1_getPlayerCommandsAllowed() { + return 0; +} + +int ScriptInterpreter::o1_setPlayerFacingAngle() { + return 0; +} + +int ScriptInterpreter::o1_disablePlayerFadeToBlack() { + return 0; +} + +int ScriptInterpreter::o1_enablePlayer() { + return 0; +} + +int ScriptInterpreter::o1_disablePlayer() { + return 0; +} + +int ScriptInterpreter::o1_freshenSentence() { + return 0; +} + +int ScriptInterpreter::o1_playerGiveItem() { + return 0; +} + +int ScriptInterpreter::o1_moveObject() { + return 0; +} + +int ScriptInterpreter::o1_setStopSoundsBetweenRooms() { + return 0; +} + +int ScriptInterpreter::o1_backupPalette() { + return 0; +} + +int ScriptInterpreter::o1_unloadWilburWalker() { + return 0; +} + +int ScriptInterpreter::o1_wilburTalk() { + return 0; +} + +int ScriptInterpreter::o1_wilburFinishedTalking() { + return 0; +} + +int ScriptInterpreter::o1_preloadSound() { + const char *name = STRING(0); + int room = INTEGER(1); + printf("name = %s; room = %d\n", name, room); + return 2; +} + +int ScriptInterpreter::o1_unloadSound() { + const char *name = STRING(0); + int room = INTEGER(1); + printf("name = %s; room = %d\n", name, room); + return 2; +} + +int ScriptInterpreter::o1_playSound() { + const char *name = STRING(0); + int channel = INTEGER(1); + int volume = INTEGER(2); + int trigger = INTEGER(3); + int room = INTEGER(4); + printf("name = %s; channel = %d; volume = %d; trigger = %d; room = %d\n", + name, channel, volume, trigger, room); + + Common::String soundName = Common::String(name) + ".raw"; + _vm->_sound->playVoice(soundName.c_str(), 100); + + // HACK until fixed + _vm->_kernel->sendTrigger(trigger); + + return 5; +} + +int ScriptInterpreter::o1_playLoopingSound() { + const char *name = STRING(0); + int channel = INTEGER(1); + int volume = INTEGER(2); + int trigger = INTEGER(3); + int room = INTEGER(4); + printf("name = %s; channel = %d; volume = %d; trigger = %d; room = %d\n", + name, channel, volume, trigger, room); + + // HACK until fixed + _vm->_kernel->sendTrigger(trigger); + + return 5; +} + +int ScriptInterpreter::o1_stopSound() { + int channel = INTEGER(0); + printf("channel = %d\n", channel); + return 1; +} + +int ScriptInterpreter::o1_fadeSetStart() { + // skip arg 0: palette ptr + int percent = INTEGER(1); + printf("percent = %d\n", percent); + return 2; +} + +int ScriptInterpreter::o1_fadeInit() { + // skip arg 0: palette ptr + int first = INTEGER(1); + int last = INTEGER(2); + int percent = INTEGER(3); + int ticks = INTEGER(4); + int trigger = INTEGER(5); + printf("first = %d; last = %d; percent = %d; ticks = %d; trigger = %d\n", + first, last, percent, ticks, trigger); + + // HACK until palette fading is implemented + _vm->_kernel->sendTrigger(trigger); + + return 6; +} + +int ScriptInterpreter::o1_fadeToBlack() { + return 0; +} + +int ScriptInterpreter::o1_initPaletteCycle() { + int first = INTEGER(0); + int last = INTEGER(1); + int delay = INTEGER(2); + int ticks = INTEGER(3); + int trigger = INTEGER(4); + printf("first = %d; last = %d; delay = %d; ticks = %d; trigger = %d\n", + first, last, delay, ticks, trigger); + + // HACK until palette cycling is implemented + _vm->_kernel->sendTrigger(trigger); + + return 5; +} + +int ScriptInterpreter::o1_stopPaletteCycle() { + return 0; +} + +int ScriptInterpreter::o1_hasPlayerSaid() { + const char *words[3]; + for (int i = 0; i < 3; i++) + words[i] = STRING(i); + printf("'%s', '%s', '%s'\n", words[0], words[1], words[2]); + + int result = _vm->_player->said(words[0], words[1], words[2]); + + printf(" -> '%d'\n", result); + fflush(stdout); + + RETURN(result); + return 3; +} + +int ScriptInterpreter::o1_hasPlayerSaidAny() { + const char *words[10]; + for (int i = 0; i < 10; i++) + words[i] = STRING(i); + + printf("'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'\n", + words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); + + int result = _vm->_player->saidAny(words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); + printf(" -> '%d'\n", result); + fflush(stdout); + + RETURN(result); + return 10; +} + +int ScriptInterpreter::o1_updatePlayerInfo() { + // skip arg 0: player info struct + return 1; +} + +int ScriptInterpreter::o1_playerHotspotWalkOverride() { + int x1 = INTEGER(0); + int y1 = INTEGER(1); + int x2 = INTEGER(2); + int y2 = INTEGER(3); + printf("(%d, %d); (%d, %d)\n", x1, y1, x2, y2); + return 4; +} + +int ScriptInterpreter::o1_playerHasItem() { + const char *name = STRING(0); + printf("item = '%s'\n", name); + // TODO + RETURN(0); + return 1; +} + +int ScriptInterpreter::o1_setWalkerLocation() { + // skip arg 0: walker + int x = INTEGER(1); + int y = INTEGER(2); + printf("x = %d; y = %d\n", x, y); + return 3; +} + +int ScriptInterpreter::o1_setWalkerFacing() { + // skip arg 0: walker + int facing = INTEGER(1); + printf("facing = %d\n", facing); + return 2; +} + +int ScriptInterpreter::o1_setHotspot() { + // skip arg 0: hotspot list + const char *name = STRING(1); + int value = INTEGER(2); + printf("name = '%s' -> %d\n", name, value); + + _vm->_scene->getSceneResources().hotspots->setActive(name, (value != 0)); + + return 2; +} + +int ScriptInterpreter::o1_loadConversation() { + const char *name = STRING(0); + int trigger = INTEGER(1); + int flag = INTEGER(2); + + // TODO; just to show something + _vm->_converse->startConversation(name); + + return 3; +} + +int ScriptInterpreter::o1_playSeries() { + const char *name = STRING(0); + int layer = INTEGER(1); + int flags = INTEGER(2); + int trigger = INTEGER(3); + int frameRate = INTEGER(4); + int loopCount = INTEGER(5); + int scale = INTEGER(6); + int x = INTEGER(7); + int y = INTEGER(8); + int firstFrame = INTEGER(9); + int lastFrame = INTEGER(10); + + printf("name = %s; layer = %04X; flags = %08X; trigger = %d; frameRate = %d; loopCount = %d; scale = %d; x = %d; y = %d: firstFrame = %d; lastFrame = %d\n", + name, layer, flags, trigger, frameRate, loopCount, scale, x, y, firstFrame, lastFrame); + fflush(stdout); + + // TODO: Return the machine to the script + _vm->_ws->playSeries(name, layer, flags, trigger, frameRate, loopCount, scale, x, y, firstFrame, lastFrame); + + return 11; +} + +int ScriptInterpreter::o1_showSeries() { + const char *name = STRING(0); + int layer = INTEGER(1); + int flags = INTEGER(2); + int trigger = INTEGER(3); + int duration = INTEGER(4); + int frameIndex = INTEGER(5); + int scale = INTEGER(6); + int x = INTEGER(7); + int y = INTEGER(8); + + printf("name = %s; layer = %04X; flags = %08X; trigger = %d; duration = %d; frameIndex = %d; scale = %d; x = %d; y = %d\n", + name, layer, flags, trigger, duration, frameIndex, scale, x, y); + fflush(stdout); + + // TODO: Return the machine to the script + _vm->_ws->showSeries(name, layer, flags, trigger, duration, frameIndex, scale, x, y); + + return 9; +} + +int ScriptInterpreter::o1_loadSeries() { + const char *name = STRING(0); + int hash = INTEGER(1); + // skip arg 3: palette ptr + + printf("name = %s; hash = %d\n", name, hash); + fflush(stdout); + + int result = _vm->_ws->loadSeries(name, hash, NULL); + + RETURN(result); + return 3; +} + +int ScriptInterpreter::o1_unloadSeries() { + return 0; +} + +int ScriptInterpreter::o1_preloadBreakSeries() { + const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); + return 1; +} + +int ScriptInterpreter::o1_unloadBreakSeries() { + const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); + return 1; +} + +int ScriptInterpreter::o1_startBreakSeries() { + const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); + return 1; +} + +int ScriptInterpreter::o1_globalTriggerProc() { + int value1 = INTEGER(0); + int value2 = INTEGER(1); + int value3 = INTEGER(2); + printf("%d; %d; %d\n", value1, value2, value3); + return 3; +} + +int ScriptInterpreter::o1_triggerTimerProc() { + int value1 = INTEGER(0); + int value2 = INTEGER(1); + int value3 = INTEGER(2); + printf("%d; %d; %d\n", value1, value2, value3); + return 3; +} + +int ScriptInterpreter::o1_dispatchTrigger() { + int trigger = INTEGER(0); + printf("trigger = %d\n", trigger); + + _vm->_kernel->sendTrigger(trigger); + //g_system->delayMillis(5000); + + return 1; +} + +int ScriptInterpreter::o1_getRangedRandomValue() { + int minValue = INTEGER(0); + int maxValue = INTEGER(1); + RETURN(_vm->imath_ranged_rand(minValue, maxValue)); + return 2; +} + +int ScriptInterpreter::o1_wilburSaid() { + const SaidArray& saidArray = DATA(0, SaidArray); + + int result = 0; + + // NOTE: The "Common::String soundName" stuff is just temporary until playVoice is fixed. + + for (int i = 0; i < saidArray.size(); i++) { + SaidArrayItem *item = saidArray[i]; + + if (_vm->_player->said("LOOK AT", item->itemName) && item->digiNameLook) { + printf(" -> LOOK AT: '%s'\n", item->digiNameLook); + Common::String soundName = Common::String(item->digiNameLook) + ".raw"; + _vm->_sound->playVoice(soundName.c_str(), 100); + result = 1; + break; + } + + if (_vm->_player->said("TAKE", item->itemName) && item->digiNameTake) { + printf(" -> TAKE: '%s'\n", item->digiNameTake); + Common::String soundName = Common::String(item->digiNameTake) + ".raw"; + _vm->_sound->playVoice(soundName.c_str(), 100); + result = 1; + break; + } + + if (_vm->_player->said("GEAR", item->itemName) && item->digiNameGear) { + printf(" -> GEAR: '%s'\n", item->digiNameGear); + Common::String soundName = Common::String(item->digiNameGear) + ".raw"; + _vm->_sound->playVoice(soundName.c_str(), 100); + result = 1; + break; + } + + /* + printf("##### itemName = '%s'; digiNameLook = %s; digiNameTake = %s; digiNameGear = %s\n", + item->itemName, item->digiNameLook, item->digiNameTake, item->digiNameGear); + */ + } + printf(" -> '%d'\n", result); + fflush(stdout); + + RETURN(result); + return 1; +} + +int ScriptInterpreter::o1_wilburParse() { + const ParserArray& parserArray = DATA(0, ParserArray); + RETURN(0); + return 1; +} + +int ScriptInterpreter::o1_wilburSpeech() { + const char *name = STRING(0); + int trigger = INTEGER(1); + int room = INTEGER(2); + int flag = INTEGER(3); + int volume = INTEGER(4); + int slot = INTEGER(5); + + printf("%s; %d; %d; %d; %d; %d\n", name, trigger, room, flag, volume, slot); + fflush(stdout); + //g_system->delayMillis(5000); + + KernelTriggerType oldTriggerMode = _vm->_kernel->triggerMode; + + // TODO + Common::String soundName = Common::String(name) + ".raw"; + _vm->_sound->playVoice(soundName.c_str(), 100); + + _vm->_kernel->triggerMode = oldTriggerMode; + + return 6; +} + +// Kernel vars + +void ScriptInterpreter::getKernelVar(int index, ScriptValue &value) { + + printf("ScriptInterpreter::getKernelVar() index = %d\n", index); + + if (index > _kernelVarsMax) { + printf("ScriptInterpreter::getKernelVar() Invalid kernel var index %d!\n", index); + return; + } + + printf("ScriptInterpreter::getKernelVar() name = %s\n", _kernelVars[index].desc); + + ScriptKernelVariable var = _kernelVars[index].var; + + switch (var) { + + case kKernelTrigger: + value = _vm->_kernel->trigger; + break; + + case kKernelTriggerMode: + value = (int)_vm->_kernel->triggerMode; + break; + + case kKernelContinueHandlingTrigger: + value = (int)_vm->_kernel->daemonTriggerAvailable; + break; + + case kGameVersion: + // TODO + value = 0; + break; + + case kGameLanguage: + // TODO + value = 0; + break; + + case kGameNewRoom: + // TODO + value = 0; + break; + + case kPlayerCommandReady: + value = (int)_vm->_player->commandReady; + break; + + default: + printf("ScriptInterpreter::getKernelVar() Invalid kernel var %d!\n", var); + //g_system->delayMillis(2000); + + } + +} + +void ScriptInterpreter::setKernelVar(int index, const ScriptValue &value) { + + printf("ScriptInterpreter::setKernelVar() index = %d\n", index); + + if (index > _kernelVarsMax) { + printf("ScriptInterpreter::setKernelVar() Invalid kernel var index %d!\n", index); + return; + } + + printf("ScriptInterpreter::setKernelVar() name = %s\n", _kernelVars[index].desc); + + ScriptKernelVariable var = _kernelVars[index].var; + + switch (var) { + + case kKernelTrigger: + _vm->_kernel->trigger = toInteger(value); + printf("kKernelTrigger -> %d\n", toInteger(value)); + break; + + case kKernelTriggerMode: + _vm->_kernel->triggerMode = (KernelTriggerType)toInteger(value); + printf("kKernelTrigger -> %d\n", toInteger(value)); + break; + + case kKernelContinueHandlingTrigger: + _vm->_kernel->daemonTriggerAvailable = (toInteger(value) != 0); + printf("kKernelContinueHandlingTrigger -> %d\n", toInteger(value)); + break; + + case kGameNewRoom: + _vm->_kernel->newRoom = toInteger(value); + printf("kGameNewRoom -> %d\n", toInteger(value)); + break; + + case kPlayerCommandReady: + // TODO + printf("kPlayerCommandReady -> %d\n", toInteger(value)); + break; + + default: + printf("ScriptInterpreter::setKernelVar() Invalid kernel var %d!\n", var); + //g_system->delayMillis(2000); + + } + +} + +} // End of namespace M4 |