From 335eb1bf0853dbdede70fc4366fd1ff166715198 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 24 May 2008 22:47:08 +0000 Subject: Committed my fix for bug #1497437 "KYRA1: Subtitles glitch during 'Speech of the Land'". svn-id: r32260 --- engines/kyra/kyra_lok.cpp | 1 + engines/kyra/kyra_lok.h | 2 ++ engines/kyra/script_lok.cpp | 68 +++++++++++++++++++++++++++++++++++++++----- engines/kyra/sound.cpp | 18 ++++++++++-- engines/kyra/sound.h | 13 +++++++-- engines/kyra/sound_lok.cpp | 2 +- engines/kyra/sound_towns.cpp | 6 ++-- engines/kyra/text.cpp | 2 +- engines/kyra/text_lok.cpp | 6 ++-- 9 files changed, 97 insertions(+), 21 deletions(-) diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index 0668cc7202..c852f6e3ee 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -91,6 +91,7 @@ KyraEngine_LoK::KyraEngine_LoK(OSystem *system, const GameFlags &flags) memset(_panPagesTable, 0, sizeof(_panPagesTable)); memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); _currHeadShape = 0; + _speechPlayTime = 0; memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp)); } diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index 6bae169a77..fa884750e5 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -211,6 +211,8 @@ public: void snd_voiceWaitForFinish(bool ingame = true); protected: + int32 _speechPlayTime; + void saveGame(const char *fileName, const char *saveName); void loadGame(const char *fileName); diff --git a/engines/kyra/script_lok.cpp b/engines/kyra/script_lok.cpp index 670c7282e3..d4825387d9 100644 --- a/engines/kyra/script_lok.cpp +++ b/engines/kyra/script_lok.cpp @@ -35,6 +35,7 @@ #include "kyra/animator_lok.h" #include "kyra/text.h" #include "kyra/timer.h" +#include "kyra/sound.h" namespace Kyra { int KyraEngine_LoK::o1_magicInMouseItem(EMCState *script) { @@ -320,9 +321,20 @@ int KyraEngine_LoK::o1_setBrandonStatusBit(EMCState *script) { } int KyraEngine_LoK::o1_delaySecs(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_delaySecs(%p) (%d)", (const void *)script, stackPos(0)); - if (stackPos(0) > 0 && !_skipFlag) - delay(stackPos(0)*1000, true); + if (_flags.isTalkie && speechEnabled()) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_voiceDelay(%p) (%d)", (const void *)script, stackPos(0)); + if (stackPos(0) == 0) { + snd_voiceWaitForFinish(true); + } else if (stackPos(0) < 0) { + uint32 time = ABS(stackPos(0)) * _tickLength; + delay(time, true); + } + } else { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_delaySecs(%p) (%d)", (const void *)script, stackPos(0)); + if (stackPos(0) >= 0 && !_skipFlag) + delay(stackPos(0)*1000, true); + } + _skipFlag = false; return 0; } @@ -700,7 +712,10 @@ int KyraEngine_LoK::o1_displayWSAFrameOnHidPage(EMCState *script) { } int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); + if (_flags.isTalkie) + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + else + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); int startFrame = stackPos(0); int endFrame = stackPos(1); int xpos = stackPos(2); @@ -708,6 +723,43 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { int waitTime = stackPos(4); int wsaIndex = stackPos(5); int maxTime = stackPos(6); + + if (_flags.isTalkie) { + int specialTime = stackPos(7); + if (specialTime) { + int32 voiceTime = _speechPlayTime; + if (voiceTime && voiceTime != -1) { + int displayFrames = ABS(endFrame-startFrame)+1; + displayFrames *= maxTime; + assert(displayFrames != 0); + + bool voiceSync = false; + + if (specialTime < 0) { + voiceSync = true; + specialTime = ABS(specialTime); + } + + voiceTime *= specialTime; + voiceTime /= 100; + + if (voiceSync) { + uint32 voicePlayedTime = _sound->voicePlayedTime(_speechFile.c_str()); + if (voicePlayedTime >= (uint32)voiceTime) + voiceTime = 0; + else + voiceTime -= voicePlayedTime; + + if (!snd_voiceIsPlaying()) + voiceTime = 0; + } + + waitTime = voiceTime / displayFrames; + waitTime /= _tickLength; + } + } + } + if (maxTime - 1 <= 0) maxTime = 1; @@ -734,7 +786,8 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { while (endFrame >= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; + if (waitTime) + _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); _animator->updateAllObjectShapes(); @@ -751,7 +804,8 @@ int KyraEngine_LoK::o1_displayWSASequentialFrames(EMCState *script) { while (endFrame <= frame) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); _movieObjects[wsaIndex]->displayFrame(frame); - _animator->_updateScreen = true; + if (waitTime) + _animator->_updateScreen = true; while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); _animator->updateAllObjectShapes(); @@ -1691,7 +1745,7 @@ int KyraEngine_LoK::o1_pauseMusicSeconds(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_LoK::o1_pauseMusicSeconds(%p) ()", (const void *)script); // if music disabled // return - o1_delaySecs(script); + delay(stackPos(0)*1000, true); return 0; } diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 854e2de41f..137956196f 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -66,14 +66,14 @@ bool Sound::voiceFileIsPresent(const char *file) { return false; } -bool Sound::voicePlay(const char *file, bool isSfx) { +int32 Sound::voicePlay(const char *file, bool isSfx) { char filenamebuffer[25]; int h = 0; while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return false; + return 0; Audio::AudioStream *audioStream = 0; @@ -107,7 +107,7 @@ bool Sound::voicePlay(const char *file, bool isSfx) { _soundChannels[h].file = file; _mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, audioStream); - return true; + return audioStream->getTotalPlayTime(); } void Sound::voiceStop(const char *file) { @@ -140,6 +140,18 @@ bool Sound::voiceIsPlaying(const char *file) { return res; } +uint32 Sound::voicePlayedTime(const char *file) { + if (!file) + return 0; + + for (int i = 0; i < kNumChannelHandles; ++i) { + if (_soundChannels[i].file == file) + return _mixer->getSoundElapsedTime(_soundChannels[i].channelHandle); + } + + return 0; +} + #pragma mark - SoundMidiPC::SoundMidiPC(KyraEngine_v1 *vm, Audio::Mixer *mixer, MidiDriver *driver) : Sound(vm, mixer) { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 595619c7e9..2427a6cdde 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -174,9 +174,9 @@ public: * * @param file file to be played * @param isSfx marks file as sfx instead of voice - * @return channel the voice file is played on + * @return playtime of the voice file (-1 marks unknown playtime) */ - virtual bool voicePlay(const char *file, bool isSfx = false); + virtual int32 voicePlay(const char *file, bool isSfx = false); /** * Checks if a voice is being played. @@ -185,6 +185,13 @@ public: */ bool voiceIsPlaying(const char *file = 0); + /** + * Checks how long a voice has been playing + * + * @return time in milliseconds + */ + uint32 voicePlayedTime(const char *file); + /** * Stops playback of the current voice. */ @@ -449,7 +456,7 @@ public: void haltTrack(); void beginFadeOut(); - bool voicePlay(const char *file, bool isSfx = false); + int32 voicePlay(const char *file, bool isSfx = false); void playSoundEffect(uint8) {} private: diff --git a/engines/kyra/sound_lok.cpp b/engines/kyra/sound_lok.cpp index 728013cdaa..b12b1fa800 100644 --- a/engines/kyra/sound_lok.cpp +++ b/engines/kyra/sound_lok.cpp @@ -67,7 +67,7 @@ void KyraEngine_LoK::snd_playVoiceFile(int id) { assert(id >= 0 && id < 9999); sprintf(vocFile, "%03d", id); _speechFile = vocFile; - _sound->voicePlay(vocFile); + _speechPlayTime = _sound->voicePlay(vocFile); } void KyraEngine_LoK::snd_voiceWaitForFinish(bool ingame) { diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 5a1801b803..4265533507 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1432,7 +1432,7 @@ void SoundTowns_v2::haltTrack() { //_driver->reset(); } -bool SoundTowns_v2::voicePlay(const char *file, bool) { +int32 SoundTowns_v2::voicePlay(const char *file, bool) { static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 }; int h = 0; @@ -1440,7 +1440,7 @@ bool SoundTowns_v2::voicePlay(const char *file, bool) { while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles) h++; if (h >= kNumChannelHandles) - return false; + return 0; } char filename [13]; @@ -1497,7 +1497,7 @@ bool SoundTowns_v2::voicePlay(const char *file, bool) { _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].channelHandle, _currentSFX); delete[] data; - return true; + return 1; } void SoundTowns_v2::beginFadeOut() { diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index 931c5fe1c9..f8eb10a85e 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -210,7 +210,7 @@ void TextDisplayer::printTalkTextMessage(const char *text, int x, int y, uint8 c calcWidestLineBounds(x1, x2, w, x); _talkCoords.x = x1; _talkCoords.w = w + 2; - _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage); + _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage, Screen::CR_NO_P_CHECK); int curPage = _screen->_curPage; _screen->_curPage = srcPage; for (int i = 0; i < lineCount; ++i) { diff --git a/engines/kyra/text_lok.cpp b/engines/kyra/text_lok.cpp index ccca079e32..f6b0407a75 100644 --- a/engines/kyra/text_lok.cpp +++ b/engines/kyra/text_lok.cpp @@ -62,10 +62,8 @@ void KyraEngine_LoK::waitForChatToFinish(int vocFile, int16 chatDuration, const if (chatDuration != -1) chatDuration *= _tickLength; - if (vocFile != -1) { - snd_voiceWaitForFinish(); + if (vocFile != -1) snd_playVoiceFile(vocFile); - } _timer->disable(14); _timer->disable(18); @@ -269,6 +267,8 @@ void KyraEngine_LoK::characterSays(int vocFile, const char *chatStr, int8 charNu if (_currentCharacter->sceneId == 210) return; + snd_voiceWaitForFinish(true); + convoInitialized = initCharacterChat(charNum); chatPartnerNum = getChatPartnerNum(); -- cgit v1.2.3