diff options
-rw-r--r-- | engines/kyra/lol.cpp | 55 | ||||
-rw-r--r-- | engines/kyra/lol.h | 8 | ||||
-rw-r--r-- | engines/kyra/screen_lol.cpp | 5 | ||||
-rw-r--r-- | engines/kyra/screen_lol.h | 1 | ||||
-rw-r--r-- | engines/kyra/script_lol.cpp | 16 | ||||
-rw-r--r-- | engines/kyra/sound.cpp | 10 | ||||
-rw-r--r-- | engines/kyra/sound.h | 2 | ||||
-rw-r--r-- | engines/kyra/text_lol.cpp | 143 | ||||
-rw-r--r-- | engines/kyra/text_lol.h | 10 |
9 files changed, 197 insertions, 53 deletions
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index f2ec3950fa..b6b655bd9c 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -190,7 +190,8 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy memset(_activeTim, 0, sizeof(_activeTim)); memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile)); memset(_openDoorState, 0, sizeof(_openDoorState)); - + + _activeVoiceFileTotalTime = 0; _pageBuffer1 = _pageBuffer2 = 0; memset(_charStatsTemp, 0, sizeof(_charStatsTemp)); @@ -359,8 +360,7 @@ Common::Error LoLEngine::init() { _pageBuffer2 = new uint8[0xfa00]; memset(_pageBuffer2, 0, 0xfa00); - // FIXME: Why do we allocate a 401 entry array, if only 400 entries are used? - _itemsInPlay = new ItemInPlay[401]; + _itemsInPlay = new ItemInPlay[400]; memset(_itemsInPlay, 0, sizeof(ItemInPlay) * 400); _characters = new LoLCharacter[4]; @@ -416,7 +416,7 @@ Common::Error LoLEngine::init() { memset(_tmpData136, 0, 136); memset(_gameFlags, 0, 16 * sizeof(uint16)); - memset(_unkEMC46, 0, 16 * sizeof(uint16)); + memset(_globalScriptVars, 0, 16 * sizeof(uint16)); _levelFileData = 0; _lvlShpFileHandle = 0; @@ -1167,9 +1167,44 @@ void LoLEngine::restoreAfterAnimatedDialogue(int redraw) { } void LoLEngine::initNonAnimatedDialogue(int controlMode, int pageNum) { + if (controlMode) { + _timer->disable(11); + _fadeText = false; + int cp = _screen->setCurPage(pageNum); + + _screen->fillRect(0, 128, 319, 199, 1); + gui_drawBox(0, 129, 320, 71, 136, 251, -1); + gui_drawBox(1, 130, 318, 69, 136, 251, 252); + + _screen->modifyScreenDim(5, 8, 131, 304, 66); + _screen->modifyScreenDim(4, 1, 133, 38, 60); + _screen->clearDim(4); + + _updateFlags |= 2; + _hideControls = controlMode; + calcCharPortraitXpos(); + + if (!textEnabled() && (!(controlMode & 2))) { + int nc = countActiveCharacters(); + for (int i = 0; i < nc; i++) { + _portraitSpeechAnimMode = 2; + _updateCharNum = i; + _screen->drawShape(0, _gameShapes[88], _activeCharsXpos[_updateCharNum] + 8, 142, 0, 0); + updatePortraits(); + } + } + + _screen->setCurPage(cp); + + } else { + _txt->setupField(true); + _txt->expandField(); + setupScreenDims(); + _screen->clearDim(4); + } - _dialogueField = true; - + _hideControls = controlMode; + _dialogueField = true; } void LoLEngine::restoreAfterNonAnimatedDialogue(int controlMode) { @@ -1327,7 +1362,7 @@ bool LoLEngine::snd_playCharacterSpeech(int id, int8 speaker, int) { }; strcpy(_activeVoiceFile, *playList.begin()); - _sound->voicePlayFromList(playList); + _activeVoiceFileTotalTime = _sound->voicePlayFromList(playList); for (Common::List<const char*>::iterator i = playList.begin(); i != playList.end(); i++) delete []*i; @@ -1343,6 +1378,7 @@ int LoLEngine::snd_characterSpeaking() { return 2; _lastSpeechId = _lastSpeaker = -1; + _activeVoiceFileTotalTime = 0; return 1; } @@ -1353,11 +1389,16 @@ void LoLEngine::snd_stopSpeech(bool setFlag) { //_dlgTimer = 0; _sound->voiceStop(_activeVoiceFile); + _activeVoiceFileTotalTime = 0; if (setFlag) _tim->_abortFlag = 1; } +uint32 LoLEngine::snd_getElapsedSpeechTime() { + return _sound->voicePlayedTime(_activeVoiceFile); +} + void LoLEngine::snd_playSoundEffect(int track, int volume) { debugC(9, kDebugLevelMain | kDebugLevelSound, "LoLEngine::snd_playSoundEffect(%d, %d)", track, volume); diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 91883117a1..3e7ab12547 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -327,6 +327,7 @@ private: bool snd_playCharacterSpeech(int id, int8 speaker, int); int snd_characterSpeaking(); void snd_stopSpeech(bool setFlag); + uint32 snd_getElapsedSpeechTime(); void snd_playSoundEffect(int track, int volume); void snd_processEnvironmentalSoundEffect(int soundId, int block); void snd_loadSoundFile(int track); @@ -336,6 +337,7 @@ private: int _lastSpeechId; int _lastSpeaker; char _activeVoiceFile[13]; + uint32 _activeVoiceFileTotalTime; int _lastSfxTrack; int _lastMusicTrack; int _curMusicFileIndex; @@ -494,7 +496,7 @@ private: bool _sceneUpdateRequired; int16 _currentBlockPropertyIndex[18]; uint16 _gameFlags[16]; - uint16 _unkEMC46[16]; + uint16 _globalScriptVars[16]; // emc opcode int olol_drawScene(EMCState *script); @@ -519,8 +521,8 @@ private: int olol_getDirection(EMCState *script); int olol_setMusicTrack(EMCState *script); int olol_clearDialogueField(EMCState *script); - int olol_getUnkArrayVal(EMCState *script); - int olol_setUnkArrayVal(EMCState *script); + int olol_getGlobalScriptVar(EMCState *script); + int olol_setGlobalScriptVar(EMCState *script); int olol_getGlobalVar(EMCState *script); int olol_setGlobalVar(EMCState *script); int olol_triggerDoorSwitch(EMCState *script); diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 615dd0c4b3..884dee4712 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -92,11 +92,6 @@ void Screen_LoL::clearDim(int dim) { fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, tmp->unkA); } -void Screen_LoL::clearCurDim() { - fillRect(_curDim->sx << 3, _curDim->sy, ((_curDim->sx + _curDim->w) << 3) - 1, (_curDim->sy + _curDim->h) - 1, _curDim->unkA); - _dimLineCount = 0; -} - void Screen_LoL::fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) { debugC(9, kDebugLevelScreen, "Screen_LoL::fprintString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags); if (!format) diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 1b1842bffc..4de43788b1 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -44,7 +44,6 @@ public: int curDimIndex() { return _curDimIndex; } void modifyScreenDim(int dim, int x, int y, int w, int h); void clearDim(int dim); - void clearCurDim(); void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...); void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...); diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index b4127a7774..31414f3b50 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -452,12 +452,16 @@ int LoLEngine::olol_clearDialogueField(EMCState *script) { return 1; } -int LoLEngine::olol_getUnkArrayVal(EMCState *script) { - return _unkEMC46[stackPos(0)]; +int LoLEngine::olol_getGlobalScriptVar(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getGlobalScriptVar(%p) (%d)", (const void *)script, stackPos(0)); + assert(stackPos(0) < 16); + return _globalScriptVars[stackPos(0)]; } -int LoLEngine::olol_setUnkArrayVal(EMCState *script) { - _unkEMC46[stackPos(0)] = stackPos(1); +int LoLEngine::olol_setGlobalScriptVar(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGlobalScriptVar(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < 16); + _globalScriptVars[stackPos(0)] = stackPos(1); return 1; } @@ -1194,8 +1198,8 @@ void LoLEngine::setupOpcodeTable() { // 0x2C OpcodeUnImpl(); - Opcode(olol_getUnkArrayVal); - Opcode(olol_setUnkArrayVal); + Opcode(olol_getGlobalScriptVar); + Opcode(olol_setGlobalScriptVar); Opcode(olol_getGlobalVar); // 0x30 diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 47045c21cd..4b4439c1e3 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -115,21 +115,22 @@ int32 Sound::voicePlay(const char *file, uint8 volume, bool isSfx) { return audioStream->getTotalPlayTime(); } -void Sound::voicePlayFromList(Common::List<const char*> fileList) { +uint32 Sound::voicePlayFromList(Common::List<const char*> fileList) { int h = 0; while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return; + return 0; Audio::AppendableAudioStream *out = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); for (Common::List<const char*>::iterator i = fileList.begin(); i != fileList.end(); i++) { Common::SeekableReadStream *file = _vm->resource()->createReadStream(*i); - // TODO: Maybe output an warning like "file not found"? - if (!file) + if (!file) { + warning("Couldn't load voice file: %s", *i); continue; + } int size, rate; uint8 *data = Audio::loadVOCFromStream(*file, size, rate); @@ -151,6 +152,7 @@ void Sound::voicePlayFromList(Common::List<const char*> fileList) { _soundChannels[h].file = *fileList.begin(); _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, out); + return out->getTotalPlayTime(); } void Sound::voiceStop(const char *file) { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 6f6a088b8b..7b7fba8e3a 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -203,7 +203,7 @@ public: * * @param fileList: files to be played */ - virtual void voicePlayFromList(Common::List<const char*> fileList); + virtual uint32 voicePlayFromList(Common::List<const char*> fileList); /** * Checks if a voice is being played. diff --git a/engines/kyra/text_lol.cpp b/engines/kyra/text_lol.cpp index ac7d7c4a6c..5996712bd3 100644 --- a/engines/kyra/text_lol.cpp +++ b/engines/kyra/text_lol.cpp @@ -31,7 +31,7 @@ namespace Kyra { TextDisplayer_LoL::TextDisplayer_LoL(LoLEngine *vm, Screen_LoL *screen) : _vm(vm), _screen(screen), - _scriptParameter(0), _stringLength(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true), + _scriptParameter(0), _animWidth(0), _animColour1(0), _animColour2(0), _animFlag(true), _printFlag(false), _lineWidth(0), _numChars(0), _numCharsPrinted(0), _posX(0), _posY(0), _colour1(0), _colour2(0) { memset(_stringParameters, 0, 15 * sizeof(char*)); @@ -184,10 +184,10 @@ void TextDisplayer_LoL::printMessage(uint16 type, char *str, ...) { if (_vm->_updateFlags & 2) { _screen->setScreenDim(4); - _screen->clearCurDim(); + clearCurDim(); } else { _screen->setScreenDim(3); - _screen->clearCurDim(); + clearCurDim(); _screen->copyColour(192, col); _vm->enableTimer(11); } @@ -360,10 +360,7 @@ void TextDisplayer_LoL::displayText(char *str, ...) { switch (c - 1) { case 0: printLine(_currentLine); - //if (!_dlgAnimCallback) - // break; - - portraitAnimation2(); + textPageBreak(); _numCharsPrinted = 0; break; @@ -478,10 +475,8 @@ void TextDisplayer_LoL::printLine(char *str) { while (_posY >= lines) { if (lines <= _screen->_dimLineCount && _animFlag) { _screen->_dimLineCount = 0; - //if (_dlgAnimCallback) { - portraitAnimation2(); - _numCharsPrinted = 0; - //} + textPageBreak(); + _numCharsPrinted = 0; } int h1 = ((sd->h / fh) - 1) * fh; @@ -490,9 +485,9 @@ void TextDisplayer_LoL::printLine(char *str) { if (h2) _screen->copyRegion(sd->sx << 3, sd->sy + fh, sd->sx << 3, sd->sy, sd->w << 3, h2, _screen->_curPage, _screen->_curPage, Screen::CR_NO_P_CHECK); - _screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2); - - _posY--; + _screen->fillRect(sd->sx << 3, sd->sy + h1, (sd->sx + sd->w - 1) << 3, sd->sy + sd->h - 1, _colour2); + if (_posY) + _posY--; } int x1 = (sd->sx << 3) + _posX; @@ -567,12 +562,122 @@ void TextDisplayer_LoL::printLine(char *str) { printLine(str); } -/*void TextDisplayer_LoL::portraitAnimation1(const char *str, uint16 lineWidth, uint8 col1, uint8 col2, uint16 numCharsPrinted) { - -}*/ +void TextDisplayer_LoL::textPageBreak() { + int cp = _screen->setCurPage(0); + Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT); + + _vm->_timer->pauseSingleTimer(11, true); + + _vm->_fadeText = false; + int updateCharV3 = 0; + int updatePortraitSpeechAnimDuration = 0; + + if (_vm->_updateCharNum != -1) { + updateCharV3 = _vm->_updateCharV3; + _vm->_updateCharV3 = 0; + updatePortraitSpeechAnimDuration = _vm->_updatePortraitSpeechAnimDuration; + if (_vm->_updatePortraitSpeechAnimDuration > 36) + _vm->_updatePortraitSpeechAnimDuration = 36; + } + + uint32 speechPartTime = 0; + if (_vm->_speechFlag && _vm->_activeVoiceFileTotalTime && _numChars) + speechPartTime = _vm->_system->getMillis() + ((_numCharsPrinted * _vm->_activeVoiceFileTotalTime) / _numChars); + + const ScreenDim *dim = _screen->getScreenDim(_screen->curDimIndex()); + + int x = ((dim->sx + dim->w) << 3) - 77; + int y = 0; + + if (_vm->_hideInventory && (_vm->_updateFlags & 2)) { + if (_vm->_hideControls || !(_vm->_updateFlags & 2)) { + y = dim->sy + dim->h - 5; + } else { + x += 6; + y = dim->sy + dim->h - 2; + } + } else { + y = dim->sy + dim->h - 10; + } + + _vm->gui_drawBox(x, y, 74, 9, 136, 251, -1); + char *txt = _vm->getLangString(0x4073); + _vm->_screen->printText(txt, x + 37 - (_vm->_screen->getTextWidth(txt) >> 1), y + 2, 144, 0); + + _vm->removeInputTop(); + + bool loop = true; + bool target = false; + + do { + int inputFlag = _vm->checkInput(0, false) & 0xFF; + _vm->removeInputTop(); + + while (!inputFlag) { + _vm->update(); + + if (_vm->_speechFlag) { + if (((_vm->_system->getMillis() > speechPartTime) || (_vm->snd_characterSpeaking() != 2)) && speechPartTime) { + loop = false; + inputFlag = 43; + break; + } + } + + inputFlag = _vm->checkInput(0, false) & 0xFF; + _vm->removeInputTop(); + } + + _vm->gui_notifyButtonListChanged(); + + switch (inputFlag) { + case 43: + case 61: + loop = false; + break; + + case 199: + case 201: + if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + 74, y + 9)) + target = true; + break; + + case 200: + case 202: + if (target) + loop = false; + break; + + default: + break; + } + } while (loop); + + _screen->fillRect(x, y, x + 74, y + 9, _colour2); + clearCurDim(); + + _vm->_timer->pauseSingleTimer(11, false); + + if (_vm->_updateCharNum != -1) { + _vm->_updateCharV3 = updateCharV3; + if (updatePortraitSpeechAnimDuration > 36) + updatePortraitSpeechAnimDuration -= 36; + else + updatePortraitSpeechAnimDuration >>= 1; + + _vm->_updatePortraitSpeechAnimDuration = updatePortraitSpeechAnimDuration; + } + + _screen->setFont(cf); + _screen->setCurPage(cp); + _vm->removeInputTop(); +} -void TextDisplayer_LoL::portraitAnimation2() { - // TODO +void TextDisplayer_LoL::clearCurDim() { + const ScreenDim *tmp = _screen->getScreenDim(_screen->curDimIndex()); + _screen->fillRect(tmp->sx << 3, tmp->sy, ((tmp->sx + tmp->w) << 3) - 1, (tmp->sy + tmp->h) - 1, _colour2); + _screen->_dimLineCount = 0; + _posX = _posY = 0; } } // end of namespace Kyra diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index 82eebd862d..9876bfbb56 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -55,12 +55,9 @@ private: void readNextPara(); void printLine(char *str); void preprocessString(char *str, EMCState *script, const uint16 *paramList, int16 paramIndex); - - //typedef void (LoLEngine::*DialogueAnimCallback)(const char *str, uint16 lineWidth, uint8 col1, uint8 col2); - //DialogueAnimCallback _dlgAnimCallback; - //void portraitAnimation1(const char *str); - void portraitAnimation2(); - + void textPageBreak(); + + void clearCurDim(); char *_stringParameters[15]; char *_buffer; @@ -71,7 +68,6 @@ private: char _ctrl[3]; char _scriptParaString[11]; - uint32 _stringLength; uint16 _lineWidth; uint32 _numChars; |