From bd965cd48388afdd8a85adf93d186db3da325822 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 2 Jan 2006 22:58:59 +0000 Subject: More 'cleanup' for kyra. Moved scene object drawing into its own class (see animator.h and .cpp) (this needs some more cleanup!) Moved text displaying into its own class (see text.h and .cpp) Also moved timer code to timers.cpp and button code to gui.cpp. Also changed wrong (c) information in debugger.h and debugger.cpp svn-id: r19890 --- kyra/animator.cpp | 525 +++++++++++++++++++ kyra/animator.h | 105 ++++ kyra/debugger.cpp | 2 +- kyra/debugger.h | 2 +- kyra/gui.cpp | 293 +++++++++++ kyra/kyra.cpp | 1424 +++++----------------------------------------------- kyra/kyra.h | 81 +-- kyra/module.mk | 6 +- kyra/script.cpp | 267 ++++++++++ kyra/script_v1.cpp | 384 +++----------- kyra/seqplayer.cpp | 7 +- kyra/sprites.cpp | 26 +- kyra/sprites.h | 1 - kyra/text.cpp | 240 +++++++++ kyra/text.h | 67 +++ kyra/timer.cpp | 277 ++++++++++ 16 files changed, 1988 insertions(+), 1719 deletions(-) create mode 100644 kyra/animator.cpp create mode 100644 kyra/animator.h create mode 100644 kyra/gui.cpp create mode 100644 kyra/text.cpp create mode 100644 kyra/text.h create mode 100644 kyra/timer.cpp (limited to 'kyra') 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; @@ -5683,260 +5026,6 @@ int KyraEngine::changeScene(int facing) { return returnValue; } -#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,13 +160,9 @@ 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 + -- cgit v1.2.3