diff options
Diffstat (limited to 'engines/kyra/script_tim.cpp')
-rw-r--r-- | engines/kyra/script_tim.cpp | 232 |
1 files changed, 214 insertions, 18 deletions
diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 24f7fce576..3df1daf306 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -28,6 +28,7 @@ #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/wsamovie.h" +#include "kyra/gui_lol.h" #include "common/endian.h" @@ -37,7 +38,7 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *sy #define COMMAND(x) { &TIMInterpreter::x, #x } #define COMMAND_UNIMPL() { 0, 0 } #define cmd_return(n) cmd_return_##n - static const CommandEntry commandProcs[] = { + static const CommandEntry commandProcsHOF[] = { // 0x00 COMMAND(cmd_initFunc0), COMMAND(cmd_stopCurFunc), @@ -74,22 +75,69 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *sy COMMAND(cmd_initFuncNow), COMMAND(cmd_stopFuncNow), // 0x1C + COMMAND(cmd_processDialogue), + COMMAND(cmd_dialogueBox), + COMMAND(cmd_return(n1)) + }; + + static const CommandEntry commandProcsLOL[] = { + // 0x00 + COMMAND(cmd_initFunc0), + COMMAND(cmd_stopAllFuncs), + COMMAND(cmd_initWSA), + COMMAND(cmd_uninitWSA), + // 0x04 + COMMAND(cmd_initFunc), + COMMAND(cmd_stopFunc), + COMMAND(cmd_wsaDisplayFrame), + COMMAND_UNIMPL(), + // 0x08 + COMMAND(cmd_loadVocFile), + COMMAND(cmd_unloadVocFile), + COMMAND(cmd_playVocFile), + COMMAND_UNIMPL(), + // 0x0C + COMMAND(cmd_loadSoundFile), + COMMAND(cmd_return(1)), + COMMAND(cmd_playMusicTrack), + COMMAND_UNIMPL(), + // 0x10 COMMAND(cmd_return(1)), COMMAND(cmd_return(1)), + COMMAND_UNIMPL(), + COMMAND_UNIMPL(), + // 0x14 + COMMAND(cmd_setLoopIp), + COMMAND(cmd_continueLoop), + COMMAND(cmd_resetLoopIp), + COMMAND(cmd_resetAllRuntimes), + // 0x18 + COMMAND(cmd_return(1)), + COMMAND(cmd_execOpcode), + COMMAND(cmd_initFuncNow), + COMMAND(cmd_stopFuncNow), + // 0x1C + COMMAND(cmd_processDialogue), + COMMAND(cmd_dialogueBox), COMMAND(cmd_return(n1)) }; #undef cmd_return - _commands = commandProcs; - _commandsSize = ARRAYSIZE(commandProcs); + _commands = vm->game() == GI_LOL ? commandProcsLOL : commandProcsHOF ; + _commandsSize = vm->game() == GI_LOL ? ARRAYSIZE(commandProcsLOL) : ARRAYSIZE(commandProcsHOF); memset(&_animations, 0, sizeof(_animations)); _langData = 0; _textDisplayed = false; _textAreaBuffer = new uint8[320*40]; assert(_textAreaBuffer); + _dlgSpeechEnabled = false; + _refresh = false; + _drawPage2 = 8; - _palDelayInc = _palDiff = _palDelayAcc = 0; + _palDelayInc = _palDiff = _palDelayAcc = 0; + _dialogueComplete = 0; + _activeVoiceFile = 0; } TIMInterpreter::~TIMInterpreter() { @@ -159,9 +207,9 @@ void TIMInterpreter::setLangData(const char *filename) { _langData = _vm->resource()->fileData(filename, 0); } -void TIMInterpreter::exec(TIM *tim, bool loop) { +int TIMInterpreter::exec(TIM *tim, bool loop) { if (!tim) - return; + return 0; _currentTim = tim; if (!_currentTim->func[0].ip) { @@ -170,14 +218,37 @@ void TIMInterpreter::exec(TIM *tim, bool loop) { } do { + if (_refresh) + _vm->gui()->update(); for (_currentFunc = 0; _currentFunc < TIM::kCountFuncs; ++_currentFunc) { TIM::Function &cur = _currentTim->func[_currentFunc]; if (_currentTim->procFunc != -1) execCommand(28, &_currentTim->procParam); - bool running = true; + if (_refresh) + _vm->gui()->update(); + + if (_dlgSpeechEnabled && _currentTim->procParam > 1 && cur.loopIp) { + if (!_vm->sound()->voiceIsPlaying(_activeVoiceFile)) { + cur.loopIp = 0; + _currentTim->dlgFunc = _currentFunc; + advanceToOpcode(21); + _currentTim->dlgFunc = -1; + } + } + + bool running = true; + int cnt = 0; while (cur.ip && cur.nextTime <= _system->getMillis() && running) { + if (cnt++ > 0) { + if (_currentTim->procFunc != -1) + execCommand(28, &_currentTim->procParam); + + if (_refresh) + _vm->gui()->update(); + } + int8 opcode = int8(cur.ip[2] & 0xFF); switch (execCommand(opcode, cur.ip + 3)) { @@ -193,6 +264,7 @@ void TIMInterpreter::exec(TIM *tim, bool loop) { case -3: _currentTim->procFunc = _currentFunc; + _currentTim->dlgFunc = -1; break; case 22: @@ -206,11 +278,18 @@ void TIMInterpreter::exec(TIM *tim, bool loop) { if (cur.ip) { cur.ip += cur.ip[0]; cur.lastTime = cur.nextTime; - cur.nextTime += cur.ip[1] * _vm->tickLength(); + cur.nextTime += (cur.ip[1] ) * _vm->tickLength(); } } } - } while (loop); + } while (loop && !_vm->shouldQuit()); + + return _currentTim->clickedButton; +} + +void TIMInterpreter::stopAllFuncs(TIM *tim) { + for (int i = 0; i < TIM::kCountFuncs; ++i) + tim->func[i].ip = 0; } void TIMInterpreter::refreshTimersAfterPause(uint32 elapsedTime) { @@ -342,6 +421,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char anim->x = x; anim->y = y; anim->wsaCopyParams = wsaFlags; + _drawPage2 = 8; uint16 wsaOpenFlags = ((wsaFlags & 0x10) != 0) ? 2 : 0; @@ -367,7 +447,7 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char _screen->checkedPageUpdate(8, 4); _screen->updateScreen(); } - + if (wsaFlags & 4) { snprintf(file, 32, "%s.CPS", filename); @@ -410,6 +490,41 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char return anim; } +TIMInterpreter::Animation *TIMInterpreter::initAnimStructIntern(int index, const char *filename, int x, int y, uint16 copyPara, uint16 wsaFlags) { + Animation *anim = &_animations[index]; + anim->x = x; + anim->y = y; + anim->wsaCopyParams = wsaFlags; + + uint16 wsaOpenFlags = 0; + if (wsaFlags & 0x10) + wsaOpenFlags |= 2; + if (wsaFlags & 8) + wsaOpenFlags |= 1; + + char file[32]; + snprintf(file, 32, "%s.WSA", filename); + + if (_vm->resource()->exists(file)) { + anim->wsa = new WSAMovie_v2(_vm, _screen); + assert(anim->wsa); + anim->wsa->open(file, wsaOpenFlags, _screen->getPalette(3)); + } + + return anim; +} + +int TIMInterpreter::freeAnimStruct(int index) { + Animation *anim = &_animations[index]; + if (!anim) + return 0; + + delete anim->wsa; + memset(anim, 0, sizeof(Animation)); + + return 1; +} + char *TIMInterpreter::getTableEntry(uint idx) { if (!_langData) return 0; @@ -424,6 +539,22 @@ const char *TIMInterpreter::getCTableEntry(uint idx) const { return (const char *)(_langData + READ_LE_UINT16(_langData + (idx<<1))); } +void TIMInterpreter::advanceToOpcode(int opcode) { + TIM::Function *f = &_currentTim->func[_currentTim->dlgFunc]; + uint16 len = f->ip[0]; + + while ((f->ip[2] & 0xFF) != opcode) { + if ((f->ip[2] & 0xFF) == 1) { + f->ip[0] = len; + break; + } + len = f->ip[0]; + f->ip += len; + } + + f->nextTime = _system->getMillis(); +} + int TIMInterpreter::execCommand(int cmd, const uint16 *param) { if (cmd < 0 || cmd >= _commandsSize) { warning("Calling unimplemented TIM command %d from file '%s'", cmd, _currentTim->filename); @@ -519,8 +650,10 @@ int TIMInterpreter::cmd_wsaDisplayFrame(const uint16 *param) { anim.wsa->setX(anim.x); anim.wsa->setY(anim.y); - anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : 8); + anim.wsa->setDrawPage((anim.wsaCopyParams & 0x4000) != 0 ? 2 : _drawPage2); anim.wsa->displayFrame(frame, anim.wsaCopyParams & 0xF0FF, 0, 0); + if (!_drawPage2) + _screen->updateScreen(); return 1; } @@ -573,7 +706,14 @@ int TIMInterpreter::cmd_playMusicTrack(const uint16 *param) { } int TIMInterpreter::cmd_setLoopIp(const uint16 *param) { - _currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip; + if (_dlgSpeechEnabled) { + if (_vm->sound()->voiceIsPlaying(_activeVoiceFile)) + _currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip; + else + advanceToOpcode(21); + } else { + _currentTim->func[_currentFunc].loopIp = _currentTim->func[_currentFunc].ip; + } return 1; } @@ -585,14 +725,16 @@ int TIMInterpreter::cmd_continueLoop(const uint16 *param) { func.ip = func.loopIp; - uint16 factor = param[0]; - if (factor) { - const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000); - uint32 waitTime = (random * factor) / 0x8000; - func.nextTime += waitTime * _vm->tickLength(); + if (!_vm->sound()->voiceIsPlaying(_activeVoiceFile)) { + uint16 factor = param[0]; + if (factor) { + const uint32 random = _vm->_rnd.getRandomNumberRng(0, 0x8000); + uint32 waitTime = (random * factor) / 0x8000; + func.nextTime += waitTime * _vm->tickLength(); + } } - return 1; + return -2; } int TIMInterpreter::cmd_resetLoopIp(const uint16 *param) { @@ -645,5 +787,59 @@ int TIMInterpreter::cmd_stopFuncNow(const uint16 *param) { return 1; } +int TIMInterpreter::cmd_stopAllFuncs(const uint16 *param) { + while (_currentTim->dlgFunc == -1 && _currentTim->clickedButton == 0 && !_vm->shouldQuit()) { + _vm->gui()->update(); + _currentTim->clickedButton = _vm->gui()->processDialogue(); + } + + for (int i = 0; i < TIM::kCountFuncs; ++i) + _currentTim->func[i].ip = 0; + + return -1; +} + +int TIMInterpreter::cmd_processDialogue(const uint16 *param) { + int res = _vm->gui()->processDialogue(); + if (!res ||!_currentTim->procParam) + return 0; + + if (_vm->sound()->voiceIsPlaying(_activeVoiceFile)) + _dialogueComplete = 0; + + _currentTim->func[_currentTim->procFunc].loopIp = 0; + _currentTim->dlgFunc = _currentTim->procFunc; + _currentTim->procFunc = -1; + _currentTim->clickedButton = res; + + if (_currentTim->procParam) + advanceToOpcode(21); + + return res; +} + +int TIMInterpreter::cmd_dialogueBox(const uint16 *param) { + uint16 func = *param; + assert(func < TIM::kCountFuncs); + _currentTim->procParam = func; + _currentTim->clickedButton = 0; + + const char *tmpStr[3]; + int cnt = 0; + + for (int i = 1; i < 4; i++) { + if (param[i] != 0xffff) { + tmpStr[i-1] = _vm->gui()->getTableString(param[i]); + cnt++; + } else { + tmpStr[i-1] = 0; + } + } + + _vm->gui()->drawDialogueBox(cnt, tmpStr[0], tmpStr[1], tmpStr[2]); + + return -3; +} + } // end of namespace Kyra |