aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/sequence/sequences_lok.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/sequence/sequences_lok.cpp')
-rw-r--r--engines/kyra/sequence/sequences_lok.cpp2116
1 files changed, 2116 insertions, 0 deletions
diff --git a/engines/kyra/sequence/sequences_lok.cpp b/engines/kyra/sequence/sequences_lok.cpp
new file mode 100644
index 0000000000..faddf762fb
--- /dev/null
+++ b/engines/kyra/sequence/sequences_lok.cpp
@@ -0,0 +1,2116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "kyra/engine/kyra_lok.h"
+#include "kyra/sequence/seqplayer.h"
+#include "kyra/resource/resource.h"
+#include "kyra/engine/sprites.h"
+#include "kyra/graphics/wsamovie.h"
+#include "kyra/graphics/animator_lok.h"
+#include "kyra/engine/timer.h"
+#include "kyra/sound/sound.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+#include "common/list.h"
+
+namespace Kyra {
+
+void KyraEngine_LoK::seq_demo() {
+ snd_playTheme(0, 2);
+
+ _screen->loadBitmap("START.CPS", 7, 7, &_screen->getPalette(0));
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+ delay(60 * _tickLength);
+ _screen->fadeToBlack();
+
+ _screen->clearPage(0);
+ _screen->loadBitmap("TOP.CPS", 7, 7, 0);
+ _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0));
+ _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+
+ _seq->playSequence(_seq_WestwoodLogo, true);
+ delay(60 * _tickLength);
+ _seq->playSequence(_seq_KyrandiaLogo, true);
+
+ _screen->fadeToBlack();
+ _screen->clearPage(2);
+ _screen->clearPage(0);
+
+ _seq->playSequence(_seq_Demo1, true);
+
+ _screen->clearPage(0);
+ _seq->playSequence(_seq_Demo2, true);
+
+ _screen->clearPage(0);
+ _seq->playSequence(_seq_Demo3, true);
+
+ _screen->clearPage(0);
+ _seq->playSequence(_seq_Demo4, true);
+
+ _screen->clearPage(0);
+ _screen->loadBitmap("FINAL.CPS", 7, 7, &_screen->getPalette(0));
+ _screen->_curPage = 0;
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+ delay(60 * _tickLength);
+ _screen->fadeToBlack();
+ _sound->haltTrack();
+}
+
+void KyraEngine_LoK::seq_intro() {
+ if (_flags.isTalkie)
+ _res->loadPakFile("INTRO.VRM");
+
+ static const IntroProc introProcTable[] = {
+ &KyraEngine_LoK::seq_introPublisherLogos,
+ &KyraEngine_LoK::seq_introLogos,
+ &KyraEngine_LoK::seq_introStory,
+ &KyraEngine_LoK::seq_introMalcolmTree,
+ &KyraEngine_LoK::seq_introKallakWriting,
+ &KyraEngine_LoK::seq_introKallakMalcolm
+ };
+
+ Common::InSaveFile *in;
+ if ((in = _saveFileMan->openForLoading(getSavegameFilename(0)))) {
+ delete in;
+ _skipIntroFlag = true;
+ } else {
+ _skipIntroFlag = !_flags.isDemo;
+ }
+
+ _seq->setCopyViewOffs(true);
+ _screen->setFont(_flags.lang == Common::JA_JPN ? Screen::FID_SJIS_FNT : Screen::FID_8_FNT);
+ if (_flags.platform != Common::kPlatformFMTowns && _flags.platform != Common::kPlatformPC98 && _flags.platform != Common::kPlatformAmiga)
+ snd_playTheme(0, 2);
+ _text->setTalkCoords(144);
+
+ for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) {
+ if ((this->*introProcTable[i])() && !shouldQuit()) {
+ resetSkipFlag();
+ _screen->fadeToBlack();
+ _screen->clearPage(0);
+ }
+ }
+
+ _text->setTalkCoords(136);
+ delay(30 * _tickLength);
+ _seq->setCopyViewOffs(false);
+ _sound->haltTrack();
+ _sound->voiceStop();
+
+ if (_flags.isTalkie)
+ _res->unloadPakFile("INTRO.VRM");
+}
+
+bool KyraEngine_LoK::seq_introPublisherLogos() {
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
+ _screen->loadBitmap("LOGO.CPS", 3, 3, &_screen->getPalette(0));
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+ delay(90 * _tickLength);
+ if (!_abortIntroFlag) {
+ _screen->fadeToBlack();
+ snd_playWanderScoreViaMap(_flags.platform == Common::kPlatformFMTowns ? 57 : 2, 0);
+ }
+ } else if (_flags.platform == Common::kPlatformMacintosh && _res->exists("MP_GOLD.CPS")) {
+ _screen->loadPalette("MP_GOLD.COL", _screen->getPalette(0));
+ _screen->loadBitmap("MP_GOLD.CPS", 3, 3, 0);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+ delay(120 * _tickLength);
+ if (!_abortIntroFlag)
+ _screen->fadeToBlack();
+ }
+
+ return _abortIntroFlag;
+}
+
+bool KyraEngine_LoK::seq_introLogos() {
+ _screen->clearPage(0);
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->loadPaletteTable("INTRO.PAL", 0);
+ _screen->loadBitmap("BOTTOM.CPS", 3, 5, 0);
+ _screen->loadBitmap("TOP.CPS", 3, 3, 0);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 2, 0);
+ _screen->copyRegion(0, 91, 0, 8, 320, 109, 2, 0);
+ _screen->copyRegion(0, 0, 0, 0, 320, 190, 0, 2);
+ } else {
+ _screen->loadBitmap("TOP.CPS", 7, 7, 0);
+ _screen->loadBitmap("BOTTOM.CPS", 5, 5, &_screen->getPalette(0));
+ _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
+ }
+
+ _screen->_curPage = 0;
+ _screen->updateScreen();
+ _screen->fadeFromBlack();
+
+ if (_seq->playSequence(_seq_WestwoodLogo, skipFlag()) || shouldQuit())
+ return true;
+
+ delay(60 * _tickLength);
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->copyPalette(0, 1);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+
+ if (_seq->playSequence(_seq_KyrandiaLogo, skipFlag()) || shouldQuit())
+ return true;
+
+ _screen->setFont(of);
+ _screen->fillRect(0, 179, 319, 199, 0);
+
+ if (shouldQuit())
+ return false;
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->copyPalette(0, 2);
+ _screen->fadeToBlack();
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 4, 0);
+ _screen->fadeFromBlack();
+ } else {
+ _screen->copyRegion(0, 91, 0, 8, 320, 104, 6, 2);
+ _screen->copyRegion(0, 0, 0, 112, 320, 64, 6, 2);
+
+ uint32 start = _system->getMillis();
+ bool doneFlag = false;
+ int oldDistance = 0;
+
+ do {
+ uint32 now = _system->getMillis();
+
+ // The smallest y2 we ever draw the screen for is 65.
+ int distance = (now - start) / _tickLength;
+ if (distance > 112) {
+ distance = 112;
+ doneFlag = true;
+ }
+
+ if (distance > oldDistance) {
+ int y1 = 8 + distance;
+ int h1 = 168 - distance;
+ int y2 = 176 - distance;
+ int h2 = distance;
+
+ _screen->copyRegion(0, y1, 0, 8, 320, h1, 2, 0);
+ if (h2 > 0)
+ _screen->copyRegion(0, 64, 0, y2, 320, h2, 4, 0);
+ _screen->updateScreen();
+ }
+
+ oldDistance = distance;
+ delay(10);
+ } while (!doneFlag && !shouldQuit() && !_abortIntroFlag);
+ }
+
+ if (_abortIntroFlag || shouldQuit())
+ return true;
+
+ return _seq->playSequence(_seq_Forest, true);
+}
+
+bool KyraEngine_LoK::seq_introStory() {
+ _screen->clearPage(3);
+ _screen->clearPage(0);
+
+ // HACK: The Italian fan translation uses an special text screen here
+ // so we show it even when text is disabled
+ if (!textEnabled() && speechEnabled() && _flags.lang != Common::IT_ITA)
+ return false;
+
+ if (((_flags.lang == Common::EN_ANY || _flags.lang == Common::RU_RUS) && !_flags.isTalkie && _flags.platform == Common::kPlatformDOS) || _flags.platform == Common::kPlatformAmiga)
+ _screen->loadBitmap("TEXT.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN)
+ _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::DE_DEU)
+ _screen->loadBitmap("TEXT_GER.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::FR_FRA)
+ _screen->loadBitmap("TEXT_FRE.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::ES_ESP)
+ _screen->loadBitmap("TEXT_SPA.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::IT_ITA && !_flags.isTalkie)
+ _screen->loadBitmap("TEXT_ITA.CPS", 3, 3, &_screen->getPalette(0));
+ else if (_flags.lang == Common::IT_ITA && _flags.isTalkie)
+ _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, &_screen->getPalette(0));
+ else
+ warning("no story graphics file found");
+
+ if (_flags.platform == Common::kPlatformAmiga)
+ _screen->setScreenPalette(_screen->getPalette(4));
+ else
+ _screen->setScreenPalette(_screen->getPalette(0));
+ _screen->copyPage(3, 0);
+
+ if (_flags.lang == Common::JA_JPN) {
+ const int y1 = 175;
+ int x1, x2, y2, col1;
+ const char *s1, *s2;
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ s1 = _seq_textsTable[18];
+ s2 = _seq_textsTable[19];
+ x1 = (Screen::SCREEN_W - _screen->getTextWidth(s1)) / 2;
+ x2 = (Screen::SCREEN_W - _screen->getTextWidth(s2)) / 2;
+ uint8 colorMap[] = { 0, 15, 12, 12 };
+ _screen->setTextColor(colorMap, 0, 3);
+ y2 = 184;
+ col1 = 5;
+
+ } else {
+ s1 = _storyStrings[0];
+ s2 = _storyStrings[1];
+ x1 = x2 = 54;
+ y2 = 185;
+ col1 = 15;
+ }
+
+ _screen->printText(s1, x1, y1, col1, 8);
+ _screen->printText(s2, x2, y2, col1, 8);
+ }
+
+ _screen->updateScreen();
+ delay(360 * _tickLength);
+
+ return _abortIntroFlag;
+}
+
+bool KyraEngine_LoK::seq_introMalcolmTree() {
+ _screen->_curPage = 0;
+ _screen->clearPage(3);
+ return _seq->playSequence(_seq_MalcolmTree, true);
+}
+
+bool KyraEngine_LoK::seq_introKallakWriting() {
+ _seq->makeHandShapes();
+ _screen->setAnimBlockPtr(5060);
+ _screen->_charWidth = -2;
+ _screen->clearPage(3);
+ const bool skipped = _seq->playSequence(_seq_KallakWriting, true);
+ _seq->freeHandShapes();
+
+ return skipped;
+}
+
+bool KyraEngine_LoK::seq_introKallakMalcolm() {
+ _screen->clearPage(3);
+ return _seq->playSequence(_seq_KallakMalcolm, true);
+}
+
+void KyraEngine_LoK::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
+ static const uint16 specialJewelTable[] = {
+ 0x167, 0x162, 0x15D, 0x158, 0x153, 0xFFFF
+ };
+ static const uint16 specialJewelTable1[] = {
+ 0x14F, 0x154, 0x159, 0x15E, 0x163, 0xFFFF
+ };
+ static const uint16 specialJewelTable2[] = {
+ 0x150, 0x155, 0x15A, 0x15F, 0x164, 0xFFFF
+ };
+ static const uint16 specialJewelTable3[] = {
+ 0x151, 0x156, 0x15B, 0x160, 0x165, 0xFFFF
+ };
+ static const uint16 specialJewelTable4[] = {
+ 0x152, 0x157, 0x15C, 0x161, 0x166, 0xFFFF
+ };
+ if (!noSound)
+ snd_playSoundEffect(0x5F);
+ _screen->hideMouse();
+ if (!drawOnly) {
+ for (int i = 0; specialJewelTable[i] != 0xFFFF; ++i) {
+ _screen->drawShape(page, _shapes[specialJewelTable[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ delayWithTicks(3);
+ }
+
+ const uint16 *opcodes = 0;
+ switch (jewel - 1) {
+ case 0:
+ opcodes = specialJewelTable1;
+ break;
+
+ case 1:
+ opcodes = specialJewelTable2;
+ break;
+
+ case 2:
+ opcodes = specialJewelTable3;
+ break;
+
+ case 3:
+ opcodes = specialJewelTable4;
+ break;
+ }
+
+ if (opcodes) {
+ for (int i = 0; opcodes[i] != 0xFFFF; ++i) {
+ _screen->drawShape(page, _shapes[opcodes[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ delayWithTicks(3);
+ }
+ }
+ }
+ _screen->drawShape(page, _shapes[323 + jewel], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ _screen->showMouse();
+ setGameFlag(0x55 + jewel);
+}
+
+void KyraEngine_LoK::seq_brandonHealing() {
+ if (!(_deathHandler & 8))
+ return;
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_healingShapeTable);
+ setupShapes123(_healingShapeTable, 22, 0);
+ _animator->setBrandonAnimSeqSize(3, 48);
+ snd_playSoundEffect(0x53);
+ for (int i = 123; i <= 144; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ for (int i = 125; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_brandonHealing2() {
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_healingShape2Table);
+ setupShapes123(_healingShape2Table, 30, 0);
+ resetBrandonPoisonFlags();
+ _animator->setBrandonAnimSeqSize(3, 48);
+ snd_playSoundEffect(0x50);
+ for (int i = 123; i <= 152; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+ assert(_poisonGone);
+ characterSays(2010, _poisonGone[0], 0, -2);
+ characterSays(2011, _poisonGone[1], 0, -2);
+}
+
+void KyraEngine_LoK::seq_poisonDeathNow(int now) {
+ if (!(_brandonStatusBit & 1))
+ return;
+ ++_poisonDeathCounter;
+ if (now)
+ _poisonDeathCounter = 2;
+ if (_poisonDeathCounter >= 2) {
+ snd_playWanderScoreViaMap(1, 1);
+ assert(_thePoison);
+ characterSays(7000, _thePoison[0], 0, -2);
+ characterSays(7001, _thePoison[1], 0, -2);
+ seq_poisonDeathNowAnim();
+ _deathHandler = 3;
+ } else {
+ assert(_thePoison);
+ characterSays(7002, _thePoison[2], 0, -2);
+ characterSays(7004, _thePoison[3], 0, -2);
+ }
+}
+
+void KyraEngine_LoK::seq_poisonDeathNowAnim() {
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_posionDeathShapeTable);
+ setupShapes123(_posionDeathShapeTable, 20, 0);
+ _animator->setBrandonAnimSeqSize(8, 48);
+
+ _currentCharacter->currentAnimFrame = 124;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(30);
+
+ _currentCharacter->currentAnimFrame = 123;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(30);
+
+ for (int i = 125; i <= 139; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(60);
+
+ for (int i = 140; i <= 142; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(60);
+
+ _animator->resetBrandonAnimSeqSize();
+ freeShapes123();
+ _animator->restoreAllObjectBackgrounds();
+ _currentCharacter->x1 = _currentCharacter->x2 = -1;
+ _currentCharacter->y1 = _currentCharacter->y2 = -1;
+ _animator->preserveAllBackgrounds();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_playFluteAnimation() {
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ setupShapes123(_fluteAnimShapeTable, 36, 0);
+ _animator->setBrandonAnimSeqSize(3, 75);
+ for (int i = 123; i <= 130; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(2);
+ }
+
+ int delayTime = 0, soundType = 0;
+ if (queryGameFlag(0x85)) {
+ snd_playSoundEffect(0x63);
+ delayTime = 9;
+ soundType = 3;
+ } else if (!queryGameFlag(0x86)) {
+ snd_playSoundEffect(0x61);
+ delayTime = 2;
+ soundType = 1;
+ setGameFlag(0x86);
+ } else {
+ snd_playSoundEffect(0x62);
+ delayTime = 2;
+ soundType = 2;
+ }
+
+ for (int i = 131; i <= 158; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(delayTime);
+ }
+
+ for (int i = 126; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(delayTime);
+ }
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+
+ if (soundType == 1) {
+ assert(_fluteString);
+ characterSays(1000, _fluteString[0], 0, -2);
+ } else if (soundType == 2) {
+ assert(_fluteString);
+ characterSays(1001, _fluteString[1], 0, -2);
+ }
+}
+
+void KyraEngine_LoK::seq_winterScroll1() {
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_winterScrollTable);
+ assert(_winterScroll1Table);
+ assert(_winterScroll2Table);
+ setupShapes123(_winterScrollTable, 7, 0);
+ _animator->setBrandonAnimSeqSize(5, 66);
+
+ for (int i = 123; i <= 129; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ freeShapes123();
+ snd_playSoundEffect(0x20);
+
+ uint8 numFrames, midpoint;
+ if (_flags.isTalkie) {
+ numFrames = 18;
+ midpoint = 136;
+ } else {
+ numFrames = 35;
+ midpoint = 147;
+ }
+ setupShapes123(_winterScroll1Table, numFrames, 0);
+ for (int i = 123; i < midpoint; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ if (_currentCharacter->sceneId == 41 && !queryGameFlag(0xA2)) {
+ snd_playSoundEffect(0x20);
+ _sprites->_anims[0].play = false;
+ _animator->sprites()[0].active = 0;
+ _sprites->_anims[1].play = true;
+ _animator->sprites()[1].active = 1;
+
+ if (_flags.platform != Common::kPlatformAmiga)
+ setGameFlag(0xA2);
+ }
+
+ for (int i = midpoint; i < 123 + numFrames; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ if (_currentCharacter->sceneId == 117 && !queryGameFlag(0xB3)) {
+ for (int i = 0; i <= 7; ++i) {
+ _sprites->_anims[i].play = false;
+ _animator->sprites()[i].active = 0;
+ }
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->copyPalette(0, 11);
+ } else {
+ _screen->getPalette(0).copy(palTable2()[0], 0, 20, 228);
+ _screen->fadePalette(_screen->getPalette(0), 72);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ setGameFlag(0xB3);
+ }
+ } else {
+ delayWithTicks(120);
+ }
+
+ freeShapes123();
+ setupShapes123(_winterScroll2Table, 4, 0);
+
+ for (int i = 123; i <= 126; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_winterScroll2() {
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_winterScrollTable);
+ setupShapes123(_winterScrollTable, 7, 0);
+ _animator->setBrandonAnimSeqSize(5, 66);
+
+ for (int i = 123; i <= 128; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(120);
+
+ for (int i = 127; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_makeBrandonInv() {
+ if (_deathHandler == 8)
+ return;
+
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ _brandonStatusBit |= 0x20;
+ _timer->setCountdown(18, 2700);
+ _brandonStatusBit |= 0x40;
+ snd_playSoundEffect(0x77);
+ _brandonInvFlag = 0;
+ while (_brandonInvFlag <= 0x100) {
+ _animator->animRefreshNPC(0);
+ delayWithTicks(10);
+ _brandonInvFlag += 0x10;
+ }
+ _brandonStatusBit &= 0xFFBF;
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_makeBrandonNormal() {
+ _screen->hideMouse();
+ _brandonStatusBit |= 0x40;
+ snd_playSoundEffect(0x77);
+ _brandonInvFlag = 0x100;
+ while (_brandonInvFlag >= 0) {
+ _animator->animRefreshNPC(0);
+ delayWithTicks(10);
+ _brandonInvFlag -= 0x10;
+ }
+ _brandonInvFlag = 0;
+ _brandonStatusBit &= 0xFF9F;
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_makeBrandonNormal2() {
+ _screen->hideMouse();
+ assert(_brandonToWispTable);
+ setupShapes123(_brandonToWispTable, 26, 0);
+ _animator->setBrandonAnimSeqSize(5, 48);
+ _brandonStatusBit &= 0xFFFD;
+ snd_playSoundEffect(0x6C);
+ for (int i = 138; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ _animator->setBrandonAnimSeqSize(3, 48);
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+
+ if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245)
+ _screen->fadeSpecialPalette(31, 234, 13, 4);
+ else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186)
+ _screen->fadeSpecialPalette(14, 228, 15, 4);
+
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_makeBrandonWisp() {
+ if (_deathHandler == 8)
+ return;
+
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_brandonToWispTable);
+ setupShapes123(_brandonToWispTable, 26, 0);
+ _animator->setBrandonAnimSeqSize(5, 48);
+ snd_playSoundEffect(0x6C);
+ for (int i = 123; i <= 138; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ _brandonStatusBit |= 2;
+
+ if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198)
+ _timer->setCountdown(14, 18000);
+ else
+ _timer->setCountdown(14, 7200);
+
+ _animator->_brandonDrawFrame = 113;
+ _brandonStatusBit0x02Flag = 1;
+ _currentCharacter->currentAnimFrame = 113;
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ if ((_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) ||
+ (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186))
+ _screen->fadePalette(_screen->getPalette(10), 0x54);
+ } else {
+ if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245)
+ _screen->fadeSpecialPalette(30, 234, 13, 4);
+ else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186)
+ _screen->fadeSpecialPalette(14, 228, 15, 4);
+ }
+
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_dispelMagicAnimation() {
+ if (_deathHandler == 8)
+ return;
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+ _screen->hideMouse();
+ // TODO
+ // This condition is always false. Is this a typo or a bug in the original?
+ if (_currentCharacter->sceneId == 210 && _currentCharacter->sceneId < 160)
+ _currentCharacter->facing = 3;
+ if (_malcolmFlag == 7 && _beadStateVar == 3) {
+ _beadStateVar = 6;
+ _unkEndSeqVar5 = 2;
+ _malcolmFlag = 10;
+ }
+ checkAmuletAnimFlags();
+ setGameFlag(0xEE);
+ assert(_magicAnimationTable);
+ setupShapes123(_magicAnimationTable, 5, 0);
+ _animator->setBrandonAnimSeqSize(8, 49);
+ snd_playSoundEffect(0x15);
+ for (int i = 123; i <= 127; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(120);
+
+ for (int i = 127; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(10);
+ }
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_fillFlaskWithWater(int item, int type) {
+ int newItem = -1;
+
+ static const uint8 flaskTable1[] = { 0x46, 0x48, 0x4A, 0x4C };
+ static const uint8 flaskTable2[] = { 0x47, 0x49, 0x4B, 0x4D };
+
+ if (item >= 60 && item <= 77) {
+ assert(_flaskFull);
+ characterSays(8006, _flaskFull[0], 0, -2);
+ } else if (item == 78) {
+ assert(type >= 0 && type < ARRAYSIZE(flaskTable1));
+ newItem = flaskTable1[type];
+ } else if (item == 79) {
+ assert(type >= 0 && type < ARRAYSIZE(flaskTable2));
+ newItem = flaskTable2[type];
+ }
+
+ if (newItem == -1)
+ return;
+
+ setMouseItem(newItem);
+ _itemInHand = newItem;
+
+ assert(_fullFlask);
+ assert(type < _fullFlask_Size && type >= 0);
+
+ static const uint16 voiceEntries[] = {
+ 0x1F40, 0x1F41, 0x1F42, 0x1F45
+ };
+ assert(type < ARRAYSIZE(voiceEntries));
+
+ characterSays(voiceEntries[type], _fullFlask[type], 0, -2);
+}
+
+void KyraEngine_LoK::seq_playDrinkPotionAnim(int item, int unk2, int flags) {
+ if (_flags.platform == Common::kPlatformAmiga) {
+ uint8 r, g, b;
+
+ switch (item) {
+ case 60: case 61:
+ // 0xC22
+ r = 50;
+ g = 8;
+ b = 8;
+ break;
+
+ case 62: case 63: case 76:
+ case 77:
+ // 0x00E
+ r = 0;
+ g = 0;
+ b = 58;
+ break;
+
+ case 64: case 65:
+ // 0xFF5
+ r = 63;
+ g = 63;
+ b = 21;
+ break;
+
+ case 66:
+ // 0x090
+ r = 0;
+ g = 37;
+ b = 0;
+ break;
+
+ case 67:
+ // 0xC61
+ r = 50;
+ g = 25;
+ b = 4;
+ break;
+
+ case 68:
+ // 0xE2E
+ r = 58;
+ g = 8;
+ b = 58;
+ break;
+
+ case 69:
+ // 0xBBB
+ r = 46;
+ g = 46;
+ b = 46;
+ break;
+
+ default:
+ // 0xFFF
+ r = 63;
+ g = 63;
+ b = 63;
+ }
+
+ _screen->setPaletteIndex(16, r, g, b);
+ } else {
+ uint8 red, green, blue;
+
+ switch (item) {
+ case 60: case 61:
+ red = 63;
+ green = blue = 6;
+ break;
+
+ case 62: case 63:
+ red = green = 0;
+ blue = 67;
+ break;
+
+ case 64: case 65:
+ red = 84;
+ green = 78;
+ blue = 14;
+ break;
+
+ case 66:
+ red = blue = 0;
+ green = 48;
+ break;
+
+ case 67:
+ red = 100;
+ green = 48;
+ blue = 23;
+ break;
+
+ case 68:
+ red = 73;
+ green = 0;
+ blue = 89;
+ break;
+
+ case 69:
+ red = green = 73;
+ blue = 86;
+ break;
+
+ default:
+ red = 33;
+ green = 66;
+ blue = 100;
+ }
+
+ red = red * 0x3F / 100;
+ green = green * 0x3F / 100;
+ blue = blue * 0x3F / 100;
+
+ _screen->setPaletteIndex(0xFE, red, green, blue);
+ }
+
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ _currentCharacter->facing = 5;
+ _animator->animRefreshNPC(0);
+ assert(_drinkAnimationTable);
+ setupShapes123(_drinkAnimationTable, 9, flags);
+ _animator->setBrandonAnimSeqSize(5, 54);
+
+ for (int i = 123; i <= 131; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(5);
+ }
+
+ snd_playSoundEffect(0x34);
+
+ for (int i = 0; i < 2; ++i) {
+ _currentCharacter->currentAnimFrame = 130;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(7);
+ _currentCharacter->currentAnimFrame = 131;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(7);
+ }
+
+ if (unk2) {
+ // XXX
+ }
+
+ for (int i = 131; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(5);
+ }
+
+ _animator->resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ freeShapes123();
+
+ if (_flags.platform != Common::kPlatformAmiga)
+ _screen->setPaletteIndex(0xFE, 30, 30, 30);
+
+ _screen->showMouse();
+}
+
+int KyraEngine_LoK::seq_playEnd() {
+ if (_endSequenceSkipFlag)
+ return 0;
+
+ if (_deathHandler == 8)
+ return 0;
+
+ _screen->_curPage = 2;
+ if (_endSequenceNeedLoading) {
+ snd_playWanderScoreViaMap(50, 1);
+ setupPanPages();
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _sound->loadSoundFile(kMusicFinale);
+
+ // The original started song 0 directly here. Since our player
+ // uses 0, 1 for stop and fade we start song 0 with 2
+ _sound->playTrack(2);
+ }
+
+ _finalA = createWSAMovie();
+ assert(_finalA);
+ _finalA->open("finala.wsa", 1, 0);
+
+ _finalB = createWSAMovie();
+ assert(_finalB);
+ _finalB->open("finalb.wsa", 1, 0);
+
+ _finalC = createWSAMovie();
+ assert(_finalC);
+ _endSequenceNeedLoading = 0;
+ _finalC->open("finalc.wsa", 1, 0);
+
+ _screen->_curPage = 0;
+ _beadStateVar = 0;
+ _malcolmFlag = 0;
+ _unkEndSeqVar2 = _system->getMillis() + 600 * _tickLength;
+
+ _screen->copyRegion(312, 0, 312, 0, 8, 136, 0, 2);
+ }
+
+ // TODO: better handling. This timer shouldn't count when the menu is open or something.
+ if (_unkEndSeqVar2 != -1) {
+ if (_system->getMillis() > (uint32)_unkEndSeqVar2) {
+ _unkEndSeqVar2 = -1;
+ if (!_malcolmFlag)
+ _malcolmFlag = 1;
+ }
+ }
+
+ if (handleMalcolmFlag()) {
+ _beadStateVar = 0;
+ _malcolmFlag = 12;
+ handleMalcolmFlag();
+ handleBeadState();
+ closeFinalWsa();
+ if (_deathHandler == 8) {
+ _screen->_curPage = 0;
+ checkAmuletAnimFlags();
+ seq_brandonToStone();
+ delay(60 * _tickLength);
+ return 1;
+ } else {
+ _endSequenceSkipFlag = 1;
+ if (_text->printed())
+ _text->restoreTalkTextMessageBkgd(2, 0);
+
+ _screen->_curPage = 0;
+ _screen->hideMouse();
+
+ if (_flags.platform != Common::kPlatformAmiga)
+ _screen->fadeSpecialPalette(32, 228, 20, 60);
+
+ delay(60 * _tickLength);
+
+ _screen->loadBitmap("GEMHEAL.CPS", 3, 3, &_screen->getPalette(0));
+ _screen->setScreenPalette(_screen->getPalette(0));
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0);
+
+ uint32 nextTime = _system->getMillis() + 120 * _tickLength;
+
+ _finalA = createWSAMovie();
+ assert(_finalA);
+ _finalA->open("finald.wsa", 1, 0);
+
+ delayUntil(nextTime);
+ snd_playSoundEffect(0x40);
+ for (int i = 0; i < 22; ++i) {
+ delayUntil(nextTime);
+ if (i == 4)
+ snd_playSoundEffect(0x3E);
+ else if (i == 20)
+ snd_playSoundEffect(_flags.platform == Common::kPlatformPC98 ? 0x13 : 0x0E);
+ nextTime = _system->getMillis() + 8 * _tickLength;
+ _finalA->displayFrame(i, 0, 8, 8, 0, 0, 0);
+ _screen->updateScreen();
+ }
+ delete _finalA;
+
+ _finalA = 0;
+ seq_playEnding();
+ return 1;
+ }
+ } else {
+ handleBeadState();
+ _screen->bitBlitRects();
+ _screen->updateScreen();
+ _screen->_curPage = 0;
+ }
+ return 0;
+}
+
+void KyraEngine_LoK::seq_brandonToStone() {
+ _screen->hideMouse();
+ assert(_brandonStoneTable);
+ setupShapes123(_brandonStoneTable, 14, 0);
+ _animator->setBrandonAnimSeqSize(5, 51);
+
+ for (int i = 123; i <= 136; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ _animator->animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ _animator->resetBrandonAnimSeqSize();
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_playEnding() {
+ if (shouldQuit())
+ return;
+ _screen->hideMouse();
+ _screen->_curPage = 0;
+ _screen->fadeToBlack();
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->loadBitmap("GEMCUT.CPS", 3, 3, &_screen->getPalette(0));
+ _screen->copyRegion(232, 136, 176, 56, 56, 56, 2, 2);
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 0, 2, Screen::CR_NO_P_CHECK);
+ } else {
+ _screen->loadBitmap("REUNION.CPS", 3, 3, &_screen->getPalette(0));
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+ }
+
+ _screen->_curPage = 0;
+ // XXX
+ assert(_homeString);
+ drawSentenceCommand(_homeString[0], 179);
+
+ _screen->getPalette(2).clear();
+ _screen->setScreenPalette(_screen->getPalette(2));
+
+ _seqPlayerFlag = true;
+ _seq->playSequence(_seq_Reunion, false);
+ _screen->fadeToBlack();
+ _seqPlayerFlag = false;
+
+ _screen->showMouse();
+
+ // To avoid any remaining input events, we remove the queue
+ // over here.
+ _eventList.clear();
+
+ if (_flags.platform == Common::kPlatformAmiga) {
+ _screen->_charWidth = -2;
+ _screen->setCurPage(2);
+
+ _screen->getPalette(2).clear();
+ _screen->setScreenPalette(_screen->getPalette(2));
+
+ while (!shouldQuit()) {
+ seq_playCreditsAmiga();
+ delayUntil(_system->getMillis() + 300 * _tickLength);
+ }
+ } else {
+ seq_playCredits();
+ }
+}
+
+namespace {
+struct CreditsLine {
+ int16 x, y;
+ Screen::FontId font;
+ uint8 *str;
+};
+} // end of anonymous namespace
+
+void KyraEngine_LoK::seq_playCredits() {
+ static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const char stringTerms[] = { 0x5, 0xD, 0x0};
+
+ typedef Common::List<CreditsLine> CreditsLineList;
+ CreditsLineList lines;
+
+ _screen->enableInterfacePalette(false);
+
+ _screen->hideMouse();
+ if (!_flags.isTalkie) {
+ _screen->loadFont(Screen::FID_CRED6_FNT, "CREDIT6.FNT");
+ _screen->loadFont(Screen::FID_CRED8_FNT, "CREDIT8.FNT");
+
+ _screen->setFont(Screen::FID_CRED8_FNT);
+ } else
+ _screen->setFont(Screen::FID_8_FNT);
+
+ _screen->loadBitmap("CHALET.CPS", 4, 4, &_screen->getPalette(0));
+
+ _screen->setCurPage(0);
+ _screen->clearCurPage();
+ _screen->setTextColorMap(colorMap);
+ _screen->_charWidth = -1;
+
+ // we only need this for the FM-TOWNS version
+ if (_flags.platform == Common::kPlatformFMTowns && _configMusic == 1)
+ snd_playWanderScoreViaMap(53, 1);
+
+ uint8 *buffer = 0;
+ uint32 size = 0;
+
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
+ int sizeTmp = 0;
+ const uint8 *bufferTmp = _staticres->loadRawData(k1CreditsStrings, sizeTmp);
+ buffer = new uint8[sizeTmp];
+ assert(buffer);
+ memcpy(buffer, bufferTmp, sizeTmp);
+ size = sizeTmp;
+ _staticres->unloadId(k1CreditsStrings);
+ } else {
+ buffer = _res->fileData("CREDITS.TXT", &size);
+ assert(buffer);
+ }
+
+ uint8 *nextString = buffer;
+ uint8 *currentString = buffer;
+ int currentY = 200;
+
+ do {
+ currentString = nextString;
+ nextString = (uint8 *)strpbrk((char *)currentString, stringTerms);
+ if (!nextString)
+ nextString = (uint8 *)strchr((char *)currentString, 0);
+
+ CreditsLine line;
+
+ int lineEndCode = nextString[0];
+ *nextString = 0;
+ if (lineEndCode != 0)
+ nextString++;
+
+ int alignment = 0;
+ if (*currentString == 3 || *currentString == 4) {
+ alignment = *currentString;
+ currentString++;
+ }
+
+ if (*currentString == 1) {
+ currentString++;
+
+ if (!_flags.isTalkie)
+ _screen->setFont(Screen::FID_CRED6_FNT);
+ } else if (*currentString == 2) {
+ currentString++;
+
+ if (!_flags.isTalkie)
+ _screen->setFont(Screen::FID_CRED8_FNT);
+ }
+
+ line.font = _screen->_currentFont;
+
+ if (alignment == 3)
+ line.x = 157 - _screen->getTextWidth((const char *)currentString);
+ else if (alignment == 4)
+ line.x = 161;
+ else
+ line.x = (320 - _screen->getTextWidth((const char *)currentString)) / 2 + 1;
+
+ line.y = currentY;
+ if (lineEndCode != 5)
+ currentY += 10;
+
+ line.str = currentString;
+
+ lines.push_back(line);
+ } while (*nextString);
+
+ _screen->setCurPage(2);
+
+ _screen->getPalette(2).clear();
+ _screen->setScreenPalette(_screen->getPalette(2));
+
+ _screen->copyRegion(0, 32, 0, 32, 320, 128, 4, 0, Screen::CR_NO_P_CHECK);
+ _screen->fadePalette(_screen->getPalette(0), 0x5A);
+
+ bool finished = false;
+ int bottom = 201;
+ while (!finished && !shouldQuit()) {
+ uint32 startLoop = _system->getMillis();
+
+ if (bottom > 175) {
+ _screen->copyRegion(0, 32, 0, 32, 320, 128, 4, 2, Screen::CR_NO_P_CHECK);
+ bottom = 0;
+
+ for (CreditsLineList::iterator it = lines.begin(); it != lines.end();) {
+ if (it->y < 0) {
+ it = lines.erase(it);
+ continue;
+ }
+
+ if (it->y < 200) {
+ if (it->font != _screen->_currentFont)
+ _screen->setFont(it->font);
+
+ _screen->printText((const char *)it->str, it->x, it->y, 15, 0);
+ }
+
+ it->y--;
+ if (it->y > bottom)
+ bottom = it->y;
+
+ ++it;
+ }
+
+ _screen->copyRegion(0, 32, 0, 32, 320, 128, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+
+ if (checkInput(0, false)) {
+ removeInputTop();
+ finished = true;
+ }
+
+ uint32 now = _system->getMillis();
+ uint32 nextLoop = startLoop + _tickLength * 5;
+
+ if (nextLoop > now)
+ _system->delayMillis(nextLoop - now);
+ }
+
+ delete[] buffer;
+
+ _screen->fadeToBlack();
+ _screen->clearCurPage();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::seq_playCreditsAmiga() {
+ _screen->setFont(Screen::FID_8_FNT);
+
+ _screen->loadBitmap("CHALET.CPS", 4, 2, &_screen->getPalette(0));
+ _screen->copyPage(2, 0);
+
+ _screen->getPalette(0).fill(16, 1, 63);
+ _screen->fadePalette(_screen->getPalette(0), 0x5A);
+ _screen->updateScreen();
+
+ const char *theEnd = "THE END";
+
+ const int width = _screen->getTextWidth(theEnd) + 1;
+ int x = (320 - width) / 2 + 1;
+
+ _screen->copyRegion(x, 8, x, 8, width, 56, 0, 2, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(x, 8, 0, 8, width, 11, 0, 2, Screen::CR_NO_P_CHECK);
+ _screen->printText(theEnd, 0, 10, 31, 0);
+
+ for (int y = 18, h = 1; y >= 10 && !shouldQuit(); --y, ++h) {
+ uint32 endTime = _system->getMillis() + 3 * _tickLength;
+
+ _screen->copyRegion(0, y, x, 8, width, h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(endTime);
+ }
+
+ for (int y = 8; y <= 62 && !shouldQuit(); ++y) {
+ uint32 endTime = _system->getMillis() + 3 * _tickLength;
+
+ _screen->copyRegion(x, y, 0, 8, width, 11, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->printText(theEnd, 0, 9, 31, 0);
+ _screen->copyRegion(0, 8, x, y, width, 11, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(endTime);
+ }
+
+ int size = 0;
+ const char *creditsData = (const char *)_staticres->loadRawData(k1CreditsStrings, size);
+
+ char stringBuffer[81];
+ memset(stringBuffer, 0, sizeof(stringBuffer));
+
+ const char *cur = creditsData;
+ char *specialString = stringBuffer;
+ bool fillRectFlag = false, subWidth = false, centerFlag = false;
+ x = 0;
+ int specialX = 0;
+
+ const int fontHeight = _screen->getFontHeight();
+
+ do {
+ char code = *cur;
+
+ if (code == 3) {
+ fillRectFlag = subWidth = true;
+ } else if (code == 5) {
+ centerFlag = true;
+ } else if (code == 4) {
+ if (fillRectFlag) {
+ _screen->fillRect(0, 0, 319, 20, 0);
+
+ if (subWidth)
+ specialX = 157 - _screen->getTextWidth(stringBuffer);
+
+ _screen->printText(stringBuffer, specialX + 8, 0, 31, 0);
+ }
+
+ specialString = stringBuffer;
+ *specialString = 0;
+
+ x = 161;
+ } else if (code == 13) {
+ if (!fillRectFlag)
+ _screen->fillRect(0, 0, 319, 20, 0);
+
+ uint32 nextTime = _system->getMillis() + 8 * _tickLength;
+
+ if (centerFlag)
+ x = (320 - _screen->getTextWidth(stringBuffer)) / 2 - 8;
+
+ _screen->printText(stringBuffer, x + 8, 0, 31, 0);
+
+ for (int i = 0; i < fontHeight && !shouldQuit(); ++i) {
+ _screen->copyRegion(0, 141, 0, 140, 320, 59, 0, 0, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(0, i, 0, 198, 320, 3, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ delayUntil(nextTime);
+ nextTime = _system->getMillis() + 8 * _tickLength;
+ }
+
+ specialString = stringBuffer;
+ *specialString = 0;
+
+ centerFlag = fillRectFlag = false;
+ } else {
+ *specialString++ = code;
+ *specialString = 0;
+ }
+
+ if (checkInput(0, false)) {
+ removeInputTop();
+ break;
+ }
+ } while (++cur != (creditsData + size) && !shouldQuit());
+}
+
+bool KyraEngine_LoK::seq_skipSequence() const {
+ return shouldQuit() || _abortIntroFlag;
+}
+
+int KyraEngine_LoK::handleMalcolmFlag() {
+ switch (_malcolmFlag) {
+ case 1:
+ _malcolmFrame = 0;
+ _malcolmFlag = 2;
+ _malcolmTimer2 = 0;
+ // fall through
+
+ case 2:
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 13) {
+ _malcolmFlag = 3;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
+ }
+ }
+ break;
+
+ case 3:
+ if (_system->getMillis() < _malcolmTimer1) {
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _malcolmFrame = _rnd.getRandomNumberRng(14, 17);
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ }
+ } else {
+ _malcolmFlag = 4;
+ _malcolmFrame = 18;
+ }
+ break;
+
+ case 4:
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 25) {
+ _malcolmFrame = 26;
+ _malcolmFlag = 5;
+ _beadStateVar = 1;
+ }
+ }
+ break;
+
+ case 5:
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 31) {
+ _malcolmFrame = 32;
+ _malcolmFlag = 6;
+ }
+ }
+ break;
+
+ case 6:
+ if (_unkEndSeqVar4) {
+ if (_malcolmFrame <= 33 && _system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 33) {
+ _malcolmFlag = 7;
+ _malcolmFrame = 32;
+ _unkEndSeqVar5 = 0;
+ }
+ }
+ }
+ break;
+
+ case 7:
+ if (_unkEndSeqVar5 == 1) {
+ _malcolmFlag = 8;
+ _malcolmFrame = 34;
+ } else if (_unkEndSeqVar5 == 2) {
+ _malcolmFlag = 3;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
+ }
+ break;
+
+ case 8:
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _finalA->displayFrame(_malcolmFrame, 0, 8, 46, 0, 0, 0);
+ _screen->updateScreen();
+ _malcolmTimer2 = _system->getMillis() + 8 * _tickLength;
+ ++_malcolmFrame;
+ if (_malcolmFrame > 37) {
+ _malcolmFlag = 0;
+ _deathHandler = 8;
+ return 1;
+ }
+ }
+ break;
+
+ case 9:
+ snd_playSoundEffect(12);
+ snd_playSoundEffect(12);
+ for (int i = 0; i < 18; ++i) {
+ _malcolmTimer2 = _system->getMillis() + 4 * _tickLength;
+ _finalC->displayFrame(i, 0, 16, 50, 0, 0, 0);
+ _screen->updateScreen();
+ delayUntil(_malcolmTimer2);
+ }
+ snd_playWanderScoreViaMap(51, 1);
+ delay(60 * _tickLength);
+ _malcolmFlag = 0;
+ return 1;
+
+ case 10:
+ if (!_beadStateVar) {
+ handleBeadState();
+ _screen->bitBlitRects();
+ assert(_veryClever);
+ _text->printTalkTextMessage(_veryClever[0], 60, 31, 5, 0, 2);
+ _malcolmTimer2 = _system->getMillis() + 180 * _tickLength;
+ _malcolmFlag = 11;
+ }
+ break;
+
+ case 11:
+ if (_system->getMillis() >= _malcolmTimer2) {
+ _text->restoreTalkTextMessageBkgd(2, 0);
+ _malcolmFlag = 3;
+ _malcolmTimer1 = _system->getMillis() + 180 * _tickLength;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int KyraEngine_LoK::handleBeadState() {
+ static const int table1[] = {
+ -1, -2, -4, -5, -6, -7, -6, -5,
+ -4, -2, -1, 0, 1, 2, 4, 5,
+ 6, 7, 6, 5, 4, 2, 1, 0, 0
+ };
+
+ static const int table2[] = {
+ 0, 0, 1, 1, 2, 2, 3, 3,
+ 4, 4, 5, 5, 5, 5, 4, 4,
+ 3, 3, 2, 2, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ switch (_beadStateVar) {
+ case 0:
+ if (_beadState1.x != -1 && _endSequenceBackUpRect) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ }
+
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
+ _beadStateTimer1 = 0;
+ _beadStateTimer2 = 0;
+ _lastDisplayedPanPage = 0;
+ return 1;
+
+ case 1:
+ if (_beadState1.x != -1) {
+ if (_endSequenceBackUpRect) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ }
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
+ }
+ _beadStateVar = 2;
+ break;
+
+ case 2:
+ if (_system->getMillis() >= _beadStateTimer1) {
+ int x = 0, y = 0;
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ if (_beadState1.x == -1) {
+ assert(_panPagesTable);
+ _beadState1.width2 = _animator->fetchAnimWidth(_panPagesTable[19], 256);
+ _beadState1.width = ((_beadState1.width2 + 7) >> 3) + 1;
+ _beadState1.height = _animator->fetchAnimHeight(_panPagesTable[19], 256);
+ if (!_endSequenceBackUpRect) {
+ _endSequenceBackUpRect = new uint8[(_beadState1.width * _beadState1.height) << 3];
+ assert(_endSequenceBackUpRect);
+ memset(_endSequenceBackUpRect, 0, ((_beadState1.width * _beadState1.height) << 3) * sizeof(uint8));
+ }
+ x = _beadState1.x = 60;
+ y = _beadState1.y = 40;
+ initBeadState(x, y, x, 25, 8, &_beadState2);
+ } else {
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
+ _beadStateVar = 3;
+ _beadStateTimer2 = _system->getMillis() + 240 * _tickLength;
+ _unkEndSeqVar4 = 0;
+ _beadState1.dstX = _beadState1.x;
+ _beadState1.dstY = _beadState1.y;
+ return 0;
+ } else {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ }
+ }
+
+ _screen->copyRegionToBuffer(_screen->_curPage, x, y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
+
+ if (_lastDisplayedPanPage > 17)
+ _lastDisplayedPanPage = 0;
+
+ _screen->addBitBlitRect(x, y, _beadState1.width2, _beadState1.height);
+ }
+ break;
+
+ case 3:
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + 4 * _tickLength;
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+
+ _beadState1.x = _beadState1.dstX + table1[_beadState1.tableIndex];
+ _beadState1.y = _beadState1.dstY + table2[_beadState1.tableIndex];
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], _beadState1.x, _beadState1.y, 0, 0);
+ if (_lastDisplayedPanPage >= 17)
+ _lastDisplayedPanPage = 0;
+
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+
+ ++_beadState1.tableIndex;
+ if (_beadState1.tableIndex > 24) {
+ _beadState1.tableIndex = 0;
+ _unkEndSeqVar4 = 1;
+ }
+ if (_system->getMillis() > _beadStateTimer2 && _malcolmFlag == 7 && !_unkAmuletVar && !_text->printed()) {
+ snd_playSoundEffect(0x0B);
+ if (_currentCharacter->x1 > 233 && _currentCharacter->x1 < 305 && _currentCharacter->y1 > 85 && _currentCharacter->y1 < 105 &&
+ (_brandonStatusBit & 0x20)) {
+ _beadState1.unk8 = 290;
+ _beadState1.unk9 = 40;
+ _beadStateVar = 5;
+ } else {
+ _beadStateVar = 4;
+ _beadState1.unk8 = _currentCharacter->x1 - 4;
+ _beadState1.unk9 = _currentCharacter->y1 - 30;
+ }
+
+ if (_text->printed())
+ _text->restoreTalkTextMessageBkgd(2, 0);
+
+ initBeadState(_beadState1.x, _beadState1.y, _beadState1.unk8, _beadState1.unk9, 12, &_beadState2);
+ _lastDisplayedPanPage = 18;
+ }
+ }
+ break;
+
+ case 4:
+ if (_system->getMillis() >= _beadStateTimer1) {
+ int x = 0, y = 0;
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
+ if (_brandonStatusBit & 20) {
+ _unkEndSeqVar5 = 2;
+ _beadStateVar = 6;
+ } else {
+ snd_playWanderScoreViaMap(52, 1);
+ snd_playSoundEffect(0x0C);
+ _unkEndSeqVar5 = 1;
+ _beadStateVar = 0;
+ }
+ } else {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
+ if (_lastDisplayedPanPage > 17) {
+ _lastDisplayedPanPage = 0;
+ }
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ }
+ }
+ break;
+
+ case 5:
+ if (_system->getMillis() >= _beadStateTimer1) {
+ _beadStateTimer1 = _system->getMillis() + _tickLength;
+ int x = 0, y = 0;
+ if (processBead(_beadState1.x, _beadState1.y, x, y, &_beadState2)) {
+ if (_beadState2.dstX == 290) {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ uint32 nextRun = 0;
+ for (int i = 0; i < 8; ++i) {
+ nextRun = _system->getMillis() + _tickLength;
+ _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0);
+ _screen->updateScreen();
+ delayUntil(nextRun);
+ }
+ snd_playSoundEffect(0x0D);
+ for (int i = 7; i >= 0; --i) {
+ nextRun = _system->getMillis() + _tickLength;
+ _finalB->displayFrame(i, 0, 224, 8, 0, 0, 0);
+ _screen->updateScreen();
+ delayUntil(nextRun);
+ }
+ initBeadState(_beadState1.x, _beadState1.y, 63, 60, 12, &_beadState2);
+ } else {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = -1;
+ _beadState1.tableIndex = 0;
+ _beadStateVar = 0;
+ _malcolmFlag = 9;
+ }
+ } else {
+ _screen->copyBlockToPage(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadState1.x = x;
+ _beadState1.y = y;
+ _screen->copyRegionToBuffer(_screen->_curPage, _beadState1.x, _beadState1.y, _beadState1.width << 3, _beadState1.height, _endSequenceBackUpRect);
+ _screen->drawShape(2, _panPagesTable[_lastDisplayedPanPage++], x, y, 0, 0);
+ if (_lastDisplayedPanPage > 17)
+ _lastDisplayedPanPage = 0;
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ }
+ }
+ break;
+
+ case 6:
+ _screen->drawShape(2, _panPagesTable[19], _beadState1.x, _beadState1.y, 0, 0);
+ _screen->addBitBlitRect(_beadState1.x, _beadState1.y, _beadState1.width2, _beadState1.height);
+ _beadStateVar = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void KyraEngine_LoK::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) {
+ ptr->unk9 = unk;
+ int xDiff = x2 - x;
+ int yDiff = y2 - y;
+ int unk1 = 0, unk2 = 0;
+ if (xDiff > 0)
+ unk1 = 1;
+ else if (xDiff == 0)
+ unk1 = 0;
+ else
+ unk1 = -1;
+
+
+ if (yDiff > 0)
+ unk2 = 1;
+ else if (yDiff == 0)
+ unk2 = 0;
+ else
+ unk2 = -1;
+
+ xDiff = ABS(xDiff);
+ yDiff = ABS(yDiff);
+
+ ptr->y = 0;
+ ptr->x = 0;
+ ptr->width = xDiff;
+ ptr->height = yDiff;
+ ptr->dstX = x2;
+ ptr->dstY = y2;
+ ptr->width2 = unk1;
+ ptr->unk8 = unk2;
+}
+
+int KyraEngine_LoK::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
+ if (x == ptr->dstX && y == ptr->dstY)
+ return 1;
+
+ int xPos = x, yPos = y;
+ if (ptr->width >= ptr->height) {
+ for (int i = 0; i < ptr->unk9; ++i) {
+ ptr->y += ptr->height;
+ if (ptr->y >= ptr->width) {
+ ptr->y -= ptr->width;
+ yPos += ptr->unk8;
+ }
+ xPos += ptr->width2;
+ }
+ } else {
+ for (int i = 0; i < ptr->unk9; ++i) {
+ ptr->x += ptr->width;
+ if (ptr->x >= ptr->height) {
+ ptr->x -= ptr->height;
+ xPos += ptr->width2;
+ }
+ yPos += ptr->unk8;
+ }
+ }
+
+ int temp = ABS(x - ptr->dstX);
+ if (ptr->unk9 > temp)
+ xPos = ptr->dstX;
+ temp = ABS(y - ptr->dstY);
+ if (ptr->unk9 > temp)
+ yPos = ptr->dstY;
+ x2 = xPos;
+ y2 = yPos;
+ return 0;
+}
+
+void KyraEngine_LoK::setupPanPages() {
+ _screen->savePageToDisk("BKGD.PG", 2);
+ _screen->loadBitmap("BEAD.CPS", 3, 3, 0);
+ if (_flags.platform == Common::kPlatformMacintosh || _flags.platform == Common::kPlatformAmiga) {
+ int pageBackUp = _screen->_curPage;
+ _screen->_curPage = 2;
+
+ delete[] _panPagesTable[19];
+ _panPagesTable[19] = _screen->encodeShape(0, 0, 16, 9, 0);
+ assert(_panPagesTable[19]);
+
+ int curX = 16;
+ for (int i = 0; i < 19; ++i) {
+ delete[] _panPagesTable[i];
+ _panPagesTable[i] = _screen->encodeShape(curX, 0, 8, 5, 0);
+ assert(_panPagesTable[i]);
+ curX += 8;
+ }
+
+ _screen->_curPage = pageBackUp;
+ } else {
+ for (int i = 0; i <= 19; ++i) {
+ delete[] _panPagesTable[i];
+ _panPagesTable[i] = _seq->setPanPages(3, i);
+ assert(_panPagesTable[i]);
+ }
+ }
+ _screen->loadPageFromDisk("BKGD.PG", 2);
+}
+
+void KyraEngine_LoK::freePanPages() {
+ delete[] _endSequenceBackUpRect;
+ _endSequenceBackUpRect = 0;
+ for (int i = 0; i <= 19; ++i) {
+ delete[] _panPagesTable[i];
+ _panPagesTable[i] = 0;
+ }
+}
+
+void KyraEngine_LoK::closeFinalWsa() {
+ delete _finalA;
+ _finalA = 0;
+ delete _finalB;
+ _finalB = 0;
+ delete _finalC;
+ _finalC = 0;
+ freePanPages();
+ _endSequenceNeedLoading = 1;
+}
+
+void KyraEngine_LoK::updateKyragemFading() {
+ if (_flags.platform == Common::kPlatformAmiga) {
+ // The AMIGA version seems to have no fading for the Kyragem. The code does not
+ // alter the screen palette.
+ //
+ // TODO: Check this in the original.
+ return;
+ }
+
+ static const uint8 kyraGemPalette[0x28] = {
+ 0x3F, 0x3B, 0x38, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x25, 0x22,
+ 0x1F, 0x1C, 0x19, 0x16, 0x12, 0x0F, 0x0C, 0x0A, 0x06, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ if (_system->getMillis() < _kyragemFadingState.timerCount)
+ return;
+
+ _kyragemFadingState.timerCount = _system->getMillis() + 4 * _tickLength;
+
+ int palPos = 684;
+ for (int i = 0; i < 20; ++i) {
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.rOffset];
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.gOffset];
+ _screen->getPalette(0)[palPos++] = kyraGemPalette[i + _kyragemFadingState.bOffset];
+ }
+
+ _screen->setScreenPalette(_screen->getPalette(0));
+
+ switch (_kyragemFadingState.nextOperation) {
+ case 0:
+ --_kyragemFadingState.bOffset;
+ if (_kyragemFadingState.bOffset >= 1)
+ return;
+ _kyragemFadingState.nextOperation = 1;
+ break;
+
+ case 1:
+ ++_kyragemFadingState.rOffset;
+ if (_kyragemFadingState.rOffset < 19)
+ return;
+ _kyragemFadingState.nextOperation = 2;
+ break;
+
+ case 2:
+ --_kyragemFadingState.gOffset;
+ if (_kyragemFadingState.gOffset >= 1)
+ return;
+ _kyragemFadingState.nextOperation = 3;
+ break;
+
+ case 3:
+ ++_kyragemFadingState.bOffset;
+ if (_kyragemFadingState.bOffset < 19)
+ return;
+ _kyragemFadingState.nextOperation = 4;
+ break;
+
+ case 4:
+ --_kyragemFadingState.rOffset;
+ if (_kyragemFadingState.rOffset >= 1)
+ return;
+ _kyragemFadingState.nextOperation = 5;
+ break;
+
+ case 5:
+ ++_kyragemFadingState.gOffset;
+ if (_kyragemFadingState.gOffset < 19)
+ return;
+ _kyragemFadingState.nextOperation = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ _kyragemFadingState.timerCount = _system->getMillis() + 120 * _tickLength;
+}
+
+void KyraEngine_LoK::drawJewelPress(int jewel, int drawSpecial) {
+ _screen->hideMouse();
+ int shape = 0;
+
+ if (drawSpecial)
+ shape = 0x14E;
+ else
+ shape = jewel + 0x149;
+
+ snd_playSoundEffect(0x45);
+ _screen->drawShape(0, _shapes[shape], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ delayWithTicks(2);
+
+ if (drawSpecial)
+ shape = 0x148;
+ else
+ shape = jewel + 0x143;
+
+ _screen->drawShape(0, _shapes[shape], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ _screen->showMouse();
+}
+
+void KyraEngine_LoK::drawJewelsFadeOutStart() {
+ static const uint16 jewelTable1[] = { 0x164, 0x15F, 0x15A, 0x155, 0x150, 0xFFFF };
+ static const uint16 jewelTable2[] = { 0x163, 0x15E, 0x159, 0x154, 0x14F, 0xFFFF };
+ static const uint16 jewelTable3[] = { 0x166, 0x160, 0x15C, 0x157, 0x152, 0xFFFF };
+ static const uint16 jewelTable4[] = { 0x165, 0x161, 0x15B, 0x156, 0x151, 0xFFFF };
+ for (int i = 0; jewelTable1[i] != 0xFFFF; ++i) {
+ if (queryGameFlag(0x57))
+ _screen->drawShape(0, _shapes[jewelTable1[i]], _amuletX2[2], _amuletY2[2], 0, 0);
+ if (queryGameFlag(0x59))
+ _screen->drawShape(0, _shapes[jewelTable3[i]], _amuletX2[4], _amuletY2[4], 0, 0);
+ if (queryGameFlag(0x56))
+ _screen->drawShape(0, _shapes[jewelTable2[i]], _amuletX2[1], _amuletY2[1], 0, 0);
+ if (queryGameFlag(0x58))
+ _screen->drawShape(0, _shapes[jewelTable4[i]], _amuletX2[3], _amuletY2[3], 0, 0);
+ _screen->updateScreen();
+ delayWithTicks(3);
+ }
+}
+
+void KyraEngine_LoK::drawJewelsFadeOutEnd(int jewel) {
+ static const uint16 jewelTable[] = { 0x153, 0x158, 0x15D, 0x162, 0x148, 0xFFFF };
+ int newDelay = 0;
+
+ switch (jewel - 1) {
+ case 2:
+ if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198)
+ newDelay = 18900;
+ else
+ newDelay = 8100;
+ break;
+
+ default:
+ newDelay = 3600;
+ }
+
+ setGameFlag(0xF1);
+ _timer->setCountdown(19, newDelay);
+ _screen->hideMouse();
+ for (int i = 0; jewelTable[i] != 0xFFFF; ++i) {
+ uint16 shape = jewelTable[i];
+ if (queryGameFlag(0x57))
+ _screen->drawShape(0, _shapes[shape], _amuletX2[2], _amuletY2[2], 0, 0);
+ if (queryGameFlag(0x59))
+ _screen->drawShape(0, _shapes[shape], _amuletX2[4], _amuletY2[4], 0, 0);
+ if (queryGameFlag(0x56))
+ _screen->drawShape(0, _shapes[shape], _amuletX2[1], _amuletY2[1], 0, 0);
+ if (queryGameFlag(0x58))
+ _screen->drawShape(0, _shapes[shape], _amuletX2[3], _amuletY2[3], 0, 0);
+
+ _screen->updateScreen();
+ delayWithTicks(3);
+ }
+ _screen->showMouse();
+}
+
+} // End of namespace Kyra