aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOystein Eftevaag2006-02-09 07:37:19 +0000
committerOystein Eftevaag2006-02-09 07:37:19 +0000
commit56d918edbe5feecb4c0239a8927adb60602ae154 (patch)
treed1e167b1b890d3718d60c734149518f9d75a3907
parent91222cc6acacc2a399ac982eae61d5c0f204bbb9 (diff)
downloadscummvm-rg350-56d918edbe5feecb4c0239a8927adb60602ae154.tar.gz
scummvm-rg350-56d918edbe5feecb4c0239a8927adb60602ae154.tar.bz2
scummvm-rg350-56d918edbe5feecb4c0239a8927adb60602ae154.zip
Moved tons of code out of kyra.cpp, and removed three redundant functions (two stubs
to sound functions, and one duplicate function (one with 'posion' in the name, one with 'poison'). The bulk of the moved code is moved to the newly created files items.cpp, scene.cpp and sequences.cpp svn-id: r20437
-rw-r--r--kyra/animator.cpp42
-rw-r--r--kyra/animator.h1
-rw-r--r--kyra/gui.cpp8
-rw-r--r--kyra/items.cpp981
-rw-r--r--kyra/kyra.cpp4252
-rw-r--r--kyra/kyra.h20
-rw-r--r--kyra/module.mk3
-rw-r--r--kyra/resource.cpp44
-rw-r--r--kyra/scene.cpp1579
-rw-r--r--kyra/screen.cpp154
-rw-r--r--kyra/screen.h14
-rw-r--r--kyra/script_v1.cpp8
-rw-r--r--kyra/seqplayer.cpp3
-rw-r--r--kyra/sequences.cpp968
-rw-r--r--kyra/sound.cpp85
-rw-r--r--kyra/staticres.cpp140
-rw-r--r--kyra/text.cpp332
17 files changed, 4361 insertions, 4273 deletions
diff --git a/kyra/animator.cpp b/kyra/animator.cpp
index df616f5965..057bb0cbeb 100644
--- a/kyra/animator.cpp
+++ b/kyra/animator.cpp
@@ -65,6 +65,48 @@ void ScreenAnimator::close() {
}
}
+void ScreenAnimator::initAnimStateList() {
+ AnimObject *animStates = _screenObjects;
+ animStates[0].index = 0;
+ animStates[0].active = 1;
+ animStates[0].flags = 0x800;
+ animStates[0].background = _vm->_shapes[2];
+ animStates[0].rectSize = _screen->getRectSize(4, 48);
+ animStates[0].width = 4;
+ animStates[0].height = 48;
+ animStates[0].width2 = 4;
+ animStates[0].height2 = 3;
+
+ for (int i = 1; i <= 4; ++i) {
+ animStates[i].index = i;
+ animStates[i].active = 0;
+ animStates[i].flags = 0x800;
+ animStates[i].background = _vm->_shapes[3];
+ animStates[i].rectSize = _screen->getRectSize(4, 64);
+ animStates[i].width = 4;
+ animStates[i].height = 48;
+ animStates[i].width2 = 4;
+ animStates[i].height2 = 3;
+ }
+
+ for (int i = 5; i < 16; ++i) {
+ animStates[i].index = i;
+ animStates[i].active = 0;
+ animStates[i].flags = 0;
+ }
+
+ for (int i = 16; i < 28; ++i) {
+ animStates[i].index = i;
+ animStates[i].flags = 0;
+ animStates[i].background = _vm->_shapes[349+i];
+ animStates[i].rectSize = _screen->getRectSize(3, 24);
+ animStates[i].width = 3;
+ animStates[i].height = 16;
+ animStates[i].width2 = 0;
+ animStates[i].height2 = 0;
+ }
+}
+
void ScreenAnimator::preserveAllBackgrounds() {
debug(9, "ScreenAnimator::preserveAllBackgrounds()");
uint8 curPage = _screen->_curPage;
diff --git a/kyra/animator.h b/kyra/animator.h
index cb6b8e2609..a20e2ae193 100644
--- a/kyra/animator.h
+++ b/kyra/animator.h
@@ -62,6 +62,7 @@ public:
AnimObject *items() { return _items; }
AnimObject *sprites() { return _sprites; }
+ void initAnimStateList();
void preserveAllBackgrounds();
void flagAllObjectsForBkgdChange();
void flagAllObjectsForRefresh();
diff --git a/kyra/gui.cpp b/kyra/gui.cpp
index 668e33459d..990b91cf6b 100644
--- a/kyra/gui.cpp
+++ b/kyra/gui.cpp
@@ -29,6 +29,14 @@
#include "common/system.h"
namespace Kyra {
+
+void KyraEngine::initMainButtonList() {
+ _buttonList = &_buttonData[0];
+ for (int i = 0; _buttonDataListPtr[i]; ++i) {
+ _buttonList = initButton(_buttonList, _buttonDataListPtr[i]);
+ }
+}
+
Button *KyraEngine::initButton(Button *list, Button *newButton) {
if (!newButton)
return list;
diff --git a/kyra/items.cpp b/kyra/items.cpp
new file mode 100644
index 0000000000..2f48433d7e
--- /dev/null
+++ b/kyra/items.cpp
@@ -0,0 +1,981 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * 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.
+ *
+ * $Header$
+ *
+ */
+
+#include "kyra/kyra.h"
+#include "kyra/seqplayer.h"
+#include "kyra/screen.h"
+#include "kyra/resource.h"
+#include "kyra/sound.h"
+#include "kyra/sprites.h"
+#include "kyra/wsamovie.h"
+#include "kyra/animator.h"
+#include "kyra/text.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+
+namespace Kyra {
+
+int KyraEngine::findDuplicateItemShape(int shape) {
+ static uint8 dupTable[] = {
+ 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47,
+ 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a,
+ 0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF
+ };
+
+ int i = 0;
+
+ while (dupTable[i] != 0xFF) {
+ if (dupTable[i] == shape)
+ return dupTable[i+1];
+ i += 2;
+ }
+ return -1;
+}
+
+void KyraEngine::addToNoDropRects(int x, int y, int w, int h) {
+ debug(9, "KyraEngine::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h);
+ for (int rect = 0; rect < 11; ++rect) {
+ if (_noDropRects[rect].x == -1) {
+ _noDropRects[rect].x = x;
+ _noDropRects[rect].y = y;
+ _noDropRects[rect].x2 = x + w - 1;
+ _noDropRects[rect].y2 = y + h - 1;
+ break;
+ }
+ }
+}
+
+void KyraEngine::clearNoDropRects() {
+ debug(9, "KyraEngine::clearNoDropRects()");
+ memset(_noDropRects, -1, sizeof(_noDropRects));
+}
+
+byte KyraEngine::findFreeItemInScene(int scene) {
+ debug(9, "KyraEngine::findFreeItemInScene(%d)", scene);
+ assert(scene < _roomTableSize);
+ Room *room = &_roomTable[scene];
+ for (int i = 0; i < 12; ++i) {
+ if (room->itemsTable[i] == 0xFF)
+ return i;
+ }
+ return 0xFF;
+}
+
+byte KyraEngine::findItemAtPos(int x, int y) {
+ debug(9, "KyraEngine::findItemAtPos(%d, %d)", x, y);
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable;
+ const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos;
+ const uint8 *yposOffset = _roomTable[_currentCharacter->sceneId].itemsYPos;
+
+ int highestYPos = -1;
+ byte returnValue = 0xFF;
+
+ for (int i = 0; i < 12; ++i) {
+ if (*itemsTable != 0xFF) {
+ int xpos = *xposOffset - 11;
+ int xpos2 = *xposOffset + 10;
+ if (x > xpos && x < xpos2) {
+ assert(*itemsTable < ARRAYSIZE(_itemTable));
+ int itemHeight = _itemTable[*itemsTable].height;
+ int ypos = *yposOffset + 3;
+ int ypos2 = ypos - itemHeight - 3;
+
+ if (y > ypos2 && ypos > y) {
+ if (highestYPos <= ypos) {
+ returnValue = i;
+ highestYPos = ypos;
+ }
+ }
+ }
+ }
+ ++xposOffset;
+ ++yposOffset;
+ ++itemsTable;
+ }
+
+ return returnValue;
+}
+
+void KyraEngine::placeItemInGenericMapScene(int item, int index) {
+ debug(9, "KyraEngine::placeItemInGenericMapScene(%d, %d)", item, index);
+ static const uint16 itemMapSceneMinTable[] = {
+ 0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000
+ };
+ static const uint16 itemMapSceneMaxTable[] = {
+ 0x0010, 0x0024, 0x00C6, 0x006C, 0x00F5, 0x0000
+ };
+
+ int minValue = itemMapSceneMinTable[index];
+ int maxValue = itemMapSceneMaxTable[index];
+
+ while (true) {
+ int room = _rnd.getRandomNumberRng(minValue, maxValue);
+ assert(room < _roomTableSize);
+ int nameIndex = _roomTable[room].nameIndex;
+ bool placeItem = false;
+
+ switch (nameIndex) {
+ case 0: case 1: case 2: case 3:
+ case 4: case 5: case 6: case 11:
+ case 12: case 16: case 17: case 20:
+ case 22: case 23: case 25: case 26:
+ case 27: case 31: case 33: case 34:
+ case 36: case 37: case 58: case 59:
+ case 60: case 61: case 83: case 84:
+ case 85: case 104: case 105: case 106:
+ placeItem = true;
+ break;
+
+ case 51:
+ if (room != 46) {
+ placeItem = true;
+ break;
+ }
+ default:
+ placeItem = false;
+ break;
+ }
+
+ if (placeItem) {
+ Room *roomPtr = &_roomTable[room];
+ if (roomPtr->northExit == 0xFFFF && roomPtr->eastExit == 0xFFFF && roomPtr->southExit == 0xFFFF && roomPtr->westExit == 0xFFFF) {
+ placeItem = false;
+ } else if (_currentCharacter->sceneId == room) {
+ placeItem = false;
+ }
+ }
+
+ if (placeItem) {
+ if (!processItemDrop(room, item, -1, -1, 2, 0))
+ continue;
+ break;
+ }
+ }
+}
+
+void KyraEngine::createMouseItem(int item) {
+ debug(9, "KyraEngine::createMouseItem(%d)", item);
+ _screen->hideMouse();
+ setMouseItem(item);
+ _itemInHand = item;
+ _screen->showMouse();
+}
+
+void KyraEngine::destroyMouseItem() {
+ debug(9, "KyraEngine::destroyMouseItem()");
+ _screen->hideMouse();
+ _screen->setMouseCursor(1, 1, _shapes[4]);
+ _itemInHand = -1;
+ _screen->showMouse();
+}
+
+void KyraEngine::setMouseItem(int item) {
+ debug(9, "KyraEngine::setMouseItem(%d)", item);
+ if (item == -1) {
+ _screen->setMouseCursor(1, 1, _shapes[10]);
+ } else {
+ _screen->setMouseCursor(8, 15, _shapes[220+item]);
+ }
+}
+
+void KyraEngine::wipeDownMouseItem(int xpos, int ypos) {
+ debug(9, "KyraEngine::wipeDownMouseItem(%d, %d)", xpos, ypos);
+ if (_itemInHand == -1)
+ return;
+ xpos -= 8;
+ ypos -= 15;
+ _screen->hideMouse();
+ _screen->backUpRect1(xpos, ypos);
+ int y = ypos;
+ int height = 16;
+
+ while (height >= 0) {
+ _screen->restoreRect1(xpos, ypos);
+ _screen->setNewShapeHeight(_shapes[220+_itemInHand], height);
+ uint32 nextTime = _system->getMillis() + 1 * _tickLength;
+ _screen->drawShape(0, _shapes[220+_itemInHand], xpos, y, 0, 0);
+ _screen->updateScreen();
+ y += 2;
+ height -= 2;
+ while (_system->getMillis() < nextTime) {}
+ }
+ _screen->restoreRect1(xpos, ypos);
+ _screen->resetShapeHeight(_shapes[220+_itemInHand]);
+ destroyMouseItem();
+ _screen->showMouse();
+}
+
+void KyraEngine::setupSceneItems() {
+ debug(9, "KyraEngine::setupSceneItems()");
+ uint16 sceneId = _currentCharacter->sceneId;
+ assert(sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[sceneId];
+ for (int i = 0; i < 12; ++i) {
+ uint8 item = currentRoom->itemsTable[i];
+ if (item == 0xFF || !currentRoom->needInit[i]) {
+ continue;
+ }
+
+ int xpos = 0;
+ int ypos = 0;
+
+ if (currentRoom->itemsXPos[i] == 0xFFFF) {
+ xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
+ ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
+ } else {
+ xpos = currentRoom->itemsXPos[i];
+ ypos = currentRoom->itemsYPos[i];
+ }
+
+ _lastProcessedItem = i;
+
+ int stop = 0;
+ while (!stop) {
+ stop = processItemDrop(sceneId, item, xpos, ypos, 3, 0);
+ if (!stop) {
+ xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
+ ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
+ if (countItemsInScene(sceneId) >= 12) {
+ break;
+ }
+ } else {
+ currentRoom->needInit[i] = 0;
+ }
+ }
+ }
+}
+
+int KyraEngine::countItemsInScene(uint16 sceneId) {
+ debug(9, "KyraEngine::countItemsInScene(%d)", sceneId);
+ assert(sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[sceneId];
+
+ int items = 0;
+
+ for (int i = 0; i < 12; ++i) {
+ if (currentRoom->itemsTable[i] != 0xFF) {
+ ++items;
+ }
+ }
+
+ return items;
+}
+
+int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) {
+ debug(9, "KyraEngine::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
+ int freeItem = -1;
+ uint8 itemIndex = findItemAtPos(x, y);
+ if (unk1) {
+ itemIndex = 0xFF;
+ }
+
+ if (itemIndex != 0xFF) {
+ exchangeItemWithMouseItem(sceneId, itemIndex);
+ return 0;
+ }
+
+ assert(sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[sceneId];
+
+ if (unk1 != 3) {
+ for (int i = 0; i < 12; ++i) {
+ if (currentRoom->itemsTable[i] == 0xFF) {
+ freeItem = i;
+ break;
+ }
+ }
+ } else {
+ freeItem = _lastProcessedItem;
+ }
+
+ if (freeItem == -1) {
+ return 0;
+ }
+
+ if (sceneId != _currentCharacter->sceneId) {
+ addItemToRoom(sceneId, item, freeItem, x, y);
+ return 1;
+ }
+
+ int itemHeight = _itemTable[item].height;
+ _lastProcessedItemHeight = itemHeight;
+
+ if (x == -1 && x == -1) {
+ x = _rnd.getRandomNumberRng(16, 304);
+ y = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 135);
+ }
+
+ int xpos = x;
+ int ypos = y;
+ int destY = -1;
+ int destX = -1;
+ int running = 1;
+
+ while (running) {
+ if ((_northExitHeight & 0xFF) <= ypos) {
+ bool running2 = true;
+
+ if (_screen->getDrawLayer(xpos, ypos) > 1) {
+ if (((_northExitHeight >> 8) & 0xFF) != ypos) {
+ running2 = false;
+ }
+ }
+
+ if (_screen->getDrawLayer2(xpos, ypos, itemHeight) > 1) {
+ if (((_northExitHeight >> 8) & 0xFF) != ypos) {
+ running2 = false;
+ }
+ }
+
+ if (!isDropable(xpos, ypos)) {
+ if (((_northExitHeight >> 8) & 0xFF) != ypos) {
+ running2 = false;
+ }
+ }
+
+ int xpos2 = xpos;
+ int xpos3 = xpos;
+
+ while (running2) {
+ if (isDropable(xpos2, ypos)) {
+ if (_screen->getDrawLayer2(xpos2, ypos, itemHeight) < 7) {
+ if (findItemAtPos(xpos2, ypos) == 0xFF) {
+ destX = xpos2;
+ destY = ypos;
+ running = 0;
+ running2 = false;
+ }
+ }
+ }
+
+ if (isDropable(xpos3, ypos)) {
+ if (_screen->getDrawLayer2(xpos3, ypos, itemHeight) < 7) {
+ if (findItemAtPos(xpos3, ypos) == 0xFF) {
+ destX = xpos3;
+ destY = ypos;
+ running = 0;
+ running2 = false;
+ }
+ }
+ }
+
+ if (!running2)
+ continue;
+
+ xpos2 -= 2;
+ if (xpos2 < 16) {
+ xpos2 = 16;
+ }
+
+ xpos3 += 2;
+ if (xpos3 > 304) {
+ xpos3 = 304;
+ }
+
+ if (xpos2 > 16)
+ continue;
+ if (xpos3 < 304)
+ continue;
+ running2 = false;
+ }
+ }
+
+ if (((_northExitHeight >> 8) & 0xFF) == ypos) {
+ running = 0;
+ destY -= _rnd.getRandomNumberRng(0, 3);
+
+ if ((_northExitHeight & 0xFF) < destY) {
+ continue;
+ }
+
+ destY = (_northExitHeight & 0xFF) + 1;
+ continue;
+ }
+ ypos += 2;
+ if (((_northExitHeight >> 8) & 0xFF) >= ypos) {
+ continue;
+ }
+ ypos = (_northExitHeight >> 8) & 0xFF;
+ }
+
+ if (destX == -1 || destY == -1) {
+ return 0;
+ }
+
+ if (unk1 == 3) {
+ currentRoom->itemsXPos[freeItem] = destX;
+ currentRoom->itemsYPos[freeItem] = destY;
+ return 1;
+ }
+
+ if (unk1 == 2) {
+ itemSpecialFX(x, y, item);
+ }
+
+ if (unk1 == 0) {
+ destroyMouseItem();
+ }
+
+ itemDropDown(x, y, destX, destY, freeItem, item);
+
+ if (unk1 == 0 && unk2 != 0) {
+ assert(_itemList && _droppedList);
+ updateSentenceCommand(_itemList[item], _droppedList[0], 179);
+ }
+
+ return 1;
+}
+
+void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
+ debug(9, "KyraEngine::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex);
+ _screen->hideMouse();
+ _animator->animRemoveGameItem(itemIndex);
+ assert(sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[sceneId];
+
+ int item = currentRoom->itemsTable[itemIndex];
+ currentRoom->itemsTable[itemIndex] = _itemInHand;
+ _itemInHand = item;
+ _animator->animAddGameItem(itemIndex, sceneId);
+ snd_playSoundEffect(53);
+
+ setMouseItem(_itemInHand);
+ assert(_itemList && _takenList);
+ updateSentenceCommand(_itemList[_itemInHand], _takenList[1], 179);
+ _screen->showMouse();
+ clickEventHandler2();
+}
+
+void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) {
+ debug(9, "KyraEngine::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y);
+ assert(sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[sceneId];
+ currentRoom->itemsTable[itemIndex] = item;
+ currentRoom->itemsXPos[itemIndex] = x;
+ currentRoom->itemsYPos[itemIndex] = y;
+ currentRoom->needInit[itemIndex] = 1;
+}
+
+int KyraEngine::checkNoDropRects(int x, int y) {
+ debug(9, "KyraEngine::checkNoDropRects(%d, %d)", x, y);
+ if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16) {
+ _lastProcessedItemHeight = 16;
+ }
+ if (_noDropRects[0].x == -1) {
+ return 0;
+ }
+
+ for (int i = 0; i < 11; ++i) {
+ if (_noDropRects[i].x == -1) {
+ break;
+ }
+
+ int xpos = _noDropRects[i].x;
+ int ypos = _noDropRects[i].y;
+ int xpos2 = _noDropRects[i].x2;
+ int ypos2 = _noDropRects[i].y2;
+
+ if (xpos > x + 16)
+ continue;
+ if (xpos2 < x)
+ continue;
+ if (y < ypos)
+ continue;
+ if (ypos2 < y - _lastProcessedItemHeight)
+ continue;
+ return 1;
+ }
+
+ return 0;
+}
+
+int KyraEngine::isDropable(int x, int y) {
+ debug(9, "KyraEngine::isDropable(%d, %d)", x, y);
+ x -= 8;
+ y -= 1;
+
+ if (checkNoDropRects(x, y)) {
+ return 0;
+ }
+
+ for (int xpos = x; xpos < x + 16; ++xpos) {
+ if (_screen->getShapeFlag1(xpos, y) == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) {
+ debug(9, "KyraEngine::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item);
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
+ if (x == destX && y == destY) {
+ currentRoom->itemsXPos[freeItem] = destX;
+ currentRoom->itemsYPos[freeItem] = destY;
+ currentRoom->itemsTable[freeItem] = item;
+ snd_playSoundEffect(0x32);
+ _animator->animAddGameItem(freeItem, _currentCharacter->sceneId);
+ return;
+ }
+ _screen->hideMouse();
+ if (y <= destY) {
+ int tempY = y;
+ int addY = 2;
+ int drawX = x - 8;
+ int drawY = 0;
+
+ _screen->backUpRect0(drawX, y - 16);
+
+ while (tempY < destY) {
+ _screen->restoreRect0(drawX, tempY - 16);
+ tempY += addY;
+ if (tempY > destY) {
+ tempY = destY;
+ }
+ ++addY;
+ drawY = tempY - 16;
+ _screen->backUpRect0(drawX, drawY);
+ uint32 nextTime = _system->getMillis() + 1 * _tickLength;
+ _screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if ((nextTime - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+
+ bool skip = false;
+ if (x == destX) {
+ if (destY - y <= 16) {
+ skip = true;
+ }
+ }
+
+ if (!skip) {
+ snd_playSoundEffect(0x47);
+ if (addY < 6)
+ addY = 6;
+
+ int xDiff = (destX - x) << 4;
+ xDiff /= addY;
+ int startAddY = addY;
+ addY >>= 1;
+ if (destY - y <= 8) {
+ addY >>= 1;
+ }
+ addY = -addY;
+ int unkX = x << 4;
+ while (--startAddY) {
+ drawX = (unkX >> 4) - 8;
+ drawY = tempY - 16;
+ _screen->restoreRect0(drawX, drawY);
+ tempY += addY;
+ unkX += xDiff;
+ if (tempY > destY) {
+ tempY = destY;
+ }
+ ++addY;
+ drawX = (unkX >> 4) - 8;
+ drawY = tempY - 16;
+ _screen->backUpRect0(drawX, drawY);
+ uint32 nextTime = _system->getMillis() + 1 * _tickLength;
+ _screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if ((nextTime - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+ _screen->restoreRect0(drawX, drawY);
+ } else {
+ _screen->restoreRect0(drawX, tempY - 16);
+ }
+ }
+ currentRoom->itemsXPos[freeItem] = destX;
+ currentRoom->itemsYPos[freeItem] = destY;
+ currentRoom->itemsTable[freeItem] = item;
+ snd_playSoundEffect(0x32);
+ _animator->animAddGameItem(freeItem, _currentCharacter->sceneId);
+ _screen->showMouse();
+}
+
+void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) {
+ debug(9, "KyraEngine::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
+ if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2))
+ return;
+ snd_playSoundEffect(54);
+ if (12 == countItemsInScene(_currentCharacter->sceneId)) {
+ assert(_noDropList);
+ drawSentenceCommand(_noDropList[0], 6);
+ } else {
+ assert(_noDropList);
+ drawSentenceCommand(_noDropList[1], 6);
+ }
+}
+
+void KyraEngine::itemSpecialFX(int x, int y, int item) {
+ debug(9, "KyraEngine::itemSpecialFX(%d, %d, %d)", x, y, item);
+ if (item == 41) {
+ itemSpecialFX1(x, y, item);
+ } else {
+ itemSpecialFX2(x, y, item);
+ }
+}
+
+void KyraEngine::itemSpecialFX1(int x, int y, int item) {
+ debug(9, "KyraEngine::itemSpecialFX1(%d, %d, %d)", x, y, item);
+ uint8 *shape = _shapes[220+item];
+ x -= 8;
+ int startY = y;
+ y -= 15;
+ _screen->hideMouse();
+ _screen->backUpRect0(x, y);
+ for (int i = 1; i <= 16; ++i) {
+ _screen->setNewShapeHeight(shape, i);
+ --startY;
+ _screen->restoreRect0(x, y);
+ uint32 nextTime = _system->getMillis() + 1 * _tickLength;
+ _screen->drawShape(0, shape, x, startY, 0, 0);
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if ((nextTime - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+ _screen->restoreRect0(x, y);
+ _screen->showMouse();
+}
+
+void KyraEngine::itemSpecialFX2(int x, int y, int item) {
+ debug(9, "KyraEngine::itemSpecialFX2(%d, %d, %d)", x, y, item);
+ x -= 8;
+ y -= 15;
+ int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF);
+ _screen->backUpRect0(x, y);
+ if (item >= 80 && item <= 89) {
+ snd_playSoundEffect(55);
+ }
+
+ for (int i = 201; i <= 205; ++i) {
+ _screen->restoreRect0(x, y);
+ uint32 nextTime = _system->getMillis() + 3 * _tickLength;
+ _screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if ((nextTime - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+
+ for (int i = 204; i >= 201; --i) {
+ _screen->restoreRect0(x, y);
+ uint32 nextTime = _system->getMillis() + 3 * _tickLength;
+ _screen->drawShape(0, _shapes[220+item], x, y, 0, 0);
+ _screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if ((nextTime - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+ _screen->restoreRect0(x, y);
+}
+
+void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) {
+ debug(9, "KyraEngine::magicOutMouseItem(%d, %d)", animIndex, itemPos);
+ int videoPageBackUp = _screen->_curPage;
+ _screen->_curPage = 0;
+ int x = 0, y = 0;
+ if (itemPos == -1) {
+ x = _mouseX - 12;
+ y = _mouseY - 18;
+ } else {
+ x = _itemPosX[itemPos] - 4;
+ y = _itemPosY[itemPos] - 3;
+ }
+
+ if (_itemInHand == -1 && itemPos == -1) {
+ return;
+ }
+
+ int tableIndex = 0, loopStart = 0, maxLoops = 0;
+ if (animIndex == 0) {
+ tableIndex = _rnd.getRandomNumberRng(0, 5);
+ loopStart = 35;
+ maxLoops = 9;
+ } else if (animIndex == 1) {
+ tableIndex = _rnd.getRandomNumberRng(0, 11);
+ loopStart = 115;
+ maxLoops = 8;
+ } else if (animIndex == 2) {
+ tableIndex = 0;
+ loopStart = 124;
+ maxLoops = 4;
+ } else {
+ tableIndex = -1;
+ }
+
+ if (animIndex == 2) {
+ snd_playSoundEffect(0x5E);
+ } else {
+ snd_playSoundEffect(0x37);
+ }
+ _screen->hideMouse();
+ _screen->backUpRect1(x, y);
+
+ for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
+ _screen->restoreRect1(x, y);
+ uint32 nextTime = _system->getMillis() + 4 * _tickLength;
+ _screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
+ if (tableIndex == -1) {
+ _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
+ } else {
+ specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+ }
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if (nextTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+ }
+
+ if (itemPos != -1) {
+ _screen->restoreRect1(x, y);
+ _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
+ _screen->backUpRect1(x, y);
+ }
+
+ for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
+ _screen->restoreRect1(x, y);
+ uint32 nextTime = _system->getMillis() + 4 * _tickLength;
+ _screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
+ if (tableIndex == -1) {
+ _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
+ } else {
+ specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+ }
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if (nextTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+ }
+ _screen->restoreRect1(x, y);
+ if (itemPos == -1) {
+ _screen->setMouseCursor(1, 1, _shapes[4]);
+ _itemInHand = -1;
+ } else {
+ _characterList[0].inventoryItems[itemPos] = 0xFF;
+ _screen->hideMouse();
+ _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
+ _screen->showMouse();
+ }
+ _screen->showMouse();
+ _screen->_curPage = videoPageBackUp;
+}
+
+void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) {
+ debug(9, "KyraEngine::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos);
+ int videoPageBackUp = _screen->_curPage;
+ _screen->_curPage = 0;
+ int x = 0, y = 0;
+ if (itemPos == -1) {
+ x = _mouseX - 12;
+ y = _mouseY - 18;
+ } else {
+ x = _itemPosX[itemPos] - 4;
+ y = _itemPosX[itemPos] - 3;
+ }
+ if (item < 0)
+ return;
+
+ int tableIndex = -1, loopStart = 0, maxLoops = 0;
+ if (animIndex == 0) {
+ tableIndex = _rnd.getRandomNumberRng(0, 5);
+ loopStart = 35;
+ maxLoops = 9;
+ } else if (animIndex == 1) {
+ tableIndex = _rnd.getRandomNumberRng(0, 11);
+ loopStart = 115;
+ maxLoops = 8;
+ } else if (animIndex == 2) {
+ tableIndex = 0;
+ loopStart = 124;
+ maxLoops = 4;
+ }
+
+ _screen->hideMouse();
+ _screen->backUpRect1(x, y);
+ if (animIndex == 2) {
+ snd_playSoundEffect(0x5E);
+ } else {
+ snd_playSoundEffect(0x37);
+ }
+
+ for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
+ _screen->restoreRect1(x, y);
+ uint32 nextTime = _system->getMillis() + 4 * _tickLength;
+ if (tableIndex == -1) {
+ _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
+ } else {
+ specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+ }
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if (nextTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+ }
+
+ for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
+ _screen->restoreRect1(x, y);
+ uint32 nextTime = _system->getMillis() + 4 * _tickLength;
+ if (tableIndex == -1) {
+ _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
+ } else {
+ specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+ }
+ _screen->updateScreen();
+ while (_system->getMillis() < nextTime) {
+ if (nextTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+ }
+ _screen->restoreRect1(x, y);
+ if (itemPos == -1) {
+ _screen->setMouseCursor(8, 15, _shapes[220+item]);
+ _itemInHand = item;
+ } else {
+ _characterList[0].inventoryItems[itemPos] = item;
+ _screen->hideMouse();
+ _screen->drawShape(0, _shapes[220+item], _itemPosX[itemPos], _itemPosY[itemPos], 0, 0);
+ _screen->showMouse();
+ }
+ _screen->showMouse();
+ _screen->_curPage = videoPageBackUp;
+}
+
+void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) {
+ debug(9, "KyraEngine::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+ static const uint8 table1[] = {
+ 0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00
+ };
+ static const uint8 table2[] = {
+ 0x73, 0xB5, 0x80, 0x21, 0x13, 0x39, 0x45, 0x55, 0x62, 0xB4, 0xCF, 0xD8
+ };
+ static const uint8 table3[] = {
+ 0x7C, 0xD0, 0x74, 0x84, 0x87, 0x00, 0x00, 0x00
+ };
+ int tableValue = 0;
+ if (animIndex == 0) {
+ tableValue = table1[tableIndex];
+ } else if (animIndex == 1) {
+ tableValue = table2[tableIndex];
+ } else if (animIndex == 2) {
+ tableValue = table3[tableIndex];
+ } else {
+ return;
+ }
+ processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops);
+}
+
+void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) {
+ debug(9, "KyraEngine::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops);
+ uint8 shapeColorTable[16];
+ uint8 *shapePtr = _shapes[4+shape] + 10;
+ if (_features & GF_TALKIE)
+ shapePtr += 2;
+ for (int i = 0; i < 16; ++i) {
+ shapeColorTable[i] = shapePtr[i];
+ }
+ for (int i = loopStart; i < loopStart + maxLoops; ++i) {
+ for (int i2 = 0; i2 < 16; ++i2) {
+ if (shapePtr[i2] == i) {
+ shapeColorTable[i2] = (i + tableValue) - loopStart;
+ }
+ }
+ }
+ _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0x8000, shapeColorTable);
+}
+
+void KyraEngine::updatePlayerItemsForScene() {
+ debug(9, "KyraEngine::updatePlayerItemsForScene()");
+ if (_itemInHand >= 29 && _itemInHand < 33) {
+ ++_itemInHand;
+ if (_itemInHand > 33)
+ _itemInHand = 33;
+ _screen->hideMouse();
+ _screen->setMouseCursor(8, 15, _shapes[220+_itemInHand]);
+ _screen->showMouse();
+ }
+
+ bool redraw = false;
+ for (int i = 0; i < 10; ++i) {
+ uint8 item = _currentCharacter->inventoryItems[i];
+ if (item >= 29 && item < 33) {
+ ++item;
+ if (item > 33)
+ item = 33;
+ _currentCharacter->inventoryItems[i] = item;
+ redraw = true;
+ }
+ }
+
+ if (redraw) {
+ _screen->hideMouse();
+ redrawInventory(0);
+ _screen->showMouse();
+ }
+
+ if (_itemInHand == 33) {
+ magicOutMouseItem(2, -1);
+ }
+
+ _screen->hideMouse();
+ for (int i = 0; i < 10; ++i) {
+ uint8 item = _currentCharacter->inventoryItems[i];
+ if (item == 33) {
+ magicOutMouseItem(2, i);
+ }
+ }
+ _screen->showMouse();
+}
+
+void KyraEngine::redrawInventory(int page) {
+ int videoPageBackUp = _screen->_curPage;
+ _screen->_curPage = page;
+ _screen->hideMouse();
+ for (int i = 0; i < 10; ++i) {
+ _screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, 12, page);
+ if (_currentCharacter->inventoryItems[i] != 0xFF) {
+ uint8 item = _currentCharacter->inventoryItems[i];
+ _screen->drawShape(page, _shapes[220+item], _itemPosX[i], _itemPosY[i], 0, 0);
+ }
+ }
+ _screen->showMouse();
+ _screen->_curPage = videoPageBackUp;
+ _screen->updateScreen();
+}
+
+} // end of namespace Kyra
diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp
index 4d988e907f..6969e3309e 100644
--- a/kyra/kyra.cpp
+++ b/kyra/kyra.cpp
@@ -466,8 +466,6 @@ KyraEngine::~KyraEngine() {
for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) {
free(_sceneAnimTable[i]);
}
- free(_unkPtr1);
- free(_unkPtr2);
}
void KyraEngine::errorString(const char *buf1, char *buf2) {
@@ -518,7 +516,7 @@ void KyraEngine::startup() {
for (int i = 5; i <= 10; ++i)
setCharactersPositions(i);
setCharactersHeight();
- resetBrandonPosionFlags();
+ resetBrandonPoisonFlags();
_maskBuffer = _screen->getPagePtr(5);
_screen->_curPage = 0;
// XXX
@@ -526,10 +524,6 @@ void KyraEngine::startup() {
int size = _screen->getRectSize(3, 24);
_shapes[365+i] = (byte*)malloc(size);
}
- _unkPtr1 = (uint8*)malloc(_screen->getRectSize(1, 144));
- memset(_unkPtr1, 0, _screen->getRectSize(1, 144));
- _unkPtr2 = (uint8*)malloc(_screen->getRectSize(1, 144));
- memset(_unkPtr2, 0, _screen->getRectSize(1, 144));
_shapes[0] = (uint8*)malloc(_screen->getRectSize(3, 24));
memset(_shapes[0], 0, _screen->getRectSize(3, 24));
_shapes[1] = (uint8*)malloc(_screen->getRectSize(4, 32));
@@ -556,7 +550,7 @@ void KyraEngine::startup() {
loadPalette("PALETTE.COL", _screen->_currentPalette);
// XXX
- initAnimStateList();
+ _animator->initAnimStateList();
setCharactersInDefaultScene();
_gameSpeed = 50;
@@ -752,48 +746,6 @@ void KyraEngine::quitGame() {
_system->quit();
}
-void KyraEngine::loadPalette(const char *filename, uint8 *palData) {
- debug(9, "KyraEngine::loadPalette('%s' 0x%X)", filename, palData);
- uint32 fileSize = 0;
- uint8 *srcData = _res->fileData(filename, &fileSize);
-
- if (palData && fileSize) {
- debug(9, "Loading a palette of size %i from '%s'", fileSize, filename);
- memcpy(palData, srcData, fileSize);
- }
- delete [] srcData;
-}
-
-void KyraEngine::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData) {
- debug(9, "KyraEngine::copyBitmap('%s', %d, %d, 0x%X)", filename, tempPage, dstPage, palData);
- uint32 fileSize;
- uint8 *srcData = _res->fileData(filename, &fileSize);
- uint8 compType = srcData[2];
- uint32 imgSize = READ_LE_UINT32(srcData + 4);
- uint16 palSize = READ_LE_UINT16(srcData + 8);
- if (palData && palSize) {
- debug(9, "Loading a palette of size %i from %s", palSize, filename);
- memcpy(palData, srcData + 10, palSize);
- }
- uint8 *srcPtr = srcData + 10 + palSize;
- uint8 *dstData = _screen->getPagePtr(dstPage);
- switch (compType) {
- case 0:
- memcpy(dstData, srcPtr, imgSize);
- break;
- case 3:
- Screen::decodeFrame3(srcPtr, dstData, imgSize);
- break;
- case 4:
- Screen::decodeFrame4(srcPtr, dstData, imgSize);
- break;
- default:
- error("Unhandled bitmap compression %d", compType);
- break;
- }
- delete[] srcData;
-}
-
void KyraEngine::waitTicks(int ticks) {
debug(9, "KyraEngine::waitTicks(%d)", ticks);
const uint32 end = _system->getMillis() + ticks * 1000 / 60;
@@ -834,1225 +786,6 @@ void KyraEngine::delayWithTicks(int ticks) {
}
}
-void KyraEngine::seq_demo() {
- debug(9, "KyraEngine::seq_demo()");
-
- snd_playTheme(MUSIC_INTRO, 2);
-
- loadBitmap("START.CPS", 7, 7, _screen->_currentPalette);
- _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
- _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
- _screen->fadeFromBlack();
- waitTicks(60);
- _screen->fadeToBlack();
-
- _screen->clearPage(0);
- loadBitmap("TOP.CPS", 7, 7, NULL);
- loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
- _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
- _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
- _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
- _screen->fadeFromBlack();
-
- _seq->playSequence(_seq_WestwoodLogo, true);
- waitTicks(60);
-
- _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);
- loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette);
- _screen->_curPage = 0;
- _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
- _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
- _screen->fadeFromBlack();
- waitTicks(60);
- _screen->fadeToBlack();
- _sound->stopMusic();
-}
-
-void KyraEngine::seq_intro() {
- debug(9, "KyraEngine::seq_intro()");
- if (_features & GF_TALKIE) {
- _res->loadPakFile("INTRO.VRM");
- }
-
- static const IntroProc introProcTable[] = {
- &KyraEngine::seq_introLogos,
- &KyraEngine::seq_introStory,
- &KyraEngine::seq_introMalcolmTree,
- &KyraEngine::seq_introKallakWriting,
- &KyraEngine::seq_introKallakMalcolm
- };
-
- Common::InSaveFile *in;
- if ((in = _saveFileMan->openForLoading(getSavegameFilename(0)))) {
- delete in;
- _skipIntroFlag = true;
- } else
- _skipIntroFlag = false;
-
- _seq->setCopyViewOffs(true);
- _screen->setFont(Screen::FID_8_FNT);
- snd_playTheme(MUSIC_INTRO, 2);
- snd_setSoundEffectFile(MUSIC_INTRO);
- _text->setTalkCoords(144);
- for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) {
- (this->*introProcTable[i])();
- }
- _text->setTalkCoords(136);
- waitTicks(30);
- _seq->setCopyViewOffs(false);
- _sound->stopMusic();
- if (_features & GF_TALKIE) {
- _res->unloadPakFile("INTRO.VRM");
- }
- res_unloadResources(RES_INTRO | RES_OUTRO);
-}
-
-void KyraEngine::seq_introLogos() {
- debug(9, "KyraEngine::seq_introLogos()");
- _screen->clearPage(0);
- loadBitmap("TOP.CPS", 7, 7, NULL);
- loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
- _screen->_curPage = 0;
- _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
- _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
- _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
- _screen->fadeFromBlack();
-
- if (_seq->playSequence(_seq_WestwoodLogo, _skipIntroFlag)) {
- _screen->fadeToBlack();
- _screen->clearPage(0);
- return;
- }
- waitTicks(60);
- if (_seq->playSequence(_seq_KyrandiaLogo, _skipIntroFlag)) {
- _screen->fadeToBlack();
- _screen->clearPage(0);
- return;
- }
- _screen->fillRect(0, 179, 319, 199, 0);
-
- int y1 = 8;
- int h1 = 175;
- int y2 = 176;
- int h2 = 0;
- _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 2);
- _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 2);
- do {
- if (h1 > 0) {
- _screen->copyRegion(0, y1, 0, 8, 320, h1, 2, 0);
- }
- ++y1;
- --h1;
- if (h2 > 0) {
- _screen->copyRegion(0, 64, 0, y2, 320, h2, 4, 0);
- }
- --y2;
- ++h2;
- _screen->updateScreen();
- waitTicks(1);
- } while (y2 >= 64);
-
- _seq->playSequence(_seq_Forest, true);
-}
-
-void KyraEngine::seq_introStory() {
- debug(9, "KyraEngine::seq_introStory()");
- _screen->clearPage(3);
- _screen->clearPage(0);
- if ((_features & GF_ENGLISH) && (_features & GF_TALKIE)) {
- loadBitmap("TEXT_ENG.CPS", 3, 3, 0);
- } else if (_features & GF_GERMAN) {
- loadBitmap("TEXT_GER.CPS", 3, 3, 0);
- } else if (_features & GF_FRENCH) {
- loadBitmap("TEXT_FRE.CPS", 3, 3, 0);
- } else if (_features & GF_SPANISH) {
- loadBitmap("TEXT_SPA.CPS", 3, 3, 0);
- } else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY)) {
- loadBitmap("TEXT.CPS", 3, 3, 0);
- } else {
- warning("no story graphics file found");
- }
- _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
- _screen->updateScreen();
- waitTicks(360);
-}
-
-void KyraEngine::seq_introMalcolmTree() {
- debug(9, "KyraEngine::seq_introMalcolmTree()");
- _screen->_curPage = 0;
- _screen->clearPage(3);
- _seq->playSequence(_seq_MalcolmTree, true);
-}
-
-void KyraEngine::seq_introKallakWriting() {
- debug(9, "KyraEngine::seq_introKallakWriting()");
- _seq->makeHandShapes();
- _screen->setAnimBlockPtr(5060);
- _screen->_charWidth = -2;
- _screen->clearPage(3);
- _seq->playSequence(_seq_KallakWriting, true);
-}
-
-void KyraEngine::seq_introKallakMalcolm() {
- debug(9, "KyraEngine::seq_introKallakMalcolm()");
- _screen->clearPage(3);
- _seq->playSequence(_seq_KallakMalcolm, true);
-}
-
-void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
- debug(9, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, 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[4+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[4+opcodes[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
- _screen->updateScreen();
- delayWithTicks(3);
- }
- }
- }
- _screen->drawShape(page, _shapes[327+jewel], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
- _screen->updateScreen();
- _screen->showMouse();
- setGameFlag(0x55+jewel);
-}
-
-void KyraEngine::seq_brandonHealing() {
- debug(9, "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);
- setBrandonAnimSeqSize(3, 48);
- snd_playSoundEffect(0x53);
- for (int i = 123; i <= 144; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- for (int i = 125; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_brandonHealing2() {
- debug(9, "seq_brandonHealing2()");
- _screen->hideMouse();
- checkAmuletAnimFlags();
- assert(_healingShape2Table);
- setupShapes123(_healingShape2Table, 30, 0);
- resetBrandonPoisonFlags();
- setBrandonAnimSeqSize(3, 48);
- snd_playSoundEffect(0x50);
- for (int i = 123; i <= 152; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
- assert(_poisonGone);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(2010);
- }
- characterSays(_poisonGone[0], 0, -2);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(2011);
- }
- characterSays(_poisonGone[1], 0, -2);
-}
-
-void KyraEngine::seq_poisonDeathNow(int now) {
- debug(9, "seq_poisonDeathNow(%d)", now);
- if (!(_brandonStatusBit & 1))
- return;
- ++_poisonDeathCounter;
- if (now)
- _poisonDeathCounter = 2;
- if (_poisonDeathCounter >= 2) {
- snd_playWanderScoreViaMap(1, 1);
- assert(_thePoison);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(7000);
- }
- characterSays(_thePoison[0], 0, -2);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(7001);
- }
- characterSays(_thePoison[1], 0, -2);
- seq_poisonDeathNowAnim();
- _deathHandler = 3;
- } else {
- assert(_thePoison);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(7002);
- }
- characterSays(_thePoison[2], 0, -2);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(7004);
- }
- characterSays(_thePoison[3], 0, -2);
- }
-}
-
-void KyraEngine::seq_poisonDeathNowAnim() {
- debug(9, "seq_poisonDeathNowAnim()");
- _screen->hideMouse();
- checkAmuletAnimFlags();
- assert(_posionDeathShapeTable);
- setupShapes123(_posionDeathShapeTable, 20, 0);
- setBrandonAnimSeqSize(8, 48);
-
- _currentCharacter->currentAnimFrame = 124;
- animRefreshNPC(0);
- delayWithTicks(30);
-
- _currentCharacter->currentAnimFrame = 123;
- animRefreshNPC(0);
- delayWithTicks(30);
-
- for (int i = 125; i <= 139; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- delayWithTicks(60);
-
- for (int i = 140; i <= 142; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- delayWithTicks(60);
-
- resetBrandonAnimSeqSize();
- freeShapes123();
- _animator->restoreAllObjectBackgrounds();
- _currentCharacter->x1 = _currentCharacter->x2 = -1;
- _currentCharacter->y1 = _currentCharacter->y2 = -1;
- _animator->preserveAllBackgrounds();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_playFluteAnimation() {
- debug(9, "seq_playFluteAnimation()");
- _screen->hideMouse();
- checkAmuletAnimFlags();
- setupShapes123(_fluteAnimShapeTable, 36, 0);
- setBrandonAnimSeqSize(3, 75);
- for (int i = 123; i <= 130; ++i) {
- _currentCharacter->currentAnimFrame = i;
- 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;
- animRefreshNPC(0);
- delayWithTicks(delayTime);
- }
-
- for (int i = 126; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(delayTime);
- }
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-
- if (soundType == 1) {
- assert(_fluteString);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(1000);
- }
- characterSays(_fluteString[0], 0, -2);
- } else if (soundType == 2) {
- assert(_fluteString);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(1001);
- }
- characterSays(_fluteString[1], 0, -2);
- }
-}
-
-void KyraEngine::seq_winterScroll1() {
- debug(9, "seq_winterScroll1()");
- _screen->hideMouse();
- checkAmuletAnimFlags();
- assert(_winterScrollTable);
- assert(_winterScroll1Table);
- assert(_winterScroll2Table);
- setupShapes123(_winterScrollTable, 7, 0);
- setBrandonAnimSeqSize(5, 66);
-
- for (int i = 123; i <= 129; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- freeShapes123();
- snd_playSoundEffect(0x20);
- setupShapes123(_winterScroll1Table, 35, 0);
-
- for (int i = 123; i <= 146; ++i) {
- _currentCharacter->currentAnimFrame = i;
- 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;
- setGameFlag(0xA2);
- }
-
- for (int i = 147; i <= 157; ++i) {
- _currentCharacter->currentAnimFrame = i;
- 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;
- }
- uint8 tmpPal[768];
- memcpy(tmpPal, _screen->_currentPalette, 768);
- memcpy(&tmpPal[684], palTable2()[0], 60);
- _screen->fadePalette(tmpPal, 72);
- memcpy(&_screen->_currentPalette[684], palTable2()[0], 60);
- _screen->setScreenPalette(_screen->_currentPalette);
- setGameFlag(0xB3);
- } else {
- delayWithTicks(120);
- }
-
- freeShapes123();
- setupShapes123(_winterScroll2Table, 4, 0);
-
- for (int i = 123; i <= 126; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_winterScroll2() {
- debug(9, "seq_winterScroll2()");
- _screen->hideMouse();
- checkAmuletAnimFlags();
- assert(_winterScrollTable);
- setupShapes123(_winterScrollTable, 7, 0);
- setBrandonAnimSeqSize(5, 66);
-
- for (int i = 123; i <= 128; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- delayWithTicks(120);
-
- for (int i = 127; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_makeBrandonInv() {
- debug(9, "seq_makeBrandonInv()");
- if (_deathHandler == 8)
- return;
-
- if (_currentCharacter->sceneId == 210) {
- if (_beadStateVar == 4 || _beadStateVar == 6)
- return;
- }
-
- _screen->hideMouse();
- checkAmuletAnimFlags();
- _brandonStatusBit |= 0x20;
- setTimerCountdown(18, 2700);
- _brandonStatusBit |= 0x40;
- snd_playSoundEffect(0x77);
- _brandonInvFlag = 0;
- while (_brandonInvFlag <= 0x100) {
- animRefreshNPC(0);
- delayWithTicks(10);
- _brandonInvFlag += 0x10;
- }
- _brandonStatusBit &= 0xFFBF;
- _screen->showMouse();
-}
-
-void KyraEngine::seq_makeBrandonNormal() {
- debug(9, "seq_makeBrandonNormal()");
- _screen->hideMouse();
- _brandonStatusBit |= 0x40;
- snd_playSoundEffect(0x77);
- _brandonInvFlag = 0x100;
- while (_brandonInvFlag >= 0) {
- animRefreshNPC(0);
- delayWithTicks(10);
- _brandonInvFlag -= 0x10;
- }
- _brandonInvFlag = 0;
- _brandonStatusBit &= 0xFF9F;
- _screen->showMouse();
-}
-
-void KyraEngine::seq_makeBrandonNormal2() {
- debug(9, "seq_makeBrandonNormal2()");
- _screen->hideMouse();
- assert(_brandonToWispTable);
- setupShapes123(_brandonToWispTable, 26, 0);
- setBrandonAnimSeqSize(5, 48);
- _brandonStatusBit &= 0xFFFD;
- snd_playSoundEffect(0x6C);
- for (int i = 138; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- setBrandonAnimSeqSize(4, 48);
- _currentCharacter->currentAnimFrame = 7;
- 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::seq_makeBrandonWisp() {
- debug(9, "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);
- setBrandonAnimSeqSize(5, 48);
- snd_playSoundEffect(0x6C);
- for (int i = 123; i <= 138; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- _brandonStatusBit |= 2;
- if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
- setTimerCountdown(14, 18000);
- } else {
- setTimerCountdown(14, 7200);
- }
- _brandonDrawFrame = 113;
- _brandonStatusBit0x02Flag = 1;
- _currentCharacter->currentAnimFrame = 113;
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- 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::seq_dispelMagicAnimation() {
- debug(9, "seq_dispelMagicAnimation()");
- if (_deathHandler == 8)
- return;
- if (_currentCharacter->sceneId == 210) {
- if (_beadStateVar == 4 || _beadStateVar == 6)
- return;
- }
- _screen->hideMouse();
- 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);
- setBrandonAnimSeqSize(8, 49);
- snd_playSoundEffect(0x15);
- for (int i = 123; i <= 127; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
-
- delayWithTicks(120);
-
- for (int i = 127; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(10);
- }
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
- debug(9, "seq_fillFlaskWithWater(%d, %d)", item, 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);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(8006);
- }
- characterSays(_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;
-
- _screen->hideMouse();
- setMouseItem(newItem);
- _screen->showMouse();
- _itemInHand = newItem;
- assert(_fullFlask);
- assert(type < _fullFlask_Size && type >= 0);
- if (_features & GF_TALKIE) {
- snd_voiceWaitForFinish();
- static const uint16 voiceEntries[] = {
- 0x1F40, 0x1F41, 0x1F42, 0x1F45
- };
- assert(type < ARRAYSIZE(voiceEntries));
- snd_playVoiceFile(voiceEntries[type]);
- }
- characterSays(_fullFlask[type], 0, -2);
-}
-
-void KyraEngine::seq_playDrinkPotionAnim(int unk1, int unk2, int flags) {
- debug(9, "KyraEngine::seq_playDrinkPotionAnim(%d, %d, %d)", unk1, unk2, flags);
- // XXX
- _screen->hideMouse();
- checkAmuletAnimFlags();
- _currentCharacter->facing = 5;
- animRefreshNPC(0);
- assert(_drinkAnimationTable);
- setupShapes123(_drinkAnimationTable, 9, flags);
- setBrandonAnimSeqSize(5, 54);
-
- for (int i = 123; i <= 131; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(5);
- }
- snd_playSoundEffect(0x34);
- for (int i = 0; i < 2; ++i) {
- _currentCharacter->currentAnimFrame = 130;
- animRefreshNPC(0);
- delayWithTicks(7);
- _currentCharacter->currentAnimFrame = 131;
- animRefreshNPC(0);
- delayWithTicks(7);
- }
-
- if (unk2) {
- // XXX
- }
-
- for (int i = 131; i >= 123; --i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(5);
- }
-
- resetBrandonAnimSeqSize();
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- freeShapes123();
- _screen->showMouse();
-}
-
-int KyraEngine::seq_playEnd() {
- debug(9, "KyraEngine::seq_playEnd()");
- if (_endSequenceSkipFlag) {
- return 0;
- }
- if (_deathHandler == 8) {
- return 0;
- }
- _screen->_curPage = 2;
- if (_endSequenceNeedLoading) {
- snd_playWanderScoreViaMap(50, 1);
- setupPanPages();
- _finalA = new WSAMovieV1(this);
- assert(_finalA);
- _finalA->open("finala.wsa", 1, 0);
- _finalB = new WSAMovieV1(this);
- assert(_finalB);
- _finalB->open("finalb.wsa", 1, 0);
- _finalC = new WSAMovieV1(this);
- assert(_finalC);
- _endSequenceNeedLoading = 0;
- _finalC->open("finalc.wsa", 1, 0);
- _screen->_curPage = 0;
- _beadStateVar = 0;
- _malcolmFlag = 0;
- // wired stuff with _unkEndSeqVar2 which needs timer handling
- _screen->copyRegion(312, 0, 312, 0, 8, 136, 0, 2);
- }
- if (handleMalcolmFlag()) {
- _beadStateVar = 0;
- _malcolmFlag = 12;
- handleMalcolmFlag();
- handleBeadState();
- closeFinalWsa();
- if (_deathHandler == 8) {
- _screen->_curPage = 0;
- checkAmuletAnimFlags();
- seq_brandonToStone();
- waitTicks(60);
- return 1;
- } else {
- _endSequenceSkipFlag = 1;
- if (_text->printed()) {
- _text->restoreTalkTextMessageBkgd(2, 0);
- }
- _screen->_curPage = 0;
- _screen->hideMouse();
- _screen->fadeSpecialPalette(32, 228, 20, 60);
- waitTicks(60);
- loadBitmap("GEMHEAL.CPS", 3, 3, _screen->_currentPalette);
- _screen->setScreenPalette(_screen->_currentPalette);
- _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0);
- uint32 nextTime = _system->getMillis() + 120 * _tickLength;
- _finalA = new WSAMovieV1(this);
- assert(_finalA);
- _finalA->open("finald.wsa", 1, 0);
- _finalA->_x = _finalA->_y = 8;
- _finalA->_drawPage = 0;
- while (_system->getMillis() < nextTime) {}
- snd_playSoundEffect(0x40);
- for (int i = 0; i < 22; ++i) {
- while (_system->getMillis() < nextTime) {}
- if (i == 4) {
- snd_playSoundEffect(0x3E);
- } else if (i == 20) {
- snd_playSoundEffect(0x0E);
- }
- nextTime = _system->getMillis() + 8 * _tickLength;
- _finalA->displayFrame(i);
- _screen->updateScreen();
- }
- delete _finalA;
- _finalA = 0;
- seq_playEnding();
- return 1;
- }
- } else {
- handleBeadState();
- _screen->bitBlitRects();
- _screen->updateScreen();
- _screen->_curPage = 0;
- }
- return 0;
-}
-
-void KyraEngine::seq_brandonToStone() {
- debug(9, "KyraEngine::seq_brandonToStone()");
- _screen->hideMouse();
- assert(_brandonStoneTable);
- setupShapes123(_brandonStoneTable, 14, 0);
- setBrandonAnimSeqSize(5, 51);
- for (int i = 123; i <= 136; ++i) {
- _currentCharacter->currentAnimFrame = i;
- animRefreshNPC(0);
- delayWithTicks(8);
- }
- resetBrandonAnimSeqSize();
- freeShapes123();
- _screen->showMouse();
-}
-
-void KyraEngine::seq_playEnding() {
- debug(9, "KyraEngine::seq_playEnding()");
- _screen->hideMouse();
- res_unloadResources(RES_INGAME);
- res_loadResources(RES_OUTRO);
- loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette);
- _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
- _screen->_curPage = 0;
- // XXX
- assert(_homeString);
- drawSentenceCommand(_homeString[0], 179);
- _screen->_curPage = 0;
- _screen->fadeToBlack();
- _seq->playSequence(_seq_Reunion, false);
- _screen->fadeToBlack();
- _screen->showMouse();
- seq_playCredits();
-}
-
-void KyraEngine::seq_playCredits() {
- debug(9, "KyraEngine::seq_playCredits()");
- static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- _screen->hideMouse();
- uint32 sz = 0;
- if (_features & GF_FLOPPY) {
- _screen->loadFont(Screen::FID_CRED6_FNT, _res->fileData("CREDIT6.FNT", &sz));
- _screen->loadFont(Screen::FID_CRED8_FNT, _res->fileData("CREDIT8.FNT", &sz));
- }
- loadBitmap("CHALET.CPS", 2, 2, _screen->_currentPalette);
- _screen->setScreenPalette(_screen->_currentPalette);
- _screen->setCurPage(0);
- _screen->clearCurPage();
- _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
- _screen->setTextColorMap(colorMap);
- _screen->_charWidth = -1;
- snd_playWanderScoreViaMap(53, 1);
- // delete
- _screen->updateScreen();
- // XXX
- waitTicks(120); // wait until user presses escape normally
- _screen->fadeToBlack();
- _screen->clearCurPage();
- _screen->showMouse();
-}
-
-bool KyraEngine::seq_skipSequence() const {
- debug(9, "KyraEngine::seq_skipSequence()");
- return _quitFlag || _abortIntroFlag;
-}
-
-void KyraEngine::snd_playTheme(int file, int track) {
- debug(9, "KyraEngine::snd_playTheme(%d)", file);
- assert(file < _xmidiFilesCount);
- _curMusicTheme = _newMusicTheme = file;
- _sound->playMusic(_xmidiFiles[file]);
- _sound->playTrack(track, false);
-}
-
-void KyraEngine::snd_playTrack(int track, bool looping) {
- debug(9, "KyraEngine::snd_playTrack(%d, %d)", track, looping);
- _sound->playTrack(track, looping);
-}
-
-void KyraEngine::snd_setSoundEffectFile(int file) {
- debug(9, "KyraEngine::snd_setSoundEffectFile(%d)", file);
- assert(file < _xmidiFilesCount);
- _sound->loadSoundEffectFile(_xmidiFiles[file]);
-}
-
-void KyraEngine::snd_playSoundEffect(int track) {
- debug(9, "KyraEngine::snd_playSoundEffect(%d)", track);
- if (track == 49) {
- snd_playWanderScoreViaMap(56, 1);
- } else {
- _sound->playSoundEffect(track);
- }
-}
-
-void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) {
- debug(9, "KyraEngine::snd_playWanderScoreViaMap(%d, %d)", command, restart);
- static const int8 soundTable[] = {
- -1, 0, -1, 1, 0, 3, 0, 2,
- 0, 4, 1, 2, 1, 3, 1, 4,
- 1, 0x5C, 1, 6, 1, 7, 2, 2,
- 2, 3, 2, 4, 2, 5, 2, 6,
- 2, 7, 3, 3, 3, 4, 1, 8,
- 1, 9, 4, 2, 4, 3, 4, 4,
- 4, 5, 4, 6, 4, 7, 4, 8,
- 1, 0x0B, 1, 0x0C, 1, 0x0E, 1, 0x0D,
- 4, 9, 5, 0x0C, 6, 2, 6, 6,
- 6, 7, 6, 8, 6, 9, 6, 3,
- 6, 4, 6, 5, 7, 2, 7, 3,
- 7, 4, 7, 5, 7, 6, 7, 7,
- 7, 8, 7, 9, 8, 2, 8, 3,
- 8, 4, 8, 5, 6, 0x0B, 5, 0x0B
- };
- //if (!_disableSound) {
- // XXX
- //}
- assert(command*2+1 < ARRAYSIZE(soundTable));
- if (_curMusicTheme != soundTable[command*2]+1) {
- if (soundTable[command*2] != -1) {
- snd_playTheme(soundTable[command*2]+1);
- }
- }
-
- if (restart)
- _lastMusicCommand = -1;
-
- if (command != 1) {
- if (_lastMusicCommand != command) {
- _lastMusicCommand = command;
- snd_playTrack(soundTable[command*2+1], true);
- }
- } else {
- _lastMusicCommand = 1;
- _sound->beginFadeOut();
- }
-}
-
-void KyraEngine::snd_playVoiceFile(int id) {
- debug(9, "KyraEngine::snd_playVoiceFile(%d)", id);
- char vocFile[9];
- assert(id >= 0 && id < 9999);
- sprintf(vocFile, "%03d.VOC", id);
- _sound->voicePlay(vocFile);
-}
-
-bool KyraEngine::snd_voicePlaying() {
- return _sound->voiceIsPlaying();
-}
-
-void KyraEngine::snd_voiceWaitForFinish(bool ingame) {
- debug(9, "KyraEngine::snd_voiceWaitForFinish(%d)", ingame);
- while (snd_voicePlaying() && !_fastMode) {
- if (ingame) {
- delay(10, true);
- } else {
- _system->delayMillis(10);
- }
- }
-}
-
-void KyraEngine::snd_startTrack() {
- debug(9, "KyraEngine::snd_startTrack()");
- _sound->startTrack();
-}
-
-void KyraEngine::snd_haltTrack() {
- debug(9, "KyraEngine::snd_haltTrack()");
- _sound->haltTrack();
-}
-
-void KyraEngine::loadMouseShapes() {
- loadBitmap("MOUSE.CPS", 3, 3, 0);
- _screen->_curPage = 2;
- _shapes[4] = _screen->encodeShape(0, 0, 8, 10, 0);
- _shapes[5] = _screen->encodeShape(0, 0x17, 0x20, 7, 0);
- _shapes[6] = _screen->encodeShape(0x50, 0x12, 0x10, 9, 0);
- _shapes[7] = _screen->encodeShape(0x60, 0x12, 0x10, 11, 0);
- _shapes[8] = _screen->encodeShape(0x70, 0x12, 0x10, 9, 0);
- _shapes[9] = _screen->encodeShape(0x80, 0x12, 0x10, 11, 0);
- _shapes[10] = _screen->encodeShape(0x90, 0x12, 0x10, 10, 0);
- _shapes[364] = _screen->encodeShape(0x28, 0, 0x10, 13, 0);
- _screen->setMouseCursor(1, 1, 0);
- _screen->setMouseCursor(1, 1, _shapes[4]);
- _screen->setShapePages(5, 3);
-}
-
-void KyraEngine::loadCharacterShapes() {
- int curImage = 0xFF;
- int videoPage = _screen->_curPage;
- _screen->_curPage = 2;
- for (int i = 0; i < 115; ++i) {
- assert(i < _defaultShapeTableSize);
- Shape *shape = &_defaultShapeTable[i];
- if (shape->imageIndex == 0xFF) {
- _shapes[i+7+4] = 0;
- continue;
- }
- if (shape->imageIndex != curImage) {
- assert(shape->imageIndex < _characterImageTableSize);
- loadBitmap(_characterImageTable[shape->imageIndex], 3, 3, 0);
- curImage = shape->imageIndex;
- }
- _shapes[i+7+4] = _screen->encodeShape(shape->x<<3, shape->y, shape->w<<3, shape->h, 1);
- }
- _screen->_curPage = videoPage;
-}
-
-void KyraEngine::loadSpecialEffectShapes() {
- loadBitmap("EFFECTS.CPS", 3, 3, 0);
- _screen->_curPage = 2;
-
- int currShape;
- for (currShape = 173; currShape < 183; currShape++)
- _shapes[4 + currShape] = _screen->encodeShape((currShape-173) * 24, 0, 24, 24, 1);
-
- for (currShape = 183; currShape < 190; currShape++)
- _shapes[4 + currShape] = _screen->encodeShape((currShape-183) * 24, 24, 24, 24, 1);
-
- for (currShape = 190; currShape < 201; currShape++)
- _shapes[4 + currShape] = _screen->encodeShape((currShape-190) * 24, 48, 24, 24, 1);
-
- for (currShape = 201; currShape < 206; currShape++)
- _shapes[4 + currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1);
-}
-
-int KyraEngine::findDuplicateItemShape(int shape) {
- static uint8 dupTable[] = {
- 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47,
- 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a,
- 0x5d, 0x5a, 0x5e, 0x5a, 0xFF, 0xFF
- };
-
- int i = 0;
-
- while (dupTable[i] != 0xFF) {
- if (dupTable[i] == shape)
- return dupTable[i+1];
- i += 2;
- }
- return -1;
-}
-
-void KyraEngine::loadItems() {
- int shape;
-
- loadBitmap("JEWELS3.CPS", 3, 3, 0);
- _screen->_curPage = 2;
-
- _shapes[327] = 0;
-
- for (shape = 1; shape < 6; shape++ )
- _shapes[327 + shape] = _screen->encodeShape((shape - 1) * 32, 0, 32, 17, 0);
-
- for (shape = 330; shape <= 334; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-330) * 32, 102, 32, 17, 0);
-
- for (shape = 335; shape <= 339; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-335) * 32, 17, 32, 17, 0);
-
- for (shape = 340; shape <= 344; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-340) * 32, 34, 32, 17, 0);
-
- for (shape = 345; shape <= 349; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-345) * 32, 51, 32, 17, 0);
-
- for (shape = 350; shape <= 354; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-350) * 32, 68, 32, 17, 0);
-
- for (shape = 355; shape <= 359; shape++)
- _shapes[4 + shape] = _screen->encodeShape((shape-355) * 32, 85, 32, 17, 0);
-
-
- loadBitmap("ITEMS.CPS", 3, 3, 0);
- _screen->_curPage = 2;
-
- for (int i = 0; i < 107; i++) {
- shape = findDuplicateItemShape(i);
-
- if (shape != -1)
- _shapes[220 + i] = _shapes[220 + shape];
- else
- _shapes[220 + i] = _screen->encodeShape( (i % 20) * 16, i/20 * 16, 16, 16, 0);
- }
-
- uint32 size;
- uint8 *fileData = _res->fileData("_ITEM_HT.DAT", &size);
- assert(fileData);
-
- for (int i = 0; i < 107; i++) {
- _itemTable[i].height = fileData[i];
- _itemTable[i].unk1 = _itemTable[i].unk2 = 0;
- }
-
- delete[] fileData;
-}
-
-void KyraEngine::loadButtonShapes() {
- loadBitmap("BUTTONS2.CPS", 3, 3, 0);
- _screen->_curPage = 2;
- _scrollUpButton.process0PtrShape = _screen->encodeShape(0, 0, 24, 14, 1);
- _scrollUpButton.process1PtrShape = _screen->encodeShape(24, 0, 24, 14, 1);
- _scrollUpButton.process2PtrShape = _screen->encodeShape(48, 0, 24, 14, 1);
- _scrollDownButton.process0PtrShape = _screen->encodeShape(0, 15, 24, 14, 1);
- _scrollDownButton.process1PtrShape = _screen->encodeShape(24, 15, 24, 14, 1);
- _scrollDownButton.process2PtrShape = _screen->encodeShape(48, 15, 24, 14, 1);
- _screen->_curPage = 0;
-}
-
-void KyraEngine::initMainButtonList() {
- _buttonList = &_buttonData[0];
- for (int i = 0; _buttonDataListPtr[i]; ++i) {
- _buttonList = initButton(_buttonList, _buttonDataListPtr[i]);
- }
-}
-
-void KyraEngine::loadMainScreen(int page) {
- if ((_features & GF_ENGLISH) && (_features & GF_TALKIE))
- loadBitmap("MAIN_ENG.CPS", page, page, 0);
- else if(_features & GF_FRENCH)
- loadBitmap("MAIN_FRE.CPS", page, page, 0);
- else if(_features & GF_GERMAN)
- loadBitmap("MAIN_GER.CPS", page, page, 0);
- else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY))
- loadBitmap("MAIN15.CPS", page, page, 0);
- else if (_features & GF_SPANISH)
- loadBitmap("MAIN_SPA.CPS", page, page, 0);
- else
- warning("no main graphics file found");
-
- uint8 *_pageSrc = _screen->getPagePtr(page);
- uint8 *_pageDst = _screen->getPagePtr(0);
- memcpy(_pageDst, _pageSrc, 320*200);
-}
-
-void KyraEngine::setCharactersInDefaultScene() {
- static const uint32 defaultSceneTable[][4] = {
- { 0xFFFF, 0x0004, 0x0003, 0xFFFF },
- { 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
- { 0xFFFF, 0x001D, 0x0021, 0xFFFF },
- { 0xFFFF, 0x0000, 0x0000, 0xFFFF }
- };
-
- for (int i = 1; i < 5; ++i) {
- Character *cur = &_characterList[i];
- //cur->field_20 = 0;
- const uint32 *curTable = defaultSceneTable[i-1];
- cur->sceneId = curTable[0];
- if (cur->sceneId == _currentCharacter->sceneId) {
- //++cur->field_20;
- cur->sceneId = curTable[1/*cur->field_20*/];
- }
- //cur->field_23 = curTable[cur->field_20+1];
- }
-}
-
void KyraEngine::setCharacterDefaultFrame(int character) {
static uint16 initFrameTable[] = {
7, 41, 77, 0, 0
@@ -2065,22 +798,6 @@ void KyraEngine::setCharacterDefaultFrame(int character) {
// edit->unk6 = 1;
}
-void KyraEngine::setCharactersPositions(int character) {
- static uint16 initXPosTable[] = {
- 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
- 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
- };
- static uint8 initYPosTable[] = {
- 0x00, 0xA2, 0x00, 0x42, 0x00,
- 0x67, 0x67, 0x60, 0x5A, 0x71,
- 0x76
- };
- assert(character < ARRAYSIZE(initXPosTable));
- Character *edit = &_characterList[character];
- edit->x1 = edit->x2 = initXPosTable[character];
- edit->y1 = edit->y2 = initYPosTable[character];
-}
-
void KyraEngine::setCharactersHeight() {
static int8 initHeightTable[] = {
48, 40, 48, 47, 56,
@@ -2106,2183 +823,6 @@ int KyraEngine::resetGameFlag(int flag) {
return 0;
}
-void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
- debug(9, "KyraEngine::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive);
- int unkVar1 = 1;
- _screen->hideMouse();
- _handleInput = false;
- _abortWalkFlag = false;
- _abortWalkFlag2 = false;
- if (_currentCharacter->sceneId == 7 && sceneId == 24) {
- _newMusicTheme = 3;
- } else if (_currentCharacter->sceneId == 25 && sceneId == 109) {
- _newMusicTheme = 4;
- } else if (_currentCharacter->sceneId == 120 && sceneId == 37) {
- _newMusicTheme = 5;
- } else if (_currentCharacter->sceneId == 52 && sceneId == 199) {
- _newMusicTheme = 6;
- } else if (_currentCharacter->sceneId == 37 && sceneId == 120) {
- _newMusicTheme = 4;
- } else if (_currentCharacter->sceneId == 109 && sceneId == 25) {
- _newMusicTheme = 3;
- } else if (_currentCharacter->sceneId == 24 && sceneId == 7) {
- _newMusicTheme = 2;
- }
- if (_newMusicTheme != _curMusicTheme) {
- snd_playTheme(_newMusicTheme);
- }
-
- switch (_currentCharacter->sceneId) {
- case 1:
- if (sceneId == 0) {
- moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
- unkVar1 = 0;
- }
- break;
-
- case 3:
- if (sceneId == 2) {
- moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- case 26:
- if (sceneId == 27) {
- moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- case 44:
- if (sceneId == 45) {
- moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- default:
- break;
- }
-
- if (unkVar1 && unk1) {
- int xpos = _currentCharacter->x1;
- int ypos = _currentCharacter->y1;
- switch (facing) {
- case 0:
- ypos = _currentCharacter->y1 - 6;
- break;
-
- case 2:
- xpos = 336;
- break;
-
- case 4:
- ypos = 143;
- break;
-
- case 6:
- xpos = -16;
- break;
-
- default:
- break;
- }
-
- moveCharacterToPos(0, facing, xpos, ypos);
- }
-
- for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) {
- _movieObjects[i]->close();
- }
-
- if (!brandonAlive) {
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptInterpreter->startScript(_scriptClick, 5);
- while (_scriptInterpreter->validScript(_scriptClick)) {
- _scriptInterpreter->runScript(_scriptClick);
- }
- }
-
- memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4);
- _currentCharacter->sceneId = sceneId;
-
- assert(sceneId < _roomTableSize);
- assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
-
- Room *currentRoom = &_roomTable[sceneId];
-
- if (_currentRoom != 0xFFFF && (_features & GF_TALKIE)) {
- char file[32];
- assert(_currentRoom < _roomTableSize);
- int tableId = _roomTable[_currentRoom].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".VRM");
- _res->unloadPakFile(file);
- }
-
- _currentRoom = sceneId;
-
- int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".DAT");
- _sprites->loadDAT(fileNameBuffer, _sceneExits);
- _sprites->setupSceneAnims();
- _scriptInterpreter->unloadScript(_scriptClickData);
- loadSceneMSC();
-
- if ((_features & GF_TALKIE)) {
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".VRM");
- _res->loadPakFile(fileNameBuffer);
- }
-
- _walkBlockNorth = currentRoom->northExit;
- _walkBlockEast = currentRoom->eastExit;
- _walkBlockSouth = currentRoom->southExit;
- _walkBlockWest = currentRoom->westExit;
-
- if (_walkBlockNorth == 0xFFFF) {
- blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3);
- }
- if (_walkBlockEast == 0xFFFF) {
- blockOutRegion(312, 0, 8, 139);
- }
- if (_walkBlockSouth == 0xFFFF) {
- blockOutRegion(0, 135, 320, 8);
- }
- if (_walkBlockWest == 0xFFFF) {
- blockOutRegion(0, 0, 8, 139);
- }
-
- if (!brandonAlive) {
- updatePlayerItemsForScene();
- }
-
- startSceneScript(brandonAlive);
- setupSceneItems();
-
- initSceneData(facing, unk2, brandonAlive);
-
- _loopFlag2 = 0;
- _screen->showMouse();
- if (!brandonAlive) {
- seq_poisonDeathNow(0);
- }
- updateMousePointer(true);
- _changedScene = true;
-}
-
-void KyraEngine::transcendScenes(int roomIndex, int roomName) {
- debug(9, "KyraEngine::transcendScenes(%d, %d)", roomIndex, roomName);
- assert(roomIndex < _roomTableSize);
- if (_features & GF_TALKIE) {
- char file[32];
- assert(roomIndex < _roomTableSize);
- int tableId = _roomTable[roomIndex].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".VRM");
- _res->unloadPakFile(file);
- }
- _roomTable[roomIndex].nameIndex = roomName;
- _unkScreenVar2 = 1;
- _unkScreenVar3 = 1;
- _unkScreenVar1 = 0;
- _brandonPosX = _currentCharacter->x1;
- _brandonPosY = _currentCharacter->y1;
- enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
- _unkScreenVar1 = 1;
- _unkScreenVar2 = 0;
- _unkScreenVar3 = 0;
-}
-
-void KyraEngine::setSceneFile(int roomIndex, int roomName) {
- debug(9, "KyraEngine::setSceneFile(%d, %d)", roomIndex, roomName);
- assert(roomIndex < _roomTableSize);
- _roomTable[roomIndex].nameIndex = roomName;
-}
-
-void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
- debug(9, "KyraEngine::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos);
- Character *ch = &_characterList[character];
- ch->facing = facing;
- _screen->hideMouse();
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
- disableTimer(19);
- disableTimer(14);
- disableTimer(18);
- uint32 nextFrame = 0;
- switch (facing) {
- case 0:
- while (ypos < ch->y1) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- while (_system->getMillis() < nextFrame) { updateGameTimers(); }
- }
- break;
-
- case 2:
- while (ch->x1 < xpos) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- while (_system->getMillis() < nextFrame) { updateGameTimers(); }
- }
- break;
-
- case 4:
- while (ypos > ch->y1) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- while (_system->getMillis() < nextFrame) { updateGameTimers(); }
- }
- break;
-
- case 6:
- while (ch->x1 > xpos) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- while (_system->getMillis() < nextFrame) { updateGameTimers(); }
- }
- break;
-
- default:
- break;
- }
- enableTimer(19);
- enableTimer(14);
- enableTimer(18);
- _screen->showMouse();
-}
-
-void KyraEngine::setCharacterPositionWithUpdate(int character) {
- debug(9, "KyraEngine::setCharacterPositionWithUpdate(%d)", character);
- setCharacterPosition(character, 0);
- _sprites->updateSceneAnims();
- updateGameTimers();
- _animator->updateAllObjectShapes();
- updateTextFade();
-
- if (_currentCharacter->sceneId == 210) {
- _animator->updateKyragemFading();
- }
-}
-
-int KyraEngine::setCharacterPosition(int character, int *facingTable) {
- debug(9, "KyraEngine::setCharacterPosition(%d, 0x%X)", character, facingTable);
- if (character == 0) {
- _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing];
- _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing];
- setCharacterPositionHelper(0, facingTable);
- return 1;
- } else {
- _characterList[character].x1 += _charXPosTable[_characterList[character].facing];
- _characterList[character].y1 += _charYPosTable[_characterList[character].facing];
- if (_characterList[character].sceneId == _currentCharacter->sceneId) {
- setCharacterPositionHelper(character, 0);
- }
- }
- return 0;
-}
-
-void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) {
- debug(9, "KyraEngine::setCharacterPositionHelper(%d, 0x%X)", character, facingTable);
- Character *ch = &_characterList[character];
- ++ch->currentAnimFrame;
- int facing = ch->facing;
- if (facingTable) {
- if (*facingTable != *(facingTable - 1)) {
- if (*(facingTable - 1) == *(facingTable + 1)) {
- facing = getOppositeFacingDirection(*(facingTable - 1));
- *facingTable = *(facingTable - 1);
- }
- }
- }
-
- static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- if (facing == 0) {
- ++facingIsZero[character];
- } else {
- bool resetTables = false;
- if (facing != 7) {
- if (facing - 1 != 0) {
- if (facing != 4) {
- if (facing == 3 || facing == 5) {
- if (facingIsFour[character] > 2) {
- facing = 4;
- }
- resetTables = true;
- }
- } else {
- ++facingIsFour[character];
- }
- } else {
- if (facingIsZero[character] > 2) {
- facing = 0;
- }
- resetTables = true;
- }
- } else {
- if (facingIsZero[character] > 2) {
- facing = 0;
- }
- resetTables = true;
- }
-
- if (resetTables) {
- facingIsZero[character] = 0;
- facingIsFour[character] = 0;
- }
- }
-
- static const uint16 maxAnimationFrame[] = {
- 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
- 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
- 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
- 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
- 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
- 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
- 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
- };
-
- if (facing == 0) {
- if (maxAnimationFrame[36+character] > ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[36+character];
- }
- if (maxAnimationFrame[30+character] < ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[36+character];
- }
- } else if (facing == 4) {
- if (maxAnimationFrame[18+character] > ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[18+character];
- }
- if (maxAnimationFrame[12+character] < ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[18+character];
- }
- } else {
- if (maxAnimationFrame[18+character] < ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[30+character];
- }
- if (maxAnimationFrame[character] == ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[6+character];
- }
- if (maxAnimationFrame[character] < ch->currentAnimFrame) {
- ch->currentAnimFrame = maxAnimationFrame[6+character]+2;
- }
- }
-
- if (character == 0) {
- if (_brandonStatusBit & 0x10)
- ch->currentAnimFrame = 88;
- }
-
- animRefreshNPC(character);
-}
-
-int KyraEngine::getOppositeFacingDirection(int dir) {
- debug(9, "KyraEngine::getOppositeFacingDirection(%d)", dir);
- switch (dir) {
- case 0:
- return 2;
- break;
-
- case 1:
- return 1;
- break;
-
- case 3:
- return 7;
- break;
-
- case 4:
- return 6;
- break;
-
- case 5:
- return 5;
- break;
-
- case 6:
- return 4;
- break;
-
- case 7:
- return 3;
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-void KyraEngine::loadSceneMSC() {
- assert(_currentCharacter->sceneId < _roomTableSize);
- int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".MSC");
- _screen->fillRect(0, 0, 319, 199, 0, 5);
- loadBitmap(fileNameBuffer, 3, 5, 0);
-}
-
-// maybe move these two functions to Screen
-void KyraEngine::blockInRegion(int x, int y, int width, int height) {
- debug(9, "KyraEngine::blockInRegion(%d, %d, %d, %d)", x, y, width, height);
- assert(_screen->_shapePages[0]);
- byte *toPtr = _screen->_shapePages[0] + (y * 320 + x);
- for (int i = 0; i < height; ++i) {
- byte *backUpTo = toPtr;
- for (int i2 = 0; i2 < width; ++i2) {
- *toPtr++ &= 0x7F;
- }
- toPtr = (backUpTo + 320);
- }
-}
-
-void KyraEngine::blockOutRegion(int x, int y, int width, int height) {
- debug(9, "KyraEngine::blockOutRegion(%d, %d, %d, %d)", x, y, width, height);
- assert(_screen->_shapePages[0]);
- byte *toPtr = _screen->_shapePages[0] + (y * 320 + x);
- for (int i = 0; i < height; ++i) {
- byte *backUpTo = toPtr;
- for (int i2 = 0; i2 < width; ++i2) {
- *toPtr++ |= 0x80;
- }
- toPtr = (backUpTo + 320);
- }
-}
-
-void KyraEngine::startSceneScript(int brandonAlive) {
- debug(9, "KyraEngine::startSceneScript(%d)", brandonAlive);
- assert(_currentCharacter->sceneId < _roomTableSize);
- int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".CPS");
- loadBitmap(fileNameBuffer, 3, 3, 0);
- _sprites->loadSceneShapes();
- _exitListPtr = 0;
-
- _screen->setScreenPalette(_screen->_currentPalette);
-
- _scaleMode = 1;
- for (int i = 0; i < 145; ++i) {
- _scaleTable[i] = 256;
- }
-
- clearNoDropRects();
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".EMC");
- _scriptInterpreter->unloadScript(_scriptClickData);
- _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, _opcodeTable, _opcodeTableSize, 0);
- _scriptInterpreter->startScript(_scriptClick, 0);
- _scriptClick->variables[0] = _currentCharacter->sceneId;
- _scriptClick->variables[7] = brandonAlive;
-
- while (_scriptInterpreter->validScript(_scriptClick)) {
- _scriptInterpreter->runScript(_scriptClick);
- }
-}
-
-void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
- debug(9, "KyraEngine::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive);
-
- int16 xpos2 = 0;
- int setFacing = 1;
-
- int16 xpos = 0, ypos = 0;
-
- if (_brandonPosX == -1 && _brandonPosY == -1) {
- switch (facing+1) {
- case 0:
- xpos = ypos = -1;
- break;
-
- case 1: case 2: case 8:
- xpos = _sceneExits.southXPos;
- ypos = _sceneExits.southYPos;
- break;
-
- case 3:
- xpos = _sceneExits.westXPos;
- ypos = _sceneExits.westYPos;
- break;
-
- case 4: case 5: case 6:
- xpos = _sceneExits.northXPos;
- ypos = _sceneExits.northYPos;
- break;
-
- case 7:
- xpos = _sceneExits.eastXPos;
- ypos = _sceneExits.eastYPos;
- break;
-
- default:
- break;
- }
-
- if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) {
- ypos = (_northExitHeight & 0xFF) + 4;
- }
- if (xpos >= 308) {
- xpos = 304;
- }
- if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) {
- ypos = (_northExitHeight >> 8) - 4;
- }
- if (xpos <= 12) {
- xpos = 16;
- }
- }
-
- if (_brandonPosX > -1) {
- xpos = _brandonPosX;
- }
- if (_brandonPosY > -1) {
- ypos = _brandonPosY;
- }
-
- int16 ypos2 = 0;
- if (_brandonPosX > -1 && _brandonPosY > -1) {
- switch (_currentCharacter->sceneId) {
- case 1:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 4;
- xpos2 = 192;
- ypos2 = 104;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 3:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 204;
- ypos2 = 94;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 26:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 192;
- ypos2 = 128;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 44:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 6;
- xpos2 = 156;
- ypos2 = 96;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 37:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 148;
- ypos2 = 114;
- setFacing = 0;
- unk1 = 1;
- break;
-
- default:
- break;
- }
- }
-
- _brandonPosX = _brandonPosY = -1;
-
- if (unk1 && setFacing) {
- ypos2 = ypos;
- xpos2 = xpos;
- switch (facing) {
- case 0:
- ypos = 142;
- break;
-
- case 2:
- xpos = -16;
- break;
-
- case 4:
- ypos = (uint8)(_northExitHeight & 0xFF) - 4;
- break;
-
- case 6:
- xpos = 336;
- break;
-
- default:
- break;
- }
- }
-
- xpos2 = (int16)(xpos2 & 0xFFFC);
- ypos2 = (int16)(ypos2 & 0xFFFE);
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
- _currentCharacter->facing = facing;
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
-
- initSceneObjectList(brandonAlive);
-
- if (unk1 && brandonAlive == 0) {
- moveCharacterToPos(0, facing, xpos2, ypos2);
- }
-
- _scriptClick->variables[4] = _itemInHand;
- _scriptClick->variables[7] = brandonAlive;
- _scriptInterpreter->startScript(_scriptClick, 3);
- while (_scriptInterpreter->validScript(_scriptClick)) {
- _scriptInterpreter->runScript(_scriptClick);
- }
-}
-
-void KyraEngine::resetBrandonPosionFlags() {
- _brandonStatusBit = 0;
- for (int i = 0; i < 256; ++i) {
- _brandonPoisonFlagsGFX[i] = i;
- }
-}
-
-void KyraEngine::initAnimStateList() {
- AnimObject *animStates = _animator->objects();
- animStates[0].index = 0;
- animStates[0].active = 1;
- animStates[0].flags = 0x800;
- animStates[0].background = _shapes[2];
- animStates[0].rectSize = _screen->getRectSize(4, 48);
- animStates[0].width = 4;
- animStates[0].height = 48;
- animStates[0].width2 = 4;
- animStates[0].height2 = 3;
-
- for (int i = 1; i <= 4; ++i) {
- animStates[i].index = i;
- animStates[i].active = 0;
- animStates[i].flags = 0x800;
- animStates[i].background = _shapes[3];
- animStates[i].rectSize = _screen->getRectSize(4, 64);
- animStates[i].width = 4;
- animStates[i].height = 48;
- animStates[i].width2 = 4;
- animStates[i].height2 = 3;
- }
-
- for (int i = 5; i < 16; ++i) {
- animStates[i].index = i;
- animStates[i].active = 0;
- animStates[i].flags = 0;
- }
-
- for (int i = 16; i < 28; ++i) {
- animStates[i].index = i;
- animStates[i].flags = 0;
- animStates[i].background = _shapes[349+i];
- animStates[i].rectSize = _screen->getRectSize(3, 24);
- animStates[i].width = 3;
- animStates[i].height = 16;
- animStates[i].width2 = 0;
- animStates[i].height2 = 0;
- }
-}
-
-void KyraEngine::initSceneObjectList(int brandonAlive) {
- debug(9, "KyraEngine::initSceneObjectList(%d)", brandonAlive);
- for (int i = 0; i < 28; ++i) {
- _animator->actors()[i].active = 0;
- }
-
- int startAnimFrame = 0;
-
- AnimObject *curAnimState = _animator->actors();
- curAnimState->active = 1;
- curAnimState->drawY = _currentCharacter->y1;
- curAnimState->sceneAnimPtr = _shapes[4+_currentCharacter->currentAnimFrame];
- curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
- startAnimFrame = _currentCharacter->currentAnimFrame-7;
- int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
- int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
- if (_scaleMode) {
- curAnimState->x1 = _currentCharacter->x1;
- curAnimState->y1 = _currentCharacter->y1;
-
- _brandonScaleX = _scaleTable[_currentCharacter->y1];
- _brandonScaleY = _scaleTable[_currentCharacter->y1];
-
- curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
- curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
- } else {
- curAnimState->x1 = _currentCharacter->x1 + xOffset;
- curAnimState->y1 = _currentCharacter->y1 + yOffset;
- }
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
- _animator->clearQueue();
- _animator->addObjectToQueue(curAnimState);
-
- int listAdded = 0;
- int addedObjects = 1;
-
- for (int i = 1; i < 5; ++i) {
- Character *ch = &_characterList[i];
- curAnimState = &_animator->actors()[addedObjects];
- if (ch->sceneId != _currentCharacter->sceneId) {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- ++addedObjects;
- continue;
- }
-
- curAnimState->drawY = ch->y1;
- curAnimState->sceneAnimPtr = _shapes[4+ch->currentAnimFrame];
- curAnimState->animFrameNumber = ch->currentAnimFrame;
- startAnimFrame = ch->currentAnimFrame-7;
- xOffset = _defaultShapeTable[startAnimFrame].xOffset;
- yOffset = _defaultShapeTable[startAnimFrame].yOffset;
- if (_scaleMode) {
- curAnimState->x1 = ch->x1;
- curAnimState->y1 = ch->y1;
-
- _brandonScaleX = _scaleTable[ch->y1];
- _brandonScaleY = _scaleTable[ch->y1];
-
- curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
- curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
- } else {
- curAnimState->x1 = ch->x1 + xOffset;
- curAnimState->y1 = ch->y1 + yOffset;
- }
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
-
- if (ch->facing >= 1 && ch->facing <= 3) {
- curAnimState->flags |= 1;
- } else if (ch->facing >= 5 && ch->facing <= 7) {
- curAnimState->flags &= 0xFFFFFFFE;
- }
-
- _animator->addObjectToQueue(curAnimState);
-
- ++addedObjects;
- ++listAdded;
- if (listAdded < 2)
- i = 5;
- }
-
- for (int i = 0; i < 11; ++i) {
- curAnimState = &_animator->sprites()[i];
-
- if (_sprites->_anims[i].play) {
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
- }
- else {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- }
- curAnimState->height = _sprites->_anims[i].height;
- curAnimState->height2 = _sprites->_anims[i].height2;
- curAnimState->width = _sprites->_anims[i].width + 1;
- curAnimState->width2 = _sprites->_anims[i].width2;
- curAnimState->drawY = _sprites->_anims[i].drawY;
- curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
- curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
- curAnimState->background = _sprites->_anims[i].background;
- curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
-
- if(_sprites->_anims[i].unk2)
- curAnimState->flags = 0x800;
- else
- curAnimState->flags = 0;
-
- if (_sprites->_anims[i].flipX)
- curAnimState->flags |= 0x1;
-
- _animator->addObjectToQueue(curAnimState);
- }
-
- for (int i = 0; i < 12; ++i) {
- curAnimState = &_animator->items()[i];
- Room *curRoom = &_roomTable[_currentCharacter->sceneId];
- byte curItem = curRoom->itemsTable[i];
- if (curItem != 0xFF) {
- curAnimState->drawY = curRoom->itemsYPos[i];
- curAnimState->sceneAnimPtr = _shapes[220+curItem];
- curAnimState->animFrameNumber = (int16)0xFFFF;
- curAnimState->y1 = curRoom->itemsYPos[i];
- curAnimState->x1 = curRoom->itemsXPos[i];
-
- curAnimState->x1 -= (fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
- curAnimState->y1 -= fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
-
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
-
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
-
- _animator->addObjectToQueue(curAnimState);
- } else {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- }
- }
-
- _animator->preserveAnyChangedBackgrounds();
- curAnimState = _animator->actors();
- curAnimState->bkgdChangeFlag = 1;
- curAnimState->refreshFlag = 1;
- for (int i = 1; i < 28; ++i) {
- curAnimState = &_animator->objects()[i];
- if (curAnimState->active) {
- curAnimState->bkgdChangeFlag = 1;
- curAnimState->refreshFlag = 1;
- }
- }
- _animator->restoreAllObjectBackgrounds();
- _animator->preserveAnyChangedBackgrounds();
- _animator->prepDrawAllObjects();
- initSceneScreen(brandonAlive);
- _animator->copyChangedObjectsForward(0);
-}
-
-void KyraEngine::initSceneScreen(int brandonAlive) {
- // XXX (Pointless?) Palette stuff
- if (_unkScreenVar2 == 1) {
- _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
- } else {
- _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
- }
- _screen->updateScreen();
- // XXX More (pointless?) palette stuff
-
- if (!_scriptInterpreter->startScript(_scriptClick, 2))
- error("Could not start script function 2 of scene script");
-
- _scriptClick->variables[7] = brandonAlive;
-
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-
- setTextFadeTimerCountdown(-1);
- if (_currentCharacter->sceneId == 210) {
- if (_itemInHand != -1)
- magicOutMouseItem(2, -1);
-
- _screen->hideMouse();
- for (int i = 0; i < 10; ++i) {
- if (_currentCharacter->inventoryItems[i] != 0xFF)
- magicOutMouseItem(2, i);
- }
- _screen->showMouse();
- }
-}
-
-#pragma mark -
-#pragma mark - Text handling
-#pragma mark -
-
-void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 charNum) {
- debug(9, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum);
- bool hasUpdatedNPCs = false;
- bool runLoop = true;
- uint8 currPage;
- OSystem::Event event;
- int16 delayTime;
-
- //while( towns_isEscKeyPressed() )
- //towns_getKey();
-
- uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
-
- if (chatDuration != -1 ) {
- switch (_configTalkspeed) {
- case 0: chatDuration *= 2;
- break;
- case 2: chatDuration /= 4;
- break;
- case 3: chatDuration = -1;
- }
- }
-
- if (chatDuration != -1)
- chatDuration *= _tickLength;
-
- disableTimer(14);
- disableTimer(18);
- disableTimer(19);
-
- uint32 timeAtStart = _system->getMillis();
- uint32 loopStart;
- while (runLoop) {
- loopStart = _system->getMillis();
- if (_currentCharacter->sceneId == 210)
- if (seq_playEnd())
- break;
-
- if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) {
- hasUpdatedNPCs = true;
- disableTimer(15);
- _currHeadShape = 4;
- animRefreshNPC(0);
- animRefreshNPC(_talkingCharNum);
-
- if (_charSayUnk2 != -1) {
- _animator->sprites()[_charSayUnk2].active = 0;
- _sprites->_anims[_charSayUnk2].play = false;
- _charSayUnk2 = -1;
- }
- }
-
- updateGameTimers();
- _sprites->updateSceneAnims();
- _animator->restoreAllObjectBackgrounds();
- _animator->preserveAnyChangedBackgrounds();
- _animator->prepDrawAllObjects();
-
- currPage = _screen->_curPage;
- _screen->_curPage = 2;
- _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1);
- _screen->_curPage = currPage;
-
- _animator->copyChangedObjectsForward(0);
- updateTextFade();
-
- if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1)
- break;
-
- while (_system->pollEvent(event)) {
- switch (event.type) {
- case OSystem::EVENT_KEYDOWN:
- if (event.kbd.keycode == '.')
- runLoop = false;
- break;
- case OSystem::EVENT_QUIT:
- quitGame();
- case OSystem::EVENT_LBUTTONDOWN:
- runLoop = false;
- break;
- default:
- break;
- }
- }
-
- if (_fastMode)
- runLoop = false;
-
- delayTime = (loopStart + _gameSpeed) - _system->getMillis();
- if (delayTime > 0)
- _system->delayMillis(delayTime);
- }
-
- enableTimer(14);
- enableTimer(15);
- enableTimer(18);
- enableTimer(19);
- //clearKyrandiaButtonIO();
-}
-
-void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) {
- _charSayUnk3 = -1;
-
- if (charNum > 4 && charNum < 11) {
- //TODO: weird _game_inventory stuff here
- warning("STUB: endCharacterChat() for high charnums");
- }
-
- if (convoInitialized != 0) {
- _talkingCharNum = -1;
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- }
-}
-
-void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) {
- _talkingCharNum = -1;
-
- if (charNum > 0 && charNum < 5) {
- _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame;
- animRefreshNPC(charNum);
- }
-
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
-}
-
-void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) {
- _talkingCharNum = 0;
-
- if (charNum < 5 && charNum > 0)
- _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame;
-
- if (_scaleMode != 0)
- _currentCharacter->currentAnimFrame = 7;
- else
- _currentCharacter->currentAnimFrame = _currentCharAnimFrame;
-
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
-}
-
-int8 KyraEngine::getChatPartnerNum() {
- uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A};
- int pos = 0;
- int partner = -1;
-
- for (int i = 1; i < 6; i++) {
- if (_currentCharacter->sceneId == sceneTable[pos]) {
- partner = sceneTable[pos+1];
- break;
- }
- pos += 2;
- }
-
- for (int i = 1; i < 5; i++) {
- if (_characterList[i].sceneId == _currentCharacter->sceneId) {
- partner = i;
- break;
- }
- }
- return partner;
-}
-
-int KyraEngine::initCharacterChat(int8 charNum) {
- if (_talkingCharNum == -1) {
- _talkingCharNum = 0;
-
- if (_scaleMode != 0)
- _currentCharacter->currentAnimFrame = 7;
- else
- _currentCharacter->currentAnimFrame = 16;
-
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- }
-
- _charSayUnk2 = -1;
- _animator->flagAllObjectsForBkgdChange();
- _animator->restoreAllObjectBackgrounds();
-
- if (charNum > 4 && charNum < 11) {
- // TODO: Fill in weird _game_inventory stuff here
- warning("STUB: initCharacterChat() for high charnums");
- }
-
- _animator->flagAllObjectsForRefresh();
- _animator->flagAllObjectsForBkgdChange();
- _animator->preserveAnyChangedBackgrounds();
- _charSayUnk3 = charNum;
-
- return 1;
-}
-
-void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) {
- debug(9, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration);
- uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 };
-
- uint16 chatTicks;
- int16 convoInitialized;
- int8 chatPartnerNum;
-
- if (_currentCharacter->sceneId == 210)
- return;
-
- convoInitialized = initCharacterChat(charNum);
- chatPartnerNum = getChatPartnerNum();
-
- if (chatPartnerNum != -1 && chatPartnerNum < 5)
- backupChatPartnerAnimFrame(chatPartnerNum);
-
- if (charNum < 5) {
- _characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
- _charSayUnk3 = charNum;
- _talkingCharNum = charNum;
- animRefreshNPC(charNum);
- }
-
- char *processedString = _text->preprocessString(chatStr);
- int lineNum = _text->buildMessageSubstrings(processedString);
-
- int16 yPos = _characterList[charNum].y1;
- yPos -= _scaleTable[charNum] * _characterList[charNum].height;
- yPos -= 8;
- yPos -= lineNum * 10;
-
- if (yPos < 11)
- yPos = 11;
-
- if (yPos > 100)
- yPos = 100;
-
- _text->_talkMessageY = yPos;
- _text->_talkMessageH = lineNum * 10;
- _animator->restoreAllObjectBackgrounds();
-
- _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2);
- _screen->hideMouse();
-
- _text->printCharacterText(processedString, charNum, _characterList[charNum].x1);
- _screen->showMouse();
-
- if (chatDuration == -2)
- chatTicks = strlen(processedString) * 9;
- else
- chatTicks = chatDuration;
-
- waitForChatToFinish(chatTicks, chatStr, charNum);
-
- _animator->restoreAllObjectBackgrounds();
-
- _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2);
- _animator->preserveAllBackgrounds();
- _animator->prepDrawAllObjects();
- _screen->hideMouse();
-
- _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0);
- _screen->showMouse();
- _animator->flagAllObjectsForRefresh();
- _animator->copyChangedObjectsForward(0);
-
- if (chatPartnerNum != -1 && chatPartnerNum < 5)
- restoreChatPartnerAnimFrame(chatPartnerNum);
-
- endCharacterChat(charNum, convoInitialized);
-}
-
-void KyraEngine::drawSentenceCommand(char *sentence, int color) {
- debug(9, "KyraEngine::drawSentenceCommand('%s', %i)", sentence, color);
- _screen->hideMouse();
- _screen->fillRect(8, 143, 311, 152, 12);
-
- if (_startSentencePalIndex != color || _fadeText != false) {
- _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
- _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
- _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
-
- _screen->setScreenPalette(_screen->_currentPalette);
- _startSentencePalIndex = 0;
- }
-
- _text->printText(sentence, 8, 143, 0xFF, 12, 0);
- _screen->showMouse();
- setTextFadeTimerCountdown(15);
- _fadeText = false;
-}
-
-void KyraEngine::updateSentenceCommand(char *str1, char *str2, int color) {
- debug(9, "KyraEngine::updateSentenceCommand('%s', '%s', %i)", str1, str2, color);
- char sentenceCommand[500];
- strncpy(sentenceCommand, str1, 500);
- if (str2)
- strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand));
-
- drawSentenceCommand(sentenceCommand, color);
- _screen->updateScreen();
-}
-
-void KyraEngine::updateTextFade() {
- debug(9, "KyraEngine::updateTextFade()");
- if (!_fadeText)
- return;
-
- bool finished = false;
- for (int i = 0; i < 3; i++)
- if (_currSentenceColor[i] > 4)
- _currSentenceColor[i] -= 4;
- else
- if (_currSentenceColor[i]) {
- _currSentenceColor[i] = 0;
- finished = true;
- }
-
- _screen->_currentPalette[765] = _currSentenceColor[0];
- _screen->_currentPalette[766] = _currSentenceColor[1];
- _screen->_currentPalette[767] = _currSentenceColor[2];
- _screen->setScreenPalette(_screen->_currentPalette);
-
- if (finished) {
- _fadeText = false;
- _startSentencePalIndex = -1;
- }
-}
-
-#pragma mark -
-#pragma mark - Item handling
-#pragma mark -
-
-void KyraEngine::addToNoDropRects(int x, int y, int w, int h) {
- debug(9, "KyraEngine::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h);
- for (int rect = 0; rect < 11; ++rect) {
- if (_noDropRects[rect].x == -1) {
- _noDropRects[rect].x = x;
- _noDropRects[rect].y = y;
- _noDropRects[rect].x2 = x + w - 1;
- _noDropRects[rect].y2 = y + h - 1;
- break;
- }
- }
-}
-
-void KyraEngine::clearNoDropRects() {
- debug(9, "KyraEngine::clearNoDropRects()");
- memset(_noDropRects, -1, sizeof(_noDropRects));
-}
-
-byte KyraEngine::findFreeItemInScene(int scene) {
- debug(9, "KyraEngine::findFreeItemInScene(%d)", scene);
- assert(scene < _roomTableSize);
- Room *room = &_roomTable[scene];
- for (int i = 0; i < 12; ++i) {
- if (room->itemsTable[i] == 0xFF)
- return i;
- }
- return 0xFF;
-}
-
-byte KyraEngine::findItemAtPos(int x, int y) {
- debug(9, "KyraEngine::findItemAtPos(%d, %d)", x, y);
- assert(_currentCharacter->sceneId < _roomTableSize);
- const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable;
- const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos;
- const uint8 *yposOffset = _roomTable[_currentCharacter->sceneId].itemsYPos;
-
- int highestYPos = -1;
- byte returnValue = 0xFF;
-
- for (int i = 0; i < 12; ++i) {
- if (*itemsTable != 0xFF) {
- int xpos = *xposOffset - 11;
- int xpos2 = *xposOffset + 10;
- if (x > xpos && x < xpos2) {
- assert(*itemsTable < ARRAYSIZE(_itemTable));
- int itemHeight = _itemTable[*itemsTable].height;
- int ypos = *yposOffset + 3;
- int ypos2 = ypos - itemHeight - 3;
-
- if (y > ypos2 && ypos > y) {
- if (highestYPos <= ypos) {
- returnValue = i;
- highestYPos = ypos;
- }
- }
- }
- }
- ++xposOffset;
- ++yposOffset;
- ++itemsTable;
- }
-
- return returnValue;
-}
-
-void KyraEngine::placeItemInGenericMapScene(int item, int index) {
- debug(9, "KyraEngine::placeItemInGenericMapScene(%d, %d)", item, index);
- static const uint16 itemMapSceneMinTable[] = {
- 0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000
- };
- static const uint16 itemMapSceneMaxTable[] = {
- 0x0010, 0x0024, 0x00C6, 0x006C, 0x00F5, 0x0000
- };
-
- int minValue = itemMapSceneMinTable[index];
- int maxValue = itemMapSceneMaxTable[index];
-
- while (true) {
- int room = _rnd.getRandomNumberRng(minValue, maxValue);
- assert(room < _roomTableSize);
- int nameIndex = _roomTable[room].nameIndex;
- bool placeItem = false;
-
- switch (nameIndex) {
- case 0: case 1: case 2: case 3:
- case 4: case 5: case 6: case 11:
- case 12: case 16: case 17: case 20:
- case 22: case 23: case 25: case 26:
- case 27: case 31: case 33: case 34:
- case 36: case 37: case 58: case 59:
- case 60: case 61: case 83: case 84:
- case 85: case 104: case 105: case 106:
- placeItem = true;
- break;
-
- case 51:
- if (room != 46) {
- placeItem = true;
- break;
- }
- default:
- placeItem = false;
- break;
- }
-
- if (placeItem) {
- Room *roomPtr = &_roomTable[room];
- if (roomPtr->northExit == 0xFFFF && roomPtr->eastExit == 0xFFFF && roomPtr->southExit == 0xFFFF && roomPtr->westExit == 0xFFFF) {
- placeItem = false;
- } else if (_currentCharacter->sceneId == room) {
- placeItem = false;
- }
- }
-
- if (placeItem) {
- if (!processItemDrop(room, item, -1, -1, 2, 0))
- continue;
- break;
- }
- }
-}
-
-void KyraEngine::createMouseItem(int item) {
- debug(9, "KyraEngine::createMouseItem(%d)", item);
- _screen->hideMouse();
- setMouseItem(item);
- _itemInHand = item;
- _screen->showMouse();
-}
-
-void KyraEngine::destroyMouseItem() {
- debug(9, "KyraEngine::destroyMouseItem()");
- _screen->hideMouse();
- _screen->setMouseCursor(1, 1, _shapes[4]);
- _itemInHand = -1;
- _screen->showMouse();
-}
-
-void KyraEngine::setMouseItem(int item) {
- debug(9, "KyraEngine::setMouseItem(%d)", item);
- if (item == -1) {
- _screen->setMouseCursor(1, 1, _shapes[10]);
- } else {
- _screen->setMouseCursor(8, 15, _shapes[220+item]);
- }
-}
-
-void KyraEngine::wipeDownMouseItem(int xpos, int ypos) {
- debug(9, "KyraEngine::wipeDownMouseItem(%d, %d)", xpos, ypos);
- if (_itemInHand == -1)
- return;
- xpos -= 8;
- ypos -= 15;
- _screen->hideMouse();
- backUpRect1(xpos, ypos);
- int y = ypos;
- int height = 16;
-
- while (height >= 0) {
- restoreRect1(xpos, ypos);
- _screen->setNewShapeHeight(_shapes[220+_itemInHand], height);
- uint32 nextTime = _system->getMillis() + 1 * _tickLength;
- _screen->drawShape(0, _shapes[220+_itemInHand], xpos, y, 0, 0);
- _screen->updateScreen();
- y += 2;
- height -= 2;
- while (_system->getMillis() < nextTime) {}
- }
- restoreRect1(xpos, ypos);
- _screen->resetShapeHeight(_shapes[220+_itemInHand]);
- destroyMouseItem();
- _screen->showMouse();
-}
-
-void KyraEngine::setupSceneItems() {
- debug(9, "KyraEngine::setupSceneItems()");
- uint16 sceneId = _currentCharacter->sceneId;
- assert(sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[sceneId];
- for (int i = 0; i < 12; ++i) {
- uint8 item = currentRoom->itemsTable[i];
- if (item == 0xFF || !currentRoom->needInit[i]) {
- continue;
- }
-
- int xpos = 0;
- int ypos = 0;
-
- if (currentRoom->itemsXPos[i] == 0xFFFF) {
- xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
- ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
- } else {
- xpos = currentRoom->itemsXPos[i];
- ypos = currentRoom->itemsYPos[i];
- }
-
- _lastProcessedItem = i;
-
- int stop = 0;
- while (!stop) {
- stop = processItemDrop(sceneId, item, xpos, ypos, 3, 0);
- if (!stop) {
- xpos = currentRoom->itemsXPos[i] = _rnd.getRandomNumberRng(24, 296);
- ypos = currentRoom->itemsYPos[i] = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 130);
- if (countItemsInScene(sceneId) >= 12) {
- break;
- }
- } else {
- currentRoom->needInit[i] = 0;
- }
- }
- }
-}
-
-int KyraEngine::countItemsInScene(uint16 sceneId) {
- debug(9, "KyraEngine::countItemsInScene(%d)", sceneId);
- assert(sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[sceneId];
-
- int items = 0;
-
- for (int i = 0; i < 12; ++i) {
- if (currentRoom->itemsTable[i] != 0xFF) {
- ++items;
- }
- }
-
- return items;
-}
-
-int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) {
- debug(9, "KyraEngine::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
- int freeItem = -1;
- uint8 itemIndex = findItemAtPos(x, y);
- if (unk1) {
- itemIndex = 0xFF;
- }
-
- if (itemIndex != 0xFF) {
- exchangeItemWithMouseItem(sceneId, itemIndex);
- return 0;
- }
-
- assert(sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[sceneId];
-
- if (unk1 != 3) {
- for (int i = 0; i < 12; ++i) {
- if (currentRoom->itemsTable[i] == 0xFF) {
- freeItem = i;
- break;
- }
- }
- } else {
- freeItem = _lastProcessedItem;
- }
-
- if (freeItem == -1) {
- return 0;
- }
-
- if (sceneId != _currentCharacter->sceneId) {
- addItemToRoom(sceneId, item, freeItem, x, y);
- return 1;
- }
-
- int itemHeight = _itemTable[item].height;
- _lastProcessedItemHeight = itemHeight;
-
- if (x == -1 && x == -1) {
- x = _rnd.getRandomNumberRng(16, 304);
- y = _rnd.getRandomNumberRng(_northExitHeight & 0xFF, 135);
- }
-
- int xpos = x;
- int ypos = y;
- int destY = -1;
- int destX = -1;
- int running = 1;
-
- while (running) {
- if ((_northExitHeight & 0xFF) <= ypos) {
- bool running2 = true;
-
- if (getDrawLayer(xpos, ypos) > 1) {
- if (((_northExitHeight >> 8) & 0xFF) != ypos) {
- running2 = false;
- }
- }
-
- if (getDrawLayer2(xpos, ypos, itemHeight) > 1) {
- if (((_northExitHeight >> 8) & 0xFF) != ypos) {
- running2 = false;
- }
- }
-
- if (!isDropable(xpos, ypos)) {
- if (((_northExitHeight >> 8) & 0xFF) != ypos) {
- running2 = false;
- }
- }
-
- int xpos2 = xpos;
- int xpos3 = xpos;
-
- while (running2) {
- if (isDropable(xpos2, ypos)) {
- if (getDrawLayer2(xpos2, ypos, itemHeight) < 7) {
- if (findItemAtPos(xpos2, ypos) == 0xFF) {
- destX = xpos2;
- destY = ypos;
- running = 0;
- running2 = false;
- }
- }
- }
-
- if (isDropable(xpos3, ypos)) {
- if (getDrawLayer2(xpos3, ypos, itemHeight) < 7) {
- if (findItemAtPos(xpos3, ypos) == 0xFF) {
- destX = xpos3;
- destY = ypos;
- running = 0;
- running2 = false;
- }
- }
- }
-
- if (!running2)
- continue;
-
- xpos2 -= 2;
- if (xpos2 < 16) {
- xpos2 = 16;
- }
-
- xpos3 += 2;
- if (xpos3 > 304) {
- xpos3 = 304;
- }
-
- if (xpos2 > 16)
- continue;
- if (xpos3 < 304)
- continue;
- running2 = false;
- }
- }
-
- if (((_northExitHeight >> 8) & 0xFF) == ypos) {
- running = 0;
- destY -= _rnd.getRandomNumberRng(0, 3);
-
- if ((_northExitHeight & 0xFF) < destY) {
- continue;
- }
-
- destY = (_northExitHeight & 0xFF) + 1;
- continue;
- }
- ypos += 2;
- if (((_northExitHeight >> 8) & 0xFF) >= ypos) {
- continue;
- }
- ypos = (_northExitHeight >> 8) & 0xFF;
- }
-
- if (destX == -1 || destY == -1) {
- return 0;
- }
-
- if (unk1 == 3) {
- currentRoom->itemsXPos[freeItem] = destX;
- currentRoom->itemsYPos[freeItem] = destY;
- return 1;
- }
-
- if (unk1 == 2) {
- itemSpecialFX(x, y, item);
- }
-
- if (unk1 == 0) {
- destroyMouseItem();
- }
-
- itemDropDown(x, y, destX, destY, freeItem, item);
-
- if (unk1 == 0 && unk2 != 0) {
- assert(_itemList && _droppedList);
- updateSentenceCommand(_itemList[item], _droppedList[0], 179);
- }
-
- return 1;
-}
-
-void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
- debug(9, "KyraEngine::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex);
- _screen->hideMouse();
- _animator->animRemoveGameItem(itemIndex);
- assert(sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[sceneId];
-
- int item = currentRoom->itemsTable[itemIndex];
- currentRoom->itemsTable[itemIndex] = _itemInHand;
- _itemInHand = item;
- _animator->animAddGameItem(itemIndex, sceneId);
- snd_playSoundEffect(53);
-
- setMouseItem(_itemInHand);
- assert(_itemList && _takenList);
- updateSentenceCommand(_itemList[_itemInHand], _takenList[1], 179);
- _screen->showMouse();
- clickEventHandler2();
-}
-
-void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) {
- debug(9, "KyraEngine::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y);
- assert(sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[sceneId];
- currentRoom->itemsTable[itemIndex] = item;
- currentRoom->itemsXPos[itemIndex] = x;
- currentRoom->itemsYPos[itemIndex] = y;
- currentRoom->needInit[itemIndex] = 1;
-}
-
-int KyraEngine::checkNoDropRects(int x, int y) {
- debug(9, "KyraEngine::checkNoDropRects(%d, %d)", x, y);
- if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16) {
- _lastProcessedItemHeight = 16;
- }
- if (_noDropRects[0].x == -1) {
- return 0;
- }
-
- for (int i = 0; i < 11; ++i) {
- if (_noDropRects[i].x == -1) {
- break;
- }
-
- int xpos = _noDropRects[i].x;
- int ypos = _noDropRects[i].y;
- int xpos2 = _noDropRects[i].x2;
- int ypos2 = _noDropRects[i].y2;
-
- if (xpos > x + 16)
- continue;
- if (xpos2 < x)
- continue;
- if (y < ypos)
- continue;
- if (ypos2 < y - _lastProcessedItemHeight)
- continue;
- return 1;
- }
-
- return 0;
-}
-
-int KyraEngine::isDropable(int x, int y) {
- debug(9, "KyraEngine::isDropable(%d, %d)", x, y);
- x -= 8;
- y -= 1;
-
- if (checkNoDropRects(x, y)) {
- return 0;
- }
-
- for (int xpos = x; xpos < x + 16; ++xpos) {
- if (_screen->getShapeFlag1(xpos, y) == 0) {
- return 0;
- }
- }
- return 1;
-}
-
-void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) {
- debug(9, "KyraEngine::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item);
- assert(_currentCharacter->sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
- if (x == destX && y == destY) {
- currentRoom->itemsXPos[freeItem] = destX;
- currentRoom->itemsYPos[freeItem] = destY;
- currentRoom->itemsTable[freeItem] = item;
- snd_playSoundEffect(0x32);
- _animator->animAddGameItem(freeItem, _currentCharacter->sceneId);
- return;
- }
- _screen->hideMouse();
- if (y <= destY) {
- int tempY = y;
- int addY = 2;
- int drawX = x - 8;
- int drawY = 0;
-
- backUpRect0(drawX, y - 16);
-
- while (tempY < destY) {
- restoreRect0(drawX, tempY - 16);
- tempY += addY;
- if (tempY > destY) {
- tempY = destY;
- }
- ++addY;
- drawY = tempY - 16;
- backUpRect0(drawX, drawY);
- uint32 nextTime = _system->getMillis() + 1 * _tickLength;
- _screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if ((nextTime - _system->getMillis()) >= 10)
- delay(10);
- }
- }
-
- bool skip = false;
- if (x == destX) {
- if (destY - y <= 16) {
- skip = true;
- }
- }
-
- if (!skip) {
- snd_playSoundEffect(0x47);
- if (addY < 6)
- addY = 6;
-
- int xDiff = (destX - x) << 4;
- xDiff /= addY;
- int startAddY = addY;
- addY >>= 1;
- if (destY - y <= 8) {
- addY >>= 1;
- }
- addY = -addY;
- int unkX = x << 4;
- while (--startAddY) {
- drawX = (unkX >> 4) - 8;
- drawY = tempY - 16;
- restoreRect0(drawX, drawY);
- tempY += addY;
- unkX += xDiff;
- if (tempY > destY) {
- tempY = destY;
- }
- ++addY;
- drawX = (unkX >> 4) - 8;
- drawY = tempY - 16;
- backUpRect0(drawX, drawY);
- uint32 nextTime = _system->getMillis() + 1 * _tickLength;
- _screen->drawShape(0, _shapes[220+item], drawX, drawY, 0, 0);
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if ((nextTime - _system->getMillis()) >= 10)
- delay(10);
- }
- }
- restoreRect0(drawX, drawY);
- } else {
- restoreRect0(drawX, tempY - 16);
- }
- }
- currentRoom->itemsXPos[freeItem] = destX;
- currentRoom->itemsYPos[freeItem] = destY;
- currentRoom->itemsTable[freeItem] = item;
- snd_playSoundEffect(0x32);
- _animator->animAddGameItem(freeItem, _currentCharacter->sceneId);
- _screen->showMouse();
-}
-
-void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) {
- debug(9, "KyraEngine::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
- if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2))
- return;
- snd_playSoundEffect(54);
- if (12 == countItemsInScene(_currentCharacter->sceneId)) {
- assert(_noDropList);
- drawSentenceCommand(_noDropList[0], 6);
- } else {
- assert(_noDropList);
- drawSentenceCommand(_noDropList[1], 6);
- }
-}
-
-void KyraEngine::itemSpecialFX(int x, int y, int item) {
- debug(9, "KyraEngine::itemSpecialFX(%d, %d, %d)", x, y, item);
- if (item == 41) {
- itemSpecialFX1(x, y, item);
- } else {
- itemSpecialFX2(x, y, item);
- }
-}
-
-void KyraEngine::itemSpecialFX1(int x, int y, int item) {
- debug(9, "KyraEngine::itemSpecialFX1(%d, %d, %d)", x, y, item);
- uint8 *shape = _shapes[220+item];
- x -= 8;
- int startY = y;
- y -= 15;
- _screen->hideMouse();
- backUpRect0(x, y);
- for (int i = 1; i <= 16; ++i) {
- _screen->setNewShapeHeight(shape, i);
- --startY;
- restoreRect0(x, y);
- uint32 nextTime = _system->getMillis() + 1 * _tickLength;
- _screen->drawShape(0, shape, x, startY, 0, 0);
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if ((nextTime - _system->getMillis()) >= 10)
- delay(10);
- }
- }
- restoreRect0(x, y);
- _screen->showMouse();
-}
-
-void KyraEngine::itemSpecialFX2(int x, int y, int item) {
- debug(9, "KyraEngine::itemSpecialFX2(%d, %d, %d)", x, y, item);
- x -= 8;
- y -= 15;
- int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF);
- backUpRect0(x, y);
- if (item >= 80 && item <= 89) {
- snd_playSoundEffect(55);
- }
-
- for (int i = 201; i <= 205; ++i) {
- restoreRect0(x, y);
- uint32 nextTime = _system->getMillis() + 3 * _tickLength;
- _screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if ((nextTime - _system->getMillis()) >= 10)
- delay(10);
- }
- }
-
- for (int i = 204; i >= 201; --i) {
- restoreRect0(x, y);
- uint32 nextTime = _system->getMillis() + 3 * _tickLength;
- _screen->drawShape(0, _shapes[220+item], x, y, 0, 0);
- _screen->drawShape(0, _shapes[4+i], x, y + yAdd, 0, 0);
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if ((nextTime - _system->getMillis()) >= 10)
- delay(10);
- }
- }
- restoreRect0(x, y);
-}
-
-void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) {
- debug(9, "KyraEngine::magicOutMouseItem(%d, %d)", animIndex, itemPos);
- int videoPageBackUp = _screen->_curPage;
- _screen->_curPage = 0;
- int x = 0, y = 0;
- if (itemPos == -1) {
- x = _mouseX - 12;
- y = _mouseY - 18;
- } else {
- x = _itemPosX[itemPos] - 4;
- y = _itemPosY[itemPos] - 3;
- }
-
- if (_itemInHand == -1 && itemPos == -1) {
- return;
- }
-
- int tableIndex = 0, loopStart = 0, maxLoops = 0;
- if (animIndex == 0) {
- tableIndex = _rnd.getRandomNumberRng(0, 5);
- loopStart = 35;
- maxLoops = 9;
- } else if (animIndex == 1) {
- tableIndex = _rnd.getRandomNumberRng(0, 11);
- loopStart = 115;
- maxLoops = 8;
- } else if (animIndex == 2) {
- tableIndex = 0;
- loopStart = 124;
- maxLoops = 4;
- } else {
- tableIndex = -1;
- }
-
- if (animIndex == 2) {
- snd_playSoundEffect(0x5E);
- } else {
- snd_playSoundEffect(0x37);
- }
- _screen->hideMouse();
- backUpRect1(x, y);
-
- for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
- restoreRect1(x, y);
- uint32 nextTime = _system->getMillis() + 4 * _tickLength;
- _screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
- if (tableIndex == -1) {
- _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
- } else {
- specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
- }
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if (nextTime - _system->getMillis() >= 10)
- delay(10);
- }
- }
-
- if (itemPos != -1) {
- restoreRect1(x, y);
- _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
- backUpRect1(x, y);
- }
-
- for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
- restoreRect1(x, y);
- uint32 nextTime = _system->getMillis() + 4 * _tickLength;
- _screen->drawShape(0, _shapes[220+_itemInHand], x + 4, y + 3, 0, 0);
- if (tableIndex == -1) {
- _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
- } else {
- specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
- }
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if (nextTime - _system->getMillis() >= 10)
- delay(10);
- }
- }
- restoreRect1(x, y);
- if (itemPos == -1) {
- _screen->setMouseCursor(1, 1, _shapes[4]);
- _itemInHand = -1;
- } else {
- _characterList[0].inventoryItems[itemPos] = 0xFF;
- _screen->hideMouse();
- _screen->fillRect(_itemPosX[itemPos], _itemPosY[itemPos], _itemPosX[itemPos] + 15, _itemPosY[itemPos] + 15, 12, 0);
- _screen->showMouse();
- }
- _screen->showMouse();
- _screen->_curPage = videoPageBackUp;
-}
-
-void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) {
- debug(9, "KyraEngine::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos);
- int videoPageBackUp = _screen->_curPage;
- _screen->_curPage = 0;
- int x = 0, y = 0;
- if (itemPos == -1) {
- x = _mouseX - 12;
- y = _mouseY - 18;
- } else {
- x = _itemPosX[itemPos] - 4;
- y = _itemPosX[itemPos] - 3;
- }
- if (item < 0)
- return;
-
- int tableIndex = -1, loopStart = 0, maxLoops = 0;
- if (animIndex == 0) {
- tableIndex = _rnd.getRandomNumberRng(0, 5);
- loopStart = 35;
- maxLoops = 9;
- } else if (animIndex == 1) {
- tableIndex = _rnd.getRandomNumberRng(0, 11);
- loopStart = 115;
- maxLoops = 8;
- } else if (animIndex == 2) {
- tableIndex = 0;
- loopStart = 124;
- maxLoops = 4;
- }
-
- _screen->hideMouse();
- backUpRect1(x, y);
- if (animIndex == 2) {
- snd_playSoundEffect(0x5E);
- } else {
- snd_playSoundEffect(0x37);
- }
-
- for (int shape = _magicMouseItemStartFrame[animIndex]; shape <= _magicMouseItemEndFrame[animIndex]; ++shape) {
- restoreRect1(x, y);
- uint32 nextTime = _system->getMillis() + 4 * _tickLength;
- if (tableIndex == -1) {
- _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
- } else {
- specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
- }
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if (nextTime - _system->getMillis() >= 10)
- delay(10);
- }
- }
-
- for (int shape = _magicMouseItemStartFrame2[animIndex]; shape <= _magicMouseItemEndFrame2[animIndex]; ++shape) {
- restoreRect1(x, y);
- uint32 nextTime = _system->getMillis() + 4 * _tickLength;
- if (tableIndex == -1) {
- _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0);
- } else {
- specialMouseItemFX(shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
- }
- _screen->updateScreen();
- while (_system->getMillis() < nextTime) {
- if (nextTime - _system->getMillis() >= 10)
- delay(10);
- }
- }
- restoreRect1(x, y);
- if (itemPos == -1) {
- _screen->setMouseCursor(8, 15, _shapes[220+item]);
- _itemInHand = item;
- } else {
- _characterList[0].inventoryItems[itemPos] = item;
- _screen->hideMouse();
- _screen->drawShape(0, _shapes[220+item], _itemPosX[itemPos], _itemPosY[itemPos], 0, 0);
- _screen->showMouse();
- }
- _screen->showMouse();
- _screen->_curPage = videoPageBackUp;
-}
-
-void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) {
- debug(9, "KyraEngine::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
- static const uint8 table1[] = {
- 0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00
- };
- static const uint8 table2[] = {
- 0x73, 0xB5, 0x80, 0x21, 0x13, 0x39, 0x45, 0x55, 0x62, 0xB4, 0xCF, 0xD8
- };
- static const uint8 table3[] = {
- 0x7C, 0xD0, 0x74, 0x84, 0x87, 0x00, 0x00, 0x00
- };
- int tableValue = 0;
- if (animIndex == 0) {
- tableValue = table1[tableIndex];
- } else if (animIndex == 1) {
- tableValue = table2[tableIndex];
- } else if (animIndex == 2) {
- tableValue = table3[tableIndex];
- } else {
- return;
- }
- processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops);
-}
-
-void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) {
- debug(9, "KyraEngine::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops);
- uint8 shapeColorTable[16];
- uint8 *shapePtr = _shapes[4+shape] + 10;
- if (_features & GF_TALKIE)
- shapePtr += 2;
- for (int i = 0; i < 16; ++i) {
- shapeColorTable[i] = shapePtr[i];
- }
- for (int i = loopStart; i < loopStart + maxLoops; ++i) {
- for (int i2 = 0; i2 < 16; ++i2) {
- if (shapePtr[i2] == i) {
- shapeColorTable[i2] = (i + tableValue) - loopStart;
- }
- }
- }
- _screen->drawShape(0, _shapes[4+shape], x, y, 0, 0x8000, shapeColorTable);
-}
-
-void KyraEngine::updatePlayerItemsForScene() {
- debug(9, "KyraEngine::updatePlayerItemsForScene()");
- if (_itemInHand >= 29 && _itemInHand < 33) {
- ++_itemInHand;
- if (_itemInHand > 33)
- _itemInHand = 33;
- _screen->hideMouse();
- _screen->setMouseCursor(8, 15, _shapes[220+_itemInHand]);
- _screen->showMouse();
- }
-
- bool redraw = false;
- for (int i = 0; i < 10; ++i) {
- uint8 item = _currentCharacter->inventoryItems[i];
- if (item >= 29 && item < 33) {
- ++item;
- if (item > 33)
- item = 33;
- _currentCharacter->inventoryItems[i] = item;
- redraw = true;
- }
- }
-
- if (redraw) {
- _screen->hideMouse();
- redrawInventory(0);
- _screen->showMouse();
- }
-
- if (_itemInHand == 33) {
- magicOutMouseItem(2, -1);
- }
-
- _screen->hideMouse();
- for (int i = 0; i < 10; ++i) {
- uint8 item = _currentCharacter->inventoryItems[i];
- if (item == 33) {
- magicOutMouseItem(2, i);
- }
- }
- _screen->showMouse();
-}
-
-void KyraEngine::redrawInventory(int page) {
- int videoPageBackUp = _screen->_curPage;
- _screen->_curPage = page;
- _screen->hideMouse();
- for (int i = 0; i < 10; ++i) {
- _screen->fillRect(_itemPosX[i], _itemPosY[i], _itemPosX[i] + 15, _itemPosY[i] + 15, 12, page);
- if (_currentCharacter->inventoryItems[i] != 0xFF) {
- uint8 item = _currentCharacter->inventoryItems[i];
- _screen->drawShape(page, _shapes[220+item], _itemPosX[i], _itemPosY[i], 0, 0);
- }
- }
- _screen->showMouse();
- _screen->_curPage = videoPageBackUp;
- _screen->updateScreen();
-}
-
#pragma mark -
#pragma mark - Animation/shape specific code
#pragma mark -
@@ -4507,126 +1047,6 @@ int16 KyraEngine::fetchAnimHeight(const uint8 *shape, int16 mult) {
return (int16)(((int8)*(shape+2)) * mult) >> 8;
}
-void KyraEngine::rectClip(int &x, int &y, int w, int h) {
- if (x < 0) {
- x = 0;
- } else if (x + w >= 320) {
- x = 320 - w;
- }
- if (y < 0) {
- y = 0;
- } else if (y + h >= 200) {
- y = 200 - h;
- }
-}
-
-void KyraEngine::backUpRect0(int xpos, int ypos) {
- debug(9, "KyraEngine::backUpRect0(%d, %d)", xpos, ypos);
- rectClip(xpos, ypos, 3<<3, 24);
- _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 3<<3, 24, _shapes[0]);
-}
-
-void KyraEngine::restoreRect0(int xpos, int ypos) {
- debug(9, "KyraEngine::restoreRect0(%d, %d)", xpos, ypos);
- rectClip(xpos, ypos, 3<<3, 24);
- _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 3<<3, 24, _shapes[0]);
-}
-
-void KyraEngine::backUpRect1(int xpos, int ypos) {
- debug(9, "KyraEngine::backUpRect1(%d, %d)", xpos, ypos);
- rectClip(xpos, ypos, 4<<3, 32);
- _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 4<<3, 32, _shapes[1]);
-}
-
-void KyraEngine::restoreRect1(int xpos, int ypos) {
- debug(9, "KyraEngine::restoreRect1(%d, %d)", xpos, ypos);
- rectClip(xpos, ypos, 4<<3, 32);
- _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _shapes[1]);
-}
-
-int KyraEngine::getDrawLayer(int x, int y) {
- debug(9, "KyraEngine::getDrawLayer(%d, %d)", x, y);
- int xpos = x - 8;
- int ypos = y - 1;
- int layer = 1;
- for (int curX = xpos; curX < xpos + 16; ++curX) {
- int tempLayer = _screen->getShapeFlag2(curX, ypos);
- if (layer < tempLayer) {
- layer = tempLayer;
- }
- if (layer >= 7) {
- return 7;
- }
- }
- return layer;
-}
-
-int KyraEngine::getDrawLayer2(int x, int y, int height) {
- debug(9, "KyraEngine::getDrawLayer2(%d, %d, %d)", x, y, height);
- int xpos = x - 8;
- int ypos = y - 1;
- int layer = 1;
-
- for (int useX = xpos; useX < xpos + 16; ++useX) {
- for (int useY = ypos - height; useY < ypos; ++useY) {
- int tempLayer = _screen->getShapeFlag2(useX, useY);
- if (tempLayer > layer) {
- layer = tempLayer;
- }
-
- if (tempLayer >= 7) {
- return 7;
- }
- }
- }
- return layer;
-}
-
-void KyraEngine::copyBackgroundBlock(int x, int page, int flag) {
- debug(9, "KyraEngine::copyBackgroundBlock(%d, %d, %d)", x, page, flag);
-
- if (x < 1)
- return;
-
- int height = 128;
- if (flag)
- height += 8;
- if (!(x & 1))
- ++x;
- if (x == 19)
- x = 17;
- uint8 *ptr1 = _unkPtr1;
- uint8 *ptr2 = _unkPtr2;
- int oldVideoPage = _screen->_curPage;
- _screen->_curPage = page;
-
- int curX = x;
- _screen->hideMouse();
- _screen->copyRegionToBuffer(_screen->_curPage, 8, 8, 8, height, ptr2);
- for (int i = 0; i < 19; ++i) {
- int tempX = curX + 1;
- _screen->copyRegionToBuffer(_screen->_curPage, tempX<<3, 8, 8, height, ptr1);
- _screen->copyBlockToPage(_screen->_curPage, tempX<<3, 8, 8, height, ptr2);
- int newXPos = curX + x;
- if (newXPos > 37) {
- newXPos = newXPos % 38;
- }
- tempX = newXPos + 1;
- _screen->copyRegionToBuffer(_screen->_curPage, tempX<<3, 8, 8, height, ptr2);
- _screen->copyBlockToPage(_screen->_curPage, tempX<<3, 8, 8, height, ptr1);
- curX += x*2;
- if (curX > 37) {
- curX = curX % 38;
- }
- }
- _screen->showMouse();
- _screen->_curPage = oldVideoPage;
-}
-
-void KyraEngine::copyBackgroundBlock2(int x) {
- copyBackgroundBlock(x, 4, 1);
-}
-
void KyraEngine::makeBrandonFaceMouse() {
debug(9, "KyraEngine::makeBrandonFaceMouse()");
if (_mouseX >= _currentCharacter->x1) {
@@ -5150,674 +1570,6 @@ int KyraEngine::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
}
#pragma mark -
-#pragma mark - Pathfinder
-#pragma mark -
-
-int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
- debug(9, "KyraEngine::findWay(%d, %d, %d, %d, 0x%X, %d)", x, y, toX, toY, moveTable, moveTableSize);
- x &= 0xFFFC; toX &= 0xFFFC;
- y &= 0xFFFE; toY &= 0xFFFE;
- x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
-
- if (x == toY && y == toY) {
- moveTable[0] = 8;
- return 0;
- }
-
- int curX = x;
- int curY = y;
- int lastUsedEntry = 0;
- int tempValue = 0;
- int *pathTable1 = new int[0x7D0];
- int *pathTable2 = new int[0x7D0];
- assert(pathTable1 && pathTable2);
-
- while (true) {
- int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
- changePosTowardsFacing(curX, curY, newFacing);
-
- if (curX == toX && curY == toY) {
- if (!lineIsPassable(curX, curY))
- break;
- moveTable[lastUsedEntry++] = newFacing;
- break;
- }
-
- if (lineIsPassable(curX, curY)) {
- if (lastUsedEntry == moveTableSize) {
- delete [] pathTable1;
- delete [] pathTable2;
- return 0x7D00;
- }
- // debug drawing
- //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
- // _screen->setPagePixel(0, curX, curY, 11);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
- moveTable[lastUsedEntry++] = newFacing;
- x = curX;
- y = curY;
- continue;
- }
-
- int temp = 0;
- while (true) {
- newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
- changePosTowardsFacing(curX, curY, newFacing);
- // debug drawing
- //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
- // _screen->setPagePixel(0, curX, curY, 8);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
-
- if (!lineIsPassable(curX, curY)) {
- if (curX != toX || curY != toY)
- continue;
- }
-
- if (curX == toX && curY == toY) {
- if (!lineIsPassable(curX, curY)) {
- tempValue = 0;
- temp = 0;
- break;
- }
- }
-
- temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
- tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
- if (curX == toX && curY == toY) {
- if (temp == 0x7D00 && tempValue == 0x7D00) {
- delete [] pathTable1;
- delete [] pathTable2;
- return 0x7D00;
- }
- }
-
- if (temp != 0x7D00 || tempValue != 0x7D00) {
- break;
- }
- }
-
- if (temp < tempValue) {
- if (lastUsedEntry + temp > moveTableSize) {
- delete [] pathTable1;
- delete [] pathTable2;
- return 0x7D00;
- }
- memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int));
- lastUsedEntry += temp;
- } else {
- if (lastUsedEntry + tempValue > moveTableSize) {
- delete [] pathTable1;
- delete [] pathTable2;
- return 0x7D00;
- }
- memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int));
- lastUsedEntry += tempValue;
- }
- x = curX;
- y = curY;
- if (curX == toX && curY == toY) {
- break;
- }
- }
- delete [] pathTable1;
- delete [] pathTable2;
- moveTable[lastUsedEntry] = 8;
- return getMoveTableSize(moveTable);
-}
-
-int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
- debug(9, "KyraEngine::findSubPath(%d, %d, %d, %d, 0x%X, %d, %d)", x, y, toX, toY, moveTable, start, end);
- // only used for debug specific code
- //static uint16 unkTable[] = { 8, 5 };
- static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 };
- static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 };
- static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 };
- static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 };
- static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
-
- // debug specific
- //++unkTable[start];
- //while (_screen->getPalette(0)[unkTable[start]] != 0x0F) {
- // ++unkTable[start];
- //}
-
- int xpos1 = x, xpos2 = x;
- int ypos1 = y, ypos2 = y;
- int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
- int position = 0;
-
- while (position != end) {
- int newFacing2 = newFacing;
- while (true) {
- changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]);
- if (!lineIsPassable(xpos1, ypos1)) {
- if (facingTable1[start*8 + newFacing2] == newFacing) {
- return 0x7D00;
- }
- newFacing2 = facingTable1[start*8 + newFacing2];
- xpos1 = x;
- ypos1 = y;
- continue;
- }
- newFacing = facingTable1[start*8 + newFacing2];
- break;
- }
- // debug drawing
- //if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
- // _screen->setPagePixel(0, xpos1, ypos1, unkTable[start]);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
- if (newFacing & 1) {
- int temp = xpos1 + addPosTableX[newFacing + start * 8];
- if (toX == temp) {
- temp = ypos1 + addPosTableY[newFacing + start * 8];
- if (toY == temp) {
- moveTable[position++] = facingTable2[newFacing + start * 8];
- return position;
- }
- }
- }
- moveTable[position++] = newFacing;
- x = xpos1;
- y = ypos1;
- if (x == toX && y == toY) {
- return position;
- }
-
- if (xpos1 == xpos2 && ypos1 == ypos2) {
- break;
- }
-
- newFacing = facingTable3[start*8 + newFacing];
- }
- return 0x7D00;
-}
-
-int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
- debug(9, "KyraEngine::getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY);
- static const int facingTable[] = {
- 1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
- };
-
- int facingEntry = 0;
- int ydiff = y - toY;
- if (ydiff < 0) {
- ++facingEntry;
- ydiff = -ydiff;
- }
- facingEntry <<= 1;
-
- int xdiff = toX - x;
- if (xdiff < 0) {
- ++facingEntry;
- xdiff = -xdiff;
- }
-
- if (xdiff >= ydiff) {
- int temp = ydiff;
- ydiff = xdiff;
- xdiff = temp;
-
- facingEntry <<= 1;
- } else {
- facingEntry <<= 1;
- facingEntry += 1;
- }
- int temp = (ydiff + 1) >> 1;
-
- if (xdiff < temp) {
- facingEntry <<= 1;
- facingEntry += 1;
- } else {
- facingEntry <<= 1;
- }
- assert(facingEntry < ARRAYSIZE(facingTable));
- return facingTable[facingEntry];
-}
-
-void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) {
- debug(9, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing);
- x += _addXPosTable[facing];
- y += _addYPosTable[facing];
-}
-
-bool KyraEngine::lineIsPassable(int x, int y) {
- debug(9, "KyraEngine::lineIsPassable(%d, %d)", x, y);
- if (queryGameFlag(0xEF)) {
- if (_currentCharacter->sceneId == 5)
- return true;
- }
-
- if (_pathfinderFlag & 2) {
- if (x >= 312)
- return false;
- }
-
- if (_pathfinderFlag & 4) {
- if (y >= 136)
- return false;
- }
-
- if (_pathfinderFlag & 8) {
- if (x < 8)
- return false;
- }
-
- if (_pathfinderFlag2) {
- if (x <= 8 || x >= 312)
- return true;
- if (y < (_northExitHeight & 0xFF) || y > 135)
- return true;
- }
-
- if (y > 137) {
- return false;
- }
-
- int ypos = 8;
- if (_scaleMode) {
- ypos = (_scaleTable[y] >> 5) + 1;
- if (8 < ypos)
- ypos = 8;
- }
-
- x -= (ypos >> 1);
- if (y < 0)
- y = 0;
-
- int xpos = x;
- int xtemp = xpos + ypos - 1;
- if (x < 0)
- xpos = 0;
-
- if (xtemp > 319)
- xtemp = 319;
-
- for (; xpos < xtemp; ++xpos) {
- if (!_screen->getShapeFlag1(xpos, y))
- return false;
- }
- return true;
-}
-
-int KyraEngine::getMoveTableSize(int *moveTable) {
- debug(9, "KyraEngine::getMoveTableSize(0x%X)", moveTable);
- int retValue = 0;
- if (moveTable[0] == 8)
- return 0;
-
- static const int facingTable[] = {
- 4, 5, 6, 7, 0, 1, 2, 3
- };
- static const int unkTable[] = {
- -1, -1, 1, 2, -1, 6, 7, -1,
- -1, -1, -1, -1, 2, -1, 0, -1,
- 1, -1, -1, -1, 3, 4, -1, 0,
- 2, -1, -1, -1, -1, -1, 4, -1,
- -1, 2, 3, -1, -1, -1, 5, 6,
- 6, -1, 4, -1, -1, -1, -1, -1,
- 7, 0, -1, 4, 5, -1, -1, -1,
- -1, -1, 0, -1, 6, -1, -1, -1
- };
-
- int *oldPosition = moveTable;
- int *tempPosition = moveTable;
- int *curPosition = moveTable + 1;
- retValue = 1;
-
- while (*curPosition != 8) {
- if (*oldPosition == facingTable[*curPosition]) {
- retValue -= 2;
- *oldPosition = 9;
- *curPosition = 9;
-
- while (tempPosition != moveTable) {
- --tempPosition;
- if (*tempPosition != 9)
- break;
- }
-
- if (tempPosition == moveTable && *tempPosition == 9) {
- while (*tempPosition != 8 && *tempPosition == 9) {
- ++tempPosition;
- }
- if (*tempPosition == 8) {
- return 0;
- }
- }
-
- oldPosition = tempPosition;
- curPosition = oldPosition+1;
- while (*curPosition != 8 && *curPosition == 9) {
- ++curPosition;
- }
- continue;
- }
-
- if (unkTable[*curPosition+((*oldPosition)*8)] != -1) {
- --retValue;
- *oldPosition = unkTable[*curPosition+((*oldPosition)*8)];
- *curPosition = 9;
-
- if (tempPosition != oldPosition) {
- curPosition = oldPosition;
- oldPosition = tempPosition;
- while (true) {
- if (tempPosition == moveTable) {
- break;
- }
- --tempPosition;
- if (*tempPosition != 9) {
- break;
- }
- }
- } else {
- while (true) {
- ++curPosition;
- if (*curPosition != 9) {
- break;
- }
- }
- }
- continue;
- }
-
- tempPosition = oldPosition;
- oldPosition = curPosition;
- ++retValue;
- while (true) {
- ++curPosition;
- if (*curPosition != 9) {
- break;
- }
- }
- }
-
- return retValue;
-}
-
-#pragma mark -
-#pragma mark - Scene handling
-#pragma mark -
-
-int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
- debug(9, "KyraEngine::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset);
- if (queryGameFlag(0xEF)) {
- unk1 = 0;
- }
- int sceneId = _currentCharacter->sceneId;
- _pathfinderFlag = 0;
- if (xpos < 12) {
- if (_roomTable[sceneId].westExit != 0xFFFF) {
- xpos = 12;
- ypos = _sceneExits.westYPos;
- _pathfinderFlag = 7;
- }
- } else if(xpos >= 308) {
- if (_roomTable[sceneId].eastExit != 0xFFFF) {
- xpos = 307;
- ypos = _sceneExits.eastYPos;
- _pathfinderFlag = 13;
- }
- }
-
- if (ypos <= (_northExitHeight&0xFF)+2) {
- if (_roomTable[sceneId].northExit != 0xFFFF) {
- xpos = _sceneExits.northXPos;
- ypos = _northExitHeight & 0xFF;
- _pathfinderFlag = 14;
- }
- } else if (ypos >= 136) {
- if (_roomTable[sceneId].southExit != 0xFFFF) {
- xpos = _sceneExits.southXPos;
- ypos = 136;
- _pathfinderFlag = 11;
- }
- }
-
- int temp = xpos - _currentCharacter->x1;
- if (ABS(temp) < 4) {
- temp = ypos - _currentCharacter->y1;
- if (ABS(temp) < 2) {
- return 0;
- }
- }
-
- int x = (int16)(_currentCharacter->x1 & 0xFFFC);
- int y = (int16)(_currentCharacter->y1 & 0xFFFE);
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
- int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
- _pathfinderFlag = 0;
- if (ret >= _lastFindWayRet) {
- _lastFindWayRet = ret;
- }
- if (ret == 0x7D00 || ret == 0) {
- return 0;
- }
- return processSceneChange(_movFacingTable, unk1, frameReset);
-}
-
-int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) {
- debug(9, "KyraEngine::processSceneChange(0x%X, %d, %d)", table, unk1, frameReset);
- if (queryGameFlag(0xEF)) {
- unk1 = 0;
- }
- int *tableStart = table;
- _sceneChangeState = 0;
- _loopFlag2 = 0;
- bool running = true;
- int returnValue = 0;
- uint32 nextFrame = 0;
- _abortWalkFlag = false;
- _mousePressFlag = false;
-
- while (running) {
- if (_abortWalkFlag) {
- *table = 8;
- _currentCharacter->currentAnimFrame = 7;
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- processInput(_mouseX, _mouseY);
- return 0;
- }
- bool forceContinue = false;
- switch (*table) {
- case 0: case 1: case 2:
- case 3: case 4: case 5:
- case 6: case 7:
- _currentCharacter->facing = getOppositeFacingDirection(*table);
- break;
-
- case 8:
- forceContinue = true;
- running = false;
- break;
-
- default:
- ++table;
- forceContinue = true;
- break;
- }
-
- returnValue = changeScene(_currentCharacter->facing);
- if (returnValue) {
- running = false;
- _abortWalkFlag = false;
- }
-
- if (unk1) {
- if (_mousePressFlag) {
- running = false;
- _sceneChangeState = 1;
- }
- }
-
- if (forceContinue || !running) {
- continue;
- }
-
- int temp = 0;
- if (table == tableStart || table[1] == 8) {
- temp = setCharacterPosition(0, 0);
- } else {
- temp = setCharacterPosition(0, table);
- }
- if (temp) {
- ++table;
- }
-
- nextFrame = getTimerDelay(5) * _tickLength + _system->getMillis();
- while (_system->getMillis() < nextFrame) {
- _sprites->updateSceneAnims();
- updateMousePointer();
- updateGameTimers();
- _animator->updateAllObjectShapes();
- updateTextFade();
- if (_currentCharacter->sceneId == 210) {
- _animator->updateKyragemFading();
- if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
- *table = 8;
- running = false;
- break;
- }
- }
- if ((nextFrame - _system->getMillis()) >= 10)
- delay(10);
- }
- }
-
- if (frameReset && !(_brandonStatusBit & 2)) {
- _currentCharacter->currentAnimFrame = 7;
- }
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- return returnValue;
-}
-
-int KyraEngine::changeScene(int facing) {
- debug(9, "KyraEngine::changeScene(%d)", facing);
- if (queryGameFlag(0xEF)) {
- if (_currentCharacter->sceneId == 5) {
- return 0;
- }
- }
-
- int xpos = _charXPosTable[facing] + _currentCharacter->x1;
- int ypos = _charYPosTable[facing] + _currentCharacter->y1;
-
- if (xpos >= 12 && xpos <= 308) {
- if (!lineIsPassable(xpos, ypos))
- return false;
- }
-
- if (_exitListPtr) {
- int16 *ptr = _exitListPtr;
- // this loop should be only entered on time, seems to be some hack in the original
- while (true) {
- if (*ptr == -1)
- break;
-
- if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
- ptr += 10;
- break;
- }
- _brandonPosX = ptr[6];
- _brandonPosY = ptr[7];
- uint16 sceneId = ptr[5];
- facing = ptr[4];
- int unk1 = ptr[8];
- int unk2 = ptr[9];
- if (sceneId == 0xFFFF) {
- switch (facing) {
- case 0:
- sceneId = _roomTable[_currentCharacter->sceneId].northExit;
- break;
-
- case 2:
- sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
- break;
-
- case 4:
- sceneId = _roomTable[_currentCharacter->sceneId].southExit;
- break;
-
- case 6:
- sceneId = _roomTable[_currentCharacter->sceneId].westExit;
- break;
-
- default:
- break;
- }
- }
-
- _currentCharacter->facing = facing;
- animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- enterNewScene(sceneId, facing, unk1, unk2, 0);
- resetGameFlag(0xEE);
- return 1;
- }
- }
-
- int returnValue = 0;
- facing = 0;
-
- if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
- facing = 0;
- returnValue = 1;
- }
-
- if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
- facing = 2;
- returnValue = 1;
- }
-
- if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
- facing = 4;
- returnValue = 1;
- }
-
- if (xpos <= 12 || _currentCharacter->y1 <= 12) {
- facing = 6;
- returnValue = 1;
- }
-
- if (!returnValue)
- return 0;
-
- uint16 sceneId = 0xFFFF;
- switch (facing) {
- case 0:
- sceneId = _roomTable[_currentCharacter->sceneId].northExit;
- break;
-
- case 2:
- sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
- break;
-
- case 4:
- sceneId = _roomTable[_currentCharacter->sceneId].southExit;
- break;
-
- default:
- sceneId = _roomTable[_currentCharacter->sceneId].westExit;
- break;
- }
-
- if (sceneId == 0xFFFF)
- return 0;
-
- enterNewScene(sceneId, facing, 1, 1, 0);
- return returnValue;
-}
-
-#pragma mark -
#pragma mark - Input
#pragma mark -
diff --git a/kyra/kyra.h b/kyra/kyra.h
index f981ae8c75..51838068c3 100644
--- a/kyra/kyra.h
+++ b/kyra/kyra.h
@@ -245,6 +245,8 @@ public:
uint8 game() const { return _game; }
uint32 features() const { return _features; }
+
+ uint8 **shapes() { return _shapes; }
Common::RandomSource _rnd;
int16 _northExitHeight;
@@ -268,9 +270,7 @@ public:
void loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData);
void snd_playTheme(int file, int track = 0);
- void snd_playTrack(int track, bool looping = false);
void snd_playVoiceFile(int id);
- bool snd_voicePlaying();
void snd_voiceWaitForFinish(bool ingame = true);
void snd_playSoundEffect(int track);
void snd_playWanderScoreViaMap(int command, int restart);
@@ -489,8 +489,6 @@ protected:
void setCharacterPositionHelper(int character, int *facingTable);
int getOppositeFacingDirection(int dir);
void loadSceneMSC();
- void blockInRegion(int x, int y, int width, int height);
- void blockOutRegion(int x, int y, int width, int height);
void startSceneScript(int brandonAlive);
void setupSceneItems();
void initSceneData(int facing, int unk1, int brandonAlive);
@@ -515,13 +513,6 @@ protected:
void destroyMouseItem();
void setMouseItem(int item);
void wipeDownMouseItem(int xpos, int ypos);
- void rectClip(int &x, int &y, int w, int h);
- void backUpRect0(int xpos, int ypos);
- void restoreRect0(int xpos, int ypos);
- void backUpRect1(int xpos, int ypos);
- void restoreRect1(int xpos, int ypos);
- void copyBackgroundBlock(int x, int page, int flag);
- void copyBackgroundBlock2(int x);
void makeBrandonFaceMouse();
void setBrandonPoisonFlags(int reset);
void resetBrandonPoisonFlags();
@@ -539,8 +530,6 @@ protected:
int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2);
void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex);
void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y);
- int getDrawLayer(int x, int y);
- int getDrawLayer2(int x, int y, int height);
int checkNoDropRects(int x, int y);
int isDropable(int x, int y);
void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item);
@@ -590,8 +579,6 @@ protected:
void seq_playEnding();
void seq_playCredits();
- void snd_startTrack();
- void snd_haltTrack();
void snd_setSoundEffectFile(int file);
static OpcodeProc _opcodeTable[];
@@ -623,8 +610,6 @@ protected:
void initMainButtonList();
void loadMainScreen(int page = 3);
void setCharactersInDefaultScene();
- void resetBrandonPosionFlags();
- void initAnimStateList();
void setupPanPages();
void freePanPages();
void closeFinalWsa();
@@ -700,7 +685,6 @@ protected:
bool _abortWalkFlag2;
bool _mousePressFlag;
uint8 _flagsTable[53];
- uint8 *_unkPtr1, *_unkPtr2;
uint8 *_shapes[377];
uint16 _gameSpeed;
uint16 _tickLength;
diff --git a/kyra/module.mk b/kyra/module.mk
index bf9a5aba49..ac11dbf32f 100644
--- a/kyra/module.mk
+++ b/kyra/module.mk
@@ -14,6 +14,9 @@ MODULE_OBJS := \
kyra/debugger.o \
kyra/animator.o \
kyra/gui.o \
+ kyra/sequences.o \
+ kyra/items.o \
+ kyra/scene.o \
kyra/text.o \
kyra/timer.o \
kyra/saveload.o
diff --git a/kyra/resource.cpp b/kyra/resource.cpp
index 6e33a49422..50062726ea 100644
--- a/kyra/resource.cpp
+++ b/kyra/resource.cpp
@@ -24,6 +24,7 @@
#include "kyra/resource.h"
#include "kyra/script.h"
#include "kyra/wsamovie.h"
+#include "kyra/screen.h"
namespace Kyra {
Resource::Resource(KyraEngine* engine) {
@@ -279,5 +280,48 @@ uint32 PAKFile::getFileSize(const char* file) {
}
return 0;
}
+
+void KyraEngine::loadPalette(const char *filename, uint8 *palData) {
+ debug(9, "KyraEngine::loadPalette('%s' 0x%X)", filename, palData);
+ uint32 fileSize = 0;
+ uint8 *srcData = _res->fileData(filename, &fileSize);
+
+ if (palData && fileSize) {
+ debug(9, "Loading a palette of size %i from '%s'", fileSize, filename);
+ memcpy(palData, srcData, fileSize);
+ }
+ delete [] srcData;
+}
+
+void KyraEngine::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData) {
+ debug(9, "KyraEngine::copyBitmap('%s', %d, %d, 0x%X)", filename, tempPage, dstPage, palData);
+ uint32 fileSize;
+ uint8 *srcData = _res->fileData(filename, &fileSize);
+ uint8 compType = srcData[2];
+ uint32 imgSize = READ_LE_UINT32(srcData + 4);
+ uint16 palSize = READ_LE_UINT16(srcData + 8);
+ if (palData && palSize) {
+ debug(9, "Loading a palette of size %i from %s", palSize, filename);
+ memcpy(palData, srcData + 10, palSize);
+ }
+ uint8 *srcPtr = srcData + 10 + palSize;
+ uint8 *dstData = _screen->getPagePtr(dstPage);
+ switch (compType) {
+ case 0:
+ memcpy(dstData, srcPtr, imgSize);
+ break;
+ case 3:
+ Screen::decodeFrame3(srcPtr, dstData, imgSize);
+ break;
+ case 4:
+ Screen::decodeFrame4(srcPtr, dstData, imgSize);
+ break;
+ default:
+ error("Unhandled bitmap compression %d", compType);
+ break;
+ }
+ delete[] srcData;
+}
+
} // end of namespace Kyra
diff --git a/kyra/scene.cpp b/kyra/scene.cpp
new file mode 100644
index 0000000000..daf44f4135
--- /dev/null
+++ b/kyra/scene.cpp
@@ -0,0 +1,1579 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * 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.
+ *
+ * $Header$
+ *
+ */
+
+#include "kyra/kyra.h"
+#include "kyra/seqplayer.h"
+#include "kyra/screen.h"
+#include "kyra/resource.h"
+#include "kyra/sound.h"
+#include "kyra/sprites.h"
+#include "kyra/wsamovie.h"
+#include "kyra/animator.h"
+#include "kyra/text.h"
+#include "kyra/script.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+
+namespace Kyra {
+
+void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
+ debug(9, "KyraEngine::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive);
+ int unkVar1 = 1;
+ _screen->hideMouse();
+ _handleInput = false;
+ _abortWalkFlag = false;
+ _abortWalkFlag2 = false;
+ if (_currentCharacter->sceneId == 7 && sceneId == 24) {
+ _newMusicTheme = 3;
+ } else if (_currentCharacter->sceneId == 25 && sceneId == 109) {
+ _newMusicTheme = 4;
+ } else if (_currentCharacter->sceneId == 120 && sceneId == 37) {
+ _newMusicTheme = 5;
+ } else if (_currentCharacter->sceneId == 52 && sceneId == 199) {
+ _newMusicTheme = 6;
+ } else if (_currentCharacter->sceneId == 37 && sceneId == 120) {
+ _newMusicTheme = 4;
+ } else if (_currentCharacter->sceneId == 109 && sceneId == 25) {
+ _newMusicTheme = 3;
+ } else if (_currentCharacter->sceneId == 24 && sceneId == 7) {
+ _newMusicTheme = 2;
+ }
+ if (_newMusicTheme != _curMusicTheme) {
+ snd_playTheme(_newMusicTheme);
+ }
+
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ if (sceneId == 0) {
+ moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 3:
+ if (sceneId == 2) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 26:
+ if (sceneId == 27) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 44:
+ if (sceneId == 45) {
+ moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (unkVar1 && unk1) {
+ int xpos = _currentCharacter->x1;
+ int ypos = _currentCharacter->y1;
+ switch (facing) {
+ case 0:
+ ypos = _currentCharacter->y1 - 6;
+ break;
+
+ case 2:
+ xpos = 336;
+ break;
+
+ case 4:
+ ypos = 143;
+ break;
+
+ case 6:
+ xpos = -16;
+ break;
+
+ default:
+ break;
+ }
+
+ moveCharacterToPos(0, facing, xpos, ypos);
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) {
+ _movieObjects[i]->close();
+ }
+
+ if (!brandonAlive) {
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ _scriptInterpreter->startScript(_scriptClick, 5);
+ while (_scriptInterpreter->validScript(_scriptClick)) {
+ _scriptInterpreter->runScript(_scriptClick);
+ }
+ }
+
+ memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4);
+ _currentCharacter->sceneId = sceneId;
+
+ assert(sceneId < _roomTableSize);
+ assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
+
+ Room *currentRoom = &_roomTable[sceneId];
+
+ if (_currentRoom != 0xFFFF && (_features & GF_TALKIE)) {
+ char file[32];
+ assert(_currentRoom < _roomTableSize);
+ int tableId = _roomTable[_currentRoom].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+ }
+
+ _currentRoom = sceneId;
+
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".DAT");
+ _sprites->loadDAT(fileNameBuffer, _sceneExits);
+ _sprites->setupSceneAnims();
+ _scriptInterpreter->unloadScript(_scriptClickData);
+ loadSceneMSC();
+
+ if ((_features & GF_TALKIE)) {
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".VRM");
+ _res->loadPakFile(fileNameBuffer);
+ }
+
+ _walkBlockNorth = currentRoom->northExit;
+ _walkBlockEast = currentRoom->eastExit;
+ _walkBlockSouth = currentRoom->southExit;
+ _walkBlockWest = currentRoom->westExit;
+
+ if (_walkBlockNorth == 0xFFFF) {
+ _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3);
+ }
+ if (_walkBlockEast == 0xFFFF) {
+ _screen->blockOutRegion(312, 0, 8, 139);
+ }
+ if (_walkBlockSouth == 0xFFFF) {
+ _screen->blockOutRegion(0, 135, 320, 8);
+ }
+ if (_walkBlockWest == 0xFFFF) {
+ _screen->blockOutRegion(0, 0, 8, 139);
+ }
+
+ if (!brandonAlive) {
+ updatePlayerItemsForScene();
+ }
+
+ startSceneScript(brandonAlive);
+ setupSceneItems();
+
+ initSceneData(facing, unk2, brandonAlive);
+
+ _loopFlag2 = 0;
+ _screen->showMouse();
+ if (!brandonAlive) {
+ seq_poisonDeathNow(0);
+ }
+ updateMousePointer(true);
+ _changedScene = true;
+}
+
+void KyraEngine::transcendScenes(int roomIndex, int roomName) {
+ debug(9, "KyraEngine::transcendScenes(%d, %d)", roomIndex, roomName);
+ assert(roomIndex < _roomTableSize);
+ if (_features & GF_TALKIE) {
+ char file[32];
+ assert(roomIndex < _roomTableSize);
+ int tableId = _roomTable[roomIndex].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+ }
+ _roomTable[roomIndex].nameIndex = roomName;
+ _unkScreenVar2 = 1;
+ _unkScreenVar3 = 1;
+ _unkScreenVar1 = 0;
+ _brandonPosX = _currentCharacter->x1;
+ _brandonPosY = _currentCharacter->y1;
+ enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
+ _unkScreenVar1 = 1;
+ _unkScreenVar2 = 0;
+ _unkScreenVar3 = 0;
+}
+
+void KyraEngine::setSceneFile(int roomIndex, int roomName) {
+ debug(9, "KyraEngine::setSceneFile(%d, %d)", roomIndex, roomName);
+ assert(roomIndex < _roomTableSize);
+ _roomTable[roomIndex].nameIndex = roomName;
+}
+
+void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
+ debug(9, "KyraEngine::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos);
+ Character *ch = &_characterList[character];
+ ch->facing = facing;
+ _screen->hideMouse();
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ disableTimer(19);
+ disableTimer(14);
+ disableTimer(18);
+ uint32 nextFrame = 0;
+ switch (facing) {
+ case 0:
+ while (ypos < ch->y1) {
+ nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ while (_system->getMillis() < nextFrame) { updateGameTimers(); }
+ }
+ break;
+
+ case 2:
+ while (ch->x1 < xpos) {
+ nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ while (_system->getMillis() < nextFrame) { updateGameTimers(); }
+ }
+ break;
+
+ case 4:
+ while (ypos > ch->y1) {
+ nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ while (_system->getMillis() < nextFrame) { updateGameTimers(); }
+ }
+ break;
+
+ case 6:
+ while (ch->x1 > xpos) {
+ nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ while (_system->getMillis() < nextFrame) { updateGameTimers(); }
+ }
+ break;
+
+ default:
+ break;
+ }
+ enableTimer(19);
+ enableTimer(14);
+ enableTimer(18);
+ _screen->showMouse();
+}
+
+void KyraEngine::setCharacterPositionWithUpdate(int character) {
+ debug(9, "KyraEngine::setCharacterPositionWithUpdate(%d)", character);
+ setCharacterPosition(character, 0);
+ _sprites->updateSceneAnims();
+ updateGameTimers();
+ _animator->updateAllObjectShapes();
+ updateTextFade();
+
+ if (_currentCharacter->sceneId == 210) {
+ _animator->updateKyragemFading();
+ }
+}
+
+int KyraEngine::setCharacterPosition(int character, int *facingTable) {
+ debug(9, "KyraEngine::setCharacterPosition(%d, 0x%X)", character, facingTable);
+ if (character == 0) {
+ _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing];
+ _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing];
+ setCharacterPositionHelper(0, facingTable);
+ return 1;
+ } else {
+ _characterList[character].x1 += _charXPosTable[_characterList[character].facing];
+ _characterList[character].y1 += _charYPosTable[_characterList[character].facing];
+ if (_characterList[character].sceneId == _currentCharacter->sceneId) {
+ setCharacterPositionHelper(character, 0);
+ }
+ }
+ return 0;
+}
+
+void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) {
+ debug(9, "KyraEngine::setCharacterPositionHelper(%d, 0x%X)", character, facingTable);
+ Character *ch = &_characterList[character];
+ ++ch->currentAnimFrame;
+ int facing = ch->facing;
+ if (facingTable) {
+ if (*facingTable != *(facingTable - 1)) {
+ if (*(facingTable - 1) == *(facingTable + 1)) {
+ facing = getOppositeFacingDirection(*(facingTable - 1));
+ *facingTable = *(facingTable - 1);
+ }
+ }
+ }
+
+ static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ if (facing == 0) {
+ ++facingIsZero[character];
+ } else {
+ bool resetTables = false;
+ if (facing != 7) {
+ if (facing - 1 != 0) {
+ if (facing != 4) {
+ if (facing == 3 || facing == 5) {
+ if (facingIsFour[character] > 2) {
+ facing = 4;
+ }
+ resetTables = true;
+ }
+ } else {
+ ++facingIsFour[character];
+ }
+ } else {
+ if (facingIsZero[character] > 2) {
+ facing = 0;
+ }
+ resetTables = true;
+ }
+ } else {
+ if (facingIsZero[character] > 2) {
+ facing = 0;
+ }
+ resetTables = true;
+ }
+
+ if (resetTables) {
+ facingIsZero[character] = 0;
+ facingIsFour[character] = 0;
+ }
+ }
+
+ static const uint16 maxAnimationFrame[] = {
+ 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
+ 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
+ 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
+ 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
+ 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
+ 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
+ 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
+ };
+
+ if (facing == 0) {
+ if (maxAnimationFrame[36+character] > ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[36+character];
+ }
+ if (maxAnimationFrame[30+character] < ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[36+character];
+ }
+ } else if (facing == 4) {
+ if (maxAnimationFrame[18+character] > ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[18+character];
+ }
+ if (maxAnimationFrame[12+character] < ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[18+character];
+ }
+ } else {
+ if (maxAnimationFrame[18+character] < ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[30+character];
+ }
+ if (maxAnimationFrame[character] == ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[6+character];
+ }
+ if (maxAnimationFrame[character] < ch->currentAnimFrame) {
+ ch->currentAnimFrame = maxAnimationFrame[6+character]+2;
+ }
+ }
+
+ if (character == 0) {
+ if (_brandonStatusBit & 0x10)
+ ch->currentAnimFrame = 88;
+ }
+
+ animRefreshNPC(character);
+}
+
+int KyraEngine::getOppositeFacingDirection(int dir) {
+ debug(9, "KyraEngine::getOppositeFacingDirection(%d)", dir);
+ switch (dir) {
+ case 0:
+ return 2;
+ break;
+
+ case 1:
+ return 1;
+ break;
+
+ case 3:
+ return 7;
+ break;
+
+ case 4:
+ return 6;
+ break;
+
+ case 5:
+ return 5;
+ break;
+
+ case 6:
+ return 4;
+ break;
+
+ case 7:
+ return 3;
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+void KyraEngine::loadSceneMSC() {
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".MSC");
+ _screen->fillRect(0, 0, 319, 199, 0, 5);
+ loadBitmap(fileNameBuffer, 3, 5, 0);
+}
+
+void KyraEngine::startSceneScript(int brandonAlive) {
+ debug(9, "KyraEngine::startSceneScript(%d)", brandonAlive);
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".CPS");
+ loadBitmap(fileNameBuffer, 3, 3, 0);
+ _sprites->loadSceneShapes();
+ _exitListPtr = 0;
+
+ _screen->setScreenPalette(_screen->_currentPalette);
+
+ _scaleMode = 1;
+ for (int i = 0; i < 145; ++i) {
+ _scaleTable[i] = 256;
+ }
+
+ clearNoDropRects();
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".EMC");
+ _scriptInterpreter->unloadScript(_scriptClickData);
+ _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, _opcodeTable, _opcodeTableSize, 0);
+ _scriptInterpreter->startScript(_scriptClick, 0);
+ _scriptClick->variables[0] = _currentCharacter->sceneId;
+ _scriptClick->variables[7] = brandonAlive;
+
+ while (_scriptInterpreter->validScript(_scriptClick)) {
+ _scriptInterpreter->runScript(_scriptClick);
+ }
+}
+
+void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
+ debug(9, "KyraEngine::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive);
+
+ int16 xpos2 = 0;
+ int setFacing = 1;
+
+ int16 xpos = 0, ypos = 0;
+
+ if (_brandonPosX == -1 && _brandonPosY == -1) {
+ switch (facing+1) {
+ case 0:
+ xpos = ypos = -1;
+ break;
+
+ case 1: case 2: case 8:
+ xpos = _sceneExits.southXPos;
+ ypos = _sceneExits.southYPos;
+ break;
+
+ case 3:
+ xpos = _sceneExits.westXPos;
+ ypos = _sceneExits.westYPos;
+ break;
+
+ case 4: case 5: case 6:
+ xpos = _sceneExits.northXPos;
+ ypos = _sceneExits.northYPos;
+ break;
+
+ case 7:
+ xpos = _sceneExits.eastXPos;
+ ypos = _sceneExits.eastYPos;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) {
+ ypos = (_northExitHeight & 0xFF) + 4;
+ }
+ if (xpos >= 308) {
+ xpos = 304;
+ }
+ if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) {
+ ypos = (_northExitHeight >> 8) - 4;
+ }
+ if (xpos <= 12) {
+ xpos = 16;
+ }
+ }
+
+ if (_brandonPosX > -1) {
+ xpos = _brandonPosX;
+ }
+ if (_brandonPosY > -1) {
+ ypos = _brandonPosY;
+ }
+
+ int16 ypos2 = 0;
+ if (_brandonPosX > -1 && _brandonPosY > -1) {
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 4;
+ xpos2 = 192;
+ ypos2 = 104;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 3:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 204;
+ ypos2 = 94;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 26:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 192;
+ ypos2 = 128;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 44:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 6;
+ xpos2 = 156;
+ ypos2 = 96;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 37:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 148;
+ ypos2 = 114;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _brandonPosX = _brandonPosY = -1;
+
+ if (unk1 && setFacing) {
+ ypos2 = ypos;
+ xpos2 = xpos;
+ switch (facing) {
+ case 0:
+ ypos = 142;
+ break;
+
+ case 2:
+ xpos = -16;
+ break;
+
+ case 4:
+ ypos = (uint8)(_northExitHeight & 0xFF) - 4;
+ break;
+
+ case 6:
+ xpos = 336;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ xpos2 = (int16)(xpos2 & 0xFFFC);
+ ypos2 = (int16)(ypos2 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ _currentCharacter->facing = facing;
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+
+ initSceneObjectList(brandonAlive);
+
+ if (unk1 && brandonAlive == 0) {
+ moveCharacterToPos(0, facing, xpos2, ypos2);
+ }
+
+ _scriptClick->variables[4] = _itemInHand;
+ _scriptClick->variables[7] = brandonAlive;
+ _scriptInterpreter->startScript(_scriptClick, 3);
+ while (_scriptInterpreter->validScript(_scriptClick)) {
+ _scriptInterpreter->runScript(_scriptClick);
+ }
+}
+
+void KyraEngine::initSceneObjectList(int brandonAlive) {
+ debug(9, "KyraEngine::initSceneObjectList(%d)", brandonAlive);
+ for (int i = 0; i < 28; ++i) {
+ _animator->actors()[i].active = 0;
+ }
+
+ int startAnimFrame = 0;
+
+ AnimObject *curAnimState = _animator->actors();
+ curAnimState->active = 1;
+ curAnimState->drawY = _currentCharacter->y1;
+ curAnimState->sceneAnimPtr = _shapes[4+_currentCharacter->currentAnimFrame];
+ curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
+ startAnimFrame = _currentCharacter->currentAnimFrame-7;
+ int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+ if (_scaleMode) {
+ curAnimState->x1 = _currentCharacter->x1;
+ curAnimState->y1 = _currentCharacter->y1;
+
+ _brandonScaleX = _scaleTable[_currentCharacter->y1];
+ _brandonScaleY = _scaleTable[_currentCharacter->y1];
+
+ curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = _currentCharacter->x1 + xOffset;
+ curAnimState->y1 = _currentCharacter->y1 + yOffset;
+ }
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ _animator->clearQueue();
+ _animator->addObjectToQueue(curAnimState);
+
+ int listAdded = 0;
+ int addedObjects = 1;
+
+ for (int i = 1; i < 5; ++i) {
+ Character *ch = &_characterList[i];
+ curAnimState = &_animator->actors()[addedObjects];
+ if (ch->sceneId != _currentCharacter->sceneId) {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ ++addedObjects;
+ continue;
+ }
+
+ curAnimState->drawY = ch->y1;
+ curAnimState->sceneAnimPtr = _shapes[4+ch->currentAnimFrame];
+ curAnimState->animFrameNumber = ch->currentAnimFrame;
+ startAnimFrame = ch->currentAnimFrame-7;
+ xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+ if (_scaleMode) {
+ curAnimState->x1 = ch->x1;
+ curAnimState->y1 = ch->y1;
+
+ _brandonScaleX = _scaleTable[ch->y1];
+ _brandonScaleY = _scaleTable[ch->y1];
+
+ curAnimState->x1 += (_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = ch->x1 + xOffset;
+ curAnimState->y1 = ch->y1 + yOffset;
+ }
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ if (ch->facing >= 1 && ch->facing <= 3) {
+ curAnimState->flags |= 1;
+ } else if (ch->facing >= 5 && ch->facing <= 7) {
+ curAnimState->flags &= 0xFFFFFFFE;
+ }
+
+ _animator->addObjectToQueue(curAnimState);
+
+ ++addedObjects;
+ ++listAdded;
+ if (listAdded < 2)
+ i = 5;
+ }
+
+ for (int i = 0; i < 11; ++i) {
+ curAnimState = &_animator->sprites()[i];
+
+ if (_sprites->_anims[i].play) {
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ }
+ else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ curAnimState->height = _sprites->_anims[i].height;
+ curAnimState->height2 = _sprites->_anims[i].height2;
+ curAnimState->width = _sprites->_anims[i].width + 1;
+ curAnimState->width2 = _sprites->_anims[i].width2;
+ curAnimState->drawY = _sprites->_anims[i].drawY;
+ curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
+ curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
+ curAnimState->background = _sprites->_anims[i].background;
+ curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
+
+ if(_sprites->_anims[i].unk2)
+ curAnimState->flags = 0x800;
+ else
+ curAnimState->flags = 0;
+
+ if (_sprites->_anims[i].flipX)
+ curAnimState->flags |= 0x1;
+
+ _animator->addObjectToQueue(curAnimState);
+ }
+
+ for (int i = 0; i < 12; ++i) {
+ curAnimState = &_animator->items()[i];
+ Room *curRoom = &_roomTable[_currentCharacter->sceneId];
+ byte curItem = curRoom->itemsTable[i];
+ if (curItem != 0xFF) {
+ curAnimState->drawY = curRoom->itemsYPos[i];
+ curAnimState->sceneAnimPtr = _shapes[220+curItem];
+ curAnimState->animFrameNumber = (int16)0xFFFF;
+ curAnimState->y1 = curRoom->itemsYPos[i];
+ curAnimState->x1 = curRoom->itemsXPos[i];
+
+ curAnimState->x1 -= (fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
+ curAnimState->y1 -= fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
+
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ _animator->addObjectToQueue(curAnimState);
+ } else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ }
+
+ _animator->preserveAnyChangedBackgrounds();
+ curAnimState = _animator->actors();
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ for (int i = 1; i < 28; ++i) {
+ curAnimState = &_animator->objects()[i];
+ if (curAnimState->active) {
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ }
+ }
+ _animator->restoreAllObjectBackgrounds();
+ _animator->preserveAnyChangedBackgrounds();
+ _animator->prepDrawAllObjects();
+ initSceneScreen(brandonAlive);
+ _animator->copyChangedObjectsForward(0);
+}
+
+void KyraEngine::initSceneScreen(int brandonAlive) {
+ // XXX (Pointless?) Palette stuff
+ if (_unkScreenVar2 == 1) {
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
+ } else {
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+ }
+ _screen->updateScreen();
+ // XXX More (pointless?) palette stuff
+
+ if (!_scriptInterpreter->startScript(_scriptClick, 2))
+ error("Could not start script function 2 of scene script");
+
+ _scriptClick->variables[7] = brandonAlive;
+
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+
+ setTextFadeTimerCountdown(-1);
+ if (_currentCharacter->sceneId == 210) {
+ if (_itemInHand != -1)
+ magicOutMouseItem(2, -1);
+
+ _screen->hideMouse();
+ for (int i = 0; i < 10; ++i) {
+ if (_currentCharacter->inventoryItems[i] != 0xFF)
+ magicOutMouseItem(2, i);
+ }
+ _screen->showMouse();
+ }
+}
+
+int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
+ debug(9, "KyraEngine::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset);
+ if (queryGameFlag(0xEF)) {
+ unk1 = 0;
+ }
+ int sceneId = _currentCharacter->sceneId;
+ _pathfinderFlag = 0;
+ if (xpos < 12) {
+ if (_roomTable[sceneId].westExit != 0xFFFF) {
+ xpos = 12;
+ ypos = _sceneExits.westYPos;
+ _pathfinderFlag = 7;
+ }
+ } else if(xpos >= 308) {
+ if (_roomTable[sceneId].eastExit != 0xFFFF) {
+ xpos = 307;
+ ypos = _sceneExits.eastYPos;
+ _pathfinderFlag = 13;
+ }
+ }
+
+ if (ypos <= (_northExitHeight&0xFF)+2) {
+ if (_roomTable[sceneId].northExit != 0xFFFF) {
+ xpos = _sceneExits.northXPos;
+ ypos = _northExitHeight & 0xFF;
+ _pathfinderFlag = 14;
+ }
+ } else if (ypos >= 136) {
+ if (_roomTable[sceneId].southExit != 0xFFFF) {
+ xpos = _sceneExits.southXPos;
+ ypos = 136;
+ _pathfinderFlag = 11;
+ }
+ }
+
+ int temp = xpos - _currentCharacter->x1;
+ if (ABS(temp) < 4) {
+ temp = ypos - _currentCharacter->y1;
+ if (ABS(temp) < 2) {
+ return 0;
+ }
+ }
+
+ int x = (int16)(_currentCharacter->x1 & 0xFFFC);
+ int y = (int16)(_currentCharacter->y1 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
+ _pathfinderFlag = 0;
+ if (ret >= _lastFindWayRet) {
+ _lastFindWayRet = ret;
+ }
+ if (ret == 0x7D00 || ret == 0) {
+ return 0;
+ }
+ return processSceneChange(_movFacingTable, unk1, frameReset);
+}
+
+int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) {
+ debug(9, "KyraEngine::processSceneChange(0x%X, %d, %d)", table, unk1, frameReset);
+ if (queryGameFlag(0xEF)) {
+ unk1 = 0;
+ }
+ int *tableStart = table;
+ _sceneChangeState = 0;
+ _loopFlag2 = 0;
+ bool running = true;
+ int returnValue = 0;
+ uint32 nextFrame = 0;
+ _abortWalkFlag = false;
+ _mousePressFlag = false;
+
+ while (running) {
+ if (_abortWalkFlag) {
+ *table = 8;
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ processInput(_mouseX, _mouseY);
+ return 0;
+ }
+ bool forceContinue = false;
+ switch (*table) {
+ case 0: case 1: case 2:
+ case 3: case 4: case 5:
+ case 6: case 7:
+ _currentCharacter->facing = getOppositeFacingDirection(*table);
+ break;
+
+ case 8:
+ forceContinue = true;
+ running = false;
+ break;
+
+ default:
+ ++table;
+ forceContinue = true;
+ break;
+ }
+
+ returnValue = changeScene(_currentCharacter->facing);
+ if (returnValue) {
+ running = false;
+ _abortWalkFlag = false;
+ }
+
+ if (unk1) {
+ if (_mousePressFlag) {
+ running = false;
+ _sceneChangeState = 1;
+ }
+ }
+
+ if (forceContinue || !running) {
+ continue;
+ }
+
+ int temp = 0;
+ if (table == tableStart || table[1] == 8) {
+ temp = setCharacterPosition(0, 0);
+ } else {
+ temp = setCharacterPosition(0, table);
+ }
+ if (temp) {
+ ++table;
+ }
+
+ nextFrame = getTimerDelay(5) * _tickLength + _system->getMillis();
+ while (_system->getMillis() < nextFrame) {
+ _sprites->updateSceneAnims();
+ updateMousePointer();
+ updateGameTimers();
+ _animator->updateAllObjectShapes();
+ updateTextFade();
+ if (_currentCharacter->sceneId == 210) {
+ _animator->updateKyragemFading();
+ if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
+ *table = 8;
+ running = false;
+ break;
+ }
+ }
+ if ((nextFrame - _system->getMillis()) >= 10)
+ delay(10);
+ }
+ }
+
+ if (frameReset && !(_brandonStatusBit & 2)) {
+ _currentCharacter->currentAnimFrame = 7;
+ }
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ return returnValue;
+}
+
+int KyraEngine::changeScene(int facing) {
+ debug(9, "KyraEngine::changeScene(%d)", facing);
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5) {
+ return 0;
+ }
+ }
+
+ int xpos = _charXPosTable[facing] + _currentCharacter->x1;
+ int ypos = _charYPosTable[facing] + _currentCharacter->y1;
+
+ if (xpos >= 12 && xpos <= 308) {
+ if (!lineIsPassable(xpos, ypos))
+ return false;
+ }
+
+ if (_exitListPtr) {
+ int16 *ptr = _exitListPtr;
+ // this loop should be only entered on time, seems to be some hack in the original
+ while (true) {
+ if (*ptr == -1)
+ break;
+
+ if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
+ ptr += 10;
+ break;
+ }
+ _brandonPosX = ptr[6];
+ _brandonPosY = ptr[7];
+ uint16 sceneId = ptr[5];
+ facing = ptr[4];
+ int unk1 = ptr[8];
+ int unk2 = ptr[9];
+ if (sceneId == 0xFFFF) {
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ case 6:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _currentCharacter->facing = facing;
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ enterNewScene(sceneId, facing, unk1, unk2, 0);
+ resetGameFlag(0xEE);
+ return 1;
+ }
+ }
+
+ int returnValue = 0;
+ facing = 0;
+
+ if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
+ facing = 0;
+ returnValue = 1;
+ }
+
+ if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
+ facing = 2;
+ returnValue = 1;
+ }
+
+ if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
+ facing = 4;
+ returnValue = 1;
+ }
+
+ if (xpos <= 12 || _currentCharacter->y1 <= 12) {
+ facing = 6;
+ returnValue = 1;
+ }
+
+ if (!returnValue)
+ return 0;
+
+ uint16 sceneId = 0xFFFF;
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ default:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ break;
+ }
+
+ if (sceneId == 0xFFFF)
+ return 0;
+
+ enterNewScene(sceneId, facing, 1, 1, 0);
+ return returnValue;
+}
+
+void KyraEngine::setCharactersInDefaultScene() {
+ static const uint32 defaultSceneTable[][4] = {
+ { 0xFFFF, 0x0004, 0x0003, 0xFFFF },
+ { 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
+ { 0xFFFF, 0x001D, 0x0021, 0xFFFF },
+ { 0xFFFF, 0x0000, 0x0000, 0xFFFF }
+ };
+
+ for (int i = 1; i < 5; ++i) {
+ Character *cur = &_characterList[i];
+ //cur->field_20 = 0;
+ const uint32 *curTable = defaultSceneTable[i-1];
+ cur->sceneId = curTable[0];
+ if (cur->sceneId == _currentCharacter->sceneId) {
+ //++cur->field_20;
+ cur->sceneId = curTable[1/*cur->field_20*/];
+ }
+ //cur->field_23 = curTable[cur->field_20+1];
+ }
+}
+
+void KyraEngine::setCharactersPositions(int character) {
+ static uint16 initXPosTable[] = {
+ 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
+ 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
+ };
+ static uint8 initYPosTable[] = {
+ 0x00, 0xA2, 0x00, 0x42, 0x00,
+ 0x67, 0x67, 0x60, 0x5A, 0x71,
+ 0x76
+ };
+ assert(character < ARRAYSIZE(initXPosTable));
+ Character *edit = &_characterList[character];
+ edit->x1 = edit->x2 = initXPosTable[character];
+ edit->y1 = edit->y2 = initYPosTable[character];
+}
+
+#pragma mark -
+#pragma mark - Pathfinder
+#pragma mark -
+
+int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
+ debug(9, "KyraEngine::findWay(%d, %d, %d, %d, 0x%X, %d)", x, y, toX, toY, moveTable, moveTableSize);
+ x &= 0xFFFC; toX &= 0xFFFC;
+ y &= 0xFFFE; toY &= 0xFFFE;
+ x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
+
+ if (x == toY && y == toY) {
+ moveTable[0] = 8;
+ return 0;
+ }
+
+ int curX = x;
+ int curY = y;
+ int lastUsedEntry = 0;
+ int tempValue = 0;
+ int *pathTable1 = new int[0x7D0];
+ int *pathTable2 = new int[0x7D0];
+ assert(pathTable1 && pathTable2);
+
+ while (true) {
+ int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
+ changePosTowardsFacing(curX, curY, newFacing);
+
+ if (curX == toX && curY == toY) {
+ if (!lineIsPassable(curX, curY))
+ break;
+ moveTable[lastUsedEntry++] = newFacing;
+ break;
+ }
+
+ if (lineIsPassable(curX, curY)) {
+ if (lastUsedEntry == moveTableSize) {
+ delete [] pathTable1;
+ delete [] pathTable2;
+ return 0x7D00;
+ }
+ // debug drawing
+ //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
+ // _screen->setPagePixel(0, curX, curY, 11);
+ // _screen->updateScreen();
+ // waitTicks(5);
+ //}
+ moveTable[lastUsedEntry++] = newFacing;
+ x = curX;
+ y = curY;
+ continue;
+ }
+
+ int temp = 0;
+ while (true) {
+ newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
+ changePosTowardsFacing(curX, curY, newFacing);
+ // debug drawing
+ //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
+ // _screen->setPagePixel(0, curX, curY, 8);
+ // _screen->updateScreen();
+ // waitTicks(5);
+ //}
+
+ if (!lineIsPassable(curX, curY)) {
+ if (curX != toX || curY != toY)
+ continue;
+ }
+
+ if (curX == toX && curY == toY) {
+ if (!lineIsPassable(curX, curY)) {
+ tempValue = 0;
+ temp = 0;
+ break;
+ }
+ }
+
+ temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
+ tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
+ if (curX == toX && curY == toY) {
+ if (temp == 0x7D00 && tempValue == 0x7D00) {
+ delete [] pathTable1;
+ delete [] pathTable2;
+ return 0x7D00;
+ }
+ }
+
+ if (temp != 0x7D00 || tempValue != 0x7D00) {
+ break;
+ }
+ }
+
+ if (temp < tempValue) {
+ if (lastUsedEntry + temp > moveTableSize) {
+ delete [] pathTable1;
+ delete [] pathTable2;
+ return 0x7D00;
+ }
+ memcpy(&moveTable[lastUsedEntry], pathTable1, temp*sizeof(int));
+ lastUsedEntry += temp;
+ } else {
+ if (lastUsedEntry + tempValue > moveTableSize) {
+ delete [] pathTable1;
+ delete [] pathTable2;
+ return 0x7D00;
+ }
+ memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue*sizeof(int));
+ lastUsedEntry += tempValue;
+ }
+ x = curX;
+ y = curY;
+ if (curX == toX && curY == toY) {
+ break;
+ }
+ }
+ delete [] pathTable1;
+ delete [] pathTable2;
+ moveTable[lastUsedEntry] = 8;
+ return getMoveTableSize(moveTable);
+}
+
+int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
+ debug(9, "KyraEngine::findSubPath(%d, %d, %d, %d, 0x%X, %d, %d)", x, y, toX, toY, moveTable, start, end);
+ // only used for debug specific code
+ //static uint16 unkTable[] = { 8, 5 };
+ static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 };
+ static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 };
+ static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 };
+ static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 };
+ static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
+
+ // debug specific
+ //++unkTable[start];
+ //while (_screen->getPalette(0)[unkTable[start]] != 0x0F) {
+ // ++unkTable[start];
+ //}
+
+ int xpos1 = x, xpos2 = x;
+ int ypos1 = y, ypos2 = y;
+ int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
+ int position = 0;
+
+ while (position != end) {
+ int newFacing2 = newFacing;
+ while (true) {
+ changePosTowardsFacing(xpos1, ypos1, facingTable1[start*8 + newFacing2]);
+ if (!lineIsPassable(xpos1, ypos1)) {
+ if (facingTable1[start*8 + newFacing2] == newFacing) {
+ return 0x7D00;
+ }
+ newFacing2 = facingTable1[start*8 + newFacing2];
+ xpos1 = x;
+ ypos1 = y;
+ continue;
+ }
+ newFacing = facingTable1[start*8 + newFacing2];
+ break;
+ }
+ // debug drawing
+ //if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
+ // _screen->setPagePixel(0, xpos1, ypos1, unkTable[start]);
+ // _screen->updateScreen();
+ // waitTicks(5);
+ //}
+ if (newFacing & 1) {
+ int temp = xpos1 + addPosTableX[newFacing + start * 8];
+ if (toX == temp) {
+ temp = ypos1 + addPosTableY[newFacing + start * 8];
+ if (toY == temp) {
+ moveTable[position++] = facingTable2[newFacing + start * 8];
+ return position;
+ }
+ }
+ }
+ moveTable[position++] = newFacing;
+ x = xpos1;
+ y = ypos1;
+ if (x == toX && y == toY) {
+ return position;
+ }
+
+ if (xpos1 == xpos2 && ypos1 == ypos2) {
+ break;
+ }
+
+ newFacing = facingTable3[start*8 + newFacing];
+ }
+ return 0x7D00;
+}
+
+int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
+ debug(9, "KyraEngine::getFacingFromPointToPoint(%d, %d, %d, %d)", x, y, toX, toY);
+ static const int facingTable[] = {
+ 1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
+ };
+
+ int facingEntry = 0;
+ int ydiff = y - toY;
+ if (ydiff < 0) {
+ ++facingEntry;
+ ydiff = -ydiff;
+ }
+ facingEntry <<= 1;
+
+ int xdiff = toX - x;
+ if (xdiff < 0) {
+ ++facingEntry;
+ xdiff = -xdiff;
+ }
+
+ if (xdiff >= ydiff) {
+ int temp = ydiff;
+ ydiff = xdiff;
+ xdiff = temp;
+
+ facingEntry <<= 1;
+ } else {
+ facingEntry <<= 1;
+ facingEntry += 1;
+ }
+ int temp = (ydiff + 1) >> 1;
+
+ if (xdiff < temp) {
+ facingEntry <<= 1;
+ facingEntry += 1;
+ } else {
+ facingEntry <<= 1;
+ }
+ assert(facingEntry < ARRAYSIZE(facingTable));
+ return facingTable[facingEntry];
+}
+
+void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) {
+ debug(9, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing);
+ x += _addXPosTable[facing];
+ y += _addYPosTable[facing];
+}
+
+bool KyraEngine::lineIsPassable(int x, int y) {
+ debug(9, "KyraEngine::lineIsPassable(%d, %d)", x, y);
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5)
+ return true;
+ }
+
+ if (_pathfinderFlag & 2) {
+ if (x >= 312)
+ return false;
+ }
+
+ if (_pathfinderFlag & 4) {
+ if (y >= 136)
+ return false;
+ }
+
+ if (_pathfinderFlag & 8) {
+ if (x < 8)
+ return false;
+ }
+
+ if (_pathfinderFlag2) {
+ if (x <= 8 || x >= 312)
+ return true;
+ if (y < (_northExitHeight & 0xFF) || y > 135)
+ return true;
+ }
+
+ if (y > 137) {
+ return false;
+ }
+
+ int ypos = 8;
+ if (_scaleMode) {
+ ypos = (_scaleTable[y] >> 5) + 1;
+ if (8 < ypos)
+ ypos = 8;
+ }
+
+ x -= (ypos >> 1);
+ if (y < 0)
+ y = 0;
+
+ int xpos = x;
+ int xtemp = xpos + ypos - 1;
+ if (x < 0)
+ xpos = 0;
+
+ if (xtemp > 319)
+ xtemp = 319;
+
+ for (; xpos < xtemp; ++xpos) {
+ if (!_screen->getShapeFlag1(xpos, y))
+ return false;
+ }
+ return true;
+}
+
+int KyraEngine::getMoveTableSize(int *moveTable) {
+ debug(9, "KyraEngine::getMoveTableSize(0x%X)", moveTable);
+ int retValue = 0;
+ if (moveTable[0] == 8)
+ return 0;
+
+ static const int facingTable[] = {
+ 4, 5, 6, 7, 0, 1, 2, 3
+ };
+ static const int unkTable[] = {
+ -1, -1, 1, 2, -1, 6, 7, -1,
+ -1, -1, -1, -1, 2, -1, 0, -1,
+ 1, -1, -1, -1, 3, 4, -1, 0,
+ 2, -1, -1, -1, -1, -1, 4, -1,
+ -1, 2, 3, -1, -1, -1, 5, 6,
+ 6, -1, 4, -1, -1, -1, -1, -1,
+ 7, 0, -1, 4, 5, -1, -1, -1,
+ -1, -1, 0, -1, 6, -1, -1, -1
+ };
+
+ int *oldPosition = moveTable;
+ int *tempPosition = moveTable;
+ int *curPosition = moveTable + 1;
+ retValue = 1;
+
+ while (*curPosition != 8) {
+ if (*oldPosition == facingTable[*curPosition]) {
+ retValue -= 2;
+ *oldPosition = 9;
+ *curPosition = 9;
+
+ while (tempPosition != moveTable) {
+ --tempPosition;
+ if (*tempPosition != 9)
+ break;
+ }
+
+ if (tempPosition == moveTable && *tempPosition == 9) {
+ while (*tempPosition != 8 && *tempPosition == 9) {
+ ++tempPosition;
+ }
+ if (*tempPosition == 8) {
+ return 0;
+ }
+ }
+
+ oldPosition = tempPosition;
+ curPosition = oldPosition+1;
+ while (*curPosition != 8 && *curPosition == 9) {
+ ++curPosition;
+ }
+ continue;
+ }
+
+ if (unkTable[*curPosition+((*oldPosition)*8)] != -1) {
+ --retValue;
+ *oldPosition = unkTable[*curPosition+((*oldPosition)*8)];
+ *curPosition = 9;
+
+ if (tempPosition != oldPosition) {
+ curPosition = oldPosition;
+ oldPosition = tempPosition;
+ while (true) {
+ if (tempPosition == moveTable) {
+ break;
+ }
+ --tempPosition;
+ if (*tempPosition != 9) {
+ break;
+ }
+ }
+ } else {
+ while (true) {
+ ++curPosition;
+ if (*curPosition != 9) {
+ break;
+ }
+ }
+ }
+ continue;
+ }
+
+ tempPosition = oldPosition;
+ oldPosition = curPosition;
+ ++retValue;
+ while (true) {
+ ++curPosition;
+ if (*curPosition != 9) {
+ break;
+ }
+ }
+ }
+
+ return retValue;
+}
+
+} // end of namespace Kyra
diff --git a/kyra/screen.cpp b/kyra/screen.cpp
index 40a3936ae6..bd93646d36 100644
--- a/kyra/screen.cpp
+++ b/kyra/screen.cpp
@@ -71,6 +71,11 @@ Screen::Screen(KyraEngine *vm, OSystem *system)
memset(_bitBlitRects, 0, sizeof(Rect)*BITBLIT_RECTS);
_bitBlitNum = 0;
memset(_saveLoadPage, 0, sizeof(_saveLoadPage));
+
+ _unkPtr1 = (uint8*)malloc(getRectSize(1, 144));
+ memset(_unkPtr1, 0, getRectSize(1, 144));
+ _unkPtr2 = (uint8*)malloc(getRectSize(1, 144));
+ memset(_unkPtr2, 0, getRectSize(1, 144));
}
Screen::~Screen() {
@@ -94,6 +99,9 @@ Screen::~Screen() {
delete [] _saveLoadPage[i];
_saveLoadPage[i] = 0;
}
+
+ free(_unkPtr1);
+ free(_unkPtr2);
}
void Screen::updateScreen() {
@@ -1916,4 +1924,150 @@ void Screen::deletePageFromDisk(int page) {
_saveLoadPage[page/2] = 0;
}
+void Screen::blockInRegion(int x, int y, int width, int height) {
+ debug(9, "Screen::blockInRegion(%d, %d, %d, %d)", x, y, width, height);
+ assert(_shapePages[0]);
+ byte *toPtr = _shapePages[0] + (y * 320 + x);
+ for (int i = 0; i < height; ++i) {
+ byte *backUpTo = toPtr;
+ for (int i2 = 0; i2 < width; ++i2) {
+ *toPtr++ &= 0x7F;
+ }
+ toPtr = (backUpTo + 320);
+ }
+}
+
+void Screen::blockOutRegion(int x, int y, int width, int height) {
+ debug(9, "Screen::blockOutRegion(%d, %d, %d, %d)", x, y, width, height);
+ assert(_shapePages[0]);
+ byte *toPtr = _shapePages[0] + (y * 320 + x);
+ for (int i = 0; i < height; ++i) {
+ byte *backUpTo = toPtr;
+ for (int i2 = 0; i2 < width; ++i2) {
+ *toPtr++ |= 0x80;
+ }
+ toPtr = (backUpTo + 320);
+ }
+}
+
+void Screen::rectClip(int &x, int &y, int w, int h) {
+ if (x < 0) {
+ x = 0;
+ } else if (x + w >= 320) {
+ x = 320 - w;
+ }
+ if (y < 0) {
+ y = 0;
+ } else if (y + h >= 200) {
+ y = 200 - h;
+ }
+}
+
+void Screen::backUpRect0(int xpos, int ypos) {
+ debug(9, "Screen::backUpRect0(%d, %d)", xpos, ypos);
+ rectClip(xpos, ypos, 3<<3, 24);
+ copyRegionToBuffer(_curPage, xpos, ypos, 3<<3, 24, _vm->shapes()[0]);
+}
+
+void Screen::restoreRect0(int xpos, int ypos) {
+ debug(9, "Screen::restoreRect0(%d, %d)", xpos, ypos);
+ rectClip(xpos, ypos, 3<<3, 24);
+ copyBlockToPage(_curPage, xpos, ypos, 3<<3, 24, _vm->shapes()[0]);
+}
+
+void Screen::backUpRect1(int xpos, int ypos) {
+ debug(9, "Screen::backUpRect1(%d, %d)", xpos, ypos);
+ rectClip(xpos, ypos, 4<<3, 32);
+ copyRegionToBuffer(_curPage, xpos, ypos, 4<<3, 32, _vm->shapes()[1]);
+}
+
+void Screen::restoreRect1(int xpos, int ypos) {
+ debug(9, "Screen::restoreRect1(%d, %d)", xpos, ypos);
+ rectClip(xpos, ypos, 4<<3, 32);
+ copyBlockToPage(_curPage, xpos, ypos, 4<<3, 32, _vm->shapes()[1]);
+}
+
+int Screen::getDrawLayer(int x, int y) {
+ debug(9, "Screen::getDrawLayer(%d, %d)", x, y);
+ int xpos = x - 8;
+ int ypos = y - 1;
+ int layer = 1;
+ for (int curX = xpos; curX < xpos + 16; ++curX) {
+ int tempLayer = getShapeFlag2(curX, ypos);
+ if (layer < tempLayer) {
+ layer = tempLayer;
+ }
+ if (layer >= 7) {
+ return 7;
+ }
+ }
+ return layer;
+}
+
+int Screen::getDrawLayer2(int x, int y, int height) {
+ debug(9, "Screen::getDrawLayer2(%d, %d, %d)", x, y, height);
+ int xpos = x - 8;
+ int ypos = y - 1;
+ int layer = 1;
+
+ for (int useX = xpos; useX < xpos + 16; ++useX) {
+ for (int useY = ypos - height; useY < ypos; ++useY) {
+ int tempLayer = getShapeFlag2(useX, useY);
+ if (tempLayer > layer) {
+ layer = tempLayer;
+ }
+
+ if (tempLayer >= 7) {
+ return 7;
+ }
+ }
+ }
+ return layer;
+}
+
+void Screen::copyBackgroundBlock(int x, int page, int flag) {
+ debug(9, "Screen::copyBackgroundBlock(%d, %d, %d)", x, page, flag);
+
+ if (x < 1)
+ return;
+
+ int height = 128;
+ if (flag)
+ height += 8;
+ if (!(x & 1))
+ ++x;
+ if (x == 19)
+ x = 17;
+ uint8 *ptr1 = _unkPtr1;
+ uint8 *ptr2 = _unkPtr2;
+ int oldVideoPage = _curPage;
+ _curPage = page;
+
+ int curX = x;
+ hideMouse();
+ copyRegionToBuffer(_curPage, 8, 8, 8, height, ptr2);
+ for (int i = 0; i < 19; ++i) {
+ int tempX = curX + 1;
+ copyRegionToBuffer(_curPage, tempX<<3, 8, 8, height, ptr1);
+ copyBlockToPage(_curPage, tempX<<3, 8, 8, height, ptr2);
+ int newXPos = curX + x;
+ if (newXPos > 37) {
+ newXPos = newXPos % 38;
+ }
+ tempX = newXPos + 1;
+ copyRegionToBuffer(_curPage, tempX<<3, 8, 8, height, ptr2);
+ copyBlockToPage(_curPage, tempX<<3, 8, 8, height, ptr1);
+ curX += x*2;
+ if (curX > 37) {
+ curX = curX % 38;
+ }
+ }
+ showMouse();
+ _curPage = oldVideoPage;
+}
+
+void Screen::copyBackgroundBlock2(int x) {
+ copyBackgroundBlock(x, 4, 1);
+}
+
} // End of namespace Kyra
diff --git a/kyra/screen.h b/kyra/screen.h
index ac3e8e0b51..dc0095351a 100644
--- a/kyra/screen.h
+++ b/kyra/screen.h
@@ -149,6 +149,19 @@ public:
void loadPageFromDisk(const char *file, int page);
void deletePageFromDisk(int page);
+ void blockInRegion(int x, int y, int width, int height);
+ void blockOutRegion(int x, int y, int width, int height);
+
+ void backUpRect0(int xpos, int ypos);
+ void restoreRect0(int xpos, int ypos);
+ void backUpRect1(int xpos, int ypos);
+ void restoreRect1(int xpos, int ypos);
+ void copyBackgroundBlock(int x, int page, int flag);
+ void copyBackgroundBlock2(int x);
+ void rectClip(int &x, int &y, int w, int h);
+ int getDrawLayer(int x, int y);
+ int getDrawLayer2(int x, int y, int height);
+
int _charWidth;
int _charOffset;
int _curPage;
@@ -181,6 +194,7 @@ private:
Rect *_bitBlitRects;
int _bitBlitNum;
+ uint8 *_unkPtr1, *_unkPtr2;
OSystem *_system;
KyraEngine *_vm;
diff --git a/kyra/script_v1.cpp b/kyra/script_v1.cpp
index b3e1c4eeb8..53310f1237 100644
--- a/kyra/script_v1.cpp
+++ b/kyra/script_v1.cpp
@@ -112,13 +112,13 @@ int KyraEngine::cmd_setSpecialExitList(ScriptState *script) {
int KyraEngine::cmd_blockInWalkableRegion(ScriptState *script) {
debug(3, "cmd_blockInWalkableRegion(0x%X) (%d, %d, %d, %d)", script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
- blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
+ _screen->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
return 0;
}
int KyraEngine::cmd_blockOutWalkableRegion(ScriptState *script) {
debug(3, "cmd_blockOutWalkableRegion(0x%X) (%d, %d, %d, %d)", script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
- blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
+ _screen->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
return 0;
}
@@ -1113,8 +1113,8 @@ int KyraEngine::cmd_getCharactersFacing(ScriptState *script) {
int KyraEngine::cmd_bkgdScrollSceneAndMasksRight(ScriptState *script) {
debug(3, "cmd_bkgdScrollSceneAndMasksRight(0x%X) (%d)", script, stackPos(0));
- copyBackgroundBlock(stackPos(0), 2, 0);
- copyBackgroundBlock2(stackPos(0));
+ _screen->copyBackgroundBlock(stackPos(0), 2, 0);
+ _screen->copyBackgroundBlock2(stackPos(0));
// update the whole screen
_screen->copyRegion(7, 7, 7, 7, 305, 129, 3, 0);
_screen->updateScreen();
diff --git a/kyra/seqplayer.cpp b/kyra/seqplayer.cpp
index ae36ad65df..5f1223bd8a 100644
--- a/kyra/seqplayer.cpp
+++ b/kyra/seqplayer.cpp
@@ -408,7 +408,7 @@ void SeqPlayer::s1_playTrack() {
} else if (msg == 1) {
_sound->beginFadeOut();
} else {
- _vm->snd_playTrack(msg);
+ _sound->playTrack(msg);
}
// }
}
@@ -635,4 +635,5 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) {
return seqSkippedFlag;
}
+
} // End of namespace Kyra
diff --git a/kyra/sequences.cpp b/kyra/sequences.cpp
new file mode 100644
index 0000000000..1ac3574a47
--- /dev/null
+++ b/kyra/sequences.cpp
@@ -0,0 +1,968 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2005-2006 The ScummVM project
+ *
+ * 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.
+ *
+ * $Header$
+ *
+ */
+
+#include "kyra/kyra.h"
+#include "kyra/seqplayer.h"
+#include "kyra/screen.h"
+#include "kyra/resource.h"
+#include "kyra/sound.h"
+#include "kyra/sprites.h"
+#include "kyra/wsamovie.h"
+#include "kyra/animator.h"
+#include "kyra/text.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+
+namespace Kyra {
+
+void KyraEngine::seq_demo() {
+ debug(9, "KyraEngine::seq_demo()");
+
+ snd_playTheme(MUSIC_INTRO, 2);
+
+ loadBitmap("START.CPS", 7, 7, _screen->_currentPalette);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
+ _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
+ _screen->fadeFromBlack();
+ waitTicks(60);
+ _screen->fadeToBlack();
+
+ _screen->clearPage(0);
+ loadBitmap("TOP.CPS", 7, 7, NULL);
+ loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
+ _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
+ _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
+ _screen->fadeFromBlack();
+
+ _seq->playSequence(_seq_WestwoodLogo, true);
+ waitTicks(60);
+
+ _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);
+ loadBitmap("FINAL.CPS", 7, 7, _screen->_currentPalette);
+ _screen->_curPage = 0;
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, 0);
+ _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
+ _screen->fadeFromBlack();
+ waitTicks(60);
+ _screen->fadeToBlack();
+ _sound->stopMusic();
+}
+
+void KyraEngine::seq_intro() {
+ debug(9, "KyraEngine::seq_intro()");
+ if (_features & GF_TALKIE) {
+ _res->loadPakFile("INTRO.VRM");
+ }
+
+ static const IntroProc introProcTable[] = {
+ &KyraEngine::seq_introLogos,
+ &KyraEngine::seq_introStory,
+ &KyraEngine::seq_introMalcolmTree,
+ &KyraEngine::seq_introKallakWriting,
+ &KyraEngine::seq_introKallakMalcolm
+ };
+
+ Common::InSaveFile *in;
+ if ((in = _saveFileMan->openForLoading(getSavegameFilename(0)))) {
+ delete in;
+ _skipIntroFlag = true;
+ } else
+ _skipIntroFlag = false;
+
+ _seq->setCopyViewOffs(true);
+ _screen->setFont(Screen::FID_8_FNT);
+ snd_playTheme(MUSIC_INTRO, 2);
+ snd_setSoundEffectFile(MUSIC_INTRO);
+ _text->setTalkCoords(144);
+ for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) {
+ (this->*introProcTable[i])();
+ }
+ _text->setTalkCoords(136);
+ waitTicks(30);
+ _seq->setCopyViewOffs(false);
+ _sound->stopMusic();
+ if (_features & GF_TALKIE) {
+ _res->unloadPakFile("INTRO.VRM");
+ }
+ res_unloadResources(RES_INTRO | RES_OUTRO);
+}
+
+void KyraEngine::seq_introLogos() {
+ debug(9, "KyraEngine::seq_introLogos()");
+ _screen->clearPage(0);
+ loadBitmap("TOP.CPS", 7, 7, NULL);
+ loadBitmap("BOTTOM.CPS", 5, 5, _screen->_currentPalette);
+ _screen->_curPage = 0;
+ _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 0);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 0);
+ _system->copyRectToScreen(_screen->getPagePtr(0), 320, 0, 0, 320, 200);
+ _screen->fadeFromBlack();
+
+ if (_seq->playSequence(_seq_WestwoodLogo, _skipIntroFlag)) {
+ _screen->fadeToBlack();
+ _screen->clearPage(0);
+ return;
+ }
+ waitTicks(60);
+ if (_seq->playSequence(_seq_KyrandiaLogo, _skipIntroFlag)) {
+ _screen->fadeToBlack();
+ _screen->clearPage(0);
+ return;
+ }
+ _screen->fillRect(0, 179, 319, 199, 0);
+
+ int y1 = 8;
+ int h1 = 175;
+ int y2 = 176;
+ int h2 = 0;
+ _screen->copyRegion(0, 91, 0, 8, 320, 103, 6, 2);
+ _screen->copyRegion(0, 0, 0, 111, 320, 64, 6, 2);
+ do {
+ if (h1 > 0) {
+ _screen->copyRegion(0, y1, 0, 8, 320, h1, 2, 0);
+ }
+ ++y1;
+ --h1;
+ if (h2 > 0) {
+ _screen->copyRegion(0, 64, 0, y2, 320, h2, 4, 0);
+ }
+ --y2;
+ ++h2;
+ _screen->updateScreen();
+ waitTicks(1);
+ } while (y2 >= 64);
+
+ _seq->playSequence(_seq_Forest, true);
+}
+
+void KyraEngine::seq_introStory() {
+ debug(9, "KyraEngine::seq_introStory()");
+ _screen->clearPage(3);
+ _screen->clearPage(0);
+ if ((_features & GF_ENGLISH) && (_features & GF_TALKIE)) {
+ loadBitmap("TEXT_ENG.CPS", 3, 3, 0);
+ } else if (_features & GF_GERMAN) {
+ loadBitmap("TEXT_GER.CPS", 3, 3, 0);
+ } else if (_features & GF_FRENCH) {
+ loadBitmap("TEXT_FRE.CPS", 3, 3, 0);
+ } else if (_features & GF_SPANISH) {
+ loadBitmap("TEXT_SPA.CPS", 3, 3, 0);
+ } else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY)) {
+ loadBitmap("TEXT.CPS", 3, 3, 0);
+ } else {
+ warning("no story graphics file found");
+ }
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 3, 0);
+ _screen->updateScreen();
+ waitTicks(360);
+}
+
+void KyraEngine::seq_introMalcolmTree() {
+ debug(9, "KyraEngine::seq_introMalcolmTree()");
+ _screen->_curPage = 0;
+ _screen->clearPage(3);
+ _seq->playSequence(_seq_MalcolmTree, true);
+}
+
+void KyraEngine::seq_introKallakWriting() {
+ debug(9, "KyraEngine::seq_introKallakWriting()");
+ _seq->makeHandShapes();
+ _screen->setAnimBlockPtr(5060);
+ _screen->_charWidth = -2;
+ _screen->clearPage(3);
+ _seq->playSequence(_seq_KallakWriting, true);
+}
+
+void KyraEngine::seq_introKallakMalcolm() {
+ debug(9, "KyraEngine::seq_introKallakMalcolm()");
+ _screen->clearPage(3);
+ _seq->playSequence(_seq_KallakMalcolm, true);
+}
+
+void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
+ debug(9, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, 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[4+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[4+opcodes[i]], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ delayWithTicks(3);
+ }
+ }
+ }
+ _screen->drawShape(page, _shapes[327+jewel], _amuletX2[jewel], _amuletY2[jewel], 0, 0);
+ _screen->updateScreen();
+ _screen->showMouse();
+ setGameFlag(0x55+jewel);
+}
+
+void KyraEngine::seq_brandonHealing() {
+ debug(9, "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);
+ setBrandonAnimSeqSize(3, 48);
+ snd_playSoundEffect(0x53);
+ for (int i = 123; i <= 144; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ for (int i = 125; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_brandonHealing2() {
+ debug(9, "seq_brandonHealing2()");
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_healingShape2Table);
+ setupShapes123(_healingShape2Table, 30, 0);
+ resetBrandonPoisonFlags();
+ setBrandonAnimSeqSize(3, 48);
+ snd_playSoundEffect(0x50);
+ for (int i = 123; i <= 152; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+ assert(_poisonGone);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(2010);
+ }
+ characterSays(_poisonGone[0], 0, -2);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(2011);
+ }
+ characterSays(_poisonGone[1], 0, -2);
+}
+
+void KyraEngine::seq_poisonDeathNow(int now) {
+ debug(9, "seq_poisonDeathNow(%d)", now);
+ if (!(_brandonStatusBit & 1))
+ return;
+ ++_poisonDeathCounter;
+ if (now)
+ _poisonDeathCounter = 2;
+ if (_poisonDeathCounter >= 2) {
+ snd_playWanderScoreViaMap(1, 1);
+ assert(_thePoison);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(7000);
+ }
+ characterSays(_thePoison[0], 0, -2);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(7001);
+ }
+ characterSays(_thePoison[1], 0, -2);
+ seq_poisonDeathNowAnim();
+ _deathHandler = 3;
+ } else {
+ assert(_thePoison);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(7002);
+ }
+ characterSays(_thePoison[2], 0, -2);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(7004);
+ }
+ characterSays(_thePoison[3], 0, -2);
+ }
+}
+
+void KyraEngine::seq_poisonDeathNowAnim() {
+ debug(9, "seq_poisonDeathNowAnim()");
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_posionDeathShapeTable);
+ setupShapes123(_posionDeathShapeTable, 20, 0);
+ setBrandonAnimSeqSize(8, 48);
+
+ _currentCharacter->currentAnimFrame = 124;
+ animRefreshNPC(0);
+ delayWithTicks(30);
+
+ _currentCharacter->currentAnimFrame = 123;
+ animRefreshNPC(0);
+ delayWithTicks(30);
+
+ for (int i = 125; i <= 139; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(60);
+
+ for (int i = 140; i <= 142; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(60);
+
+ resetBrandonAnimSeqSize();
+ freeShapes123();
+ _animator->restoreAllObjectBackgrounds();
+ _currentCharacter->x1 = _currentCharacter->x2 = -1;
+ _currentCharacter->y1 = _currentCharacter->y2 = -1;
+ _animator->preserveAllBackgrounds();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_playFluteAnimation() {
+ debug(9, "seq_playFluteAnimation()");
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ setupShapes123(_fluteAnimShapeTable, 36, 0);
+ setBrandonAnimSeqSize(3, 75);
+ for (int i = 123; i <= 130; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ 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;
+ animRefreshNPC(0);
+ delayWithTicks(delayTime);
+ }
+
+ for (int i = 126; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(delayTime);
+ }
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+
+ if (soundType == 1) {
+ assert(_fluteString);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(1000);
+ }
+ characterSays(_fluteString[0], 0, -2);
+ } else if (soundType == 2) {
+ assert(_fluteString);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(1001);
+ }
+ characterSays(_fluteString[1], 0, -2);
+ }
+}
+
+void KyraEngine::seq_winterScroll1() {
+ debug(9, "seq_winterScroll1()");
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_winterScrollTable);
+ assert(_winterScroll1Table);
+ assert(_winterScroll2Table);
+ setupShapes123(_winterScrollTable, 7, 0);
+ setBrandonAnimSeqSize(5, 66);
+
+ for (int i = 123; i <= 129; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ freeShapes123();
+ snd_playSoundEffect(0x20);
+ setupShapes123(_winterScroll1Table, 35, 0);
+
+ for (int i = 123; i <= 146; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ 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;
+ setGameFlag(0xA2);
+ }
+
+ for (int i = 147; i <= 157; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ 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;
+ }
+ uint8 tmpPal[768];
+ memcpy(tmpPal, _screen->_currentPalette, 768);
+ memcpy(&tmpPal[684], palTable2()[0], 60);
+ _screen->fadePalette(tmpPal, 72);
+ memcpy(&_screen->_currentPalette[684], palTable2()[0], 60);
+ _screen->setScreenPalette(_screen->_currentPalette);
+ setGameFlag(0xB3);
+ } else {
+ delayWithTicks(120);
+ }
+
+ freeShapes123();
+ setupShapes123(_winterScroll2Table, 4, 0);
+
+ for (int i = 123; i <= 126; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_winterScroll2() {
+ debug(9, "seq_winterScroll2()");
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ assert(_winterScrollTable);
+ setupShapes123(_winterScrollTable, 7, 0);
+ setBrandonAnimSeqSize(5, 66);
+
+ for (int i = 123; i <= 128; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(120);
+
+ for (int i = 127; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_makeBrandonInv() {
+ debug(9, "seq_makeBrandonInv()");
+ if (_deathHandler == 8)
+ return;
+
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ _brandonStatusBit |= 0x20;
+ setTimerCountdown(18, 2700);
+ _brandonStatusBit |= 0x40;
+ snd_playSoundEffect(0x77);
+ _brandonInvFlag = 0;
+ while (_brandonInvFlag <= 0x100) {
+ animRefreshNPC(0);
+ delayWithTicks(10);
+ _brandonInvFlag += 0x10;
+ }
+ _brandonStatusBit &= 0xFFBF;
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_makeBrandonNormal() {
+ debug(9, "seq_makeBrandonNormal()");
+ _screen->hideMouse();
+ _brandonStatusBit |= 0x40;
+ snd_playSoundEffect(0x77);
+ _brandonInvFlag = 0x100;
+ while (_brandonInvFlag >= 0) {
+ animRefreshNPC(0);
+ delayWithTicks(10);
+ _brandonInvFlag -= 0x10;
+ }
+ _brandonInvFlag = 0;
+ _brandonStatusBit &= 0xFF9F;
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_makeBrandonNormal2() {
+ debug(9, "seq_makeBrandonNormal2()");
+ _screen->hideMouse();
+ assert(_brandonToWispTable);
+ setupShapes123(_brandonToWispTable, 26, 0);
+ setBrandonAnimSeqSize(5, 48);
+ _brandonStatusBit &= 0xFFFD;
+ snd_playSoundEffect(0x6C);
+ for (int i = 138; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ setBrandonAnimSeqSize(4, 48);
+ _currentCharacter->currentAnimFrame = 7;
+ 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::seq_makeBrandonWisp() {
+ debug(9, "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);
+ setBrandonAnimSeqSize(5, 48);
+ snd_playSoundEffect(0x6C);
+ for (int i = 123; i <= 138; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ _brandonStatusBit |= 2;
+ if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) {
+ setTimerCountdown(14, 18000);
+ } else {
+ setTimerCountdown(14, 7200);
+ }
+ _brandonDrawFrame = 113;
+ _brandonStatusBit0x02Flag = 1;
+ _currentCharacter->currentAnimFrame = 113;
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ 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::seq_dispelMagicAnimation() {
+ debug(9, "seq_dispelMagicAnimation()");
+ if (_deathHandler == 8)
+ return;
+ if (_currentCharacter->sceneId == 210) {
+ if (_beadStateVar == 4 || _beadStateVar == 6)
+ return;
+ }
+ _screen->hideMouse();
+ 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);
+ setBrandonAnimSeqSize(8, 49);
+ snd_playSoundEffect(0x15);
+ for (int i = 123; i <= 127; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+
+ delayWithTicks(120);
+
+ for (int i = 127; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(10);
+ }
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
+ debug(9, "seq_fillFlaskWithWater(%d, %d)", item, 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);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(8006);
+ }
+ characterSays(_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;
+
+ _screen->hideMouse();
+ setMouseItem(newItem);
+ _screen->showMouse();
+ _itemInHand = newItem;
+ assert(_fullFlask);
+ assert(type < _fullFlask_Size && type >= 0);
+ if (_features & GF_TALKIE) {
+ snd_voiceWaitForFinish();
+ static const uint16 voiceEntries[] = {
+ 0x1F40, 0x1F41, 0x1F42, 0x1F45
+ };
+ assert(type < ARRAYSIZE(voiceEntries));
+ snd_playVoiceFile(voiceEntries[type]);
+ }
+ characterSays(_fullFlask[type], 0, -2);
+}
+
+void KyraEngine::seq_playDrinkPotionAnim(int unk1, int unk2, int flags) {
+ debug(9, "KyraEngine::seq_playDrinkPotionAnim(%d, %d, %d)", unk1, unk2, flags);
+ // XXX
+ _screen->hideMouse();
+ checkAmuletAnimFlags();
+ _currentCharacter->facing = 5;
+ animRefreshNPC(0);
+ assert(_drinkAnimationTable);
+ setupShapes123(_drinkAnimationTable, 9, flags);
+ setBrandonAnimSeqSize(5, 54);
+
+ for (int i = 123; i <= 131; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(5);
+ }
+ snd_playSoundEffect(0x34);
+ for (int i = 0; i < 2; ++i) {
+ _currentCharacter->currentAnimFrame = 130;
+ animRefreshNPC(0);
+ delayWithTicks(7);
+ _currentCharacter->currentAnimFrame = 131;
+ animRefreshNPC(0);
+ delayWithTicks(7);
+ }
+
+ if (unk2) {
+ // XXX
+ }
+
+ for (int i = 131; i >= 123; --i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(5);
+ }
+
+ resetBrandonAnimSeqSize();
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ freeShapes123();
+ _screen->showMouse();
+}
+
+int KyraEngine::seq_playEnd() {
+ debug(9, "KyraEngine::seq_playEnd()");
+ if (_endSequenceSkipFlag) {
+ return 0;
+ }
+ if (_deathHandler == 8) {
+ return 0;
+ }
+ _screen->_curPage = 2;
+ if (_endSequenceNeedLoading) {
+ snd_playWanderScoreViaMap(50, 1);
+ setupPanPages();
+ _finalA = new WSAMovieV1(this);
+ assert(_finalA);
+ _finalA->open("finala.wsa", 1, 0);
+ _finalB = new WSAMovieV1(this);
+ assert(_finalB);
+ _finalB->open("finalb.wsa", 1, 0);
+ _finalC = new WSAMovieV1(this);
+ assert(_finalC);
+ _endSequenceNeedLoading = 0;
+ _finalC->open("finalc.wsa", 1, 0);
+ _screen->_curPage = 0;
+ _beadStateVar = 0;
+ _malcolmFlag = 0;
+ // wired stuff with _unkEndSeqVar2 which needs timer handling
+ _screen->copyRegion(312, 0, 312, 0, 8, 136, 0, 2);
+ }
+ if (handleMalcolmFlag()) {
+ _beadStateVar = 0;
+ _malcolmFlag = 12;
+ handleMalcolmFlag();
+ handleBeadState();
+ closeFinalWsa();
+ if (_deathHandler == 8) {
+ _screen->_curPage = 0;
+ checkAmuletAnimFlags();
+ seq_brandonToStone();
+ waitTicks(60);
+ return 1;
+ } else {
+ _endSequenceSkipFlag = 1;
+ if (_text->printed()) {
+ _text->restoreTalkTextMessageBkgd(2, 0);
+ }
+ _screen->_curPage = 0;
+ _screen->hideMouse();
+ _screen->fadeSpecialPalette(32, 228, 20, 60);
+ waitTicks(60);
+ loadBitmap("GEMHEAL.CPS", 3, 3, _screen->_currentPalette);
+ _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, 1, 0);
+ uint32 nextTime = _system->getMillis() + 120 * _tickLength;
+ _finalA = new WSAMovieV1(this);
+ assert(_finalA);
+ _finalA->open("finald.wsa", 1, 0);
+ _finalA->_x = _finalA->_y = 8;
+ _finalA->_drawPage = 0;
+ while (_system->getMillis() < nextTime) {}
+ snd_playSoundEffect(0x40);
+ for (int i = 0; i < 22; ++i) {
+ while (_system->getMillis() < nextTime) {}
+ if (i == 4) {
+ snd_playSoundEffect(0x3E);
+ } else if (i == 20) {
+ snd_playSoundEffect(0x0E);
+ }
+ nextTime = _system->getMillis() + 8 * _tickLength;
+ _finalA->displayFrame(i);
+ _screen->updateScreen();
+ }
+ delete _finalA;
+ _finalA = 0;
+ seq_playEnding();
+ return 1;
+ }
+ } else {
+ handleBeadState();
+ _screen->bitBlitRects();
+ _screen->updateScreen();
+ _screen->_curPage = 0;
+ }
+ return 0;
+}
+
+void KyraEngine::seq_brandonToStone() {
+ debug(9, "KyraEngine::seq_brandonToStone()");
+ _screen->hideMouse();
+ assert(_brandonStoneTable);
+ setupShapes123(_brandonStoneTable, 14, 0);
+ setBrandonAnimSeqSize(5, 51);
+ for (int i = 123; i <= 136; ++i) {
+ _currentCharacter->currentAnimFrame = i;
+ animRefreshNPC(0);
+ delayWithTicks(8);
+ }
+ resetBrandonAnimSeqSize();
+ freeShapes123();
+ _screen->showMouse();
+}
+
+void KyraEngine::seq_playEnding() {
+ debug(9, "KyraEngine::seq_playEnding()");
+ _screen->hideMouse();
+ res_unloadResources(RES_INGAME);
+ res_loadResources(RES_OUTRO);
+ loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette);
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+ _screen->_curPage = 0;
+ // XXX
+ assert(_homeString);
+ drawSentenceCommand(_homeString[0], 179);
+ _screen->_curPage = 0;
+ _screen->fadeToBlack();
+ _seq->playSequence(_seq_Reunion, false);
+ _screen->fadeToBlack();
+ _screen->showMouse();
+ seq_playCredits();
+}
+
+void KyraEngine::seq_playCredits() {
+ debug(9, "KyraEngine::seq_playCredits()");
+ static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ _screen->hideMouse();
+ uint32 sz = 0;
+ if (_features & GF_FLOPPY) {
+ _screen->loadFont(Screen::FID_CRED6_FNT, _res->fileData("CREDIT6.FNT", &sz));
+ _screen->loadFont(Screen::FID_CRED8_FNT, _res->fileData("CREDIT8.FNT", &sz));
+ }
+ loadBitmap("CHALET.CPS", 2, 2, _screen->_currentPalette);
+ _screen->setScreenPalette(_screen->_currentPalette);
+ _screen->setCurPage(0);
+ _screen->clearCurPage();
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+ _screen->setTextColorMap(colorMap);
+ _screen->_charWidth = -1;
+ snd_playWanderScoreViaMap(53, 1);
+ // delete
+ _screen->updateScreen();
+ // XXX
+ waitTicks(120); // wait until user presses escape normally
+ _screen->fadeToBlack();
+ _screen->clearCurPage();
+ _screen->showMouse();
+}
+
+bool KyraEngine::seq_skipSequence() const {
+ debug(9, "KyraEngine::seq_skipSequence()");
+ return _quitFlag || _abortIntroFlag;
+}
+
+} // end of namespace Kyra
diff --git a/kyra/sound.cpp b/kyra/sound.cpp
index 31c947f12f..535a29a3b8 100644
--- a/kyra/sound.cpp
+++ b/kyra/sound.cpp
@@ -345,4 +345,89 @@ void SoundPC::voicePlay(const char *file) {
bool SoundPC::voiceIsPlaying() {
return _mixer->isSoundHandleActive(_vocHandle);
}
+
+void KyraEngine::snd_playTheme(int file, int track) {
+ debug(9, "KyraEngine::snd_playTheme(%d)", file);
+ assert(file < _xmidiFilesCount);
+ _curMusicTheme = _newMusicTheme = file;
+ _sound->playMusic(_xmidiFiles[file]);
+ _sound->playTrack(track, false);
+}
+
+void KyraEngine::snd_setSoundEffectFile(int file) {
+ debug(9, "KyraEngine::snd_setSoundEffectFile(%d)", file);
+ assert(file < _xmidiFilesCount);
+ _sound->loadSoundEffectFile(_xmidiFiles[file]);
+}
+
+void KyraEngine::snd_playSoundEffect(int track) {
+ debug(9, "KyraEngine::snd_playSoundEffect(%d)", track);
+ if (track == 49) {
+ snd_playWanderScoreViaMap(56, 1);
+ } else {
+ _sound->playSoundEffect(track);
+ }
+}
+
+void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) {
+ debug(9, "KyraEngine::snd_playWanderScoreViaMap(%d, %d)", command, restart);
+ static const int8 soundTable[] = {
+ -1, 0, -1, 1, 0, 3, 0, 2,
+ 0, 4, 1, 2, 1, 3, 1, 4,
+ 1, 0x5C, 1, 6, 1, 7, 2, 2,
+ 2, 3, 2, 4, 2, 5, 2, 6,
+ 2, 7, 3, 3, 3, 4, 1, 8,
+ 1, 9, 4, 2, 4, 3, 4, 4,
+ 4, 5, 4, 6, 4, 7, 4, 8,
+ 1, 0x0B, 1, 0x0C, 1, 0x0E, 1, 0x0D,
+ 4, 9, 5, 0x0C, 6, 2, 6, 6,
+ 6, 7, 6, 8, 6, 9, 6, 3,
+ 6, 4, 6, 5, 7, 2, 7, 3,
+ 7, 4, 7, 5, 7, 6, 7, 7,
+ 7, 8, 7, 9, 8, 2, 8, 3,
+ 8, 4, 8, 5, 6, 0x0B, 5, 0x0B
+ };
+ //if (!_disableSound) {
+ // XXX
+ //}
+ assert(command*2+1 < ARRAYSIZE(soundTable));
+ if (_curMusicTheme != soundTable[command*2]+1) {
+ if (soundTable[command*2] != -1) {
+ snd_playTheme(soundTable[command*2]+1);
+ }
+ }
+
+ if (restart)
+ _lastMusicCommand = -1;
+
+ if (command != 1) {
+ if (_lastMusicCommand != command) {
+ _lastMusicCommand = command;
+ _sound->playTrack(soundTable[command*2+1], true);
+ }
+ } else {
+ _lastMusicCommand = 1;
+ _sound->beginFadeOut();
+ }
+}
+
+void KyraEngine::snd_playVoiceFile(int id) {
+ debug(9, "KyraEngine::snd_playVoiceFile(%d)", id);
+ char vocFile[9];
+ assert(id >= 0 && id < 9999);
+ sprintf(vocFile, "%03d.VOC", id);
+ _sound->voicePlay(vocFile);
+}
+
+void KyraEngine::snd_voiceWaitForFinish(bool ingame) {
+ debug(9, "KyraEngine::snd_voiceWaitForFinish(%d)", ingame);
+ while (_sound->voiceIsPlaying() && !_fastMode) {
+ if (ingame) {
+ delay(10, true);
+ } else {
+ _system->delayMillis(10);
+ }
+ }
+}
+
} // end of namespace Kyra
diff --git a/kyra/staticres.cpp b/kyra/staticres.cpp
index ebf9edb4c3..2720af4c03 100644
--- a/kyra/staticres.cpp
+++ b/kyra/staticres.cpp
@@ -453,6 +453,146 @@ void KyraEngine::res_freeLangTable(char ***string, int *size) {
*string = 0;
}
+void KyraEngine::loadMouseShapes() {
+ loadBitmap("MOUSE.CPS", 3, 3, 0);
+ _screen->_curPage = 2;
+ _shapes[4] = _screen->encodeShape(0, 0, 8, 10, 0);
+ _shapes[5] = _screen->encodeShape(0, 0x17, 0x20, 7, 0);
+ _shapes[6] = _screen->encodeShape(0x50, 0x12, 0x10, 9, 0);
+ _shapes[7] = _screen->encodeShape(0x60, 0x12, 0x10, 11, 0);
+ _shapes[8] = _screen->encodeShape(0x70, 0x12, 0x10, 9, 0);
+ _shapes[9] = _screen->encodeShape(0x80, 0x12, 0x10, 11, 0);
+ _shapes[10] = _screen->encodeShape(0x90, 0x12, 0x10, 10, 0);
+ _shapes[364] = _screen->encodeShape(0x28, 0, 0x10, 13, 0);
+ _screen->setMouseCursor(1, 1, 0);
+ _screen->setMouseCursor(1, 1, _shapes[4]);
+ _screen->setShapePages(5, 3);
+}
+
+void KyraEngine::loadCharacterShapes() {
+ int curImage = 0xFF;
+ int videoPage = _screen->_curPage;
+ _screen->_curPage = 2;
+ for (int i = 0; i < 115; ++i) {
+ assert(i < _defaultShapeTableSize);
+ Shape *shape = &_defaultShapeTable[i];
+ if (shape->imageIndex == 0xFF) {
+ _shapes[i+7+4] = 0;
+ continue;
+ }
+ if (shape->imageIndex != curImage) {
+ assert(shape->imageIndex < _characterImageTableSize);
+ loadBitmap(_characterImageTable[shape->imageIndex], 3, 3, 0);
+ curImage = shape->imageIndex;
+ }
+ _shapes[i+7+4] = _screen->encodeShape(shape->x<<3, shape->y, shape->w<<3, shape->h, 1);
+ }
+ _screen->_curPage = videoPage;
+}
+
+void KyraEngine::loadSpecialEffectShapes() {
+ loadBitmap("EFFECTS.CPS", 3, 3, 0);
+ _screen->_curPage = 2;
+
+ int currShape;
+ for (currShape = 173; currShape < 183; currShape++)
+ _shapes[4 + currShape] = _screen->encodeShape((currShape-173) * 24, 0, 24, 24, 1);
+
+ for (currShape = 183; currShape < 190; currShape++)
+ _shapes[4 + currShape] = _screen->encodeShape((currShape-183) * 24, 24, 24, 24, 1);
+
+ for (currShape = 190; currShape < 201; currShape++)
+ _shapes[4 + currShape] = _screen->encodeShape((currShape-190) * 24, 48, 24, 24, 1);
+
+ for (currShape = 201; currShape < 206; currShape++)
+ _shapes[4 + currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1);
+}
+
+void KyraEngine::loadItems() {
+ int shape;
+
+ loadBitmap("JEWELS3.CPS", 3, 3, 0);
+ _screen->_curPage = 2;
+
+ _shapes[327] = 0;
+
+ for (shape = 1; shape < 6; shape++ )
+ _shapes[327 + shape] = _screen->encodeShape((shape - 1) * 32, 0, 32, 17, 0);
+
+ for (shape = 330; shape <= 334; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-330) * 32, 102, 32, 17, 0);
+
+ for (shape = 335; shape <= 339; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-335) * 32, 17, 32, 17, 0);
+
+ for (shape = 340; shape <= 344; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-340) * 32, 34, 32, 17, 0);
+
+ for (shape = 345; shape <= 349; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-345) * 32, 51, 32, 17, 0);
+
+ for (shape = 350; shape <= 354; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-350) * 32, 68, 32, 17, 0);
+
+ for (shape = 355; shape <= 359; shape++)
+ _shapes[4 + shape] = _screen->encodeShape((shape-355) * 32, 85, 32, 17, 0);
+
+
+ loadBitmap("ITEMS.CPS", 3, 3, 0);
+ _screen->_curPage = 2;
+
+ for (int i = 0; i < 107; i++) {
+ shape = findDuplicateItemShape(i);
+
+ if (shape != -1)
+ _shapes[220 + i] = _shapes[220 + shape];
+ else
+ _shapes[220 + i] = _screen->encodeShape( (i % 20) * 16, i/20 * 16, 16, 16, 0);
+ }
+
+ uint32 size;
+ uint8 *fileData = _res->fileData("_ITEM_HT.DAT", &size);
+ assert(fileData);
+
+ for (int i = 0; i < 107; i++) {
+ _itemTable[i].height = fileData[i];
+ _itemTable[i].unk1 = _itemTable[i].unk2 = 0;
+ }
+
+ delete[] fileData;
+}
+
+void KyraEngine::loadButtonShapes() {
+ loadBitmap("BUTTONS2.CPS", 3, 3, 0);
+ _screen->_curPage = 2;
+ _scrollUpButton.process0PtrShape = _screen->encodeShape(0, 0, 24, 14, 1);
+ _scrollUpButton.process1PtrShape = _screen->encodeShape(24, 0, 24, 14, 1);
+ _scrollUpButton.process2PtrShape = _screen->encodeShape(48, 0, 24, 14, 1);
+ _scrollDownButton.process0PtrShape = _screen->encodeShape(0, 15, 24, 14, 1);
+ _scrollDownButton.process1PtrShape = _screen->encodeShape(24, 15, 24, 14, 1);
+ _scrollDownButton.process2PtrShape = _screen->encodeShape(48, 15, 24, 14, 1);
+ _screen->_curPage = 0;
+}
+
+void KyraEngine::loadMainScreen(int page) {
+ if ((_features & GF_ENGLISH) && (_features & GF_TALKIE))
+ loadBitmap("MAIN_ENG.CPS", page, page, 0);
+ else if(_features & GF_FRENCH)
+ loadBitmap("MAIN_FRE.CPS", page, page, 0);
+ else if(_features & GF_GERMAN)
+ loadBitmap("MAIN_GER.CPS", page, page, 0);
+ else if ((_features & GF_ENGLISH) && (_features & GF_FLOPPY))
+ loadBitmap("MAIN15.CPS", page, page, 0);
+ else if (_features & GF_SPANISH)
+ loadBitmap("MAIN_SPA.CPS", page, page, 0);
+ else
+ warning("no main graphics file found");
+
+ uint8 *_pageSrc = _screen->getPagePtr(page);
+ uint8 *_pageDst = _screen->getPagePtr(0);
+ memcpy(_pageDst, _pageSrc, 320*200);
+}
+
const ScreenDim Screen::_screenDimTable[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 },
{ 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 },
diff --git a/kyra/text.cpp b/kyra/text.cpp
index db4f737d61..b39a589f12 100644
--- a/kyra/text.cpp
+++ b/kyra/text.cpp
@@ -21,10 +21,342 @@
#include "common/stdafx.h"
+#include "kyra/kyra.h"
#include "kyra/screen.h"
#include "kyra/text.h"
+#include "kyra/animator.h"
+#include "kyra/sprites.h"
+
+#include "common/system.h"
namespace Kyra {
+
+void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 charNum) {
+ debug(9, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum);
+ bool hasUpdatedNPCs = false;
+ bool runLoop = true;
+ uint8 currPage;
+ OSystem::Event event;
+ int16 delayTime;
+
+ //while( towns_isEscKeyPressed() )
+ //towns_getKey();
+
+ uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
+
+ if (chatDuration != -1 ) {
+ switch (_configTalkspeed) {
+ case 0: chatDuration *= 2;
+ break;
+ case 2: chatDuration /= 4;
+ break;
+ case 3: chatDuration = -1;
+ }
+ }
+
+ if (chatDuration != -1)
+ chatDuration *= _tickLength;
+
+ disableTimer(14);
+ disableTimer(18);
+ disableTimer(19);
+
+ uint32 timeAtStart = _system->getMillis();
+ uint32 loopStart;
+ while (runLoop) {
+ loopStart = _system->getMillis();
+ if (_currentCharacter->sceneId == 210)
+ if (seq_playEnd())
+ break;
+
+ if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) {
+ hasUpdatedNPCs = true;
+ disableTimer(15);
+ _currHeadShape = 4;
+ animRefreshNPC(0);
+ animRefreshNPC(_talkingCharNum);
+
+ if (_charSayUnk2 != -1) {
+ _animator->sprites()[_charSayUnk2].active = 0;
+ _sprites->_anims[_charSayUnk2].play = false;
+ _charSayUnk2 = -1;
+ }
+ }
+
+ updateGameTimers();
+ _sprites->updateSceneAnims();
+ _animator->restoreAllObjectBackgrounds();
+ _animator->preserveAnyChangedBackgrounds();
+ _animator->prepDrawAllObjects();
+
+ currPage = _screen->_curPage;
+ _screen->_curPage = 2;
+ _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1);
+ _screen->_curPage = currPage;
+
+ _animator->copyChangedObjectsForward(0);
+ updateTextFade();
+
+ if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1)
+ break;
+
+ while (_system->pollEvent(event)) {
+ switch (event.type) {
+ case OSystem::EVENT_KEYDOWN:
+ if (event.kbd.keycode == '.')
+ runLoop = false;
+ break;
+ case OSystem::EVENT_QUIT:
+ quitGame();
+ case OSystem::EVENT_LBUTTONDOWN:
+ runLoop = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (_fastMode)
+ runLoop = false;
+
+ delayTime = (loopStart + _gameSpeed) - _system->getMillis();
+ if (delayTime > 0)
+ _system->delayMillis(delayTime);
+ }
+
+ enableTimer(14);
+ enableTimer(15);
+ enableTimer(18);
+ enableTimer(19);
+ //clearKyrandiaButtonIO();
+}
+
+void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) {
+ _charSayUnk3 = -1;
+
+ if (charNum > 4 && charNum < 11) {
+ //TODO: weird _game_inventory stuff here
+ warning("STUB: endCharacterChat() for high charnums");
+ }
+
+ if (convoInitialized != 0) {
+ _talkingCharNum = -1;
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ }
+}
+
+void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) {
+ _talkingCharNum = -1;
+
+ if (charNum > 0 && charNum < 5) {
+ _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame;
+ animRefreshNPC(charNum);
+ }
+
+ _currentCharacter->currentAnimFrame = 7;
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+}
+
+void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) {
+ _talkingCharNum = 0;
+
+ if (charNum < 5 && charNum > 0)
+ _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame;
+
+ if (_scaleMode != 0)
+ _currentCharacter->currentAnimFrame = 7;
+ else
+ _currentCharacter->currentAnimFrame = _currentCharAnimFrame;
+
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+}
+
+int8 KyraEngine::getChatPartnerNum() {
+ uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A};
+ int pos = 0;
+ int partner = -1;
+
+ for (int i = 1; i < 6; i++) {
+ if (_currentCharacter->sceneId == sceneTable[pos]) {
+ partner = sceneTable[pos+1];
+ break;
+ }
+ pos += 2;
+ }
+
+ for (int i = 1; i < 5; i++) {
+ if (_characterList[i].sceneId == _currentCharacter->sceneId) {
+ partner = i;
+ break;
+ }
+ }
+ return partner;
+}
+
+int KyraEngine::initCharacterChat(int8 charNum) {
+ if (_talkingCharNum == -1) {
+ _talkingCharNum = 0;
+
+ if (_scaleMode != 0)
+ _currentCharacter->currentAnimFrame = 7;
+ else
+ _currentCharacter->currentAnimFrame = 16;
+
+ animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ }
+
+ _charSayUnk2 = -1;
+ _animator->flagAllObjectsForBkgdChange();
+ _animator->restoreAllObjectBackgrounds();
+
+ if (charNum > 4 && charNum < 11) {
+ // TODO: Fill in weird _game_inventory stuff here
+ warning("STUB: initCharacterChat() for high charnums");
+ }
+
+ _animator->flagAllObjectsForRefresh();
+ _animator->flagAllObjectsForBkgdChange();
+ _animator->preserveAnyChangedBackgrounds();
+ _charSayUnk3 = charNum;
+
+ return 1;
+}
+
+void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) {
+ debug(9, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration);
+ uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 };
+
+ uint16 chatTicks;
+ int16 convoInitialized;
+ int8 chatPartnerNum;
+
+ if (_currentCharacter->sceneId == 210)
+ return;
+
+ convoInitialized = initCharacterChat(charNum);
+ chatPartnerNum = getChatPartnerNum();
+
+ if (chatPartnerNum != -1 && chatPartnerNum < 5)
+ backupChatPartnerAnimFrame(chatPartnerNum);
+
+ if (charNum < 5) {
+ _characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
+ _charSayUnk3 = charNum;
+ _talkingCharNum = charNum;
+ animRefreshNPC(charNum);
+ }
+
+ char *processedString = _text->preprocessString(chatStr);
+ int lineNum = _text->buildMessageSubstrings(processedString);
+
+ int16 yPos = _characterList[charNum].y1;
+ yPos -= _scaleTable[charNum] * _characterList[charNum].height;
+ yPos -= 8;
+ yPos -= lineNum * 10;
+
+ if (yPos < 11)
+ yPos = 11;
+
+ if (yPos > 100)
+ yPos = 100;
+
+ _text->_talkMessageY = yPos;
+ _text->_talkMessageH = lineNum * 10;
+ _animator->restoreAllObjectBackgrounds();
+
+ _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2);
+ _screen->hideMouse();
+
+ _text->printCharacterText(processedString, charNum, _characterList[charNum].x1);
+ _screen->showMouse();
+
+ if (chatDuration == -2)
+ chatTicks = strlen(processedString) * 9;
+ else
+ chatTicks = chatDuration;
+
+ waitForChatToFinish(chatTicks, chatStr, charNum);
+
+ _animator->restoreAllObjectBackgrounds();
+
+ _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2);
+ _animator->preserveAllBackgrounds();
+ _animator->prepDrawAllObjects();
+ _screen->hideMouse();
+
+ _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0);
+ _screen->showMouse();
+ _animator->flagAllObjectsForRefresh();
+ _animator->copyChangedObjectsForward(0);
+
+ if (chatPartnerNum != -1 && chatPartnerNum < 5)
+ restoreChatPartnerAnimFrame(chatPartnerNum);
+
+ endCharacterChat(charNum, convoInitialized);
+}
+
+void KyraEngine::drawSentenceCommand(char *sentence, int color) {
+ debug(9, "KyraEngine::drawSentenceCommand('%s', %i)", sentence, color);
+ _screen->hideMouse();
+ _screen->fillRect(8, 143, 311, 152, 12);
+
+ if (_startSentencePalIndex != color || _fadeText != false) {
+ _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
+ _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
+ _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
+
+ _screen->setScreenPalette(_screen->_currentPalette);
+ _startSentencePalIndex = 0;
+ }
+
+ _text->printText(sentence, 8, 143, 0xFF, 12, 0);
+ _screen->showMouse();
+ setTextFadeTimerCountdown(15);
+ _fadeText = false;
+}
+
+void KyraEngine::updateSentenceCommand(char *str1, char *str2, int color) {
+ debug(9, "KyraEngine::updateSentenceCommand('%s', '%s', %i)", str1, str2, color);
+ char sentenceCommand[500];
+ strncpy(sentenceCommand, str1, 500);
+ if (str2)
+ strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand));
+
+ drawSentenceCommand(sentenceCommand, color);
+ _screen->updateScreen();
+}
+
+void KyraEngine::updateTextFade() {
+ debug(9, "KyraEngine::updateTextFade()");
+ if (!_fadeText)
+ return;
+
+ bool finished = false;
+ for (int i = 0; i < 3; i++)
+ if (_currSentenceColor[i] > 4)
+ _currSentenceColor[i] -= 4;
+ else
+ if (_currSentenceColor[i]) {
+ _currSentenceColor[i] = 0;
+ finished = true;
+ }
+
+ _screen->_currentPalette[765] = _currSentenceColor[0];
+ _screen->_currentPalette[766] = _currSentenceColor[1];
+ _screen->_currentPalette[767] = _currSentenceColor[2];
+ _screen->setScreenPalette(_screen->_currentPalette);
+
+ if (finished) {
+ _fadeText = false;
+ _startSentencePalIndex = -1;
+ }
+}
+
TextDisplayer::TextDisplayer(Screen *screen) {
_screen = screen;