diff options
-rw-r--r-- | kyra/animator.cpp | 525 | ||||
-rw-r--r-- | kyra/animator.h | 105 | ||||
-rw-r--r-- | kyra/debugger.cpp | 2 | ||||
-rw-r--r-- | kyra/debugger.h | 2 | ||||
-rw-r--r-- | kyra/gui.cpp | 293 | ||||
-rw-r--r-- | kyra/kyra.cpp | 1424 | ||||
-rw-r--r-- | kyra/kyra.h | 81 | ||||
-rw-r--r-- | kyra/module.mk | 6 | ||||
-rw-r--r-- | kyra/script.cpp | 267 | ||||
-rw-r--r-- | kyra/script_v1.cpp | 384 | ||||
-rwxr-xr-x | kyra/seqplayer.cpp | 7 | ||||
-rw-r--r-- | kyra/sprites.cpp | 26 | ||||
-rw-r--r-- | kyra/sprites.h | 1 | ||||
-rw-r--r-- | kyra/text.cpp | 240 | ||||
-rw-r--r-- | kyra/text.h | 67 | ||||
-rw-r--r-- | kyra/timer.cpp | 277 |
16 files changed, 1988 insertions, 1719 deletions
diff --git a/kyra/animator.cpp b/kyra/animator.cpp new file mode 100644 index 0000000000..769037f45f --- /dev/null +++ b/kyra/animator.cpp @@ -0,0 +1,525 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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/screen.h" +#include "kyra/animator.h" +#include "kyra/sprites.h" + +namespace Kyra { +ScreenAnimator::ScreenAnimator(KyraEngine *vm) { + _vm = vm; + _screen = vm->screen(); + _initOk = false; + _updateScreen = false; + _screenObjects = _actors = _items = _sprites = _objectQueue = 0; + _noDrawShapesFlag = 0; +} + +ScreenAnimator::~ScreenAnimator() { + close(); +} + +void ScreenAnimator::init(int actors_, int items_, int sprites_) { + debug(9, "ScreenAnimator::init(%d, %d, %d)", actors_, items_, sprites_); + _screenObjects = new AnimObject[actors_ + items_ + sprites_]; + assert(_screenObjects); + memset(_screenObjects, 0, sizeof(AnimObject) * (actors_ + items_ + sprites_)); + _actors = _screenObjects; + _sprites = &_screenObjects[actors_]; + _items = &_screenObjects[actors_ + items_]; + _initOk = true; +} + +void ScreenAnimator::close() { + debug(9, "ScreenAnimator::close()"); + if (_initOk) { + _initOk = false; + delete [] _screenObjects; + _screenObjects = _actors = _items = _sprites = _objectQueue = 0; + } +} + +void ScreenAnimator::preserveAllBackgrounds() { + debug(9, "ScreenAnimator::preserveAllBackgrounds()"); + uint8 curPage = _screen->_curPage; + _screen->_curPage = 2; + + AnimObject *curObject = _objectQueue; + while (curObject) { + if (curObject->active && !curObject->unk1) { + preserveOrRestoreBackground(curObject, false); + curObject->bkgdChangeFlag = 0; + } + curObject = curObject->nextAnimObject; + } + _screen->_curPage = curPage; +} + +void ScreenAnimator::flagAllObjectsForBkgdChange() { + debug(9, "ScreenAnimator::flagAllObjectsForBkgdChange()"); + AnimObject *curObject = _objectQueue; + while (curObject) { + curObject->bkgdChangeFlag = 1; + curObject = curObject->nextAnimObject; + } +} + +void ScreenAnimator::flagAllObjectsForRefresh() { + debug(9, "ScreenAnimator::flagAllObjectsForRefresh()"); + AnimObject *curObject = _objectQueue; + while (curObject) { + curObject->refreshFlag = 1; + curObject = curObject->nextAnimObject; + } +} + +void ScreenAnimator::restoreAllObjectBackgrounds() { + debug(9, "ScreenAnimator::restoreAllObjectBackground()"); + AnimObject *curObject = _objectQueue; + _screen->_curPage = 2; + + while (curObject) { + if (curObject->active && !curObject->unk1) { + preserveOrRestoreBackground(curObject, true); + curObject->x2 = curObject->x1; + curObject->y2 = curObject->y1; + } + curObject = curObject->nextAnimObject; + } + + _screen->_curPage = 0; +} + +void ScreenAnimator::preserveAnyChangedBackgrounds() { + debug(9, "ScreenAnimator::preserveAnyChangedBackgrounds()"); + AnimObject *curObject = _objectQueue; + _screen->_curPage = 2; + + while (curObject) { + if (curObject->active && !curObject->unk1 && curObject->bkgdChangeFlag) { + preserveOrRestoreBackground(curObject, false); + curObject->bkgdChangeFlag = 0; + } + curObject = curObject->nextAnimObject; + } + + _screen->_curPage = 0; +} + +void ScreenAnimator::preserveOrRestoreBackground(AnimObject *obj, bool restore) { + debug(9, "ScreenAnimator::preserveOrRestoreBackground(0x%X, restore)", obj, restore); + int x = 0, y = 0, width = obj->width << 3, height = obj->height; + + if (restore) { + x = obj->x2; + y = obj->y2; + } else { + x = obj->x1; + y = obj->y1; + } + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + int temp; + + temp = x + width; + if (temp >= 319) { + x = 319 - width; + } + temp = y + height; + if (temp >= 136) { + y = 136 - height; + } + + if (restore) { + _screen->copyBlockToPage(_screen->_curPage, x, y, width, height, obj->background); + } else { + _screen->copyRegionToBuffer(_screen->_curPage, x, y, width, height, obj->background); + } +} + +void ScreenAnimator::prepDrawAllObjects() { + debug(9, "ScreenAnimator::prepDrawAllObjects()"); + AnimObject *curObject = _objectQueue; + int drawPage = 2; + int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0; + if (_noDrawShapesFlag) + return; + if (_vm->_brandonStatusBit & 0x20) + flagUnk1 = 0x200; + if (_vm->_brandonStatusBit & 0x40) + flagUnk2 = 0x4000; + + while (curObject) { + if (curObject->active) { + int xpos = curObject->x1; + int ypos = curObject->y1; + + int drawLayer = 0; + if (!(curObject->flags & 0x800)) { + drawLayer = 7; + } else if (curObject->unk1) { + drawLayer = 0; + } else { + drawLayer = _vm->_sprites->getDrawLayer(curObject->drawY); + } + + // talking head functionallity + if (_vm->_talkingCharNum != -1) { + const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00, 0x00 }; + const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00, 0x00 }; + const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, 0, 0, 0 }; + const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, 0, 0, 0 }; + const int8 yOffsetTable1[] = { 0, 8, 1, 1, 0, 0, 0, 0 }; + const int8 yOffsetTable2[] = { 0, 8, 1, 1, 0, 0, 0, 0 }; + if (curObject->index == 0 || curObject->index <= 4) { + int shapesIndex = 0; + if (curObject->index == _vm->_charSayUnk3) { + shapesIndex = _vm->_currHeadShape + baseAnimFrameTable1[curObject->index]; + } else { + shapesIndex = baseAnimFrameTable2[curObject->index]; + int temp2 = 0; + if (curObject->index == 2) { + if (_vm->_characterList[2].sceneId == 0x4D || _vm->_characterList[2].sceneId == 0x56) { + temp2 = 1; + } else { + temp2 = 0; + } + } else { + temp2 = 1; + } + + if (!temp2) { + shapesIndex = -1; + } + } + + xpos = curObject->x1; + ypos = curObject->y1; + + int tempX = 0, tempY = 0; + if (curObject->flags & 0x1) { + tempX = (xOffsetTable1[curObject->index] * _vm->_brandonScaleX) >> 8; + tempY = yOffsetTable1[curObject->index]; + } else { + tempX = (xOffsetTable2[curObject->index] * _vm->_brandonScaleX) >> 8; + tempY = yOffsetTable2[curObject->index]; + } + tempY = (tempY * _vm->_brandonScaleY) >> 8; + xpos += tempX; + ypos += tempY; + + if (_vm->_scaleMode && _vm->_brandonScaleX != 256) { + ++xpos; + } + + if (curObject->index == 0) { + if (!(_vm->_brandonStatusBit & 2)) { + flagUnk3 = 0x100; + if ((flagUnk1 & 0x200) || (flagUnk2 & 0x4000)) { + flagUnk3 = 0; + } + + int tempFlags = 0; + if (flagUnk3 & 0x100) { + if (curObject->flags & 1) { + tempFlags = 1; + } + tempFlags |= 0x800 | flagUnk1 | 0x100; + } + + if (!(flagUnk3 & 0x100) && (flagUnk2 & 0x4000)) { + tempFlags = 0; + if (curObject->flags & 1) { + tempFlags = 1; + } + tempFlags |= 0x900 | flagUnk1 | 0x4000; + _screen->drawShape(drawPage, _vm->_shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), int(0)/*XXX*/, drawLayer, _vm->_brandonScaleX, _vm->_brandonScaleY); + } else { + if (!(flagUnk2 & 0x4000)) { + tempFlags = 0; + if (curObject->flags & 1) { + tempFlags = 1; + } + tempFlags |= 0x900 | flagUnk1; + } + + _screen->drawShape(drawPage, _vm->_shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _vm->_brandonScaleX, _vm->_brandonScaleY); + } + } + } else { + if (shapesIndex != -1) { + int tempFlags = 0; + if (curObject->flags & 1) { + tempFlags = 1; + } + _screen->drawShape(drawPage, _vm->_shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 0x800, drawLayer); + } + } + } + } + + xpos = curObject->x1; + ypos = curObject->y1; + + curObject->flags |= 0x800; + if (curObject->index == 0) { + flagUnk3 = 0x100; + + if (flagUnk1 & 0x200 || flagUnk2 & 0x4000) { + flagUnk3 = 0; + } + + if (_vm->_brandonStatusBit & 2) { + curObject->flags &= 0xFFFFFFFE; + } + + if (!_vm->_scaleMode) { + if (flagUnk3 & 0x100) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8*)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer); + } else if (flagUnk3 & 0x4000) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, _vm->_brandonInvFlag, drawLayer); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, drawLayer); + } + } else { + if (flagUnk3 & 0x100) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8*)_vm->_brandonPoisonFlagsGFX, int(1), drawLayer, _vm->_brandonScaleX, _vm->_brandonScaleY); + } else if (flagUnk3 & 0x4000) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, int(0), drawLayer, _vm->_brandonInvFlag, _vm->_brandonScaleX, _vm->_brandonScaleY); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, drawLayer, _vm->_brandonScaleX, _vm->_brandonScaleY); + } + } + } else { + if (curObject->index >= 16 && curObject->index <= 27) { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, drawLayer, (int)_vm->_scaleTable[curObject->drawY], (int)_vm->_scaleTable[curObject->drawY]); + } else { + _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, drawLayer); + } + } + } + curObject = curObject->nextAnimObject; + } +} + +void ScreenAnimator::copyChangedObjectsForward(int refreshFlag) { + debug(9, "ScreenAnimator::copyChangedObjectsForward(%d)", refreshFlag); + AnimObject *curObject = _objectQueue; + + while (curObject) { + if (curObject->active) { + if (curObject->refreshFlag || refreshFlag) { + int xpos = 0, ypos = 0, width = 0, height = 0; + xpos = curObject->x1 - (curObject->width2+1); + ypos = curObject->y1 - curObject->height2; + width = (curObject->width + ((curObject->width2)>>3)+2)<<3; + height = curObject->height + curObject->height2*2; + + if (xpos < 8) { + xpos = 8; + } else if (xpos + width > 312) { + width = 312 - xpos; + } + + if (ypos < 8) { + ypos = 8; + } else if (ypos + height > 136) { + height = 136 - ypos; + } + + _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, 2, 0, Screen::CR_CLIPPED); + curObject->refreshFlag = 0; + _updateScreen = true; + } + } + curObject = curObject->nextAnimObject; + } + if (_updateScreen) { + _screen->updateScreen(); + _updateScreen = false; + } +} + +void ScreenAnimator::updateAllObjectShapes() { + debug(9, "ScreenAnimator::updateAllObjectShapes()"); + restoreAllObjectBackgrounds(); + preserveAnyChangedBackgrounds(); + prepDrawAllObjects(); + copyChangedObjectsForward(0); +} + +void ScreenAnimator::animRemoveGameItem(int index) { + debug(9, "ScreenAnimator::animRemoveGameItem(%d)", index); + restoreAllObjectBackgrounds(); + + AnimObject *animObj = &_items[index]; + animObj->sceneAnimPtr = 0; + animObj->animFrameNumber = -1; + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; + updateAllObjectShapes(); + animObj->active = 0; + + objectRemoveQueue(_objectQueue, animObj); +} + +void ScreenAnimator::animAddGameItem(int index, uint16 sceneId) { + debug(9, "ScreenAnimator::animRemoveGameItem(%d, %d)", index, sceneId); + restoreAllObjectBackgrounds(); + assert(sceneId < _vm->_roomTableSize); + Room *currentRoom = &_vm->_roomTable[sceneId]; + AnimObject *animObj = &_items[index]; + animObj->active = 1; + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; + animObj->drawY = currentRoom->itemsYPos[index]; + animObj->sceneAnimPtr = _vm->_shapes[220+currentRoom->itemsTable[index]]; + animObj->animFrameNumber = -1; + animObj->x1 = currentRoom->itemsXPos[index]; + animObj->y1 = currentRoom->itemsYPos[index]; + animObj->x1 -= _vm->fetchAnimWidth(animObj->sceneAnimPtr, _vm->_scaleTable[animObj->drawY]) >> 1; + animObj->y1 -= _vm->fetchAnimHeight(animObj->sceneAnimPtr, _vm->_scaleTable[animObj->drawY]); + animObj->x2 = animObj->x1; + animObj->y2 = animObj->y1; + animObj->width2 = 0; + animObj->height2 = 0; + _objectQueue = objectQueue(_objectQueue, animObj); + preserveAnyChangedBackgrounds(); + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; +} + +void ScreenAnimator::animAddNPC(int character) { + debug(9, "ScreenAnimator::animAddNPC(%d)", character); + restoreAllObjectBackgrounds(); + AnimObject *animObj = &_actors[character]; + const Character *ch = &_vm->_characterList[character]; + + animObj->active = 1; + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; + animObj->drawY = ch->y1; + animObj->sceneAnimPtr = _vm->_shapes[4+ch->currentAnimFrame]; + animObj->x1 = animObj->x2 = ch->x1 + _vm->_defaultShapeTable[ch->currentAnimFrame-7].xOffset; + animObj->y1 = animObj->y2 = ch->y1 + _vm->_defaultShapeTable[ch->currentAnimFrame-7].yOffset; + if (ch->facing >= 1 && ch->facing <= 3) { + animObj->flags |= 1; + } else if (ch->facing >= 5 && ch->facing <= 7) { + animObj->flags &= 0xFFFFFFFE; + } + _objectQueue = objectQueue(_objectQueue, animObj); + preserveAnyChangedBackgrounds(); + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; +} + +AnimObject *ScreenAnimator::objectRemoveQueue(AnimObject *queue, AnimObject *rem) { + debug(9, "ScreenAnimator::objectRemoveQueue(0x%X, 0x%X)", queue, rem); + AnimObject *cur = queue; + AnimObject *prev = queue; + + while (cur != rem && cur) { + AnimObject *temp = cur->nextAnimObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (cur == queue) { + if (!cur) + return 0; + return cur->nextAnimObject; + } + + if (!cur->nextAnimObject) { + if (cur == rem) { + if (!prev) { + return 0; + } else { + prev->nextAnimObject = 0; + } + } + } else { + if (cur == rem) { + prev->nextAnimObject = rem->nextAnimObject; + } + } + + return queue; +} + +AnimObject *ScreenAnimator::objectAddHead(AnimObject *queue, AnimObject *head) { + debug(9, "ScreenAnimator::objectAddHead(0x%X, 0x%X)", queue, head); + head->nextAnimObject = queue; + return head; +} + +AnimObject *ScreenAnimator::objectQueue(AnimObject *queue, AnimObject *add) { + debug(9, "ScreenAnimator::objectQueue(0x%X, 0x%X)", queue, add); + if (add->drawY <= queue->drawY || !queue) { + add->nextAnimObject = queue; + return add; + } + AnimObject *cur = queue; + AnimObject *prev = queue; + while (add->drawY > cur->drawY) { + AnimObject *temp = cur->nextAnimObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (add->drawY <= cur->drawY) { + prev->nextAnimObject = add; + add->nextAnimObject = cur; + } else { + cur->nextAnimObject = add; + add->nextAnimObject = 0; + } + return queue; +} + +void ScreenAnimator::addObjectToQueue(AnimObject *object) { + debug(9, "ScreenAnimator::addObjectToQueue(0x%X)", object); + if (!_objectQueue) { + _objectQueue = objectAddHead(0, object); + } else { + _objectQueue = objectQueue(_objectQueue, object); + } +} + +void ScreenAnimator::refreshObject(AnimObject *object) { + debug(9, "ScreenAnimator::refreshObject(0x%X)", object); + _objectQueue = objectRemoveQueue(_objectQueue, object); + if (_objectQueue) { + _objectQueue = objectQueue(_objectQueue, object); + } else { + _objectQueue = objectAddHead(0, object); + } +} +} // end of namespace Kyra diff --git a/kyra/animator.h b/kyra/animator.h new file mode 100644 index 0000000000..a82279aa37 --- /dev/null +++ b/kyra/animator.h @@ -0,0 +1,105 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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$ + * + */ + +#ifndef KYRAANIMATOR_H +#define KYRAANIMATOR_H + +namespace Kyra { +class KyraEngine; +class Screen; + +struct AnimObject { + uint8 index; + uint32 active; + uint32 refreshFlag; + uint32 bkgdChangeFlag; + uint32 unk1; + uint32 flags; + int16 drawY; + uint8 *sceneAnimPtr; + int16 animFrameNumber; + uint8 *background; + uint16 rectSize; + int16 x1, y1; + int16 x2, y2; + uint16 width; + uint16 height; + uint16 width2; + uint16 height2; + AnimObject *nextAnimObject; + }; + +class ScreenAnimator { +public: + ScreenAnimator(KyraEngine *vm); + virtual ~ScreenAnimator(); + + operator bool() const { return _initOk; } + + void init(int actors, int items, int sprites); + void close(); + + AnimObject *objects() { return _screenObjects; } + AnimObject *actors() { return _actors; } + AnimObject *items() { return _items; } + AnimObject *sprites() { return _sprites; } + + void preserveAllBackgrounds(); + void flagAllObjectsForBkgdChange(); + void flagAllObjectsForRefresh(); + void restoreAllObjectBackgrounds(); + void preserveAnyChangedBackgrounds(); + virtual void prepDrawAllObjects(); + void copyChangedObjectsForward(int refreshFlag); + + void updateAllObjectShapes(); + void animRemoveGameItem(int index); + void animAddGameItem(int index, uint16 sceneId); + void animAddNPC(int character); + + void clearQueue() { _objectQueue = 0; } + void addObjectToQueue(AnimObject *object); + void refreshObject(AnimObject *object); + + int _noDrawShapesFlag; + bool _updateScreen; +protected: + KyraEngine *_vm; + Screen *_screen; + bool _initOk; + + AnimObject *_screenObjects; + + AnimObject *_actors; + AnimObject *_items; + AnimObject *_sprites; + + AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem); + AnimObject *objectAddHead(AnimObject *queue, AnimObject *head); + AnimObject *objectQueue(AnimObject *queue, AnimObject *add); + + void preserveOrRestoreBackground(AnimObject *obj, bool restore); + + AnimObject *_objectQueue; +}; +} // end of namespace Kyra + +#endif diff --git a/kyra/debugger.cpp b/kyra/debugger.cpp index c1bc7fd65e..1384ce5fd8 100644 --- a/kyra/debugger.cpp +++ b/kyra/debugger.cpp @@ -1,5 +1,5 @@ /* ScummVM - Scumm Interpreter - * Copyright (C) 2003-2005 The ScummVM project + * Copyright (C) 2005 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 diff --git a/kyra/debugger.h b/kyra/debugger.h index ea7f1aba7c..2a15103548 100644 --- a/kyra/debugger.h +++ b/kyra/debugger.h @@ -1,5 +1,5 @@ /* ScummVM - Scumm Interpreter - * Copyright (C) 2003-2005 The ScummVM project + * Copyright (C) 2005 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 diff --git a/kyra/gui.cpp b/kyra/gui.cpp new file mode 100644 index 0000000000..8f3212b2e5 --- /dev/null +++ b/kyra/gui.cpp @@ -0,0 +1,293 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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/screen.h" +#include "kyra/script.h" + +namespace Kyra { +Button *KyraEngine::initButton(Button *list, Button *newButton) { + if (!newButton) + return list; + if (!list) + return newButton; + Button *cur = list; + while (true) { + if (!cur->nextButton) { + break; + } + cur = cur->nextButton; + } + cur->nextButton = newButton; + return list; +} + +int KyraEngine::buttonInventoryCallback(Button *caller) { + int itemOffset = caller->specialValue - 2; + uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset]; + if (_itemInHand == -1) { + if (inventoryItem == 0xFF) { + // snd_playSoundEffect(0x36); + return 0; + } else { + _screen->hideMouse(); + _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); + // snd_playSoundEffect(0x35); + setMouseItem(inventoryItem); + updateSentenceCommand(_itemList[inventoryItem], _takenList[0], 179); + _itemInHand = inventoryItem; + _screen->showMouse(); + _currentCharacter->inventoryItems[itemOffset] = 0xFF; + } + } else { + if (inventoryItem != 0xFF) { + // snd_playSoundEffect(0x35); + _screen->hideMouse(); + _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); + _screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); + setMouseItem(inventoryItem); + updateSentenceCommand(_itemList[inventoryItem], _takenList[1], 179); + _screen->showMouse(); + _currentCharacter->inventoryItems[itemOffset] = _itemInHand; + _itemInHand = inventoryItem; + } else { + // snd_playSoundEffect(0x32); + _screen->hideMouse(); + _screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); + _screen->setMouseCursor(1, 1, _shapes[4]); + updateSentenceCommand(_itemList[_itemInHand], _placedList[0], 179); + _screen->showMouse(); + _currentCharacter->inventoryItems[itemOffset] = _itemInHand; + _itemInHand = -1; + } + } + _screen->updateScreen(); + // XXX clearKyrandiaButtonIO + return 0; +} + +int KyraEngine::buttonAmuletCallback(Button *caller) { + if (!(_deathHandler & 8)) + return 1; + int jewel = caller->specialValue - 0x14; + if (_currentCharacter->sceneId == 210) { + //if (_unkSceneVar == 4 || _unkSceneVar == 6) + // return 1; + } + if (!queryGameFlag(0x2D)) + return 1; + if (_itemInHand != -1) { + assert(_putDownFirst); + characterSays(_putDownFirst[0], 0, -2); + return 1; + } + if (queryGameFlag(0xF1)) { + assert(_waitForAmulet); + characterSays(_waitForAmulet[0], 0, -2); + return 1; + } + if (!queryGameFlag(0x55+jewel)) { + assert(_blackJewel); + makeBrandonFaceMouse(); + drawJewelPress(jewel, 1); + characterSays(_blackJewel[0], 0, -2); + return 1; + } + drawJewelPress(jewel, 0); + drawJewelsFadeOutStart(); + drawJewelsFadeOutEnd(jewel); + + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + _scriptClick->variables[3] = 0; + _scriptClick->variables[6] = jewel; + _scriptInterpreter->startScript(_scriptClick, 4); + + while (_scriptInterpreter->validScript(_scriptClick)) { + _scriptInterpreter->runScript(_scriptClick); + } + + if (_scriptClick->variables[3]) + return 1; + + _unkAmuletVar = 1; + switch (jewel-1) { + case 0: + if (_brandonStatusBit & 1) { + seq_brandonHealing2(); + } else if (_brandonStatusBit == 0) { + seq_brandonHealing(); + assert(_healingTip); + characterSays(_healingTip[0], 0, -2); + } + break; + + case 1: + seq_makeBrandonInv(); + break; + + case 2: + if (_brandonStatusBit & 1) { + assert(_wispJewelStrings); + characterSays(_wispJewelStrings[0], 0, -2); + } else { + if (_brandonStatusBit & 2) { + // XXX + seq_makeBrandonNormal2(); + // XXX + } else { + // do not check for item in hand again as in the original since some strings are missing + // in the cd version + if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) { + // XXX + seq_makeBrandonWisp(); + // XXX + } else { + seq_makeBrandonWisp(); + } + setGameFlag(0x9E); + } + } + break; + + case 3: + seq_dispelMagicAnimation(); + assert(_magicJewelString); + characterSays(_magicJewelString[0], 0, -2); + break; + + default: + break; + } + _unkAmuletVar = 0; + // XXX clearKyrandiaButtonIO (!used before every return in this function!) + return 1; +} + +void KyraEngine::processButtonList(Button *list) { + while (list) { + if (list->flags & 8) { + list = list->nextButton; + continue; + } + + int x = list->x; + int y = list->y; + assert(list->dimTableIndex < _screen->_screenDimTableCount); + if (x < 0) { + x += _screen->_screenDimTable[list->dimTableIndex].w << 3; + } + x += _screen->_screenDimTable[list->dimTableIndex].sx << 3; + + if (y < 0) { + y += _screen->_screenDimTable[list->dimTableIndex].h; + } + y += _screen->_screenDimTable[list->dimTableIndex].sy; + + if (_mouseX >= x && _mouseY >= y && x + list->width >= _mouseX && y + list->height >= _mouseY) { + int processMouseClick = 0; + if (list->flags & 0x400) { + if (_mousePressFlag) { + if (!(list->flags2 & 1)) { + list->flags2 |= 1; + processButton(list); + } + } else { + if (list->flags2 & 1) { + list->flags2 &= 0xFFFE; + processButton(list); + processMouseClick = 1; + } + } + } else if (_mousePressFlag) { + processMouseClick = 1; + } + + if (processMouseClick) { + if (list->buttonCallback) { + if ((this->*(list->buttonCallback))(list)) { + break; + } + } + } + } else { + if (list->flags2 & 1) { + list->flags2 &= 0xFFFE; + processButton(list); + } + list = list->nextButton; + continue; + } + + list = list->nextButton; + } +} + +void KyraEngine::processButton(Button *button) { + if (!button) + return; + + int processType = 0; + uint8 *shape = 0; + Button::ButtonCallback callback = 0; + + int flags = (button->flags2 & 5); + if (flags == 1) { + processType = button->process2; + if (processType == 1) { + shape = button->process2PtrShape; + } else if (processType == 4) { + callback = button->process2PtrCallback; + } + } else if (flags == 4 || flags == 5) { + processType = button->process1; + if (processType == 1) { + shape = button->process1PtrShape; + } else if (processType == 4) { + callback = button->process1PtrCallback; + } + } else { + processType = button->process0; + if (processType == 1) { + shape = button->process0PtrShape; + } else if (processType == 4) { + callback = button->process0PtrCallback; + } + } + + int x = button->x; + int y = button->y; + assert(button->dimTableIndex < _screen->_screenDimTableCount); + if (x < 0) { + x += _screen->_screenDimTable[button->dimTableIndex].w << 3; + } + + if (y < 0) { + y += _screen->_screenDimTable[button->dimTableIndex].h; + } + + if (processType == 1 && shape) { + _screen->drawShape(_screen->_curPage, shape, x, y, button->dimTableIndex, 0x10); + } else if (processType == 4 && callback) { + (this->*callback)(button); + } +} +} // end of namespace Kyra + diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp index ca90fa940f..422b3da563 100644 --- a/kyra/kyra.cpp +++ b/kyra/kyra.cpp @@ -45,6 +45,8 @@ #include "kyra/sound.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" +#include "kyra/animator.h" +#include "kyra/text.h" #include "kyra/debugger.h" using namespace Kyra; @@ -293,6 +295,12 @@ int KyraEngine::init(GameDetector &detector) { assert(_sprites); _seq = new SeqPlayer(this, _system); assert(_seq); + _animator = new ScreenAnimator(this); + assert(_animator); + _animator->init(5, 11, 12); + assert(*_animator); + _text = new TextDisplayer(_screen); + assert(_text); _paletteChanged = 1; _currentCharacter = 0; @@ -307,14 +315,6 @@ int KyraEngine::init(GameDetector &detector) { _characterList[0].facing = 3; _characterList[0].currentAnimFrame = 7; - _objectQueue = 0; - _animStates = new AnimObject[31]; - assert(_animStates); - memset(_animStates, 0, sizeof(AnimObject)*31); - _charactersAnimState = &_animStates[0]; - _sprites->_animObjects = &_animStates[5]; - _animItems = &_animStates[16]; - _scriptInterpreter = new ScriptHelper(this); assert(_scriptInterpreter); @@ -349,19 +349,12 @@ int KyraEngine::init(GameDetector &detector) { _fastMode = false; _abortWalkFlag = false; _abortWalkFlag2 = false; - _talkCoords.y = 0x88; - _talkCoords.x = 0; - _talkCoords.w = 0; - _talkMessageY = 0xC; - _talkMessageH = 0; - _talkMessagePrinted = false; _talkingCharNum = -1; _charSayUnk3 = -1; _mouseX = _mouseY = -1; memset(_currSentenceColor, 0, 3); _startSentencePalIndex = -1; _fadeText = false; - _noDrawShapesFlag = 0; _cauldronState = 0; _crystalState[0] = _crystalState[1] = -1; @@ -415,12 +408,14 @@ KyraEngine::~KyraEngine() { delete _debugger; delete _sprites; + delete _animator; delete _screen; delete _res; delete _midi; delete _saveFileMan; delete _seq; delete _scriptInterpreter; + delete _text; delete _npcScriptData; delete _scriptMain; @@ -428,7 +423,6 @@ KyraEngine::~KyraEngine() { delete _scriptClickData; delete _scriptClick; - delete [] _animStates; delete [] _characterList; delete [] _movFacingTable; @@ -626,7 +620,7 @@ void KyraEngine::delay(uint32 amount, bool update) { _sprites->updateSceneAnims(); if (update) - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); if (_currentCharacter->sceneId == 210) { //XXX @@ -690,7 +684,7 @@ void KyraEngine::mainLoop() { updateMousePointer(); updateGameTimers(); _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); updateTextFade(); _handleInput = true; @@ -785,7 +779,7 @@ void KyraEngine::delayWithTicks(int ticks) { uint32 nextTime = _system->getMillis() + ticks * _tickLength; while (_system->getMillis() < nextTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); //if (_currentCharacter->sceneId == 210) { // updateKyragemFading(); // seq_playEnd(); @@ -862,11 +856,11 @@ void KyraEngine::seq_intro() { _screen->setFont(Screen::FID_8_FNT); snd_playTheme(MUSIC_INTRO, 2); snd_setSoundEffectFile(MUSIC_INTRO); - setTalkCoords(144); + _text->setTalkCoords(144); for (int i = 0; i < ARRAYSIZE(introProcTable) && !seq_skipSequence(); ++i) { (this->*introProcTable[i])(); } - setTalkCoords(136); + _text->setTalkCoords(136); waitTicks(30); _seq->setCopyViewOffs(false); _midi->stopMusic(); @@ -1138,10 +1132,10 @@ void KyraEngine::seq_poisonDeathNowAnim() { resetBrandonAnimSeqSize(); freeShapes123(); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); _currentCharacter->x1 = _currentCharacter->x2 = -1; _currentCharacter->y1 = _currentCharacter->y2 = -1; - preserveAllBackgrounds(); + _animator->preserveAllBackgrounds(); _screen->showMouse(); } @@ -1227,9 +1221,9 @@ void KyraEngine::seq_winterScroll1() { if (_currentCharacter->sceneId == 41 && !queryGameFlag(0xA2)) { // snd_playSoundEffect(0x20); _sprites->_anims[0].play = false; - _sprites->_animObjects[0].active = 0; + _animator->sprites()[0].active = 0; _sprites->_anims[1].play = true; - _sprites->_animObjects[1].active = 1; + _animator->sprites()[1].active = 1; } for (int i = 147; i <= 157; ++i) { @@ -1241,7 +1235,7 @@ void KyraEngine::seq_winterScroll1() { if (_currentCharacter->sceneId == 117 && !queryGameFlag(0xB3)) { for (int i = 0; i <= 7; ++i) { _sprites->_anims[i].play = false; - _sprites->_animObjects[i].active = 0; + _animator->sprites()[i].active = 0; } uint8 tmpPal[768]; memcpy(tmpPal, _screen->_currentPalette, 768); @@ -1392,7 +1386,7 @@ void KyraEngine::seq_makeBrandonWisp() { _brandonStatusBit0x02Flag = 1; _currentCharacter->currentAnimFrame = 113; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245) { _screen->fadeSpecialPalette(30, 234, 13, 4); } else if (_currentCharacter->sceneId >= 118 && _currentCharacter->sceneId <= 186) { @@ -2068,7 +2062,7 @@ void KyraEngine::setCharacterPositionWithUpdate(int character) { setCharacterPosition(character, 0); _sprites->updateSceneAnims(); updateGameTimers(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); updateTextFade(); if (_currentCharacter->sceneId == 210) { @@ -2484,55 +2478,56 @@ void KyraEngine::resetBrandonPosionFlags() { } void KyraEngine::initAnimStateList() { - _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; + 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; + 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; + 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; + 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, "initSceneObjectList(%d)", brandonAlive); for (int i = 0; i < 31; ++i) { - _charactersAnimState[i].active = 0; + _animator->actors()[i].active = 0; } int startAnimFrame = 0; - AnimObject *curAnimState = _charactersAnimState; + AnimObject *curAnimState = _animator->actors(); curAnimState->active = 1; curAnimState->drawY = _currentCharacter->y1; curAnimState->sceneAnimPtr = _shapes[4+_currentCharacter->currentAnimFrame]; @@ -2557,15 +2552,15 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { curAnimState->y2 = curAnimState->y1; curAnimState->refreshFlag = 1; curAnimState->bkgdChangeFlag = 1; - _objectQueue = 0; - _objectQueue = objectAddHead(0, curAnimState); + _animator->clearQueue(); + _animator->addObjectToQueue(curAnimState); int listAdded = 0; int addedObjects = 1; for (int i = 1; i < 5; ++i) { Character *ch = &_characterList[i]; - curAnimState = &_charactersAnimState[addedObjects]; + curAnimState = &_animator->actors()[addedObjects]; if (ch->sceneId != _currentCharacter->sceneId) { curAnimState->active = 0; curAnimState->refreshFlag = 0; @@ -2605,7 +2600,7 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { curAnimState->flags &= 0xFFFFFFFE; } - _objectQueue = objectQueue(_objectQueue, curAnimState); + _animator->addObjectToQueue(curAnimState); ++addedObjects; ++listAdded; @@ -2614,7 +2609,7 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { } for (int i = 0; i < 11; ++i) { - curAnimState = &_sprites->_animObjects[i]; + curAnimState = &_animator->sprites()[i]; if (_sprites->_anims[i].play) { curAnimState->active = 1; @@ -2644,12 +2639,11 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { if (_sprites->_anims[i].flipX) curAnimState->flags |= 0x1; - _objectQueue = objectQueue(_objectQueue, curAnimState); - + _animator->addObjectToQueue(curAnimState); } for (int i = 0; i < 12; ++i) { - curAnimState = &_animItems[i]; + curAnimState = &_animator->items()[i]; Room *curRoom = &_roomTable[_currentCharacter->sceneId]; byte curItem = curRoom->itemsTable[i]; if (curItem != 0xFF) { @@ -2669,7 +2663,7 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { curAnimState->refreshFlag = 1; curAnimState->bkgdChangeFlag = 1; - _objectQueue = objectQueue(_objectQueue, curAnimState); + _animator->addObjectToQueue(curAnimState); } else { curAnimState->active = 0; curAnimState->refreshFlag = 0; @@ -2677,22 +2671,22 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { } } - preserveAnyChangedBackgrounds(); - curAnimState = _charactersAnimState; + _animator->preserveAnyChangedBackgrounds(); + curAnimState = _animator->actors(); curAnimState->bkgdChangeFlag = 1; curAnimState->refreshFlag = 1; for (int i = 1; i < 28; ++i) { - curAnimState = &_animStates[i]; + curAnimState = &_animator->objects()[i]; if (curAnimState->active) { curAnimState->bkgdChangeFlag = 1; curAnimState->refreshFlag = 1; } } - restoreAllObjectBackgrounds(); - preserveAnyChangedBackgrounds(); - prepDrawAllObjects(); + _animator->restoreAllObjectBackgrounds(); + _animator->preserveAnyChangedBackgrounds(); + _animator->prepDrawAllObjects(); initSceneScreen(brandonAlive); - copyChangedObjectsForward(0); + _animator->copyChangedObjectsForward(0); } void KyraEngine::initSceneScreen(int brandonAlive) { @@ -2731,186 +2725,6 @@ void KyraEngine::initSceneScreen(int brandonAlive) { #pragma mark - Text handling #pragma mark - -void KyraEngine::setTalkCoords(uint16 y) { - debug(9, "KyraEngine::setTalkCoords(%d)", y); - _talkCoords.y = y; -} - -int KyraEngine::getCenterStringX(const char *str, int x1, int x2) { - debug(9, "KyraEngine::getCenterStringX('%s', %d, %d)", str, x1, x2); - _screen->_charWidth = -2; - Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); - int strWidth = _screen->getTextWidth(str); - _screen->setFont(curFont); - _screen->_charWidth = 0; - int w = x2 - x1 + 1; - return x1 + (w - strWidth) / 2; -} - -int KyraEngine::getCharLength(const char *str, int len) { - debug(9, "KyraEngine::getCharLength('%s', %d)", str, len); - int charsCount = 0; - if (*str) { - _screen->_charWidth = -2; - Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); - int i = 0; - while (i <= len && *str) { - i += _screen->getCharWidth(*str++); - ++charsCount; - } - _screen->setFont(curFont); - _screen->_charWidth = 0; - } - return charsCount; -} - -int KyraEngine::dropCRIntoString(char *str, int offs) { - debug(9, "KyraEngine::dropCRIntoString('%s', %d)", str, offs); - int pos = 0; - str += offs; - while (*str) { - if (*str == ' ') { - *str = '\r'; - return pos; - } - ++str; - ++pos; - } - return 0; -} - -char *KyraEngine::preprocessString(const char *str) { - debug(9, "KyraEngine::preprocessString('%s')", str); - assert(strlen(str) < sizeof(_talkBuffer) - 1); - strcpy(_talkBuffer, str); - char *p = _talkBuffer; - while (*p) { - if (*p == '\r') { - return _talkBuffer; - } - ++p; - } - p = _talkBuffer; - Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); - _screen->_charWidth = -2; - int textWidth = _screen->getTextWidth(p); - _screen->_charWidth = 0; - if (textWidth > 176) { - if (textWidth > 352) { - int count = getCharLength(p, textWidth / 3); - int offs = dropCRIntoString(p, count); - p += count + offs; - _screen->_charWidth = -2; - textWidth = _screen->getTextWidth(p); - _screen->_charWidth = 0; - count = getCharLength(p, textWidth / 2); - dropCRIntoString(p, count); - } else { - int count = getCharLength(p, textWidth / 2); - dropCRIntoString(p, count); - } - } - _screen->setFont(curFont); - return _talkBuffer; -} - -int KyraEngine::buildMessageSubstrings(const char *str) { - debug(9, "KyraEngine::buildMessageSubstrings('%s')", str); - int currentLine = 0; - int pos = 0; - while (*str) { - if (*str == '\r') { - assert(currentLine < TALK_SUBSTRING_NUM); - _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0'; - ++currentLine; - pos = 0; - } else { - _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = *str; - ++pos; - if (pos > TALK_SUBSTRING_LEN - 2) { - pos = TALK_SUBSTRING_LEN - 2; - } - } - ++str; - } - _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0'; - return currentLine + 1; -} - -int KyraEngine::getWidestLineWidth(int linesCount) { - debug(9, "KyraEngine::getWidestLineWidth(%d)", linesCount); - int maxWidth = 0; - Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); - _screen->_charWidth = -2; - for (int l = 0; l < linesCount; ++l) { - int w = _screen->getTextWidth(&_talkSubstrings[l * TALK_SUBSTRING_LEN]); - if (maxWidth < w) { - maxWidth = w; - } - } - _screen->setFont(curFont); - _screen->_charWidth = 0; - return maxWidth; -} - -void KyraEngine::calcWidestLineBounds(int &x1, int &x2, int w, int cx) { - debug(9, "KyraEngine::calcWidestLineBounds(%d, %d)", w, cx); - x1 = cx - w / 2; - if (x1 + w >= Screen::SCREEN_W - 12) { - x1 = Screen::SCREEN_W - 12 - w - 1; - } else if (x1 < 12) { - x1 = 12; - } - x2 = x1 + w + 1; -} - -void KyraEngine::restoreTalkTextMessageBkgd(int srcPage, int dstPage) { - debug(9, "KyraEngine::restoreTalkTextMessageBkgd(%d, %d)", srcPage, dstPage); - if (_talkMessagePrinted) { - _talkMessagePrinted = false; - _screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage); - } -} - -void KyraEngine::printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage) { - debug(9, "KyraEngine::printTalkTextMessage('%s', %d, %d, %d, %d, %d)", text, x, y, color, srcPage, dstPage); - char *str = preprocessString(text); - int lineCount = buildMessageSubstrings(str); - int top = y - lineCount * 10; - if (top < 0) { - top = 0; - } - _talkMessageY = top; - _talkMessageH = lineCount * 10; - int w = getWidestLineWidth(lineCount); - int x1, x2; - calcWidestLineBounds(x1, x2, w, x); - _talkCoords.x = x1; - _talkCoords.w = w + 2; - _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage); - int curPage = _screen->_curPage; - _screen->_curPage = srcPage; - for (int i = 0; i < lineCount; ++i) { - top = i * 10 + _talkMessageY; - char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; - int left = getCenterStringX(msg, x1, x2); - printText(msg, left, top, color, 0xC, 0); - } - _screen->_curPage = curPage; - _talkMessagePrinted = true; -} - -void KyraEngine::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2) { - uint8 colorMap[] = { 0, 15, 12, 12 }; - colorMap[3] = c1; - _screen->setTextColor(colorMap, 0, 3); - Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); - _screen->_charWidth = -2; - _screen->printText(str, x, y, c0, c2); - _screen->_charWidth = 0; - _screen->setFont(curFont); -} - void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 charNum) { debug(9, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); bool hasUpdatedNPCs = false; @@ -2959,7 +2773,7 @@ void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 ch animRefreshNPC(_talkingCharNum); if (_charSayUnk2 != -1) { - _sprites->_animObjects[_charSayUnk2].active = 0; + _animator->sprites()[_charSayUnk2].active = 0; _sprites->_anims[_charSayUnk2].play = false; _charSayUnk2 = -1; } @@ -2967,16 +2781,16 @@ void KyraEngine::waitForChatToFinish(int16 chatDuration, char *chatStr, uint8 ch updateGameTimers(); _sprites->updateSceneAnims(); - restoreAllObjectBackgrounds(); - preserveAnyChangedBackgrounds(); - prepDrawAllObjects(); + _animator->restoreAllObjectBackgrounds(); + _animator->preserveAnyChangedBackgrounds(); + _animator->prepDrawAllObjects(); currPage = _screen->_curPage; _screen->_curPage = 2; - printCharacterText(chatStr, charNum); + _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1); _screen->_curPage = currPage; - copyChangedObjectsForward(0); + _animator->copyChangedObjectsForward(0); updateTextFade(); if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1) @@ -3025,7 +2839,7 @@ void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) { _talkingCharNum = -1; _currentCharacter->currentAnimFrame = 7; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } } @@ -3039,7 +2853,7 @@ void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) { _currentCharacter->currentAnimFrame = 7; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) { @@ -3054,7 +2868,7 @@ void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) { _currentCharacter->currentAnimFrame = _currentCharAnimFrame; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } int8 KyraEngine::getChatPartnerNum() { @@ -3089,46 +2903,26 @@ int KyraEngine::initCharacterChat(int8 charNum) { _currentCharacter->currentAnimFrame = 16; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } _charSayUnk2 = -1; - flagAllObjectsForBkgdChange(); - restoreAllObjectBackgrounds(); + _animator->flagAllObjectsForBkgdChange(); + _animator->restoreAllObjectBackgrounds(); if (charNum > 4 && charNum < 11) { // TODO: Fill in weird _game_inventory stuff here warning("STUB: initCharacterChat() for high charnums"); } - flagAllObjectsForRefresh(); - flagAllObjectsForBkgdChange(); - preserveAnyChangedBackgrounds(); + _animator->flagAllObjectsForRefresh(); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); _charSayUnk3 = charNum; return 1; } -void KyraEngine::printCharacterText(char *text, int8 charNum) { - uint8 colorTable[] = {0x0F, 0x9, 0x0C9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a}; - int top, left, x1, x2, w, x; - char *msg; - - uint8 color = colorTable[charNum]; - text = preprocessString(text); - int lineCount = buildMessageSubstrings(text); - w = getWidestLineWidth(lineCount); - x = _characterList[charNum].x1; - calcWidestLineBounds(x1, x2, w, x); - - for (int i = 0; i < lineCount; ++i) { - top = i * 10 + _talkMessageY; - msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; - left = getCenterStringX(msg, x1, x2); - printText(msg, left, top, color, 0xC, 0); - } -} - 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 }; @@ -3153,8 +2947,8 @@ void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) { animRefreshNPC(charNum); } - char *processedString = preprocessString(chatStr); - int lineNum = buildMessageSubstrings(processedString); + char *processedString = _text->preprocessString(chatStr); + int lineNum = _text->buildMessageSubstrings(processedString); int16 yPos = _characterList[charNum].y1; yPos -= _scaleTable[charNum] * _characterList[charNum].height; @@ -3167,14 +2961,14 @@ void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) { if (yPos > 100) yPos = 100; - _talkMessageY = yPos; - _talkMessageH = lineNum * 10; - restoreAllObjectBackgrounds(); + _text->_talkMessageY = yPos; + _text->_talkMessageH = lineNum * 10; + _animator->restoreAllObjectBackgrounds(); - _screen->copyRegion(1, _talkMessageY, 1, 136, 319, _talkMessageH, 2, 2); + _screen->copyRegion(1, _text->_talkMessageY, 1, 136, 319, _text->_talkMessageH, 2, 2); _screen->hideMouse(); - printCharacterText(processedString, charNum); + _text->printCharacterText(processedString, charNum, _characterList[charNum].x1); _screen->showMouse(); if (chatDuration == -2) @@ -3184,17 +2978,17 @@ void KyraEngine::characterSays(char *chatStr, int8 charNum, int8 chatDuration) { waitForChatToFinish(chatTicks, chatStr, charNum); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); - _screen->copyRegion(1, 136, 1, _talkMessageY, 319, _talkMessageH, 2, 2); - preserveAllBackgrounds(); - prepDrawAllObjects(); + _screen->copyRegion(1, 136, 1, _text->_talkMessageY, 319, _text->_talkMessageH, 2, 2); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); _screen->hideMouse(); - _screen->copyRegion(1, _talkMessageY, 1, _talkMessageY, 319, _talkMessageH, 2, 0); + _screen->copyRegion(1, _text->_talkMessageY, 1, _text->_talkMessageY, 319, _text->_talkMessageH, 2, 0); _screen->showMouse(); - flagAllObjectsForRefresh(); - copyChangedObjectsForward(0); + _animator->flagAllObjectsForRefresh(); + _animator->copyChangedObjectsForward(0); if (chatPartnerNum != -1 && chatPartnerNum < 5) restoreChatPartnerAnimFrame(chatPartnerNum); @@ -3216,7 +3010,7 @@ void KyraEngine::drawSentenceCommand(char *sentence, int color) { _startSentencePalIndex = 0; } - printText(sentence, 8, 143, 0xFF, 12, 0); + _text->printText(sentence, 8, 143, 0xFF, 12, 0); _screen->showMouse(); setTextFadeTimerCountdown(15); _fadeText = false; @@ -3257,10 +3051,8 @@ void KyraEngine::updateTextFade() { _fadeText = false; _startSentencePalIndex = -1; } - } - #pragma mark - #pragma mark - Item handling #pragma mark - @@ -3663,14 +3455,14 @@ int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int un void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { debug(9, "exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex); _screen->hideMouse(); - animRemoveGameItem(itemIndex); + _animator->animRemoveGameItem(itemIndex); assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; int item = currentRoom->itemsTable[itemIndex]; currentRoom->itemsTable[itemIndex] = _itemInHand; _itemInHand = item; - animAddGameItem(itemIndex, sceneId); + _animator->animAddGameItem(itemIndex, sceneId); // XXX snd_kyraPlaySound 53 setMouseItem(_itemInHand); @@ -3749,7 +3541,7 @@ void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, currentRoom->itemsYPos[freeItem] = destY; currentRoom->itemsTable[freeItem] = item; // call kyraPlaySound(0x32) - animAddGameItem(freeItem, _currentCharacter->sceneId); + _animator->animAddGameItem(freeItem, _currentCharacter->sceneId); return; } _screen->hideMouse(); @@ -3830,7 +3622,7 @@ void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, currentRoom->itemsYPos[freeItem] = destY; currentRoom->itemsTable[freeItem] = item; // call kyraPlaySound(0x32) - animAddGameItem(freeItem, _currentCharacter->sceneId); + _animator->animAddGameItem(freeItem, _currentCharacter->sceneId); _screen->showMouse(); } @@ -4196,319 +3988,9 @@ void KyraEngine::redrawInventory(int page) { #pragma mark - Animation/shape specific code #pragma mark - -void KyraEngine::preserveAllBackgrounds() { - uint8 currPage = _screen->_curPage; - _screen->_curPage = 2; - - AnimObject *curObject = _objectQueue; - while (curObject) { - if (curObject->active && !curObject->unk1) { - preserveOrRestoreBackground(curObject, false); - curObject->bkgdChangeFlag = 0; - } - curObject = curObject->nextAnimObject; - } - _screen->_curPage = currPage; -} - -void KyraEngine::flagAllObjectsForBkgdChange() { - AnimObject *curObject = _objectQueue; - while (curObject) { - curObject->bkgdChangeFlag = 1; - curObject = curObject->nextAnimObject; - } -} - -void KyraEngine::flagAllObjectsForRefresh() { - AnimObject *curObject = _objectQueue; - while (curObject) { - curObject->refreshFlag = 1; - curObject = curObject->nextAnimObject; - } -} - -void KyraEngine::restoreAllObjectBackgrounds() { - debug(9, "restoreAllObjectBackground()"); - AnimObject *curObject = _objectQueue; - _screen->_curPage = 2; - - while (curObject) { - if (curObject->active && !curObject->unk1) { - preserveOrRestoreBackground(curObject, true); - curObject->x2 = curObject->x1; - curObject->y2 = curObject->y1; - } - curObject = curObject->nextAnimObject; - } - - _screen->_curPage = 0; -} - -void KyraEngine::preserveAnyChangedBackgrounds() { - debug(9, "preserveAnyChangedBackgrounds()"); - AnimObject *curObject = _objectQueue; - _screen->_curPage = 2; - - while (curObject) { - if (curObject->active && !curObject->unk1 && curObject->bkgdChangeFlag) { - preserveOrRestoreBackground(curObject, false); - curObject->bkgdChangeFlag = 0; - } - curObject = curObject->nextAnimObject; - } - - _screen->_curPage = 0; -} - -void KyraEngine::preserveOrRestoreBackground(AnimObject *obj, bool restore) { - debug(9, "preserveOrRestoreBackground(0x%X, restore)", obj, restore); - int x = 0, y = 0, width = obj->width << 3, height = obj->height; - - if (restore) { - x = obj->x2; - y = obj->y2; - } else { - x = obj->x1; - y = obj->y1; - } - - if (x < 0) - x = 0; - if (y < 0) - y = 0; - - int temp; - - temp = x + width; - if (temp >= 319) { - x = 319 - width; - } - temp = y + height; - if (temp >= 136) { - y = 136 - height; - } - - if (restore) { - _screen->copyBlockToPage(_screen->_curPage, x, y, width, height, obj->background); - } else { - _screen->copyRegionToBuffer(_screen->_curPage, x, y, width, height, obj->background); - } -} - -void KyraEngine::prepDrawAllObjects() { - debug(9, "prepDrawAllObjects()"); - AnimObject *curObject = _objectQueue; - int drawPage = 2; - int flagUnk1 = 0, flagUnk2 = 0, flagUnk3 = 0; - if (_noDrawShapesFlag) - return; - if (_brandonStatusBit & 0x20) - flagUnk1 = 0x200; - if (_brandonStatusBit & 0x40) - flagUnk2 = 0x4000; - - while (curObject) { - if (curObject->active) { - int xpos = curObject->x1; - int ypos = curObject->y1; - - int drawLayer = 0; - if (!(curObject->flags & 0x800)) { - drawLayer = 7; - } else if (curObject->unk1) { - drawLayer = 0; - } else { - drawLayer = _sprites->getDrawLayer(curObject->drawY); - } - - // talking head functionallity - if (_talkingCharNum != -1) { - const int16 baseAnimFrameTable1[] = { 0x11, 0x35, 0x59, 0x00, 0x00, 0x00 }; - const int16 baseAnimFrameTable2[] = { 0x15, 0x39, 0x5D, 0x00, 0x00, 0x00 }; - const int8 xOffsetTable1[] = { 2, 4, 0, 5, 2, 0, 0, 0 }; - const int8 xOffsetTable2[] = { 6, 4, 8, 3, 6, 0, 0, 0 }; - const int8 yOffsetTable1[] = { 0, 8, 1, 1, 0, 0, 0, 0 }; - const int8 yOffsetTable2[] = { 0, 8, 1, 1, 0, 0, 0, 0 }; - if (curObject->index == 0 || curObject->index <= 4) { - int shapesIndex = 0; - if (curObject->index == _charSayUnk3) { - shapesIndex = _currHeadShape + baseAnimFrameTable1[curObject->index]; - } else { - shapesIndex = baseAnimFrameTable2[curObject->index]; - int temp2 = 0; - if (curObject->index == 2) { - if (_characterList[2].sceneId == 0x4D || _characterList[2].sceneId == 0x56) { - temp2 = 1; - } else { - temp2 = 0; - } - } else { - temp2 = 1; - } - - if (!temp2) { - shapesIndex = -1; - } - } - - xpos = curObject->x1; - ypos = curObject->y1; - - int tempX = 0, tempY = 0; - if (curObject->flags & 0x1) { - tempX = (xOffsetTable1[curObject->index] * _brandonScaleX) >> 8; - tempY = yOffsetTable1[curObject->index]; - } else { - tempX = (xOffsetTable2[curObject->index] * _brandonScaleX) >> 8; - tempY = yOffsetTable2[curObject->index]; - } - tempY = (tempY * _brandonScaleY) >> 8; - xpos += tempX; - ypos += tempY; - - if (_scaleMode && _brandonScaleX != 256) { - ++xpos; - } - - if (curObject->index == 0) { - if (!(_brandonStatusBit & 2)) { - flagUnk3 = 0x100; - if ((flagUnk1 & 0x200) || (flagUnk2 & 0x4000)) { - flagUnk3 = 0; - } - - int tempFlags = 0; - if (flagUnk3 & 0x100) { - if (curObject->flags & 1) { - tempFlags = 1; - } - tempFlags |= 0x800 | flagUnk1 | 0x100; - } - - if (!(flagUnk3 & 0x100) && (flagUnk2 & 0x4000)) { - tempFlags = 0; - if (curObject->flags & 1) { - tempFlags = 1; - } - tempFlags |= 0x900 | flagUnk1 | 0x4000; - _screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _brandonPoisonFlagsGFX, int(1), int(0)/*XXX*/, drawLayer, _brandonScaleX, _brandonScaleY); - } else { - if (!(flagUnk2 & 0x4000)) { - tempFlags = 0; - if (curObject->flags & 1) { - tempFlags = 1; - } - tempFlags |= 0x900 | flagUnk1; - } - - _screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 4, _brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY); - } - } - } else { - if (shapesIndex != -1) { - int tempFlags = 0; - if (curObject->flags & 1) { - tempFlags = 1; - } - _screen->drawShape(drawPage, _shapes[4+shapesIndex], xpos, ypos, 2, tempFlags | 0x800, drawLayer); - } - } - } - } - - xpos = curObject->x1; - ypos = curObject->y1; - - curObject->flags |= 0x800; - if (curObject->index == 0) { - flagUnk3 = 0x100; - - if (flagUnk1 & 0x200 || flagUnk2 & 0x4000) { - flagUnk3 = 0; - } - - if (_brandonStatusBit & 2) { - curObject->flags &= 0xFFFFFFFE; - } - - if (!_scaleMode) { - if (flagUnk3 & 0x100) { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x100, (uint8*)_brandonPoisonFlagsGFX, int(1), drawLayer); - } else if (flagUnk3 & 0x4000) { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4000, _brandonInvFlag, drawLayer); - } else { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1, drawLayer); - } - } else { - if (flagUnk3 & 0x100) { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x104, (uint8*)_brandonPoisonFlagsGFX, int(1), drawLayer, _brandonScaleX, _brandonScaleY); - } else if (flagUnk3 & 0x4000) { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4004, int(0), drawLayer, _brandonInvFlag, _brandonScaleX, _brandonScaleY); - } else { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | flagUnk1 | 0x4, drawLayer, _brandonScaleX, _brandonScaleY); - } - } - } else { - if (curObject->index >= 16 && curObject->index <= 27) { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags | 4, drawLayer, (int)_scaleTable[curObject->drawY], (int)_scaleTable[curObject->drawY]); - } else { - _screen->drawShape(drawPage, curObject->sceneAnimPtr, xpos, ypos, 2, curObject->flags, drawLayer); - } - } - } - curObject = curObject->nextAnimObject; - } -} - -void KyraEngine::copyChangedObjectsForward(int refreshFlag) { - debug(9, "copyChangedObjectsForward(%d)", refreshFlag); - AnimObject *curObject = _objectQueue; - - while (curObject) { - if (curObject->active) { - if (curObject->refreshFlag || refreshFlag) { - int xpos = 0, ypos = 0, width = 0, height = 0; - xpos = curObject->x1 - (curObject->width2+1); - ypos = curObject->y1 - curObject->height2; - width = (curObject->width + ((curObject->width2)>>3)+2)<<3; - height = curObject->height + curObject->height2*2; - - if (xpos < 8) { - xpos = 8; - } else if (xpos + width > 312) { - width = 312 - xpos; - } - - if (ypos < 8) { - ypos = 8; - } else if (ypos + height > 136) { - height = 136 - ypos; - } - - _screen->copyRegion(xpos, ypos, xpos, ypos, width, height, 2, 0, Screen::CR_CLIPPED); - curObject->refreshFlag = 0; - _updateScreen = true; - } - } - curObject = curObject->nextAnimObject; - } - if (_updateScreen) { - _screen->updateScreen(); - _updateScreen = false; - } -} - -void KyraEngine::updateAllObjectShapes() { - debug(9, "updateAllObjectShapes()"); - restoreAllObjectBackgrounds(); - preserveAnyChangedBackgrounds(); - prepDrawAllObjects(); - copyChangedObjectsForward(0); -} - void KyraEngine::animRefreshNPC(int character) { debug(9, "animRefreshNPC(%d)", character); - AnimObject *animObj = &_charactersAnimState[character]; + AnimObject *animObj = &_animator->actors()[character]; Character *ch = &_characterList[character]; animObj->refreshFlag = 1; @@ -4560,77 +4042,7 @@ void KyraEngine::animRefreshNPC(int character) { animObj->width2 = 4; animObj->height2 = 3; - _objectQueue = objectRemoveQueue(_objectQueue, animObj); - if (_objectQueue) { - _objectQueue = objectQueue(_objectQueue, animObj); - } else { - _objectQueue = objectAddHead(0, animObj); - } -} - -void KyraEngine::animRemoveGameItem(int index) { - debug(9, "animRemoveGameItem(%d)", index); - restoreAllObjectBackgrounds(); - - AnimObject *animObj = &_animItems[index]; - animObj->sceneAnimPtr = 0; - animObj->animFrameNumber = -1; - animObj->refreshFlag = 1; - animObj->bkgdChangeFlag = 1; - updateAllObjectShapes(); - animObj->active = 0; - - objectRemoveQueue(_objectQueue, animObj); -} - -void KyraEngine::animAddGameItem(int index, uint16 sceneId) { - debug(9, "animRemoveGameItem(%d, %d)", index, sceneId); - restoreAllObjectBackgrounds(); - assert(sceneId < _roomTableSize); - Room *currentRoom = &_roomTable[sceneId]; - AnimObject *animObj = &_animItems[index]; - animObj->active = 1; - animObj->refreshFlag = 1; - animObj->bkgdChangeFlag = 1; - animObj->drawY = currentRoom->itemsYPos[index]; - animObj->sceneAnimPtr = _shapes[220+currentRoom->itemsTable[index]]; - animObj->animFrameNumber = -1; - animObj->x1 = currentRoom->itemsXPos[index]; - animObj->y1 = currentRoom->itemsYPos[index]; - animObj->x1 -= fetchAnimWidth(animObj->sceneAnimPtr, _scaleTable[animObj->drawY]) >> 1; - animObj->y1 -= fetchAnimHeight(animObj->sceneAnimPtr, _scaleTable[animObj->drawY]); - animObj->x2 = animObj->x1; - animObj->y2 = animObj->y1; - animObj->width2 = 0; - animObj->height2 = 0; - _objectQueue = objectQueue(_objectQueue, animObj); - preserveAnyChangedBackgrounds(); - animObj->refreshFlag = 1; - animObj->bkgdChangeFlag = 1; -} - -void KyraEngine::animAddNPC(int character) { - debug(9, "animAddNPC(%d)", character); - restoreAllObjectBackgrounds(); - AnimObject *animObj = &_charactersAnimState[character]; - const Character *ch = &_characterList[character]; - - animObj->active = 1; - animObj->refreshFlag = 1; - animObj->bkgdChangeFlag = 1; - animObj->drawY = ch->y1; - animObj->sceneAnimPtr = _shapes[4+ch->currentAnimFrame]; - animObj->x1 = animObj->x2 = ch->x1 + _defaultShapeTable[ch->currentAnimFrame-7].xOffset; - animObj->y1 = animObj->y2 = ch->y1 + _defaultShapeTable[ch->currentAnimFrame-7].yOffset; - if (ch->facing >= 1 && ch->facing <= 3) { - animObj->flags |= 1; - } else if (ch->facing >= 5 && ch->facing <= 7) { - animObj->flags &= 0xFFFFFFFE; - } - _objectQueue = objectQueue(_objectQueue, animObj); - preserveAnyChangedBackgrounds(); - animObj->refreshFlag = 1; - animObj->bkgdChangeFlag = 1; + _animator->refreshObject(animObj); } void KyraEngine::drawJewelPress(int jewel, int drawSpecial) { @@ -4758,88 +4170,19 @@ void KyraEngine::freeShapes123() { void KyraEngine::setBrandonAnimSeqSize(int width, int height) { debug(9, "setBrandonAnimSeqSize(%d, %d)", width, height); - restoreAllObjectBackgrounds(); - _brandonAnimSeqSizeWidth = _charactersAnimState[0].width; - _brandonAnimSeqSizeHeight = _charactersAnimState[0].height; - _charactersAnimState[0].width = width + 1; - _charactersAnimState[0].height = height; - preserveAllBackgrounds(); + _animator->restoreAllObjectBackgrounds(); + _brandonAnimSeqSizeWidth = _animator->actors()[0].width; + _brandonAnimSeqSizeHeight = _animator->actors()[0].height; + _animator->actors()[0].width = width + 1; + _animator->actors()[0].height = height; + _animator->preserveAllBackgrounds(); } void KyraEngine::resetBrandonAnimSeqSize() { - restoreAllObjectBackgrounds(); - _charactersAnimState[0].width = _brandonAnimSeqSizeWidth; - _charactersAnimState[0].height = _brandonAnimSeqSizeHeight; - preserveAllBackgrounds(); -} - -#pragma mark - -#pragma mark - Queue handling -#pragma mark - - -AnimObject *KyraEngine::objectRemoveQueue(AnimObject *queue, AnimObject *rem) { - AnimObject *cur = queue; - AnimObject *prev = queue; - - while (cur != rem && cur) { - AnimObject *temp = cur->nextAnimObject; - if (!temp) - break; - prev = cur; - cur = temp; - } - - if (cur == queue) { - if (!cur) - return 0; - return cur->nextAnimObject; - } - - if (!cur->nextAnimObject) { - if (cur == rem) { - if (!prev) { - return 0; - } else { - prev->nextAnimObject = 0; - } - } - } else { - if (cur == rem) { - prev->nextAnimObject = rem->nextAnimObject; - } - } - - return queue; -} - -AnimObject *KyraEngine::objectAddHead(AnimObject *queue, AnimObject *head) { - head->nextAnimObject = queue; - return head; -} - -AnimObject *KyraEngine::objectQueue(AnimObject *queue, AnimObject *add) { - if (add->drawY <= queue->drawY || !queue) { - add->nextAnimObject = queue; - return add; - } - AnimObject *cur = queue; - AnimObject *prev = queue; - while (add->drawY > cur->drawY) { - AnimObject *temp = cur->nextAnimObject; - if (!temp) - break; - prev = cur; - cur = temp; - } - - if (add->drawY <= cur->drawY) { - prev->nextAnimObject = add; - add->nextAnimObject = cur; - } else { - cur->nextAnimObject = add; - add->nextAnimObject = 0; - } - return queue; + _animator->restoreAllObjectBackgrounds(); + _animator->actors()[0].width = _brandonAnimSeqSizeWidth; + _animator->actors()[0].height = _brandonAnimSeqSizeHeight; + _animator->preserveAllBackgrounds(); } #pragma mark - @@ -4993,7 +4336,7 @@ void KyraEngine::makeBrandonFaceMouse() { _currentCharacter->facing = 5; } animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } void KyraEngine::setBrandonPoisonFlags(int reset) { @@ -5491,7 +4834,7 @@ int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) { *table = 8; _currentCharacter->currentAnimFrame = 7; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); processInput(_mouseX, _mouseY); return 0; } @@ -5546,7 +4889,7 @@ int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) { _sprites->updateSceneAnims(); updateMousePointer(); updateGameTimers(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); updateTextFade(); if (_currentCharacter->sceneId == 210) { // XXX updateKyragemFading @@ -5562,7 +4905,7 @@ int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) { _currentCharacter->currentAnimFrame = 7; } animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); return returnValue; } @@ -5624,7 +4967,7 @@ int KyraEngine::changeScene(int facing) { _currentCharacter->facing = facing; animRefreshNPC(0); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); enterNewScene(sceneId, facing, unk1, unk2, 0); resetGameFlag(0xEE); return 1; @@ -5684,260 +5027,6 @@ int KyraEngine::changeScene(int facing) { } #pragma mark - -#pragma mark - Timer handling -#pragma mark - - -void KyraEngine::setupTimers() { - debug(9, "setupTimers()"); - memset(_timers, 0, sizeof(_timers)); - - for (int i = 0; i < 34; i++) - _timers[i].active = 1; - - _timers[0].func = _timers[1].func = _timers[2].func = _timers[3].func = _timers[4].func = 0; //Unused. - _timers[5].func = _timers[6].func = _timers[7].func = _timers[8].func = _timers[9].func = 0; //_nullsub51; - _timers[10].func = _timers[11].func = _timers[12].func = _timers[13].func = 0; //_nullsub50; - _timers[14].func = &KyraEngine::timerCheckAnimFlag2; //_nullsub52; - _timers[15].func = &KyraEngine::timerUpdateHeadAnims; //_nullsub48; - _timers[16].func = &KyraEngine::timerSetFlags1; //_nullsub47; - _timers[17].func = 0; //sub_15120; - _timers[18].func = &KyraEngine::timerCheckAnimFlag1; //_nullsub53; - _timers[19].func = &KyraEngine::timerRedrawAmulet; //_nullsub54; - _timers[20].func = 0; //offset _timerDummy1 - _timers[21].func = 0; //sub_1517C; - _timers[22].func = 0; //offset _timerDummy2 - _timers[23].func = 0; //offset _timerDummy3, - _timers[24].func = 0; //_nullsub45; - _timers[25].func = 0; //offset _timerDummy4 - _timers[26].func = 0; //_nullsub46; - _timers[27].func = 0; //offset _timerDummy5, - _timers[28].func = 0; //offset _timerDummy6 - _timers[29].func = 0; //offset _timerDummy7, - _timers[30].func = 0; //offset _timerDummy8, - _timers[31].func = &KyraEngine::timerFadeText; //sub_151F8; - _timers[32].func = &KyraEngine::updateAnimFlag1; //_nullsub61; - _timers[33].func = &KyraEngine::updateAnimFlag2; //_nullsub62; - - _timers[0].countdown = _timers[1].countdown = _timers[2].countdown = _timers[3].countdown = _timers[4].countdown = -1; - _timers[5].countdown = 5; - _timers[6].countdown = 7; - _timers[7].countdown = 8; - _timers[8].countdown = 9; - _timers[9].countdown = 7; - _timers[10].countdown = _timers[11].countdown = _timers[12].countdown = _timers[13].countdown = 420; - _timers[14].countdown = 600; - _timers[15].countdown = 11; - _timers[16].countdown = _timers[17].countdown = 7200; - _timers[18].countdown = _timers[19].countdown = 600; - _timers[20].countdown = 7200; - _timers[21].countdown = 18000; - _timers[22].countdown = 7200; - _timers[23].countdown = _timers[24].countdown = _timers[25].countdown = _timers[26].countdown = _timers[27].countdown = 10800; - _timers[28].countdown = 21600; - _timers[29].countdown = 7200; - _timers[30].countdown = 10800; - _timers[31].countdown = -1; - _timers[32].countdown = 9; - _timers[33].countdown = 3; -} - -void KyraEngine::updateGameTimers() { - debug(9, "updateGameTimers()"); - - if (_system->getMillis() < _timerNextRun) - return; - - _timerNextRun += 99999; - - for (int i = 0; i < 34; i++) { - if (_timers[i].active && _timers[i].countdown > -1) { - if (_timers[i].nextRun <=_system->getMillis()) { - if (i > 4 && _timers[i].func) - (*this.*_timers[i].func)(i); - - _timers[i].nextRun = _system->getMillis() + _timers[i].countdown * _tickLength; - - } - } - if (_timers[i].nextRun < _timerNextRun) - _timerNextRun = _timers[i].nextRun; - } -} - -void KyraEngine::clearNextEventTickCount() { - debug(9, "clearNextEventTickCount()"); - _timerNextRun = 0; -} - -void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) { - debug(9, "setTimerDelay(%i, %d)", timer, countdown); - _timers[timer].countdown = countdown; -} - -int16 KyraEngine::getTimerDelay(uint8 timer) { - debug(9, "getTimerDelay(%i)", timer); - return _timers[timer].countdown; -} - -void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) { - debug(9, "setTimerCountdown(%i, %i)", timer, countdown); - _timers[timer].countdown = countdown; - - uint32 nextRun = _system->getMillis() + countdown; - if (nextRun < _timerNextRun) - _timerNextRun = nextRun; -} - -void KyraEngine::enableTimer(uint8 timer) { - debug(9, "enableTimer(%i)", timer); - _timers[timer].active = 1; -} - -void KyraEngine::disableTimer(uint8 timer) { - debug(9, "disableTimer(%i)", timer); - _timers[timer].active = 0; -} - -void KyraEngine::timerUpdateHeadAnims(int timerNum) { - debug(9, "timerUpdateHeadAnims(%i)", timerNum); - static int8 currentFrame = 0; - static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5, - 4, 4, 6, 4, 8, 1, 9, 4, -1}; - - if (_talkingCharNum < 0) - return; - - _currHeadShape = frameTable[currentFrame]; - currentFrame++; - - if (frameTable[currentFrame] == -1) - currentFrame = 0; - - animRefreshNPC(0); - animRefreshNPC(_talkingCharNum); -} - -void KyraEngine::timerSetFlags1(int timerNum) { - debug(9, "timerSetFlags(%i)", timerNum); - if (_currentCharacter->sceneId == 0x1C) - return; - - int rndNr = _rnd.getRandomNumberRng(0, 3); - - for (int i = 0; i < 4; i++) { - if (!queryGameFlag(rndNr + 17)) { - setGameFlag(rndNr + 17); - break; - } else { - rndNr++; - if (rndNr > 3) - rndNr = 0; - } - } -} - -void KyraEngine::timerFadeText(int timerNum) { - debug(9, "timerFadeText(%i)", timerNum); - _fadeText = true; -} - -void KyraEngine::updateAnimFlag1(int timerNum) { - debug(9, "updateAnimFlag1(%d)", timerNum); - if (_brandonStatusBit & 2) { - _brandonStatusBit0x02Flag = 1; - } -} - -void KyraEngine::updateAnimFlag2(int timerNum) { - debug(9, "updateAnimFlag2(%d)", timerNum); - if (_brandonStatusBit & 0x20) { - _brandonStatusBit0x20Flag = 1; - } -} - -void KyraEngine::setTextFadeTimerCountdown(int16 countdown) { - debug(9, "setTextFadeTimerCountdown(%i)", countdown); - //if (countdown == -1) - //countdown = 32000; - - setTimerCountdown(31, countdown*60); -} - -void KyraEngine::timerSetFlags2(int timerNum) { - debug(9, "timerSetFlags2(%i)", timerNum); - if (!((uint32*)(_flagsTable+0x2D))[timerNum]) - ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; -} - -void KyraEngine::timerCheckAnimFlag1(int timerNum) { - debug(9, "timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x20) { - checkAmuletAnimFlags(); - setTimerCountdown(18, -1); - } -} - -void KyraEngine::timerCheckAnimFlag2(int timerNum) { - debug(9, "timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x2) { - checkAmuletAnimFlags(); - setTimerCountdown(14, -1); - } -} - -void KyraEngine::checkAmuletAnimFlags() { - debug(9, "checkSpecialAnimFlags()"); - if (_brandonStatusBit & 2) { - seq_makeBrandonNormal2(); - setTimerCountdown(19, 300); - } - - if (_brandonStatusBit & 0x20) { - seq_makeBrandonNormal(); - setTimerCountdown(19, 300); - } -} - -void KyraEngine::timerRedrawAmulet(int timerNum) { - debug(9, "timerRedrawAmulet(%i)", timerNum); - if (queryGameFlag(0xF1)) { - drawAmulet(); - setTimerCountdown(19, -1); - } -} - -void KyraEngine::drawAmulet() { - debug(9, "drawAmulet()"); - static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1}; - static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1}; - static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1}; - static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1}; - - resetGameFlag(0xF1); - _screen->hideMouse(); - - int i = 0; - while (amuletTable1[i] != -1) { - if (queryGameFlag(87)) - _screen->drawShape(0, _shapes[4+amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0); - - if (queryGameFlag(89)) - _screen->drawShape(0, _shapes[4+amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0); - - if (queryGameFlag(86)) - _screen->drawShape(0, _shapes[4+amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0); - - if (queryGameFlag(88)) - _screen->drawShape(0, _shapes[4+amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0); - - _screen->updateScreen(); - delayWithTicks(3); - i++; - } - _screen->showMouse(); -} - -#pragma mark - #pragma mark - Input #pragma mark - @@ -6007,7 +5096,7 @@ int KyraEngine::processInputHelper(int xpos, int ypos) { if (item != 0xFF) { if (_itemInHand == -1) { _screen->hideMouse(); - animRemoveGameItem(item); + _animator->animRemoveGameItem(item); // XXX call kyraPlaySound(53) assert(_currentCharacter->sceneId < _roomTableSize); Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; @@ -6401,275 +5490,4 @@ void KyraEngine::saveGame(const char *fileName, const char *saveName) { delete out; } - -#pragma mark - -#pragma mark - Button handling -#pragma mark - - -Button *KyraEngine::initButton(Button *list, Button *newButton) { - if (!newButton) - return list; - if (!list) - return newButton; - Button *cur = list; - while (true) { - if (!cur->nextButton) { - break; - } - cur = cur->nextButton; - } - cur->nextButton = newButton; - return list; -} - -int KyraEngine::buttonInventoryCallback(Button *caller) { - int itemOffset = caller->specialValue - 2; - uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset]; - if (_itemInHand == -1) { - if (inventoryItem == 0xFF) { - // snd_playSoundEffect(0x36); - return 0; - } else { - _screen->hideMouse(); - _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); - // snd_playSoundEffect(0x35); - setMouseItem(inventoryItem); - updateSentenceCommand(_itemList[inventoryItem], _takenList[0], 179); - _itemInHand = inventoryItem; - _screen->showMouse(); - _currentCharacter->inventoryItems[itemOffset] = 0xFF; - } - } else { - if (inventoryItem != 0xFF) { - // snd_playSoundEffect(0x35); - _screen->hideMouse(); - _screen->fillRect(_itemPosX[itemOffset], _itemPosY[itemOffset], _itemPosX[itemOffset] + 15, _itemPosY[itemOffset] + 15, 12); - _screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); - setMouseItem(inventoryItem); - updateSentenceCommand(_itemList[inventoryItem], _takenList[1], 179); - _screen->showMouse(); - _currentCharacter->inventoryItems[itemOffset] = _itemInHand; - _itemInHand = inventoryItem; - } else { - // snd_playSoundEffect(0x32); - _screen->hideMouse(); - _screen->drawShape(0, _shapes[220+_itemInHand], _itemPosX[itemOffset], _itemPosY[itemOffset], 0, 0); - _screen->setMouseCursor(1, 1, _shapes[4]); - updateSentenceCommand(_itemList[_itemInHand], _placedList[0], 179); - _screen->showMouse(); - _currentCharacter->inventoryItems[itemOffset] = _itemInHand; - _itemInHand = -1; - } - } - _screen->updateScreen(); - // XXX clearKyrandiaButtonIO - return 0; -} - -int KyraEngine::buttonAmuletCallback(Button *caller) { - if (!(_deathHandler & 8)) - return 1; - int jewel = caller->specialValue - 0x14; - if (_currentCharacter->sceneId == 210) { - //if (_unkSceneVar == 4 || _unkSceneVar == 6) - // return 1; - } - if (!queryGameFlag(0x2D)) - return 1; - if (_itemInHand != -1) { - assert(_putDownFirst); - characterSays(_putDownFirst[0], 0, -2); - return 1; - } - if (queryGameFlag(0xF1)) { - assert(_waitForAmulet); - characterSays(_waitForAmulet[0], 0, -2); - return 1; - } - if (!queryGameFlag(0x55+jewel)) { - assert(_blackJewel); - makeBrandonFaceMouse(); - drawJewelPress(jewel, 1); - characterSays(_blackJewel[0], 0, -2); - return 1; - } - drawJewelPress(jewel, 0); - drawJewelsFadeOutStart(); - drawJewelsFadeOutEnd(jewel); - - _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->variables[3] = 0; - _scriptClick->variables[6] = jewel; - _scriptInterpreter->startScript(_scriptClick, 4); - - while (_scriptInterpreter->validScript(_scriptClick)) { - _scriptInterpreter->runScript(_scriptClick); - } - - if (_scriptClick->variables[3]) - return 1; - - _unkAmuletVar = 1; - switch (jewel-1) { - case 0: - if (_brandonStatusBit & 1) { - seq_brandonHealing2(); - } else if (_brandonStatusBit == 0) { - seq_brandonHealing(); - assert(_healingTip); - characterSays(_healingTip[0], 0, -2); - } - break; - - case 1: - seq_makeBrandonInv(); - break; - - case 2: - if (_brandonStatusBit & 1) { - assert(_wispJewelStrings); - characterSays(_wispJewelStrings[0], 0, -2); - } else { - if (_brandonStatusBit & 2) { - // XXX - seq_makeBrandonNormal2(); - // XXX - } else { - // do not check for item in hand again as in the original since some strings are missing - // in the cd version - if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) { - // XXX - seq_makeBrandonWisp(); - // XXX - } else { - seq_makeBrandonWisp(); - } - setGameFlag(0x9E); - } - } - break; - - case 3: - seq_dispelMagicAnimation(); - assert(_magicJewelString); - characterSays(_magicJewelString[0], 0, -2); - break; - - default: - break; - } - _unkAmuletVar = 0; - // XXX clearKyrandiaButtonIO (!used before every return in this function!) - return 1; -} - -void KyraEngine::processButtonList(Button *list) { - while (list) { - if (list->flags & 8) { - list = list->nextButton; - continue; - } - - int x = list->x; - int y = list->y; - assert(list->dimTableIndex < _screen->_screenDimTableCount); - if (x < 0) { - x += _screen->_screenDimTable[list->dimTableIndex].w << 3; - } - x += _screen->_screenDimTable[list->dimTableIndex].sx << 3; - - if (y < 0) { - y += _screen->_screenDimTable[list->dimTableIndex].h; - } - y += _screen->_screenDimTable[list->dimTableIndex].sy; - - if (_mouseX >= x && _mouseY >= y && x + list->width >= _mouseX && y + list->height >= _mouseY) { - int processMouseClick = 0; - if (list->flags & 0x400) { - if (_mousePressFlag) { - if (!(list->flags2 & 1)) { - list->flags2 |= 1; - processButton(list); - } - } else { - if (list->flags2 & 1) { - list->flags2 &= 0xFFFE; - processButton(list); - processMouseClick = 1; - } - } - } else if (_mousePressFlag) { - processMouseClick = 1; - } - - if (processMouseClick) { - if (list->buttonCallback) { - if ((this->*(list->buttonCallback))(list)) { - break; - } - } - } - } else { - if (list->flags2 & 1) { - list->flags2 &= 0xFFFE; - processButton(list); - } - list = list->nextButton; - continue; - } - - list = list->nextButton; - } -} - -void KyraEngine::processButton(Button *button) { - if (!button) - return; - - int processType = 0; - uint8 *shape = 0; - Button::ButtonCallback callback = 0; - - int flags = (button->flags2 & 5); - if (flags == 1) { - processType = button->process2; - if (processType == 1) { - shape = button->process2PtrShape; - } else if (processType == 4) { - callback = button->process2PtrCallback; - } - } else if (flags == 4 || flags == 5) { - processType = button->process1; - if (processType == 1) { - shape = button->process1PtrShape; - } else if (processType == 4) { - callback = button->process1PtrCallback; - } - } else { - processType = button->process0; - if (processType == 1) { - shape = button->process0PtrShape; - } else if (processType == 4) { - callback = button->process0PtrCallback; - } - } - - int x = button->x; - int y = button->y; - assert(button->dimTableIndex < _screen->_screenDimTableCount); - if (x < 0) { - x += _screen->_screenDimTable[button->dimTableIndex].w << 3; - } - - if (y < 0) { - y += _screen->_screenDimTable[button->dimTableIndex].h; - } - - if (processType == 1 && shape) { - _screen->drawShape(_screen->_curPage, shape, x, y, button->dimTableIndex, 0x10); - } else if (processType == 4 && callback) { - (this->*callback)(button); - } -} - } // End of namespace Kyra diff --git a/kyra/kyra.h b/kyra/kyra.h index 6cdf4a1116..1b41ccb3d5 100644 --- a/kyra/kyra.h +++ b/kyra/kyra.h @@ -78,36 +78,11 @@ struct Room { uint32 unkField3[12]; }; -struct AnimObject { - uint8 index; - uint32 active; - uint32 refreshFlag; - uint32 bkgdChangeFlag; - uint32 unk1; - uint32 flags; - int16 drawY; - uint8 *sceneAnimPtr; - int16 animFrameNumber; - uint8 *background; - uint16 rectSize; - int16 x1, y1; - int16 x2, y2; - uint16 width; - uint16 height; - uint16 width2; - uint16 height2; - AnimObject *nextAnimObject; -}; - struct Rect { int x, y; int x2, y2; }; -struct TalkCoords { - uint16 y, x, w; -}; - struct Item { uint8 unk1; uint8 height; @@ -143,6 +118,8 @@ struct ScriptState; struct ScriptData; class ScriptHelper; class Debugger; +class ScreenAnimator; +class TextDisplayer; class KyraEngine; struct Timer { @@ -183,14 +160,10 @@ struct Button { class KyraEngine : public Engine { friend class MusicPlayer; friend class Debugger; + friend class ScreenAnimator; public: enum { - TALK_SUBSTRING_LEN = 80, - TALK_SUBSTRING_NUM = 3 - }; - - enum { MUSIC_INTRO = 0 }; @@ -201,6 +174,8 @@ public: Resource *resource() { return _res; } Screen *screen() { return _screen; } + ScreenAnimator *animator() { return _animator; } + TextDisplayer *text() { return _text; } MusicPlayer *midi() { return _midi; } Movie *createWSAMovie(); @@ -234,8 +209,6 @@ public: bool snd_voicePlaying(); void snd_playSoundEffect(int track); - void printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage); - void restoreTalkTextMessageBkgd(int srcPage, int dstPage); void drawSentenceCommand(char *sentence, int unk1); void updateSentenceCommand(char *str1, char *str2, int unk1); void updateTextFade(); @@ -250,8 +223,6 @@ public: void waitTicks(int ticks); void delayWithTicks(int ticks); - void updateAllObjectShapes(); - void flagAllObjectsForRefresh(); void animRefreshNPC(int character); int16 fetchAnimWidth(const uint8 *shape, int16 mult); int16 fetchAnimHeight(const uint8 *shape, int16 mult); @@ -426,23 +397,13 @@ protected: void startup(); void mainLoop(); - void setTalkCoords(uint16 y); - int getCenterStringX(const char *str, int x1, int x2); - int getCharLength(const char *str, int len); - int dropCRIntoString(char *str, int offs); - char *preprocessString(const char *str); - int buildMessageSubstrings(const char *str); - int getWidestLineWidth(int linesCount); - void calcWidestLineBounds(int &x1, int &x2, int w, int cx); - void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2); - void characterSays(char *msg, int8 charNum, int8 chatDuration); int initCharacterChat(int8 charNum); int8 getChatPartnerNum(); void backupChatPartnerAnimFrame(int8 charNum); void restoreChatPartnerAnimFrame(int8 charNum); void endCharacterChat(int8 charNum, int16 arg_4); void waitForChatToFinish(int16 chatDuration, char *str, uint8 charNum); - void printCharacterText(char *text, int8 charNum); + void characterSays(char *chatStr, int8 charNum, int8 chatDuration); void setCharacterDefaultFrame(int character); void setCharactersPositions(int character); @@ -472,13 +433,6 @@ protected: void placeItemInGenericMapScene(int item, int index); void initSceneObjectList(int brandonAlive); void initSceneScreen(int brandonAlive); - void preserveAllBackgrounds(); - void flagAllObjectsForBkgdChange(); - void restoreAllObjectBackgrounds(); - void preserveAnyChangedBackgrounds(); - void preserveOrRestoreBackground(AnimObject *obj, bool restore); - void prepDrawAllObjects(); - void copyChangedObjectsForward(int refreshFlag); int findDuplicateItemShape(int shape); int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end); @@ -533,9 +487,6 @@ protected: void updatePlayerItemsForScene(); void redrawInventory(int page); - void animRemoveGameItem(int index); - void animAddGameItem(int index, uint16 sceneId); - void animAddNPC(int character); void drawJewelPress(int jewel, int drawSpecial); void drawJewelsFadeOutStart(); void drawJewelsFadeOutEnd(int jewel); @@ -544,11 +495,6 @@ protected: void setBrandonAnimSeqSize(int width, int height); void resetBrandonAnimSeqSize(); - AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem); - AnimObject *objectAddHead(AnimObject *queue, AnimObject *head); - AnimObject *objectQueue(AnimObject *queue, AnimObject *add); - AnimObject *_animStates; - void seq_demo(); void seq_intro(); void seq_introLogos(); @@ -637,12 +583,6 @@ protected: bool _abortWalkFlag; bool _abortWalkFlag2; bool _mousePressFlag; - char _talkBuffer[300]; - char _talkSubstrings[TALK_SUBSTRING_LEN * TALK_SUBSTRING_NUM]; - TalkCoords _talkCoords; - uint16 _talkMessageY; - uint16 _talkMessageH; - bool _talkMessagePrinted; uint8 _flagsTable[53]; uint8 *_unkPtr1, *_unkPtr2; uint8 *_hidPage, *_screenPage; @@ -654,10 +594,8 @@ protected: int8 _itemInHand; int _mouseState; bool _handleInput; - bool _updateScreen; bool _changedScene; int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; - int _noDrawShapesFlag; int _unkAmuletVar; int _brandonAnimSeqSizeWidth; @@ -688,7 +626,7 @@ protected: uint16 _brandonStatusBit; int _brandonStatusBit0x02Flag; int _brandonStatusBit0x20Flag; - uint8 _brandonPoisonFlagsGFX[256]; // this seem not to be posion flags, it is used for drawing once + uint8 _brandonPoisonFlagsGFX[256]; uint8 _deathHandler; int _brandonInvFlag; int8 _poisonDeathCounter; @@ -731,9 +669,6 @@ protected: bool _fadeText; uint8 _configTalkspeed; - AnimObject *_objectQueue; - AnimObject *_charactersAnimState; - AnimObject *_animItems; int _curMusicTheme; int _newMusicTheme; @@ -742,9 +677,11 @@ protected: Resource *_res; Screen *_screen; + ScreenAnimator *_animator; MusicPlayer *_midi; SeqPlayer *_seq; Sprites *_sprites; + TextDisplayer *_text; ScriptHelper *_scriptInterpreter; Debugger *_debugger; Common::SaveFileManager *_saveFileMan; diff --git a/kyra/module.mk b/kyra/module.mk index ed33f27ba6..75568213eb 100644 --- a/kyra/module.mk +++ b/kyra/module.mk @@ -11,7 +11,11 @@ MODULE_OBJS := \ kyra/staticres.o \ kyra/sprites.o \ kyra/wsamovie.o \ - kyra/debugger.o + kyra/debugger.o \ + kyra/animator.o \ + kyra/gui.o \ + kyra/text.o \ + kyra/timer.o MODULE_DIRS += \ kyra diff --git a/kyra/script.cpp b/kyra/script.cpp index ad9d853eed..c374b007ee 100644 --- a/kyra/script.cpp +++ b/kyra/script.cpp @@ -294,4 +294,271 @@ bool ScriptHelper::loadIFFBlock(byte *start, byte *&data, uint32 maxSize, const } return false; } + +#pragma mark - +#pragma mark - Command implementations +#pragma mark - + +void ScriptHelper::c1_jmpTo() { + _curScript->ip = _curScript->dataPtr->data + (_parameter << 1); +} + +void ScriptHelper::c1_setRetValue() { + _curScript->retValue = _parameter; +} + +void ScriptHelper::c1_pushRetOrPos() { + switch (_parameter) { + case 0: + _curScript->stack[--_curScript->sp] = _curScript->retValue; + break; + + case 1: + _curScript->stack[--_curScript->sp] = (_curScript->ip - _curScript->dataPtr->data) / 2 + 1; + _curScript->stack[--_curScript->sp] = _curScript->bp; + _curScript->bp = _curScript->sp + 2; + break; + + default: + _continue = false; + _curScript->ip = 0; + break; + } +} + +void ScriptHelper::c1_push() { + _curScript->stack[--_curScript->sp] = _parameter; +} + +void ScriptHelper::c1_pushVar() { + _curScript->stack[--_curScript->sp] = _curScript->variables[_parameter]; +} + +void ScriptHelper::c1_pushBPNeg() { + _curScript->stack[--_curScript->sp] = _curScript->stack[(-(int32)(_parameter + 2)) + _curScript->bp]; +} + +void ScriptHelper::c1_pushBPAdd() { + _curScript->stack[--_curScript->sp] = _curScript->stack[(_parameter - 1) + _curScript->bp]; +} + +void ScriptHelper::c1_popRetOrPos() { + switch (_parameter) { + case 0: + _curScript->retValue = _curScript->stack[_curScript->sp++]; + break; + + case 1: + if (_curScript->sp >= 60) { + _continue = false; + _curScript->ip = 0; + } else { + _curScript->bp = _curScript->stack[_curScript->sp++]; + _curScript->ip = _curScript->dataPtr->data + (_curScript->stack[_curScript->sp++] << 1); + } + break; + + default: + _continue = false; + _curScript->ip = 0; + break; + } +} + +void ScriptHelper::c1_popVar() { + _curScript->variables[_parameter] = _curScript->stack[_curScript->sp++]; +} + +void ScriptHelper::c1_popBPNeg() { + _curScript->stack[(-(int32)(_parameter + 2)) + _curScript->bp] = _curScript->stack[_curScript->sp++]; +} + +void ScriptHelper::c1_popBPAdd() { + _curScript->stack[(_parameter - 1) + _curScript->bp] = _curScript->stack[_curScript->sp++]; +} + +void ScriptHelper::c1_addSP() { + _curScript->sp += _parameter; +} + +void ScriptHelper::c1_subSP() { + _curScript->sp -= _parameter; +} + +void ScriptHelper::c1_execOpcode() { + assert((uint8)_parameter < _curScript->dataPtr->opcodeSize); + if (_curScript->dataPtr->opcodes[(uint8)_parameter] == &KyraEngine::cmd_dummy) + debug("calling unimplemented opcode(0x%.02X)", (uint8)_parameter); + _curScript->retValue = (_vm->*_curScript->dataPtr->opcodes[(uint8)_parameter])(_curScript); +} + +void ScriptHelper::c1_ifNotJmp() { + if (!_curScript->stack[_curScript->sp++]) { + _parameter &= 0x7FFF; + _curScript->ip = _curScript->dataPtr->data + (_parameter << 1); + } +} + +void ScriptHelper::c1_negate() { + int16 value = _curScript->stack[_curScript->sp]; + switch (_parameter) { + case 0: + if (!value) { + _curScript->stack[_curScript->sp] = 1; + } else { + _curScript->stack[_curScript->sp] = 0; + } + break; + + case 1: + _curScript->stack[_curScript->sp] = -value; + break; + + case 2: + _curScript->stack[_curScript->sp] = ~value; + break; + + default: + _continue = false; + break; + } +} + +void ScriptHelper::c1_eval() { + int16 ret = 0; + bool error = false; + + int16 val1 = _curScript->stack[_curScript->sp++]; + int16 val2 = _curScript->stack[_curScript->sp++]; + + switch (_parameter) { + case 0: + if (!val2 || !val1) { + ret = 0; + } else { + ret = 1; + } + break; + + case 1: + if (val2 || val1) { + ret = 1; + } else { + ret = 0; + } + break; + + case 2: + if (val1 == val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 3: + if (val1 != val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 4: + if (val1 > val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 5: + if (val1 >= val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 6: + if (val1 < val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 7: + if (val1 <= val2) { + ret = 1; + } else { + ret = 0; + } + break; + + case 8: + ret = val1 + val2; + break; + + case 9: + ret = val2 - val1; + break; + + case 10: + ret = val1 * val2; + break; + + case 11: + ret = val2 / val1; + break; + + case 12: + ret = val2 >> val1; + break; + + case 13: + ret = val2 << val1; + break; + + case 14: + ret = val1 & val2; + break; + + case 15: + ret = val1 | val2; + break; + + case 16: + ret = val2 % val1; + break; + + case 17: + ret = val1 ^ val2; + break; + + default: + warning("Unknown evaluate func: %d", _parameter); + error = true; + break; + } + + if (error) { + _curScript->ip = 0; + _continue = false; + } else { + _curScript->stack[--_curScript->sp] = ret; + } +} + +void ScriptHelper::c1_setRetAndJmp() { + if (_curScript->sp >= 60) { + _continue = false; + _curScript->ip = 0; + } else { + _curScript->retValue = _curScript->stack[_curScript->sp++]; + uint16 temp = _curScript->stack[_curScript->sp++]; + _curScript->stack[60] = 0; + _curScript->ip = &_curScript->dataPtr->data[temp*2]; + } +} } // end of namespace Kyra diff --git a/kyra/script_v1.cpp b/kyra/script_v1.cpp index e8c078faf0..d3aa3a8d8c 100644 --- a/kyra/script_v1.cpp +++ b/kyra/script_v1.cpp @@ -25,277 +25,11 @@ #include "kyra/screen.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" +#include "kyra/animator.h" +#include "kyra/text.h" #include "common/system.h" namespace Kyra { - -void ScriptHelper::c1_jmpTo() { - _curScript->ip = _curScript->dataPtr->data + (_parameter << 1); -} - -void ScriptHelper::c1_setRetValue() { - _curScript->retValue = _parameter; -} - -void ScriptHelper::c1_pushRetOrPos() { - switch (_parameter) { - case 0: - _curScript->stack[--_curScript->sp] = _curScript->retValue; - break; - - case 1: - _curScript->stack[--_curScript->sp] = (_curScript->ip - _curScript->dataPtr->data) / 2 + 1; - _curScript->stack[--_curScript->sp] = _curScript->bp; - _curScript->bp = _curScript->sp + 2; - break; - - default: - _continue = false; - _curScript->ip = 0; - break; - } -} - -void ScriptHelper::c1_push() { - _curScript->stack[--_curScript->sp] = _parameter; -} - -void ScriptHelper::c1_pushVar() { - _curScript->stack[--_curScript->sp] = _curScript->variables[_parameter]; -} - -void ScriptHelper::c1_pushBPNeg() { - _curScript->stack[--_curScript->sp] = _curScript->stack[(-(int32)(_parameter + 2)) + _curScript->bp]; -} - -void ScriptHelper::c1_pushBPAdd() { - _curScript->stack[--_curScript->sp] = _curScript->stack[(_parameter - 1) + _curScript->bp]; -} - -void ScriptHelper::c1_popRetOrPos() { - switch (_parameter) { - case 0: - _curScript->retValue = _curScript->stack[_curScript->sp++]; - break; - - case 1: - if (_curScript->sp >= 60) { - _continue = false; - _curScript->ip = 0; - } else { - _curScript->bp = _curScript->stack[_curScript->sp++]; - _curScript->ip = _curScript->dataPtr->data + (_curScript->stack[_curScript->sp++] << 1); - } - break; - - default: - _continue = false; - _curScript->ip = 0; - break; - } -} - -void ScriptHelper::c1_popVar() { - _curScript->variables[_parameter] = _curScript->stack[_curScript->sp++]; -} - -void ScriptHelper::c1_popBPNeg() { - _curScript->stack[(-(int32)(_parameter + 2)) + _curScript->bp] = _curScript->stack[_curScript->sp++]; -} - -void ScriptHelper::c1_popBPAdd() { - _curScript->stack[(_parameter - 1) + _curScript->bp] = _curScript->stack[_curScript->sp++]; -} - -void ScriptHelper::c1_addSP() { - _curScript->sp += _parameter; -} - -void ScriptHelper::c1_subSP() { - _curScript->sp -= _parameter; -} - -void ScriptHelper::c1_execOpcode() { - assert((uint8)_parameter < _curScript->dataPtr->opcodeSize); - if (_curScript->dataPtr->opcodes[(uint8)_parameter] == &KyraEngine::cmd_dummy) - debug("calling unimplemented opcode(0x%.02X)", (uint8)_parameter); - _curScript->retValue = (_vm->*_curScript->dataPtr->opcodes[(uint8)_parameter])(_curScript); -} - -void ScriptHelper::c1_ifNotJmp() { - if (!_curScript->stack[_curScript->sp++]) { - _parameter &= 0x7FFF; - _curScript->ip = _curScript->dataPtr->data + (_parameter << 1); - } -} - -void ScriptHelper::c1_negate() { - int16 value = _curScript->stack[_curScript->sp]; - switch (_parameter) { - case 0: - if (!value) { - _curScript->stack[_curScript->sp] = 1; - } else { - _curScript->stack[_curScript->sp] = 0; - } - break; - - case 1: - _curScript->stack[_curScript->sp] = -value; - break; - - case 2: - _curScript->stack[_curScript->sp] = ~value; - break; - - default: - _continue = false; - break; - } -} - -void ScriptHelper::c1_eval() { - int16 ret = 0; - bool error = false; - - int16 val1 = _curScript->stack[_curScript->sp++]; - int16 val2 = _curScript->stack[_curScript->sp++]; - - switch (_parameter) { - case 0: - if (!val2 || !val1) { - ret = 0; - } else { - ret = 1; - } - break; - - case 1: - if (val2 || val1) { - ret = 1; - } else { - ret = 0; - } - break; - - case 2: - if (val1 == val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 3: - if (val1 != val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 4: - if (val1 > val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 5: - if (val1 >= val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 6: - if (val1 < val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 7: - if (val1 <= val2) { - ret = 1; - } else { - ret = 0; - } - break; - - case 8: - ret = val1 + val2; - break; - - case 9: - ret = val2 - val1; - break; - - case 10: - ret = val1 * val2; - break; - - case 11: - ret = val2 / val1; - break; - - case 12: - ret = val2 >> val1; - break; - - case 13: - ret = val2 << val1; - break; - - case 14: - ret = val1 & val2; - break; - - case 15: - ret = val1 | val2; - break; - - case 16: - ret = val2 % val1; - break; - - case 17: - ret = val1 ^ val2; - break; - - default: - warning("Unknown evaluate func: %d", _parameter); - error = true; - break; - } - - if (error) { - _curScript->ip = 0; - _continue = false; - } else { - _curScript->stack[--_curScript->sp] = ret; - } -} - -void ScriptHelper::c1_setRetAndJmp() { - if (_curScript->sp >= 60) { - _continue = false; - _curScript->ip = 0; - } else { - _curScript->retValue = _curScript->stack[_curScript->sp++]; - uint16 temp = _curScript->stack[_curScript->sp++]; - _curScript->stack[60] = 0; - _curScript->ip = &_curScript->dataPtr->data[temp*2]; - } -} - -#pragma mark - -#pragma mark - Opcode implementations -#pragma mark - - #define stackPos(x) script->stack[script->sp+x] #define stackPosString(x) (char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])] @@ -431,8 +165,8 @@ int KyraEngine::cmd_dropItemInScene(ScriptState *script) { room->itemsYPos[freeItem] = ypos; room->itemsTable[freeItem] = item; - animAddGameItem(freeItem, sceneId); - updateAllObjectShapes(); + _animator->animAddGameItem(freeItem, sceneId); + _animator->updateAllObjectShapes(); } else { if (item == 43) { placeItemInGenericMapScene(item, 0); @@ -446,17 +180,17 @@ int KyraEngine::cmd_dropItemInScene(ScriptState *script) { int KyraEngine::cmd_drawAnimShapeIntoScene(ScriptState *script) { debug(3, "cmd_drawAnimShapeIntoScene(0x%X) (%d, %d, %d, %d)", stackPos(0), stackPos(1), stackPos(2), stackPos(3)); _screen->hideMouse(); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); int shape = stackPos(0); int xpos = stackPos(1); int ypos = stackPos(2); int flags = (stackPos(3) != 0) ? 1 : 0; _screen->drawShape(2, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); _screen->drawShape(0, _sprites->_sceneShapes[shape], xpos, ypos, 0, flags); - flagAllObjectsForBkgdChange(); - preserveAnyChangedBackgrounds(); - flagAllObjectsForRefresh(); - updateAllObjectShapes(); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); + _animator->flagAllObjectsForRefresh(); + _animator->updateAllObjectShapes(); _screen->showMouse(); return 0; } @@ -506,16 +240,16 @@ int KyraEngine::cmd_destroyMouseItem(ScriptState *script) { int KyraEngine::cmd_runSceneAnimUntilDone(ScriptState *script) { debug(3, "cmd_runSceneAnimUntilDone(0x%X) (%d)", script, stackPos(0)); _sprites->_anims[stackPos(0)].play = true; - _sprites->_animObjects[stackPos(0)].active = 1; + _animator->sprites()[stackPos(0)].active = 1; _screen->hideMouse(); - restoreAllObjectBackgrounds(); - flagAllObjectsForBkgdChange(); - preserveAnyChangedBackgrounds(); + _animator->restoreAllObjectBackgrounds(); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); while (_sprites->_anims[stackPos(0)].play) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); _screen->showMouse(); return 0; } @@ -636,7 +370,7 @@ int KyraEngine::cmd_magicOutMouseItem(ScriptState *script) { int KyraEngine::cmd_internalAnimOn(ScriptState *script) { debug(3, "cmd_internalAnimOn(0x%X) (%d)", script, stackPos(0)); - _sprites->_animObjects[stackPos(0)].active = 1; + _animator->sprites()[stackPos(0)].active = 1; return 0; } @@ -715,7 +449,7 @@ int KyraEngine::cmd_runWSAFromBeginningToEnd(ScriptState *script) { _movieObjects[wsaIndex]->_drawPage = 0; while (running) { _movieObjects[wsaIndex]->displayFrame(wsaFrame++); - _updateScreen = true; + _animator->_updateScreen = true; if (wsaFrame >= _movieObjects[wsaIndex]->frames()) running = false; @@ -723,7 +457,7 @@ int KyraEngine::cmd_runWSAFromBeginningToEnd(ScriptState *script) { while (_system->getMillis() < continueTime) { if (worldUpdate) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } else { _screen->updateScreen(); } @@ -751,10 +485,10 @@ int KyraEngine::cmd_displayWSAFrame(ScriptState *script) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); delay(10); } - _updateScreen = true; + _animator->_updateScreen = true; _screen->showMouse(); return 0; } @@ -793,7 +527,7 @@ int KyraEngine::cmd_popBrandonIntoScene(ScriptState *script) { int yOffset = _defaultShapeTable[0].yOffset; int width = _defaultShapeTable[0].w << 3; int height = _defaultShapeTable[0].h; - AnimObject *curAnim = _charactersAnimState; + AnimObject *curAnim = _animator->actors(); if (changeScaleMode) { curAnim->x1 = _currentCharacter->x1; @@ -820,9 +554,9 @@ int KyraEngine::cmd_popBrandonIntoScene(ScriptState *script) { } animRefreshNPC(0); - preserveAllBackgrounds(); - prepDrawAllObjects(); - copyChangedObjectsForward(0); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); + _animator->copyChangedObjectsForward(0); _scaleMode = scaleModeBackup; @@ -831,7 +565,7 @@ int KyraEngine::cmd_popBrandonIntoScene(ScriptState *script) { int KyraEngine::cmd_restoreAllObjectBackgrounds(ScriptState *script) { debug(3, "cmd_restoreAllObjectBackgrounds(0x%X) ()", script); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); return 0; } @@ -855,18 +589,18 @@ int KyraEngine::cmd_customPrintTalkString(ScriptState *script) { delay(10); } snd_playVoiceFile(stackPos(0)); - printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2); + _text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2); } else { debug(3, "cmd_customPrintTalkString(0x%X) ('%s', %d, %d, %d)", script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF); - printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2); + _text->printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2); } - _updateScreen = true; + _animator->_updateScreen = true; return 0; } int KyraEngine::cmd_restoreCustomPrintBackground(ScriptState *script) { debug(3, "cmd_restoreCustomPrintBackground(0x%X) ()", script); - restoreTalkTextMessageBkgd(2, 0); + _text->restoreTalkTextMessageBkgd(2, 0); return 0; } @@ -898,15 +632,15 @@ int KyraEngine::cmd_changeCharactersFacing(ScriptState *script) { int facing = stackPos(1); int newAnimFrame = stackPos(2); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); if (newAnimFrame != -1) { _characterList[character].currentAnimFrame = newAnimFrame; } _characterList[character].facing = facing; animRefreshNPC(character); - preserveAllBackgrounds(); - prepDrawAllObjects(); - copyChangedObjectsForward(0); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); + _animator->copyChangedObjectsForward(0); return 0; } @@ -957,7 +691,7 @@ int KyraEngine::cmd_displayWSAFrameOnHidPage(ScriptState *script) { uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); delay(10); } _screen->showMouse(); @@ -988,11 +722,11 @@ int KyraEngine::cmd_displayWSASequentialFrames(ScriptState *script) { int frame = startFrame; while (endFrame >= frame) { _movieObjects[wsaIndex]->displayFrame(frame); - _updateScreen = true; + _animator->_updateScreen = true; uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); if (continueTime - _system->getMillis() >= 10) delay(10); } @@ -1002,11 +736,11 @@ int KyraEngine::cmd_displayWSASequentialFrames(ScriptState *script) { int frame = startFrame; while (endFrame <= frame) { _movieObjects[wsaIndex]->displayFrame(frame); - _updateScreen = true; + _animator->_updateScreen = true; uint32 continueTime = waitTime * _tickLength + _system->getMillis(); while (_system->getMillis() < continueTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); if (continueTime - _system->getMillis() >= 10) delay(10); } @@ -1032,14 +766,14 @@ int KyraEngine::cmd_drawCharacterStanding(ScriptState *script) { } animRefreshNPC(character); if (updateShapes) { - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } return 0; } int KyraEngine::cmd_internalAnimOff(ScriptState *script) { debug(3, "cmd_internalAnimOff(0x%X) (%d)", script, stackPos(0)); - _sprites->_animObjects[stackPos(0)].active = 0; + _animator->sprites()[stackPos(0)].active = 0; return 0; } @@ -1052,10 +786,10 @@ int KyraEngine::cmd_changeCharactersXAndY(ScriptState *script) { x &= 0xFFFC; y &= 0xFFFE; } - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); ch->x1 = ch->x2 = x; ch->y1 = ch->y2 = y; - preserveAllBackgrounds(); + _animator->preserveAllBackgrounds(); return 0; } @@ -1073,7 +807,7 @@ int KyraEngine::cmd_querySceneAnimatorBeacon(ScriptState *script) { int KyraEngine::cmd_refreshSceneAnimator(ScriptState *script) { debug(3, "cmd_refreshSceneAnimator(0x%X) ()", script); _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); return 0; } @@ -1149,8 +883,8 @@ int KyraEngine::cmd_popMobileNPCIntoScene(ScriptState *script) { curChar->x1 = curChar->x2 = xpos; curChar->y1 = curChar->y2 = ypos; - animAddNPC(character); - updateAllObjectShapes(); + _animator->animAddNPC(character); + _animator->updateAllObjectShapes(); return 0; } @@ -1172,7 +906,7 @@ int KyraEngine::cmd_unhideMobileCharacter(ScriptState *script) { int KyraEngine::cmd_setCharactersLocation(ScriptState *script) { debug(3, "cmd_setCharactersLocation(0x%X) (%d, %d)", script, stackPos(0), stackPos(1)); Character *ch = &_characterList[stackPos(0)]; - AnimObject *animObj = &_charactersAnimState[stackPos(0)]; + AnimObject *animObj = &_animator->actors()[stackPos(0)]; int newScene = stackPos(1); if (_currentCharacter->sceneId == ch->sceneId) { if (_currentCharacter->sceneId != newScene) @@ -1260,7 +994,7 @@ int KyraEngine::cmd_walkCharacterToPoint(ScriptState *script) { _sprites->updateSceneAnims(); updateMousePointer(); updateGameTimers(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); updateTextFade(); if ((nextFrame - _system->getMillis()) >= 10) delay(10); @@ -1317,13 +1051,13 @@ int KyraEngine::cmd_setLogicPage(ScriptState *script) { int KyraEngine::cmd_fatPrint(ScriptState *script) { debug(3, "cmd_fatPrint(0x%X) ('%s', %d, %d, %d, %d, %d)", script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); - printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + _text->printText(stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); return 0; } int KyraEngine::cmd_preserveAllObjectBackgrounds(ScriptState *script) { debug(3, "cmd_preserveAllObjectBackgrounds(0x%X) ()", script); - preserveAllBackgrounds(); + _animator->preserveAllBackgrounds(); return 0; } @@ -1331,7 +1065,7 @@ int KyraEngine::cmd_updateSceneAnimations(ScriptState *script) { debug(3, "cmd_updateSceneAnimations(0x%X) (%d)", script, stackPos(0)); if (stackPos(0)) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } return 0; } @@ -1489,11 +1223,11 @@ int KyraEngine::cmd_makeAmuletAppear(ScriptState *script) { amulet.displayFrame(code); - _updateScreen = true; + _animator->_updateScreen = true; while (_system->getMillis() < nextTime) { _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); } } _screen->showMouse(); @@ -1515,12 +1249,12 @@ int KyraEngine::cmd_drawItemShapeIntoScene(ScriptState *script) { _screen->drawShape(2, _shapes[220+item], x, y, 0, flags); } else { _screen->hideMouse(); - restoreAllObjectBackgrounds(); + _animator->restoreAllObjectBackgrounds(); _screen->drawShape(2, _shapes[220+item], x, y, 0, flags); _screen->drawShape(0, _shapes[220+item], x, y, 0, flags); - flagAllObjectsForBkgdChange(); - flagAllObjectsForRefresh(); - updateAllObjectShapes(); + _animator->flagAllObjectsForBkgdChange(); + _animator->flagAllObjectsForRefresh(); + _animator->updateAllObjectShapes(); _screen->showMouse(); } return 0; @@ -1538,14 +1272,14 @@ int KyraEngine::cmd_waitForConfirmationMouseClick(ScriptState *script) { while (!_mousePressFlag) { updateMousePointer(); _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); delay(10); } while (_mousePressFlag) { updateMousePointer(); _sprites->updateSceneAnims(); - updateAllObjectShapes(); + _animator->updateAllObjectShapes(); delay(10); } // } @@ -1706,7 +1440,7 @@ int KyraEngine::cmd_itemAppearsOnGround(ScriptState *script) { int KyraEngine::cmd_setNoDrawShapesFlag(ScriptState *script) { debug(3, "cmd_setNoDrawShapesFlag(0x%X) (%d)", script, stackPos(0)); - _noDrawShapesFlag = stackPos(0); + _animator->_noDrawShapesFlag = stackPos(0); return 0; } diff --git a/kyra/seqplayer.cpp b/kyra/seqplayer.cpp index 6cd2b97aae..71be508b91 100755 --- a/kyra/seqplayer.cpp +++ b/kyra/seqplayer.cpp @@ -29,6 +29,7 @@ #include "kyra/screen.h" #include "kyra/sound.h" #include "kyra/wsamovie.h" +#include "kyra/text.h" #include "kyra/seqplayer.h" @@ -266,7 +267,7 @@ void SeqPlayer::s1_printTalkText() { } else { b = 0; } - _vm->restoreTalkTextMessageBkgd(2, b); + _vm->text()->restoreTalkTextMessageBkgd(2, b); } _seqTalkTextPrinted = true; _seqTalkTextRestored = false; @@ -275,7 +276,7 @@ void SeqPlayer::s1_printTalkText() { } else { b = 0; } - _vm->printTalkTextMessage(_vm->seqTextsTable()[txt], x, y, fillColor, b, 2); + _vm->text()->printTalkTextMessage(_vm->seqTextsTable()[txt], x, y, fillColor, b, 2); } void SeqPlayer::s1_restoreTalkText() { @@ -286,7 +287,7 @@ void SeqPlayer::s1_restoreTalkText() { } else { b = 0; } - _vm->restoreTalkTextMessageBkgd(2, b); + _vm->text()->restoreTalkTextMessageBkgd(2, b); _seqTalkTextRestored = true; } } diff --git a/kyra/sprites.cpp b/kyra/sprites.cpp index 6115c18c08..f83b53d083 100644 --- a/kyra/sprites.cpp +++ b/kyra/sprites.cpp @@ -27,6 +27,7 @@ #include "kyra/kyra.h" #include "kyra/sprites.h" #include "kyra/resource.h" +#include "kyra/animator.h" namespace Kyra { @@ -339,8 +340,8 @@ void Sprites::updateSceneAnims() { data += 2; debug(6, "func: Update Brandon's sprite"); _engine->animRefreshNPC(0); - _engine->flagAllObjectsForRefresh(); - _engine->updateAllObjectShapes(); + _engine->animator()->flagAllObjectsForRefresh(); + _engine->animator()->updateAllObjectShapes(); break; case 0xFFB0: data += 2; @@ -524,23 +525,24 @@ void Sprites::loadSceneShapes() { void Sprites::refreshSceneAnimObject(uint8 animNum, uint8 shapeNum, uint16 x, uint16 y, bool flipX, bool unkFlag) { debug(9, "Sprites::refreshSceneAnimObject(%i, %i, %i, %i, %i, %i", animNum, shapeNum, x, y, flipX, unkFlag); - _animObjects[animNum].refreshFlag = 1; - _animObjects[animNum].bkgdChangeFlag = 1; + AnimObject &anim = _engine->animator()->sprites()[animNum]; + anim.refreshFlag = 1; + anim.bkgdChangeFlag = 1; if (unkFlag) - _animObjects[animNum].flags |= 0x0200; + anim.flags |= 0x0200; else - _animObjects[animNum].flags &= 0xFD00; + anim.flags &= 0xFD00; if (flipX) - _animObjects[animNum].flags |= 1; + anim.flags |= 1; else - _animObjects[animNum].flags &= 0xFE; + anim.flags &= 0xFE; - _animObjects[animNum].sceneAnimPtr = _sceneShapes[shapeNum]; - _animObjects[animNum].animFrameNumber = -1; - _animObjects[animNum].x1 = x; - _animObjects[animNum].y1 = y; + anim.sceneAnimPtr = _sceneShapes[shapeNum]; + anim.animFrameNumber = -1; + anim.x1 = x; + anim.y1 = y; } int Sprites::getDrawLayer(int y) { diff --git a/kyra/sprites.h b/kyra/sprites.h index 81405e7cee..87a7427b1a 100644 --- a/kyra/sprites.h +++ b/kyra/sprites.h @@ -67,7 +67,6 @@ public: void loadSceneShapes(); Anim _anims[MAX_NUM_ANIMS]; - AnimObject *_animObjects; uint8 *_sceneShapes[50]; void refreshSceneAnimObject(uint8 animNum, uint8 shapeNum, uint16 x, uint16 y, bool flipX, bool unkFlag); diff --git a/kyra/text.cpp b/kyra/text.cpp new file mode 100644 index 0000000000..c9feadbb49 --- /dev/null +++ b/kyra/text.cpp @@ -0,0 +1,240 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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 "common/stdafx.h" + +#include "kyra/screen.h" +#include "kyra/text.h" + +namespace Kyra { +TextDisplayer::TextDisplayer(Screen *screen) { + _screen = screen; + + _talkCoords.y = 0x88; + _talkCoords.x = 0; + _talkCoords.w = 0; + _talkMessageY = 0xC; + _talkMessageH = 0; + _talkMessagePrinted = false; +} + +void TextDisplayer::setTalkCoords(uint16 y) { + debug(9, "TextDisplayer::setTalkCoords(%d)", y); + _talkCoords.y = y; +} + +int TextDisplayer::getCenterStringX(const char *str, int x1, int x2) { + debug(9, "TextDisplayer::getCenterStringX('%s', %d, %d)", str, x1, x2); + _screen->_charWidth = -2; + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + int strWidth = _screen->getTextWidth(str); + _screen->setFont(curFont); + _screen->_charWidth = 0; + int w = x2 - x1 + 1; + return x1 + (w - strWidth) / 2; +} + +int TextDisplayer::getCharLength(const char *str, int len) { + debug(9, "TextDisplayer::getCharLength('%s', %d)", str, len); + int charsCount = 0; + if (*str) { + _screen->_charWidth = -2; + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + int i = 0; + while (i <= len && *str) { + i += _screen->getCharWidth(*str++); + ++charsCount; + } + _screen->setFont(curFont); + _screen->_charWidth = 0; + } + return charsCount; +} + +int TextDisplayer::dropCRIntoString(char *str, int offs) { + debug(9, "TextDisplayer::dropCRIntoString('%s', %d)", str, offs); + int pos = 0; + str += offs; + while (*str) { + if (*str == ' ') { + *str = '\r'; + return pos; + } + ++str; + ++pos; + } + return 0; +} + +char *TextDisplayer::preprocessString(const char *str) { + debug(9, "TextDisplayer::preprocessString('%s')", str); + assert(strlen(str) < sizeof(_talkBuffer) - 1); + strcpy(_talkBuffer, str); + char *p = _talkBuffer; + while (*p) { + if (*p == '\r') { + return _talkBuffer; + } + ++p; + } + p = _talkBuffer; + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + _screen->_charWidth = -2; + int textWidth = _screen->getTextWidth(p); + _screen->_charWidth = 0; + if (textWidth > 176) { + if (textWidth > 352) { + int count = getCharLength(p, textWidth / 3); + int offs = dropCRIntoString(p, count); + p += count + offs; + _screen->_charWidth = -2; + textWidth = _screen->getTextWidth(p); + _screen->_charWidth = 0; + count = getCharLength(p, textWidth / 2); + dropCRIntoString(p, count); + } else { + int count = getCharLength(p, textWidth / 2); + dropCRIntoString(p, count); + } + } + _screen->setFont(curFont); + return _talkBuffer; +} + +int TextDisplayer::buildMessageSubstrings(const char *str) { + debug(9, "TextDisplayer::buildMessageSubstrings('%s')", str); + int currentLine = 0; + int pos = 0; + while (*str) { + if (*str == '\r') { + assert(currentLine < TALK_SUBSTRING_NUM); + _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0'; + ++currentLine; + pos = 0; + } else { + _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = *str; + ++pos; + if (pos > TALK_SUBSTRING_LEN - 2) { + pos = TALK_SUBSTRING_LEN - 2; + } + } + ++str; + } + _talkSubstrings[currentLine * TALK_SUBSTRING_LEN + pos] = '\0'; + return currentLine + 1; +} + +int TextDisplayer::getWidestLineWidth(int linesCount) { + debug(9, "TextDisplayer::getWidestLineWidth(%d)", linesCount); + int maxWidth = 0; + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + _screen->_charWidth = -2; + for (int l = 0; l < linesCount; ++l) { + int w = _screen->getTextWidth(&_talkSubstrings[l * TALK_SUBSTRING_LEN]); + if (maxWidth < w) { + maxWidth = w; + } + } + _screen->setFont(curFont); + _screen->_charWidth = 0; + return maxWidth; +} + +void TextDisplayer::calcWidestLineBounds(int &x1, int &x2, int w, int cx) { + debug(9, "TextDisplayer::calcWidestLineBounds(%d, %d)", w, cx); + x1 = cx - w / 2; + if (x1 + w >= Screen::SCREEN_W - 12) { + x1 = Screen::SCREEN_W - 12 - w - 1; + } else if (x1 < 12) { + x1 = 12; + } + x2 = x1 + w + 1; +} + +void TextDisplayer::restoreTalkTextMessageBkgd(int srcPage, int dstPage) { + debug(9, "TextDisplayer::restoreTalkTextMessageBkgd(%d, %d)", srcPage, dstPage); + if (_talkMessagePrinted) { + _talkMessagePrinted = false; + _screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage); + } +} + +void TextDisplayer::printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage) { + debug(9, "TextDisplayer::printTalkTextMessage('%s', %d, %d, %d, %d, %d)", text, x, y, color, srcPage, dstPage); + char *str = preprocessString(text); + int lineCount = buildMessageSubstrings(str); + int top = y - lineCount * 10; + if (top < 0) { + top = 0; + } + _talkMessageY = top; + _talkMessageH = lineCount * 10; + int w = getWidestLineWidth(lineCount); + int x1, x2; + calcWidestLineBounds(x1, x2, w, x); + _talkCoords.x = x1; + _talkCoords.w = w + 2; + _screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkCoords.y, _talkCoords.w, _talkMessageH, srcPage, dstPage); + int curPage = _screen->_curPage; + _screen->_curPage = srcPage; + for (int i = 0; i < lineCount; ++i) { + top = i * 10 + _talkMessageY; + char *msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; + int left = getCenterStringX(msg, x1, x2); + printText(msg, left, top, color, 0xC, 0); + } + _screen->_curPage = curPage; + _talkMessagePrinted = true; +} + +void TextDisplayer::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2) { + debug(9, "TextDisplayer::printText('%s', %d, %d, %d, %d, %d)", str, x, y, c0, c1, c2); + uint8 colorMap[] = { 0, 15, 12, 12 }; + colorMap[3] = c1; + _screen->setTextColor(colorMap, 0, 3); + Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT); + _screen->_charWidth = -2; + _screen->printText(str, x, y, c0, c2); + _screen->_charWidth = 0; + _screen->setFont(curFont); +} + +void TextDisplayer::printCharacterText(char *text, int8 charNum, int charX) { + debug(9, "TextDisplayer::printCharacterText('%s', %d, %d)", text, charNum, charX); + uint8 colorTable[] = {0x0F, 0x9, 0x0C9, 0x80, 0x5, 0x81, 0x0E, 0xD8, 0x55, 0x3A, 0x3a}; + int top, left, x1, x2, w, x; + char *msg; + + uint8 color = colorTable[charNum]; + text = preprocessString(text); + int lineCount = buildMessageSubstrings(text); + w = getWidestLineWidth(lineCount); + x = charX; + calcWidestLineBounds(x1, x2, w, x); + + for (int i = 0; i < lineCount; ++i) { + top = i * 10 + _talkMessageY; + msg = &_talkSubstrings[i * TALK_SUBSTRING_LEN]; + left = getCenterStringX(msg, x1, x2); + printText(msg, left, top, color, 0xC, 0); + } +} +} // end of namespace Kyra diff --git a/kyra/text.h b/kyra/text.h new file mode 100644 index 0000000000..7f0a10df34 --- /dev/null +++ b/kyra/text.h @@ -0,0 +1,67 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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$ + * + */ + +#ifndef KYRATEXT_H +#define KYRATEXT_H + +namespace Kyra { +class Screen; + +class TextDisplayer { + struct TalkCoords { + uint16 y, x, w; + }; + + enum { + TALK_SUBSTRING_LEN = 80, + TALK_SUBSTRING_NUM = 3 + }; +public: + TextDisplayer(Screen *screen); + ~TextDisplayer() {} + + void setTalkCoords(uint16 y); + int getCenterStringX(const char *str, int x1, int x2); + int getCharLength(const char *str, int len); + int dropCRIntoString(char *str, int offs); + char *preprocessString(const char *str); + int buildMessageSubstrings(const char *str); + int getWidestLineWidth(int linesCount); + void calcWidestLineBounds(int &x1, int &x2, int w, int cx); + void restoreTalkTextMessageBkgd(int srcPage, int dstPage); + void printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage); + void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2); + void printCharacterText(char *text, int8 charNum, int charX); + + uint16 _talkMessageY; + uint16 _talkMessageH; +private: + Screen *_screen; + + char _talkBuffer[300]; + char _talkSubstrings[TALK_SUBSTRING_LEN * TALK_SUBSTRING_NUM]; + TalkCoords _talkCoords; + bool _talkMessagePrinted; +}; +} // end of namespace Kyra + +#endif + diff --git a/kyra/timer.cpp b/kyra/timer.cpp new file mode 100644 index 0000000000..9760ec5287 --- /dev/null +++ b/kyra/timer.cpp @@ -0,0 +1,277 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005 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/screen.h" +#include "common/system.h" + +namespace Kyra { +void KyraEngine::setupTimers() { + debug(9, "setupTimers()"); + memset(_timers, 0, sizeof(_timers)); + + for (int i = 0; i < 34; i++) + _timers[i].active = 1; + + _timers[0].func = _timers[1].func = _timers[2].func = _timers[3].func = _timers[4].func = 0; //Unused. + _timers[5].func = _timers[6].func = _timers[7].func = _timers[8].func = _timers[9].func = 0; //_nullsub51; + _timers[10].func = _timers[11].func = _timers[12].func = _timers[13].func = 0; //_nullsub50; + _timers[14].func = &KyraEngine::timerCheckAnimFlag2; //_nullsub52; + _timers[15].func = &KyraEngine::timerUpdateHeadAnims; //_nullsub48; + _timers[16].func = &KyraEngine::timerSetFlags1; //_nullsub47; + _timers[17].func = 0; //sub_15120; + _timers[18].func = &KyraEngine::timerCheckAnimFlag1; //_nullsub53; + _timers[19].func = &KyraEngine::timerRedrawAmulet; //_nullsub54; + _timers[20].func = 0; //offset _timerDummy1 + _timers[21].func = 0; //sub_1517C; + _timers[22].func = 0; //offset _timerDummy2 + _timers[23].func = 0; //offset _timerDummy3, + _timers[24].func = 0; //_nullsub45; + _timers[25].func = 0; //offset _timerDummy4 + _timers[26].func = 0; //_nullsub46; + _timers[27].func = 0; //offset _timerDummy5, + _timers[28].func = 0; //offset _timerDummy6 + _timers[29].func = 0; //offset _timerDummy7, + _timers[30].func = 0; //offset _timerDummy8, + _timers[31].func = &KyraEngine::timerFadeText; //sub_151F8; + _timers[32].func = &KyraEngine::updateAnimFlag1; //_nullsub61; + _timers[33].func = &KyraEngine::updateAnimFlag2; //_nullsub62; + + _timers[0].countdown = _timers[1].countdown = _timers[2].countdown = _timers[3].countdown = _timers[4].countdown = -1; + _timers[5].countdown = 5; + _timers[6].countdown = 7; + _timers[7].countdown = 8; + _timers[8].countdown = 9; + _timers[9].countdown = 7; + _timers[10].countdown = _timers[11].countdown = _timers[12].countdown = _timers[13].countdown = 420; + _timers[14].countdown = 600; + _timers[15].countdown = 11; + _timers[16].countdown = _timers[17].countdown = 7200; + _timers[18].countdown = _timers[19].countdown = 600; + _timers[20].countdown = 7200; + _timers[21].countdown = 18000; + _timers[22].countdown = 7200; + _timers[23].countdown = _timers[24].countdown = _timers[25].countdown = _timers[26].countdown = _timers[27].countdown = 10800; + _timers[28].countdown = 21600; + _timers[29].countdown = 7200; + _timers[30].countdown = 10800; + _timers[31].countdown = -1; + _timers[32].countdown = 9; + _timers[33].countdown = 3; +} + +void KyraEngine::updateGameTimers() { + debug(9, "updateGameTimers()"); + + if (_system->getMillis() < _timerNextRun) + return; + + _timerNextRun += 99999; + + for (int i = 0; i < 34; i++) { + if (_timers[i].active && _timers[i].countdown > -1) { + if (_timers[i].nextRun <=_system->getMillis()) { + if (i > 4 && _timers[i].func) + (*this.*_timers[i].func)(i); + + _timers[i].nextRun = _system->getMillis() + _timers[i].countdown * _tickLength; + + } + } + if (_timers[i].nextRun < _timerNextRun) + _timerNextRun = _timers[i].nextRun; + } +} + +void KyraEngine::clearNextEventTickCount() { + debug(9, "clearNextEventTickCount()"); + _timerNextRun = 0; +} + +void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) { + debug(9, "setTimerDelay(%i, %d)", timer, countdown); + _timers[timer].countdown = countdown; +} + +int16 KyraEngine::getTimerDelay(uint8 timer) { + debug(9, "getTimerDelay(%i)", timer); + return _timers[timer].countdown; +} + +void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) { + debug(9, "setTimerCountdown(%i, %i)", timer, countdown); + _timers[timer].countdown = countdown; + + uint32 nextRun = _system->getMillis() + countdown; + if (nextRun < _timerNextRun) + _timerNextRun = nextRun; +} + +void KyraEngine::enableTimer(uint8 timer) { + debug(9, "enableTimer(%i)", timer); + _timers[timer].active = 1; +} + +void KyraEngine::disableTimer(uint8 timer) { + debug(9, "disableTimer(%i)", timer); + _timers[timer].active = 0; +} + +void KyraEngine::timerUpdateHeadAnims(int timerNum) { + debug(9, "timerUpdateHeadAnims(%i)", timerNum); + static int8 currentFrame = 0; + static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5, + 4, 4, 6, 4, 8, 1, 9, 4, -1}; + + if (_talkingCharNum < 0) + return; + + _currHeadShape = frameTable[currentFrame]; + currentFrame++; + + if (frameTable[currentFrame] == -1) + currentFrame = 0; + + animRefreshNPC(0); + animRefreshNPC(_talkingCharNum); +} + +void KyraEngine::timerSetFlags1(int timerNum) { + debug(9, "timerSetFlags(%i)", timerNum); + if (_currentCharacter->sceneId == 0x1C) + return; + + int rndNr = _rnd.getRandomNumberRng(0, 3); + + for (int i = 0; i < 4; i++) { + if (!queryGameFlag(rndNr + 17)) { + setGameFlag(rndNr + 17); + break; + } else { + rndNr++; + if (rndNr > 3) + rndNr = 0; + } + } +} + +void KyraEngine::timerFadeText(int timerNum) { + debug(9, "timerFadeText(%i)", timerNum); + _fadeText = true; +} + +void KyraEngine::updateAnimFlag1(int timerNum) { + debug(9, "updateAnimFlag1(%d)", timerNum); + if (_brandonStatusBit & 2) { + _brandonStatusBit0x02Flag = 1; + } +} + +void KyraEngine::updateAnimFlag2(int timerNum) { + debug(9, "updateAnimFlag2(%d)", timerNum); + if (_brandonStatusBit & 0x20) { + _brandonStatusBit0x20Flag = 1; + } +} + +void KyraEngine::setTextFadeTimerCountdown(int16 countdown) { + debug(9, "setTextFadeTimerCountdown(%i)", countdown); + //if (countdown == -1) + //countdown = 32000; + + setTimerCountdown(31, countdown*60); +} + +void KyraEngine::timerSetFlags2(int timerNum) { + debug(9, "timerSetFlags2(%i)", timerNum); + if (!((uint32*)(_flagsTable+0x2D))[timerNum]) + ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; +} + +void KyraEngine::timerCheckAnimFlag1(int timerNum) { + debug(9, "timerCheckAnimFlag1(%i)", timerNum); + if (_brandonStatusBit & 0x20) { + checkAmuletAnimFlags(); + setTimerCountdown(18, -1); + } +} + +void KyraEngine::timerCheckAnimFlag2(int timerNum) { + debug(9, "timerCheckAnimFlag1(%i)", timerNum); + if (_brandonStatusBit & 0x2) { + checkAmuletAnimFlags(); + setTimerCountdown(14, -1); + } +} + +void KyraEngine::checkAmuletAnimFlags() { + debug(9, "checkSpecialAnimFlags()"); + if (_brandonStatusBit & 2) { + seq_makeBrandonNormal2(); + setTimerCountdown(19, 300); + } + + if (_brandonStatusBit & 0x20) { + seq_makeBrandonNormal(); + setTimerCountdown(19, 300); + } +} + +void KyraEngine::timerRedrawAmulet(int timerNum) { + debug(9, "timerRedrawAmulet(%i)", timerNum); + if (queryGameFlag(0xF1)) { + drawAmulet(); + setTimerCountdown(19, -1); + } +} + +void KyraEngine::drawAmulet() { + debug(9, "drawAmulet()"); + static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1}; + static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1}; + static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1}; + static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1}; + + resetGameFlag(0xF1); + _screen->hideMouse(); + + int i = 0; + while (amuletTable1[i] != -1) { + if (queryGameFlag(87)) + _screen->drawShape(0, _shapes[4+amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0); + + if (queryGameFlag(89)) + _screen->drawShape(0, _shapes[4+amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0); + + if (queryGameFlag(86)) + _screen->drawShape(0, _shapes[4+amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0); + + if (queryGameFlag(88)) + _screen->drawShape(0, _shapes[4+amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0); + + _screen->updateScreen(); + delayWithTicks(3); + i++; + } + _screen->showMouse(); +} +} // end of namespace Kyra + |