aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;