From 9840744acc6e43135ef5e28d041b1d55dd86804b Mon Sep 17 00:00:00 2001 From: athrxx Date: Thu, 9 Aug 2012 18:13:15 +0200 Subject: KYRA: move HOF sequence player into its own class (also cleaning up and fixing things while doing that) --- engines/kyra/kyra_hof.cpp | 80 +- engines/kyra/kyra_hof.h | 273 +-- engines/kyra/kyra_lok.h | 2 + engines/kyra/kyra_v1.cpp | 13 - engines/kyra/kyra_v1.h | 2 + engines/kyra/lol.cpp | 15 +- engines/kyra/lol.h | 8 + engines/kyra/resource.h | 16 +- engines/kyra/scene_lol.cpp | 4 +- engines/kyra/screen_hof.cpp | 6 - engines/kyra/screen_hof.h | 2 +- engines/kyra/screen_lol.cpp | 28 - engines/kyra/screen_lol.h | 1 - engines/kyra/screen_v2.cpp | 34 + engines/kyra/screen_v2.h | 5 + engines/kyra/sequences_hof.cpp | 4862 ++++++++++++++++++++++------------------ engines/kyra/sequences_lol.cpp | 13 +- engines/kyra/staticres.cpp | 152 +- 18 files changed, 2887 insertions(+), 2629 deletions(-) (limited to 'engines') diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 7fbecb7f53..885e3d5d00 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -52,13 +52,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn _screen = 0; _text = 0; - _seqProcessedString = 0; - _activeWSA = 0; - _activeText = 0; - _seqWsa = 0; - _sequences = 0; - _sequenceSoundList = 0; - _gamePlayBuffer = 0; _cCodeBuffer = _optionsBuffer = _chapterBuffer = 0; @@ -89,7 +82,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn memset(&_invWsa, 0, sizeof(_invWsa)); _itemAnimDefinition = 0; - _demoAnimData = 0; _nextAnimItem = 0; for (int i = 0; i < 15; i++) @@ -136,7 +128,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn memset(_cauldronStateTables, 0, sizeof(_cauldronStateTables)); _menuDirectlyToLoad = false; - _menu = 0; _chatIsNote = false; memset(&_npcScriptData, 0, sizeof(_npcScriptData)); @@ -148,7 +139,6 @@ KyraEngine_HoF::KyraEngine_HoF(OSystem *system, const GameFlags &flags) : KyraEn KyraEngine_HoF::~KyraEngine_HoF() { cleanup(); - seq_uninit(); delete _screen; delete _text; @@ -157,15 +147,6 @@ KyraEngine_HoF::~KyraEngine_HoF() { _text = 0; delete _invWsa.wsa; - if (_sequenceSoundList) { - for (int i = 0; i < _sequenceSoundListSize; i++) { - if (_sequenceSoundList[i]) - delete[] _sequenceSoundList[i]; - } - delete[] _sequenceSoundList; - _sequenceSoundList = NULL; - } - delete[] _dlgBuffer; for (int i = 0; i < 19; i++) delete[] _conversationState[i]; @@ -179,41 +160,13 @@ KyraEngine_HoF::~KyraEngine_HoF() { void KyraEngine_HoF::pauseEngineIntern(bool pause) { KyraEngine_v2::pauseEngineIntern(pause); + seq_pausePlayer(pause); + if (!pause) { uint32 pausedTime = _system->getMillis() - _pauseStart; _pauseStart = 0; - // sequence player - // - // Timers in KyraEngine_HoF::seq_cmpFadeFrame() and KyraEngine_HoF::seq_animatedSubFrame() - // have been left out for now. I think we don't need them here. - - _seqStartTime += pausedTime; - _seqSubFrameStartTime += pausedTime; - _seqEndTime += pausedTime; - _seqSubFrameEndTimeInternal += pausedTime; - _seqWsaChatTimeout += pausedTime; - _seqWsaChatFrameTimeout += pausedTime; - - if (_activeText) { - for (int x = 0; x < 10; x++) { - if (_activeText[x].duration != -1) - _activeText[x].startTime += pausedTime; - } - } - - if (_activeWSA) { - for (int x = 0; x < 8; x++) { - if (_activeWSA[x].flags != -1) - _activeWSA[x].nextFrame += pausedTime; - } - } - _nextIdleAnim += pausedTime; - - for (int x = 0; x < _itemAnimDefinitionSize; x++) - _activeItemAnim[x].nextFrameTime += pausedTime; - _tim->refreshTimersAfterPause(pausedTime); } } @@ -254,13 +207,6 @@ Common::Error KyraEngine_HoF::init() { if (!_sound->init()) error("Couldn't init sound"); - _abortIntroFlag = false; - - if (_sequenceStrings) { - for (int i = 0; i < MIN(33, _sequenceStringsSize); i++) - _sequenceStringsDuration[i] = (int) strlen(_sequenceStrings[i]) * 8; - } - // No mouse display in demo if (_flags.isDemo && !_flags.isTalkie) return Common::kNoError; @@ -279,28 +225,24 @@ Common::Error KyraEngine_HoF::init() { } Common::Error KyraEngine_HoF::go() { + int menuChoice = 0; + if (_gameToLoad == -1) { if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) seq_showStarcraftLogo(); if (_flags.isDemo && !_flags.isTalkie) { -#ifdef ENABLE_LOL - if (_flags.gameID == GI_LOL) - seq_playSequences(kSequenceLoLDemoScene1, kSequenceLoLDemoScene6); - else -#endif // ENABLE_LOL - seq_playSequences(kSequenceDemoVirgin, kSequenceDemoFisher); - _menuChoice = 4; + menuChoice = seq_playDemo(); } else { - seq_playSequences(kSequenceVirgin, kSequenceZanfaun); + menuChoice = seq_playIntro(); } } else { - _menuChoice = 1; + menuChoice = 1; } _res->unloadAllPakFiles(); - if (_menuChoice != 4) { + if (menuChoice != 4) { // load just the pak files needed for ingame _staticres->loadStaticResourceFile(); @@ -317,17 +259,17 @@ Common::Error KyraEngine_HoF::go() { } } - _menuDirectlyToLoad = (_menuChoice == 3) ? true : false; + _menuDirectlyToLoad = (menuChoice == 3) ? true : false; _menuDirectlyToLoad &= saveFileLoadable(0); - if (_menuChoice & 1) { + if (menuChoice & 1) { startup(); if (!shouldQuit()) runLoop(); cleanup(); if (_showOutro) - seq_playSequences(kSequenceFunters, kSequenceFrash); + seq_playOutro(); } return Common::kNoError; diff --git a/engines/kyra/kyra_hof.h b/engines/kyra/kyra_hof.h index 182854cdf1..3ee6446436 100644 --- a/engines/kyra/kyra_hof.h +++ b/engines/kyra/kyra_hof.h @@ -35,158 +35,13 @@ namespace Kyra { -enum Sequences { - kSequenceVirgin = 0, - kSequenceWestwood, - kSequenceTitle, - kSequenceOverview, - kSequenceLibrary, - kSequenceHand, - kSequencePoint, - kSequenceZanfaun, - - kSequenceFunters, - kSequenceFerb, - kSequenceFish, - kSequenceFheep, - kSequenceFarmer, - kSequenceFuards, - kSequenceFirates, - kSequenceFrash, - - kSequenceArraySize -}; - -enum NestedSequences { - kSequenceFiggle = 0, - kSequenceOver1, - kSequenceOver2, - kSequenceForest, - kSequenceDragon, - kSequenceDarm, - kSequenceLibrary2, - kSequenceLibrary3, - kSequenceMarco, - kSequenceHand1a, - kSequenceHand1b, - kSequenceHand1c, - kSequenceHand2, - kSequenceHand3, - kSequenceHand4 -}; - -enum SequencesDemo { - kSequenceDemoVirgin = 0, - kSequenceDemoWestwood, - kSequenceDemoTitle, - kSequenceDemoHill, - kSequenceDemoOuthome, - kSequenceDemoWharf, - kSequenceDemoDinob, - kSequenceDemoFisher -}; - -enum NestedSequencesDemo { - kSequenceDemoWharf2 = 0, - kSequenceDemoDinob2, - kSequenceDemoWater, - kSequenceDemoBail, - kSequenceDemoDig -}; - -#ifdef ENABLE_LOL -enum SequencesLoLDemo { - kSequenceLoLDemoScene1 = 0, - kSequenceLoLDemoText1, - kSequenceLoLDemoScene2, - kSequenceLoLDemoText2, - kSequenceLoLDemoScene3, - kSequenceLoLDemoText3, - kSequenceLoLDemoScene4, - kSequenceLoLDemoText4, - kSequenceLoLDemoScene5, - kSequenceLoLDemoText5, - kSequenceLoLDemoScene6 -}; -#endif // ENABLE_LOL - -class WSAMovie_v2; -class KyraEngine_HoF; +//class WSAMovie_v2; +//class KyraEngine_HoF; class TextDisplayer_HoF; +class SeqPlayer_HOF; struct TIM; -typedef int (KyraEngine_HoF::*SeqProc)(WSAMovie_v2 *, int, int, int); - -struct ActiveWSA { - SeqProc callback; - WSAMovie_v2 *movie; - const FrameControl *control; - int16 flags; - uint16 startFrame; - uint16 endFrame; - uint16 frameDelay; - uint32 nextFrame; - uint16 currentFrame; - uint16 lastFrame; - uint16 x; - uint16 y; - uint16 startupCommand; - uint16 finalCommand; -}; - -struct ActiveText { - uint16 strIndex; - uint16 x; - uint16 y; - uint16 width; - int32 duration; - uint32 startTime; - int16 textcolor; -}; - -struct Sequence { - const char *wsaFile; - const char *cpsFile; - uint16 flags; - uint8 startupCommand; - uint8 finalCommand; - int16 stringIndex1; - int16 stringIndex2; - uint16 startFrame; - uint16 numFrames; - uint16 frameDelay; - uint16 xPos; - uint16 yPos; - uint16 duration; -}; - -struct NestedSequence { - const char *wsaFile; - const FrameControl *wsaControl; - uint16 flags; - uint16 startframe; - uint16 endFrame; - uint16 frameDelay; - uint16 x; - uint16 y; - uint16 startupCommand; - uint16 finalCommand; -}; - -struct HofSeqData { - const Sequence *seq; - int numSeq; - const NestedSequence *seqn; - int numSeqn; -}; - -struct ItemAnimData_v1 { - int16 itemIndex; - uint16 y; - const uint16 *frames; -}; - class KyraEngine_HoF : public KyraEngine_v2 { friend class Debugger_HoF; friend class TextDisplayer_HoF; @@ -202,98 +57,19 @@ public: GUI *gui() const { return _gui; } virtual TextDisplayer *text() { return _text; } int language() const { return _lang; } + const AudioDataStruct *soundData(int index) { return &_soundData[index]; } + protected: static const EngineDesc _hofEngineDesc; // intro/outro - void seq_playSequences(int startSeq, int endSeq = -1); - - int seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm); - - int seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm); - -#ifdef ENABLE_LOL - int seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene2(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene3(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene4(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoText5(WSAMovie_v2 *wsaObj, int x, int y, int frm); - int seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm); -#endif // ENABLE_LOL - - void seq_sequenceCommand(int command); - void seq_loadNestedSequence(int wsaNum, int seqNum); - void seq_nestedSequenceFrame(int command, int wsaNum); - void seq_animatedSubFrame(int srcPage, int dstPage, int delaytime, - int steps, int x, int y, int w, int h, int openClose, int directionFlags); - bool seq_processNextSubFrame(int wsaNum); - void seq_resetActiveWSA(int wsaNum); - void seq_unloadWSA(int wsaNum); - void seq_processWSAs(); - void seq_cmpFadeFrame(const char *cmpFile); - void seq_playTalkText(uint8 chatNum); - void seq_resetAllTextEntries(); - uint32 seq_activeTextsTimeLeft(); - void seq_waitForTextsTimeout(); - int seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width); - void seq_processText(); - char *seq_preprocessString(const char *str, int width); - void seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor); - void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, - WSAMovie_v2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); - void seq_finaleActorScreen(); - void seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData = 0, const char *const *specialData = 0); - void seq_scrollPage(int bottom, int top); void seq_showStarcraftLogo(); - MainMenu *_menu; + int seq_playIntro(); + int seq_playOutro(); + int seq_playDemo(); - void seq_init(); - void seq_uninit(); + void seq_pausePlayer(bool toggle); Common::Error init(); Common::Error go(); @@ -312,6 +88,7 @@ protected: static const int _pcSpkSfxMapSize; AudioDataStruct _soundData[3]; + protected: // game initialization void startup(); @@ -841,11 +618,11 @@ protected: bool _chatAltFlag; // sequence player - ActiveWSA *_activeWSA; +/* ActiveWSA *_activeWSA; ActiveText *_activeText; - - const char * const *_sequencePakList; - int _sequencePakListSize; + */ + /*const char * const *_sequencePakList; + int _sequencePakListSize;*/ const char * const *_ingamePakList; int _ingamePakListSize; @@ -861,34 +638,33 @@ protected: int _cdaTrackTableIngameSize; const uint8 *_cdaTrackTableFinale; int _cdaTrackTableFinaleSize; - const char * const *_sequenceSoundList; - int _sequenceSoundListSize; const char * const *_ingameSoundList; int _ingameSoundListSize; const uint16 *_ingameSoundIndex; int _ingameSoundIndexSize; - const char * const *_sequenceStrings; - int _sequenceStringsSize; const uint16 *_ingameTalkObjIndex; int _ingameTalkObjIndexSize; const char * const *_ingameTimJpStr; int _ingameTimJpStrSize; - const HofSeqData *_sequences; + const ItemAnimDefinition *_itemAnimDefinition; int _itemAnimDefinitionSize; + + /*const HofSeqData *_sequences; + const ItemAnimData_v1 *_demoAnimData; int _demoAnimSize; - int _sequenceStringsDuration[33]; + int _sequenceStringsDuration[33];*/ - static const uint8 _seqTextColorPresets[]; +/* static const uint8 _seqTextColorPresets[]; char *_seqProcessedString; WSAMovie_v2 *_seqWsa; bool _abortIntroFlag; - int _menuChoice; + int _menuChoice;*/ - uint32 _seqFrameDelay; + /*uint32 _seqFrameDelay; uint32 _seqStartTime; uint32 _seqSubFrameStartTime; uint32 _seqEndTime; @@ -902,10 +678,7 @@ protected: bool _seqSpecialFlag; bool _seqSubframePlaying; uint8 _seqTextColor[2]; - uint8 _seqTextColorMap[16]; - - const SeqProc *_callbackS; - const SeqProc *_callbackN; + uint8 _seqTextColorMap[16];*/ static const uint8 _rainbowRoomData[]; diff --git a/engines/kyra/kyra_lok.h b/engines/kyra/kyra_lok.h index e5fb3cddca..71177f59e8 100644 --- a/engines/kyra/kyra_lok.h +++ b/engines/kyra/kyra_lok.h @@ -134,6 +134,8 @@ public: const uint8 * const *palTable1() { return &_specialPalettes[0]; } const uint8 * const *palTable2() { return &_specialPalettes[29]; } + const AudioDataStruct *soundData(int index) { return &_soundData[index]; } + protected: virtual Common::Error go(); virtual Common::Error init(); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 2672618c67..f6fc4c3234 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -172,19 +172,6 @@ Common::Error KyraEngine_v1::init() { assert(_res); _res->reset(); - if (_flags.isDemo) { - // HACK: check whether this is the HOF demo or the LOL demo. - // The LOL demo needs to be detected and run as KyraEngine_HoF, - // but the static resource loader and the sequence player will - // need correct IDs. - if (_res->exists("scene1.cps")) -#ifdef ENABLE_LOL - _flags.gameID = GI_LOL; -#else - error("Lands of Lore demo is not supported in this build"); -#endif // !ENABLE_LOL - } - _staticres = new StaticResource(this); assert(_staticres); if (!_staticres->init()) diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 0033969047..c83f0a6eb7 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -242,6 +242,8 @@ public: virtual bool snd_voiceIsPlaying(); virtual void snd_stopVoice(); + virtual const AudioDataStruct *soundData(int index) { return 0; } + // delay functionallity virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index d3028c5e2d..ed7fe52446 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -499,6 +499,11 @@ void LoLEngine::initKeymap() { #endif } +void LoLEngine::pauseEngineIntern(bool pause) { + KyraEngine_v1::pauseEngineIntern(pause); + pauseDemoPlayer(pause); +} + Common::Error LoLEngine::go() { int action = -1; @@ -2361,7 +2366,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { playSpellAnimation(0, 0, 0, 2, 0, 0, 0, s.getData(), tpal.getData(), 40, false); - _screen->fadePaletteStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); + _screen->timedPaletteFadeStep(s.getData(), tpal.getData(), _system->getMillis(), _tickLength); if (mov->opened()) { int r = true; if (spellLevel > 2) { @@ -2430,7 +2435,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { playSpellAnimation(0, 0, 0, 2, 0, 0, 0, tpal.getData(), swampCol.getData(), 40, 0); - _screen->fadePaletteStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); + _screen->timedPaletteFadeStep(tpal.getData(), swampCol.getData(), _system->getMillis(), _tickLength); if (breakWall) breakIceWall(tpal.getData(), swampCol.getData()); @@ -2886,7 +2891,7 @@ int LoLEngine::processMagicVaelansCube() { uint32 endTime = _system->getMillis() + 70 * _tickLength; while (_system->getMillis() < endTime) { - _screen->fadePaletteStep(tmpPal1, tmpPal2, _system->getMillis() - ctime, 70 * _tickLength); + _screen->timedPaletteFadeStep(tmpPal1, tmpPal2, _system->getMillis() - ctime, 70 * _tickLength); updateInput(); } @@ -2915,7 +2920,7 @@ int LoLEngine::processMagicVaelansCube() { endTime = _system->getMillis() + 70 * _tickLength; while (_system->getMillis() < endTime) { - _screen->fadePaletteStep(tmpPal2, tmpPal1, _system->getMillis() - ctime, 70 * _tickLength); + _screen->timedPaletteFadeStep(tmpPal2, tmpPal1, _system->getMillis() - ctime, 70 * _tickLength); updateInput(); } @@ -3244,7 +3249,7 @@ void LoLEngine::playSpellAnimation(WSAMovie_v2 *mov, int firstFrame, int lastFra continue; } - if (!_screen->fadePaletteStep(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov) + if (!_screen->timedPaletteFadeStep(pal1, pal2, _system->getMillis() - startTime, _tickLength * fadeDelay) && !mov) return; if (del) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index dcd13804b3..06f9e32285 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -270,9 +270,13 @@ public: virtual void initKeymap(); + void pauseEngineIntern(bool pause); + Screen *screen(); GUI *gui() const; + const AudioDataStruct *soundData(int index) { return &_soundData[index]; } + private: Screen_LoL *_screen; GUI_LoL *_gui; @@ -400,6 +404,10 @@ private: static const int _outroMonsterScaleTableX[]; static const int _outroMonsterScaleTableY[]; + // Non-interactive demo + int playDemo(); + void pauseDemoPlayer(bool toggle); + // timers void setupTimers(); diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index f2bc4e8146..74ac1b6229 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -742,6 +742,8 @@ enum KyraResources { struct Shape; struct Room; struct AmigaSfxTable; +struct HoFSeqData; +struct HoFSeqItemAnimData; class StaticResource { public: @@ -760,8 +762,8 @@ public: const Shape *loadShapeTable(int id, int &entries); const AmigaSfxTable *loadAmigaSfxTable(int id, int &entries); const Room *loadRoomTable(int id, int &entries); - const HofSeqData *loadHofSequenceData(int id, int &entries); - const ItemAnimData_v1 *loadShapeAnimData_v1(int id, int &entries); + const HoFSeqData *loadHoFSequenceData(int id, int &entries); + const HoFSeqItemAnimData *loadHoFSeqItemAnimData(int id, int &entries); const ItemAnimDefinition *loadItemAnimDefinition(int id, int &entries); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) const uint16 *loadRawDataBe16(int id, int &entries); @@ -803,8 +805,8 @@ private: bool loadShapeTable(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadAmigaSfxTable(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadRoomTable(Common::SeekableReadStream &stream, void *&ptr, int &size); - bool loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size); - bool loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size); + bool loadHoFSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size); + bool loadHoFSeqItemAnimData(Common::SeekableReadStream &stream, void *&ptr, int &size); bool loadItemAnimDefinition(Common::SeekableReadStream &stream, void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) bool loadRawDataBe16(Common::SeekableReadStream &stream, void *&ptr, int &size); @@ -829,8 +831,8 @@ private: void freeShapeTable(void *&ptr, int &size); void freeAmigaSfxTable(void *&ptr, int &size); void freeRoomTable(void *&ptr, int &size); - void freeHofSequenceData(void *&ptr, int &size); - void freeHofShapeAnimDataV1(void *&ptr, int &size); + void freeHoFSequenceData(void *&ptr, int &size); + void freeHoFSeqItemAnimData(void *&ptr, int &size); void freeItemAnimDefinition(void *&ptr, int &size); #if defined(ENABLE_EOB) || defined(ENABLE_LOL) void freeRawDataBe16(void *&ptr, int &size); @@ -857,7 +859,7 @@ private: kAmigaSfxTable = 4, k2SeqData = 5, - k2ShpAnimDataV1 = 6, + k2SeqItemAnimData = 6, k2ItemAnimDefinition = 7, kLoLCharData = 8, diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 628654f127..d916348fb8 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -1183,11 +1183,11 @@ void LoLEngine::processGasExplosion(int soundId) { p2[i * 3] = 0x3f; uint32 ctime = _system->getMillis(); - while (_screen->fadePaletteStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) + while (_screen->timedPaletteFadeStep(_screen->getPalette(0).getData(), p2, _system->getMillis() - ctime, 10)) updateInput(); ctime = _system->getMillis(); - while (_screen->fadePaletteStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) + while (_screen->timedPaletteFadeStep(p2, _screen->getPalette(0).getData(), _system->getMillis() - ctime, 50)) updateInput(); } diff --git a/engines/kyra/screen_hof.cpp b/engines/kyra/screen_hof.cpp index ac6ee5eb77..7fdbdeb4db 100644 --- a/engines/kyra/screen_hof.cpp +++ b/engines/kyra/screen_hof.cpp @@ -93,12 +93,6 @@ void Screen_HoF::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int } } -void Screen_HoF::copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes) { - const uint8 *src = getPagePtr(srcPage) + srcPos; - uint8 *dst = getPagePtr(dstPage) + dstPos; - memcpy(dst, src, numBytes); -} - void Screen_HoF::copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX, int dstY, int dstW, int dstH, const ScreenDim *dim, bool flag) { int x0 = dim->sx << 3; int y0 = dim->sy; diff --git a/engines/kyra/screen_hof.h b/engines/kyra/screen_hof.h index 51c6a001fa..07fcd96844 100644 --- a/engines/kyra/screen_hof.h +++ b/engines/kyra/screen_hof.h @@ -37,7 +37,7 @@ public: // sequence player void generateGrayOverlay(const Palette &pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag); void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage); - void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); + void copyRegionEx(int srcPage, int srcW, int srcH, int dstPage, int dstX,int dstY, int dstW, int dstH, const ScreenDim *d, bool flag = false); private: KyraEngine_HoF *_vm; diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index 714a9d8b97..4e64f51269 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -808,34 +808,6 @@ bool Screen_LoL::fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedT return res; } -bool Screen_LoL::fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime) { - Palette &p1 = getPalette(1); - - bool res = false; - for (int i = 0; i < p1.getNumColors() * 3; i++) { - uint8 out = 0; - - if (elapsedTime < targetTime) { - int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f)); - if (d) - res = true; - - int32 val = ((((d << 8) / (int32)targetTime) * (int32)elapsedTime) >> 8); - out = ((pal1[i] & 0x3f) + (int8)val); - } else { - out = p1[i] = (pal2[i] & 0x3f); - res = false; - } - - (*_internFadePalette)[i] = out; - } - - setScreenPalette(*_internFadePalette); - updateScreen(); - - return res; -} - Palette **Screen_LoL::generateFadeTable(Palette **dst, Palette *src1, Palette *src2, int numTabs) { int len = _use16ColorMode ? 48 : 768; if (!src1) diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index 09496705bb..8ceb8431bc 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -65,7 +65,6 @@ public: void loadSpecialColors(Palette &dst); void copyColor(int dstColorIndex, int srcColorIndex); bool fadeColor(int dstColorIndex, int srcColorIndex, uint32 elapsedTicks, uint32 totalTicks); - bool fadePaletteStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 targetTime); Palette **generateFadeTable(Palette **dst, Palette *src1, Palette *src2, int numTabs); void generateGrayOverlay(const Palette &Pal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool skipSpecialColors); diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp index 7d4b064e2a..11314604e7 100644 --- a/engines/kyra/screen_v2.cpp +++ b/engines/kyra/screen_v2.cpp @@ -162,6 +162,34 @@ void Screen_v2::getFadeParams(const Palette &pal, int delay, int &delayInc, int } } +bool Screen_v2::timedPaletteFadeStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 totalTime) { + Palette &p1 = getPalette(1); + + bool res = false; + for (int i = 0; i < p1.getNumColors() * 3; i++) { + uint8 out = 0; + + if (elapsedTime < totalTime) { + int32 d = ((pal2[i] & 0x3f) - (pal1[i] & 0x3f)); + if (d) + res = true; + + int32 val = ((((d << 8) / (int32)totalTime) * (int32)elapsedTime) >> 8); + out = ((pal1[i] & 0x3f) + (int8)val); + } else { + out = p1[i] = (pal2[i] & 0x3f); + res = false; + } + + (*_internFadePalette)[i] = out; + } + + setScreenPalette(*_internFadePalette); + updateScreen(); + + return res; +} + const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { uint16 shapes = READ_LE_UINT16(shpFile); @@ -322,6 +350,12 @@ void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2, addDirtyRect(x2, y2, w2, h2); } +void Screen_v2::copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes) { + const uint8 *src = getPagePtr(srcPage) + srcPos; + uint8 *dst = getPagePtr(dstPage) + dstPos; + memcpy(dst, src, numBytes); +} + bool Screen_v2::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) { x2 = 0; y2 = 0; diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h index f84c923128..31c0b9f0b8 100644 --- a/engines/kyra/screen_v2.h +++ b/engines/kyra/screen_v2.h @@ -43,6 +43,8 @@ public: virtual void getFadeParams(const Palette &pal, int delay, int &delayInc, int &diff); + bool timedPaletteFadeStep(uint8 *pal1, uint8 *pal2, uint32 elapsedTime, uint32 totalTime); + // shape handling uint8 *getPtrToShape(uint8 *shpFile, int shape); const uint8 *getPtrToShape(const uint8 *shpFile, int shape); @@ -66,6 +68,9 @@ public: // special WSA handling void wsaFrameAnimationStep(int x1, int y1, int x2, int y2, int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim); + + // used in non-interactive HoF/LoL demos + void copyPageMemory(int srcPage, int srcPos, int dstPage, int dstPos, int numBytes); protected: uint8 *_wsaFrameAnimBuffer; }; diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index f2abfb81dc..26e2fd7934 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -21,2711 +21,3349 @@ */ #include "kyra/kyra_hof.h" -#include "kyra/timer.h" +#include "kyra/screen_hof.h" +#include "kyra/screen_lol.h" #include "kyra/resource.h" #include "kyra/sound.h" +#include "kyra/sequences_hof.h" +#include "kyra/timer.h" #include "common/system.h" namespace Kyra { -void KyraEngine_HoF::seq_playSequences(int startSeq, int endSeq) { - seq_init(); +enum SequenceID { + kSequenceNoLooping = -1, + kSequenceVirgin = 0, + kSequenceWestwood, + kSequenceTitle, + kSequenceOverview, + kSequenceLibrary, + kSequenceHand, + kSequencePoint, + kSequenceZanfaun, + + kSequenceFunters, + kSequenceFerb, + kSequenceFish, + kSequenceFheep, + kSequenceFarmer, + kSequenceFuards, + kSequenceFirates, + kSequenceFrash, + + kSequenceHoFDemoVirgin, + kSequenceHoFDemoWestwood, + kSequenceHoFDemoTitle, + kSequenceHoFDemoHill, + kSequenceHoFDemoOuthome, + kSequenceHoFDemoWharf, + kSequenceHoFDemoDinob, + kSequenceHoFDemoFisher, + +// The following enums remain active even if LoL is disabled + kSequenceLoLDemoScene1, + kSequenceLoLDemoText1, + kSequenceLoLDemoScene2, + kSequenceLoLDemoText2, + kSequenceLoLDemoScene3, + kSequenceLoLDemoText3, + kSequenceLoLDemoScene4, + kSequenceLoLDemoText4, + kSequenceLoLDemoScene5, + kSequenceLoLDemoText5, + kSequenceLoLDemoScene6, + + kSequenceArraySize +}; + +enum NestedSequenceID { + kNestedSequenceFiggle = 0, + + kNestedSequenceOver1, + kNestedSequenceOver2, + kNestedSequenceForest, + kNestedSequenceDragon, + kNestedSequenceDarm, + kNestedSequenceLibrary2, + kNestedSequenceLibrary3, + kNestedSequenceMarco, + kNestedSequenceHand1a, + kNestedSequenceHand1b, + kNestedSequenceHand1c, + kNestedSequenceHand2, + kNestedSequenceHand3, + kNestedSequenceHand4, + + kNestedSequenceHoFDemoWharf2, + kNestedSequenceHoFDemoDinob2, + kNestedSequenceHoFDemoWater, + kNestedSequenceHoFDemoBail, + kNestedSequenceHoFDemoDig, + + kNestedSequenceArraySize +}; + +typedef int (SeqPlayer_HOF::*SeqProc)(WSAMovie_v2 *, int, int, int); + +struct SeqPlayerConfig { + SeqPlayerConfig(const HoFSeqData *data, const SeqProc *callbacks, const SeqProc *nestedCallbacks) : seq(data->seq), seqProc(callbacks), numSeq(data->numSeq), nestedSeq(data->nestedSeq), nestedSeqProc(nestedCallbacks), numNestedSeq(data->numNestedSeq) {} + const HoFSequence *seq; + const SeqProc *seqProc; + int numSeq; + const HoFNestedSequence *nestedSeq; + const SeqProc *nestedSeqProc; + int numNestedSeq; +}; + +class SeqPlayer_HOF { +public: + SeqPlayer_HOF(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *system, bool startupSaveLoadable = false); + ~SeqPlayer_HOF(); + + int play(SequenceID firstScene, SequenceID loopStartScene); + void pause(bool toggle); + + static SeqPlayer_HOF *instance() { return _instance; } + +private: + // Init + void setupCallbacks(); + + // Playback loop + void runLoop(); + void playScenes(); + + bool checkAbortPlayback(); + bool checkPlaybackStatus(); + + bool _abortRequested; + + uint32 _seqWsaChatTimeout; + uint32 _seqWsaChatFrameTimeout; + + int _seqScrollTextCounter; + uint8 _seqTextColor[2]; + uint8 _seqTextColorMap[16]; + + // Sequence transitions + void doTransition(int type); + void nestedFrameAnimTransition(int srcPage, int dstPage, int delaytime, int steps, int x, int y, int w, int h, int openClose, int directionFlags); + void nestedFrameFadeTransition(const char *cmpFile); + + // Animations + void playAnimation(WSAMovie_v2 *wsaObj, int startFrame, int numFrames, int frameRate, int x, int y, const SeqProc callback, Palette *fadePal1, Palette *fadePal2, int fadeRate, bool restoreScreen); + + void startNestedAnimation(int animSlot, int sequenceID); + void closeNestedAnimation(int animSlot); + void unloadNestedAnimation(int animSlot); + void doNestedFrameTransition(int transitionType, int animSlot); + void updateAllNestedAnimations(); + bool updateNestedAnimation(int animSlot); + + struct AnimSlot { + SeqProc callback; + WSAMovie_v2 *movie; + const FrameControl *control; + int16 flags; + uint16 startFrame; + uint16 endFrame; + uint16 frameDelay; + uint32 nextFrame; + uint16 currentFrame; + uint16 lastFrame; + uint16 x; + uint16 y; + uint16 fadeInTransitionType; + uint16 fadeOutTransitionType; + }; - bool allowSkip = (_flags.isDemo && !_flags.isTalkie) || startSeq != kSequenceTitle; + AnimSlot _animSlots[8]; + + bool _updateAnimations; + uint32 _animDuration; + int _animCurrentFrame; + int _callbackCurrentFrame; + + // Subtitles/Dialogue/Sound + void seq_playTalkText(uint8 chatNum); + void seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovie_v2 * wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos); + void seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor); + int seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width); + + void seq_processText(); + char *seq_preprocessString(const char *str, int width); + + void waitForSubTitlesTimeout(); + uint32 ticksTillSubTitlesTimeout(); + void seq_resetAllTextEntries(); + void fadeOutMusic(); + + struct TextSlot { + uint16 strIndex; + uint16 x; + uint16 y; + uint16 width; + int32 duration; + uint32 startTime; + int16 textcolor; + }; - if (endSeq == -1) - endSeq = startSeq; + TextSlot _textSlots[10]; - assert(startSeq >= 0 && endSeq < kSequenceArraySize && startSeq <= endSeq); + char *_tempString; - _sound->setSoundList(&_soundData[(startSeq > kSequenceZanfaun) ? kMusicFinale : kMusicIntro]); - _sound->loadSoundFile(0); + const char * const *_sequenceStrings; + const char * const *_sequenceSoundList; + int _sequenceSoundListSize; - _screen->_charWidth = (_flags.gameID == GI_LOL) ? 0 : -2; + Audio::SoundHandle _speechHandle; - memset(_activeWSA, 0, sizeof(ActiveWSA) * 8); - for (int i = 0; i < 8; ++i) - _activeWSA[i].flags = -1; + int _textDuration[33]; + static const uint8 _textColorPresets[]; - memset(_activeText, 0, sizeof(ActiveText) * 10); - seq_resetAllTextEntries(); + // HOF credits + void seq_finaleActorScreen(); + void seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData = 0, const char *const *specialData = 0); - _screen->hideMouse(); - int oldPage = _screen->setCurPage(2); + bool _talkieFinaleExtraFlag; - for (int i = 0; i < 4; ++i) - _screen->getPalette(i).clear(); + // HOF demo specific + void seq_scrollPage(int bottom, int top); - _screen->clearPage(10); - _screen->clearPage(12); + ActiveItemAnim _hofDemoActiveItemAnim[5]; + uint32 _fisherAnimCurTime; - _seqSubframePlaying = false; + const HoFSeqItemAnimData *_hofDemoAnimData; + uint8 *_hofDemoShapeData; + uint8 *_hofDemoItemShapes[20]; - _seqWsaCurrentFrame = 0; - _seqTextColor[0] = _seqTextColor[1] = 0; - _seqEndTime = 0; - _menuChoice = 0; + // Misc + void delayTicks(uint32 ticks); + void delayUntil(uint32 dest); + void setCountDown(uint32 ticks); + bool countDownRunning(); - for (int seqNum = startSeq; seqNum <= endSeq && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) { - _screen->clearPage(0); - _screen->clearPage(8); - _screen->copyPalette(1, 0); - _seqFrameCounter = 0; - _seqStartTime = _system->getMillis(); + uint32 _countDownRemainder; + uint32 _countDownLastUpdate; - allowSkip = (_flags.isDemo && !_flags.isTalkie) || seqNum != kSequenceTitle; + enum SeqPlayerTargetInfo { + kHoF = 0, + kHoFDemo, + kLoLDemo + }; - Sequence cseq = _sequences->seq[seqNum]; - SeqProc cb = _callbackS[seqNum]; + SeqPlayerTargetInfo _target; + int _firstScene, _loopStartScene, _curScene, _preventSkipBeforeScene, _lastScene; + bool _startupSaveLoadable, _isFinale, _preventLooping; + + SeqPlayerConfig *_config; + + MainMenu *_menu; + int _result; + + bool _abortPlayback; + + KyraEngine_v1 *_vm; + Screen_v2 *_screen; + Screen_HoF *_screenHoF; + OSystem *_system; + + static SeqPlayer_HOF *_instance; + +private: + // Sequence specific callback functions + int cbHOF_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_title(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_overview(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_library(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_point(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_zanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_over1(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_over2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_forest(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_dragon(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_darm(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_library2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_marco(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_hand3(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_funters(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_ferb(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fish(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fheep(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_farmer(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_fuards(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_firates(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOF_frash(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOF_figgle(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOFDEMO_virgin(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_title(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_hill(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_outhome(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_wharf(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dinob(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_fisher(WSAMovie_v2 *wsaObj, int x, int y, int frm); + + int cbHOFDEMO_wharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_water(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_bail(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbHOFDEMO_dig(WSAMovie_v2 *wsaObj, int x, int y, int frm); - if (cseq.flags & 2) { - _screen->loadBitmap(cseq.cpsFile, 2, 2, &_screen->getPalette(0)); - _screen->setScreenPalette(_screen->getPalette(0)); - } else { - _screen->setCurPage(2); - _screen->clearPage(2); - _screen->loadPalette("goldfont.col", _screen->getPalette(0)); - } +#ifdef ENABLE_LOL + int cbLOLDEMO_scene1(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene2(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene3(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene4(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene5(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_text5(WSAMovie_v2 *wsaObj, int x, int y, int frm); + int cbLOLDEMO_scene6(WSAMovie_v2 *wsaObj, int x, int y, int frm); +#endif // ENABLE_LOL +}; + +SeqPlayer_HOF *SeqPlayer_HOF::_instance = 0; + +SeqPlayer_HOF::SeqPlayer_HOF(KyraEngine_v1 *vm, Screen_v2 *screen, OSystem *system, bool startupSaveLoadable) : _vm(vm), _screen(screen), _system(system), _startupSaveLoadable(startupSaveLoadable) { + // We use a static pointer for pauseEngine functionality. Since we don't + // ever need more than one SeqPlayer_HOF object at the same time we keep + // this simple and just add an assert to detect typos, regressions, etc. + assert(_instance == 0); + + memset(_animSlots, 0, sizeof(_animSlots)); + memset(_textSlots, 0, sizeof(_textSlots)); + memset(_hofDemoActiveItemAnim, 0, sizeof(_hofDemoActiveItemAnim)); + + _screenHoF = _vm->game() == GI_KYRA2 ? (Screen_HoF*)screen : 0; + _config = 0; + _result = 0; + _sequenceSoundList = 0; + _hofDemoAnimData = 0; + _hofDemoShapeData = 0; + _isFinale = false; + _preventLooping = false; + _menu = 0; + _abortRequested = false; - if (cb && !(_flags.isDemo && !_flags.isTalkie)) - (this->*cb)(0, 0, 0, -1); + _updateAnimations = false; + _animDuration = 0; + _animCurrentFrame = 0; + _callbackCurrentFrame = 0; - if (cseq.flags & 1) { - _seqWsa->close(); - _seqWsa->open(cseq.wsaFile, 0, &_screen->getPalette(0)); - _screen->setScreenPalette(_screen->getPalette(0)); - _seqWsa->displayFrame(0, 2, cseq.xPos, cseq.yPos, 0, 0, 0); - } + _abortPlayback = false; + _curScene = 0; + _preventSkipBeforeScene = -1; + _lastScene = 0; - if (cseq.flags & 4) { - int cp = _screen->setCurPage(2); - Screen::FontId cf = _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - if (cseq.stringIndex1 != -1) { - int sX = (320 - _screen->getTextWidth(_sequenceStrings[cseq.stringIndex1])) / 2; - _screen->printText(_sequenceStrings[cseq.stringIndex1], sX, 100 - _screen->getFontHeight(), 1, 0); - } - if (cseq.stringIndex2 != -1) { - int sX = (320 - _screen->getTextWidth(_sequenceStrings[cseq.stringIndex2])) / 2; - _screen->printText(_sequenceStrings[cseq.stringIndex2], sX, 100, 1, 0); - } - _screen->setFont(cf); - _screen->setCurPage(cp); - } + _fisherAnimCurTime = 0; - _screen->copyPage(2, 12); - _screen->copyPage(0, 2); - _screen->copyPage(2, 10); - _screen->copyPage(12, 2); + _tempString = new char[200]; - seq_sequenceCommand(cseq.startupCommand); + _countDownRemainder = 0; + _countDownLastUpdate = 0; - if (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _screen->copyPage(2, 0); - _screen->updateScreen(); - } + int tempSize = 0; + _vm->resource()->unloadAllPakFiles(); + _vm->resource()->loadPakFile(StaticResource::staticDataFilename()); + const char *const *files = _vm->staticres()->loadStrings(k2SeqplayPakFiles, tempSize); + _vm->resource()->loadFileList(files, tempSize); - if (cseq.flags & 1) { - int x = cseq.xPos; - int y = cseq.yPos; + _sequenceStrings = _vm->staticres()->loadStrings(k2SeqplayStrings, tempSize); + uint8 multiplier = (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) ? 12 : 8; + for (int i = 0; i < MIN(33, tempSize); i++) + _textDuration[i] = (int) strlen(_sequenceStrings[i]) * multiplier; + + if (_sequenceSoundList) { + for (int i = 0; i < _sequenceSoundListSize; i++) { + if (_sequenceSoundList[i]) + delete[] _sequenceSoundList[i]; + } + delete[] _sequenceSoundList; + _sequenceSoundList = 0; + } - _seqFrameDelay = cseq.frameDelay; + const char *const *seqSoundList = _vm->staticres()->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); - if (_seqWsa) { - if (x < 0) { - _seqWsa->setWidth(_seqWsa->width() + x); - x = 0; - } + // replace sequence talkie files with localized versions + const char *const *tlkfiles = _vm->staticres()->loadStrings(k2SeqplayTlkFiles, tempSize); + char **tmpSndLst = new char *[_sequenceSoundListSize]; - if (y < 0) { - _seqWsa->setHeight(_seqWsa->height() + y); - y = 0; - } + for (int i = 0; i < _sequenceSoundListSize; i++) { + const int len = strlen(seqSoundList[i]); - if (cseq.xPos + _seqWsa->width() > 319) - _seqWsa->setWidth(320 - cseq.xPos); + tmpSndLst[i] = new char[len + 1]; + tmpSndLst[i][0] = 0; - if (cseq.yPos + _seqWsa->height() > 199) - _seqWsa->setHeight(199 - cseq.yPos); + if (tlkfiles && len > 1) { + for (int ii = 0; ii < tempSize; ii++) { + if (strlen(tlkfiles[ii]) > 1 && !scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) + strcpy(tmpSndLst[i], tlkfiles[ii]); } - uint8 dir = (cseq.startFrame > cseq.numFrames) ? 0 : 1; - _seqWsaCurrentFrame = cseq.startFrame; + } - bool loop = true; - while (loop && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; + if (tmpSndLst[i][0] == 0) + strcpy(tmpSndLst[i], seqSoundList[i]); + } - if (_seqWsa || !cb) - _screen->copyPage(12, 2); + tlkfiles = seqSoundList = 0; + _vm->staticres()->unloadId(k2SeqplayTlkFiles); + _vm->staticres()->unloadId(k2SeqplaySfxFiles); + _sequenceSoundList = tmpSndLst; - if (cb) { - int f = _seqWsaCurrentFrame % _seqWsa->frames(); - (this->*cb)(_seqWsa, cseq.xPos, cseq.yPos, f); - } - if (_seqWsa) { - int f = _seqWsaCurrentFrame % _seqWsa->frames(); - _seqWsa->displayFrame(f, 2, cseq.xPos, cseq.yPos, 0, 0, 0); - } + if (_vm->gameFlags().platform == Common::kPlatformPC98) + _vm->sound()->loadSoundFile("SOUND.DAT"); - _screen->copyPage(2, 12); + _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - seq_processWSAs(); - seq_processText(); + if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) { + if (_vm->game() == GI_KYRA2) { + _hofDemoAnimData = _vm->staticres()->loadHoFSeqItemAnimData(k2SeqplayShapeAnimData, tempSize); + uint8 *shp = _vm->resource()->fileData("ICONS.SHP", 0); + uint32 outsize = READ_LE_UINT16(shp + 4); + _hofDemoShapeData = new uint8[outsize]; + Screen::decodeFrame4(shp + 10, _hofDemoShapeData, outsize); + for (int i = 0; i < 20; i++) + _hofDemoItemShapes[i] = _screen->getPtrToShape(_hofDemoShapeData, i); + delete[] shp; + } + } else { + const MainMenu::StaticData data = { + { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, + { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6 }, + { 0xd8, 0xda, 0xd9, 0xd8 }, + (_vm->gameFlags().lang == Common::JA_JPN) ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT, 240 + }; - if ((_seqWsa || !cb) && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _screen->copyPage(2, 0); - _screen->updateScreen(); - } + _menu = new MainMenu(_vm); + _menu->init(data, MainMenu::Animation()); + } - bool loop2 = true; - while (loop2 && !((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - if (_seqWsa) { - seq_processText(); - if (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _screen->copyPage(2, 0); - _screen->updateScreen(); - } + _instance = this; +} - uint32 now = _system->getMillis(); - if (now >= _seqEndTime) { - loop2 = false; - } else { - uint32 tdiff = _seqEndTime - now; - uint32 dly = tdiff < _tickLength ? tdiff : _tickLength; - delay(dly); - } - } else { - loop = loop2 = false; - } - } +SeqPlayer_HOF::~SeqPlayer_HOF() { + _instance = 0; - if (loop) { - if (dir == 1) { - if (++_seqWsaCurrentFrame >= cseq.numFrames) - loop = false; - } else { - if (--_seqWsaCurrentFrame < cseq.numFrames) - loop = false; - } - } - } - _seqWsa->close(); - } else { - _seqFrameDelay = cseq.frameDelay; - _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - while (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqSubFrameStartTime = _system->getMillis(); - seq_processWSAs(); - if (cb) - (this->*cb)(0, 0, 0, 0); + if (_sequenceSoundList) { + for (int i = 0; i < _sequenceSoundListSize; i++) { + if (_sequenceSoundList[i]) + delete[] _sequenceSoundList[i]; + } + delete[] _sequenceSoundList; + _sequenceSoundList = NULL; + } - seq_processText(); + delete[] _tempString; + delete[] _hofDemoShapeData; + delete _menu; - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->copyPage(12, 2); + _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); +} - uint32 now = _system->getMillis(); - if (now >= _seqEndTime && !_seqSubframePlaying) - break; +int SeqPlayer_HOF::play(SequenceID firstScene, SequenceID loopStartScene) { + bool incompatibleData = false; + MusicDataID soundSet = kMusicIntro; + _firstScene = firstScene; + _loopStartScene = loopStartScene; + _preventLooping = false; + _result = 0; - uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; - int32 dly = _tickLength - (now - _seqSubFrameStartTime); - if (dly > 0) - delay(MIN(dly, tdiff)); - else - updateInput(); - } + if (firstScene >= kSequenceArraySize || firstScene < kSequenceVirgin || loopStartScene >= kSequenceArraySize || loopStartScene < kSequenceNoLooping) { + return 0; + } else if (firstScene >= kSequenceLoLDemoScene1) { +#ifndef ENABLE_LOL + error("SeqPlayer_HOF::play(): The Lands of Lore sub engine (including this non-interactive demo) has been disabled in this build"); +#endif + incompatibleData = (_vm->game() != GI_LOL); + _firstScene -= kSequenceLoLDemoScene1; + if (loopStartScene != kSequenceNoLooping) + _loopStartScene -= kSequenceLoLDemoScene1; + _lastScene = kSequenceLoLDemoScene6 - kSequenceLoLDemoScene1; + _target = kLoLDemo; + _screen->_charWidth = 0; + } else if (firstScene >= kSequenceHoFDemoVirgin) { + incompatibleData = (_vm->game() != GI_KYRA2 || _vm->gameFlags().isDemo || _vm->gameFlags().isTalkie); + _firstScene -= kSequenceHoFDemoVirgin; + if (loopStartScene != kSequenceNoLooping) + _loopStartScene -= kSequenceHoFDemoVirgin; + _lastScene = kSequenceHoFDemoFisher - kSequenceHoFDemoVirgin; + _target = kHoFDemo; + _screen->_charWidth = -2; + } else { + _isFinale = _preventLooping = firstScene > kSequenceZanfaun; + incompatibleData = (_vm->game() != GI_KYRA2 || (_vm->gameFlags().isDemo && (!_vm->gameFlags().isTalkie || _isFinale))); + _target = kHoF; + _screen->_charWidth = -2; + if (_isFinale) { + soundSet = kMusicFinale; + _lastScene = kSequenceFrash; + } else { + _lastScene = kSequenceZanfaun; } + } - if (cb && !(_flags.isDemo && !_flags.isTalkie)) - (this->*cb)(0, 0, 0, -2); - - uint32 ct = seq_activeTextsTimeLeft(); - uint32 dl = cseq.duration * _tickLength; - if (dl < ct) - dl = ct; - _seqEndTime = _system->getMillis() + dl; - - while (!((skipFlag() && allowSkip) || shouldQuit() || (_abortIntroFlag && allowSkip) || _menuChoice)) { - _seqSubFrameStartTime = _system->getMillis(); - seq_processWSAs(); + if (incompatibleData) + error("SeqPlayer_HOF::play(): Requested sequences do not match the available sequence data for this target"); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->copyPage(12, 2); + _vm->sound()->setSoundList(_vm->soundData(soundSet)); + _vm->sound()->loadSoundFile(0); - uint32 now = _system->getMillis(); - if (now >= _seqEndTime && !_seqSubframePlaying) { - break; - } + setupCallbacks(); + runLoop(); - uint32 tdiff = _seqEndTime - _seqSubFrameStartTime; - int32 dly = _tickLength - (now - _seqSubFrameStartTime); - if (dly > 0) - delay(MIN(dly, tdiff)); - else - updateInput(); - } + return _result; +} - seq_sequenceCommand(cseq.finalCommand); - seq_resetAllTextEntries(); +void SeqPlayer_HOF::pause(bool toggle) { + if (toggle) { - if (_abortIntroFlag || skipFlag()) { - _sound->haltTrack(); - _sound->voiceStop(); - } - - if (!_flags.isDemo || _flags.isTalkie) { - if ((seqNum != kSequenceTitle && seqNum < kSequenceZanfaun && - (_abortIntroFlag || skipFlag())) || seqNum == kSequenceZanfaun) { - _abortIntroFlag = false; - _eventList.clear(); - seqNum = kSequenceWestwood; - } else if (seqNum < kSequenceFrash && (_abortIntroFlag || skipFlag())) { - _abortIntroFlag = false; - _eventList.clear(); - seqNum = kSequenceFirates; + } else { + // + // Timers in KyraEngine_HoF::nestedFrameFadeTransition() and KyraEngine_HoF::nestedFrameAnimTransition() + // have been left out for now. I think we don't need them here. + + /* _fisherAnimCurTime += pausedTime; + _seqSubFrameStartTime += pausedTime; + _seqEndTime += pausedTime; + _seqSubFrameEndTimeInternal += pausedTime; + _seqWsaChatTimeout += pausedTime; + _seqWsaChatFrameTimeout += pausedTime; + + if (_textSlots) { + for (int x = 0; x < 10; x++) { + if (_textSlots[x].duration != -1) + _textSlots[x].startTime += pausedTime; } - } else if (seqNum == endSeq && !(_abortIntroFlag || skipFlag())) { - seqNum = 0; } - if (_menuChoice) { - _abortIntroFlag = false; - _eventList.clear(); - - if (_menuChoice == 2) { - seqNum = kSequenceTitle; - _menuChoice = 0; + if (_animSlots) { + for (int x = 0; x < 8; x++) { + if (_animSlots[x].flags != -1) + _animSlots[x].nextFrame += pausedTime; } } - } - if (_flags.isDemo && !_flags.isTalkie) { - _eventList.clear(); - _screen->fadeToBlack(); + for (int x = 0; x < _itemAnimDefinitionSize; x++) + _activeItemAnim[x].nextFrameTime += pausedTime;*/ } +} - if (!_menuChoice) - delay(1200); - - _screen->setCurPage(oldPage); - _screen->showMouse(); +void SeqPlayer_HOF::setupCallbacks() { +#define SCB(x) &SeqPlayer_HOF::cbHOF_##x + static const SeqProc seqCallbacksHoF[] = { 0, SCB(westwood), SCB(title), SCB(overview), SCB(library), SCB(hand), SCB(point), SCB(zanfaun), SCB(funters), SCB(ferb), SCB(fish), SCB(fheep), SCB(farmer), SCB(fuards), SCB(firates), SCB(frash) }; + static const SeqProc nestedSeqCallbacksHoF[] = { SCB(figgle), SCB(over1), SCB(over2), SCB(forest), SCB(dragon), SCB(darm), SCB(library2), SCB(library2), SCB(marco), SCB(hand1a), SCB(hand1b), SCB(hand1c), SCB(hand2), SCB(hand3), 0 }; +#undef SCB +#define SCB(x) &SeqPlayer_HOF::cbHOFDEMO_##x + static const SeqProc seqCallbacksHoFDemo[] = { SCB(virgin), SCB(westwood), SCB(title), SCB(hill), SCB(outhome), SCB(wharf), SCB(dinob), SCB(fisher) }; + static const SeqProc nestedSeqCallbacksHoFDemo[] = { SCB(wharf2), SCB(dinob2), SCB(water), SCB(bail), SCB(dig), 0 }; +#undef SCB +#ifdef ENABLE_LOL +#define SCB(x) &SeqPlayer_HOF::cbLOLDEMO_##x + static const SeqProc seqCallbacksLoLDemo[] = { SCB(scene1), SCB(scene2), SCB(scene3), SCB(scene4), SCB(scene5), SCB(text5), SCB(scene6), 0 }; +#undef SCB +#else + static const SeqProc seqCallbacksLoLDemo[] = { 0 }; +#endif + static const SeqProc nestedSeqCallbacksLoLDemo[] = { 0 }; + + static const SeqProc *seqCallbacks[] = { seqCallbacksHoF, seqCallbacksHoFDemo, seqCallbacksLoLDemo}; + static const SeqProc *nestedSeqCallbacks[] = { nestedSeqCallbacksHoF, nestedSeqCallbacksHoFDemo, nestedSeqCallbacksLoLDemo}; + + int tmpSize = 0; + delete _config; + _config = new SeqPlayerConfig(_vm->staticres()->loadHoFSequenceData(k2SeqplaySeqData, tmpSize), seqCallbacks[_target], nestedSeqCallbacks[_target]); +} + +void SeqPlayer_HOF::runLoop() { + memset(_animSlots, 0, sizeof(_animSlots)); + memset(_textSlots, 0, sizeof(_textSlots)); + memset(_hofDemoActiveItemAnim, 0, sizeof(_hofDemoActiveItemAnim)); + for (int i = 0; i < 8; ++i) + _animSlots[i].flags = -1; - for (int i = 0; i < 8; i++) - seq_unloadWSA(i); + _screen->clearPage(10); + _screen->clearPage(12); + _screen->hideMouse(); + int oldPage = _screen->setCurPage(2); - _seqWsa->close(); + for (int i = 0; i < 4; ++i) + _screen->getPalette(i).clear(); - _screen->_charWidth = 0; + _updateAnimations = false; + _animCurrentFrame = 0; + _seqTextColor[0] = _seqTextColor[1] = 0; + _curScene = _firstScene; - seq_uninit(); -} + do { + playScenes(); + doTransition(0); + seq_resetAllTextEntries(); + fadeOutMusic(); + _firstScene = ((!_startupSaveLoadable || _preventLooping) && _curScene >= _loopStartScene) ? kSequenceNoLooping : _loopStartScene; + } while (!_vm->shouldQuit() && _firstScene != kSequenceNoLooping); -int KyraEngine_HoF::seq_introWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == -2) { - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - delay(300 * _tickLength); - } else if (!frm) { - _sound->playTrack(2); - } + checkPlaybackStatus(); - return 0; -} + for (int i = 0; i < 8; i++) + unloadNestedAnimation(i); -int KyraEngine_HoF::seq_introTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 1) { - _sound->playTrack(3); - } else if (frm == 25) { - int cp = _screen->setCurPage(0); - _screen->showMouse(); - _system->updateScreen(); - _menuChoice = _menu->handle(11) + 1; - _seqEndTime = 0; - _seqSubframePlaying = false; - if (_menuChoice == 4) - quitGame(); + if (_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie) + _screen->fadeToBlack(); - _screen->hideMouse(); - _screen->setCurPage(cp); - } + if (!_result) + delayTicks(75); - return 0; + _screen->setCurPage(oldPage); + _screen->_charWidth = 0; + _screen->showMouse(); } -int KyraEngine_HoF::seq_introOverview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101; - memset(tmpPal, 0, 256); - _seqSubFrameEndTimeInternal = 0; - uint32 now = 0; +void SeqPlayer_HOF::playScenes() { + _vm->sound()->stopAllSoundEffects(); + _curScene = _firstScene; - switch (_seqFrameCounter) { - case 0: - _seqSubframePlaying = true; - _sound->playTrack(4); - _seqSubFrameEndTimeInternal = _system->getMillis() + 60 * _tickLength; + _screen->copyPalette(1, 0); + WSAMovie_v2 anim(_vm); + _abortRequested = false; - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + while (!_vm->shouldQuit()) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; - _screen->setTextColorMap(_seqTextColorMap); + _callbackCurrentFrame = 0; - now = _system->getMillis(); - if (_seqSubFrameEndTimeInternal > now) - delay(_seqSubFrameEndTimeInternal - now); - break; + if (_curScene > _lastScene) + break; - case 1: - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); - for (int i = 0; i < 256; i++) - tmpPal[_screen->getPalette(3)[i]] = 1; + const Kyra::HoFSequence &sq = _config->seq[_curScene]; - for (int i = 0; i < 256; i++) { - int v = (tmpPal[i] == 1) ? i : _screen->getPalette(3)[i]; - v *= 3; - _screen->getPalette(2)[3 * i] = _screen->getPalette(0)[v]; - _screen->getPalette(2)[3 * i + 1] = _screen->getPalette(0)[v + 1]; - _screen->getPalette(2)[3 * i + 2] = _screen->getPalette(0)[v + 2]; + if (sq.flags & 2) { + _screen->loadBitmap(sq.cpsFile, 2, 2, &_screen->getPalette(0)); + _screen->setScreenPalette(_screen->getPalette(0)); + } else { + _screen->setCurPage(2); + _screen->clearPage(2); + _screen->loadPalette("GOLDFONT.COL", _screen->getPalette(0)); } - break; - case 40: - seq_loadNestedSequence(0, kSequenceOver1); - break; + if (_config->seqProc[_curScene] && !(_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)) + (this->*_config->seqProc[_curScene])(0, 0, 0, -1); - case 60: - seq_loadNestedSequence(1, kSequenceOver2); - break; + if (sq.flags & 1) { + anim.open(sq.wsaFile, 0, &_screen->getPalette(0)); + if (!(sq.flags & 2)) + anim.displayFrame(0, 2, sq.xPos, sq.yPos, 0x4000, 0, 0); + } - case 120: - seq_playTalkText(0); - break; + if (sq.flags & 4) { + int cp = _screen->setCurPage(2); + Screen::FontId cf = _screen->setFont(_vm->gameFlags().lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - case 200: - seq_waitForTextsTimeout(); - _screen->fadePalette(_screen->getPalette(2), 64); - break; + if (sq.stringIndex1 != -1) + _screen->printText(_sequenceStrings[sq.stringIndex1], (320 - _screen->getTextWidth(_sequenceStrings[sq.stringIndex1])) / 2, 100 - _screen->getFontHeight(), 1, 0); - case 201: - _screen->setScreenPalette(_screen->getPalette(2)); - _screen->updateScreen(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); - _screen->copyPage(2, 12); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->setScreenPalette(_screen->getPalette(0)); - _screen->updateScreen(); - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); - break; + if (sq.stringIndex2 != -1) + _screen->printText(_sequenceStrings[sq.stringIndex2], (320 - _screen->getTextWidth(_sequenceStrings[sq.stringIndex2])) / 2, 100, 1, 0); - case 282: - seq_loadNestedSequence(0, kSequenceForest); - seq_playTalkText(1); - break; + _screen->setFont(cf); + _screen->setCurPage(cp); + } - case 354: - case 434: - if (!((_seqFrameCounter == 354 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 434 && _flags.platform == Common::kPlatformPC))) - break; + _screen->copyPage(2, 12); + _screen->copyPage(0, 2); + _screen->copyPage(2, 10); + _screen->copyPage(12, 2); - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceDragon); - break; + doTransition(sq.fadeInTransitionType); - case 400: - case 540: - if (!((_seqFrameCounter == 400 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 540 && _flags.platform == Common::kPlatformPC))) - break; + if (!(checkAbortPlayback() || _vm->shouldQuit() || _result)) { + _screen->copyPage(2, 0); + _screen->updateScreen(); + } - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; - break; + //_screen->copyPage(2, 6); - default: - break; - } + if (sq.flags & 1) { + playAnimation(&anim, sq.startFrame, sq.numFrames, sq.duration, sq.xPos, sq.yPos, _config->seqProc[_curScene], &_screen->getPalette(1), &_screen->getPalette(0), 30, 0); + anim.close(); + } else { + _animDuration = sq.duration; + setCountDown(_animDuration); + + while (!checkAbortPlayback() && !_vm->shouldQuit() && (countDownRunning() || _updateAnimations)) { + uint32 endFrame = (_system->getMillis() + _vm->tickLength()) & ~(_vm->tickLength() - 1); + updateAllNestedAnimations(); + // Due to bugged coding / sequence data in the FM-Towns and PC-98 versions these animations will only play correctly on slow hardware. + // If the hardware is too fast the animations will not finish. This bug was probably irrelevant for original FM-Towns or PC-98 machines. + // We compensate this with a small extra delay. + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + delayTicks(1); + + if (_config->seqProc[_curScene]) + (this->*_config->seqProc[_curScene])(0, 0, 0, 0); - _seqFrameCounter++; - return 0; -} + seq_processText(); -int KyraEngine_HoF::seq_introLibrary(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { - case 0: - _seqSubframePlaying = true; - _sound->playTrack(5); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->copyPage(12, 2); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + // See comment above. + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + delayTicks(1); - _screen->setTextColorMap(_seqTextColorMap); - break; + do { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; + } while (_system->getMillis() < endFrame); + } + } - case 1: - seq_loadNestedSequence(0, kSequenceLibrary3); - seq_playTalkText(4); - break; + if (_config->seqProc[_curScene] && !(_vm->gameFlags().isDemo && !_vm->gameFlags().isTalkie)) + (this->*_config->seqProc[_curScene])(0, 0, 0, -2); - case 100: - seq_waitForTextsTimeout(); + uint32 textTimeOut = ticksTillSubTitlesTimeout(); + setCountDown(sq.timeout < textTimeOut ? textTimeOut : sq.timeout); - _screen->copyPage(12, 2); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - _screen->copyPage(2, 12); + while (!checkAbortPlayback() && !_vm->shouldQuit() && (countDownRunning() || _updateAnimations)) { + updateAllNestedAnimations(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->copyPage(12, 2); + } - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceDarm); - break; + doTransition(sq.fadeOutTransitionType); + _curScene++; + } - case 104: - seq_playTalkText(5); - break; + if (checkAbortPlayback() || _vm->shouldQuit()) { + seq_resetAllTextEntries(); + _vm->sound()->haltTrack(); + _vm->sound()->voiceStop(); + } +} - case 240: - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - seq_loadNestedSequence(0, kSequenceLibrary2); - break; +bool SeqPlayer_HOF::checkAbortPlayback() { + Common::Event event; - case 340: - seq_resetActiveWSA(0); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); - _screen->copyPage(2, 12); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); + if (_abortRequested) + return true; - seq_loadNestedSequence(0, kSequenceMarco); - seq_playTalkText(6); - break; + while (_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_q && event.kbd.hasFlags(Common::KBD_CTRL)) { + _abortRequested = true; + _vm->quitGame(); + return true; + } else if (event.kbd.keycode != Common::KEYCODE_ESCAPE && event.kbd.keycode != Common::KEYCODE_RETURN && event.kbd.keycode != Common::KEYCODE_SPACE) + continue; + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _abortRequested = true; + return true; + } + } - case 480: - case 660: - if (!((_seqFrameCounter == 480 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 660 && _flags.platform == Common::kPlatformPC))) - break; + return false; +} - _screen->copyPage(2, 12); - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; - break; +bool SeqPlayer_HOF::checkPlaybackStatus() { + _updateAnimations = false; - default: - break; + if (_curScene <= _preventSkipBeforeScene || _curScene == _loopStartScene) { + _abortRequested = false; + return false; } - _seqFrameCounter++; - return 0; + if (_loopStartScene == kSequenceNoLooping) { + doTransition(0); + fadeOutMusic(); + _abortPlayback = true; + } else { + return true; + } + + return false; } +void SeqPlayer_HOF::doTransition(int type) { + for (int i = 0; i < 8; i++) + closeNestedAnimation(i); -int KyraEngine_HoF::seq_introHand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { + switch (type) { case 0: - _seqSubframePlaying = true; - _sound->playTrack(6); - - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - - _screen->setTextColorMap(_seqTextColorMap); + _screen->fadeToBlack(36); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); break; case 1: - seq_loadNestedSequence(0, kSequenceHand1a); - seq_loadNestedSequence(1, kSequenceHand1b); - seq_loadNestedSequence(2, kSequenceHand1c); - seq_playTalkText(7); + seq_playTalkText(_vm->_rnd.getRandomBit()); + + _screen->getPalette(0).fill(0, 256, 0x3F); + _screen->fadePalette(_screen->getPalette(0), 16); + + _screen->copyPalette(1, 0); break; - case 201: - seq_waitForTextsTimeout(); - _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); - _screen->copyPage(2, 12); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); - seq_resetActiveWSA(2); - seq_loadNestedSequence(0, kSequenceHand2); - seq_playTalkText(8); + case 3: + _screen->copyPage(2, 0); + _screen->fadePalette(_screen->getPalette(0), 16); + _screen->copyPalette(1, 0); break; - case 260: - case 395: - if (!((_seqFrameCounter == 260 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 395 && _flags.platform == Common::kPlatformPC))) - break; + case 4: + _screen->copyPage(2, 0); + _screen->fadePalette(_screen->getPalette(0), 36); + _screen->copyPalette(1, 0); + break; - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - seq_loadNestedSequence(1, kSequenceHand3); - seq_playTalkText(9); + case 5: + _screen->copyPage(2, 0); break; - case 365: - case 500: - if (!((_seqFrameCounter == 365 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 500 && _flags.platform == Common::kPlatformPC))) - break; + case 6: + // UNUSED + // seq_loadBLD("library.bld"); + break; - seq_waitForTextsTimeout(); - seq_resetActiveWSA(1); - seq_loadNestedSequence(0, kSequenceHand4); + case 7: + // UNUSED + // seq_loadBLD("marco.bld"); break; - case 405: - case 540: - if (!((_seqFrameCounter == 405 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 540 && _flags.platform == Common::kPlatformPC))) - break; + case 8: + _screen->fadeToBlack(16); + _screen->getPalette(0).clear(); + _screen->getPalette(1).clear(); - seq_playTalkText(10); + delayTicks(120); break; - case 484: - case 630: - if (!((_seqFrameCounter == 484 && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) || (_seqFrameCounter == 630 && _flags.platform == Common::kPlatformPC))) - break; + case 9: { + Palette &pal = _screen->getPalette(0); + for (int i = 0; i < 256; i++) { + int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3; + pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff; + } - seq_waitForTextsTimeout(); - seq_resetActiveWSA(0); - _seqEndTime = 0; - _seqSubframePlaying = false; - break; + //int a = 0x100; + //int d = (0x800 << 5) - 0x100; + //pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f; + + _screen->fadePalette(pal, 64); + _screen->copyPalette(1, 0); + } break; default: break; } - - _seqFrameCounter++; - return 0; } -int KyraEngine_HoF::seq_introPoint(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == -2) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; - } +void SeqPlayer_HOF::nestedFrameAnimTransition(int srcPage, int dstPage, int delaytime, int steps, int x, int y, int w, int h, int openClose, int directionFlags) { + if (openClose) { + for (int i = 1; i < steps; i++) { + uint32 endtime = _system->getMillis() + delaytime * _vm->tickLength(); - switch (_seqFrameCounter) { - case -2: - seq_waitForTextsTimeout(); - break; + int w2 = (((w * 256) / steps) * i) / 256; + int h2 = (((h * 256) / steps) * i) / 256; - case 0: - _sound->playTrack(7); + int ym = (directionFlags & 2) ? (h - h2) : 0; + int xm = (directionFlags & 1) ? (w - w2) : 0; - _seqTextColor[1] = 0xf7; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - _screen->setTextColorMap(_seqTextColorMap); - _screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); - break; + _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); - case 1: - seq_playTalkText(11); - break; + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); - default: - break; - } + _screen->copyPage(12, dstPage); + delayUntil(endtime); + } - _seqFrameCounter++; - return 0; + _screen->wsaFrameAnimationStep(0, 0, x, y, w, h, w, h, srcPage, dstPage, 0); + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); + } else { + _screen->copyPage(12, dstPage); + for (int i = steps; i; i--) { + uint32 endtime = _system->getMillis() + delaytime * _vm->tickLength(); + + int w2 = (((w * 256) / steps) * i) / 256; + int h2 = (((h * 256) / steps) * i) / 256; + + int ym = (directionFlags & 2) ? (h - h2) : 0; + int xm = (directionFlags & 1) ? (w - w2) : 0; + + _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); + + _screen->copyPage(dstPage, 6); + _screen->copyPage(dstPage, 0); + _screen->updateScreen(); + + _screen->copyPage(12, dstPage); + delayUntil(endtime); + } + } } -int KyraEngine_HoF::seq_introZanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == -2) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; - return 0; +void SeqPlayer_HOF::nestedFrameFadeTransition(const char *cmpFile) { + _screen->copyPage(10, 2); + _screen->copyPage(4, 10); + _screen->clearPage(6); + _screen->loadBitmap(cmpFile, 6, 6, 0); + _screen->copyPage(12, 4); + + for (int i = 0; i < 3; i++) { + uint32 endtime = _system->getMillis() + 4 * _vm->tickLength(); + assert(_screenHoF); + _screenHoF->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + delayUntil(endtime); } - switch (_seqFrameCounter) { - case 0: - _sound->playTrack(8); + _screen->copyPage(4, 0); + _screen->updateScreen(); + _screen->copyPage(4, 2); + _screen->copyPage(4, 6); + _screen->copyPage(10, 4); +} - _seqTextColor[1] = 0xfd; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - _screen->setTextColorMap(_seqTextColorMap); - break; +void SeqPlayer_HOF::playAnimation(WSAMovie_v2 *wsaObj, int startFrame, int lastFrame, int frameRate, int x, int y, const SeqProc callback, Palette *fadePal1, Palette *fadePal2, int fadeRate, bool restoreScreen) { + bool finished = false; + uint32 startTime = _system->getMillis(); - case 1: - if (_flags.isTalkie) { - seq_playWsaSyncDialogue(21, 13, -1, 140, 70, 160, wsaObj, 0, 8, x, y); - } else { - seq_setTextEntry(21, 140, 70, 200, 160); - _seqFrameDelay = 200; - } - break; + int origW = wsaObj->width(); + int origH = wsaObj->width(); + int drwX = x; + int drwY = y; + int drwW = origW; + int drwH = origH; - case 2: - case 11: - case 21: - if (!_flags.isTalkie) - _seqFrameDelay = 12; - break; + _animDuration = frameRate; - case 9: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(13, 14, -1, 140, (_flags.lang == Common::FR_FRA - || _flags.lang == Common::DE_DEU) ? 50 : 70, 160, wsaObj, 9, 15, x, y); - break; + if (wsaObj) { + if (x < 0) { + drwW += x; + drwX = 0; + } - case 10: - if (!_flags.isTalkie) { - seq_waitForTextsTimeout(); - seq_setTextEntry(13, 140, 50, _sequenceStringsDuration[13], 160); - _seqFrameDelay = 300; + if (y < 0) { + drwH += y; + drwY = 0; } - break; - case 16: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(18, 15, -1, 140, (_flags.lang == Common::FR_FRA) ? 50 : - (_flags.lang == Common::DE_DEU ? 40 : 70), 160, wsaObj, 10, 16, x, y); - break; + if (x + origW > 319) + origW = 320 - x; - case 17: - if (_flags.isTalkie) - _seqFrameDelay = 12; - break; + if (y + origH > 199) + origW = 200 - y; + } - case 20: - if (!_flags.isTalkie) { - seq_waitForTextsTimeout(); - seq_setTextEntry(18, 160, 50, _sequenceStringsDuration[18], 160); - _seqFrameDelay = 200; - } - break; + int8 frameStep = (startFrame > lastFrame) ? -1 : 1; + _animCurrentFrame = startFrame; - case 26: - seq_waitForTextsTimeout(); - break; + while (!_vm->shouldQuit() && !finished) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; - case 46: - if (_flags.isTalkie) { - seq_playWsaSyncDialogue(16, 16, -1, 200, 50, 120, wsaObj, 46, 46, x, y); - } else { - seq_waitForTextsTimeout(); - seq_setTextEntry(16, 200, 50, _sequenceStringsDuration[16], 120); + setCountDown(_animDuration); + + if (wsaObj || callback) + _screen->copyPage(12, 2); + + int frameIndex = _animCurrentFrame; + if (wsaObj) + frameIndex %= wsaObj->frames(); + + if (callback) + (this->*callback)(wsaObj, x, y, frameIndex); + + if (wsaObj) + wsaObj->displayFrame(frameIndex, 2, x, y, 0, 0, 0); + + _screen->copyPage(2, 12); + + updateAllNestedAnimations(); + seq_processText(); + + if (wsaObj || callback && (!(checkAbortPlayback() || _vm->shouldQuit() || _result))) { + _screen->copyPage(2, 0); + _screen->updateScreen(); } - _seqEndTime = _system->getMillis() + 120 * _tickLength; - break; + while (!_vm->shouldQuit()) { + if (checkAbortPlayback()) + if (checkPlaybackStatus()) + break; - default: - break; - } + if (fadePal1 && fadePal2) { + if (!_screen->timedPaletteFadeStep(fadePal1->getData(), fadePal2->getData(), _system->getMillis() - startTime, fadeRate * _vm->tickLength()) && !wsaObj) + break; + } - _seqFrameCounter++; - return 0; -} + if (wsaObj || callback && (!(checkAbortPlayback() || _vm->shouldQuit() || _result))) { + _screen->copyPage(2, 0); + _screen->updateScreen(); + } -int KyraEngine_HoF::seq_introOver1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 2) - seq_waitForTextsTimeout(); - else if (frm == 3) - seq_playTalkText(12); - return frm; -} + seq_processText(); + if (!countDownRunning()) + break; + } -int KyraEngine_HoF::seq_introOver2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 1) - seq_playTalkText(12); - return frm; + if (wsaObj) { + _animCurrentFrame += frameStep; + if (_animCurrentFrame == lastFrame) + finished = true; + } + + if (restoreScreen && (wsaObj || callback)) { + _screen->copyPage(12, 2); + _screen->copyRegion(drwX, drwY, drwX, drwY, drwW, drwH, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + } + } } -int KyraEngine_HoF::seq_introForest(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 11) - seq_waitForTextsTimeout(); - else if (frm == 12) - seq_playTalkText(2); +void SeqPlayer_HOF::startNestedAnimation(int animSlot, int sequenceID) { + if (_animSlots[animSlot].flags != -1) + return; - return frm; -} + HoFNestedSequence s = _config->nestedSeq[sequenceID]; -int KyraEngine_HoF::seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 11) - seq_waitForTextsTimeout(); - else if (frm == 3) - seq_playTalkText(3); - return frm; -} + if (!_animSlots[animSlot].movie) { + _animSlots[animSlot].movie = new WSAMovie_v2(_vm); + assert(_animSlots[animSlot].movie); + } -int KyraEngine_HoF::seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) - return frm; -} + _animSlots[animSlot].movie->close(); -int KyraEngine_HoF::seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) - return frm; -} + _animSlots[animSlot].movie->open(s.wsaFile, 0, 0); -int KyraEngine_HoF::seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 36) { - seq_waitForTextsTimeout(); - _seqEndTime = 0; + if (!_animSlots[animSlot].movie->opened()) { + delete _animSlots[animSlot].movie; + _animSlots[animSlot].movie = 0; + return; } - return frm; -} -int KyraEngine_HoF::seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) - return frm; -} + _animSlots[animSlot].endFrame = s.endFrame; + _animSlots[animSlot].startFrame = _animSlots[animSlot].currentFrame = s.startframe; + _animSlots[animSlot].frameDelay = s.frameDelay; + _animSlots[animSlot].callback = _config->nestedSeqProc[sequenceID]; + _animSlots[animSlot].control = s.wsaControl; -int KyraEngine_HoF::seq_introHand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 15) - frm = 12; - return frm; -} + _animSlots[animSlot].flags = s.flags | 1; + _animSlots[animSlot].x = s.x; + _animSlots[animSlot].y = s.y; + _animSlots[animSlot].fadeInTransitionType = s.fadeInTransitionType; + _animSlots[animSlot].fadeOutTransitionType = s.fadeOutTransitionType; + _animSlots[animSlot].lastFrame = 0xffff; -int KyraEngine_HoF::seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 8) - frm = 4; - return frm; + doNestedFrameTransition(s.fadeInTransitionType, animSlot); + + if (!s.fadeInTransitionType) + updateNestedAnimation(animSlot); + + _animSlots[animSlot].nextFrame = _system->getMillis() & ~(_vm->tickLength() - 1); } -int KyraEngine_HoF::seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) - return frm; +void SeqPlayer_HOF::closeNestedAnimation(int animSlot) { + if (_animSlots[animSlot].flags == -1) + return; + + _animSlots[animSlot].flags = -1; + doNestedFrameTransition(_animSlots[animSlot].fadeOutTransitionType, animSlot); + _animSlots[animSlot].movie->close(); } -int KyraEngine_HoF::seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in FM-TOWNS version) - return frm; +void SeqPlayer_HOF::unloadNestedAnimation(int animSlot) { + if (_animSlots[animSlot].movie) { + _animSlots[animSlot].movie->close(); + delete _animSlots[animSlot].movie; + _animSlots[animSlot].movie = 0; + } } -int KyraEngine_HoF::seq_finaleFunters(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; - uint16 voiceIndex = 0; +void SeqPlayer_HOF::doNestedFrameTransition(int transitionType, int animSlot) { + int xa = 0, ya = 0; + transitionType--; + if (!_animSlots[animSlot].movie || _abortPlayback || _vm->shouldQuit()) + return; - switch (frm) { - case -2: - seq_sequenceCommand(9); + switch (transitionType) { + case 0: + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 1, 2); break; - case 0: - _sound->playTrack(3); + case 1: + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 1, 1); + break; - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); + case 2: + waitForSubTitlesTimeout(); + xa = -_animSlots[animSlot].movie->xAdd(); + ya = -_animSlots[animSlot].movie->yAdd(); + _animSlots[animSlot].movie->displayFrame(21, 8, xa, ya, 0, 0, 0); + nestedFrameAnimTransition(8, 2, 7, 8, _animSlots[animSlot].movie->xAdd(), _animSlots[animSlot].movie->yAdd(), + _animSlots[animSlot].movie->width(), _animSlots[animSlot].movie->height(), 0, 2); + break; - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(81, 240, 70, _seqTextColorMap, 252); - seq_printCreditsString(82, 240, 90, _seqTextColorMap, _seqTextColor[0]); + case 3: + _screen->copyPage(2, 10); + _animSlots[animSlot].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 12); - seq_playTalkText(_flags.isTalkie ? 28 : 24); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqTextColor[0] = 1; + nestedFrameFadeTransition("scene2.cmp"); + break; - if (_flags.isTalkie) { - chatY = (_flags.lang == Common::FR_FRA) ? 70 : 78; - chatFirstFrame = 9; - chatLastFrame = 15; - voiceIndex = 34; - } else { - chatY = (_flags.lang == Common::FR_FRA) ? 78 : 70; - chatFirstFrame = 0; - chatLastFrame = 8; - } - chatX = (_flags.lang == Common::FR_FRA) ? 84 : 88; - chatW = 100; + case 4: + _screen->copyPage(2, 10); + _animSlots[animSlot].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); + _screen->copyPage(2, 12); + nestedFrameFadeTransition("scene3.cmp"); + break; - seq_playWsaSyncDialogue(22, voiceIndex, 187, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + default: break; + } +} - case 9: - case 16: - if (!((frm == 9 && !_flags.isTalkie) || (frm == 16 && _flags.isTalkie))) - break; +void SeqPlayer_HOF::updateAllNestedAnimations() { + for (int i = 0; i < 8; i++) { + if (_animSlots[i].flags != -1) { + if (updateNestedAnimation(i)) + closeNestedAnimation(i); + } + } +} - _seqFrameDelay = 12; +bool SeqPlayer_HOF::updateNestedAnimation(int animSlot) { + uint16 currentFrame = _animSlots[animSlot].currentFrame; + uint32 curTick = _system->getMillis() & ~(_vm->tickLength() - 1); + + if (_animSlots[animSlot].callback && currentFrame != _animSlots[animSlot].lastFrame) { + _animSlots[animSlot].lastFrame = currentFrame; + currentFrame = (this->*_animSlots[animSlot].callback)(_animSlots[animSlot].movie, _animSlots[animSlot].x, _animSlots[animSlot].y, currentFrame); + } - if (_flags.lang == Common::FR_FRA) { - chatX = 80; - chatW = 112; + if (_animSlots[animSlot].movie) { + if (_animSlots[animSlot].flags & 0x20) { + _animSlots[animSlot].movie->displayFrame(_animSlots[animSlot].control[currentFrame].index, 2, _animSlots[animSlot].x, _animSlots[animSlot].y, 0x4000, 0, 0); + _animSlots[animSlot].frameDelay = _animSlots[animSlot].control[currentFrame].delay; } else { - chatX = (_flags.lang == Common::DE_DEU) ? 84 : 96; - chatW = 100; + _animSlots[animSlot].movie->displayFrame(currentFrame % _animSlots[animSlot].movie->frames(), 2, _animSlots[animSlot].x, _animSlots[animSlot].y, 0x4000, 0, 0); } + } - if (_flags.isTalkie) { - chatFirstFrame = 0; - chatLastFrame = 8; - voiceIndex = 35; - } else { - chatFirstFrame = 9; - chatLastFrame = 15; + if (_animSlots[animSlot].flags & 0x10) { + currentFrame = (curTick - _animSlots[animSlot].nextFrame) / (_animSlots[animSlot].frameDelay * _vm->tickLength()); + } else { + int diff = (curTick - _animSlots[animSlot].nextFrame) / (_animSlots[animSlot].frameDelay * _vm->tickLength()); + if (diff > 0) { + currentFrame++; + _animSlots[animSlot].nextFrame = curTick; } - chatY = 70; + } - seq_playWsaSyncDialogue(23, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 17; - break; + bool res = false; - default: - break; + if (currentFrame >= _animSlots[animSlot].endFrame) { + int sw = ((_animSlots[animSlot].flags & 0x1e) - 2); + switch (sw) { + case 0: + res = true; + currentFrame = _animSlots[animSlot].endFrame; + _screen->copyPage(2, 12); + break; + + case 6: + case 8: + currentFrame = _animSlots[animSlot].endFrame - 1; + break; + + case 2: + case 10: + currentFrame = _animSlots[animSlot].startFrame; + break; + + default: + currentFrame = _animSlots[animSlot].endFrame - 1; + res = true; + } } - _seqFrameCounter++; - return 0; + _animSlots[animSlot].currentFrame = currentFrame; + return res; } -int KyraEngine_HoF::seq_finaleFerb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; - uint16 voiceIndex = 0; +void SeqPlayer_HOF::seq_playTalkText(uint8 chatNum) { + assert(chatNum < _sequenceSoundListSize); - switch (frm) { - case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(34, 240, _flags.isTalkie ? 60 : 40, _seqTextColorMap, 252); - seq_printCreditsString(35, 240, _flags.isTalkie ? 70 : 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(36, 240, _flags.isTalkie ? 90 : 70, _seqTextColorMap, 252); - seq_printCreditsString(37, 240, _flags.isTalkie ? 100 : 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(38, 240, _flags.isTalkie ? 120 : 110, _seqTextColorMap, 252); - seq_printCreditsString(39, 240, _flags.isTalkie ? 130 : 120, _seqTextColorMap, _seqTextColor[0]); - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - seq_printCreditsString(103, 240, 130, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; + if (chatNum < 12 && !_vm->gameFlags().isDemo && _vm->textEnabled()) + seq_setTextEntry(chatNum, 160, 168, _textDuration[chatNum], 160); - case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 255; - _screen->setTextColorMap(_seqTextColorMap); - break; + _vm->sound()->voicePlay(_sequenceSoundList[chatNum], &_speechHandle); +} - case 5: - if (!_flags.isTalkie) - seq_playTalkText(18); - _seqFrameDelay = 16; +void SeqPlayer_HOF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovie_v2 *wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) { + int dur = int(strlen(_sequenceStrings[strIndex])) * (_vm->gameFlags().isTalkie ? 7 : 15); + if (_vm->textEnabled()) { + int entry = seq_setTextEntry(strIndex, x, y, dur, width); + _textSlots[entry].textcolor = textColor; + } + _seqWsaChatTimeout = _system->getMillis() + dur * _vm->tickLength(); + int curframe = firstframe; - if (_flags.isTalkie) { - chatFirstFrame = 5; - chatLastFrame = 8; - voiceIndex = 22; - } else { - chatLastFrame = 14; + if (vocIndex && _vm->speechEnabled()) { + while (_vm->sound()->voiceIsPlaying() && !_abortPlayback) + delayTicks(1); + seq_playTalkText(vocIndex); + } + + while (_system->getMillis() < _seqWsaChatTimeout && !_abortPlayback) { + if (lastframe < 0) { + int t = ABS(lastframe); + if (t < curframe) + curframe = t; } - chatX = 116; - chatY = 90; - chatW = 60; - seq_playWsaSyncDialogue(24, voiceIndex, 149, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - break; + if (ABS(lastframe) < curframe) + curframe = firstframe; - case 11: - if (_flags.isTalkie) - seq_playWsaSyncDialogue(24, 22, 149, 116, 90, 60, wsaObj, 11, 14, x, y); - break; + _seqWsaChatFrameTimeout = _system->getMillis() + _animDuration * _vm->tickLength(); + setCountDown(_animDuration); - case 16: - seq_playTalkText(_flags.isTalkie ? 23 : 19); - _seqFrameDelay = _flags.isTalkie ? 20 : 16; + if (wsa) + wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0); - if (_flags.lang == Common::FR_FRA) { - chatY = 48; - chatW = 88; - } else { - chatY = 60; - chatW = 100; - } - chatX = 60; + _screen->copyPage(2, 12); - if (_flags.isTalkie) - voiceIndex = 36; + seq_processText(); - seq_playWsaSyncDialogue(25, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 16, 25, x, y); - _seqFrameDelay = 16; - break; + uint32 tm = _system->getMillis(); + if (_seqWsaChatFrameTimeout > tm && _seqWsaChatTimeout > tm) + _vm->delay(MIN(_seqWsaChatFrameTimeout - tm, _seqWsaChatTimeout - tm)); - default: - break; + if (_vm->speechEnabled() && !_vm->textEnabled() && !_vm->snd_voiceIsPlaying()) + break; + + _screen->copyPage(2, 0); + _screen->updateScreen(); + curframe++; } - _seqFrameCounter++; - return 0; -} + if (_abortPlayback) + _vm->sound()->voiceStop(); -int KyraEngine_HoF::seq_finaleFish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - uint16 voiceIndex = 0; + if (ABS(lastframe) < curframe) + curframe = ABS(lastframe); - switch (frm) { - case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; + if (curframe == firstframe) + curframe++; - seq_printCreditsString(40, 240, _flags.isTalkie ? 55 : 40, _seqTextColorMap, 252); - seq_printCreditsString(41, 240, _flags.isTalkie ? 65 : 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(42, 240, _flags.isTalkie ? 75 : 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(43, 240, _flags.isTalkie ? 95 : 80, _seqTextColorMap, 252); - seq_printCreditsString(44, 240, _flags.isTalkie ? 105 : 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(93, 240, _flags.isTalkie ? 125 : 110, _seqTextColorMap, 252); - seq_printCreditsString(94, 240, _flags.isTalkie ? 135 : 120, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; + _animCurrentFrame = curframe; +} - case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); - break; +void SeqPlayer_HOF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { + uint8 colormap[16]; + if (_abortPlayback || _vm->shouldQuit() || _result) + return; - case 4: - chatX = 94; - chatY = 42; - chatW = 100; - if (_flags.isTalkie) - voiceIndex = 37; - seq_playWsaSyncDialogue(26, voiceIndex, 149, chatX, chatY, chatW, wsaObj, 3, 12, x, y); - break; + Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); - case 14: - seq_playTalkText(_flags.isTalkie ? 19 : 15); - break; + memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); + _screen->getPalette(0)[0x2f6] = 0x3f; + _screen->getPalette(0)[0x2f5] = 0x20; + _screen->getPalette(0)[0x2f4] = 0x30; + colormap[0] = colorMap[0]; + colormap[1] = 0xfd; + memcpy(&colormap[2], &colorMap[2], 14); + uint8 seqTextColor0 = _seqTextColor[0]; - case 23: - seq_playTalkText(_flags.isTalkie ? 20 : 16); - break; + _seqTextColor[0] = 253; + _screen->setTextColorMap(colormap); + seq_resetAllTextEntries(); + seq_setTextEntry(strIndex, x, y, 0x80, 0x78); + seq_processText(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[textcolor * 3]; + _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[textcolor * 3 + 1]; + _screen->getPalette(0)[0x2f9] = _screen->getPalette(0)[textcolor * 3 + 2]; + _screen->fadePalette(_screen->getPalette(0), 0x18); - case 29: - chatX = (_flags.lang == Common::DE_DEU) ? 82 : ((_flags.lang == Common::FR_FRA) ? 92 : 88); - chatY = 40; - chatW = 100; + _seqTextColor[0] = textcolor; + _screen->setTextColorMap(colorMap); + seq_resetAllTextEntries(); + seq_setTextEntry(strIndex, x, y, 0x80, 0x78); + seq_processText(); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[0x2f9] = 0; + _screen->fadePalette(_screen->getPalette(0), 1); + _screen->copyPage(2, 12); + seq_resetAllTextEntries(); - if (_flags.isTalkie) { - if (_flags.lang == Common::DE_DEU) - chatY = 35; - voiceIndex = 38; - } + _seqTextColor[0] = seqTextColor0; - seq_playWsaSyncDialogue(27, voiceIndex, 187, chatX, chatY, chatW, wsaObj, 28, 34, x, y); - break; + _screen->setFont(of); +} - case 45: - seq_playTalkText(_flags.isTalkie ? 21 : 17); - break; +int SeqPlayer_HOF::seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width) { + for (int i = 0; i < 10; i++) { + if (_textSlots[i].duration != -1) { + if (i < 9) + continue; + else + return -1; + } - case 50: - seq_playTalkText(_flags.isTalkie ? 29 : 25); - break; + _textSlots[i].strIndex = strIndex; + _textSlots[i].x = posX; + _textSlots[i].y = posY; + _textSlots[i].duration = duration * _vm->tickLength(); + _textSlots[i].width = width; + _textSlots[i].startTime = _system->getMillis(); + _textSlots[i].textcolor = -1; - default: - break; + return i; } - - _seqFrameCounter++; - return 0; + return -1; } -int KyraEngine_HoF::seq_finaleFheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; - uint16 voiceIndex = 0; +void SeqPlayer_HOF::seq_processText() { + int curPage = _screen->setCurPage(2); + char outputStr[70]; - switch (frm) { - case -2: - _screen->copyPage(12, 2); - _screen->copyPage(2, 0); - _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(49, 240, 20, _seqTextColorMap, 252); - seq_printCreditsString(50, 240, 30, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(51, 240, 40, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(52, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(53, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(54, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(55, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(56, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(57, 240, 100, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(58, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(60, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(61, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(62, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(63, 240, 150, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(64, 240, 160, _seqTextColorMap, _seqTextColor[0]); + for (int i = 0; i < 10; i++) { + if (_textSlots[i].startTime + _textSlots[i].duration > _system->getMillis() && _textSlots[i].duration != -1) { - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; + char *srcStr = seq_preprocessString(_sequenceStrings[_textSlots[i].strIndex], _textSlots[i].width); + int yPos = _textSlots[i].y; - case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); - break; - - case 2: - seq_playTalkText(_flags.isTalkie ? 25 : 21); + while (*srcStr) { + uint32 linePos = 0; + for (; *srcStr; linePos++) { + if (*srcStr == '\r') + break; + outputStr[linePos] = *srcStr; + srcStr++; + } + outputStr[linePos] = 0; + if (*srcStr == '\r') + srcStr++; - if (_flags.lang == Common::FR_FRA) { - chatX = 92; - chatY = 72; + uint8 textColor = (_textSlots[i].textcolor >= 0) ? _textSlots[i].textcolor : _seqTextColor[0]; + _screen->printText(outputStr, _textSlots[i].x - (_screen->getTextWidth(outputStr) / 2), yPos, textColor, 0); + yPos += 10; + } } else { - chatX = (_flags.lang == Common::DE_DEU) ? 90 : 98; - chatY = 84; + _textSlots[i].duration = -1; } + } - if (_flags.isTalkie) { - chatFirstFrame = 8; - chatLastFrame = 9; - voiceIndex = 39; + _screen->setCurPage(curPage); +} + +char *SeqPlayer_HOF::seq_preprocessString(const char *srcStr, int width) { + char *dstStr = _tempString; + int lineStart = 0; + int linePos = 0; + + while (*srcStr) { + while (*srcStr && *srcStr != ' ') + dstStr[lineStart + linePos++] = *srcStr++; + dstStr[lineStart + linePos] = 0; + + int len = _screen->getTextWidth(&dstStr[lineStart]); + if (width >= len && *srcStr) { + dstStr[lineStart + linePos++] = *srcStr++; } else { - chatFirstFrame = 2; - chatLastFrame = -8; + dstStr[lineStart + linePos] = '\r'; + lineStart += linePos + 1; + linePos = 0; + if (*srcStr) + srcStr++; } - chatW = 100; + } + dstStr[lineStart + linePos] = 0; - seq_playWsaSyncDialogue(28, voiceIndex, -1, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 4; - break; + return strlen(_tempString) ? dstStr : 0; +} - case 9: - seq_playTalkText(_flags.isTalkie ? 24 : 20); - _seqFrameDelay = 100; - break; +void SeqPlayer_HOF::waitForSubTitlesTimeout() { + uint32 timeOut = _system->getMillis() + ticksTillSubTitlesTimeout() * _vm->tickLength(); - default: - break; + if (_vm->textEnabled()) { + delayUntil(timeOut); + } else if (_vm->speechEnabled()) { + while (_vm->snd_voiceIsPlaying()) + delayTicks(1); } - _seqFrameCounter++; - return 0; + seq_resetAllTextEntries(); } -int KyraEngine_HoF::seq_finaleFarmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - uint16 voiceIndex = 0; +uint32 SeqPlayer_HOF::ticksTillSubTitlesTimeout() { + uint32 longest = 0; - switch (frm) { - case -2: - _screen->copyPage(12, 2); - _screen->copyPage(2, 0); - _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(45, 240, 40, _seqTextColorMap, 252); - seq_printCreditsString(46, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(47, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(83, 240, 80, _seqTextColorMap, 252); - seq_printCreditsString(48, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(65, 240, 110, _seqTextColorMap, 252); - seq_printCreditsString(66, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(67, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(68, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(69, 240, 150, _seqTextColorMap, _seqTextColor[0]); - if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) - seq_printCreditsString(104, 240, 160, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; + for (int i = 0; i < 10; i++) { + uint32 timeOut = (_textSlots[i].duration + _textSlots[i].startTime); + uint32 curtime = _system->getMillis(); + if (_textSlots[i].duration != -1 && timeOut > curtime) { + timeOut -= curtime; + if (longest < timeOut) + longest = timeOut; + } + } - case 0: - _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 254) & 0xff); - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff); - _screen->setTextColorMap(_seqTextColorMap); - seq_playTalkText(_flags.isTalkie ? 30 : 26); - break; + uint32 tl = _vm->tickLength(); + return (longest + (tl - 1)) / tl; +} - case 6: - if (_flags.isTalkie) - seq_playTalkText(18); - break; +void SeqPlayer_HOF::seq_resetAllTextEntries() { + for (int i = 0; i < 10; i++) + _textSlots[i].duration = -1; +} - case 12: - if (!_flags.isTalkie) - seq_playTalkText(14); +void SeqPlayer_HOF::fadeOutMusic() { + _vm->sound()->beginFadeOut(); + delayTicks(80); +} - chatX = 90; - chatY = 30; - chatW = 100; +void SeqPlayer_HOF::seq_finaleActorScreen() { + static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; - if (_flags.isTalkie) { - if (_flags.lang == Common::FR_FRA || _flags.lang == Common::DE_DEU) { - chatX = 75; - chatY = 25; - } - voiceIndex = 40; - } + _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); + _screen->setFont(Screen::FID_GOLDFONT_FNT); - seq_playWsaSyncDialogue(29, voiceIndex, 150, chatX, chatY, chatW, wsaObj, 12, -21, x, y); - break; + int talkieCreditsSize, talkieCreditsSpecialSize; + const uint8 *talkieCredits = _vm->staticres()->loadRawData(k2SeqplayCredits, talkieCreditsSize); + const char * const *talkieCreditsSpecial = _vm->staticres()->loadStrings(k2SeqplayCreditsSpecial, talkieCreditsSpecialSize); - default: - break; - } + _vm->sound()->setSoundList(_vm->soundData(kMusicIngame)); + _vm->sound()->loadSoundFile(3); + _vm->sound()->playTrack(3); - _seqFrameCounter++; - return 0; -} + _screen->setTextColorMap(colormap); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + _screen->fadeFromBlack(); -int KyraEngine_HoF::seq_finaleFuards(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - int chatFirstFrame = 0; - int chatLastFrame = 0; - //int textCol = 0; + _screen->_charWidth = -2; + uint8 *dataPtr = new uint8[0xafd]; + memcpy(dataPtr, talkieCredits, talkieCreditsSize); + _vm->staticres()->unloadId(k2SeqplayCredits); - uint16 voiceIndex = 0; + seq_displayScrollText(dataPtr, &d, 2, 6, 5, 1, Screen::FID_GOLDFONT_FNT, Screen::FID_GOLDFONT_FNT, 0, talkieCreditsSpecial); + delayTicks(8); - switch (frm) { - case -2: - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(70, 240, 20, _seqTextColorMap, 252); - seq_printCreditsString(71, 240, 30, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(72, 240, 40, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(73, 240, 50, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(74, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(75, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(101, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(102, 240, 90, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(87, 240, 100, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(88, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(89, 240, 120, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(90, 240, 130, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(91, 240, 140, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(92, 240, 150, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; + delete[] dataPtr; + _vm->staticres()->unloadId(k2SeqplayCreditsSpecial); + _vm->sound()->setSoundList(_vm->soundData(kMusicFinale)); + _vm->sound()->loadSoundFile(0); +} - case 0: - for (int i = 0; i < 0x300; i++) - _screen->getPalette(0)[i] &= 0x3f; - _seqTextColor[1] = 0xCf; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xfe; +void SeqPlayer_HOF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, + int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData, const char *const *specialData) { + if (!data) + return; - _screen->setTextColorMap(_seqTextColorMap); - break; + static const char mark[] = { 5, 13, 0 }; - case 6: - _seqFrameDelay = 20; + _screen->clearPage(tempPage1); + _screen->clearPage(tempPage2); + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, 0, tempPage1); - if (_flags.isTalkie) { - chatX = 82; - //textCol = 143; - chatFirstFrame = 16; - chatLastFrame = 21; - voiceIndex = 41; - } else { - chatX = 62; - //textCol = 137; - chatFirstFrame = 9; - chatLastFrame = 13; + struct ScrollTextData { + int16 x; + int16 y; + uint8 *text; + byte unk1; + byte height; + byte adjust; + + ScrollTextData() { + x = 0; // 0 11 + y = 0; // 2 13 + text = 0; // 4 15 + unk1 = 0; // 8 19 + height = 0; // 9 20 + adjust = 0; // 10 21 } - chatY = (_flags.lang == Common::FR_FRA || _flags.lang == Common::DE_DEU) ? 88 :100; - chatW = 80; + }; - seq_playWsaSyncDialogue(30, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 8; - break; + ScrollTextData *textData = new ScrollTextData[36]; + uint8 *ptr = data; - case 9: - case 16: - if (_flags.isTalkie) { - if (frm == 16) + bool loop = true; + int cnt = 0; + + while (loop) { + uint32 loopEnd = _system->getMillis() + speed * _vm->tickLength(); + + while (cnt < 35 && *ptr) { + uint16 cH; + + if (cnt) + cH = textData[cnt].y + textData[cnt].height + (textData[cnt].height >> 3); + else + cH = d->h; + + char *str = (char *)ptr; + + ptr = (uint8 *)strpbrk(str, mark); + if (!ptr) + ptr = (uint8 *)strchr(str, 0); + + textData[cnt + 1].unk1 = *ptr; + *ptr = 0; + if (textData[cnt + 1].unk1) + ptr++; + + if (*str == 3 || *str == 4) + textData[cnt + 1].adjust = *str++; + else + textData[cnt + 1].adjust = 0; + + _screen->setFont(fid1); + + if (*str == 1) { + _screen->setFont(fid2); + str++; + } else if (*str == 2) { + str++; + } + + textData[cnt + 1].height = _screen->getFontHeight(); + + switch (textData[cnt + 1].adjust) { + case 3: + textData[cnt + 1].x = 157 - _screen->getTextWidth(str); break; - chatX = 64; - //textCol = 137; - chatFirstFrame = 9; - chatLastFrame = 13; - voiceIndex = 42; - } else { - if (frm == 9) + case 4: + textData[cnt + 1].x = 161; break; - chatX = 80; - //textCol = 143; - chatFirstFrame = 16; - chatLastFrame = 21; + default: + textData[cnt + 1].x = (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1; + } + + if (textData[cnt].unk1 == 5) + cH -= (textData[cnt].height + (textData[cnt].height >> 3)); + + textData[cnt + 1].y = cH; + textData[cnt + 1].text = (uint8 *)str; + cnt++; } - chatY = 100; - chatW = 100; - seq_playWsaSyncDialogue(31, voiceIndex, 143, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); - if (_flags.isTalkie) - _seqWsaCurrentFrame = 21; - break; + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage1, tempPage2); - default: - break; - } + int cnt2 = 0; + bool palCycle = 0; - _seqFrameCounter++; - return 0; -} + while (cnt2 < cnt) { + const char *str = (const char *)textData[cnt2 + 1].text; + const char *str2 = str; + int16 cW = textData[cnt2 + 1].x - 10; + int16 cH = textData[cnt2 + 1].y; + int x = (d->sx << 3) + cW; + int y = d->sy + cH; + int col1 = 255; -int KyraEngine_HoF::seq_finaleFirates(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - _seqSubFrameEndTimeInternal = 0; - int chatX = 0; - int chatY = 0; - int chatW = 0; - uint16 voiceIndex = 0; + if (cH < d->h) { + _screen->setCurPage(tempPage2); + _screen->setFont(fid1); + if (textData[cnt2 + 1].height != _screen->getFontHeight()) + _screen->setFont(fid2); - switch (frm) { - case -2: - _screen->copyPage(12, 2); - _screen->copyPage(2, 0); + if (specialData) { + if (!strcmp(str, specialData[0])) { + col1 = 112; + char cChar[2] = " "; + while (*str2) { + cChar[0] = *str2; + _screen->printText(cChar, x, y, col1++, 0); + x += _screen->getCharWidth((uint8)*str2++); + } + palCycle = true; + } else if (!strcmp(str, specialData[1])) { + col1 = 133; + char cChar[2] = " "; + while (*str2) { + cChar[0] = *str2; + _screen->printText(cChar, x, y, col1--, 0); + x += _screen->getCharWidth((uint8)*str2++); + } + palCycle = true; + } else { + _screen->printText(str, x, y, col1, 0); + } + } else { + _screen->printText(str, x, y, col1, 0); + } + _screen->setCurPage(0); + } + + textData[cnt2 + 1].y -= step; + cnt2++; + } + + _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage2, 0); _screen->updateScreen(); - seq_sequenceCommand(9); - _seqSubFrameEndTimeInternal = _system->getMillis() + 480 * _tickLength; - seq_printCreditsString(76, 240, 40, _seqTextColorMap, 252); - seq_printCreditsString(77, 240, 50, _seqTextColorMap, 252); - seq_printCreditsString(78, 240, 60, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(79, 240, 70, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(80, 240, 80, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(84, 240, 100, _seqTextColorMap, 252); - seq_printCreditsString(85, 240, 110, _seqTextColorMap, _seqTextColor[0]); - seq_printCreditsString(99, 240, 130, _seqTextColorMap, 252); - seq_printCreditsString(100, 240, 140, _seqTextColorMap, _seqTextColor[0]); - delay(_seqSubFrameEndTimeInternal - _system->getMillis()); - _seqEndTime = 0; - break; - case 0: - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); - break; + if (textData[1].y < -10) { + textData[1].text += strlen((char *)textData[1].text); + textData[1].text[0] = textData[1].unk1; + cnt--; + memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); + } - case 6: - seq_playTalkText(_flags.isTalkie ? 31 : 27); - break; + if (palCycle) { + for (int col = 133; col > 112; col--) + _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); + _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); + _screen->setScreenPalette(_screen->getPalette(0)); + } - case 14: - case 15: - if (!((frm == 15 && !_flags.isTalkie) || (frm == 14 && _flags.isTalkie))) - break; + delayUntil(loopEnd); - seq_playTalkText(_flags.isTalkie ? 31 : 27); + if ((cnt < 36) && ((d->sy + d->h) > (textData[cnt].y + textData[cnt].height)) && !_abortPlayback) { + delayTicks(500); + cnt = 0; + } - if (_flags.lang == Common::DE_DEU) { - chatX = 82; - chatY = 84; - chatW = 140; - } else { - chatX = 74; - chatY = (_flags.lang == Common::FR_FRA) ? 96: 108; - chatW = 80; + if (!cnt || _abortPlayback) + loop = false; + } + + _vm->sound()->beginFadeOut(); + _screen->fadeToBlack(); + + _abortPlayback = false; + + delete[] textData; +} + +void SeqPlayer_HOF::seq_scrollPage(int bottom, int top) { + int dstY, dstH, srcH; + + static const ScreenDim d = { 0x00, 0x00, 0x28, 0x320, 0xFF, 0xFE, 0x00, 0x00 }; + + if (_seqScrollTextCounter - (top - 1) < 0) { + dstY = top - _seqScrollTextCounter; + dstH = _seqScrollTextCounter; + srcH = 0; + } else { + dstY = 0; + srcH = _seqScrollTextCounter - top; + dstH = (400 - srcH <= top) ? 400 - srcH : top; + } + + if (dstH > 0) { + assert(_hofDemoAnimData); + for (int i = 0; i < 4; i++) { + const HoFSeqItemAnimData *def = &_hofDemoAnimData[i]; + ActiveItemAnim *a = &_hofDemoActiveItemAnim[i]; + + _screen->fillRect(12, def->y - 8, 28, def->y + 8, 0, 4); + _screen->drawShape(4, _hofDemoItemShapes[def->itemIndex + def->frames[a->currentFrame]], 12, def->y - 8, 0, 0); + if (_animCurrentFrame % 2 == 0) + a->currentFrame = (a->currentFrame + 1) % 20; } + assert(_screenHoF); + _screenHoF->copyRegionEx(4, 0, srcH, 2, 2, dstY + bottom, 320, dstH, &d); + } +} - if (_flags.isTalkie) - voiceIndex = 43; +void SeqPlayer_HOF::delayTicks(uint32 ticks) { + uint32 len = ticks * _vm->tickLength(); + while (len && !_vm->shouldQuit() && !checkAbortPlayback()) { + uint32 step = (len >= 10) ? 10 : len; + _system->delayMillis(step); + len -= step; + } +} - seq_playWsaSyncDialogue(32, voiceIndex, 137, chatX, chatY, chatW, wsaObj, 14, 16, x, y); - break; +void SeqPlayer_HOF::delayUntil(uint32 dest) { + for (uint32 ct = _system->getMillis(); ct < dest && !_vm->shouldQuit() && !checkAbortPlayback(); ) { + uint32 step = (dest - ct >= 10) ? 10 : (dest - ct); + _system->delayMillis(step); + ct = _system->getMillis(); + } +} - case 28: - seq_playTalkText(_flags.isTalkie ? 32 : 28); - break; +void SeqPlayer_HOF::setCountDown(uint32 ticks) { + _countDownRemainder = ticks * _vm->tickLength(); + _countDownLastUpdate = _system->getMillis() & ~(_vm->tickLength() - 1); +} + +bool SeqPlayer_HOF::countDownRunning() { + uint32 cur = _system->getMillis(); + uint32 step = cur - _countDownLastUpdate; + _countDownLastUpdate = cur; + _countDownRemainder = (step <= _countDownRemainder) ? _countDownRemainder - step : 0; + return _countDownRemainder; +} - case 29: - seq_playTalkText(_flags.isTalkie ? 33 : 29); - break; +#define CASE_ALT(dosCase, towns98Case)\ + case dosCase:\ + case towns98Case:\ + if (!((_callbackCurrentFrame == towns98Case && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == dosCase && _vm->gameFlags().platform == Common::kPlatformPC)))\ + break; - case 31: - if (_flags.isTalkie) - voiceIndex = 44; +int SeqPlayer_HOF::cbHOF_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == -2) { + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + delayTicks(300); + } else if (!frm) { + _vm->sound()->playTrack(2); + } - chatX = 90; - chatY = (_flags.lang == Common::DE_DEU) ? 60 : 76; - chatW = 80; + return 0; +} - seq_playWsaSyncDialogue(33, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 31, 34, x, y); - break; +int SeqPlayer_HOF::cbHOF_title(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 1) { + _vm->sound()->playTrack(3); + } else if (frm == 25 && _startupSaveLoadable) { + int cp = _screen->setCurPage(0); + _screen->showMouse(); + _system->updateScreen(); + _result = _menu->handle(11) + 1; + _updateAnimations = false; + + if (_result == 1) { + _curScene = _lastScene; + _preventLooping = true; + } else { + setCountDown(200); + } - case 35: - _seqFrameDelay = 300; - break; + if (_result == 4) + _vm->quitGame(); - default: - break; + _screen->hideMouse(); + _screen->setCurPage(cp); } - _seqFrameCounter++; return 0; } -int KyraEngine_HoF::seq_finaleFrash(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - int tmp = 0; +int SeqPlayer_HOF::cbHOF_overview(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint8 *tmpPal = _screen->getPalette(3).getData() + 0x101; + memset(tmpPal, 0, 256); + uint32 frameEnd = 0; + uint32 curTime = 0; - switch (frm) { - case -2: - _screen->setCurPage(2); - _screen->clearCurPage(); - _screen->copyPage(2, 12); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _seqFrameCounter = 0; - seq_loadNestedSequence(0, kSequenceFiggle); - break; + switch (_callbackCurrentFrame) { + case 0: + _updateAnimations = true; + fadeOutMusic(); + _vm->sound()->playTrack(4); + frameEnd = _system->getMillis() + 60 * _vm->tickLength(); - case -1: - if (_flags.isTalkie) - seq_finaleActorScreen(); - _seqSpecialFlag = _flags.isTalkie; - break; + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + _screen->setTextColorMap(_seqTextColorMap); - case 0: - if (_seqFrameCounter == 1) { - _sound->playTrack(4); - _seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0), 1, 255) & 0xff; - memset(_seqTextColorMap, _seqTextColor[1], 16); - _seqTextColor[0] = _seqTextColorMap[1] = 0xff; - _screen->setTextColorMap(_seqTextColorMap); - } - _seqFrameDelay = 10; + delayUntil(frameEnd); break; case 1: - if (_seqFrameCounter < 20 && _seqSpecialFlag) { - _seqWsaCurrentFrame = 0; - } else { - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); - seq_playTalkText(_flags.isTalkie ? 26 : 22); - if (_seqSpecialFlag) { - _seqFrameCounter = 3; - _seqSpecialFlag = false; - } + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x40, 0, 0, 0, 0x100, true); + for (int i = 0; i < 256; i++) + tmpPal[_screen->getPalette(3)[i]] = 1; + + for (int i = 0; i < 256; i++) { + int v = (tmpPal[i] == 1) ? i : _screen->getPalette(3)[i]; + v *= 3; + _screen->getPalette(2)[3 * i] = _screen->getPalette(0)[v]; + _screen->getPalette(2)[3 * i + 1] = _screen->getPalette(0)[v + 1]; + _screen->getPalette(2)[3 * i + 2] = _screen->getPalette(0)[v + 2]; } break; - case 2: - _seqFrameDelay = 20; + case 40: + startNestedAnimation(0, kNestedSequenceOver1); break; - case 3: - seq_playTalkText(_flags.isTalkie ? 27 : 23); - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); + case 60: + startNestedAnimation(1, kNestedSequenceOver2); break; - case 4: - _seqFrameDelay = 10; + case 120: + seq_playTalkText(0); break; - case 5: - seq_playTalkText(_flags.isTalkie ? 27 : 23); - tmp = _seqFrameCounter / 6; - if (tmp == 2) - _seqFrameDelay = _flags.isTalkie ? 7 : (1 + _rnd.getRandomNumberRng(1, 10)); - else if (tmp < 2) - _seqFrameDelay = _flags.isTalkie ? 500 : (300 + _rnd.getRandomNumberRng(1, 300)); + case 200: + waitForSubTitlesTimeout(); + _screen->fadePalette(_screen->getPalette(2), 64); break; - case 6: - _seqFrameDelay = 10; - tmp = _seqFrameCounter / 6; - if (tmp == 2) - _seqWsaCurrentFrame = 4; - else if (tmp < 2) - _seqWsaCurrentFrame = 0; + case 201: + _screen->setScreenPalette(_screen->getPalette(2)); + _screen->updateScreen(); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); + _screen->copyPage(2, 12); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->setScreenPalette(_screen->getPalette(0)); + _screen->updateScreen(); + closeNestedAnimation(0); + closeNestedAnimation(1); break; - case 7: - _seqFrameCounter = 0; - _seqFrameDelay = 5; - seq_playTalkText(_flags.isTalkie ? 26 : 22); + case 282: + startNestedAnimation(0, kNestedSequenceForest); + seq_playTalkText(1); break; - case 11: - if (_seqFrameCounter < 8) - _seqWsaCurrentFrame = 8; + CASE_ALT(434, 354) + /*case 354: + case 434: + if (!((_callbackCurrentFrame == 354 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 434 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceDragon); + break; + + CASE_ALT(540, 400) + /*case 400: + case 540: + if (!((_callbackCurrentFrame == 400 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 540 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -void KyraEngine_HoF::seq_finaleActorScreen() { - static const uint8 colormap[] = {0, 0, 102, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - static const ScreenDim d = { 0x00, 0x0C, 0x28, 0xB4, 0xFF, 0x00, 0x00, 0x00 }; +int SeqPlayer_HOF::cbHOF_library(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame) { + case 0: + _updateAnimations = true; + _vm->sound()->playTrack(5); - _screen->loadBitmap("finale.cps", 3, 3, &_screen->getPalette(0)); - _screen->setFont(Screen::FID_GOLDFONT_FNT); + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; - int talkieCreditsSize, talkieCreditsSpecialSize; - const uint8 *talkieCredits = _staticres->loadRawData(k2SeqplayCredits, talkieCreditsSize); - const char * const *talkieCreditsSpecial = _staticres->loadStrings(k2SeqplayCreditsSpecial, talkieCreditsSpecialSize); + _screen->setTextColorMap(_seqTextColorMap); + break; - _sound->setSoundList(&_soundData[kMusicIngame]); - _sound->loadSoundFile(3); - _sound->playTrack(3); + case 1: + startNestedAnimation(0, kNestedSequenceLibrary3); + seq_playTalkText(4); + break; - _screen->setTextColorMap(colormap); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - _screen->fadeFromBlack(); + case 100: + waitForSubTitlesTimeout(); - _screen->_charWidth = -2; - uint8 *dataPtr = new uint8[0xafd]; - memcpy(dataPtr, talkieCredits, talkieCreditsSize); - _staticres->unloadId(k2SeqplayCredits); + _screen->copyPage(12, 2); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + _screen->copyPage(2, 12); - seq_displayScrollText(dataPtr, &d, 2, 6, 5, 1, Screen::FID_GOLDFONT_FNT, Screen::FID_GOLDFONT_FNT, 0, talkieCreditsSpecial); - delay(120); + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceDarm); + break; - delete[] dataPtr; - _staticres->unloadId(k2SeqplayCreditsSpecial); - _sound->setSoundList(&_soundData[kMusicFinale]); - _sound->loadSoundFile(0); -} + case 104: + seq_playTalkText(5); + break; -int KyraEngine_HoF::seq_finaleFiggle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter == 10) - _seqEndTime = 0; - if (_seqFrameCounter == 10 || _seqFrameCounter == 5 || _seqFrameCounter == 7) - seq_playTalkText(_flags.isTalkie ? 45 : 30); + case 240: + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + startNestedAnimation(0, kNestedSequenceLibrary2); + break; - _seqFrameCounter++; - return frm; -} + case 340: + closeNestedAnimation(0); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); + _screen->copyPage(2, 12); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); -int KyraEngine_HoF::seq_demoVirgin(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!frm) - delay(50 * _tickLength); - return 0; -} + startNestedAnimation(0, kNestedSequenceMarco); + seq_playTalkText(6); + break; -int KyraEngine_HoF::seq_demoWestwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!frm) - _sound->playTrack(2); - return 0; -} -int KyraEngine_HoF::seq_demoTitle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!frm) { - _sound->playTrack(3); - } else if (frm == 25) { - delay(60 * _tickLength); - _seqEndTime = 0; - seq_sequenceCommand(0); - } - return 0; -} + CASE_ALT(660, 480) + /*case 480: + case 660: + if (!((_callbackCurrentFrame == 480 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 660 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ -int KyraEngine_HoF::seq_demoHill(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!frm) { - _sound->playTrack(4); - } else if (frm == 25) { - seq_loadNestedSequence(0, kSequenceDemoWater); - _seqFrameDelay--; - } else if (frm > 25 && frm < 50) { - if (_seqFrameDelay > 3) - _seqFrameDelay--; - } else if (frm == 95) { - _seqFrameDelay = 70; - } else if (frm == 96) { - _seqFrameDelay = 7; - } else if (frm == 129) { - seq_resetActiveWSA(0); + _screen->copyPage(2, 12); + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; + break; + + default: + break; } + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_demoOuthome(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (frm) { - case 12: - seq_playTalkText(4); +int SeqPlayer_HOF::cbHOF_hand(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame) { + case 0: + _updateAnimations = true; + _vm->sound()->playTrack(6); + + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + + _screen->setTextColorMap(_seqTextColorMap); break; - case 32: + case 1: + startNestedAnimation(0, kNestedSequenceHand1a); + startNestedAnimation(1, kNestedSequenceHand1b); + startNestedAnimation(2, kNestedSequenceHand1c); seq_playTalkText(7); break; - case 36: - seq_playTalkText(10); + case 201: + waitForSubTitlesTimeout(); + _screen->applyOverlay(0, 0, 320, 200, 2, _screen->getPalette(3).getData()); + _screen->copyPage(2, 12); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); + _screen->updateScreen(); + closeNestedAnimation(0); + closeNestedAnimation(1); + closeNestedAnimation(2); + startNestedAnimation(0, kNestedSequenceHand2); + seq_playTalkText(8); break; - case 57: + CASE_ALT(395, 260) + /*case 260: + case 395: + if (!((_callbackCurrentFrame == 260 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 395 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + startNestedAnimation(1, kNestedSequenceHand3); seq_playTalkText(9); break; - case 80: - case 96: - case 149: - _seqFrameDelay = 70; + CASE_ALT(500, 365) + /*case 365: + case 500: + if (!((_callbackCurrentFrame == 365 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 500 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + waitForSubTitlesTimeout(); + closeNestedAnimation(1); + startNestedAnimation(0, kNestedSequenceHand4); break; - case 81: - case 97: - _seqFrameDelay = 5; + CASE_ALT(540, 405) + /*case 405: + case 540: + if (!((_callbackCurrentFrame == 405 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 540 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + seq_playTalkText(10); break; - case 110: - seq_playTalkText(5); + CASE_ALT(630, 484) + /*case 484: + case 630: + if (!((_callbackCurrentFrame == 484 && (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)) || (_callbackCurrentFrame == 630 && _vm->gameFlags().platform == Common::kPlatformPC))) + break;*/ + + waitForSubTitlesTimeout(); + closeNestedAnimation(0); + setCountDown(0); + _updateAnimations = false; break; - case 137: - seq_playTalkText(6); + default: break; } + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_demoWharf(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (!_seqFrameCounter) - seq_loadNestedSequence(0, kSequenceDemoWharf2); - - switch (frm) { - case 0: - seq_playTalkText(11); - break; - - case 5: - if ((_seqFrameCounter / 8) <= 2 || _activeWSA[0].flags != -1) - _seqWsaCurrentFrame = 0; - else - seq_resetActiveWSA(0); - break; +int SeqPlayer_HOF::cbHOF_point(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == -2) { + waitForSubTitlesTimeout(); + setCountDown(0); + } - case 6: - seq_resetActiveWSA(0); + switch (_callbackCurrentFrame) { + case -2: + waitForSubTitlesTimeout(); break; - case 8: - case 10: - seq_playTalkText(2); - break; + case 0: + _vm->sound()->playTrack(7); - case 13: - seq_playTalkText(7); + _seqTextColor[1] = 0xf7; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + _screen->setTextColorMap(_seqTextColorMap); + assert(_screenHoF); + _screenHoF->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3).getData(), 0x24, 0, 0, 0, 0x100, false); break; - case 16: - seq_playTalkText(12); + case 1: + seq_playTalkText(11); break; default: break; } - _seqFrameCounter++; + _callbackCurrentFrame++; return 0; } -int KyraEngine_HoF::seq_demoDinob(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 0) { - if (!(_seqFrameCounter/8)) { - seq_loadNestedSequence(0, kSequenceDemoDinob2); - _seqWsaCurrentFrame = 0; - } - } else if (frm == 3) { - if (_activeWSA[0].flags != -1) { - _seqWsaCurrentFrame = 0; - } else { - seq_resetActiveWSA(0); - _screen->copyPage(2, 12); - } - } else if (frm == 4) { - seq_resetActiveWSA(0); +int SeqPlayer_HOF::cbHOF_zanfaun(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == -2) { + waitForSubTitlesTimeout(); + setCountDown(0); + return 0; } - _seqFrameCounter++; - return 0; -} - -int KyraEngine_HoF::seq_demoFisher(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (((_system->getMillis() - _seqStartTime) / (5 * _tickLength)) > 0) { - _seqStartTime = _system->getMillis(); - if (!_seqFrameCounter) { - seq_loadNestedSequence(0, kSequenceDemoBail); - seq_loadNestedSequence(1, kSequenceDemoDig); - } - - if (_seqScrollTextCounter >= 0x18f && !_seqFrameCounter) - return 0; - - if (!_seqFrameCounter) { - _screen->loadBitmap("adtext.cps", 4, 4, 0); - _screen->loadBitmap("adtext2.cps", 6, 6, 0); - _screen->copyPageMemory(6, 0, 4, 64000, 1024); - _screen->copyPageMemory(6, 1023, 6, 0, 64000); - _seqScrollTextCounter = 0; - } + switch (_callbackCurrentFrame) { + case 0: + _vm->sound()->playTrack(8); - seq_scrollPage(24, 144); - _seqFrameCounter++; - if (_seqFrameCounter < 0x256 || _seqFrameCounter > 0x31c) { - if (_seqFrameCounter < 0x174 || _seqFrameCounter > 0x1d7) { - if (_seqFrameCounter < 0x84 || _seqFrameCounter > 0xe7) { - _seqScrollTextCounter++; - } - } - } + _seqTextColor[1] = 0xfd; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 255) & 0xff; + _screen->setTextColorMap(_seqTextColorMap); + break; - if (_seqFrameCounter > 0x31e) { - seq_resetActiveWSA(0); - seq_resetActiveWSA(1); - _seqEndTime = 0; - _screen->copyPage(2, 12); + case 1: + if (_vm->gameFlags().isTalkie) { + seq_playWsaSyncDialogue(21, 13, -1, 140, 70, 160, wsaObj, 0, 8, x, y); + } else { + seq_setTextEntry(21, 140, 70, 200, 160); + _animDuration = 200; } + break; - } else { - seq_scrollPage(24, 144); - } - return 0; -} + case 2: + case 11: + case 21: + if (!_vm->gameFlags().isTalkie) + _animDuration = 12; + break; -int KyraEngine_HoF::seq_demoWharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (frm == 69) - _seqWsaCurrentFrame = 8; + case 9: + if (_vm->gameFlags().isTalkie) + seq_playWsaSyncDialogue(13, 14, -1, 140, (_vm->gameFlags().lang == Common::FR_FRA + || _vm->gameFlags().lang == Common::DE_DEU) ? 50 : 70, 160, wsaObj, 9, 15, x, y); + break; - return frm; -} + case 10: + if (!_vm->gameFlags().isTalkie) { + waitForSubTitlesTimeout(); + seq_setTextEntry(13, 140, 50, _textDuration[13], 160); + _animDuration = 300; + } + break; -int KyraEngine_HoF::seq_demoDinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (frm) { - case 19: - seq_playTalkText(13); + case 16: + if (_vm->gameFlags().isTalkie) + seq_playWsaSyncDialogue(18, 15, -1, 140, (_vm->gameFlags().lang == Common::FR_FRA) ? 50 : + (_vm->gameFlags().lang == Common::DE_DEU ? 40 : 70), 160, wsaObj, 10, 16, x, y); break; - case 54: - seq_playTalkText(15); + case 17: + if (_vm->gameFlags().isTalkie) + _animDuration = 12; break; - case 61: - seq_playTalkText(16); + case 20: + if (!_vm->gameFlags().isTalkie) { + waitForSubTitlesTimeout(); + seq_setTextEntry(18, 160, 50, _textDuration[18], 160); + _animDuration = 200; + } break; - case 69: - seq_playTalkText(14); + case 26: + waitForSubTitlesTimeout(); break; - case 77: - seq_playTalkText(13); + case 46: + if (_vm->gameFlags().isTalkie) { + seq_playWsaSyncDialogue(16, 16, -1, 200, 50, 120, wsaObj, 46, 46, x, y); + } else { + waitForSubTitlesTimeout(); + seq_setTextEntry(16, 200, 50, _textDuration[16], 120); + } + + setCountDown(120); break; - case 79: - _seqWsaCurrentFrame = 4; + default: break; } + _callbackCurrentFrame++; + return 0; +} + +int SeqPlayer_HOF::cbHOF_over1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 2) + waitForSubTitlesTimeout(); + else if (frm == 3) + seq_playTalkText(12); return frm; } -int KyraEngine_HoF::seq_demoWater(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_over2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { if (frm == 1) - seq_playTalkText(11); + seq_playTalkText(12); return frm; } -int KyraEngine_HoF::seq_demoBail(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_forest(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 11) + waitForSubTitlesTimeout(); + else if (frm == 12) + seq_playTalkText(2); + return frm; } -int KyraEngine_HoF::seq_demoDig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { +int SeqPlayer_HOF::cbHOF_dragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 11) + waitForSubTitlesTimeout(); + else if (frm == 3) + seq_playTalkText(3); return frm; } -#ifdef ENABLE_LOL -int KyraEngine_HoF::seq_lolDemoScene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - Palette &tmpPal = _screen->getPalette(2); - - if (!(_seqFrameCounter % 100)) { - if (_seqFrameCounter == 0) { - _sound->haltTrack(); - _sound->playTrack(6); - } - tmpPal.copy(_screen->getPalette(0)); - - for (int i = 3; i < 0x300; i++) { - tmpPal[i] = ((int)tmpPal[i] * 120) / 64; - if (tmpPal[i] > 0x3f) - tmpPal[i] = 0x3f; - } - - seq_playTalkText(_rnd.getRandomBit()); - _screen->setScreenPalette(tmpPal); - _screen->updateScreen(); - delay(8); - } else { - _screen->setScreenPalette(_screen->getPalette(0)); - _screen->updateScreen(); - if (_seqFrameCounter == 40) - seq_playTalkText(3); - } +int SeqPlayer_HOF::cbHOF_darm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + //NULLSUB (at least in FM-TOWNS version) + return frm; +} - _seqFrameCounter++; +int SeqPlayer_HOF::cbHOF_library2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + //NULLSUB (at least in FM-TOWNS version) return frm; } -int KyraEngine_HoF::seq_lolDemoScene2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter - 17) { - case 0: - _seqFrameDelay = 8; - break; - case 3: - case 6: - case 9: - seq_playTalkText(8); - break; - case 15: - seq_playTalkText(9); - break; - case 18: - seq_playTalkText(2); - break; - default: - break; +int SeqPlayer_HOF::cbHOF_marco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 36) { + waitForSubTitlesTimeout(); + setCountDown(0); } - _seqFrameCounter++; return frm; } -int KyraEngine_HoF::seq_lolDemoScene3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter == 1) - seq_playTalkText(6); - else if (frm == 26) - seq_playTalkText(7); - - _seqFrameCounter++; +int SeqPlayer_HOF::cbHOF_hand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + //NULLSUB (at least in FM-TOWNS version) return frm; } -int KyraEngine_HoF::seq_lolDemoScene4(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter) { - case 11: - case 14: - case 17: - case 20: - seq_playTalkText(8); - break; - case 22: - seq_playTalkText(11); - break; - case 24: - seq_playTalkText(8); - break; - case 30: - seq_playTalkText(15); - break; - case 34: - seq_playTalkText(14); - break; - case 38: - seq_playTalkText(13); - break; - case 42: - seq_playTalkText(12); - break; - default: - break; - } +int SeqPlayer_HOF::cbHOF_hand1b(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 15) + frm = 12; + return frm; +} - _seqFrameCounter++; +int SeqPlayer_HOF::cbHOF_hand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 8) + frm = 4; return frm; } -int KyraEngine_HoF::seq_lolDemoScene5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - switch (_seqFrameCounter++) { - case 0: - case 4: - case 6: - case 8: - case 10: - case 14: - case 16: - case 18: - case 20: - case 22: - case 24: - case 26: - case 28: - case 30: - seq_playTalkText(15); - break; - case 32: - seq_playTalkText(16); - break; - case 42: - seq_playTalkText(6); - break; - default: - break; - } +int SeqPlayer_HOF::cbHOF_hand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + //NULLSUB (at least in FM-TOWNS version) return frm; } -int KyraEngine_HoF::seq_lolDemoText5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - if (_seqFrameCounter++ == 100) - seq_playTalkText(5); +int SeqPlayer_HOF::cbHOF_hand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + //NULLSUB (at least in FM-TOWNS version) return frm; } -int KyraEngine_HoF::seq_lolDemoScene6(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - while (_seqScrollTextCounter < 0x122) { - _seqEndTime = _system->getMillis() + 6 * _tickLength; - if (!_seqFrameCounter) { - _screen->loadBitmap("adtext.cps", 4, 4, 0); - _screen->loadBitmap("adtext2.cps", 6, 6, 0); - _screen->copyPageMemory(6, 0, 4, 64000, 1024); - _screen->copyPageMemory(6, 1023, 6, 0, 64000); - _seqScrollTextCounter = 0; - } +int SeqPlayer_HOF::cbHOF_funters(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + int chatFirstFrame = 0; + int chatLastFrame = 0; + uint16 voiceIndex = 0; - if (_seqFrameCounter % 175) { - _screen->setScreenPalette(_screen->getPalette(0)); - } else { - Palette &tmpPal = _screen->getPalette(2); - tmpPal.copy(_screen->getPalette(0)); + switch (frm) { + case -2: + doTransition(9); + break; - for (int i = 3; i < 0x300; i++) { - tmpPal[i] = ((int)tmpPal[i] * 120) / 64; - if (tmpPal[i] > 0x3f) - tmpPal[i] = 0x3f; - } + case 0: + _vm->sound()->playTrack(3); - seq_playTalkText(_rnd.getRandomBit()); - _screen->setScreenPalette(tmpPal); - _screen->updateScreen(); - delay(8); + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xff; + _screen->setTextColorMap(_seqTextColorMap); + + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(81, 240, 70, _seqTextColorMap, 252); + seq_printCreditsString(82, 240, 90, _seqTextColorMap, _seqTextColor[0]); + _screen->copyPage(2, 12); + seq_playTalkText(_vm->gameFlags().isTalkie ? 28 : 24); + delayUntil(frameEnd); + _seqTextColor[0] = 1; + + if (_vm->gameFlags().isTalkie) { + chatY = (_vm->gameFlags().lang == Common::FR_FRA) ? 70 : 78; + chatFirstFrame = 9; + chatLastFrame = 15; + voiceIndex = 34; + } else { + chatY = (_vm->gameFlags().lang == Common::FR_FRA) ? 78 : 70; + chatFirstFrame = 0; + chatLastFrame = 8; } + chatX = (_vm->gameFlags().lang == Common::FR_FRA) ? 84 : 88; + chatW = 100; - if (_seqFrameCounter == 40 || _seqFrameCounter == 80 || _seqFrameCounter == 150 || _seqFrameCounter == 300) - seq_playTalkText(3); + seq_playWsaSyncDialogue(22, voiceIndex, 187, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + break; - _screen->copyPage(12, 2); - seq_scrollPage(70, 130); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _seqFrameCounter++; - if (_seqFrameCounter < 128 || _seqFrameCounter > 207) - _seqScrollTextCounter++; - delayUntil(_seqEndTime); - } - _screen->copyPage(2, 12); + case 9: + case 16: + if (!((frm == 9 && !_vm->gameFlags().isTalkie) || (frm == 16 && _vm->gameFlags().isTalkie))) + break; - return 0; -} -#endif // ENABLE_LOL + _animDuration = 12; -uint32 KyraEngine_HoF::seq_activeTextsTimeLeft() { - uint32 res = 0; + if (_vm->gameFlags().lang == Common::FR_FRA) { + chatX = 80; + chatW = 112; + } else { + chatX = (_vm->gameFlags().lang == Common::DE_DEU) ? 84 : 96; + chatW = 100; + } - for (int i = 0; i < 10; i++) { - uint32 chatend = (_activeText[i].duration + _activeText[i].startTime); - uint32 curtime = _system->getMillis(); - if (_activeText[i].duration != -1 && chatend > curtime) { - chatend -= curtime; - if (res < chatend) - res = chatend; + if (_vm->gameFlags().isTalkie) { + chatFirstFrame = 0; + chatLastFrame = 8; + voiceIndex = 35; + } else { + chatFirstFrame = 9; + chatLastFrame = 15; } - } + chatY = 70; - return res; -} + seq_playWsaSyncDialogue(23, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 17; + break; -void KyraEngine_HoF::seq_processWSAs() { - for (int i = 0; i < 8; i++) { - if (_activeWSA[i].flags != -1) { - if (seq_processNextSubFrame(i)) - seq_resetActiveWSA(i); - } + default: + break; } + + _callbackCurrentFrame++; + return 0; } -void KyraEngine_HoF::seq_processText() { - int curPage = _screen->setCurPage(2); - char outputStr[70]; +int SeqPlayer_HOF::cbHOF_ferb(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + int chatFirstFrame = 0; + int chatLastFrame = 0; + uint16 voiceIndex = 0; - for (int i = 0; i < 10; i++) { - if (_activeText[i].startTime + _activeText[i].duration > _system->getMillis() && _activeText[i].duration != -1) { + switch (frm) { + case -2: + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(34, 240, _vm->gameFlags().isTalkie ? 60 : 40, _seqTextColorMap, 252); + seq_printCreditsString(35, 240, _vm->gameFlags().isTalkie ? 70 : 50, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(36, 240, _vm->gameFlags().isTalkie ? 90 : 70, _seqTextColorMap, 252); + seq_printCreditsString(37, 240, _vm->gameFlags().isTalkie ? 100 : 90, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(38, 240, _vm->gameFlags().isTalkie ? 120 : 110, _seqTextColorMap, 252); + seq_printCreditsString(39, 240, _vm->gameFlags().isTalkie ? 130 : 120, _seqTextColorMap, _seqTextColor[0]); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + seq_printCreditsString(103, 240, 130, _seqTextColorMap, _seqTextColor[0]); + delayUntil(frameEnd); + setCountDown(0); + break; - char *srcStr = seq_preprocessString(_sequenceStrings[_activeText[i].strIndex], _activeText[i].width); - int yPos = _activeText[i].y; + case 0: + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 255; + _screen->setTextColorMap(_seqTextColorMap); + break; - while (*srcStr) { - uint32 linePos = 0; - for (; *srcStr; linePos++) { - if (*srcStr == 0x0d) // Carriage return - break; - outputStr[linePos] = *srcStr; - srcStr++; - } - outputStr[linePos] = 0; - if (*srcStr == 0x0d) - srcStr++; + case 5: + if (!_vm->gameFlags().isTalkie) + seq_playTalkText(18); + _animDuration = 16; - uint8 textColor = (_activeText[i].textcolor >= 0) ? _activeText[i].textcolor : _seqTextColor[0]; - _screen->printText(outputStr, _activeText[i].x - (_screen->getTextWidth(outputStr) / 2), yPos, textColor, 0); - yPos += 10; - } + if (_vm->gameFlags().isTalkie) { + chatFirstFrame = 5; + chatLastFrame = 8; + voiceIndex = 22; } else { - _activeText[i].duration = -1; + chatLastFrame = 14; } - } + chatX = 116; + chatY = 90; + chatW = 60; - _screen->setCurPage(curPage); -} + seq_playWsaSyncDialogue(24, voiceIndex, 149, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + break; -char *KyraEngine_HoF::seq_preprocessString(const char *srcStr, int width) { - char *dstStr = _seqProcessedString; - int lineStart = 0; - int linePos = 0; + case 11: + if (_vm->gameFlags().isTalkie) + seq_playWsaSyncDialogue(24, 22, 149, 116, 90, 60, wsaObj, 11, 14, x, y); + break; - while (*srcStr) { - while (*srcStr && *srcStr != 0x20) // Space - dstStr[lineStart + linePos++] = *srcStr++; - dstStr[lineStart + linePos] = 0; + case 16: + seq_playTalkText(_vm->gameFlags().isTalkie ? 23 : 19); + _animDuration = _vm->gameFlags().isTalkie ? 20 : 16; - int len = _screen->getTextWidth(&dstStr[lineStart]); - if (width >= len && *srcStr) { - dstStr[lineStart + linePos++] = *srcStr++; + if (_vm->gameFlags().lang == Common::FR_FRA) { + chatY = 48; + chatW = 88; } else { - dstStr[lineStart + linePos] = 0x0d; // Carriage return - lineStart += linePos + 1; - linePos = 0; - if (*srcStr) - srcStr++; + chatY = 60; + chatW = 100; } - } - dstStr[lineStart + linePos] = 0; + chatX = 60; - return strlen(_seqProcessedString) ? dstStr : 0; -} + if (_vm->gameFlags().isTalkie) + voiceIndex = 36; -void KyraEngine_HoF::seq_sequenceCommand(int command) { - for (int i = 0; i < 8; i++) - seq_resetActiveWSA(i); + seq_playWsaSyncDialogue(25, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 16, 25, x, y); + _animDuration = 16; + break; - switch (command) { - case 0: - _screen->fadeToBlack(36); - _screen->getPalette(0).clear(); - _screen->getPalette(1).clear(); + default: break; + } - case 1: - seq_playTalkText(_rnd.getRandomBit()); + _callbackCurrentFrame++; + return 0; +} - _screen->getPalette(0).fill(0, 256, 0x3F); - _screen->fadePalette(_screen->getPalette(0), 16); +int SeqPlayer_HOF::cbHOF_fish(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + uint16 voiceIndex = 0; - _screen->copyPalette(1, 0); + switch (frm) { + case -2: + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + + seq_printCreditsString(40, 240, _vm->gameFlags().isTalkie ? 55 : 40, _seqTextColorMap, 252); + seq_printCreditsString(41, 240, _vm->gameFlags().isTalkie ? 65 : 50, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(42, 240, _vm->gameFlags().isTalkie ? 75 : 60, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(43, 240, _vm->gameFlags().isTalkie ? 95 : 80, _seqTextColorMap, 252); + seq_printCreditsString(44, 240, _vm->gameFlags().isTalkie ? 105 : 90, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(93, 240, _vm->gameFlags().isTalkie ? 125 : 110, _seqTextColorMap, 252); + seq_printCreditsString(94, 240, _vm->gameFlags().isTalkie ? 135 : 120, _seqTextColorMap, _seqTextColor[0]); + delayUntil(frameEnd); + setCountDown(0); break; - case 3: - _screen->copyPage(2, 0); - _screen->fadePalette(_screen->getPalette(0), 16); - _screen->copyPalette(1, 0); + case 0: + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xff; + _screen->setTextColorMap(_seqTextColorMap); break; case 4: - _screen->copyPage(2, 0); - _screen->fadePalette(_screen->getPalette(0), 36); - _screen->copyPalette(1, 0); + chatX = 94; + chatY = 42; + chatW = 100; + if (_vm->gameFlags().isTalkie) + voiceIndex = 37; + seq_playWsaSyncDialogue(26, voiceIndex, 149, chatX, chatY, chatW, wsaObj, 3, 12, x, y); break; - case 5: - _screen->copyPage(2, 0); + case 14: + seq_playTalkText(_vm->gameFlags().isTalkie ? 19 : 15); break; - case 6: - // UNUSED - // seq_loadBLD("library.bld"); + case 23: + seq_playTalkText(_vm->gameFlags().isTalkie ? 20 : 16); break; - case 7: - // UNUSED - // seq_loadBLD("marco.bld"); - break; + case 29: + chatX = (_vm->gameFlags().lang == Common::DE_DEU) ? 82 : ((_vm->gameFlags().lang == Common::FR_FRA) ? 92 : 88); + chatY = 40; + chatW = 100; - case 8: - _screen->fadeToBlack(16); - _screen->getPalette(0).clear(); - _screen->getPalette(1).clear(); + if (_vm->gameFlags().isTalkie) { + if (_vm->gameFlags().lang == Common::DE_DEU) + chatY = 35; + voiceIndex = 38; + } - delay(120 * _tickLength); + seq_playWsaSyncDialogue(27, voiceIndex, 187, chatX, chatY, chatW, wsaObj, 28, 34, x, y); break; - case 9: { - Palette &pal = _screen->getPalette(0); - for (int i = 0; i < 256; i++) { - int pv = (pal[3 * i] + pal[3 * i + 1] + pal[3 * i + 2]) / 3; - pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff; - } - - //int a = 0x100; - //int d = (0x800 << 5) - 0x100; - //pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f; + case 45: + seq_playTalkText(_vm->gameFlags().isTalkie ? 21 : 17); + break; - _screen->fadePalette(pal, 64); - _screen->copyPalette(1, 0); - } break; + case 50: + seq_playTalkText(_vm->gameFlags().isTalkie ? 29 : 25); + break; default: break; } -} - -void KyraEngine_HoF::seq_cmpFadeFrame(const char *cmpFile) { - _screen->copyPage(10, 2); - _screen->copyPage(4, 10); - _screen->clearPage(6); - _screen->loadBitmap(cmpFile, 6, 6, 0); - _screen->copyPage(12, 4); - - for (int i = 0; i < 3; i++) { - uint32 endtime = _system->getMillis() + 4 * _tickLength; - _screen->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6); - _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0); - _screen->updateScreen(); - delayUntil(endtime); - } - _screen->copyPage(4, 0); - _screen->updateScreen(); - _screen->copyPage(4, 2); - _screen->copyPage(4, 6); - _screen->copyPage(10, 4); + _callbackCurrentFrame++; + return 0; } -void KyraEngine_HoF::seq_playTalkText(uint8 chatNum) { - assert(chatNum < _sequenceSoundListSize); - - if (chatNum < 12 && !_flags.isDemo && textEnabled()) - seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160); +int SeqPlayer_HOF::cbHOF_fheep(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + int chatFirstFrame = 0; + int chatLastFrame = 0; + uint16 voiceIndex = 0; - _sound->voicePlay(_sequenceSoundList[chatNum], &_speechHandle); -} + switch (frm) { + case -2: + _screen->copyPage(12, 2); + _screen->copyPage(2, 0); + _screen->updateScreen(); + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(49, 240, 20, _seqTextColorMap, 252); + seq_printCreditsString(50, 240, 30, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(51, 240, 40, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(52, 240, 50, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(53, 240, 60, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(54, 240, 70, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(55, 240, 80, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(56, 240, 90, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(57, 240, 100, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(58, 240, 110, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(60, 240, 120, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(61, 240, 130, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(62, 240, 140, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(63, 240, 150, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(64, 240, 160, _seqTextColorMap, _seqTextColor[0]); -void KyraEngine_HoF::seq_waitForTextsTimeout() { - uint32 longest = seq_activeTextsTimeLeft() + _system->getMillis(); - uint32 now = _system->getMillis(); + delayUntil(frameEnd); + setCountDown(0); + break; - if (textEnabled()) { - if (longest > now) - delay(longest - now); - } else if (speechEnabled()) { - while (snd_voiceIsPlaying()) - delay(_tickLength); - } + case 0: + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xff; + _screen->setTextColorMap(_seqTextColorMap); + break; - seq_resetAllTextEntries(); -} + case 2: + seq_playTalkText(_vm->gameFlags().isTalkie ? 25 : 21); -void KyraEngine_HoF::seq_resetAllTextEntries() { - for (int i = 0; i < 10; i++) - _activeText[i].duration = -1; -} + if (_vm->gameFlags().lang == Common::FR_FRA) { + chatX = 92; + chatY = 72; + } else { + chatX = (_vm->gameFlags().lang == Common::DE_DEU) ? 90 : 98; + chatY = 84; + } -int KyraEngine_HoF::seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width) { - for (int i = 0; i < 10; i++) { - if (_activeText[i].duration != -1) { - if (i < 9) - continue; - else - return -1; + if (_vm->gameFlags().isTalkie) { + chatFirstFrame = 8; + chatLastFrame = 9; + voiceIndex = 39; + } else { + chatFirstFrame = 2; + chatLastFrame = -8; } + chatW = 100; + + seq_playWsaSyncDialogue(28, voiceIndex, -1, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 4; + break; - _activeText[i].strIndex = strIndex; - _activeText[i].x = posX; - _activeText[i].y = posY; - _activeText[i].duration = duration * _tickLength; - _activeText[i].width = width; - _activeText[i].startTime = _system->getMillis(); - _activeText[i].textcolor = -1; + case 9: + seq_playTalkText(_vm->gameFlags().isTalkie ? 24 : 20); + _animDuration = 100; + break; - return i; + default: + break; } - return -1; + + _callbackCurrentFrame++; + return 0; } -void KyraEngine_HoF::seq_loadNestedSequence(int wsaNum, int seqNum) { - if (_activeWSA[wsaNum].flags != -1) - return; +int SeqPlayer_HOF::cbHOF_farmer(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + uint16 voiceIndex = 0; + + switch (frm) { + case -2: + _screen->copyPage(12, 2); + _screen->copyPage(2, 0); + _screen->updateScreen(); + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(45, 240, 40, _seqTextColorMap, 252); + seq_printCreditsString(46, 240, 50, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(47, 240, 60, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(83, 240, 80, _seqTextColorMap, 252); + seq_printCreditsString(48, 240, 90, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(65, 240, 110, _seqTextColorMap, 252); + seq_printCreditsString(66, 240, 120, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(67, 240, 130, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(68, 240, 140, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(69, 240, 150, _seqTextColorMap, _seqTextColor[0]); + if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) + seq_printCreditsString(104, 240, 160, _seqTextColorMap, _seqTextColor[0]); + delayUntil(frameEnd); + setCountDown(0); + break; - NestedSequence s = _sequences->seqn[seqNum]; + case 0: + _seqTextColor[1] = 1 + (_screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 254) & 0xff); + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColorMap[1] = _seqTextColor[0] = 1 + (_screen->findLeastDifferentColor(_textColorPresets + 3, _screen->getPalette(0), 1, 254) & 0xff); + _screen->setTextColorMap(_seqTextColorMap); + seq_playTalkText(_vm->gameFlags().isTalkie ? 30 : 26); + break; - if (!_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie = new WSAMovie_v2(this); - assert(_activeWSA[wsaNum].movie); - } + case 6: + if (_vm->gameFlags().isTalkie) + seq_playTalkText(18); + break; - _activeWSA[wsaNum].movie->close(); + case 12: + if (!_vm->gameFlags().isTalkie) + seq_playTalkText(14); - _activeWSA[wsaNum].movie->open(s.wsaFile, 0, 0); + chatX = 90; + chatY = 30; + chatW = 100; - if (!_activeWSA[wsaNum].movie->opened()) { - delete _activeWSA[wsaNum].movie; - _activeWSA[wsaNum].movie = 0; - return; - } + if (_vm->gameFlags().isTalkie) { + if (_vm->gameFlags().lang == Common::FR_FRA || _vm->gameFlags().lang == Common::DE_DEU) { + chatX = 75; + chatY = 25; + } + voiceIndex = 40; + } - _activeWSA[wsaNum].endFrame = s.endFrame; - _activeWSA[wsaNum].startFrame = _activeWSA[wsaNum].currentFrame = s.startframe; - _activeWSA[wsaNum].frameDelay = s.frameDelay; - _activeWSA[wsaNum].callback = _callbackN[seqNum]; - _activeWSA[wsaNum].control = s.wsaControl; + seq_playWsaSyncDialogue(29, voiceIndex, 150, chatX, chatY, chatW, wsaObj, 12, -21, x, y); + break; - _activeWSA[wsaNum].flags = s.flags | 1; - _activeWSA[wsaNum].x = s.x; - _activeWSA[wsaNum].y = s.y; - _activeWSA[wsaNum].startupCommand = s.startupCommand; - _activeWSA[wsaNum].finalCommand = s.finalCommand; - _activeWSA[wsaNum].lastFrame = 0xffff; + default: + break; + } - seq_nestedSequenceFrame(s.startupCommand, wsaNum); + _callbackCurrentFrame++; + return 0; +} - if (!s.startupCommand) - seq_processNextSubFrame(wsaNum); +int SeqPlayer_HOF::cbHOF_fuards(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + int chatFirstFrame = 0; + int chatLastFrame = 0; + //int textCol = 0; - _activeWSA[wsaNum].nextFrame = _system->getMillis(); -} + uint16 voiceIndex = 0; -void KyraEngine_HoF::seq_nestedSequenceFrame(int command, int wsaNum) { - int xa = 0, ya = 0; - command--; - if (!_activeWSA[wsaNum].movie || skipFlag() || shouldQuit() || _abortIntroFlag) - return; + switch (frm) { + case -2: + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(70, 240, 20, _seqTextColorMap, 252); + seq_printCreditsString(71, 240, 30, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(72, 240, 40, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(73, 240, 50, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(74, 240, 60, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(75, 240, 70, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(101, 240, 80, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(102, 240, 90, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(87, 240, 100, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(88, 240, 110, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(89, 240, 120, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(90, 240, 130, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(91, 240, 140, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(92, 240, 150, _seqTextColorMap, _seqTextColor[0]); + delayUntil(frameEnd); + setCountDown(0); + break; - switch (command) { case 0: - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2); - break; + for (int i = 0; i < 0x300; i++) + _screen->getPalette(0)[i] &= 0x3f; + _seqTextColor[1] = 0xCf; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xfe; - case 1: - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1); + _screen->setTextColorMap(_seqTextColorMap); break; - case 2: - seq_waitForTextsTimeout(); - xa = -_activeWSA[wsaNum].movie->xAdd(); - ya = -_activeWSA[wsaNum].movie->yAdd(); - _activeWSA[wsaNum].movie->displayFrame(0x15, 8, xa, ya, 0, 0, 0); - seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(), - _activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2); - break; + case 6: + _animDuration = 20; - case 3: - _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); - _screen->copyPage(2, 12); - seq_cmpFadeFrame("scene2.cmp"); + if (_vm->gameFlags().isTalkie) { + chatX = 82; + //textCol = 143; + chatFirstFrame = 16; + chatLastFrame = 21; + voiceIndex = 41; + } else { + chatX = 62; + //textCol = 137; + chatFirstFrame = 9; + chatLastFrame = 13; + } + chatY = (_vm->gameFlags().lang == Common::FR_FRA || _vm->gameFlags().lang == Common::DE_DEU) ? 88 :100; + chatW = 80; + + seq_playWsaSyncDialogue(30, voiceIndex, 137, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 8; break; - case 4: - _screen->copyPage(2, 10); - _activeWSA[wsaNum].movie->displayFrame(0, 2, 0, 0, 0, 0, 0); - _screen->copyPage(2, 12); - seq_cmpFadeFrame("scene3.cmp"); + case 9: + case 16: + if (_vm->gameFlags().isTalkie) { + if (frm == 16) + break; + chatX = 64; + //textCol = 137; + chatFirstFrame = 9; + chatLastFrame = 13; + voiceIndex = 42; + } else { + if (frm == 9) + break; + chatX = 80; + //textCol = 143; + chatFirstFrame = 16; + chatLastFrame = 21; + } + chatY = 100; + chatW = 100; + + seq_playWsaSyncDialogue(31, voiceIndex, 143, chatX, chatY, chatW, wsaObj, chatFirstFrame, chatLastFrame, x, y); + if (_vm->gameFlags().isTalkie) + _animCurrentFrame = 21; break; default: break; } + + _callbackCurrentFrame++; + return 0; } -void KyraEngine_HoF::seq_animatedSubFrame(int srcPage, int dstPage, int delaytime, int steps, - int x, int y, int w, int h, int openClose, int directionFlags) { - if (openClose) { - for (int i = 1; i < steps; i++) { - uint32 endtime = _system->getMillis() + delaytime * _tickLength; +int SeqPlayer_HOF::cbHOF_firates(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + uint32 frameEnd = 0; + int chatX = 0; + int chatY = 0; + int chatW = 0; + uint16 voiceIndex = 0; - int w2 = (((w * 256) / steps) * i) / 256; - int h2 = (((h * 256) / steps) * i) / 256; + switch (frm) { + case -2: + _screen->copyPage(12, 2); + _screen->copyPage(2, 0); + _screen->updateScreen(); + doTransition(9); + frameEnd = _system->getMillis() + 480 * _vm->tickLength(); + seq_printCreditsString(76, 240, 40, _seqTextColorMap, 252); + seq_printCreditsString(77, 240, 50, _seqTextColorMap, 252); + seq_printCreditsString(78, 240, 60, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(79, 240, 70, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(80, 240, 80, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(84, 240, 100, _seqTextColorMap, 252); + seq_printCreditsString(85, 240, 110, _seqTextColorMap, _seqTextColor[0]); + seq_printCreditsString(99, 240, 130, _seqTextColorMap, 252); + seq_printCreditsString(100, 240, 140, _seqTextColorMap, _seqTextColor[0]); + delayUntil(frameEnd); + setCountDown(0); + break; - int ym = (directionFlags & 2) ? (h - h2) : 0; - int xm = (directionFlags & 1) ? (w - w2) : 0; + case 0: + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xff; + _screen->setTextColorMap(_seqTextColorMap); + break; - _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); + case 6: + seq_playTalkText(_vm->gameFlags().isTalkie ? 31 : 27); + break; - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); + case 14: + case 15: + if (!((frm == 15 && !_vm->gameFlags().isTalkie) || (frm == 14 && _vm->gameFlags().isTalkie))) + break; - _screen->copyPage(12, dstPage); - delayUntil(endtime); + seq_playTalkText(_vm->gameFlags().isTalkie ? 31 : 27); + + if (_vm->gameFlags().lang == Common::DE_DEU) { + chatX = 82; + chatY = 84; + chatW = 140; + } else { + chatX = 74; + chatY = (_vm->gameFlags().lang == Common::FR_FRA) ? 96: 108; + chatW = 80; } - _screen->wsaFrameAnimationStep(0, 0, x, y, w, h, w, h, srcPage, dstPage, 0); - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); - } else { - _screen->copyPage(12, dstPage); - for (int i = steps; i; i--) { - uint32 endtime = _system->getMillis() + delaytime * _tickLength; + if (_vm->gameFlags().isTalkie) + voiceIndex = 43; - int w2 = (((w * 256) / steps) * i) / 256; - int h2 = (((h * 256) / steps) * i) / 256; + seq_playWsaSyncDialogue(32, voiceIndex, 137, chatX, chatY, chatW, wsaObj, 14, 16, x, y); + break; - int ym = (directionFlags & 2) ? (h - h2) : 0; - int xm = (directionFlags & 1) ? (w - w2) : 0; + case 28: + seq_playTalkText(_vm->gameFlags().isTalkie ? 32 : 28); + break; - _screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0); + case 29: + seq_playTalkText(_vm->gameFlags().isTalkie ? 33 : 29); + break; - _screen->copyPage(dstPage, 6); - _screen->copyPage(dstPage, 0); - _screen->updateScreen(); + case 31: + if (_vm->gameFlags().isTalkie) + voiceIndex = 44; - _screen->copyPage(12, dstPage); - delayUntil(endtime); - } - } -} + chatX = 90; + chatY = (_vm->gameFlags().lang == Common::DE_DEU) ? 60 : 76; + chatW = 80; -void KyraEngine_HoF::seq_resetActiveWSA(int wsaNum) { - if (_activeWSA[wsaNum].flags == -1) - return; + seq_playWsaSyncDialogue(33, voiceIndex, 143, chatX, chatY, chatW, wsaObj, 31, 34, x, y); + break; - _activeWSA[wsaNum].flags = -1; - seq_nestedSequenceFrame(_activeWSA[wsaNum].finalCommand, wsaNum); - _activeWSA[wsaNum].movie->close(); -} + case 35: + _animDuration = 300; + break; -void KyraEngine_HoF::seq_unloadWSA(int wsaNum) { - if (_activeWSA[wsaNum].movie) { - _activeWSA[wsaNum].movie->close(); - delete _activeWSA[wsaNum].movie; - _activeWSA[wsaNum].movie = 0; + default: + break; } + + _callbackCurrentFrame++; + return 0; } -bool KyraEngine_HoF::seq_processNextSubFrame(int wsaNum) { - uint32 currentFrame = _activeWSA[wsaNum].currentFrame; - uint32 currentTime = _system->getMillis(); +int SeqPlayer_HOF::cbHOF_frash(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + int tmp = 0; - if (_activeWSA[wsaNum].callback && currentFrame != _activeWSA[wsaNum].lastFrame) { - _activeWSA[wsaNum].lastFrame = currentFrame; - currentFrame = (this->*_activeWSA[wsaNum].callback)(_activeWSA[wsaNum].movie, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, currentFrame); - } + switch (frm) { + case -2: + _screen->setCurPage(2); + _screen->clearCurPage(); + _screen->copyPage(2, 12); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _callbackCurrentFrame = 0; + startNestedAnimation(0, kNestedSequenceFiggle); + break; - if (_activeWSA[wsaNum].movie) { - if (_activeWSA[wsaNum].flags & 0x20) { - _activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].index, 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); - _activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].delay; - } else { - _activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 2, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, 0x4000, 0, 0); + case -1: + if (_vm->gameFlags().isTalkie) + seq_finaleActorScreen(); + _talkieFinaleExtraFlag = _vm->gameFlags().isTalkie; + break; + + case 0: + if (_callbackCurrentFrame == 1) { + _vm->sound()->playTrack(4); + _seqTextColor[1] = _screen->findLeastDifferentColor(_textColorPresets, _screen->getPalette(0), 1, 255) & 0xff; + memset(_seqTextColorMap, _seqTextColor[1], 16); + _seqTextColor[0] = _seqTextColorMap[1] = 0xff; + _screen->setTextColorMap(_seqTextColorMap); } - } + _animDuration = 10; + break; - if (_activeWSA[wsaNum].flags & 0x10) { - currentFrame = (currentTime - _activeWSA[wsaNum].nextFrame) / (_activeWSA[wsaNum].frameDelay * _tickLength); - } else { - if (((int32)(currentTime - _activeWSA[wsaNum].nextFrame) / (int32)(_activeWSA[wsaNum].frameDelay * _tickLength)) > 0) { - currentFrame++; - _activeWSA[wsaNum].nextFrame = currentTime; + case 1: + if (_callbackCurrentFrame < 20 && _talkieFinaleExtraFlag) { + _animCurrentFrame = 0; + } else { + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); + seq_playTalkText(_vm->gameFlags().isTalkie ? 26 : 22); + if (_talkieFinaleExtraFlag) { + _callbackCurrentFrame = 3; + _talkieFinaleExtraFlag = false; + } } - } + break; - bool res = false; + case 2: + _animDuration = 20; + break; - if (currentFrame >= _activeWSA[wsaNum].endFrame) { - int sw = ((_activeWSA[wsaNum].flags & 0x1e) - 2); - switch (sw) { - case 0: - res = true; - currentFrame = _activeWSA[wsaNum].endFrame; - _screen->copyPage(2, 12); - break; + case 3: + seq_playTalkText(_vm->gameFlags().isTalkie ? 27 : 23); + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); + break; - case 6: - case 8: - currentFrame = _activeWSA[wsaNum].endFrame - 1; - break; + case 4: + _animDuration = 10; + break; + + case 5: + seq_playTalkText(_vm->gameFlags().isTalkie ? 27 : 23); + tmp = _callbackCurrentFrame / 6; + if (tmp == 2) + _animDuration = _vm->gameFlags().isTalkie ? 7 : (1 + _vm->_rnd.getRandomNumberRng(1, 10)); + else if (tmp < 2) + _animDuration = _vm->gameFlags().isTalkie ? 500 : (300 + _vm->_rnd.getRandomNumberRng(1, 300)); + break; + + case 6: + _animDuration = 10; + tmp = _callbackCurrentFrame / 6; + if (tmp == 2) + _animCurrentFrame = 4; + else if (tmp < 2) + _animCurrentFrame = 0; + break; + + case 7: + _callbackCurrentFrame = 0; + _animDuration = 5; + seq_playTalkText(_vm->gameFlags().isTalkie ? 26 : 22); + break; - case 2: - case 10: - currentFrame = _activeWSA[wsaNum].startFrame; - break; + case 11: + if (_callbackCurrentFrame < 8) + _animCurrentFrame = 8; + break; - default: - currentFrame = _activeWSA[wsaNum].endFrame - 1; - res = true; - } + default: + break; } - _activeWSA[wsaNum].currentFrame = currentFrame & 0xffff; - return res; + _callbackCurrentFrame++; + return 0; } -void KyraEngine_HoF::seq_printCreditsString(uint16 strIndex, int x, int y, const uint8 *colorMap, uint8 textcolor) { - uint8 colormap[16]; - if (skipFlag() || shouldQuit() || _abortIntroFlag || _menuChoice) - return; - - Screen::FontId of = _screen->setFont(Screen::FID_8_FNT); - - memset(&_screen->getPalette(0)[0x2fa], 0x3f, 6); - _screen->getPalette(0)[0x2f6] = 0x3f; - _screen->getPalette(0)[0x2f5] = 0x20; - _screen->getPalette(0)[0x2f4] = 0x30; - colormap[0] = colorMap[0]; - colormap[1] = 0xfd; - memcpy(&colormap[2], &colorMap[2], 14); - uint8 seqTextColor0 = _seqTextColor[0]; - - _seqTextColor[0] = 0xfd; - _screen->setTextColorMap(colormap); - seq_resetAllTextEntries(); - seq_setTextEntry(strIndex, x, y, 0x80, 0x78); - seq_processText(); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[textcolor * 3]; - _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[textcolor * 3 + 1]; - _screen->getPalette(0)[0x2f9] = _screen->getPalette(0)[textcolor * 3 + 2]; - _screen->fadePalette(_screen->getPalette(0), 0x18); +int SeqPlayer_HOF::cbHOF_figgle(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (_callbackCurrentFrame == 10) + setCountDown(0); + if (_callbackCurrentFrame == 10 || _callbackCurrentFrame == 5 || _callbackCurrentFrame == 7) + seq_playTalkText(_vm->gameFlags().isTalkie ? 45 : 30); - _seqTextColor[0] = textcolor; - _screen->setTextColorMap(colorMap); - seq_resetAllTextEntries(); - seq_setTextEntry(strIndex, x, y, 0x80, 0x78); - seq_processText(); - _screen->copyPage(2, 0); - _screen->updateScreen(); - _screen->getPalette(0)[0x2f7] = _screen->getPalette(0)[0x2f8] = _screen->getPalette(0)[0x2f9] = 0; - _screen->fadePalette(_screen->getPalette(0), 1); - _screen->copyPage(2, 12); - seq_resetAllTextEntries(); + _callbackCurrentFrame++; + return frm; +} - _seqTextColor[0] = seqTextColor0; +int SeqPlayer_HOF::cbHOFDEMO_virgin(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!frm) + delayTicks(50); + return 0; +} - _screen->setFont(of); +int SeqPlayer_HOF::cbHOFDEMO_westwood(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!frm) + _vm->sound()->playTrack(2); + return 0; } -void KyraEngine_HoF::seq_playWsaSyncDialogue(uint16 strIndex, uint16 vocIndex, int textColor, int x, int y, int width, WSAMovie_v2 *wsa, int firstframe, int lastframe, int wsaXpos, int wsaYpos) { - int dur = int(strlen(_sequenceStrings[strIndex])) * (_flags.isTalkie ? 7 : 15); - if (textEnabled()) { - int entry = seq_setTextEntry(strIndex, x, y, dur, width); - _activeText[entry].textcolor = textColor; +int SeqPlayer_HOF::cbHOFDEMO_title(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!frm) { + _vm->sound()->playTrack(3); + } else if (frm == 25) { + delayTicks(60); + setCountDown(0); + doTransition(0); } - _seqWsaChatTimeout = _system->getMillis() + dur * _tickLength; - int curframe = firstframe; + return 0; +} - if (vocIndex && speechEnabled()) { - while (_sound->voiceIsPlaying() && !skipFlag()) - delay(4); - seq_playTalkText(vocIndex); +int SeqPlayer_HOF::cbHOFDEMO_hill(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!frm) { + _vm->sound()->playTrack(4); + } else if (frm == 25) { + startNestedAnimation(0, kNestedSequenceHoFDemoWater); + _animDuration--; + } else if (frm > 25 && frm < 50) { + if (_animDuration > 3) + _animDuration--; + } else if (frm == 95) { + _animDuration = 70; + } else if (frm == 96) { + _animDuration = 7; + } else if (frm == 129) { + closeNestedAnimation(0); } - while (_system->getMillis() < _seqWsaChatTimeout && !(_abortIntroFlag || skipFlag())) { - if (lastframe < 0) { - int t = ABS(lastframe); - if (t < curframe) - curframe = t; - } + return 0; +} - if (ABS(lastframe) < curframe) - curframe = firstframe; +int SeqPlayer_HOF::cbHOFDEMO_outhome(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (frm) { + case 12: + seq_playTalkText(4); + break; - _seqWsaChatFrameTimeout = _seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength; - if (wsa) - wsa->displayFrame(curframe % wsa->frames(), 2, wsaXpos, wsaYpos, 0, 0, 0); + case 32: + seq_playTalkText(7); + break; - _screen->copyPage(2, 12); + case 36: + seq_playTalkText(10); + break; - seq_processText(); + case 57: + seq_playTalkText(9); + break; - uint32 tm = _system->getMillis(); - if (_seqWsaChatFrameTimeout > tm && _seqWsaChatTimeout > tm) - delay(MIN(_seqWsaChatFrameTimeout - tm, _seqWsaChatTimeout - tm)); + case 80: + case 96: + case 149: + _animDuration = 70; + break; - if (speechEnabled() && !textEnabled() && !snd_voiceIsPlaying()) - break; + case 81: + case 97: + _animDuration = 5; + break; - _screen->copyPage(2, 0); - _screen->updateScreen(); - curframe++; + case 110: + seq_playTalkText(5); + break; + + case 137: + seq_playTalkText(6); + break; } - if (_abortIntroFlag || skipFlag()) - _sound->voiceStop(); + return 0; +} - if (ABS(lastframe) < curframe) - curframe = ABS(lastframe); +int SeqPlayer_HOF::cbHOFDEMO_wharf(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (!_callbackCurrentFrame) + startNestedAnimation(0, kNestedSequenceHoFDemoWharf2); - if (curframe == firstframe) - curframe++; + switch (frm) { + case 0: + seq_playTalkText(11); + break; - _seqWsaCurrentFrame = curframe; -} + case 5: + if ((_callbackCurrentFrame / 8) <= 2 || _animSlots[0].flags != -1) + _animCurrentFrame = 0; + else + closeNestedAnimation(0); + break; -void KyraEngine_HoF::seq_displayScrollText(uint8 *data, const ScreenDim *d, int tempPage1, int tempPage2, int speed, - int step, Screen::FontId fid1, Screen::FontId fid2, const uint8 *shapeData, const char *const *specialData) { - if (!data) - return; + case 6: + closeNestedAnimation(0); + break; - static const char mark[] = { 5, 13, 0 }; + case 8: + case 10: + seq_playTalkText(2); + break; - _screen->clearPage(tempPage1); - _screen->clearPage(tempPage2); - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, 0, tempPage1); + case 13: + seq_playTalkText(7); + break; - struct ScrollTextData { - int16 x; - int16 y; - uint8 *text; - byte unk1; - byte height; - byte adjust; + case 16: + seq_playTalkText(12); + break; - ScrollTextData() { - x = 0; // 0 11 - y = 0; // 2 13 - text = 0; // 4 15 - unk1 = 0; // 8 19 - height = 0; // 9 20 - adjust = 0; // 10 21 - } - }; + default: + break; + } - ScrollTextData *textData = new ScrollTextData[36]; - uint8 *ptr = data; + _callbackCurrentFrame++; + return 0; +} - bool loop = true; - int cnt = 0; +int SeqPlayer_HOF::cbHOFDEMO_dinob(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 0) { + if (!(_callbackCurrentFrame/8)) { + startNestedAnimation(0, kNestedSequenceHoFDemoDinob2); + _animCurrentFrame = 0; + } + } else if (frm == 3) { + if (_animSlots[0].flags != -1) { + _animCurrentFrame = 0; + } else { + closeNestedAnimation(0); + _screen->copyPage(2, 12); + } + } else if (frm == 4) { + closeNestedAnimation(0); + } - while (loop) { - _seqSubFrameEndTimeInternal = _system->getMillis() + speed * _tickLength; + _callbackCurrentFrame++; + return 0; +} - while (cnt < 35 && *ptr) { - uint16 cH; +int SeqPlayer_HOF::cbHOFDEMO_fisher(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (((_system->getMillis() - _fisherAnimCurTime) / (5 * _vm->tickLength())) > 0) { + _fisherAnimCurTime = _system->getMillis(); + if (!_callbackCurrentFrame) { + startNestedAnimation(0, kNestedSequenceHoFDemoBail); + startNestedAnimation(1, kNestedSequenceHoFDemoDig); + } - if (cnt) - cH = textData[cnt].y + textData[cnt].height + (textData[cnt].height >> 3); - else - cH = d->h; + if (_seqScrollTextCounter >= 0x18f && !_callbackCurrentFrame) + return 0; - char *str = (char *)ptr; + if (!_callbackCurrentFrame) { + _screen->loadBitmap("adtext.cps", 4, 4, 0); + _screen->loadBitmap("adtext2.cps", 6, 6, 0); + _screen->copyPageMemory(6, 0, 4, 64000, 1024); + _screen->copyPageMemory(6, 1023, 6, 0, 64000); + _seqScrollTextCounter = 0; + } - ptr = (uint8 *)strpbrk(str, mark); - if (!ptr) - ptr = (uint8 *)strchr(str, 0); + seq_scrollPage(24, 144); + _callbackCurrentFrame++; + if (_callbackCurrentFrame < 0x256 || _callbackCurrentFrame > 0x31c) { + if (_callbackCurrentFrame < 0x174 || _callbackCurrentFrame > 0x1d7) { + if (_callbackCurrentFrame < 0x84 || _callbackCurrentFrame > 0xe7) { + _seqScrollTextCounter++; + } + } + } - textData[cnt + 1].unk1 = *ptr; - *ptr = 0; - if (textData[cnt + 1].unk1) - ptr++; + if (_callbackCurrentFrame > 0x31e) { + closeNestedAnimation(0); + closeNestedAnimation(1); + setCountDown(0); + _screen->copyPage(2, 12); + } - if (*str == 3 || *str == 4) - textData[cnt + 1].adjust = *str++; - else - textData[cnt + 1].adjust = 0; + } else { + seq_scrollPage(24, 144); + } + return 0; +} - _screen->setFont(fid1); +int SeqPlayer_HOF::cbHOFDEMO_wharf2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 69) + _animCurrentFrame = 8; - if (*str == 1) { - _screen->setFont(fid2); - str++; - } else if (*str == 2) { - str++; - } + return frm; +} - textData[cnt + 1].height = _screen->getFontHeight(); +int SeqPlayer_HOF::cbHOFDEMO_dinob2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (frm) { + case 19: + seq_playTalkText(13); + break; - switch (textData[cnt + 1].adjust) { - case 3: - textData[cnt + 1].x = 157 - _screen->getTextWidth(str); - break; - case 4: - textData[cnt + 1].x = 161; - break; - default: - textData[cnt + 1].x = (((d->w << 3) - _screen->getTextWidth(str)) >> 1) + 1; - } + case 54: + seq_playTalkText(15); + break; - if (textData[cnt].unk1 == 5) - cH -= (textData[cnt].height + (textData[cnt].height >> 3)); + case 61: + seq_playTalkText(16); + break; - textData[cnt + 1].y = cH; - textData[cnt + 1].text = (uint8 *)str; - cnt++; - } + case 69: + seq_playTalkText(14); + break; - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage1, tempPage2); + case 77: + seq_playTalkText(13); + break; - int cnt2 = 0; - bool palCycle = 0; + case 79: + _animCurrentFrame = 4; + break; + } - while (cnt2 < cnt) { - const char *str = (const char *)textData[cnt2 + 1].text; - const char *str2 = str; - int16 cW = textData[cnt2 + 1].x - 10; - int16 cH = textData[cnt2 + 1].y; - int x = (d->sx << 3) + cW; - int y = d->sy + cH; - int col1 = 255; + return frm; +} - if (cH < d->h) { - _screen->setCurPage(tempPage2); - _screen->setFont(fid1); - if (textData[cnt2 + 1].height != _screen->getFontHeight()) - _screen->setFont(fid2); +int SeqPlayer_HOF::cbHOFDEMO_water(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (frm == 1) + seq_playTalkText(11); + return frm; +} - if (specialData) { - if (!strcmp(str, specialData[0])) { - col1 = 112; - char cChar[2] = " "; - while (*str2) { - cChar[0] = *str2; - _screen->printText(cChar, x, y, col1++, 0); - x += _screen->getCharWidth((uint8)*str2++); - } - palCycle = true; - } else if (!strcmp(str, specialData[1])) { - col1 = 133; - char cChar[2] = " "; - while (*str2) { - cChar[0] = *str2; - _screen->printText(cChar, x, y, col1--, 0); - x += _screen->getCharWidth((uint8)*str2++); - } - palCycle = true; - } else { - _screen->printText(str, x, y, col1, 0); - } - } else { - _screen->printText(str, x, y, col1, 0); - } - _screen->setCurPage(0); - } +int SeqPlayer_HOF::cbHOFDEMO_bail(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + return frm; +} - textData[cnt2 + 1].y -= step; - cnt2++; - } +int SeqPlayer_HOF::cbHOFDEMO_dig(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + return frm; +} - _screen->copyRegion(d->sx << 3, d->sy, d->sx << 3, d->sy, d->w << 3, d->h, tempPage2, 0); - _screen->updateScreen(); +#ifdef ENABLE_LOL +int SeqPlayer_HOF::cbLOLDEMO_scene1(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + Palette &tmpPal = _screen->getPalette(2); - if (textData[1].y < -10) { - textData[1].text += strlen((char *)textData[1].text); - textData[1].text[0] = textData[1].unk1; - cnt--; - memcpy(&textData[1], &textData[2], cnt * sizeof(ScrollTextData)); + if (!(_callbackCurrentFrame % 100)) { + if (_callbackCurrentFrame == 0) { + _vm->sound()->haltTrack(); + _vm->sound()->playTrack(6); } + tmpPal.copy(_screen->getPalette(0)); - if (palCycle) { - for (int col = 133; col > 112; col--) - _screen->getPalette(0).copy(_screen->getPalette(0), col - 1, 1, col); - _screen->getPalette(0).copy(_screen->getPalette(0), 133, 1, 112); - _screen->setScreenPalette(_screen->getPalette(0)); + for (int i = 3; i < 0x300; i++) { + tmpPal[i] = ((int)tmpPal[i] * 120) / 64; + if (tmpPal[i] > 0x3f) + tmpPal[i] = 0x3f; } - delayUntil(_seqSubFrameEndTimeInternal); + seq_playTalkText(_vm->_rnd.getRandomBit()); + _screen->setScreenPalette(tmpPal); + _screen->updateScreen(); + _vm->delay(8); + } else { + _screen->setScreenPalette(_screen->getPalette(0)); + _screen->updateScreen(); + if (_callbackCurrentFrame == 40) + seq_playTalkText(3); + } - if ((cnt < 36) && ((d->sy + d->h) > (textData[cnt].y + textData[cnt].height)) && !skipFlag()) { - resetSkipFlag(); - delay(_tickLength * 500); - cnt = 0; - } + _callbackCurrentFrame++; + return frm; +} - if (!cnt || skipFlag()) - loop = false; +int SeqPlayer_HOF::cbLOLDEMO_scene2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame - 17) { + case 0: + _animDuration = 8; + break; + case 3: + case 6: + case 9: + seq_playTalkText(8); + break; + case 15: + seq_playTalkText(9); + break; + case 18: + seq_playTalkText(2); + break; + default: + break; } + _callbackCurrentFrame++; + return frm; +} - _sound->beginFadeOut(); - _screen->fadeToBlack(); - - _abortIntroFlag= false; - resetSkipFlag(); +int SeqPlayer_HOF::cbLOLDEMO_scene3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (_callbackCurrentFrame == 1) + seq_playTalkText(6); + else if (frm == 26) + seq_playTalkText(7); - delete[] textData; + _callbackCurrentFrame++; + return frm; } -void KyraEngine_HoF::seq_scrollPage(int bottom, int top) { - int dstY, dstH, srcH; +int SeqPlayer_HOF::cbLOLDEMO_scene4(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame) { + case 11: + case 14: + case 17: + case 20: + seq_playTalkText(8); + break; + case 22: + seq_playTalkText(11); + break; + case 24: + seq_playTalkText(8); + break; + case 30: + seq_playTalkText(15); + break; + case 34: + seq_playTalkText(14); + break; + case 38: + seq_playTalkText(13); + break; + case 42: + seq_playTalkText(12); + break; + default: + break; + } - static const ScreenDim d = { 0x00, 0x00, 0x28, 0x320, 0xFF, 0xFE, 0x00, 0x00 }; + _callbackCurrentFrame++; + return frm; +} - if (_seqScrollTextCounter - (top - 1) < 0) { - dstY = top - _seqScrollTextCounter; - dstH = _seqScrollTextCounter; - srcH = 0; - } else { - dstY = 0; - srcH = _seqScrollTextCounter - top; - dstH = (400 - srcH <= top) ? 400 - srcH : top; +int SeqPlayer_HOF::cbLOLDEMO_scene5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + switch (_callbackCurrentFrame++) { + case 0: + case 4: + case 6: + case 8: + case 10: + case 14: + case 16: + case 18: + case 20: + case 22: + case 24: + case 26: + case 28: + case 30: + seq_playTalkText(15); + break; + case 32: + seq_playTalkText(16); + break; + case 42: + seq_playTalkText(6); + break; + default: + break; } + return frm; +} - if (dstH > 0) { - if (_demoAnimData) { - for (int i = 0; i < 4; i++) { - const ItemAnimData_v1 *def = &_demoAnimData[i]; - ActiveItemAnim *a = &_activeItemAnim[i]; - - _screen->fillRect(12, def->y - 8, 28, def->y + 8, 0, 4); - _screen->drawShape(4, getShapePtr(def->itemIndex + def->frames[a->currentFrame]), 12, def->y - 8, 0, 0); - if (_seqFrameCounter % 2 == 0) - a->currentFrame = (a->currentFrame + 1) % 20; +int SeqPlayer_HOF::cbLOLDEMO_text5(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + if (_callbackCurrentFrame++ == 100) + seq_playTalkText(5); + return frm; +} + +int SeqPlayer_HOF::cbLOLDEMO_scene6(WSAMovie_v2 *wsaObj, int x, int y, int frm) { + while (_seqScrollTextCounter < 0x122) { + setCountDown(6); + if (!_callbackCurrentFrame) { + _screen->loadBitmap("adtext.cps", 4, 4, 0); + _screen->loadBitmap("adtext2.cps", 6, 6, 0); + _screen->copyPageMemory(6, 0, 4, 64000, 1024); + _screen->copyPageMemory(6, 1023, 6, 0, 64000); + _seqScrollTextCounter = 0; + } + + if (_callbackCurrentFrame % 175) { + _screen->setScreenPalette(_screen->getPalette(0)); + } else { + Palette &tmpPal = _screen->getPalette(2); + tmpPal.copy(_screen->getPalette(0)); + + for (int i = 3; i < 0x300; i++) { + tmpPal[i] = ((int)tmpPal[i] * 120) / 64; + if (tmpPal[i] > 0x3f) + tmpPal[i] = 0x3f; } + + seq_playTalkText(_vm->_rnd.getRandomBit()); + _screen->setScreenPalette(tmpPal); + _screen->updateScreen(); + _vm->delay(8); } - _screen->copyRegionEx(4, 0, srcH, 2, 2, dstY + bottom, 320, dstH, &d); + + if (_callbackCurrentFrame == 40 || _callbackCurrentFrame == 80 || _callbackCurrentFrame == 150 || _callbackCurrentFrame == 300) + seq_playTalkText(3); + + _screen->copyPage(12, 2); + seq_scrollPage(70, 130); + _screen->copyPage(2, 0); + _screen->updateScreen(); + _callbackCurrentFrame++; + if (_callbackCurrentFrame < 128 || _callbackCurrentFrame > 207) + _seqScrollTextCounter++; + + while (countDownRunning()) + delayTicks(1); } + _screen->copyPage(2, 12); + + return 0; } +#endif // ENABLE_LOL + +#undef CASE_ALT + +const uint8 SeqPlayer_HOF::_textColorPresets[] = { 0x01, 0x01, 0x00, 0x3f, 0x3f, 0x3f }; void KyraEngine_HoF::seq_showStarcraftLogo() { WSAMovie_v2 *ci = new WSAMovie_v2(this); assert(ci); _screen->clearPage(2); _res->loadPakFile("INTROGEN.PAK"); - int endframe = ci->open("ci.wsa", 0, &_screen->getPalette(0)); + int endframe = ci->open("CI.WSA", 0, &_screen->getPalette(0)); _res->unloadPakFile("INTROGEN.PAK"); if (!ci->opened()) { delete ci; @@ -2736,20 +3374,28 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { _screen->copyPage(2, 0); _screen->fadeFromBlack(); for (int i = 1; i < endframe; i++) { - _seqEndTime = _system->getMillis() + 50; + uint32 end = _system->getMillis() + 50; if (skipFlag()) break; ci->displayFrame(i, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(_seqEndTime - _system->getMillis()); + uint32 cur = _system->getMillis(); + if (end > cur) + delay(end - cur); + else + updateInput(); } if (!skipFlag()) { - _seqEndTime = _system->getMillis() + 50; + uint32 end = _system->getMillis() + 50; ci->displayFrame(0, 2, 0, 0, 0, 0, 0); _screen->copyPage(2, 0); _screen->updateScreen(); - delay(_seqEndTime - _system->getMillis()); + uint32 cur = _system->getMillis(); + if (end > cur) + delay(end - cur); + else + updateInput(); } _screen->fadeToBlack(); _screen->showMouse(); @@ -2758,67 +3404,39 @@ void KyraEngine_HoF::seq_showStarcraftLogo() { delete ci; } -void KyraEngine_HoF::seq_init() { - _seqProcessedString = new char[200]; - _seqWsa = new WSAMovie_v2(this); - _activeWSA = new ActiveWSA[8]; - _activeText = new ActiveText[10]; - - _res->unloadAllPakFiles(); - _res->loadPakFile(StaticResource::staticDataFilename()); - _res->loadFileList(_sequencePakList, _sequencePakListSize); - - if (_flags.platform == Common::kPlatformPC98) - _sound->loadSoundFile("SOUND.DAT"); - - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_GOLDFONT_FNT); - - if (_flags.gameID == GI_LOL) - return; - - if (_flags.isDemo && !_flags.isTalkie) { - _demoAnimData = _staticres->loadShapeAnimData_v1(k2SeqplayShapeAnimData, _itemAnimDefinitionSize); - uint8 *shp = _res->fileData("icons.shp", 0); - uint32 outsize = READ_LE_UINT16(shp + 4); - _animShapeFiledata = new uint8[outsize]; - Screen::decodeFrame4(shp + 10, _animShapeFiledata, outsize); - delete[] shp; - - for (int i = 0; i < 20; i++) - addShapeToPool(_screen->getPtrToShape(_animShapeFiledata, i), i); - } else { - const MainMenu::StaticData data = { - { _sequenceStrings[97], _sequenceStrings[96], _sequenceStrings[95], _sequenceStrings[98], 0 }, - { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6 }, - { 0xd8, 0xda, 0xd9, 0xd8 }, - (_flags.lang == Common::JA_JPN) ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT, 240 - }; - _menu = new MainMenu(this); - _menu->init(data, MainMenu::Animation()); - } +int KyraEngine_HoF::seq_playIntro() { + bool startupSaveLoadable = saveFileLoadable(0); + return SeqPlayer_HOF(this, _screen, _system, startupSaveLoadable).play(kSequenceVirgin, startupSaveLoadable? kSequenceTitle : kSequenceNoLooping); } -void KyraEngine_HoF::seq_uninit() { - delete[] _seqProcessedString; - _seqProcessedString = NULL; - - delete[] _activeWSA; - _activeWSA = NULL; +int KyraEngine_HoF::seq_playOutro() { + return SeqPlayer_HOF(this, _screen, _system).play(kSequenceFunters, kSequenceFrash); +} - delete[] _activeText; - _activeText = NULL; +int KyraEngine_HoF::seq_playDemo() { + SeqPlayer_HOF(this, _screen, _system).play(kSequenceHoFDemoVirgin, kSequenceHoFDemoVirgin); + return 4; +} - delete _seqWsa; - _seqWsa = NULL; +void KyraEngine_HoF::seq_pausePlayer(bool toggle) { + SeqPlayer_HOF *activePlayer = SeqPlayer_HOF::instance(); + if (activePlayer) + activePlayer->pause(toggle); +} - delete[] _animShapeFiledata; - _animShapeFiledata = 0; +#ifdef ENABLE_LOL +int LoLEngine::playDemo() { + SeqPlayer_HOF(this, _screen, _system).play(kSequenceLoLDemoScene1, kSequenceLoLDemoScene1); + return -1; +} - delete _menu; - _menu = 0; - _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT); +void LoLEngine::pauseDemoPlayer(bool toggle) { + SeqPlayer_HOF *activePlayer = SeqPlayer_HOF::instance(); + if (activePlayer) + activePlayer->pause(toggle); } +#endif // ENABLE_LOL #pragma mark - #pragma mark - Ingame sequences diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index a06f2077ba..485120a49d 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -36,10 +36,15 @@ namespace Kyra { #pragma mark - Intro int LoLEngine::processPrologue() { - setupPrologueData(true); - - if (!saveFileLoadable(0) || _flags.isDemo) - showIntro(); + // There are two non-interactive demos (one which plays the intro and another one) which plays a number of specific scenes. + // We try to identify the latter one by looking for a specific file. + if (_flags.isDemo && _res->exists("scene1.cps")) { + return playDemo(); + } else { + setupPrologueData(true); + if (!saveFileLoadable(0) || _flags.isDemo) + showIntro(); + } if (_flags.isDemo) { _screen->fadePalette(_screen->getPalette(1), 30, 0); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 00dc4f9e13..04e111b51e 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -31,6 +31,7 @@ #include "kyra/gui_lok.h" #include "kyra/gui_hof.h" #include "kyra/gui_mr.h" +#include "kyra/sequences_hof.h" #include "kyra/sound_intern.h" #include "common/endian.h" @@ -245,8 +246,8 @@ bool StaticResource::init() { { kAmigaSfxTable, proc(loadAmigaSfxTable), proc(freeAmigaSfxTable) }, { kRawData, proc(loadRawData), proc(freeRawData) }, - { k2SeqData, proc(loadHofSequenceData), proc(freeHofSequenceData) }, - { k2ShpAnimDataV1, proc(loadShapeAnimData_v1), proc(freeHofShapeAnimDataV1) }, + { k2SeqData, proc(loadHoFSequenceData), proc(freeHoFSequenceData) }, + { k2SeqItemAnimData, proc(loadHoFSeqItemAnimData), proc(freeHoFSeqItemAnimData) }, { k2ItemAnimDefinition, proc(loadItemAnimDefinition), proc(freeItemAnimDefinition) }, #ifdef ENABLE_LOL @@ -308,12 +309,12 @@ const Room *StaticResource::loadRoomTable(int id, int &entries) { return (const Room *)getData(id, StaticResource::kRoomList, entries); } -const HofSeqData *StaticResource::loadHofSequenceData(int id, int &entries) { - return (const HofSeqData *)getData(id, k2SeqData, entries); +const HoFSeqData *StaticResource::loadHoFSequenceData(int id, int &entries) { + return (const HoFSeqData *)getData(id, k2SeqData, entries); } -const ItemAnimData_v1 *StaticResource::loadShapeAnimData_v1(int id, int &entries) { - return (const ItemAnimData_v1 *)getData(id, k2ShpAnimDataV1, entries); +const HoFSeqItemAnimData *StaticResource::loadHoFSeqItemAnimData(int id, int &entries) { + return (const HoFSeqItemAnimData *)getData(id, k2SeqItemAnimData, entries); } const ItemAnimDefinition *StaticResource::loadItemAnimDefinition(int id, int &entries) { @@ -513,12 +514,12 @@ bool StaticResource::loadRoomTable(Common::SeekableReadStream &stream, void *&pt return true; } -bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size) { +bool StaticResource::loadHoFSequenceData(Common::SeekableReadStream &stream, void *&ptr, int &size) { int numSeq = stream.readUint16BE(); uint32 offset = 2; - Sequence *tmp_s = new Sequence[numSeq]; + HoFSequence *tmp_s = new HoFSequence[numSeq]; - size = sizeof(HofSeqData) + numSeq * (sizeof(Sequence) + 28); + size = sizeof(HoFSeqData) + numSeq * (sizeof(HoFSequence) + 28); for (int i = 0; i < numSeq; i++) { stream.seek(offset, SEEK_SET); offset += 2; @@ -529,22 +530,22 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi stream.read(const_cast(tmp_s[i].wsaFile), 14); tmp_s[i].cpsFile = new char[14]; stream.read(const_cast(tmp_s[i].cpsFile), 14); - tmp_s[i].startupCommand = stream.readByte(); - tmp_s[i].finalCommand = stream.readByte(); + tmp_s[i].fadeInTransitionType = stream.readByte(); + tmp_s[i].fadeOutTransitionType = stream.readByte(); tmp_s[i].stringIndex1 = stream.readUint16BE(); tmp_s[i].stringIndex2 = stream.readUint16BE(); tmp_s[i].startFrame = stream.readUint16BE(); tmp_s[i].numFrames = stream.readUint16BE(); - tmp_s[i].frameDelay = stream.readUint16BE(); + tmp_s[i].duration = stream.readUint16BE(); tmp_s[i].xPos = stream.readUint16BE(); tmp_s[i].yPos = stream.readUint16BE(); - tmp_s[i].duration = stream.readUint16BE(); + tmp_s[i].timeout = stream.readUint16BE(); } stream.seek(offset, SEEK_SET); offset += 2; int numSeqN = stream.readUint16BE(); - NestedSequence *tmp_n = new NestedSequence[numSeqN]; - size += (numSeqN * (sizeof(NestedSequence) + 14)); + HoFNestedSequence *tmp_n = new HoFNestedSequence[numSeqN]; + size += (numSeqN * (sizeof(HoFNestedSequence) + 14)); for (int i = 0; i < numSeqN; i++) { stream.seek(offset, SEEK_SET); offset += 2; @@ -559,8 +560,8 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi tmp_n[i].x = stream.readUint16BE(); tmp_n[i].y = stream.readUint16BE(); uint16 ctrlOffs = stream.readUint16BE(); - tmp_n[i].startupCommand = stream.readUint16BE(); - tmp_n[i].finalCommand = stream.readUint16BE(); + tmp_n[i].fadeInTransitionType = stream.readUint16BE(); + tmp_n[i].fadeOutTransitionType = stream.readUint16BE(); if (ctrlOffs) { stream.seek(ctrlOffs, SEEK_SET); @@ -580,21 +581,21 @@ bool StaticResource::loadHofSequenceData(Common::SeekableReadStream &stream, voi } } - HofSeqData *loadTo = new HofSeqData; + HoFSeqData *loadTo = new HoFSeqData; assert(loadTo); loadTo->seq = tmp_s; - loadTo->seqn = tmp_n; + loadTo->nestedSeq = tmp_n; loadTo->numSeq = numSeq; - loadTo->numSeqn = numSeqN; + loadTo->numNestedSeq = numSeqN; ptr = loadTo; return true; } -bool StaticResource::loadShapeAnimData_v1(Common::SeekableReadStream &stream, void *&ptr, int &size) { +bool StaticResource::loadHoFSeqItemAnimData(Common::SeekableReadStream &stream, void *&ptr, int &size) { size = stream.readByte(); - ItemAnimData_v1 *loadTo = new ItemAnimData_v1[size]; + HoFSeqItemAnimData *loadTo = new HoFSeqItemAnimData[size]; assert(loadTo); for (int i = 0; i < size; i++) { @@ -670,8 +671,8 @@ void StaticResource::freeRoomTable(void *&ptr, int &size) { size = 0; } -void StaticResource::freeHofSequenceData(void *&ptr, int &size) { - HofSeqData *h = (HofSeqData *)ptr; +void StaticResource::freeHoFSequenceData(void *&ptr, int &size) { + HoFSeqData *h = (HoFSeqData *)ptr; for (int i = 0; i < h->numSeq; i++) { delete[] h->seq[i].wsaFile; @@ -679,19 +680,19 @@ void StaticResource::freeHofSequenceData(void *&ptr, int &size) { } delete[] h->seq; - for (int i = 0; i < h->numSeqn; i++) { - delete[] h->seqn[i].wsaFile; - delete[] h->seqn[i].wsaControl; + for (int i = 0; i < h->numNestedSeq; i++) { + delete[] h->nestedSeq[i].wsaFile; + delete[] h->nestedSeq[i].wsaControl; } - delete[] h->seqn; + delete[] h->nestedSeq; delete h; ptr = 0; size = 0; } -void StaticResource::freeHofShapeAnimDataV1(void *&ptr, int &size) { - ItemAnimData_v1 *d = (ItemAnimData_v1 *)ptr; +void StaticResource::freeHoFSeqItemAnimData(void *&ptr, int &size) { + HoFSeqItemAnimData *d = (HoFSeqItemAnimData *)ptr; for (int i = 0; i < size; i++) delete[] d[i].frames; delete[] d; @@ -994,9 +995,7 @@ void KyraEngine_LoK::loadMainScreen(int page) { void KyraEngine_HoF::initStaticResource() { int tmpSize = 0; - _sequencePakList = _staticres->loadStrings(k2SeqplayPakFiles, _sequencePakListSize); _ingamePakList = _staticres->loadStrings(k2IngamePakFiles, _ingamePakListSize); - _sequenceStrings = _staticres->loadStrings(k2SeqplayStrings, _sequenceStringsSize); _ingameSoundList = _staticres->loadStrings(k2IngameSfxFiles, _ingameSoundListSize); _ingameSoundIndex = (const uint16 *)_staticres->loadRawData(k2IngameSfxIndex, _ingameSoundIndexSize); _musicFileListIntro = _staticres->loadStrings(k2SeqplayIntroTracks, _musicFileListIntroSize); @@ -1009,33 +1008,6 @@ void KyraEngine_HoF::initStaticResource() { _ingameTimJpStr = _staticres->loadStrings(k2IngameTimJpStrings, _ingameTimJpStrSize); _itemAnimDefinition = _staticres->loadItemAnimDefinition(k2IngameShapeAnimData, _itemAnimDefinitionSize); - // replace sequence talkie files with localized versions - const char *const *seqSoundList = _staticres->loadStrings(k2SeqplaySfxFiles, _sequenceSoundListSize); - const char *const *tlkfiles = _staticres->loadStrings(k2SeqplayTlkFiles, tmpSize); - char **tmpSndLst = new char *[_sequenceSoundListSize]; - - for (int i = 0; i < _sequenceSoundListSize; i++) { - const int len = strlen(seqSoundList[i]); - - tmpSndLst[i] = new char[len + 1]; - tmpSndLst[i][0] = 0; - - if (tlkfiles && len > 1) { - for (int ii = 0; ii < tmpSize; ii++) { - if (strlen(tlkfiles[ii]) > 1 && !scumm_stricmp(&seqSoundList[i][1], &tlkfiles[ii][1])) - strcpy(tmpSndLst[i], tlkfiles[ii]); - } - } - - if (tmpSndLst[i][0] == 0) - strcpy(tmpSndLst[i], seqSoundList[i]); - } - - tlkfiles = seqSoundList = 0; - _staticres->unloadId(k2SeqplayTlkFiles); - _staticres->unloadId(k2SeqplaySfxFiles); - _sequenceSoundList = tmpSndLst; - // assign music data static const char *const fmtMusicFileListIntro[] = { "intro%d.twn" }; static const char *const fmtMusicFileListFinale[] = { "finale%d.twn" }; @@ -1074,66 +1046,6 @@ void KyraEngine_HoF::initStaticResource() { _soundData[2].fileList = pc98MusicFileListFinale; _soundData[2].fileListLen = 1; } - - // setup sequence data - _sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize); - - static const SeqProc hofSequenceCallbacks[] = { - 0, &KyraEngine_HoF::seq_introWestwood, - &KyraEngine_HoF::seq_introTitle, &KyraEngine_HoF::seq_introOverview, - &KyraEngine_HoF::seq_introLibrary, &KyraEngine_HoF::seq_introHand, - &KyraEngine_HoF::seq_introPoint, &KyraEngine_HoF::seq_introZanfaun, - &KyraEngine_HoF::seq_finaleFunters, &KyraEngine_HoF::seq_finaleFerb, - &KyraEngine_HoF::seq_finaleFish, &KyraEngine_HoF::seq_finaleFheep, - &KyraEngine_HoF::seq_finaleFarmer, &KyraEngine_HoF::seq_finaleFuards, - &KyraEngine_HoF::seq_finaleFirates, &KyraEngine_HoF::seq_finaleFrash - }; - - static const SeqProc hofNestedSequenceCallbacks[] = { - &KyraEngine_HoF::seq_finaleFiggle, &KyraEngine_HoF::seq_introOver1, - &KyraEngine_HoF::seq_introOver2, &KyraEngine_HoF::seq_introForest, - &KyraEngine_HoF::seq_introDragon, &KyraEngine_HoF::seq_introDarm, - &KyraEngine_HoF::seq_introLibrary2, &KyraEngine_HoF::seq_introLibrary2, - &KyraEngine_HoF::seq_introMarco, &KyraEngine_HoF::seq_introHand1a, - &KyraEngine_HoF::seq_introHand1b, &KyraEngine_HoF::seq_introHand1c, - &KyraEngine_HoF::seq_introHand2, &KyraEngine_HoF::seq_introHand3, 0 - }; - - static const SeqProc hofDemoSequenceCallbacks[] = { - &KyraEngine_HoF::seq_demoVirgin, &KyraEngine_HoF::seq_demoWestwood, - &KyraEngine_HoF::seq_demoTitle, &KyraEngine_HoF::seq_demoHill, - &KyraEngine_HoF::seq_demoOuthome, &KyraEngine_HoF::seq_demoWharf, - &KyraEngine_HoF::seq_demoDinob, &KyraEngine_HoF::seq_demoFisher, 0 - }; - - static const SeqProc hofDemoNestedSequenceCallbacks[] = { - &KyraEngine_HoF::seq_demoWharf2, &KyraEngine_HoF::seq_demoDinob2, - &KyraEngine_HoF::seq_demoWater, &KyraEngine_HoF::seq_demoBail, - &KyraEngine_HoF::seq_demoDig, 0 - }; - -#ifdef ENABLE_LOL - static const SeqProc kLoLDemoSequenceCallbacks[] = { - &KyraEngine_HoF::seq_lolDemoScene1, 0, &KyraEngine_HoF::seq_lolDemoScene2, 0, - &KyraEngine_HoF::seq_lolDemoScene3, 0, &KyraEngine_HoF::seq_lolDemoScene4, 0, - &KyraEngine_HoF::seq_lolDemoScene5, &KyraEngine_HoF::seq_lolDemoText5, - &KyraEngine_HoF::seq_lolDemoScene6, 0 - }; - - static const SeqProc kLoLDemoNestedSequenceCallbacks[] = { 0 }; -#endif // ENABLE_LOL - - _callbackS = -#ifdef ENABLE_LOL - _flags.gameID == GI_LOL ? kLoLDemoSequenceCallbacks : -#endif // ENABLE_LOL - ((_flags.isDemo && !_flags.isTalkie) ? hofDemoSequenceCallbacks : hofSequenceCallbacks); - - _callbackN = -#ifdef ENABLE_LOL - _flags.gameID == GI_LOL ? kLoLDemoNestedSequenceCallbacks : -#endif // ENABLE_LOL - ((_flags.isDemo && !_flags.isTalkie) ? hofDemoNestedSequenceCallbacks : hofNestedSequenceCallbacks); } void KyraEngine_MR::initStaticResource() { @@ -1412,8 +1324,6 @@ const int GUI_v2::_sliderBarsPosition[] = { // kyra 2 static res -const uint8 KyraEngine_HoF::_seqTextColorPresets[] = { 0x01, 0x01, 0x00, 0x3f, 0x3f, 0x3f }; - const char *const KyraEngine_HoF::_languageExtension[] = { "ENG", "FRE", -- cgit v1.2.3