diff options
-rw-r--r-- | saga/game.cpp | 6 | ||||
-rw-r--r-- | saga/interface.cpp | 3 | ||||
-rw-r--r-- | saga/script.h | 21 | ||||
-rw-r--r-- | saga/sfuncs.cpp | 255 | ||||
-rw-r--r-- | saga/sthread.cpp | 3 |
5 files changed, 244 insertions, 44 deletions
diff --git a/saga/game.cpp b/saga/game.cpp index 304df7c276..f3281df625 100644 --- a/saga/game.cpp +++ b/saga/game.cpp @@ -430,9 +430,9 @@ static GameDisplayInfo IHNM_DisplayInfo = { //TODO: fill it all 0,0, // save reminder w&h 0,0, // save reminder sprite numbers - 147, // verb text color - 15, // verb text shadow color - 96, // verb text active color + 253, // verb text color + 15, // verb text shadow color FIXME + 252, // verb text active color 5, 4, // left portrait x, y offset -1, -1, // right portrait x, y offset diff --git a/saga/interface.cpp b/saga/interface.cpp index 47d1d69a71..3f7df23ef4 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -263,6 +263,9 @@ void Interface::setMode(int mode) { switch (_panelMode) { case kPanelMain: + if (_vm->getGameType() == GType_IHNM) + warning("FIXME: Implement IHNM differences from ExecuteInvontoryPanel"); + _mainPanel.currentButton = NULL; break; case kPanelConverse: diff --git a/saga/script.h b/saga/script.h index 844f917f46..d5f2ce1bb0 100644 --- a/saga/script.h +++ b/saga/script.h @@ -39,14 +39,9 @@ namespace Saga { #define SCRIPT_TBLENTRY_LEN 4 #define SCRIPT_MAX 5000 -#define SCRIPTLIST_HDR 12 -#define SCRIPT_STRINGLIMIT 255 -#define TAB " " -#define S_ERROR_PREFIX "SError: " -#define S_WARN_PREFIX "SWarning: " - -#define SCRIPT_FUNCTION_MAX 104 +#define ITE_SCRIPT_FUNCTION_MAX 78 +#define IHNM_SCRIPT_FUNCTION_MAX 105 #define DEFAULT_THREAD_STACK_SIZE 256 enum AddressTypes { @@ -527,8 +522,20 @@ private: void sfProtectResult(SCRIPTFUNC_PARAMS); void sfRand(SCRIPTFUNC_PARAMS); void sfFadeMusic(SCRIPTFUNC_PARAMS); + void sfScriptStartCutAway(SCRIPTFUNC_PARAMS); + void sfReturnFromCutAway(SCRIPTFUNC_PARAMS); + void sfEndCutAway(SCRIPTFUNC_PARAMS); + void sfGetMouseClicks(SCRIPTFUNC_PARAMS); + void sfResetMouseClicks(SCRIPTFUNC_PARAMS); + void sfWaitFrames(SCRIPTFUNC_PARAMS); + void sfScriptFade(SCRIPTFUNC_PARAMS); void sfPlayVoice(SCRIPTFUNC_PARAMS); + void sfVstopFX(SCRIPTFUNC_PARAMS); + void sfVstopLoopedFX(SCRIPTFUNC_PARAMS); + void sfDemoIsInteractive(SCRIPTFUNC_PARAMS); + void sfDebugShowData(SCRIPTFUNC_PARAMS); void SF_stub(SCRIPTFUNC_PARAMS); + void sfNull(SCRIPTFUNC_PARAMS); }; } // End of namespace Saga diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp index a7ecb88d1f..ff23dd5692 100644 --- a/saga/sfuncs.cpp +++ b/saga/sfuncs.cpp @@ -53,7 +53,7 @@ namespace Saga { #define OPCODE(x) {&Script::x, #x} void Script::setupScriptFuncList(void) { - static const ScriptFunctionDescription scriptFunctionsList[SCRIPT_FUNCTION_MAX] = { + static const ScriptFunctionDescription ITEscriptFunctionsList[ITE_SCRIPT_FUNCTION_MAX] = { OPCODE(sfPutString), OPCODE(sfWait), OPCODE(sfTakeObject), @@ -131,23 +131,104 @@ void Script::setupScriptFuncList(void) { OPCODE(sfProtectResult), OPCODE(sfRand), OPCODE(sfFadeMusic), - OPCODE(sfPlayVoice), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), - OPCODE(SF_stub), + OPCODE(sfPlayVoice) + }; + +static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCTION_MAX] = { + OPCODE(sfNull), + OPCODE(sfWait), + OPCODE(sfTakeObject), + OPCODE(sfIsCarried), + OPCODE(sfStatusBar), + OPCODE(sfMainMode), + OPCODE(sfScriptWalkTo), + OPCODE(sfScriptDoAction), + OPCODE(sfSetActorFacing), + OPCODE(sfStartBgdAnim), + OPCODE(sfStopBgdAnim), + OPCODE(sfNull), + OPCODE(sfPreDialog), + OPCODE(sfKillActorThreads), + OPCODE(sfFaceTowards), + OPCODE(sfSetFollower), + OPCODE(sfScriptGotoScene), + OPCODE(sfSetObjImage), + OPCODE(sfSetObjName), + OPCODE(sfGetObjImage), + OPCODE(sfGetNumber), + OPCODE(sfScriptOpenDoor), + OPCODE(sfScriptCloseDoor), + OPCODE(sfSetBgdAnimSpeed), + OPCODE(SF_cycleColors), + OPCODE(sfDoCenterActor), + OPCODE(sfStartBgdAnimSpeed), + OPCODE(sfScriptWalkToAsync), + OPCODE(sfEnableZone), + OPCODE(sfSetActorState), + OPCODE(sfScriptMoveTo), + OPCODE(sfSceneEq), + OPCODE(sfDropObject), + OPCODE(sfFinishBgdAnim), + OPCODE(sfSwapActors), + OPCODE(sfSimulSpeech), + OPCODE(sfScriptWalk), + OPCODE(sfCycleFrames), + OPCODE(sfSetFrame), + OPCODE(sfSetPortrait), + OPCODE(sfSetProtagPortrait), + OPCODE(sfChainBgdAnim), + OPCODE(sfScriptSpecialWalk), + OPCODE(sfPlaceActor), + OPCODE(sfCheckUserInterrupt), + OPCODE(sfScriptWalkRelative), + OPCODE(sfScriptMoveRelative), + OPCODE(sfSimulSpeech2), + OPCODE(sfPlacard), + OPCODE(sfPlacardOff), + OPCODE(sfSetProtagState), + OPCODE(sfResumeBgdAnim), + OPCODE(sfThrowActor), + OPCODE(sfWaitWalk), + OPCODE(sfScriptSceneID), + OPCODE(sfChangeActorScene), + OPCODE(sfScriptClimb), + OPCODE(sfSetDoorState), + OPCODE(sfSetActorZ), + OPCODE(sfScriptText), + OPCODE(sfGetActorX), + OPCODE(sfGetActorY), + OPCODE(sfEraseDelta), + OPCODE(sfPlayMusic), + OPCODE(sfNull), + OPCODE(sfEnableEscape), + OPCODE(sfPlaySound), + OPCODE(sfPlayLoopedSound), + OPCODE(sfGetDeltaFrame), + OPCODE(sfNull), + OPCODE(sfNull), + OPCODE(sfRand), + OPCODE(sfFadeMusic), + OPCODE(sfNull), OPCODE(SF_stub), OPCODE(SF_stub), + OPCODE(sfScriptStartCutAway), + OPCODE(sfReturnFromCutAway), + OPCODE(sfEndCutAway), + OPCODE(sfGetMouseClicks), + OPCODE(sfResetMouseClicks), + OPCODE(sfWaitFrames), + OPCODE(sfScriptFade), OPCODE(SF_stub), OPCODE(SF_stub), OPCODE(SF_stub), + OPCODE(sfSetActorZ), OPCODE(SF_stub), OPCODE(SF_stub), + OPCODE(sfVstopFX), + OPCODE(sfVstopLoopedFX), OPCODE(SF_stub), + OPCODE(sfNull), + OPCODE(sfDemoIsInteractive), OPCODE(SF_stub), OPCODE(SF_stub), OPCODE(SF_stub), @@ -155,11 +236,15 @@ void Script::setupScriptFuncList(void) { OPCODE(SF_stub), OPCODE(SF_stub), OPCODE(SF_stub), + OPCODE(sfDebugShowData), OPCODE(SF_stub), OPCODE(SF_stub), OPCODE(SF_stub) }; - _scriptFunctionsList = scriptFunctionsList; + if (_vm->getGameType() == GType_IHNM) + _scriptFunctionsList = IHNMscriptFunctionsList; + else + _scriptFunctionsList = ITEscriptFunctionsList; } // Script function #0 (0x00) @@ -225,7 +310,9 @@ void Script::sfMainMode(SCRIPTFUNC_PARAMS) { showVerb(); _vm->_interface->activate(); _vm->_interface->setMode(kPanelMain); - setPointerVerb(); + + if (_vm->getGameType() == GType_ITE) + setPointerVerb(); } // Script function #6 (0x06) blocking @@ -513,6 +600,9 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) { return; } + if (_vm->getGameType() == GType_IHNM) + warning("FIXME: implement sfScriptGotoScene differences for IHNM"); + // It is possible to leave scene when converse panel is on, // particulalrly it may happen at Moneychanger tent. This // prevent this from happening. @@ -578,7 +668,11 @@ void Script::sfGetObjImage(SCRIPTFUNC_PARAMS) { objectId = thread->pop(); obj = _vm->_actor->getObj(objectId); - thread->_returnValue = obj->spriteListResourceId - OBJ_SPRITE_BASE; + + if (_vm->getGameType() == GType_IHNM) + thread->_returnValue = obj->spriteListResourceId; + else + thread->_returnValue = obj->spriteListResourceId - OBJ_SPRITE_BASE; } // Script function #20 (0x14) @@ -784,7 +878,12 @@ void Script::sfDropObject(SCRIPTFUNC_PARAMS) { } obj->sceneNumber = _vm->_scene->currentSceneNumber(); - obj->spriteListResourceId = OBJ_SPRITE_BASE + spriteId; + + if (_vm->getGameType() == GType_IHNM) + obj->spriteListResourceId = spriteId; + else + obj->spriteListResourceId = OBJ_SPRITE_BASE + spriteId; + obj->location.x = x; obj->location.y = y; } @@ -824,6 +923,10 @@ void Script::sfSwapActors(SCRIPTFUNC_PARAMS) { actor1->flags |= kProtagonist; _vm->_actor->_protagonist = _vm->_actor->_centerActor = actor1; } + + // Here non-protagonist ID gets saved in variable + if (_vm->getGameType() == GType_IHNM) + warning("sfSwapActors: incomplete implementation"); } // Script function #35 (0x23) @@ -852,9 +955,13 @@ void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) { string = thread->_strings->getString(stringId); if (thread->_voiceLUT->voices) { - sampleResourceId = thread->_voiceLUT->voices[stringId]; - if (sampleResourceId <= 0 || sampleResourceId > 4000) + if (_vm->getGameType() == GType_IHNM && stringId >= 338) { sampleResourceId = -1; + } else { + sampleResourceId = thread->_voiceLUT->voices[stringId]; + if (sampleResourceId <= 0 || sampleResourceId > 4000) + sampleResourceId = -1; + } } _vm->_actor->simulSpeech(string, actorsIds, actorsCount, 0, sampleResourceId); @@ -1197,7 +1304,12 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { PalEntry *pal; EVENT event; EVENT *q_event; - + + if (_vm->getGameType() == GType_IHNM) { + warning("Psychic profile is not implemented"); + return; + } + thread->wait(kWaitTypePlacard); _vm->_interface->rememberMode(); @@ -1743,11 +1855,18 @@ void Script::sfPlaySound(SCRIPTFUNC_PARAMS) { int16 param = thread->pop(); int res; + if (_vm->getGameType() == GType_IHNM) { + int16 param2 = thread->pop(); + + // Here sfxTable comes from Resource #265 + debug(0, "STUB: sfPlaySound(%d, %d)", param, param2); + return; + } + if (param >= 0 && param < ARRAYSIZE(sfxTable)) { res = sfxTable[param].res; if (_vm->getFeatures() & GF_CD_FX) res -= 14; - _vm->_sndRes->playSound(res, sfxTable[param].vol, false); } else { _vm->_sound->stopSound(); @@ -1759,6 +1878,14 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) { int16 param = thread->pop(); int res; + if (_vm->getGameType() == GType_IHNM) { + int16 param2 = thread->pop(); + + // Here sfxTable comes from Resource #265 + debug(0, "STUB: sfPlayLoopedSound(%d, %d)", param, param2); + return; + } + if (param >= 0 && param < ARRAYSIZE(sfxTable)) { res = sfxTable[param].res; if (_vm->getFeatures() & GF_CD_FX) @@ -1798,21 +1925,8 @@ void Script::sfProtectResult(SCRIPTFUNC_PARAMS) { void Script::sfRand(SCRIPTFUNC_PARAMS) { int16 param; - if (_vm->getGameType() == GType_IHNM) { - // I don't know what this function does in IHNM, but apparently - // it can take three parameters. - - debug(0, "STUB: sfRand()"); - - for (int i = 0; i < nArgs; i++) { - thread->pop(); - } - - thread->_returnValue = 0; - } else { - param = thread->pop(); - thread->_returnValue = _vm->_rnd.getRandomNumber(param - 1); - } + param = thread->pop(); + thread->_returnValue = _vm->_rnd.getRandomNumber(param - 1); } // Script function #76 (0x4c) @@ -1852,6 +1966,81 @@ void Script::finishDialog(int replyID, int flags, int bitOffset) { wakeUpThreads(kWaitTypeDialogBegin); } +void Script::sfScriptStartCutAway(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfScriptStartCutAway(), %d args", nArgs); +} + +void Script::sfReturnFromCutAway(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfReturnFromCutAway(), %d args", nArgs); +} + +void Script::sfEndCutAway(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfEndCutAway(), %d args", nArgs); +} + +void Script::sfGetMouseClicks(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfGetMouseClicks(), %d args", nArgs); +} + +void Script::sfResetMouseClicks(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfResetMouseClicks(), %d args", nArgs); +} + +void Script::sfWaitFrames(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfWaitFrames(), %d args", nArgs); +} + +void Script::sfScriptFade(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); + + debug(0, "STUB: sfScriptFade(), %d args", nArgs); +} + +void Script::sfVstopFX(SCRIPTFUNC_PARAMS) { + _vm->_sound->stopSound(); +} + +void Script::sfVstopLoopedFX(SCRIPTFUNC_PARAMS) { + _vm->_sound->stopSound(); +} + +void Script::sfDemoIsInteractive(SCRIPTFUNC_PARAMS) { + thread->_returnValue = 0; +} + +void Script::sfDebugShowData(SCRIPTFUNC_PARAMS) { + int16 param = thread->pop(); + char buf[50]; + + snprintf(buf, 50, "Reached breakpoint %d", param); + + _vm->_interface->setStatusText(buf); +} + +void Script::sfNull(SCRIPTFUNC_PARAMS) { + for (int i = 0; i < nArgs; i++) + thread->pop(); +} + void Script::SF_stub(SCRIPTFUNC_PARAMS) { for (int i = 0; i < nArgs; i++) thread->pop(); diff --git a/saga/sthread.cpp b/saga/sthread.cpp index c5f1f74a3a..209c6ebb6f 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -317,7 +317,8 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) { CASEOP(opCcallV) argumentsCount = scriptS.readByte(); functionNumber = scriptS.readUint16LE(); - if (functionNumber >= SCRIPT_FUNCTION_MAX) { + if (functionNumber >= (_vm->getGameType() == GType_IHNM) ? + IHNM_SCRIPT_FUNCTION_MAX : ITE_SCRIPT_FUNCTION_MAX) { error("Script::runThread() Invalid script function number (%d)", functionNumber); } |