diff options
Diffstat (limited to 'engines/kyra')
54 files changed, 9374 insertions, 4748 deletions
diff --git a/engines/kyra/animator.cpp b/engines/kyra/animator_v1.cpp index 7683bb6417..4169b59a36 100644 --- a/engines/kyra/animator.cpp +++ b/engines/kyra/animator_v1.cpp @@ -26,15 +26,15 @@ #include "common/stdafx.h" #include "common/endian.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/screen.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" #include "kyra/sprites.h" #include "common/system.h" namespace Kyra { -ScreenAnimator::ScreenAnimator(KyraEngine *vm, OSystem *system) { +ScreenAnimator::ScreenAnimator(KyraEngine_v1 *vm, OSystem *system) { _vm = vm; _screen = vm->screen(); _initOk = false; diff --git a/engines/kyra/animator.h b/engines/kyra/animator_v1.h index e817be86d5..8b554adf12 100644 --- a/engines/kyra/animator.h +++ b/engines/kyra/animator_v1.h @@ -27,7 +27,7 @@ #define KYRA_ANIMATOR_H namespace Kyra { -class KyraEngine; +class KyraEngine_v1; class Screen; struct AnimObject { @@ -53,7 +53,7 @@ struct AnimObject { class ScreenAnimator { public: - ScreenAnimator(KyraEngine *vm, OSystem *system); + ScreenAnimator(KyraEngine_v1 *vm, OSystem *system); virtual ~ScreenAnimator(); operator bool() const { return _initOk; } @@ -101,7 +101,7 @@ public: int _brandonScaleY; protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; Screen *_screen; OSystem *_system; bool _initOk; diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp new file mode 100644 index 0000000000..179bdd140d --- /dev/null +++ b/engines/kyra/animator_v2.cpp @@ -0,0 +1,313 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v2.h" +#include "kyra/wsamovie.h" + +namespace Kyra { + +void KyraEngine_v2::clearAnimObjects() { + memset(_animObjects, 0, sizeof(_animObjects)); + + _animObjects[0].index = 0; + _animObjects[0].type = 0; + _animObjects[0].enabled = 1; + _animObjects[0].flags = 0x800; + _animObjects[0].width = 32; + _animObjects[0].height = 49; + _animObjects[0].width2 = 4; + _animObjects[0].height2 = 10; + + for (int i = 1; i < 11; ++i) { + _animObjects[i].index = i; + _animObjects[i].type = 2; + } + + for (int i = 11; i <= 40; ++i) { + _animObjects[i].index = i; + _animObjects[i].type = 1; + _animObjects[i].flags = 0x800; + _animObjects[i].width = 16; + _animObjects[i].height = 16; + } +} + +KyraEngine_v2::AnimObj *KyraEngine_v2::initAnimList(AnimObj *list, AnimObj *entry) { + entry->nextObject = list; + return entry; +} + +KyraEngine_v2::AnimObj *KyraEngine_v2::addToAnimListSorted(AnimObj *list, AnimObj *add) { + if (add->yPos1 <= list->yPos1) { + add->nextObject = list; + return add; + } + + AnimObj *cur = list; + AnimObj *prev = list; + while (add->yPos1 > cur->yPos1) { + AnimObj *temp = cur->nextObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (add->yPos1 <= cur->yPos1) { + prev->nextObject = add; + add->nextObject = cur; + } else { + cur->nextObject = add; + add->nextObject = 0; + } + return list; +} + +KyraEngine_v2::AnimObj *KyraEngine_v2::deleteAnimListEntry(AnimObj *list, AnimObj *entry) { + if (!list) + return 0; + + AnimObj *old = 0; + AnimObj *cur = list; + + while (true) { + if (cur == entry) + break; + if (!cur->nextObject) + break; + old = cur; + cur = cur->nextObject; + } + + if (cur == list) { + if (!cur->nextObject) + return 0; + cur = cur->nextObject; + return cur; + } + + if (!cur->nextObject) { + if (!old) + return 0; + old->nextObject = 0; + return list; + } + + if (cur != entry) + return list; + + old->nextObject = entry->nextObject; + return list; +} + +void KyraEngine_v2::drawAnimObjects() { + for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) { + if (!curObject->enabled) + continue; + + int x = curObject->xPos2 - (_screen->getScreenDim(2)->sx << 3); + int y = curObject->yPos2 - _screen->getScreenDim(2)->sy; + int layer = 7; + + if (curObject->flags & 0x800) { + if (curObject->animFlags) + layer = 0; + else + layer = getDrawLayer(curObject->xPos1, curObject->yPos1); + } + curObject->flags |= 0x800; + + if (curObject->index) + drawSceneAnimObject(curObject, x, y, layer); + else + drawCharacterAnimObject(curObject, x, y, layer); + } +} + +void KyraEngine_v2::refreshAnimObjects(int force) { + for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) { + if (!curObject->enabled) + continue; + if (!curObject->needRefresh && !force) + continue; + + int x = curObject->xPos2 - curObject->width2; + if (x < 0) + x = 0; + if (x >= 320) + x = 319; + int y = curObject->yPos2 - curObject->height2; + if (y < 0) + y = 0; + if (y >= 143) + y = 142; + + int width = curObject->width + curObject->width2 + 8; + int height = curObject->height + curObject->height2*2; + if (width + x > 320) + width -= width + x - 322; + if (height + y > 143) + height -= height + y - 144; + + _screen->hideMouse(); + _screen->copyRegion(x, y, x, y, width, height, 2, 0, Screen::CR_CLIPPED); + _screen->showMouse(); + + curObject->needRefresh = false; + } +} + +void KyraEngine_v2::refreshAnimObjectsIfNeed() { + for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) { + if (curEntry->enabled && curEntry->needRefresh) { + restorePage3(); + drawAnimObjects(); + refreshAnimObjects(0); + _screen->updateScreen(); + return; + } + } +} + +void KyraEngine_v2::updateCharacterAnim(int) { + Character *c = &_mainCharacter; + AnimObj *animState = _animObjects; + + animState->needRefresh = 1; + animState->unk8 = 1; + + if (c->facing >= 1 && c->facing <= 3) + animState->flags |= 1; + else if (c->facing >= 5 && c->facing <= 7) + animState->flags &= ~1; + + animState->xPos2 = animState->xPos1 = c->x1; + animState->yPos2 = animState->yPos1 = c->y1; + animState->shapePtr = _defaultShapeTable[c->animFrame]; + animState->shapeIndex1 = animState->shapeIndex2 = c->animFrame; + + int xAdd = _shapeDescTable[c->animFrame-9].xAdd; + int yAdd = _shapeDescTable[c->animFrame-9].yAdd; + + _charScaleX = _charScaleY = getScale(c->x1, c->y1); + + animState->xPos2 += (xAdd * _charScaleX) >> 8; + animState->yPos2 += (yAdd * _charScaleY) >> 8; + animState->width2 = 8; + animState->height2 = 10; + + _animList = deleteAnimListEntry(_animList, animState); + if (_animList) + _animList = addToAnimListSorted(_animList, animState); + else + _animList = initAnimList(_animList, animState); + + updateCharPal(1); +} + +void KyraEngine_v2::updateSceneAnim(int anim, int newFrame) { + AnimObj *animObject = &_animObjects[1+anim]; + if (!animObject->enabled) + return; + + animObject->needRefresh = 1; + animObject->unk8 = 1; + animObject->flags = 0; + + if (_sceneAnims[anim].flags & 2) + animObject->flags |= 0x800; + else + animObject->flags &= ~0x800; + + if (_sceneAnims[anim].flags & 4) + animObject->flags |= 1; + else + animObject->flags &= ~1; + + if (_sceneAnims[anim].flags & 0x20) { + animObject->shapePtr = _sceneShapeTable[newFrame]; + animObject->shapeIndex2 = 0xFFFF; + animObject->shapeIndex3 = 0xFFFF; + animObject->animNum = 0xFFFF; + } else { + animObject->shapePtr = 0; + animObject->shapeIndex3 = newFrame; + animObject->animNum = anim; + } + + animObject->xPos1 = _sceneAnims[anim].x; + animObject->yPos1 = _sceneAnims[anim].y; + animObject->xPos2 = _sceneAnims[anim].x2; + animObject->yPos2 = _sceneAnims[anim].y2; + + if (_sceneAnims[anim].flags & 2) { + _animList = deleteAnimListEntry(_animList, animObject); + if (!_animList) + _animList = initAnimList(_animList, animObject); + else + _animList = addToAnimListSorted(_animList, animObject); + } +} + +void KyraEngine_v2::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) { + if (obj->type == 1) { + if (obj->shapeIndex1 == 0xFFFF) + return; + int scale = getScale(obj->xPos1, obj->yPos1); + _screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, scale, scale); + return; + } + + if (obj->shapePtr) { + _screen->drawShape(2, obj->shapePtr, x, y, 2, obj->flags, layer); + } else { + if (obj->shapeIndex3 == 0xFFFF || obj->animNum == 0xFFFF) + return; + + int flags = 0x4000; + if (obj->flags & 0x800) + flags |= 0x8000; + + if (_sceneAnims[obj->animNum].wsaFlag) { + x = y = 0; + } else { + x = obj->xPos2; + y = obj->yPos2; + } + + _sceneAnimMovie[obj->animNum]->setX(x); + _sceneAnimMovie[obj->animNum]->setY(y); + _sceneAnimMovie[obj->animNum]->setDrawPage(2); + _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, int(flags | layer), 0, 0); + } +} + +void KyraEngine_v2::drawCharacterAnimObject(AnimObj *obj, int x, int y, int layer) { + if (_drawNoShapeFlag || obj->shapeIndex1 == 0xFFFF) + return; + _screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, _charScaleX, _charScaleY); +} + +} // end of namespace Kyra diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index d5909bd8b0..152dc21c61 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -27,35 +27,36 @@ #include "common/config-manager.h" #include "common/system.h" #include "kyra/debugger.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/screen.h" +#include "kyra/timer.h" namespace Kyra { -Debugger::Debugger(KyraEngine *vm) - : GUI::Debugger() { +Debugger_v1::Debugger_v1(KyraEngine_v1 *vm) + : Debugger(vm) { _vm = vm; - DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); - DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom)); - DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms)); - DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags)); - DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag)); - DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag)); - DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers)); - DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown)); - DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem)); + DCmd_Register("continue", WRAP_METHOD(Debugger_v1, Cmd_Exit)); + DCmd_Register("enter", WRAP_METHOD(Debugger_v1, cmd_enterRoom)); + DCmd_Register("rooms", WRAP_METHOD(Debugger_v1, cmd_listRooms)); + DCmd_Register("flags", WRAP_METHOD(Debugger_v1, cmd_listFlags)); + DCmd_Register("toggleflag", WRAP_METHOD(Debugger_v1, cmd_toggleFlag)); + DCmd_Register("queryflag", WRAP_METHOD(Debugger_v1, cmd_queryFlag)); + DCmd_Register("timers", WRAP_METHOD(Debugger_v1, cmd_listTimers)); + DCmd_Register("settimercountdown", WRAP_METHOD(Debugger_v1, cmd_setTimerCountdown)); + DCmd_Register("give", WRAP_METHOD(Debugger_v1, cmd_giveItem)); } -void Debugger::preEnter() { +void Debugger_v1::preEnter() { //_vm->midi.pause(1); } -void Debugger::postEnter() { +void Debugger_v1::postEnter() { //_vm->midi.pause(0); } -bool Debugger::cmd_enterRoom(int argc, const char **argv) { +bool Debugger_v1::cmd_enterRoom(int argc, const char **argv) { uint direction = 0; if (argc > 1) { int room = atoi(argv[1]); @@ -93,7 +94,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) { return true; } -bool Debugger::cmd_listRooms(int argc, const char **argv) { +bool Debugger_v1::cmd_listRooms(int argc, const char **argv) { for (int i = 0; i < _vm->_roomTableSize; i++) { DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]); if (!(i % 8)) @@ -104,7 +105,7 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) { return true; } -bool Debugger::cmd_listFlags(int argc, const char **argv) { +bool Debugger_v1::cmd_listFlags(int argc, const char **argv) { for (int i = 0; i < (int)sizeof(_vm->_flagsTable)*8; i++) { DebugPrintf("(%-3i): %-5i", i, _vm->queryGameFlag(i)); if (!(i % 10)) @@ -114,7 +115,7 @@ bool Debugger::cmd_listFlags(int argc, const char **argv) { return true; } -bool Debugger::cmd_toggleFlag(int argc, const char **argv) { +bool Debugger_v1::cmd_toggleFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); if (_vm->queryGameFlag(flag)) @@ -129,7 +130,7 @@ bool Debugger::cmd_toggleFlag(int argc, const char **argv) { return true; } -bool Debugger::cmd_queryFlag(int argc, const char **argv) { +bool Debugger_v1::cmd_queryFlag(int argc, const char **argv) { if (argc > 1) { uint flag = atoi(argv[1]); DebugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag)); @@ -140,19 +141,19 @@ bool Debugger::cmd_queryFlag(int argc, const char **argv) { return true; } -bool Debugger::cmd_listTimers(int argc, const char **argv) { - for (int i = 0; i < ARRAYSIZE(_vm->_timers); i++) - DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i\n", i, _vm->_timers[i].active ? "Yes" : "No", _vm->_timers[i].countdown); +bool Debugger_v1::cmd_listTimers(int argc, const char **argv) { + for (int i = 0; i < _vm->timer()->count(); i++) + DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i)); return true; } -bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { +bool Debugger_v1::cmd_setTimerCountdown(int argc, const char **argv) { if (argc > 2) { uint timer = atoi(argv[1]); uint countdown = atoi(argv[2]); - _vm->setTimerCountdown(timer, countdown); - DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->_timers[timer].countdown); + _vm->timer()->setCountdown(timer, countdown); + DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer)); } else { DebugPrintf("Syntax: settimercountdown <timer> <countdown>\n"); } @@ -160,7 +161,7 @@ bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { return true; } -bool Debugger::cmd_giveItem(int argc, const char **argv) { +bool Debugger_v1::cmd_giveItem(int argc, const char **argv) { if (argc == 2) { int item = atoi(argv[1]); diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index 2d0e82c220..16b1e42a58 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -31,14 +31,21 @@ namespace Kyra { class KyraEngine; +class KyraEngine_v1; class Debugger : public GUI::Debugger { public: - Debugger(KyraEngine *vm); + Debugger(KyraEngine *vm) {} virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ +}; + +class Debugger_v1 : public Debugger { +public: + Debugger_v1(KyraEngine_v1 *vm); + virtual ~Debugger_v1() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; virtual void preEnter(); virtual void postEnter(); diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index e1b5a2b7c3..02b505b177 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -73,6 +73,8 @@ const KYRAGameDescription adGameDescs[] = { { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS }, { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS }, + { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), Common::IT_ITA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS }, // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat" + { { "kyra1", "Demo", AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DEMO }, KYRA1_DEMO_FLAGS }, { { "kyra2", 0, AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA2_CD_FLAGS }, // CD version diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui_v1.cpp index 6fc347158f..b7692cc97d 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui_v1.cpp @@ -23,11 +23,11 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/screen.h" #include "kyra/script.h" #include "kyra/text.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" #include "kyra/sound.h" #include "common/config-manager.h" @@ -37,14 +37,14 @@ namespace Kyra { -void KyraEngine::registerDefaultSettings() { +void KyraEngine_v1::registerDefaultSettings() { // Most settings already have sensible defaults. This one, however, is // specific to the Kyra engine. ConfMan.registerDefault("walkspeed", 2); ConfMan.registerDefault("cdaudio", _flags.platform == Common::kPlatformFMTowns); } -void KyraEngine::readSettings() { +void KyraEngine_v1::readSettings() { int talkspeed = ConfMan.getInt("talkspeed"); // The default talk speed is 60. This should be mapped to "Normal". @@ -78,7 +78,7 @@ void KyraEngine::readSettings() { setWalkspeed(_configWalkspeed); } -void KyraEngine::writeSettings() { +void KyraEngine_v1::writeSettings() { bool speechMute, subtitles; int talkspeed; @@ -130,14 +130,14 @@ void KyraEngine::writeSettings() { ConfMan.flushToDisk(); } -void KyraEngine::initMainButtonList() { +void KyraEngine_v1::initMainButtonList() { _haveScrollButtons = false; _buttonList = &_buttonData[0]; for (int i = 0; _buttonDataListPtr[i]; ++i) _buttonList = initButton(_buttonList, _buttonDataListPtr[i]); } -Button *KyraEngine::initButton(Button *list, Button *newButton) { +Button *KyraEngine_v1::initButton(Button *list, Button *newButton) { if (!newButton) return list; if (!list) @@ -154,7 +154,7 @@ Button *KyraEngine::initButton(Button *list, Button *newButton) { return list; } -int KyraEngine::buttonInventoryCallback(Button *caller) { +int KyraEngine_v1::buttonInventoryCallback(Button *caller) { int itemOffset = caller->specialValue - 2; uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset]; if (_itemInHand == -1) { @@ -198,7 +198,7 @@ int KyraEngine::buttonInventoryCallback(Button *caller) { return 0; } -int KyraEngine::buttonAmuletCallback(Button *caller) { +int KyraEngine_v1::buttonAmuletCallback(Button *caller) { if (!(_deathHandler & 8)) return 1; int jewel = caller->specialValue - 0x14; @@ -294,7 +294,7 @@ int KyraEngine::buttonAmuletCallback(Button *caller) { return 1; } -void KyraEngine::processButtonList(Button *list) { +void KyraEngine_v1::processButtonList(Button *list) { if (_haveScrollButtons) { if (_mouseWheel < 0) gui_scrollUp(&_scrollUpButton); @@ -367,7 +367,7 @@ void KyraEngine::processButtonList(Button *list) { } } -void KyraEngine::processButton(Button *button) { +void KyraEngine_v1::processButton(Button *button) { if (!button) return; @@ -411,7 +411,7 @@ void KyraEngine::processButton(Button *button) { (this->*callback)(button); } -void KyraEngine::processAllMenuButtons() { +void KyraEngine_v1::processAllMenuButtons() { if (!_menuButtonList) return; @@ -425,7 +425,7 @@ void KyraEngine::processAllMenuButtons() { return; } -void KyraEngine::processMenuButton(Button *button) { +void KyraEngine_v1::processMenuButton(Button *button) { if (!_displayMenu) return; @@ -449,7 +449,7 @@ void KyraEngine::processMenuButton(Button *button) { processButton(button); } -int KyraEngine::drawBoxCallback(Button *button) { +int KyraEngine_v1::drawBoxCallback(Button *button) { if (!_displayMenu) return 0; @@ -460,7 +460,7 @@ int KyraEngine::drawBoxCallback(Button *button) { return 0; } -int KyraEngine::drawShadedBoxCallback(Button *button) { +int KyraEngine_v1::drawShadedBoxCallback(Button *button) { if (!_displayMenu) return 0; @@ -471,7 +471,7 @@ int KyraEngine::drawShadedBoxCallback(Button *button) { return 0; } -void KyraEngine::setGUILabels() { +void KyraEngine_v1::setGUILabels() { int offset = 0; int offsetOptions = 0; int offsetMainMenu = 0; @@ -485,7 +485,7 @@ void KyraEngine::setGUILabels() { offset = 52; else if (_flags.lang == Common::DE_DEU) offset = 30; - else if (_flags.lang == Common::FR_FRA) + else if (_flags.lang == Common::FR_FRA || _flags.lang == Common::IT_ITA) offset = 6; offsetOn = offsetMainMenu = offsetOptions = offset; walkspeedGarbageOffset = 48; @@ -561,7 +561,7 @@ void KyraEngine::setGUILabels() { _onCDString = _guiStrings[21]; } -int KyraEngine::buttonMenuCallback(Button *caller) { +int KyraEngine_v1::buttonMenuCallback(Button *caller) { _displayMenu = true; assert(_guiStrings); @@ -584,9 +584,9 @@ int KyraEngine::buttonMenuCallback(Button *caller) { _screen->setPaletteIndex(0xFE, 60, 60, 0); for (int i = 0; i < 6; i++) { _menuButtonData[i].process0 = _menuButtonData[i].process1 = _menuButtonData[i].process2 = 4; - _menuButtonData[i].process0PtrCallback = &KyraEngine::drawShadedBoxCallback; - _menuButtonData[i].process1PtrCallback = &KyraEngine::drawBoxCallback; - _menuButtonData[i].process2PtrCallback = &KyraEngine::drawShadedBoxCallback; + _menuButtonData[i].process0PtrCallback = &KyraEngine_v1::drawShadedBoxCallback; + _menuButtonData[i].process1PtrCallback = &KyraEngine_v1::drawBoxCallback; + _menuButtonData[i].process2PtrCallback = &KyraEngine_v1::drawShadedBoxCallback; } _screen->savePageToDisk("SEENPAGE.TMP", 0); @@ -627,7 +627,7 @@ int KyraEngine::buttonMenuCallback(Button *caller) { return 0; } -void KyraEngine::initMenu(Menu &menu) { +void KyraEngine_v1::initMenu(Menu &menu) { _menuButtonList = 0; _screen->hideMouse(); @@ -707,14 +707,14 @@ void KyraEngine::initMenu(Menu &menu) { _scrollUpButton.x = menu.scrollUpBtnX + menu.x; _scrollUpButton.y = menu.scrollUpBtnY + menu.y; - _scrollUpButton.buttonCallback = &KyraEngine::gui_scrollUp; + _scrollUpButton.buttonCallback = &KyraEngine_v1::gui_scrollUp; _scrollUpButton.nextButton = 0; _menuButtonList = initButton(_menuButtonList, &_scrollUpButton); processMenuButton(&_scrollUpButton); _scrollDownButton.x = menu.scrollDownBtnX + menu.x; _scrollDownButton.y = menu.scrollDownBtnY + menu.y; - _scrollDownButton.buttonCallback = &KyraEngine::gui_scrollDown; + _scrollDownButton.buttonCallback = &KyraEngine_v1::gui_scrollDown; _scrollDownButton.nextButton = 0; _menuButtonList = initButton(_menuButtonList, &_scrollDownButton); processMenuButton(&_scrollDownButton); @@ -726,7 +726,7 @@ void KyraEngine::initMenu(Menu &menu) { _screen->updateScreen(); } -void KyraEngine::calcCoords(Menu &menu) { +void KyraEngine_v1::calcCoords(Menu &menu) { assert(menu.nrOfItems < 7); int widthBackup = _screen->_charWidth; @@ -798,7 +798,7 @@ void KyraEngine::calcCoords(Menu &menu) { _screen->_charWidth = widthBackup; } -void KyraEngine::gui_getInput() { +void KyraEngine_v1::gui_getInput() { Common::Event event; static uint32 lastScreenUpdate = 0; uint32 now = _system->getMillis(); @@ -841,22 +841,22 @@ void KyraEngine::gui_getInput() { _system->delayMillis(3); } -int KyraEngine::gui_resumeGame(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_resumeGame()"); +int KyraEngine_v1::gui_resumeGame(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_resumeGame()"); processMenuButton(button); _displayMenu = false; return 0; } -const char *KyraEngine::getSavegameFilename(int num) { +const char *KyraEngine_v1::getSavegameFilename(int num) { static char saveLoadSlot[12]; sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num); return saveLoadSlot; } -int KyraEngine::getNextSavegameSlot() { +int KyraEngine_v1::getNextSavegameSlot() { Common::InSaveFile *in; for (int i = 1; i < 1000; i++) { @@ -869,7 +869,7 @@ int KyraEngine::getNextSavegameSlot() { return 0; } -void KyraEngine::setupSavegames(Menu &menu, int num) { +void KyraEngine_v1::setupSavegames(Menu &menu, int num) { Common::InSaveFile *in; static char savenames[5][31]; uint8 startSlot; @@ -900,8 +900,8 @@ void KyraEngine::setupSavegames(Menu &menu, int num) { } } -int KyraEngine::gui_saveGameMenu(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGameMenu()"); +int KyraEngine_v1::gui_saveGameMenu(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_saveGameMenu()"); processMenuButton(button); _menu[2].item[5].enabled = true; @@ -911,7 +911,7 @@ int KyraEngine::gui_saveGameMenu(Button *button) { _menu[2].menuName = _guiStrings[8]; // Select a position to save to: _specialSavegameString = _guiStrings[9]; // [ EMPTY SLOT ] for (int i = 0; i < 5; i++) - _menu[2].item[i].callback = &KyraEngine::gui_saveGame; + _menu[2].item[i].callback = &KyraEngine_v1::gui_saveGame; _savegameOffset = 0; setupSavegames(_menu[2], 5); @@ -940,8 +940,8 @@ int KyraEngine::gui_saveGameMenu(Button *button) { return 0; } -int KyraEngine::gui_loadGameMenu(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGameMenu()"); +int KyraEngine_v1::gui_loadGameMenu(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_loadGameMenu()"); if (_menuDirectlyToLoad) { _menu[2].item[5].enabled = false; } else { @@ -955,7 +955,7 @@ int KyraEngine::gui_loadGameMenu(Button *button) { _specialSavegameString = _newGameString[0]; //[ START A NEW GAME ] _menu[2].menuName = _guiStrings[7]; // Which game would you like to reload? for (int i = 0; i < 5; i++) - _menu[2].item[i].callback = &KyraEngine::gui_loadGame; + _menu[2].item[i].callback = &KyraEngine_v1::gui_loadGame; _savegameOffset = 0; setupSavegames(_menu[2], 5); @@ -987,7 +987,7 @@ int KyraEngine::gui_loadGameMenu(Button *button) { return 0; } -void KyraEngine::gui_redrawTextfield() { +void KyraEngine_v1::gui_redrawTextfield() { _screen->fillRect(38, 91, 287, 102, 250); _text->printText(_savegameName, 38, 92, 253, 0, 0); @@ -999,7 +999,7 @@ void KyraEngine::gui_redrawTextfield() { _screen->updateScreen(); } -void KyraEngine::gui_updateSavegameString() { +void KyraEngine_v1::gui_updateSavegameString() { int length; if (_keyPressed.keycode) { @@ -1026,8 +1026,8 @@ void KyraEngine::gui_updateSavegameString() { _keyPressed.reset(); } -int KyraEngine::gui_saveGame(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGame()"); +int KyraEngine_v1::gui_saveGame(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_saveGame()"); processMenuButton(button); _gameToLoad = button->specialValue; @@ -1074,16 +1074,16 @@ int KyraEngine::gui_saveGame(Button *button) { return 0; } -int KyraEngine::gui_savegameConfirm(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_savegameConfirm()"); +int KyraEngine_v1::gui_savegameConfirm(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_savegameConfirm()"); processMenuButton(button); _displaySubMenu = false; return 0; } -int KyraEngine::gui_loadGame(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGame()"); +int KyraEngine_v1::gui_loadGame(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_loadGame()"); processMenuButton(button); _displaySubMenu = false; _gameToLoad = button->specialValue; @@ -1091,8 +1091,8 @@ int KyraEngine::gui_loadGame(Button *button) { return 0; } -int KyraEngine::gui_cancelSubMenu(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_cancelLoadGameMenu()"); +int KyraEngine_v1::gui_cancelSubMenu(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_cancelLoadGameMenu()"); processMenuButton(button); _displaySubMenu = false; _cancelSubMenu = true; @@ -1100,8 +1100,8 @@ int KyraEngine::gui_cancelSubMenu(Button *button) { return 0; } -int KyraEngine::gui_quitPlaying(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitPlaying()"); +int KyraEngine_v1::gui_quitPlaying(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitPlaying()"); processMenuButton(button); if (gui_quitConfirm(_guiStrings[14])) { // Are you sure you want to quit playing? @@ -1114,8 +1114,8 @@ int KyraEngine::gui_quitPlaying(Button *button) { return 0; } -bool KyraEngine::gui_quitConfirm(const char *str) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirm()"); +bool KyraEngine_v1::gui_quitConfirm(const char *str) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirm()"); _screen->loadPageFromDisk("SEENPAGE.TMP", 0); _screen->savePageToDisk("SEENPAGE.TMP", 0); @@ -1139,8 +1139,8 @@ bool KyraEngine::gui_quitConfirm(const char *str) { return !_cancelSubMenu; } -int KyraEngine::gui_quitConfirmYes(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmYes()"); +int KyraEngine_v1::gui_quitConfirmYes(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirmYes()"); processMenuButton(button); _displaySubMenu = false; _cancelSubMenu = false; @@ -1148,8 +1148,8 @@ int KyraEngine::gui_quitConfirmYes(Button *button) { return 0; } -int KyraEngine::gui_quitConfirmNo(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmNo()"); +int KyraEngine_v1::gui_quitConfirmNo(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirmNo()"); processMenuButton(button); _displaySubMenu = false; _cancelSubMenu = true; @@ -1157,8 +1157,8 @@ int KyraEngine::gui_quitConfirmNo(Button *button) { return 0; } -int KyraEngine::gui_gameControlsMenu(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_gameControlsMenu()"); +int KyraEngine_v1::gui_gameControlsMenu(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_gameControlsMenu()"); readSettings(); @@ -1175,14 +1175,14 @@ int KyraEngine::gui_gameControlsMenu(Button *button) { } _menu[5].item[3].labelString = _voiceTextString; //"Voice / Text " - _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeVoice; + _menu[5].item[3].callback = &KyraEngine_v1::gui_controlsChangeVoice; } else { //_menu[5].height = 136; //_menu[5].item[5].y = 110; _menu[5].item[4].enabled = 0; _menu[5].item[3].labelString = _textSpeedString; // "Text speed " - _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeText; + _menu[5].item[3].callback = &KyraEngine_v1::gui_controlsChangeText; } gui_setupControls(_menu[5]); @@ -1208,8 +1208,8 @@ int KyraEngine::gui_gameControlsMenu(Button *button) { return 0; } -void KyraEngine::gui_setupControls(Menu &menu) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_setupControls()"); +void KyraEngine_v1::gui_setupControls(Menu &menu) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_setupControls()"); switch (_configMusic) { case 0: @@ -1299,8 +1299,8 @@ void KyraEngine::gui_setupControls(Menu &menu) { initMenu(menu); } -int KyraEngine::gui_controlsChangeMusic(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeMusic()"); +int KyraEngine_v1::gui_controlsChangeMusic(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeMusic()"); processMenuButton(button); _configMusic = ++_configMusic % (_flags.platform == Common::kPlatformFMTowns ? 3 : 2); @@ -1308,8 +1308,8 @@ int KyraEngine::gui_controlsChangeMusic(Button *button) { return 0; } -int KyraEngine::gui_controlsChangeSounds(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeSounds()"); +int KyraEngine_v1::gui_controlsChangeSounds(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeSounds()"); processMenuButton(button); _configSounds = !_configSounds; @@ -1317,8 +1317,8 @@ int KyraEngine::gui_controlsChangeSounds(Button *button) { return 0; } -int KyraEngine::gui_controlsChangeWalk(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeWalk()"); +int KyraEngine_v1::gui_controlsChangeWalk(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeWalk()"); processMenuButton(button); _configWalkspeed = ++_configWalkspeed % 5; @@ -1327,8 +1327,8 @@ int KyraEngine::gui_controlsChangeWalk(Button *button) { return 0; } -int KyraEngine::gui_controlsChangeText(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeText()"); +int KyraEngine_v1::gui_controlsChangeText(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeText()"); processMenuButton(button); _configTextspeed = ++_configTextspeed % 4; @@ -1336,8 +1336,8 @@ int KyraEngine::gui_controlsChangeText(Button *button) { return 0; } -int KyraEngine::gui_controlsChangeVoice(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeVoice()"); +int KyraEngine_v1::gui_controlsChangeVoice(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeVoice()"); processMenuButton(button); _configVoice = ++_configVoice % 3; @@ -1345,14 +1345,14 @@ int KyraEngine::gui_controlsChangeVoice(Button *button) { return 0; } -int KyraEngine::gui_controlsApply(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsApply()"); +int KyraEngine_v1::gui_controlsApply(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsApply()"); writeSettings(); return gui_cancelSubMenu(button); } -int KyraEngine::gui_scrollUp(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollUp()"); +int KyraEngine_v1::gui_scrollUp(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_scrollUp()"); processMenuButton(button); if (_savegameOffset > 0) { @@ -1363,8 +1363,8 @@ int KyraEngine::gui_scrollUp(Button *button) { return 0; } -int KyraEngine::gui_scrollDown(Button *button) { - debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollDown()"); +int KyraEngine_v1::gui_scrollDown(Button *button) { + debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_scrollDown()"); processMenuButton(button); _savegameOffset++; @@ -1374,7 +1374,7 @@ int KyraEngine::gui_scrollDown(Button *button) { return 0; } -void KyraEngine::gui_processHighlights(Menu &menu) { +void KyraEngine_v1::gui_processHighlights(Menu &menu) { int x1, y1, x2, y2; Common::Point mouse = getMousePos(); @@ -1403,7 +1403,7 @@ void KyraEngine::gui_processHighlights(Menu &menu) { } } -void KyraEngine::gui_redrawText(Menu menu) { +void KyraEngine_v1::gui_redrawText(Menu menu) { int textX; int i = menu.highlightedItem; @@ -1422,7 +1422,7 @@ void KyraEngine::gui_redrawText(Menu menu) { _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].textColor, 0, 0); } -void KyraEngine::gui_redrawHighlight(Menu menu) { +void KyraEngine_v1::gui_redrawHighlight(Menu menu) { int textX; int i = menu.highlightedItem; @@ -1441,7 +1441,7 @@ void KyraEngine::gui_redrawHighlight(Menu menu) { _text->printText(menu.item[i].itemString, textX, textY, menu.item[i].highlightColor, 0, 0); } -void KyraEngine::gui_fadePalette() { +void KyraEngine_v1::gui_fadePalette() { if (_flags.platform == Common::kPlatformAmiga) return; @@ -1461,7 +1461,7 @@ void KyraEngine::gui_fadePalette() { _screen->fadePalette(_screen->_currentPalette, 2); } -void KyraEngine::gui_restorePalette() { +void KyraEngine_v1::gui_restorePalette() { if (_flags.platform == Common::kPlatformAmiga) return; @@ -1471,169 +1471,35 @@ void KyraEngine::gui_restorePalette() { #pragma mark - -// Kyra 2 and 3 main menu +void KyraEngine_v1::drawAmulet() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::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}; -void KyraEngine::gui_updateMainMenuAnimation() { - _screen->updateScreen(); -} - -bool KyraEngine::gui_mainMenuGetInput() { - Common::Event event; - - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_QUIT: - quitGame(); - break; - case Common::EVENT_LBUTTONUP: - return true; - default: - break; - } - } - return false; -} - -int KyraEngine::gui_handleMainMenu() { - debugC(9, kDebugLevelMain, "KyraEngine::gui_handleMainMenu()"); - int command = -1; - - uint8 colorMap[16]; - memset(colorMap, 0, sizeof(colorMap)); - _screen->setTextColorMap(colorMap); - - const char * const *strings = &_mainMenuStrings[_lang << 2]; - Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT); - int charWidthBackUp = _screen->_charWidth; - - _screen->_charWidth = -2; - _screen->setScreenDim(3); - int backUpX = _screen->_curDim->sx; - int backUpY = _screen->_curDim->sy; - int backUpWidth = _screen->_curDim->w; - int backUpHeight = _screen->_curDim->h; - _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3); - - int x = _screen->_curDim->sx << 3; - int y = _screen->_curDim->sy; - int width = _screen->_curDim->w << 3; - int height = _screen->_curDim->h; - - gui_drawMainBox(x, y, width, height, 1); - gui_drawMainBox(x + 1, y + 1, width - 2, height - 2, 0); - - int selected = 0; - - gui_drawMainMenu(strings, selected); - - _screen->showMouse(); - - int fh = _screen->getFontHeight(); - int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3; - - Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4); - - while (!_quitFlag) { - gui_updateMainMenuAnimation(); - bool mousePressed = gui_mainMenuGetInput(); - - Common::Point mouse = getMousePos(); - if (menuRect.contains(mouse)) { - int item = (mouse.y - menuRect.top) / fh; - - if (item != selected) { - gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5); - gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5); + resetGameFlag(0xF1); + _screen->hideMouse(); - selected = item; - } + int i = 0; + while (amuletTable1[i] != -1) { + if (queryGameFlag(87)) + _screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0); - if (mousePressed) { - // TODO: Flash the text - command = item; - break; - } - } - _system->delayMillis(10); - } - - if (_quitFlag) - command = -1; - - _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0); - _screen->_charWidth = charWidthBackUp; - _screen->setFont(oldFont); - - return command; -} - -void KyraEngine::gui_drawMainMenu(const char * const *strings, int select) { - debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainMenu(%p)", (const void*)strings); - static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 }; - - int top = _screen->_curDim->sy; - top += menuTable[1]; - - for (int i = 0; i < menuTable[3]; ++i) { - int curY = top + i * _screen->getFontHeight(); - int color = (i == select) ? menuTable[6] : menuTable[5]; - gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5); - } -} + if (queryGameFlag(89)) + _screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0); -void KyraEngine::gui_drawMainBox(int x, int y, int w, int h, int fill) { - debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill); - static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 }; - static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 }; - - const uint8 *colorTable; - if (_flags.gameID == GI_KYRA3) - colorTable = kyra3ColorTable; - else - colorTable = kyra2ColorTable; - - --w; --h; + if (queryGameFlag(86)) + _screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0); - if (fill) - _screen->fillRect(x, y, x+w, y+h, colorTable[0]); - - _screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]); - _screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]); - _screen->drawClippedLine(x, y, x+w, y, colorTable[2]); - _screen->drawClippedLine(x, y, x, y+h, colorTable[2]); - - _screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]); - _screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]); -} + if (queryGameFlag(88)) + _screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0); -void KyraEngine::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) { - debugC(9, kDebugLevelMain, "KyraEngine::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags); - if (!format) - return; - - char string[512]; - va_list vaList; - va_start(vaList, flags); - vsprintf(string, format, vaList); - va_end(vaList); - - if (flags & 1) - x -= _screen->getTextWidth(string) >> 1; - - if (flags & 2) - x -= _screen->getTextWidth(string); - - if (flags & 4) { - _screen->printText(string, x - 1, y, 240, col2); - _screen->printText(string, x, y + 1, 240, col2); + _screen->updateScreen(); + delayWithTicks(3); + i++; } - - if (flags & 8) { - _screen->printText(string, x - 1, y, 227, col2); - _screen->printText(string, x, y + 1, 227, col2); - } - - _screen->printText(string, x, y, col1, col2); + _screen->showMouse(); } } // end of namespace Kyra diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp new file mode 100644 index 0000000000..838d347f8f --- /dev/null +++ b/engines/kyra/gui_v2.cpp @@ -0,0 +1,198 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra.h" +#include "kyra/kyra_v2.h" +#include "kyra/screen.h" + +namespace Kyra { + +void KyraEngine_v2::gui_updateMainMenuAnimation() { + _screen->updateScreen(); +} + +bool KyraEngine_v2::gui_mainMenuGetInput() { + Common::Event event; + + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + quitGame(); + break; + case Common::EVENT_LBUTTONUP: + return true; + default: + break; + } + } + return false; +} + +int KyraEngine_v2::gui_handleMainMenu() { + debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_handleMainMenu()"); + int command = -1; + + uint8 colorMap[16]; + memset(colorMap, 0, sizeof(colorMap)); + _screen->setTextColorMap(colorMap); + + const char * const *strings = &_mainMenuStrings[_lang << 2]; + Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT); + int charWidthBackUp = _screen->_charWidth; + + _screen->_charWidth = -2; + if (_flags.gameID == GI_KYRA2) + _screen->setScreenDim(11); + else + _screen->setScreenDim(3); + int backUpX = _screen->_curDim->sx; + int backUpY = _screen->_curDim->sy; + int backUpWidth = _screen->_curDim->w; + int backUpHeight = _screen->_curDim->h; + _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3); + + int x = _screen->_curDim->sx << 3; + int y = _screen->_curDim->sy; + int width = _screen->_curDim->w << 3; + int height = _screen->_curDim->h; + + gui_drawMainBox(x, y, width, height, 1); + gui_drawMainBox(x + 1, y + 1, width - 2, height - 2, 0); + + int selected = 0; + + gui_drawMainMenu(strings, selected); + + _screen->showMouse(); + + int fh = _screen->getFontHeight(); + int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3; + + Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4); + + while (!_quitFlag) { + gui_updateMainMenuAnimation(); + bool mousePressed = gui_mainMenuGetInput(); + + Common::Point mouse = getMousePos(); + if (menuRect.contains(mouse)) { + int item = (mouse.y - menuRect.top) / fh; + + if (item != selected) { + gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5); + gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5); + + selected = item; + } + + if (mousePressed) { + // TODO: Flash the text + command = item; + break; + } + } + _system->delayMillis(10); + } + + if (_quitFlag) + command = -1; + + _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0); + _screen->_charWidth = charWidthBackUp; + _screen->setFont(oldFont); + + return command; +} + +void KyraEngine_v2::gui_drawMainMenu(const char * const *strings, int select) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainMenu(%p)", (const void*)strings); + static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 }; + + int top = _screen->_curDim->sy; + top += menuTable[1]; + + for (int i = 0; i < menuTable[3]; ++i) { + int curY = top + i * _screen->getFontHeight(); + int color = (i == select) ? menuTable[6] : menuTable[5]; + gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5); + } +} + +void KyraEngine_v2::gui_drawMainBox(int x, int y, int w, int h, int fill) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill); + static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 }; + static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 }; + + const uint8 *colorTable; + if (_flags.gameID == GI_KYRA3) + colorTable = kyra3ColorTable; + else + colorTable = kyra2ColorTable; + + --w; --h; + + if (fill) + _screen->fillRect(x, y, x+w, y+h, colorTable[0]); + + _screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]); + _screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]); + _screen->drawClippedLine(x, y, x+w, y, colorTable[2]); + _screen->drawClippedLine(x, y, x, y+h, colorTable[2]); + + _screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]); + _screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]); +} + +void KyraEngine_v2::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags); + if (!format) + return; + + char string[512]; + va_list vaList; + va_start(vaList, flags); + vsprintf(string, format, vaList); + va_end(vaList); + + if (flags & 1) + x -= _screen->getTextWidth(string) >> 1; + + if (flags & 2) + x -= _screen->getTextWidth(string); + + if (flags & 4) { + _screen->printText(string, x - 1, y, 240, col2); + _screen->printText(string, x, y + 1, 240, col2); + } + + if (flags & 8) { + _screen->printText(string, x - 1, y, 227, col2); + _screen->printText(string, x, y + 1, 227, col2); + } + + _screen->printText(string, x, y, col1, col2); +} + +} // end of namespace Kyra diff --git a/engines/kyra/items.cpp b/engines/kyra/items_v1.cpp index 2a1a08b7de..84b76c59a6 100644 --- a/engines/kyra/items.cpp +++ b/engines/kyra/items_v1.cpp @@ -23,14 +23,14 @@ * */ -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/seqplayer.h" #include "kyra/screen.h" #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" #include "kyra/text.h" #include "common/system.h" @@ -38,7 +38,7 @@ namespace Kyra { -int KyraEngine::findDuplicateItemShape(int shape) { +int KyraEngine_v1::findDuplicateItemShape(int shape) { static uint8 dupTable[] = { 0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47, 0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a, @@ -55,8 +55,8 @@ int KyraEngine::findDuplicateItemShape(int shape) { return -1; } -void KyraEngine::addToNoDropRects(int x, int y, int w, int h) { - debugC(9, kDebugLevelMain, "KyraEngine::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h); +void KyraEngine_v1::addToNoDropRects(int x, int y, int w, int h) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h); for (int rect = 0; rect < 11; ++rect) { if (_noDropRects[rect].x == -1) { _noDropRects[rect].x = x; @@ -68,13 +68,13 @@ void KyraEngine::addToNoDropRects(int x, int y, int w, int h) { } } -void KyraEngine::clearNoDropRects() { - debugC(9, kDebugLevelMain, "KyraEngine::clearNoDropRects()"); +void KyraEngine_v1::clearNoDropRects() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::clearNoDropRects()"); memset(_noDropRects, -1, sizeof(_noDropRects)); } -byte KyraEngine::findFreeItemInScene(int scene) { - debugC(9, kDebugLevelMain, "KyraEngine::findFreeItemInScene(%d)", scene); +byte KyraEngine_v1::findFreeItemInScene(int scene) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::findFreeItemInScene(%d)", scene); assert(scene < _roomTableSize); Room *room = &_roomTable[scene]; for (int i = 0; i < 12; ++i) { @@ -84,8 +84,8 @@ byte KyraEngine::findFreeItemInScene(int scene) { return 0xFF; } -byte KyraEngine::findItemAtPos(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine::findItemAtPos(%d, %d)", x, y); +byte KyraEngine_v1::findItemAtPos(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::findItemAtPos(%d, %d)", x, y); assert(_currentCharacter->sceneId < _roomTableSize); const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable; const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos; @@ -120,8 +120,8 @@ byte KyraEngine::findItemAtPos(int x, int y) { return returnValue; } -void KyraEngine::placeItemInGenericMapScene(int item, int index) { - debugC(9, kDebugLevelMain, "KyraEngine::placeItemInGenericMapScene(%d, %d)", item, index); +void KyraEngine_v1::placeItemInGenericMapScene(int item, int index) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::placeItemInGenericMapScene(%d, %d)", item, index); static const uint16 itemMapSceneMinTable[] = { 0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000 }; @@ -175,32 +175,32 @@ void KyraEngine::placeItemInGenericMapScene(int item, int index) { } } -void KyraEngine::createMouseItem(int item) { - debugC(9, kDebugLevelMain, "KyraEngine::createMouseItem(%d)", item); +void KyraEngine_v1::createMouseItem(int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::createMouseItem(%d)", item); _screen->hideMouse(); setMouseItem(item); _itemInHand = item; _screen->showMouse(); } -void KyraEngine::destroyMouseItem() { - debugC(9, kDebugLevelMain, "KyraEngine::destroyMouseItem()"); +void KyraEngine_v1::destroyMouseItem() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::destroyMouseItem()"); _screen->hideMouse(); _screen->setMouseCursor(1, 1, _shapes[0]); _itemInHand = -1; _screen->showMouse(); } -void KyraEngine::setMouseItem(int item) { - debugC(9, kDebugLevelMain, "KyraEngine::setMouseItem(%d)", item); +void KyraEngine_v1::setMouseItem(int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setMouseItem(%d)", item); if (item == -1) _screen->setMouseCursor(1, 1, _shapes[6]); else _screen->setMouseCursor(8, 15, _shapes[216+item]); } -void KyraEngine::wipeDownMouseItem(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::wipeDownMouseItem(%d, %d)", xpos, ypos); +void KyraEngine_v1::wipeDownMouseItem(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::wipeDownMouseItem(%d, %d)", xpos, ypos); if (_itemInHand == -1) return; xpos -= 8; @@ -226,8 +226,8 @@ void KyraEngine::wipeDownMouseItem(int xpos, int ypos) { _screen->showMouse(); } -void KyraEngine::setupSceneItems() { - debugC(9, kDebugLevelMain, "KyraEngine::setupSceneItems()"); +void KyraEngine_v1::setupSceneItems() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneItems()"); uint16 sceneId = _currentCharacter->sceneId; assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; @@ -264,8 +264,8 @@ void KyraEngine::setupSceneItems() { } } -int KyraEngine::countItemsInScene(uint16 sceneId) { - debugC(9, kDebugLevelMain, "KyraEngine::countItemsInScene(%d)", sceneId); +int KyraEngine_v1::countItemsInScene(uint16 sceneId) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::countItemsInScene(%d)", sceneId); assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; @@ -279,8 +279,8 @@ int KyraEngine::countItemsInScene(uint16 sceneId) { return items; } -int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) { - debugC(9, kDebugLevelMain, "KyraEngine::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2); +int KyraEngine_v1::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2); int freeItem = -1; uint8 itemIndex = findItemAtPos(x, y); if (unk1) @@ -432,8 +432,8 @@ int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int un return 1; } -void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { - debugC(9, kDebugLevelMain, "KyraEngine::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex); +void KyraEngine_v1::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex); _screen->hideMouse(); _animator->animRemoveGameItem(itemIndex); assert(sceneId < _roomTableSize); @@ -452,8 +452,8 @@ void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) { clickEventHandler2(); } -void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y); +void KyraEngine_v1::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y); assert(sceneId < _roomTableSize); Room *currentRoom = &_roomTable[sceneId]; currentRoom->itemsTable[itemIndex] = item; @@ -462,8 +462,8 @@ void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, currentRoom->needInit[itemIndex] = 1; } -int KyraEngine::checkNoDropRects(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine::checkNoDropRects(%d, %d)", x, y); +int KyraEngine_v1::checkNoDropRects(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::checkNoDropRects(%d, %d)", x, y); if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16) _lastProcessedItemHeight = 16; if (_noDropRects[0].x == -1) @@ -492,8 +492,8 @@ int KyraEngine::checkNoDropRects(int x, int y) { return 0; } -int KyraEngine::isDropable(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine::isDropable(%d, %d)", x, y); +int KyraEngine_v1::isDropable(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::isDropable(%d, %d)", x, y); x -= 8; y -= 1; @@ -507,8 +507,8 @@ int KyraEngine::isDropable(int x, int y) { return 1; } -void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) { - debugC(9, kDebugLevelMain, "KyraEngine::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item); +void KyraEngine_v1::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item); assert(_currentCharacter->sceneId < _roomTableSize); Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; if (x == destX && y == destY) { @@ -591,8 +591,8 @@ void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, _screen->showMouse(); } -void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) { - debugC(9, kDebugLevelMain, "KyraEngine::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2); +void KyraEngine_v1::dropItem(int unk1, int item, int x, int y, int unk2) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2); if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2)) return; snd_playSoundEffect(54); @@ -603,16 +603,16 @@ void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) { drawSentenceCommand(_noDropList[1], 6); } -void KyraEngine::itemSpecialFX(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX(%d, %d, %d)", x, y, item); +void KyraEngine_v1::itemSpecialFX(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX(%d, %d, %d)", x, y, item); if (item == 41) itemSpecialFX1(x, y, item); else itemSpecialFX2(x, y, item); } -void KyraEngine::itemSpecialFX1(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX1(%d, %d, %d)", x, y, item); +void KyraEngine_v1::itemSpecialFX1(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX1(%d, %d, %d)", x, y, item); uint8 *shape = _shapes[216+item]; x -= 8; int startY = y; @@ -632,8 +632,8 @@ void KyraEngine::itemSpecialFX1(int x, int y, int item) { _screen->showMouse(); } -void KyraEngine::itemSpecialFX2(int x, int y, int item) { - debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX2(%d, %d, %d)", x, y, item); +void KyraEngine_v1::itemSpecialFX2(int x, int y, int item) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX2(%d, %d, %d)", x, y, item); x -= 8; y -= 15; int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF); @@ -660,8 +660,8 @@ void KyraEngine::itemSpecialFX2(int x, int y, int item) { restoreItemRect0(x, y); } -void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) { - debugC(9, kDebugLevelMain, "KyraEngine::magicOutMouseItem(%d, %d)", animIndex, itemPos); +void KyraEngine_v1::magicOutMouseItem(int animIndex, int itemPos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::magicOutMouseItem(%d, %d)", animIndex, itemPos); int videoPageBackUp = _screen->_curPage; _screen->_curPage = 0; int x = 0, y = 0; @@ -744,8 +744,8 @@ void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) { _screen->_curPage = videoPageBackUp; } -void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) { - debugC(9, kDebugLevelMain, "KyraEngine::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos); +void KyraEngine_v1::magicInMouseItem(int animIndex, int item, int itemPos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos); int videoPageBackUp = _screen->_curPage; _screen->_curPage = 0; int x = 0, y = 0; @@ -817,8 +817,8 @@ void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) { _screen->_curPage = videoPageBackUp; } -void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) { - debugC(9, kDebugLevelMain, "KyraEngine::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops); +void KyraEngine_v1::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops); static const uint8 table1[] = { 0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00 }; @@ -840,8 +840,8 @@ void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops); } -void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) { - debugC(9, kDebugLevelMain, "KyraEngine::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops); +void KyraEngine_v1::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops); uint8 shapeColorTable[16]; uint8 *shapePtr = _shapes[shape] + 10; if (_flags.useAltShapeHeader) @@ -859,8 +859,8 @@ void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableVal _screen->drawShape(0, _shapes[shape], x, y, 0, 0x8000, shapeColorTable); } -void KyraEngine::updatePlayerItemsForScene() { - debugC(9, kDebugLevelMain, "KyraEngine::updatePlayerItemsForScene()"); +void KyraEngine_v1::updatePlayerItemsForScene() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::updatePlayerItemsForScene()"); if (_itemInHand >= 29 && _itemInHand < 33) { ++_itemInHand; if (_itemInHand > 33) @@ -900,7 +900,7 @@ void KyraEngine::updatePlayerItemsForScene() { _screen->showMouse(); } -void KyraEngine::redrawInventory(int page) { +void KyraEngine_v1::redrawInventory(int page) { int videoPageBackUp = _screen->_curPage; _screen->_curPage = page; _screen->hideMouse(); @@ -916,26 +916,26 @@ void KyraEngine::redrawInventory(int page) { _screen->updateScreen(); } -void KyraEngine::backUpItemRect0(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::backUpItemRect0(%d, %d)", xpos, ypos); +void KyraEngine_v1::backUpItemRect0(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect0(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 3<<3, 24); _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]); } -void KyraEngine::restoreItemRect0(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::restoreItemRect0(%d, %d)", xpos, ypos); +void KyraEngine_v1::restoreItemRect0(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect0(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 3<<3, 24); _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]); } -void KyraEngine::backUpItemRect1(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::backUpItemRect1(%d, %d)", xpos, ypos); +void KyraEngine_v1::backUpItemRect1(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect1(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 4<<3, 32); _screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } -void KyraEngine::restoreItemRect1(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::restoreItemRect1(%d, %d)", xpos, ypos); +void KyraEngine_v1::restoreItemRect1(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect1(%d, %d)", xpos, ypos); _screen->rectClip(xpos, ypos, 4<<3, 32); _screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]); } diff --git a/engines/kyra/items_v2.cpp b/engines/kyra/items_v2.cpp new file mode 100644 index 0000000000..fd4c7a5fab --- /dev/null +++ b/engines/kyra/items_v2.cpp @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v2.h" + +namespace Kyra { + +int KyraEngine_v2::findFreeItem() { + for (int i = 0; i < 30; ++i) { + if (_itemList[i].id == 0xFFFF) + return i; + } + return -1; +} + +int KyraEngine_v2::findItem(uint16 sceneId, int id) { + for (int i = 0; i < 30; ++i) { + if (_itemList[i].id == id && _itemList[i].sceneId == sceneId) + return i; + } + return -1; +} + +void KyraEngine_v2::resetItemList() { + for (int i = 0; i < 30; ++i) { + _itemList[i].id = 0xFFFF; + _itemList[i].sceneId = 0xFFFF; + _itemList[i].x = 0; + _itemList[i].y = 0; + _itemList[i].unk7 = 0; + } +} + +} // end of namespace Kyra diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp index 1664ce144f..1d8d7440f0 100644 --- a/engines/kyra/kyra.cpp +++ b/engines/kyra/kyra.cpp @@ -26,91 +26,38 @@ #include "common/stdafx.h" #include "common/config-manager.h" -#include "common/file.h" -#include "common/events.h" -#include "common/system.h" -#include "common/savefile.h" -#include "sound/mixer.h" #include "sound/mididrv.h" - -#include "gui/message.h" +#include "sound/mixer.h" #include "kyra/kyra.h" +#include "kyra/sound.h" #include "kyra/resource.h" #include "kyra/screen.h" -#include "kyra/script.h" -#include "kyra/seqplayer.h" -#include "kyra/sound.h" -#include "kyra/sprites.h" -#include "kyra/wsamovie.h" -#include "kyra/animator.h" #include "kyra/text.h" -#include "kyra/debugger.h" +#include "kyra/timer.h" +#include "kyra/script.h" namespace Kyra { KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags) : Engine(system) { - _flags = flags; - - _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm = - _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 = - _seq_Demo4 = 0; - - _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0; - _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0; - - _roomFilenameTable = _characterImageTable = 0; - _roomFilenameTableSize = _characterImageTableSize = 0; - _itemList = _takenList = _placedList = _droppedList = _noDropList = 0; - _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0; - _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0; - _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0; - _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0; - _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0; - _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0; - - _defaultShapeTable = 0; - _healingShapeTable = _healingShape2Table = 0; - _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0; - _posionDeathShapeTable = _fluteAnimShapeTable = 0; - _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0; - _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0; - _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0; - _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0; - _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0; - memset(&_specialPalettes, 0, sizeof(_specialPalettes)); - _debugger = 0; - _sprites = 0; - _animator = 0; - _screen = 0; _res = 0; _sound = 0; - _seq = 0; - _scriptInterpreter = 0; _text = 0; - _npcScriptData = 0; - _scriptMain = 0; - _scriptClickData = 0; - _scriptClick = 0; - _characterList = 0; - _movFacingTable = 0; - memset(_shapes, 0, sizeof(_shapes)); - memset(_movieObjects, 0, sizeof(_movieObjects)); - _finalA = _finalB = _finalC = 0; - _endSequenceBackUpRect = 0; - memset(_panPagesTable, 0, sizeof(_panPagesTable)); - _npcScriptData = _scriptClickData = 0; - _scrollUpButton.process0PtrShape = _scrollUpButton.process1PtrShape = _scrollUpButton.process2PtrShape = 0; - _scrollDownButton.process0PtrShape = _scrollDownButton.process1PtrShape = _scrollDownButton.process2PtrShape = 0; - memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); + _staticres = 0; + _timer = 0; + _scriptInterpreter = 0; + + _flags = flags; + _gameSpeed = 60; + _tickLength = (uint8)(1000.0 / _gameSpeed); + _quitFlag = false; - _currHeadShape = 0; - - _curSfxFile = _curMusicTheme = 0; - - memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp)); + + _skipFlag = false; + + memset(_flagsTable, 0, sizeof(_flagsTable)); // sets up all engine specific debug levels Common::addSpecialDebugLevel(kDebugLevelScriptFuncs, "ScriptFuncs", "Script function debug level"); @@ -123,6 +70,7 @@ KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags) Common::addSpecialDebugLevel(kDebugLevelGUI, "GUI", "GUI debug level"); Common::addSpecialDebugLevel(kDebugLevelSequence, "Sequence", "Sequence debug level"); Common::addSpecialDebugLevel(kDebugLevelMovie, "Movie", "Movie debug level"); + Common::addSpecialDebugLevel(kDebugLevelTimer, "Timer", "Timer debug level"); } int KyraEngine::init() { @@ -133,18 +81,10 @@ int KyraEngine::init() { _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - - _screen = new Screen(this, _system); - assert(_screen); - if (!_screen->init()) - error("_screen->init() failed"); - - // for now we prefer Adlib over native MIDI + + // for now we prefer Adlib over native MIDI int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/); - // TODO: We should play the native Kyra 2 Adlib music, but until that - // is support, we'll use the automagic MIDI -> Adlib converter. - if (_flags.platform == Common::kPlatformFMTowns) { // no sfx enabled for CD audio music atm // later on here should be a usage of MixedSoundDriver @@ -183,155 +123,18 @@ int KyraEngine::init() { _res = new Resource(this); assert(_res); - _sprites = new Sprites(this, _system); - assert(_sprites); - _seq = new SeqPlayer(this, _system); - assert(_seq); - _animator = new ScreenAnimator(this, _system); - assert(_animator); - _animator->init(5, 11, 12); - assert(*_animator); - _text = new TextDisplayer(this, _screen); + _text = new TextDisplayer(this, this->screen()); assert(_text); - _staticres = new StaticResource(this); assert(_staticres); if (!_staticres->init()) error("_staticres->init() failed"); - - initStaticResource(); - - if (!_sound->init()) - error("Couldn't init sound"); - - if (_flags.platform == Common::kPlatformFMTowns) - _sound->setSoundFileList(_soundFilesTowns, _soundFilesTownsCount); - else - _sound->setSoundFileList(_soundFiles, _soundFilesCount); - - _sound->setVolume(255); - _sound->loadSoundFile(0); - - setupOpcodeTable(); - setupButtonData(); - setupMenu(); - - _paletteChanged = 1; - _currentCharacter = 0; - _characterList = new Character[11]; - assert(_characterList); - memset(_characterList, 0, sizeof(Character)*11); - - for (int i = 0; i < 11; ++i) - memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems)); - - _characterList[0].sceneId = 5; - _characterList[0].height = 48; - _characterList[0].facing = 3; - _characterList[0].currentAnimFrame = 7; - + _timer = new TimerManager(this, _system); + assert(_timer); _scriptInterpreter = new ScriptHelper(this); assert(_scriptInterpreter); - _npcScriptData = new ScriptData; - memset(_npcScriptData, 0, sizeof(ScriptData)); - assert(_npcScriptData); - _npcScript = new ScriptState; - assert(_npcScript); - memset(_npcScript, 0, sizeof(ScriptState)); - - _scriptMain = new ScriptState; - assert(_scriptMain); - memset(_scriptMain, 0, sizeof(ScriptState)); - - _scriptClickData = new ScriptData; - assert(_scriptClickData); - memset(_scriptClickData, 0, sizeof(ScriptData)); - _scriptClick = new ScriptState; - assert(_scriptClick); - memset(_scriptClick, 0, sizeof(ScriptState)); - - _debugger = new Debugger(this); - assert(_debugger); - memset(_shapes, 0, sizeof(_shapes)); - - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) - _movieObjects[i] = createWSAMovie(); - - memset(_flagsTable, 0, sizeof(_flagsTable)); - - _abortWalkFlag = false; - _abortWalkFlag2 = false; - _talkingCharNum = -1; - _charSayUnk3 = -1; - memset(_currSentenceColor, 0, 3); - _startSentencePalIndex = -1; - _fadeText = false; - - _cauldronState = 0; - _crystalState[0] = _crystalState[1] = -1; - - _brandonStatusBit = 0; - _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10; - _brandonPosX = _brandonPosY = -1; - _deathHandler = 0xFF; - _poisonDeathCounter = 0; - - memset(_itemTable, 0, sizeof(_itemTable)); - memset(_exitList, 0xFFFF, sizeof(_exitList)); - _exitListPtr = 0; - _pathfinderFlag = _pathfinderFlag2 = 0; - _lastFindWayRet = 0; - _sceneChangeState = _loopFlag2 = 0; - _timerNextRun = 0; - - _movFacingTable = new int[150]; - assert(_movFacingTable); - _movFacingTable[0] = 8; - - registerDefaultSettings(); - readSettings(); - - _skipFlag = false; - - _marbleVaseItem = -1; - memset(_foyerItemTable, -1, sizeof(_foyerItemTable)); - _mouseState = _itemInHand = -1; - _handleInput = false; - - _currentRoom = 0xFFFF; - _scenePhasingFlag = 0; - _lastProcessedItem = 0; - _lastProcessedItemHeight = 16; - - _unkScreenVar1 = 1; - _unkScreenVar2 = 0; - _unkScreenVar3 = 0; - _unkAmuletVar = 0; - - _endSequenceNeedLoading = 1; - _malcolmFlag = 0; - _beadStateVar = 0; - _endSequenceSkipFlag = 0; - _unkEndSeqVar2 = 0; - _endSequenceBackUpRect = 0; - _unkEndSeqVar4 = 0; - _unkEndSeqVar5 = 0; - _lastDisplayedPanPage = 0; - memset(_panPagesTable, 0, sizeof(_panPagesTable)); - _finalA = _finalB = _finalC = 0; - memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState)); - _kyragemFadingState.gOffset = 0x13; - _kyragemFadingState.bOffset = 0x13; - - _mousePressFlag = false; - - _menuDirectlyToLoad = false; - - _lastMusicCommand = 0; - - _gameSpeed = 60; - _tickLength = (uint8)(1000.0 / _gameSpeed); + setupOpcodeTable(); _lang = 0; Common::Language lang = Common::parseLanguage(ConfMan.get("language")); @@ -363,216 +166,11 @@ int KyraEngine::init() { } KyraEngine::~KyraEngine() { - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) { - if (_movieObjects[i]) - _movieObjects[i]->close(); - delete _movieObjects[i]; - _movieObjects[i] = 0; - } - - closeFinalWsa(); - if (_scriptInterpreter) { - _scriptInterpreter->unloadScript(_npcScriptData); - _scriptInterpreter->unloadScript(_scriptClickData); - } - - Common::clearAllSpecialDebugLevels(); - - delete _debugger; - delete _sprites; - delete _animator; - delete _screen; delete _res; delete _sound; - delete _seq; - delete _scriptInterpreter; delete _text; - - delete _npcScriptData; - delete _scriptMain; - - delete _scriptClickData; - delete _scriptClick; - - delete [] _characterList; - - delete [] _movFacingTable; - - delete [] _scrollUpButton.process0PtrShape; - delete [] _scrollUpButton.process1PtrShape; - delete [] _scrollUpButton.process2PtrShape; - delete [] _scrollDownButton.process0PtrShape; - delete [] _scrollDownButton.process1PtrShape; - delete [] _scrollDownButton.process2PtrShape; - - delete [] _itemBkgBackUp[0]; - delete [] _itemBkgBackUp[1]; - - for (int i = 0; i < ARRAYSIZE(_shapes); ++i) { - if (_shapes[i] != 0) { - delete [] _shapes[i]; - for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) { - if (_shapes[i2] == _shapes[i] && i2 != i) { - _shapes[i2] = 0; - } - } - _shapes[i] = 0; - } - } - - for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) - delete [] _sceneAnimTable[i]; -} - -int KyraEngine::go() { - if (_res->getFileSize("6.FNT")) - _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); - _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); - _screen->setScreenDim(0); - - _abortIntroFlag = false; - - if (_flags.isDemo) { - seq_demo(); - } else { - setGameFlag(0xF3); - setGameFlag(0xFD); - setGameFlag(0xEF); - seq_intro(); - if (_quitFlag) - return 0; - if (_skipIntroFlag && _abortIntroFlag) - resetGameFlag(0xEF); - startup(); - resetGameFlag(0xEF); - mainLoop(); - } - return 0; -} - - -void KyraEngine::startup() { - debugC(9, kDebugLevelMain, "KyraEngine::startup()"); - static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 }; - _screen->setTextColorMap(colorMap); -// _screen->setFont(Screen::FID_6_FNT); - _screen->setAnimBlockPtr(3750); - memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); - loadMouseShapes(); - _currentCharacter = &_characterList[0]; - for (int i = 1; i < 5; ++i) - _animator->setCharacterDefaultFrame(i); - for (int i = 5; i <= 10; ++i) - setCharactersPositions(i); - _animator->setCharactersHeight(); - resetBrandonPoisonFlags(); - _screen->_curPage = 0; - // XXX - for (int i = 0; i < 12; ++i) { - int size = _screen->getRectSize(3, 24); - _shapes[361+i] = new byte[size]; - } - - _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)]; - memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24)); - _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)]; - memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32)); - - for (int i = 0; i < _roomTableSize; ++i) { - for (int item = 0; item < 12; ++item) { - _roomTable[i].itemsTable[item] = 0xFF; - _roomTable[i].itemsXPos[item] = 0xFFFF; - _roomTable[i].itemsYPos[item] = 0xFF; - _roomTable[i].needInit[item] = 0; - } - } - - loadCharacterShapes(); - loadSpecialEffectShapes(); - loadItems(); - loadButtonShapes(); - initMainButtonList(); - loadMainScreen(); - setupTimers(); - _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); - - // XXX - _animator->initAnimStateList(); - setCharactersInDefaultScene(); - - if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, &_opcodes)) - error("Could not load \"_STARTUP.EMC\" script"); - _scriptInterpreter->initScript(_scriptMain, _npcScriptData); - - if (!_scriptInterpreter->startScript(_scriptMain, 0)) - error("Could not start script function 0 of script \"_STARTUP.EMC\""); - - while (_scriptInterpreter->validScript(_scriptMain)) - _scriptInterpreter->runScript(_scriptMain); - - _scriptInterpreter->unloadScript(_npcScriptData); - - if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, &_opcodes)) - error("Could not load \"_NPC.EMC\" script"); - - snd_playTheme(1); - enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); - - if (_abortIntroFlag && _skipIntroFlag) { - _menuDirectlyToLoad = true; - _screen->setMouseCursor(1, 1, _shapes[0]); - _screen->showMouse(); - buttonMenuCallback(0); - _menuDirectlyToLoad = false; - } else - saveGame(getSavegameFilename(0), "New game"); -} - -void KyraEngine::mainLoop() { - debugC(9, kDebugLevelMain, "KyraEngine::mainLoop()"); - - while (!_quitFlag) { - int32 frameTime = (int32)_system->getMillis(); - _skipFlag = false; - - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - if (seq_playEnd() && _deathHandler != 8) - break; - } - - if (_deathHandler != 0xFF) { - snd_playWanderScoreViaMap(0, 1); - snd_playSoundEffect(49); - _screen->hideMouse(); - _screen->setMouseCursor(1, 1, _shapes[0]); - destroyMouseItem(); - _screen->showMouse(); - buttonMenuCallback(0); - _deathHandler = 0xFF; - } - - if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag) - _animator->animRefreshNPC(0); - - if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) { - _animator->animRefreshNPC(0); - _brandonStatusBit0x20Flag = 0; - } - - _screen->showMouse(); - - processButtonList(_buttonList); - updateMousePointer(); - updateGameTimers(); - updateTextFade(); - - _handleInput = true; - delay((frameTime + _gameSpeed) - _system->getMillis(), true, true); - _handleInput = false; - - _sound->process(); - } + delete _timer; + delete _scriptInterpreter; } void KyraEngine::quitGame() { @@ -581,209 +179,15 @@ void KyraEngine::quitGame() { // Nothing to do here } -void KyraEngine::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { - while (_system->getMillis() < timestamp && !_quitFlag) { - if (updateTimers) - updateGameTimers(); - - if (timestamp - _system->getMillis() >= 10) - delay(10, update, isMainLoop); - } -} - -void KyraEngine::delay(uint32 amount, bool update, bool isMainLoop) { - Common::Event event; - char saveLoadSlot[20]; - char savegameName[14]; - - uint32 start = _system->getMillis(); - do { - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && - (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) { - sprintf(saveLoadSlot, "%s.00%d", _targetName.c_str(), event.kbd.keycode - '0'); - if (event.kbd.flags == Common::KBD_CTRL) - loadGame(saveLoadSlot); - else { - sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); - saveGame(saveLoadSlot, savegameName); - } - } else if (event.kbd.flags == Common::KBD_CTRL) { - if (event.kbd.keycode == 'd') - _debugger->attach(); - else if (event.kbd.keycode == 'q') - _quitFlag = true; - } else if (event.kbd.keycode == '.') - _skipFlag = true; - else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { - _abortIntroFlag = true; - _skipFlag = true; - } - - break; - case Common::EVENT_MOUSEMOVE: - _animator->_updateScreen = true; - break; - case Common::EVENT_QUIT: - quitGame(); - break; - case Common::EVENT_LBUTTONDOWN: - _mousePressFlag = true; - break; - case Common::EVENT_LBUTTONUP: - _mousePressFlag = false; - - if (_abortWalkFlag2) - _abortWalkFlag = true; - - if (_handleInput) { - _handleInput = false; - processInput(); - _handleInput = true; - } else - _skipFlag = true; - - break; - default: - break; - } - } - - if (_debugger->isAttached()) - _debugger->onFrame(); - - if (update) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - updateTextFade(); - updateMousePointer(); - } - - if (_currentCharacter && _currentCharacter->sceneId == 210 && update) - updateKyragemFading(); - - if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) - _skipFlag = false; - - if (amount > 0 && !_skipFlag && !_quitFlag) - _system->delayMillis(10); - - if (_skipFlag) - _sound->voiceStop(); - } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag); -} - Common::Point KyraEngine::getMousePos() const { Common::Point mouse = _eventMan->getMousePos(); + if (_flags.useHiResOverlay) { mouse.x >>= 1; mouse.y >>= 1; } - return mouse; -} - -void KyraEngine::waitForEvent() { - bool finished = false; - Common::Event event; - - while (!finished && !_quitFlag) { - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - finished = true; - break; - case Common::EVENT_QUIT: - quitGame(); - break; - case Common::EVENT_LBUTTONDOWN: - finished = true; - _skipFlag = true; - break; - default: - break; - } - } - - if (_debugger->isAttached()) - _debugger->onFrame(); - - _system->delayMillis(10); - } -} - -void KyraEngine::delayWithTicks(int ticks) { - uint32 nextTime = _system->getMillis() + ticks * _tickLength; - - while (_system->getMillis() < nextTime) { - _sprites->updateSceneAnims(); - _animator->updateAllObjectShapes(); - - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - seq_playEnd(); - } - - if (_skipFlag) - break; - - if (nextTime - _system->getMillis() >= 10) - delay(10); - } -} - -#pragma mark - -#pragma mark - Animation/shape specific code -#pragma mark - - -void KyraEngine::setupShapes123(const Shape *shapeTable, int endShape, int flags) { - debugC(9, kDebugLevelMain, "KyraEngine::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags); - - for (int i = 123; i <= 172; ++i) - _shapes[i] = 0; - - uint8 curImage = 0xFF; - int curPageBackUp = _screen->_curPage; - _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff - int shapeFlags = 2; - if (flags) - shapeFlags = 3; - for (int i = 123; i < 123+endShape; ++i) { - uint8 newImage = shapeTable[i-123].imageIndex; - if (newImage != curImage && newImage != 0xFF) { - assert(_characterImageTable); - _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0); - curImage = newImage; - } - _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags); - assert(i-7 < _defaultShapeTableSize); - _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset; - _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset; - _defaultShapeTable[i-7].w = shapeTable[i-123].w; - _defaultShapeTable[i-7].h = shapeTable[i-123].h; - } - _screen->_curPage = curPageBackUp; -} - -void KyraEngine::freeShapes123() { - debugC(9, kDebugLevelMain, "KyraEngine::freeShapes123()"); - - for (int i = 123; i <= 172; ++i) { - delete [] _shapes[i]; - _shapes[i] = 0; - } -} - -#pragma mark - -#pragma mark - Misc stuff -#pragma mark - -Movie *KyraEngine::createWSAMovie() { - if (_flags.platform == Common::kPlatformAmiga) - return new WSAMovieAmiga(this); - - return new WSAMovieV1(this); + return mouse; } int KyraEngine::setGameFlag(int flag) { @@ -791,7 +195,7 @@ int KyraEngine::setGameFlag(int flag) { return 1; } -int KyraEngine::queryGameFlag(int flag) { +int KyraEngine::queryGameFlag(int flag) const { return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1); } @@ -800,344 +204,19 @@ int KyraEngine::resetGameFlag(int flag) { return 0; } -void KyraEngine::setBrandonPoisonFlags(int reset) { - debugC(9, kDebugLevelMain, "KyraEngine::setBrandonPoisonFlags(%d)", reset); - _brandonStatusBit |= 1; - - if (reset) - _poisonDeathCounter = 0; - - for (int i = 0; i < 0x100; ++i) - _brandonPoisonFlagsGFX[i] = i; - - _brandonPoisonFlagsGFX[0x99] = 0x34; - _brandonPoisonFlagsGFX[0x9A] = 0x35; - _brandonPoisonFlagsGFX[0x9B] = 0x37; - _brandonPoisonFlagsGFX[0x9C] = 0x38; - _brandonPoisonFlagsGFX[0x9D] = 0x2B; -} - -void KyraEngine::resetBrandonPoisonFlags() { - debugC(9, kDebugLevelMain, "KyraEngine::resetBrandonPoisonFlags()"); - _brandonStatusBit = 0; - - for (int i = 0; i < 0x100; ++i) - _brandonPoisonFlagsGFX[i] = i; -} - -#pragma mark - -#pragma mark - Input -#pragma mark - - -void KyraEngine::processInput() { - Common::Point mouse = getMousePos(); - int xpos = mouse.x; - int ypos = mouse.y; - - debugC(9, kDebugLevelMain, "KyraEngine::processInput(%d, %d)", xpos, ypos); - _abortWalkFlag2 = false; - - if (processInputHelper(xpos, ypos)) - return; - - uint8 item = findItemAtPos(xpos, ypos); - if (item == 0xFF) { - _changedScene = false; - int handled = clickEventHandler(xpos, ypos); - if (_changedScene || handled) - return; - } - - // XXX _deathHandler specific - if (ypos <= 158) { - uint16 exit = 0xFFFF; - if (xpos < 12) { - exit = _walkBlockWest; - } else if (xpos >= 308) { - exit = _walkBlockEast; - } else if (ypos >= 136) { - exit = _walkBlockSouth; - } else if (ypos < 12) { - exit = _walkBlockNorth; - } - - if (exit != 0xFFFF) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - return; - } else { - int script = checkForNPCScriptRun(xpos, ypos); - if (script >= 0) { - runNpcScript(script); - return; - } - if (_itemInHand != -1) { - if (ypos < 155) { - if (hasClickedOnExit(xpos, ypos)) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - return; - } - dropItem(0, _itemInHand, xpos, ypos, 1); - } - } else { - if (ypos <= 155) { - _abortWalkFlag2 = true; - handleSceneChange(xpos, ypos, 1, 1); - _abortWalkFlag2 = false; - } - } - } - } -} - -int KyraEngine::processInputHelper(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::processInputHelper(%d, %d)", xpos, ypos); - uint8 item = findItemAtPos(xpos, ypos); - if (item != 0xFF) { - if (_itemInHand == -1) { - _screen->hideMouse(); - _animator->animRemoveGameItem(item); - snd_playSoundEffect(53); - assert(_currentCharacter->sceneId < _roomTableSize); - Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; - int item2 = currentRoom->itemsTable[item]; - currentRoom->itemsTable[item] = 0xFF; - setMouseItem(item2); - assert(_itemList && _takenList); - updateSentenceCommand(_itemList[item2], _takenList[0], 179); - _itemInHand = item2; - _screen->showMouse(); - clickEventHandler2(); - return 1; - } else { - exchangeItemWithMouseItem(_currentCharacter->sceneId, item); - return 1; - } - } - return 0; -} - -int KyraEngine::clickEventHandler(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler(%d, %d)", xpos, ypos); - _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->regs[1] = xpos; - _scriptClick->regs[2] = ypos; - _scriptClick->regs[3] = 0; - _scriptClick->regs[4] = _itemInHand; - _scriptInterpreter->startScript(_scriptClick, 1); - - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); - - return _scriptClick->regs[3]; -} - -void KyraEngine::updateMousePointer(bool forceUpdate) { - int shape = 0; - - int newMouseState = 0; - int newX = 0; - int newY = 0; - Common::Point mouse = getMousePos(); - if (mouse.y <= 158) { - if (mouse.x >= 12) { - if (mouse.x >= 308) { - if (_walkBlockEast == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -5; - shape = 3; - newX = 7; - newY = 5; - } - } else if (mouse.y >= 136) { - if (_walkBlockSouth == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -4; - shape = 4; - newX = 5; - newY = 7; - } - } else if (mouse.y < 12) { - if (_walkBlockNorth == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -6; - shape = 2; - newX = 5; - newY = 1; - } - } - } else { - if (_walkBlockWest == 0xFFFF) { - newMouseState = -2; - } else { - newMouseState = -3; - newX = 1; - newY = shape = 5; - } - } - } - - if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1] - && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) { - switch (_entranceMouseCursorTracks[4]) { - case 0: - newMouseState = -6; - shape = 2; - newX = 5; - newY = 1; - break; - - case 2: - newMouseState = -5; - shape = 3; - newX = 7; - newY = 5; - break; - - case 4: - newMouseState = -4; - shape = 4; - newX = 5; - newY = 7; - break; - - case 6: - newMouseState = -3; - shape = 5; - newX = 1; - newY = 5; - break; - - default: - break; - } - } - - if (newMouseState == -2) { - shape = 6; - newX = 4; - newY = 4; - } - - if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) { - _mouseState = newMouseState; - _screen->hideMouse(); - _screen->setMouseCursor(newX, newY, _shapes[shape]); - _screen->showMouse(); - } - - if (!newMouseState) { - if (_mouseState != _itemInHand || forceUpdate) { - if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) { - _mouseState = _itemInHand; - _screen->hideMouse(); - if (_itemInHand == -1) { - _screen->setMouseCursor(1, 1, _shapes[0]); - } else { - _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]); - } - _screen->showMouse(); - } - } +void KyraEngine::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { + while (_system->getMillis() < timestamp && !_quitFlag) { + if (timestamp - _system->getMillis() >= 10) + delay(10, update, isMainLoop); } } -bool KyraEngine::hasClickedOnExit(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::hasClickedOnExit(%d, %d)", xpos, ypos); - if (xpos < 16 || xpos >= 304) - return true; - - if (ypos < 8) - return true; - - if (ypos < 136 || ypos > 155) - return false; - - return true; -} - -void KyraEngine::clickEventHandler2() { - debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler2()"); - - Common::Point mouse = getMousePos(); - - _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->regs[0] = _currentCharacter->sceneId; - _scriptClick->regs[1] = mouse.x; - _scriptClick->regs[2] = mouse.y; - _scriptClick->regs[4] = _itemInHand; - _scriptInterpreter->startScript(_scriptClick, 6); - - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); -} - -int KyraEngine::checkForNPCScriptRun(int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::checkForNPCScriptRun(%d, %d)", xpos, ypos); - int returnValue = -1; - const Character *currentChar = _currentCharacter; - int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0; - - int scaleFactor = _scaleTable[currentChar->y1]; - int addX = (((scaleFactor*8)*3)>>8)>>1; - int addY = ((scaleFactor*3)<<4)>>8; - - charLeft = currentChar->x1 - addX; - charRight = currentChar->x1 + addX; - charTop = currentChar->y1 - addY; - charBottom = currentChar->y1; - - if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) - return 0; - - if (xpos > 304 || xpos < 16) - return -1; - - for (int i = 1; i < 5; ++i) { - currentChar = &_characterList[i]; - - if (currentChar->sceneId != _currentCharacter->sceneId) - continue; - - charLeft = currentChar->x1 - 12; - charRight = currentChar->x1 + 11; - charTop = currentChar->y1 - 48; - // if (!i) { - // charBottom = currentChar->y2 - 16; - // } else { - charBottom = currentChar->y1; - // } - - if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) - continue; - - if (returnValue != -1) { - if (currentChar->y1 >= _characterList[returnValue].y1) - returnValue = i; - } else { - returnValue = i; - } - } - - return returnValue; +void KyraEngine::delay(uint32 amount, bool update, bool isMainLoop) { + _system->delayMillis(amount); } -void KyraEngine::runNpcScript(int func) { - debugC(9, kDebugLevelMain, "KyraEngine::runNpcScript(%d)", func); - _scriptInterpreter->initScript(_npcScript, _npcScriptData); - _scriptInterpreter->startScript(_npcScript, func); - _npcScript->regs[0] = _currentCharacter->sceneId; - _npcScript->regs[4] = _itemInHand; - _npcScript->regs[5] = func; - - while (_scriptInterpreter->validScript(_npcScript)) - _scriptInterpreter->runScript(_npcScript); +void KyraEngine::delayWithTicks(int ticks) { + delay(ticks * _tickLength); } } // End of namespace Kyra diff --git a/engines/kyra/kyra.h b/engines/kyra/kyra.h index bb41a68e6b..8ed546d1ce 100644 --- a/engines/kyra/kyra.h +++ b/engines/kyra/kyra.h @@ -31,26 +31,9 @@ #include "common/array.h" #include "common/events.h" -namespace Kyra { +#include "kyra/util.h" -class Movie; -class Sound; -class SoundDigital; -class SeqPlayer; -class Resource; -class PAKFile; -class Screen; -class Sprites; -class ScriptHelper; -class Debugger; -class ScreenAnimator; -class TextDisplayer; -class KyraEngine; -class StaticResource; - -struct Opcode; -struct ScriptState; -struct ScriptData; +namespace Kyra { struct GameFlags { Common::Language lang; @@ -62,6 +45,11 @@ struct GameFlags { byte gameID; }; +struct Rect { + int x, y; + int x2, y2; +}; + enum { GI_KYRA1 = 0, GI_KYRA2 = 1, @@ -71,851 +59,110 @@ enum { // TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable // in the future we maybe merge some flags and/or create new ones enum kDebugLevels { - kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o1_* functions + kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o#_* functions kDebugLevelScript = 1 << 1, // prints debug output of "ScriptHelper" functions kDebugLevelSprites = 1 << 2, // prints debug output of "Sprites" functions kDebugLevelScreen = 1 << 3, // prints debug output of "Screen" functions kDebugLevelSound = 1 << 4, // prints debug output of "Sound" functions kDebugLevelAnimator = 1 << 5, // prints debug output of "ScreenAnimator" functions - kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine*" functions && "TextDisplayer" functions + kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine(_v#)" functions && "TextDisplayer" functions kDebugLevelGUI = 1 << 7, // prints debug output of "KyraEngine*" gui functions kDebugLevelSequence = 1 << 8, // prints debug output of "SeqPlayer" functions - kDebugLevelMovie = 1 << 9 // prints debug output of movie specific funtions -}; - -struct Character { - uint16 sceneId; - uint8 height; - uint8 facing; - uint16 currentAnimFrame; - uint8 inventoryItems[10]; - int16 x1, y1, x2, y2; -}; - -struct Shape { - uint8 imageIndex; - int8 xOffset, yOffset; - uint8 x, y, w, h; -}; - -struct Room { - uint8 nameIndex; - uint16 northExit; - uint16 eastExit; - uint16 southExit; - uint16 westExit; - uint8 itemsTable[12]; - uint16 itemsXPos[12]; - uint8 itemsYPos[12]; - uint8 needInit[12]; -}; - -struct Rect { - int x, y; - int x2, y2; -}; - -struct Item { - uint8 unk1; - uint8 height; - uint8 unk2; - uint8 unk3; -}; - -struct SeqLoop { - const uint8 *ptr; - uint16 count; -}; - -struct SceneExits { - uint16 northXPos; - uint8 northYPos; - uint16 eastXPos; - uint8 eastYPos; - uint16 southXPos; - uint8 southYPos; - uint16 westXPos; - uint8 westYPos; -}; - -struct BeadState { - int16 x; - int16 y; - int16 width; - int16 height; - int16 dstX; - int16 dstY; - int16 width2; - int16 unk8; - int16 unk9; - int16 tableIndex; -}; - -struct Timer { - uint8 active; - int32 countdown; - uint32 nextRun; - void (KyraEngine::*func)(int timerNum); -}; - -struct Button { - Button *nextButton; - uint16 specialValue; - // uint8 unk[4]; - uint8 process0; - uint8 process1; - uint8 process2; - // uint8 unk - uint16 flags; - typedef int (KyraEngine::*ButtonCallback)(Button*); - // using 6 pointers instead of 3 as in the orignal here (safer for use with classes) - uint8 *process0PtrShape; - uint8 *process1PtrShape; - uint8 *process2PtrShape; - ButtonCallback process0PtrCallback; - ButtonCallback process1PtrCallback; - ButtonCallback process2PtrCallback; - uint16 dimTableIndex; - uint16 x; - uint16 y; - uint16 width; - uint16 height; - // uint8 unk[8]; - uint32 flags2; - ButtonCallback buttonCallback; - // uint8 unk[8]; + kDebugLevelMovie = 1 << 9, // prints debug output of movie specific funtions + kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions }; -struct MenuItem { - bool enabled; - uint16 field_1; - uint8 field_3; - const char *itemString; - int16 x; - int16 field_9; - uint16 y; - uint16 width; - uint16 height; - uint8 textColor; - uint8 highlightColor; - int16 field_12; - uint8 field_13; - uint8 bgcolor; - uint8 color1; - uint8 color2; - int (KyraEngine::*callback)(Button*); - int16 field_1b; - const char *labelString; - uint16 labelX; - uint8 labelY; - uint8 field_24; - uint32 field_25; -}; - -struct Menu { - int16 x; - int16 y; - uint16 width; - uint16 height; - uint8 bgcolor; - uint8 color1; - uint8 color2; - const char *menuName; - uint8 textColor; - int16 field_10; - uint16 field_12; - uint16 highlightedItem; - uint8 nrOfItems; - int16 scrollUpBtnX; - int16 scrollUpBtnY; - int16 scrollDownBtnX; - int16 scrollDownBtnY; - MenuItem item[6]; -}; +class Screen; +class Resource; +class Sound; +class Movie; +class TextDisplayer; +class StaticResource; +class TimerManager; +class ScriptHelper; class KyraEngine : public Engine { - friend class MusicPlayer; - friend class Debugger; - friend class ScreenAnimator; public: KyraEngine(OSystem *system, const GameFlags &flags); virtual ~KyraEngine(); - + + bool quit() const { return _quitFlag; } + + uint8 game() const { return _flags.gameID; } + const GameFlags &gameFlags() const { return _flags; } + + // access to Kyra specific functionallity Resource *resource() { return _res; } - Screen *screen() { return _screen; } - ScreenAnimator *animator() { return _animator; } + virtual Screen *screen() = 0; TextDisplayer *text() { return _text; } Sound *sound() { return _sound; } StaticResource *staticres() { return _staticres; } + TimerManager *timer() { return _timer; } + uint32 tickLength() const { return _tickLength; } - virtual Movie *createWSAMovie(); - - uint8 game() const { return _flags.gameID; } - const GameFlags &gameFlags() const { return _flags; } - - uint8 **shapes() { return _shapes; } - Character *currentCharacter() { return _currentCharacter; } - Character *characterList() { return _characterList; } - uint16 brandonStatus() { return _brandonStatusBit; } - - // TODO: remove me with workaround in animator.cpp l209 - uint16 getScene() { return _currentRoom; } - - bool quit() const { return _quitFlag; } - - int _paletteChanged; - Common::RandomSource _rnd; - int16 _northExitHeight; - - typedef void (KyraEngine::*IntroProc)(); - - // static data access - const char * const*seqWSATable() { return _seq_WSATable; } - const char * const*seqCPSTable() { return _seq_CPSTable; } - const char * const*seqCOLTable() { return _seq_COLTable; } - const char * const*seqTextsTable() { return _seq_textsTable; } - const uint8 * const*palTable1() { return &_specialPalettes[0]; } - const uint8 * const*palTable2() { return &_specialPalettes[29]; } - - // sequences - // -> misc - bool seq_skipSequence() const; - -protected: - // -> demo - void seq_demo(); - - // -> intro - void seq_intro(); - void seq_introLogos(); - void seq_introStory(); - void seq_introMalcolmTree(); - void seq_introKallakWriting(); - void seq_introKallakMalcolm(); - - // -> ingame animations - void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly); - void seq_brandonHealing(); - void seq_brandonHealing2(); - void seq_poisonDeathNow(int now); - void seq_poisonDeathNowAnim(); - void seq_playFluteAnimation(); - void seq_winterScroll1(); - void seq_winterScroll2(); - void seq_makeBrandonInv(); - void seq_makeBrandonNormal(); - void seq_makeBrandonNormal2(); - void seq_makeBrandonWisp(); - void seq_dispelMagicAnimation(); - void seq_fillFlaskWithWater(int item, int type); - void seq_playDrinkPotionAnim(int item, int unk2, int flags); - void seq_brandonToStone(); - - // -> end fight - int seq_playEnd(); - void seq_playEnding(); - - int handleMalcolmFlag(); - int handleBeadState(); - void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr); - int processBead(int x, int y, int &x2, int &y2, BeadState *ptr); - - // -> credits - void seq_playCredits(); - -public: - // delay - void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); - void delay(uint32 millis, bool update = false, bool isMainLoop = false); - void delayWithTicks(int ticks); - void waitForEvent(); - - // TODO - void quitGame(); - - void registerDefaultSettings(); - void readSettings(); - void writeSettings(); - - void snd_playTheme(int file, int track = 0); - void snd_playVoiceFile(int id); - void snd_voiceWaitForFinish(bool ingame = true); - bool snd_voiceIsPlaying(); - void snd_stopVoice(); - void snd_playSoundEffect(int track); - void snd_playWanderScoreViaMap(int command, int restart); - - bool speechEnabled(); - bool textEnabled(); + virtual Movie *createWSAMovie() = 0; - void updateGameTimers(); - void clearNextEventTickCount(); - void setTimerCountdown(uint8 timer, int32 countdown); - void setTimerDelay(uint8 timer, int32 countdown); - int16 getTimerDelay(uint8 timer); - void enableTimer(uint8 timer); - void disableTimer(uint8 timer); - - void saveGame(const char *fileName, const char *saveName); - void loadGame(const char *fileName); - - Common::Point getMousePos() const; + Common::RandomSource _rnd; + + // quit handling + virtual void quitGame(); + // game flag handling int setGameFlag(int flag); - int queryGameFlag(int flag); + int queryGameFlag(int flag) const; int resetGameFlag(int flag); -protected: - virtual int go(); - virtual int init(); - - // input - void processInput(); - int processInputHelper(int xpos, int ypos); - int clickEventHandler(int xpos, int ypos); - void clickEventHandler2(); - void updateMousePointer(bool forceUpdate = false); - bool hasClickedOnExit(int xpos, int ypos); - - // scene - // -> init - void loadSceneMsc(); - void startSceneScript(int brandonAlive); - void setupSceneItems(); - void initSceneData(int facing, int unk1, int brandonAlive); - void initSceneObjectList(int brandonAlive); - void initSceneScreen(int brandonAlive); - void setupSceneResource(int sceneId); - - // -> process - void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); - int handleSceneChange(int xpos, int ypos, int unk1, int frameReset); - int processSceneChange(int *table, int unk1, int frameReset); - int changeScene(int facing); - - // -> modification - void transcendScenes(int roomIndex, int roomName); - void setSceneFile(int roomIndex, int roomName); - - // -> pathfinder - 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); - int getFacingFromPointToPoint(int x, int y, int toX, int toY); - void changePosTowardsFacing(int &x, int &y, int facing); - bool lineIsPassable(int x, int y); - int getMoveTableSize(int *moveTable); - - // -> item handling - // --> misc - void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y); - - // --> drop handling - void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item); - int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2); - void dropItem(int unk1, int item, int x, int y, int unk2); - - // --> dropped item handling - int countItemsInScene(uint16 sceneId); - void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex); - byte findFreeItemInScene(int scene); - byte findItemAtPos(int x, int y); - - // --> drop area handling - void addToNoDropRects(int x, int y, int w, int h); - void clearNoDropRects(); - int isDropable(int x, int y); - int checkNoDropRects(int x, int y); - - // --> player items handling - void updatePlayerItemsForScene(); - - // --> item GFX handling - void backUpItemRect0(int xpos, int ypos); - void restoreItemRect0(int xpos, int ypos); - void backUpItemRect1(int xpos, int ypos); - void restoreItemRect1(int xpos, int ypos); - - // items - // -> misc - void placeItemInGenericMapScene(int item, int index); - - // -> mouse item - void createMouseItem(int item); - void destroyMouseItem(); - void setMouseItem(int item); - - // -> graphics effects - void wipeDownMouseItem(int xpos, int ypos); - void itemSpecialFX(int x, int y, int item); - void itemSpecialFX1(int x, int y, int item); - void itemSpecialFX2(int x, int y, int item); - void magicOutMouseItem(int animIndex, int itemPos); - void magicInMouseItem(int animIndex, int item, int itemPos); - void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops); - void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops); - - // character - // -> movement - void moveCharacterToPos(int character, int facing, int xpos, int ypos); - void setCharacterPositionWithUpdate(int character); - int setCharacterPosition(int character, int *facingTable); - void setCharacterPositionHelper(int character, int *facingTable); - int getOppositeFacingDirection(int dir); - void setCharactersPositions(int character); - - // -> brandon - void setBrandonPoisonFlags(int reset); - void resetBrandonPoisonFlags(); - - // chat - // -> process - void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration); - void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum); - - // -> initialization - int initCharacterChat(int8 charNum); - void backupChatPartnerAnimFrame(int8 charNum); - void restoreChatPartnerAnimFrame(int8 charNum); - int8 getChatPartnerNum(); - - // -> deinitialization - void endCharacterChat(int8 charNum, int16 arg_4); - - // graphics - // -> misc - int findDuplicateItemShape(int shape); - void updateKyragemFading(); - - // -> interface - void loadMainScreen(int page = 3); - void redrawInventory(int page); -public: - void drawSentenceCommand(const char *sentence, int unk1); - void updateSentenceCommand(const char *str1, const char *str2, int unk1); - void updateTextFade(); - -protected: - // -> amulet - void drawJewelPress(int jewel, int drawSpecial); - void drawJewelsFadeOutStart(); - void drawJewelsFadeOutEnd(int jewel); - - // -> shape handling - void setupShapes123(const Shape *shapeTable, int endShape, int flags); - void freeShapes123(); - - // misc (TODO) - void startup(); - void mainLoop(); - - int checkForNPCScriptRun(int xpos, int ypos); - void runNpcScript(int func); - - virtual void setupOpcodeTable() = 0; - Common::Array<const Opcode*> _opcodes; - - void loadMouseShapes(); - void loadCharacterShapes(); - void loadSpecialEffectShapes(); - void loadItems(); - void loadButtonShapes(); - void initMainButtonList(); - void setCharactersInDefaultScene(); - void setupPanPages(); - void freePanPages(); - void closeFinalWsa(); - void setTimer19(); - void setupTimers(); - void timerUpdateHeadAnims(int timerNum); - void timerSetFlags1(int timerNum); - void timerSetFlags2(int timerNum); - void timerSetFlags3(int timerNum); - void timerCheckAnimFlag1(int timerNum); - void timerCheckAnimFlag2(int timerNum); - void checkAmuletAnimFlags(); - void timerRedrawAmulet(int timerNum); - void timerFadeText(int timerNum); - void updateAnimFlag1(int timerNum); - void updateAnimFlag2(int timerNum); - void drawAmulet(); - void setTextFadeTimerCountdown(int16 countdown); - void setWalkspeed(uint8 newSpeed); + // delay functionallity + virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); + virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false); + virtual void delayWithTicks(int ticks); - int buttonInventoryCallback(Button *caller); - int buttonAmuletCallback(Button *caller); - int buttonMenuCallback(Button *caller); - int drawBoxCallback(Button *button); - int drawShadedBoxCallback(Button *button); - void calcCoords(Menu &menu); - void initMenu(Menu &menu); - void setGUILabels(); - - Button *initButton(Button *list, Button *newButton); - void processButtonList(Button *list); - void processButton(Button *button); - void processMenuButton(Button *button); - void processAllMenuButtons(); - - const char *getSavegameFilename(int num); - void setupSavegames(Menu &menu, int num); - int getNextSavegameSlot(); - - int gui_resumeGame(Button *button); - int gui_loadGameMenu(Button *button); - int gui_saveGameMenu(Button *button); - int gui_gameControlsMenu(Button *button); - int gui_quitPlaying(Button *button); - int gui_quitConfirmYes(Button *button); - int gui_quitConfirmNo(Button *button); - int gui_loadGame(Button *button); - int gui_saveGame(Button *button); - int gui_savegameConfirm(Button *button); - int gui_cancelSubMenu(Button *button); - int gui_scrollUp(Button *button); - int gui_scrollDown(Button *button); - int gui_controlsChangeMusic(Button *button); - int gui_controlsChangeSounds(Button *button); - int gui_controlsChangeWalk(Button *button); - int gui_controlsChangeText(Button *button); - int gui_controlsChangeVoice(Button *button); - int gui_controlsApply(Button *button); - - bool gui_quitConfirm(const char *str); - void gui_getInput(); - void gui_redrawText(Menu menu); - void gui_redrawHighlight(Menu menu); - void gui_processHighlights(Menu &menu); - void gui_updateSavegameString(); - void gui_redrawTextfield(); - void gui_fadePalette(); - void gui_restorePalette(); - void gui_setupControls(Menu &menu); - - // Kyra 2 and 3 main menu - - static const char *_mainMenuStrings[]; - virtual void gui_initMainMenu() {} - int gui_handleMainMenu(); - virtual void gui_updateMainMenuAnimation(); - void gui_drawMainMenu(const char * const *strings, int select); - void gui_drawMainBox(int x, int y, int w, int h, int fill); - bool gui_mainMenuGetInput(); +protected: + virtual int go() = 0; + virtual int init(); - void gui_printString(const char *string, int x, int y, int col1, int col2, int flags, ...); - - GameFlags _flags; + // quit Handling bool _quitFlag; - bool _skipFlag; - bool _skipIntroFlag; - bool _abortIntroFlag; - bool _menuDirectlyToLoad; - bool _abortWalkFlag; - bool _abortWalkFlag2; - bool _mousePressFlag; - int8 _mouseWheel; - uint8 _flagsTable[69]; - uint8 *_itemBkgBackUp[2]; - uint8 *_shapes[373]; - uint16 _gameSpeed; - uint16 _tickLength; - int _lang; - int8 _itemInHand; - int _mouseState; - bool _handleInput; - bool _changedScene; - int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; - int _beadStateVar; - int _unkAmuletVar; - - int _malcolmFlag; - int _endSequenceSkipFlag; - int _endSequenceNeedLoading; - int _unkEndSeqVar2; - uint8 *_endSequenceBackUpRect; - int _unkEndSeqVar4; - int _unkEndSeqVar5; - int _lastDisplayedPanPage; - uint8 *_panPagesTable[20]; - Movie *_finalA, *_finalB, *_finalC; - - Movie *_movieObjects[10]; - - uint16 _entranceMouseCursorTracks[8]; - uint16 _walkBlockNorth; - uint16 _walkBlockEast; - uint16 _walkBlockSouth; - uint16 _walkBlockWest; - - int32 _scaleMode; - int16 _scaleTable[145]; - - Rect _noDropRects[11]; - - int8 _birthstoneGemTable[4]; - int8 _idolGemsTable[3]; - - int8 _marbleVaseItem; - int8 _foyerItemTable[3]; - - int8 _cauldronState; - int8 _crystalState[2]; - - uint16 _brandonStatusBit; - uint8 _brandonStatusBit0x02Flag; - uint8 _brandonStatusBit0x20Flag; - uint8 _brandonPoisonFlagsGFX[256]; - uint8 _deathHandler; - int16 _brandonInvFlag; - uint8 _poisonDeathCounter; - int _brandonPosX; - int _brandonPosY; - - uint16 _currentChatPartnerBackupFrame; - uint16 _currentCharAnimFrame; - - int8 *_sceneAnimTable[50]; - - Item _itemTable[145]; - int _lastProcessedItem; - int _lastProcessedItemHeight; - int16 *_exitListPtr; - int16 _exitList[11]; - SceneExits _sceneExits; - uint16 _currentRoom; - int _scenePhasingFlag; - - int _sceneChangeState; - int _loopFlag2; - - int _pathfinderFlag; - int _pathfinderFlag2; - int _lastFindWayRet; - int *_movFacingTable; - - int8 _talkingCharNum; - int8 _charSayUnk2; - int8 _charSayUnk3; - int8 _currHeadShape; - uint8 _currSentenceColor[3]; - int8 _startSentencePalIndex; - bool _fadeText; - - uint8 _configTextspeed; - uint8 _configWalkspeed; - int _configMusic; - bool _configSounds; - uint8 _configVoice; - - int _curMusicTheme; - int _curSfxFile; - int16 _lastMusicCommand; - + // intern Resource *_res; - Screen *_screen; - ScreenAnimator *_animator; Sound *_sound; - SeqPlayer *_seq; - Sprites *_sprites; TextDisplayer *_text; - ScriptHelper *_scriptInterpreter; - Debugger *_debugger; StaticResource *_staticres; - - ScriptState *_scriptMain; - - ScriptState *_npcScript; - ScriptData *_npcScriptData; - - ScriptState *_scriptClick; - ScriptData *_scriptClickData; - - Character *_characterList; - Character *_currentCharacter; - - Button *_buttonList; - Button *_menuButtonList; - bool _displayMenu; - bool _menuRestoreScreen; - bool _displaySubMenu; - bool _cancelSubMenu; - uint8 _toplevelMenu; - int _savegameOffset; - int _gameToLoad; - char _savegameName[31]; - const char *_specialSavegameString; - Common::KeyState _keyPressed; - - struct KyragemState { - uint16 nextOperation; - uint16 rOffset; - uint16 gOffset; - uint16 bOffset; - uint32 timerCount; - } _kyragemFadingState; - - // TODO: get rid of all variables having pointers to the static resources if possible - // i.e. let them directly use the _staticres functions - void initStaticResource(); - - const uint8 *_seq_Forest; - const uint8 *_seq_KallakWriting; - const uint8 *_seq_KyrandiaLogo; - const uint8 *_seq_KallakMalcolm; - const uint8 *_seq_MalcolmTree; - const uint8 *_seq_WestwoodLogo; - const uint8 *_seq_Demo1; - const uint8 *_seq_Demo2; - const uint8 *_seq_Demo3; - const uint8 *_seq_Demo4; - const uint8 *_seq_Reunion; - - const char * const*_seq_WSATable; - const char * const*_seq_CPSTable; - const char * const*_seq_COLTable; - const char * const*_seq_textsTable; - - int _seq_WSATable_Size; - int _seq_CPSTable_Size; - int _seq_COLTable_Size; - int _seq_textsTable_Size; - - const char * const*_itemList; - const char * const*_takenList; - const char * const*_placedList; - const char * const*_droppedList; - const char * const*_noDropList; - const char * const*_putDownFirst; - const char * const*_waitForAmulet; - const char * const*_blackJewel; - const char * const*_poisonGone; - const char * const*_healingTip; - const char * const*_thePoison; - const char * const*_fluteString; - const char * const*_wispJewelStrings; - const char * const*_magicJewelString; - const char * const*_flaskFull; - const char * const*_fullFlask; - const char * const*_veryClever; - const char * const*_homeString; - const char * const*_newGameString; + TimerManager *_timer; + ScriptHelper *_scriptInterpreter; - const char *_voiceTextString; - const char *_textSpeedString; - const char *_onString; - const char *_offString; - const char *_onCDString; - - int _itemList_Size; - int _takenList_Size; - int _placedList_Size; - int _droppedList_Size; - int _noDropList_Size; - int _putDownFirst_Size; - int _waitForAmulet_Size; - int _blackJewel_Size; - int _poisonGone_Size; - int _healingTip_Size; - int _thePoison_Size; - int _fluteString_Size; - int _wispJewelStrings_Size; - int _magicJewelString_Size; - int _flaskFull_Size; - int _fullFlask_Size; - int _veryClever_Size; - int _homeString_Size; - int _newGameString_Size; + // game speed + bool _skipFlag; + uint16 _tickLength; + uint16 _gameSpeed; - const char * const*_characterImageTable; - int _characterImageTableSize; - - const char * const*_guiStrings; - int _guiStringsSize; + // detection + GameFlags _flags; + int _lang; - const char * const*_configStrings; - int _configStringsSize; - - Shape *_defaultShapeTable; - int _defaultShapeTableSize; - - const Shape *_healingShapeTable; - int _healingShapeTableSize; - const Shape *_healingShape2Table; - int _healingShape2TableSize; - - const Shape *_posionDeathShapeTable; - int _posionDeathShapeTableSize; - - const Shape *_fluteAnimShapeTable; - int _fluteAnimShapeTableSize; - - const Shape *_winterScrollTable; - int _winterScrollTableSize; - const Shape *_winterScroll1Table; - int _winterScroll1TableSize; - const Shape *_winterScroll2Table; - int _winterScroll2TableSize; - - const Shape *_drinkAnimationTable; - int _drinkAnimationTableSize; - - const Shape *_brandonToWispTable; - int _brandonToWispTableSize; - - const Shape *_magicAnimationTable; - int _magicAnimationTableSize; - - const Shape *_brandonStoneTable; - int _brandonStoneTableSize; + // opcode + virtual void setupOpcodeTable() = 0; + Common::Array<const Opcode*> _opcodes; - Room *_roomTable; - int _roomTableSize; - const char * const*_roomFilenameTable; - int _roomFilenameTableSize; + // game flags + uint8 _flagsTable[100]; // TODO: check this value - const uint8 *_amuleteAnim; + // input + Common::Point getMousePos() const; - const uint8 * const*_specialPalettes; - - Timer _timers[34]; - uint32 _timerNextRun; - - static const char *_soundFiles[]; - static const int _soundFilesCount; - static const char *_soundFilesTowns[]; - static const int _soundFilesTownsCount; + // pathfinder + virtual 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); + int getFacingFromPointToPoint(int x, int y, int toX, int toY); + int getOppositeFacingDirection(int dir); + void changePosTowardsFacing(int &x, int &y, int facing); + int getMoveTableSize(int *moveTable); + virtual bool lineIsPassable(int x, int y) = 0; - static const int8 _charXPosTable[]; static const int8 _addXPosTable[]; - static const int8 _charYPosTable[]; static const int8 _addYPosTable[]; - - // positions of the inventory - static const uint16 _itemPosX[]; - static const uint8 _itemPosY[]; - - void setupButtonData(); - Button *_buttonData; - Button **_buttonDataListPtr; - static Button _menuButtonData[]; - static Button _scrollUpButton; - static Button _scrollDownButton; - - bool _haveScrollButtons; - - void setupMenu(); - Menu *_menu; - - static const uint8 _magicMouseItemStartFrame[]; - static const uint8 _magicMouseItemEndFrame[]; - static const uint8 _magicMouseItemStartFrame2[]; - static const uint8 _magicMouseItemEndFrame2[]; - - static const uint16 _amuletX[]; - static const uint16 _amuletY[]; - static const uint16 _amuletX2[]; - static const uint16 _amuletY2[]; }; } // End of namespace Kyra diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 7fc13a6c38..3c6e257376 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -25,15 +25,991 @@ #include "kyra/kyra_v1.h" +#include "common/file.h" +#include "common/events.h" +#include "common/system.h" +#include "common/savefile.h" + +#include "gui/message.h" + +#include "kyra/resource.h" +#include "kyra/screen.h" +#include "kyra/script.h" +#include "kyra/seqplayer.h" +#include "kyra/sound.h" +#include "kyra/sprites.h" +#include "kyra/wsamovie.h" +#include "kyra/animator_v1.h" +#include "kyra/text.h" +#include "kyra/debugger.h" +#include "kyra/timer.h" + namespace Kyra { KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) { + _flags = flags; + + _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm = + _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 = + _seq_Demo4 = 0; + + _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0; + _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0; + + _roomFilenameTable = _characterImageTable = 0; + _roomFilenameTableSize = _characterImageTableSize = 0; + _itemList = _takenList = _placedList = _droppedList = _noDropList = 0; + _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0; + _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0; + _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0; + _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0; + _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0; + _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0; + + _defaultShapeTable = 0; + _healingShapeTable = _healingShape2Table = 0; + _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0; + _posionDeathShapeTable = _fluteAnimShapeTable = 0; + _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0; + _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0; + _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0; + _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0; + _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0; + memset(&_specialPalettes, 0, sizeof(_specialPalettes)); + _debugger = 0; + _sprites = 0; + _animator = 0; + _seq = 0; + _npcScriptData = 0; + _scriptMain = 0; + _scriptClickData = 0; + _scriptClick = 0; + _characterList = 0; + _movFacingTable = 0; + memset(_shapes, 0, sizeof(_shapes)); + memset(_movieObjects, 0, sizeof(_movieObjects)); + _finalA = _finalB = _finalC = 0; + _endSequenceBackUpRect = 0; + memset(_panPagesTable, 0, sizeof(_panPagesTable)); + _npcScriptData = _scriptClickData = 0; + _scrollUpButton.process0PtrShape = _scrollUpButton.process1PtrShape = _scrollUpButton.process2PtrShape = 0; + _scrollDownButton.process0PtrShape = _scrollDownButton.process1PtrShape = _scrollDownButton.process2PtrShape = 0; + memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); + _currHeadShape = 0; + + _curSfxFile = _curMusicTheme = 0; + + memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp)); } KyraEngine_v1::~KyraEngine_v1() { + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) { + if (_movieObjects[i]) + _movieObjects[i]->close(); + delete _movieObjects[i]; + _movieObjects[i] = 0; + } + + closeFinalWsa(); + if (_scriptInterpreter) { + _scriptInterpreter->unloadScript(_npcScriptData); + _scriptInterpreter->unloadScript(_scriptClickData); + } + + Common::clearAllSpecialDebugLevels(); + + delete _screen; + delete _debugger; + delete _sprites; + delete _animator; + delete _seq; + + delete _npcScriptData; + delete _scriptMain; + + delete _scriptClickData; + delete _scriptClick; + + delete [] _characterList; + + delete [] _movFacingTable; + + delete [] _scrollUpButton.process0PtrShape; + delete [] _scrollUpButton.process1PtrShape; + delete [] _scrollUpButton.process2PtrShape; + delete [] _scrollDownButton.process0PtrShape; + delete [] _scrollDownButton.process1PtrShape; + delete [] _scrollDownButton.process2PtrShape; + + delete [] _itemBkgBackUp[0]; + delete [] _itemBkgBackUp[1]; + + for (int i = 0; i < ARRAYSIZE(_shapes); ++i) { + if (_shapes[i] != 0) { + delete [] _shapes[i]; + for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) { + if (_shapes[i2] == _shapes[i] && i2 != i) { + _shapes[i2] = 0; + } + } + _shapes[i] = 0; + } + } + + for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i) + delete [] _sceneAnimTable[i]; +} + +int KyraEngine_v1::init() { + _screen = new Screen_v1(this, _system); + assert(_screen); + if (!_screen->init()) + error("_screen->init() failed"); + + KyraEngine::init(); + + _sprites = new Sprites(this, _system); + assert(_sprites); + _seq = new SeqPlayer(this, _system); + assert(_seq); + _animator = new ScreenAnimator(this, _system); + assert(_animator); + _animator->init(5, 11, 12); + assert(*_animator); + + initStaticResource(); + + if (_flags.platform == Common::kPlatformFMTowns) + _sound->setSoundFileList(_soundFilesTowns, _soundFilesTownsCount); + else + _sound->setSoundFileList(_soundFiles, _soundFilesCount); + + if (!_sound->init()) + error("Couldn't init sound"); + + _sound->setVolume(255); + _sound->loadSoundFile(0); + + setupTimers(); + setupButtonData(); + setupMenu(); + + _paletteChanged = 1; + _currentCharacter = 0; + _characterList = new Character[11]; + assert(_characterList); + memset(_characterList, 0, sizeof(Character)*11); + + for (int i = 0; i < 11; ++i) + memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems)); + + _characterList[0].sceneId = 5; + _characterList[0].height = 48; + _characterList[0].facing = 3; + _characterList[0].currentAnimFrame = 7; + + _npcScriptData = new ScriptData; + memset(_npcScriptData, 0, sizeof(ScriptData)); + assert(_npcScriptData); + _npcScript = new ScriptState; + assert(_npcScript); + memset(_npcScript, 0, sizeof(ScriptState)); + + _scriptMain = new ScriptState; + assert(_scriptMain); + memset(_scriptMain, 0, sizeof(ScriptState)); + + _scriptClickData = new ScriptData; + assert(_scriptClickData); + memset(_scriptClickData, 0, sizeof(ScriptData)); + _scriptClick = new ScriptState; + assert(_scriptClick); + memset(_scriptClick, 0, sizeof(ScriptState)); + + _debugger = new Debugger_v1(this); + assert(_debugger); + memset(_shapes, 0, sizeof(_shapes)); + + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) + _movieObjects[i] = createWSAMovie(); + + memset(_flagsTable, 0, sizeof(_flagsTable)); + + _abortWalkFlag = false; + _abortWalkFlag2 = false; + _talkingCharNum = -1; + _charSayUnk3 = -1; + memset(_currSentenceColor, 0, 3); + _startSentencePalIndex = -1; + _fadeText = false; + + _cauldronState = 0; + _crystalState[0] = _crystalState[1] = -1; + + _brandonStatusBit = 0; + _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10; + _brandonPosX = _brandonPosY = -1; + _deathHandler = 0xFF; + _poisonDeathCounter = 0; + + memset(_itemTable, 0, sizeof(_itemTable)); + memset(_exitList, 0xFFFF, sizeof(_exitList)); + _exitListPtr = 0; + _pathfinderFlag = _pathfinderFlag2 = 0; + _lastFindWayRet = 0; + _sceneChangeState = _loopFlag2 = 0; + + _movFacingTable = new int[150]; + assert(_movFacingTable); + _movFacingTable[0] = 8; + + registerDefaultSettings(); + readSettings(); + + _skipFlag = false; + + _marbleVaseItem = -1; + memset(_foyerItemTable, -1, sizeof(_foyerItemTable)); + _mouseState = _itemInHand = -1; + _handleInput = false; + + _currentRoom = 0xFFFF; + _scenePhasingFlag = 0; + _lastProcessedItem = 0; + _lastProcessedItemHeight = 16; + + _unkScreenVar1 = 1; + _unkScreenVar2 = 0; + _unkScreenVar3 = 0; + _unkAmuletVar = 0; + + _endSequenceNeedLoading = 1; + _malcolmFlag = 0; + _beadStateVar = 0; + _endSequenceSkipFlag = 0; + _unkEndSeqVar2 = 0; + _endSequenceBackUpRect = 0; + _unkEndSeqVar4 = 0; + _unkEndSeqVar5 = 0; + _lastDisplayedPanPage = 0; + memset(_panPagesTable, 0, sizeof(_panPagesTable)); + _finalA = _finalB = _finalC = 0; + memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState)); + _kyragemFadingState.gOffset = 0x13; + _kyragemFadingState.bOffset = 0x13; + + _mousePressFlag = false; + + _menuDirectlyToLoad = false; + + _lastMusicCommand = 0; + + return 0; +} + +int KyraEngine_v1::go() { + if (_res->getFileSize("6.FNT")) + _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); + _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); + _screen->setScreenDim(0); + + _abortIntroFlag = false; + + if (_flags.isDemo) { + seq_demo(); + } else { + setGameFlag(0xF3); + setGameFlag(0xFD); + setGameFlag(0xEF); + seq_intro(); + if (_quitFlag) + return 0; + if (_skipIntroFlag && _abortIntroFlag) + resetGameFlag(0xEF); + startup(); + resetGameFlag(0xEF); + mainLoop(); + } + return 0; +} + + +void KyraEngine_v1::startup() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::startup()"); + static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 }; + _screen->setTextColorMap(colorMap); +// _screen->setFont(Screen::FID_6_FNT); + _screen->setAnimBlockPtr(3750); + memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable)); + loadMouseShapes(); + _currentCharacter = &_characterList[0]; + for (int i = 1; i < 5; ++i) + _animator->setCharacterDefaultFrame(i); + for (int i = 5; i <= 10; ++i) + setCharactersPositions(i); + _animator->setCharactersHeight(); + resetBrandonPoisonFlags(); + _screen->_curPage = 0; + // XXX + for (int i = 0; i < 12; ++i) { + int size = _screen->getRectSize(3, 24); + _shapes[361+i] = new byte[size]; + } + + _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)]; + memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24)); + _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)]; + memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32)); + + for (int i = 0; i < _roomTableSize; ++i) { + for (int item = 0; item < 12; ++item) { + _roomTable[i].itemsTable[item] = 0xFF; + _roomTable[i].itemsXPos[item] = 0xFFFF; + _roomTable[i].itemsYPos[item] = 0xFF; + _roomTable[i].needInit[item] = 0; + } + } + + loadCharacterShapes(); + loadSpecialEffectShapes(); + loadItems(); + loadButtonShapes(); + initMainButtonList(); + loadMainScreen(); + setupTimers(); + _screen->loadPalette("PALETTE.COL", _screen->_currentPalette); + + // XXX + _animator->initAnimStateList(); + setCharactersInDefaultScene(); + + if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, &_opcodes)) + error("Could not load \"_STARTUP.EMC\" script"); + _scriptInterpreter->initScript(_scriptMain, _npcScriptData); + + if (!_scriptInterpreter->startScript(_scriptMain, 0)) + error("Could not start script function 0 of script \"_STARTUP.EMC\""); + + while (_scriptInterpreter->validScript(_scriptMain)) + _scriptInterpreter->runScript(_scriptMain); + + _scriptInterpreter->unloadScript(_npcScriptData); + + if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, &_opcodes)) + error("Could not load \"_NPC.EMC\" script"); + + snd_playTheme(1); + enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); + + if (_abortIntroFlag && _skipIntroFlag) { + _menuDirectlyToLoad = true; + _screen->setMouseCursor(1, 1, _shapes[0]); + _screen->showMouse(); + buttonMenuCallback(0); + _menuDirectlyToLoad = false; + } else + saveGame(getSavegameFilename(0), "New game"); +} + +void KyraEngine_v1::mainLoop() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::mainLoop()"); + + while (!_quitFlag) { + int32 frameTime = (int32)_system->getMillis(); + _skipFlag = false; + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + if (seq_playEnd() && _deathHandler != 8) + break; + } + + if (_deathHandler != 0xFF) { + snd_playWanderScoreViaMap(0, 1); + snd_playSoundEffect(49); + _screen->hideMouse(); + _screen->setMouseCursor(1, 1, _shapes[0]); + destroyMouseItem(); + _screen->showMouse(); + buttonMenuCallback(0); + _deathHandler = 0xFF; + } + + if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag) + _animator->animRefreshNPC(0); + + if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) { + _animator->animRefreshNPC(0); + _brandonStatusBit0x20Flag = 0; + } + + _screen->showMouse(); + + processButtonList(_buttonList); + updateMousePointer(); + _timer->update(); + updateTextFade(); + + _handleInput = true; + delay((frameTime + _gameSpeed) - _system->getMillis(), true, true); + _handleInput = false; + + _sound->process(); + } +} + +void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) { + while (_system->getMillis() < timestamp && !_quitFlag) { + if (updateTimers) + _timer->update(); + + if (timestamp - _system->getMillis() >= 10) + delay(10, update, isMainLoop); + } +} + +void KyraEngine_v1::delay(uint32 amount, bool update, bool isMainLoop) { + Common::Event event; + char saveLoadSlot[20]; + char savegameName[14]; + + uint32 start = _system->getMillis(); + do { + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && + (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) { + sprintf(saveLoadSlot, "%s.00%d", _targetName.c_str(), event.kbd.keycode - '0'); + if (event.kbd.flags == Common::KBD_CTRL) + loadGame(saveLoadSlot); + else { + sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0'); + saveGame(saveLoadSlot, savegameName); + } + } else if (event.kbd.flags == Common::KBD_CTRL) { + if (event.kbd.keycode == 'd') + _debugger->attach(); + else if (event.kbd.keycode == 'q') + _quitFlag = true; + } else if (event.kbd.keycode == '.') + _skipFlag = true; + else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) { + _abortIntroFlag = true; + _skipFlag = true; + } + + break; + case Common::EVENT_MOUSEMOVE: + _animator->_updateScreen = true; + break; + case Common::EVENT_QUIT: + quitGame(); + break; + case Common::EVENT_LBUTTONDOWN: + _mousePressFlag = true; + break; + case Common::EVENT_LBUTTONUP: + _mousePressFlag = false; + + if (_abortWalkFlag2) + _abortWalkFlag = true; + + if (_handleInput) { + _handleInput = false; + processInput(); + _handleInput = true; + } else + _skipFlag = true; + + break; + default: + break; + } + } + + if (_debugger->isAttached()) + _debugger->onFrame(); + + if (update) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + updateTextFade(); + updateMousePointer(); + } + + if (_currentCharacter && _currentCharacter->sceneId == 210 && update) + updateKyragemFading(); + + if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE)) + _skipFlag = false; + + if (amount > 0 && !_skipFlag && !_quitFlag) + _system->delayMillis(10); + + if (_skipFlag) + _sound->voiceStop(); + } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag); +} + +void KyraEngine_v1::waitForEvent() { + bool finished = false; + Common::Event event; + + while (!finished && !_quitFlag) { + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + finished = true; + break; + case Common::EVENT_QUIT: + quitGame(); + break; + case Common::EVENT_LBUTTONDOWN: + finished = true; + _skipFlag = true; + break; + default: + break; + } + } + + if (_debugger->isAttached()) + _debugger->onFrame(); + + _system->delayMillis(10); + } +} + +void KyraEngine_v1::delayWithTicks(int ticks) { + uint32 nextTime = _system->getMillis() + ticks * _tickLength; + + while (_system->getMillis() < nextTime) { + _sprites->updateSceneAnims(); + _animator->updateAllObjectShapes(); + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + seq_playEnd(); + } + + if (_skipFlag) + break; + + if (nextTime - _system->getMillis() >= 10) + delay(10); + } +} + +#pragma mark - +#pragma mark - Animation/shape specific code +#pragma mark - + +void KyraEngine_v1::setupShapes123(const Shape *shapeTable, int endShape, int flags) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags); + + for (int i = 123; i <= 172; ++i) + _shapes[i] = 0; + + uint8 curImage = 0xFF; + int curPageBackUp = _screen->_curPage; + _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff + int shapeFlags = 2; + if (flags) + shapeFlags = 3; + for (int i = 123; i < 123+endShape; ++i) { + uint8 newImage = shapeTable[i-123].imageIndex; + if (newImage != curImage && newImage != 0xFF) { + assert(_characterImageTable); + _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0); + curImage = newImage; + } + _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags); + assert(i-7 < _defaultShapeTableSize); + _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset; + _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset; + _defaultShapeTable[i-7].w = shapeTable[i-123].w; + _defaultShapeTable[i-7].h = shapeTable[i-123].h; + } + _screen->_curPage = curPageBackUp; +} + +void KyraEngine_v1::freeShapes123() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::freeShapes123()"); + + for (int i = 123; i <= 172; ++i) { + delete [] _shapes[i]; + _shapes[i] = 0; + } +} + +#pragma mark - +#pragma mark - Misc stuff +#pragma mark - + +Movie *KyraEngine_v1::createWSAMovie() { + if (_flags.platform == Common::kPlatformAmiga) + return new WSAMovieAmiga(this); + + return new WSAMovieV1(this); +} + +void KyraEngine_v1::setBrandonPoisonFlags(int reset) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setBrandonPoisonFlags(%d)", reset); + _brandonStatusBit |= 1; + + if (reset) + _poisonDeathCounter = 0; + + for (int i = 0; i < 0x100; ++i) + _brandonPoisonFlagsGFX[i] = i; + + _brandonPoisonFlagsGFX[0x99] = 0x34; + _brandonPoisonFlagsGFX[0x9A] = 0x35; + _brandonPoisonFlagsGFX[0x9B] = 0x37; + _brandonPoisonFlagsGFX[0x9C] = 0x38; + _brandonPoisonFlagsGFX[0x9D] = 0x2B; +} + +void KyraEngine_v1::resetBrandonPoisonFlags() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::resetBrandonPoisonFlags()"); + _brandonStatusBit = 0; + + for (int i = 0; i < 0x100; ++i) + _brandonPoisonFlagsGFX[i] = i; +} + +#pragma mark - +#pragma mark - Input +#pragma mark - + +void KyraEngine_v1::processInput() { + Common::Point mouse = getMousePos(); + int xpos = mouse.x; + int ypos = mouse.y; + + debugC(9, kDebugLevelMain, "KyraEngine_v1::processInput(%d, %d)", xpos, ypos); + _abortWalkFlag2 = false; + + if (processInputHelper(xpos, ypos)) + return; + + uint8 item = findItemAtPos(xpos, ypos); + if (item == 0xFF) { + _changedScene = false; + int handled = clickEventHandler(xpos, ypos); + if (_changedScene || handled) + return; + } + + // XXX _deathHandler specific + if (ypos <= 158) { + uint16 exit = 0xFFFF; + if (xpos < 12) { + exit = _walkBlockWest; + } else if (xpos >= 308) { + exit = _walkBlockEast; + } else if (ypos >= 136) { + exit = _walkBlockSouth; + } else if (ypos < 12) { + exit = _walkBlockNorth; + } + + if (exit != 0xFFFF) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + return; + } else { + int script = checkForNPCScriptRun(xpos, ypos); + if (script >= 0) { + runNpcScript(script); + return; + } + if (_itemInHand != -1) { + if (ypos < 155) { + if (hasClickedOnExit(xpos, ypos)) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + return; + } + dropItem(0, _itemInHand, xpos, ypos, 1); + } + } else { + if (ypos <= 155) { + _abortWalkFlag2 = true; + handleSceneChange(xpos, ypos, 1, 1); + _abortWalkFlag2 = false; + } + } + } + } +} + +int KyraEngine_v1::processInputHelper(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::processInputHelper(%d, %d)", xpos, ypos); + uint8 item = findItemAtPos(xpos, ypos); + if (item != 0xFF) { + if (_itemInHand == -1) { + _screen->hideMouse(); + _animator->animRemoveGameItem(item); + snd_playSoundEffect(53); + assert(_currentCharacter->sceneId < _roomTableSize); + Room *currentRoom = &_roomTable[_currentCharacter->sceneId]; + int item2 = currentRoom->itemsTable[item]; + currentRoom->itemsTable[item] = 0xFF; + setMouseItem(item2); + assert(_itemList && _takenList); + updateSentenceCommand(_itemList[item2], _takenList[0], 179); + _itemInHand = item2; + _screen->showMouse(); + clickEventHandler2(); + return 1; + } else { + exchangeItemWithMouseItem(_currentCharacter->sceneId, item); + return 1; + } + } + return 0; +} + +int KyraEngine_v1::clickEventHandler(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler(%d, %d)", xpos, ypos); + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + _scriptClick->regs[1] = xpos; + _scriptClick->regs[2] = ypos; + _scriptClick->regs[3] = 0; + _scriptClick->regs[4] = _itemInHand; + _scriptInterpreter->startScript(_scriptClick, 1); + + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); + + return _scriptClick->regs[3]; +} + +void KyraEngine_v1::updateMousePointer(bool forceUpdate) { + int shape = 0; + + int newMouseState = 0; + int newX = 0; + int newY = 0; + Common::Point mouse = getMousePos(); + if (mouse.y <= 158) { + if (mouse.x >= 12) { + if (mouse.x >= 308) { + if (_walkBlockEast == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -5; + shape = 3; + newX = 7; + newY = 5; + } + } else if (mouse.y >= 136) { + if (_walkBlockSouth == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -4; + shape = 4; + newX = 5; + newY = 7; + } + } else if (mouse.y < 12) { + if (_walkBlockNorth == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -6; + shape = 2; + newX = 5; + newY = 1; + } + } + } else { + if (_walkBlockWest == 0xFFFF) { + newMouseState = -2; + } else { + newMouseState = -3; + newX = 1; + newY = shape = 5; + } + } + } + + if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1] + && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) { + switch (_entranceMouseCursorTracks[4]) { + case 0: + newMouseState = -6; + shape = 2; + newX = 5; + newY = 1; + break; + + case 2: + newMouseState = -5; + shape = 3; + newX = 7; + newY = 5; + break; + + case 4: + newMouseState = -4; + shape = 4; + newX = 5; + newY = 7; + break; + + case 6: + newMouseState = -3; + shape = 5; + newX = 1; + newY = 5; + break; + + default: + break; + } + } + + if (newMouseState == -2) { + shape = 6; + newX = 4; + newY = 4; + } + + if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) { + _mouseState = newMouseState; + _screen->hideMouse(); + _screen->setMouseCursor(newX, newY, _shapes[shape]); + _screen->showMouse(); + } + + if (!newMouseState) { + if (_mouseState != _itemInHand || forceUpdate) { + if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) { + _mouseState = _itemInHand; + _screen->hideMouse(); + if (_itemInHand == -1) { + _screen->setMouseCursor(1, 1, _shapes[0]); + } else { + _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]); + } + _screen->showMouse(); + } + } + } +} + +bool KyraEngine_v1::hasClickedOnExit(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::hasClickedOnExit(%d, %d)", xpos, ypos); + if (xpos < 16 || xpos >= 304) + return true; + + if (ypos < 8) + return true; + + if (ypos < 136 || ypos > 155) + return false; + + return true; +} + +void KyraEngine_v1::clickEventHandler2() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler2()"); + + Common::Point mouse = getMousePos(); + + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + _scriptClick->regs[0] = _currentCharacter->sceneId; + _scriptClick->regs[1] = mouse.x; + _scriptClick->regs[2] = mouse.y; + _scriptClick->regs[4] = _itemInHand; + _scriptInterpreter->startScript(_scriptClick, 6); + + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); +} + +int KyraEngine_v1::checkForNPCScriptRun(int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::checkForNPCScriptRun(%d, %d)", xpos, ypos); + int returnValue = -1; + const Character *currentChar = _currentCharacter; + int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0; + + int scaleFactor = _scaleTable[currentChar->y1]; + int addX = (((scaleFactor*8)*3)>>8)>>1; + int addY = ((scaleFactor*3)<<4)>>8; + + charLeft = currentChar->x1 - addX; + charRight = currentChar->x1 + addX; + charTop = currentChar->y1 - addY; + charBottom = currentChar->y1; + + if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) + return 0; + + if (xpos > 304 || xpos < 16) + return -1; + + for (int i = 1; i < 5; ++i) { + currentChar = &_characterList[i]; + + if (currentChar->sceneId != _currentCharacter->sceneId) + continue; + + charLeft = currentChar->x1 - 12; + charRight = currentChar->x1 + 11; + charTop = currentChar->y1 - 48; + // if (!i) { + // charBottom = currentChar->y2 - 16; + // } else { + charBottom = currentChar->y1; + // } + + if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) + continue; + + if (returnValue != -1) { + if (currentChar->y1 >= _characterList[returnValue].y1) + returnValue = i; + } else { + returnValue = i; + } + } + + return returnValue; +} + +void KyraEngine_v1::runNpcScript(int func) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::runNpcScript(%d)", func); + _scriptInterpreter->initScript(_npcScript, _npcScriptData); + _scriptInterpreter->startScript(_npcScript, func); + _npcScript->regs[0] = _currentCharacter->sceneId; + _npcScript->regs[4] = _itemInHand; + _npcScript->regs[5] = func; + + while (_scriptInterpreter->validScript(_npcScript)) + _scriptInterpreter->runScript(_npcScript); +} + +void KyraEngine_v1::checkAmuletAnimFlags() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::checkSpecialAnimFlags()"); + + if (_brandonStatusBit & 2) { + seq_makeBrandonNormal2(); + _timer->setCountdown(19, 300); + } + + if (_brandonStatusBit & 0x20) { + seq_makeBrandonNormal(); + _timer->setCountdown(19, 300); + } } +typedef Functor1Mem<ScriptState*, int, KyraEngine_v1> OpcodeV1; #define Opcode(x) OpcodeV1(this, &KyraEngine_v1::x) void KyraEngine_v1::setupOpcodeTable() { static const OpcodeV1 opcodeTable[] = { @@ -232,6 +1208,7 @@ void KyraEngine_v1::setupOpcodeTable() { Opcode(o1_fillRect), Opcode(o1_vocUnload), Opcode(o1_vocLoad), + // 0x9c Opcode(o1_dummy) }; diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index e103086dc4..8c9437b6fe 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -28,16 +28,779 @@ #include "kyra/kyra.h" #include "kyra/script.h" +#include "kyra/screen_v1.h" namespace Kyra { +class Movie; +class SoundDigital; +class SeqPlayer; +class Sprites; +class Debugger; +class ScreenAnimator; +class TextDisplayer; +class KyraEngine_v1; + +struct Character { + uint16 sceneId; + uint8 height; + uint8 facing; + uint16 currentAnimFrame; + uint8 inventoryItems[10]; + int16 x1, y1, x2, y2; +}; + +struct Shape { + uint8 imageIndex; + int8 xOffset, yOffset; + uint8 x, y, w, h; +}; + +struct Room { + uint8 nameIndex; + uint16 northExit; + uint16 eastExit; + uint16 southExit; + uint16 westExit; + uint8 itemsTable[12]; + uint16 itemsXPos[12]; + uint8 itemsYPos[12]; + uint8 needInit[12]; +}; + +struct Item { + uint8 unk1; + uint8 height; + uint8 unk2; + uint8 unk3; +}; + +struct SeqLoop { + const uint8 *ptr; + uint16 count; +}; + +struct SceneExits { + uint16 northXPos; + uint8 northYPos; + uint16 eastXPos; + uint8 eastYPos; + uint16 southXPos; + uint8 southYPos; + uint16 westXPos; + uint8 westYPos; +}; + +struct BeadState { + int16 x; + int16 y; + int16 width; + int16 height; + int16 dstX; + int16 dstY; + int16 width2; + int16 unk8; + int16 unk9; + int16 tableIndex; +}; + +struct Button { + Button *nextButton; + uint16 specialValue; + // uint8 unk[4]; + uint8 process0; + uint8 process1; + uint8 process2; + // uint8 unk + uint16 flags; + typedef int (KyraEngine_v1::*ButtonCallback)(Button*); + // using 6 pointers instead of 3 as in the orignal here (safer for use with classes) + uint8 *process0PtrShape; + uint8 *process1PtrShape; + uint8 *process2PtrShape; + ButtonCallback process0PtrCallback; + ButtonCallback process1PtrCallback; + ButtonCallback process2PtrCallback; + uint16 dimTableIndex; + uint16 x; + uint16 y; + uint16 width; + uint16 height; + // uint8 unk[8]; + uint32 flags2; + ButtonCallback buttonCallback; + // uint8 unk[8]; +}; + +struct MenuItem { + bool enabled; + uint16 field_1; + uint8 field_3; + const char *itemString; + int16 x; + int16 field_9; + uint16 y; + uint16 width; + uint16 height; + uint8 textColor; + uint8 highlightColor; + int16 field_12; + uint8 field_13; + uint8 bgcolor; + uint8 color1; + uint8 color2; + int (KyraEngine_v1::*callback)(Button*); + int16 field_1b; + const char *labelString; + uint16 labelX; + uint8 labelY; + uint8 field_24; + uint32 field_25; +}; + +struct Menu { + int16 x; + int16 y; + uint16 width; + uint16 height; + uint8 bgcolor; + uint8 color1; + uint8 color2; + const char *menuName; + uint8 textColor; + int16 field_10; + uint16 field_12; + uint16 highlightedItem; + uint8 nrOfItems; + int16 scrollUpBtnX; + int16 scrollUpBtnY; + int16 scrollDownBtnX; + int16 scrollDownBtnY; + MenuItem item[6]; +}; + class KyraEngine_v1 : public KyraEngine { + friend class MusicPlayer; + friend class Debugger_v1; + friend class ScreenAnimator; public: KyraEngine_v1(OSystem *system, const GameFlags &flags); ~KyraEngine_v1(); + Screen *screen() { return _screen; } + ScreenAnimator *animator() { return _animator; } + virtual Movie *createWSAMovie(); + + uint8 **shapes() { return _shapes; } + Character *currentCharacter() { return _currentCharacter; } + Character *characterList() { return _characterList; } + uint16 brandonStatus() { return _brandonStatusBit; } + + // TODO: remove me with workaround in animator.cpp l209 + uint16 getScene() { return _currentRoom; } + + int _paletteChanged; + int16 _northExitHeight; + + typedef void (KyraEngine_v1::*IntroProc)(); + + // static data access + const char * const*seqWSATable() { return _seq_WSATable; } + const char * const*seqCPSTable() { return _seq_CPSTable; } + const char * const*seqCOLTable() { return _seq_COLTable; } + const char * const*seqTextsTable() { return _seq_textsTable; } + + const uint8 * const*palTable1() { return &_specialPalettes[0]; } + const uint8 * const*palTable2() { return &_specialPalettes[29]; } + +protected: + virtual int go(); + virtual int init(); + +public: + // sequences + // -> misc + bool seq_skipSequence() const; +protected: + // -> demo + void seq_demo(); + + // -> intro + void seq_intro(); + void seq_introLogos(); + void seq_introStory(); + void seq_introMalcolmTree(); + void seq_introKallakWriting(); + void seq_introKallakMalcolm(); + + // -> ingame animations + void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly); + void seq_brandonHealing(); + void seq_brandonHealing2(); + void seq_poisonDeathNow(int now); + void seq_poisonDeathNowAnim(); + void seq_playFluteAnimation(); + void seq_winterScroll1(); + void seq_winterScroll2(); + void seq_makeBrandonInv(); + void seq_makeBrandonNormal(); + void seq_makeBrandonNormal2(); + void seq_makeBrandonWisp(); + void seq_dispelMagicAnimation(); + void seq_fillFlaskWithWater(int item, int type); + void seq_playDrinkPotionAnim(int item, int unk2, int flags); + void seq_brandonToStone(); + + // -> end fight + int seq_playEnd(); + void seq_playEnding(); + + int handleMalcolmFlag(); + int handleBeadState(); + void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr); + int processBead(int x, int y, int &x2, int &y2, BeadState *ptr); + + // -> credits + void seq_playCredits(); + +public: + // delay + void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false); + void delay(uint32 millis, bool update = false, bool isMainLoop = false); + void delayWithTicks(int ticks); + void waitForEvent(); + + // TODO + void registerDefaultSettings(); + void readSettings(); + void writeSettings(); + + void snd_playTheme(int file, int track = 0); + void snd_playVoiceFile(int id); + void snd_voiceWaitForFinish(bool ingame = true); + bool snd_voiceIsPlaying(); + void snd_stopVoice(); + void snd_playSoundEffect(int track); + void snd_playWanderScoreViaMap(int command, int restart); + + bool speechEnabled(); + bool textEnabled(); + + void saveGame(const char *fileName, const char *saveName); + void loadGame(const char *fileName); + +protected: + // input + void processInput(); + int processInputHelper(int xpos, int ypos); + int clickEventHandler(int xpos, int ypos); + void clickEventHandler2(); + void updateMousePointer(bool forceUpdate = false); + bool hasClickedOnExit(int xpos, int ypos); + + // scene + // -> init + void loadSceneMsc(); + void startSceneScript(int brandonAlive); + void setupSceneItems(); + void initSceneData(int facing, int unk1, int brandonAlive); + void initSceneObjectList(int brandonAlive); + void initSceneScreen(int brandonAlive); + void setupSceneResource(int sceneId); + + // -> process + void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); + int handleSceneChange(int xpos, int ypos, int unk1, int frameReset); + int processSceneChange(int *table, int unk1, int frameReset); + int changeScene(int facing); + + // -> modification + void transcendScenes(int roomIndex, int roomName); + void setSceneFile(int roomIndex, int roomName); + + // -> pathfinder + int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize); + bool lineIsPassable(int x, int y); + + // -> item handling + // --> misc + void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y); + + // --> drop handling + void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item); + int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2); + void dropItem(int unk1, int item, int x, int y, int unk2); + + // --> dropped item handling + int countItemsInScene(uint16 sceneId); + void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex); + byte findFreeItemInScene(int scene); + byte findItemAtPos(int x, int y); + + // --> drop area handling + void addToNoDropRects(int x, int y, int w, int h); + void clearNoDropRects(); + int isDropable(int x, int y); + int checkNoDropRects(int x, int y); + + // --> player items handling + void updatePlayerItemsForScene(); + + // --> item GFX handling + void backUpItemRect0(int xpos, int ypos); + void restoreItemRect0(int xpos, int ypos); + void backUpItemRect1(int xpos, int ypos); + void restoreItemRect1(int xpos, int ypos); + + // items + // -> misc + void placeItemInGenericMapScene(int item, int index); + + // -> mouse item + void createMouseItem(int item); + void destroyMouseItem(); + void setMouseItem(int item); + + // -> graphics effects + void wipeDownMouseItem(int xpos, int ypos); + void itemSpecialFX(int x, int y, int item); + void itemSpecialFX1(int x, int y, int item); + void itemSpecialFX2(int x, int y, int item); + void magicOutMouseItem(int animIndex, int itemPos); + void magicInMouseItem(int animIndex, int item, int itemPos); + void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops); + void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops); + + // character + // -> movement + void moveCharacterToPos(int character, int facing, int xpos, int ypos); + void setCharacterPositionWithUpdate(int character); + int setCharacterPosition(int character, int *facingTable); + void setCharacterPositionHelper(int character, int *facingTable); + void setCharactersPositions(int character); + + // -> brandon + void setBrandonPoisonFlags(int reset); + void resetBrandonPoisonFlags(); + + // chat + // -> process + void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration); + void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum); + + // -> initialization + int initCharacterChat(int8 charNum); + void backupChatPartnerAnimFrame(int8 charNum); + void restoreChatPartnerAnimFrame(int8 charNum); + int8 getChatPartnerNum(); + + // -> deinitialization + void endCharacterChat(int8 charNum, int16 arg_4); + + // graphics + // -> misc + int findDuplicateItemShape(int shape); + void updateKyragemFading(); + + // -> interface + void loadMainScreen(int page = 3); + void redrawInventory(int page); +public: + void drawSentenceCommand(const char *sentence, int unk1); + void updateSentenceCommand(const char *str1, const char *str2, int unk1); + void updateTextFade(); + +protected: + // -> amulet + void drawJewelPress(int jewel, int drawSpecial); + void drawJewelsFadeOutStart(); + void drawJewelsFadeOutEnd(int jewel); + + // -> shape handling + void setupShapes123(const Shape *shapeTable, int endShape, int flags); + void freeShapes123(); + + // misc (TODO) + void startup(); + void mainLoop(); + + int checkForNPCScriptRun(int xpos, int ypos); + void runNpcScript(int func); + + void loadMouseShapes(); + void loadCharacterShapes(); + void loadSpecialEffectShapes(); + void loadItems(); + void loadButtonShapes(); + void initMainButtonList(); + void setCharactersInDefaultScene(); + void setupPanPages(); + void freePanPages(); + void closeFinalWsa(); + + //void setTimer19(); + void setupTimers(); + void timerUpdateHeadAnims(int timerNum); + void timerSetFlags1(int timerNum); + void timerSetFlags2(int timerNum); + void timerSetFlags3(int timerNum); + void timerCheckAnimFlag1(int timerNum); + void timerCheckAnimFlag2(int timerNum); + void checkAmuletAnimFlags(); + void timerRedrawAmulet(int timerNum); + void timerFadeText(int timerNum); + void updateAnimFlag1(int timerNum); + void updateAnimFlag2(int timerNum); + void drawAmulet(); + void setTextFadeTimerCountdown(int16 countdown); + void setWalkspeed(uint8 newSpeed); + + int buttonInventoryCallback(Button *caller); + int buttonAmuletCallback(Button *caller); + int buttonMenuCallback(Button *caller); + int drawBoxCallback(Button *button); + int drawShadedBoxCallback(Button *button); + void calcCoords(Menu &menu); + void initMenu(Menu &menu); + void setGUILabels(); + + Button *initButton(Button *list, Button *newButton); + void processButtonList(Button *list); + void processButton(Button *button); + void processMenuButton(Button *button); + void processAllMenuButtons(); + + const char *getSavegameFilename(int num); + void setupSavegames(Menu &menu, int num); + int getNextSavegameSlot(); + + int gui_resumeGame(Button *button); + int gui_loadGameMenu(Button *button); + int gui_saveGameMenu(Button *button); + int gui_gameControlsMenu(Button *button); + int gui_quitPlaying(Button *button); + int gui_quitConfirmYes(Button *button); + int gui_quitConfirmNo(Button *button); + int gui_loadGame(Button *button); + int gui_saveGame(Button *button); + int gui_savegameConfirm(Button *button); + int gui_cancelSubMenu(Button *button); + int gui_scrollUp(Button *button); + int gui_scrollDown(Button *button); + int gui_controlsChangeMusic(Button *button); + int gui_controlsChangeSounds(Button *button); + int gui_controlsChangeWalk(Button *button); + int gui_controlsChangeText(Button *button); + int gui_controlsChangeVoice(Button *button); + int gui_controlsApply(Button *button); + + bool gui_quitConfirm(const char *str); + void gui_getInput(); + void gui_redrawText(Menu menu); + void gui_redrawHighlight(Menu menu); + void gui_processHighlights(Menu &menu); + void gui_updateSavegameString(); + void gui_redrawTextfield(); + void gui_fadePalette(); + void gui_restorePalette(); + void gui_setupControls(Menu &menu); + + bool _skipIntroFlag; + bool _abortIntroFlag; + bool _menuDirectlyToLoad; + bool _abortWalkFlag; + bool _abortWalkFlag2; + bool _mousePressFlag; + int8 _mouseWheel; + uint8 *_itemBkgBackUp[2]; + uint8 *_shapes[373]; + int8 _itemInHand; + int _mouseState; + bool _handleInput; + bool _changedScene; + int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3; + int _beadStateVar; + int _unkAmuletVar; + + int _malcolmFlag; + int _endSequenceSkipFlag; + int _endSequenceNeedLoading; + int _unkEndSeqVar2; + uint8 *_endSequenceBackUpRect; + int _unkEndSeqVar4; + int _unkEndSeqVar5; + int _lastDisplayedPanPage; + uint8 *_panPagesTable[20]; + Movie *_finalA, *_finalB, *_finalC; + + Movie *_movieObjects[10]; + + uint16 _entranceMouseCursorTracks[8]; + uint16 _walkBlockNorth; + uint16 _walkBlockEast; + uint16 _walkBlockSouth; + uint16 _walkBlockWest; + + int32 _scaleMode; + int16 _scaleTable[145]; + + Rect _noDropRects[11]; + + int8 _birthstoneGemTable[4]; + int8 _idolGemsTable[3]; + + int8 _marbleVaseItem; + int8 _foyerItemTable[3]; + + int8 _cauldronState; + int8 _crystalState[2]; + + uint16 _brandonStatusBit; + uint8 _brandonStatusBit0x02Flag; + uint8 _brandonStatusBit0x20Flag; + uint8 _brandonPoisonFlagsGFX[256]; + uint8 _deathHandler; + int16 _brandonInvFlag; + uint8 _poisonDeathCounter; + int _brandonPosX; + int _brandonPosY; + + uint16 _currentChatPartnerBackupFrame; + uint16 _currentCharAnimFrame; + + int8 *_sceneAnimTable[50]; + + Item _itemTable[145]; + int _lastProcessedItem; + int _lastProcessedItemHeight; + + int16 *_exitListPtr; + int16 _exitList[11]; + SceneExits _sceneExits; + uint16 _currentRoom; + int _scenePhasingFlag; + + int _sceneChangeState; + int _loopFlag2; + + int _pathfinderFlag; + int _pathfinderFlag2; + int _lastFindWayRet; + int *_movFacingTable; + + int8 _talkingCharNum; + int8 _charSayUnk2; + int8 _charSayUnk3; + int8 _currHeadShape; + uint8 _currSentenceColor[3]; + int8 _startSentencePalIndex; + bool _fadeText; + + uint8 _configTextspeed; + uint8 _configWalkspeed; + int _configMusic; + bool _configSounds; + uint8 _configVoice; + + int _curMusicTheme; + int _curSfxFile; + int16 _lastMusicCommand; + + ScreenAnimator *_animator; + SeqPlayer *_seq; + Sprites *_sprites; + Screen_v1 *_screen; + Debugger *_debugger; + + ScriptState *_scriptMain; + + ScriptState *_npcScript; + ScriptData *_npcScriptData; + + ScriptState *_scriptClick; + ScriptData *_scriptClickData; + + Character *_characterList; + Character *_currentCharacter; + + Button *_buttonList; + Button *_menuButtonList; + bool _displayMenu; + bool _menuRestoreScreen; + bool _displaySubMenu; + bool _cancelSubMenu; + uint8 _toplevelMenu; + int _savegameOffset; + int _gameToLoad; + char _savegameName[31]; + const char *_specialSavegameString; + Common::KeyState _keyPressed; + + struct KyragemState { + uint16 nextOperation; + uint16 rOffset; + uint16 gOffset; + uint16 bOffset; + uint32 timerCount; + } _kyragemFadingState; + + // TODO: get rid of all variables having pointers to the static resources if possible + // i.e. let them directly use the _staticres functions + void initStaticResource(); + + const uint8 *_seq_Forest; + const uint8 *_seq_KallakWriting; + const uint8 *_seq_KyrandiaLogo; + const uint8 *_seq_KallakMalcolm; + const uint8 *_seq_MalcolmTree; + const uint8 *_seq_WestwoodLogo; + const uint8 *_seq_Demo1; + const uint8 *_seq_Demo2; + const uint8 *_seq_Demo3; + const uint8 *_seq_Demo4; + const uint8 *_seq_Reunion; + + const char * const*_seq_WSATable; + const char * const*_seq_CPSTable; + const char * const*_seq_COLTable; + const char * const*_seq_textsTable; + + int _seq_WSATable_Size; + int _seq_CPSTable_Size; + int _seq_COLTable_Size; + int _seq_textsTable_Size; + + const char * const*_itemList; + const char * const*_takenList; + const char * const*_placedList; + const char * const*_droppedList; + const char * const*_noDropList; + const char * const*_putDownFirst; + const char * const*_waitForAmulet; + const char * const*_blackJewel; + const char * const*_poisonGone; + const char * const*_healingTip; + const char * const*_thePoison; + const char * const*_fluteString; + const char * const*_wispJewelStrings; + const char * const*_magicJewelString; + const char * const*_flaskFull; + const char * const*_fullFlask; + const char * const*_veryClever; + const char * const*_homeString; + const char * const*_newGameString; + + const char *_voiceTextString; + const char *_textSpeedString; + const char *_onString; + const char *_offString; + const char *_onCDString; + + int _itemList_Size; + int _takenList_Size; + int _placedList_Size; + int _droppedList_Size; + int _noDropList_Size; + int _putDownFirst_Size; + int _waitForAmulet_Size; + int _blackJewel_Size; + int _poisonGone_Size; + int _healingTip_Size; + int _thePoison_Size; + int _fluteString_Size; + int _wispJewelStrings_Size; + int _magicJewelString_Size; + int _flaskFull_Size; + int _fullFlask_Size; + int _veryClever_Size; + int _homeString_Size; + int _newGameString_Size; + + const char * const*_characterImageTable; + int _characterImageTableSize; + + const char * const*_guiStrings; + int _guiStringsSize; + + const char * const*_configStrings; + int _configStringsSize; + + Shape *_defaultShapeTable; + int _defaultShapeTableSize; + + const Shape *_healingShapeTable; + int _healingShapeTableSize; + const Shape *_healingShape2Table; + int _healingShape2TableSize; + + const Shape *_posionDeathShapeTable; + int _posionDeathShapeTableSize; + + const Shape *_fluteAnimShapeTable; + int _fluteAnimShapeTableSize; + + const Shape *_winterScrollTable; + int _winterScrollTableSize; + const Shape *_winterScroll1Table; + int _winterScroll1TableSize; + const Shape *_winterScroll2Table; + int _winterScroll2TableSize; + + const Shape *_drinkAnimationTable; + int _drinkAnimationTableSize; + + const Shape *_brandonToWispTable; + int _brandonToWispTableSize; + + const Shape *_magicAnimationTable; + int _magicAnimationTableSize; + + const Shape *_brandonStoneTable; + int _brandonStoneTableSize; + + Room *_roomTable; + int _roomTableSize; + const char * const*_roomFilenameTable; + int _roomFilenameTableSize; + + const uint8 *_amuleteAnim; + + const uint8 * const*_specialPalettes; + + static const char *_soundFiles[]; + static const int _soundFilesCount; + static const char *_soundFilesTowns[]; + static const int _soundFilesTownsCount; + + static const int8 _charXPosTable[]; + static const int8 _charYPosTable[]; + + // positions of the inventory + static const uint16 _itemPosX[]; + static const uint8 _itemPosY[]; + + void setupButtonData(); + Button *_buttonData; + Button **_buttonDataListPtr; + static Button _menuButtonData[]; + static Button _scrollUpButton; + static Button _scrollDownButton; + + bool _haveScrollButtons; + + void setupMenu(); + Menu *_menu; + + static const uint8 _magicMouseItemStartFrame[]; + static const uint8 _magicMouseItemEndFrame[]; + static const uint8 _magicMouseItemStartFrame2[]; + static const uint8 _magicMouseItemEndFrame2[]; + + static const uint16 _amuletX[]; + static const uint16 _amuletY[]; + static const uint16 _amuletX2[]; + static const uint16 _amuletY2[]; protected: - typedef OpcodeImpl<KyraEngine_v1> OpcodeV1; void setupOpcodeTable(); // Opcodes diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 6857b3ac09..317fd218b2 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -29,29 +29,64 @@ #include "kyra/resource.h" #include "kyra/wsamovie.h" #include "kyra/sound.h" +#include "kyra/script.h" +#include "kyra/text.h" +#include "kyra/timer.h" #include "common/system.h" namespace Kyra { KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) { - memset(_gameShapes, 0, sizeof(_gameShapes)); + memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable)); _mouseSHPBuf = 0; + + _gamePlayBuffer = 0; + _cCodeBuffer = _optionsBuffer = _chapterBuffer = 0; + + _overwriteSceneFacing = false; + _mainCharX = _mainCharY = -1; + _drawNoShapeFlag = false; + _charPalEntry = 0; + _itemInHand = -1; + _unkSceneScreenFlag1 = false; + _noScriptEnter = true; + _currentChapter = 0; + _newChapterFile = 1; + _handItemSet = -1; + _lastProcessedSceneScript = 0; + _specialSceneScriptRunFlag = false; + memset(_animObjects, 0, sizeof(_animObjects)); + _unkHandleSceneChangeFlag = false; + _pathfinderFlag = 0; + + memset(&_sceneScriptData, 0, sizeof(_sceneScriptData)); } KyraEngine_v2::~KyraEngine_v2() { delete [] _mouseSHPBuf; + delete _screen; +} + +Movie *KyraEngine_v2::createWSAMovie() { + return new WSAMovieV2(this); } int KyraEngine_v2::init() { + _screen = new Screen_v2(this, _system); + assert(_screen); + if (!_screen->init()) + error("_screen->init() failed"); + KyraEngine::init(); + + setupTimers(); - if (_res->getFileSize("6.FNT")) - _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); - if (_res->getFileSize("8FAT.FNT")) - _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); - _screen->loadFont(Screen::FID_GOLDFONT_FNT, "GOLDFONT.FNT"); - _screen->setAnimBlockPtr(3500); + _screen->loadFont(_screen->FID_6_FNT, "6.FNT"); + _screen->loadFont(_screen->FID_8_FNT, "8FAT.FNT"); + _screen->loadFont(_screen->FID_GOLDFONT_FNT, "GOLDFONT.FNT"); + _screen->loadFont(_screen->FID_BOOKFONT_FNT, "BOOKFONT.FNT"); + _screen->setAnimBlockPtr(3504); _screen->setScreenDim(0); assert(_introStringsSize == 21); @@ -66,11 +101,11 @@ int KyraEngine_v2::init() { assert(_mouseSHPBuf); for (int i = 0; i < 2; i++) { - _gameShapes[i] = _screen->getPtrToShape(_mouseSHPBuf, i); - assert(_gameShapes[i]); + _defaultShapeTable[i] = _screen->getPtrToShape(_mouseSHPBuf, i); + assert(_defaultShapeTable[i]); } - _screen->setMouseCursor(0, 0, _gameShapes[0]); + _screen->setMouseCursor(0, 0, _defaultShapeTable[0]); return 0; } @@ -95,7 +130,7 @@ int KyraEngine_v2::go() { _res->unloadPakFile("OUTFARM.PAK"); _res->unloadPakFile("FLYTRAP.PAK"); - seq_playSequences(kSequenceVirgin, kSequenceWestwood); + //seq_playSequences(kSequenceVirgin, kSequenceWestwood); mainMenu(); return 0; @@ -110,6 +145,11 @@ void KyraEngine_v2::mainMenu() { switch (gui_handleMainMenu()) { case 0: + _screen->showMouse(); + startup(); + runLoop(); + cleanup(); + running = false; break; case 1: seq_playSequences(kSequenceOverview, kSequenceZanFaun); @@ -123,7 +163,1130 @@ void KyraEngine_v2::mainMenu() { break; } _screen->hideMouse(); - } + } +} + +void KyraEngine_v2::startup() { + _screen->_curPage = 0; + delete [] _mouseSHPBuf; + _mouseSHPBuf = 0; + + memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable)); + memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable)); + _gamePlayBuffer = new uint8[46080]; + _unkBuf500Bytes = new uint8[500]; + + loadMouseShapes(); + loadItemShapes(); + + _screen->setMouseCursor(0, 0, getShapePtr(0)); + + _screenBuffer = new uint8[64000]; + + loadCCodeBuffer("C_CODE.XXX"); + loadOptionsBuffer("OPTIONS.XXX"); + loadChapterBuffer(_newChapterFile); + + _unkBuf200kByte = new uint8[200000]; + + showMessageFromCCode(265, 150, 0); + + // XXX + + showMessageFromCCode(0, 0, 207); + + // XXX + + _screen->setShapePages(5, 3); + + memset(&_mainCharacter, 0, sizeof(_mainCharacter)); + _mainCharacter.height = 0x30; + _mainCharacter.facing = 4; + _mainCharacter.animFrame = 0x12; + memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); + + memset(_sceneAnims, 0, sizeof(_sceneAnims)); + for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) + _sceneAnimMovie[i] = new WSAMovieV2(this); + memset(_wsaSlots, 0, sizeof(_wsaSlots)); + for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) + _wsaSlots[i] = new WSAMovieV2(this); + + _maskPage = 0;//_screen->getPagePtr(5); + _screen->_curPage = 0; + + _objectList = new Object[72]; + memset(_objectList, 0, sizeof(Object)*72); + _shapeDescTable = new ShapeDesc[55]; + memset(_shapeDescTable, 0, sizeof(ShapeDesc)*55); + + for (int i = 9; i <= 32; ++i) { + _shapeDescTable[i-9].unk5 = 30; + _shapeDescTable[i-9].unk7 = 55; + _shapeDescTable[i-9].xAdd = -15; + _shapeDescTable[i-9].yAdd = -50; + } + + for (int i = 19; i <= 24; ++i) { + _shapeDescTable[i-9].unk7 = 53; + _shapeDescTable[i-9].yAdd = -51; + } + + _gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)]; + _itemList = new Item[30]; + resetItemList(); + //loadButtonShapes(); + _loadedZTable = 1; + loadZShapes(_loadedZTable); + loadInventoryShapes(); + + _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300); + _screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0); + _screen->copyPage(3, 0); + _screen->showMouse(); + _screen->hideMouse(); + + clearAnimObjects(); + + // XXX + + _sceneList = new SceneDesc[86]; + runStartScript(1, 0); + loadNPCScript(); + + // XXX + + enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); + _screen->showMouse(); + + //sub_20EE8(1); + //setNextIdleAnimTimer(); + //XXX + _timer->setDelay(0, 5); +} + +void KyraEngine_v2::runLoop() { + _screen->updateScreen(); + + _quitFlag = false; + while (!_quitFlag) { + //XXX + int inputFlag = checkInput(0/*dword_324C5*/); + update(); + if (inputFlag == 198 || inputFlag == 199) { + _unk3 = _handItemSet; + Common::Point mouse = getMousePos(); + handleInput(mouse.x, mouse.y); + } + //XXX + } +} + +void KyraEngine_v2::handleInput(int x, int y) { + //setNextIdleAnimTimer(); + if (_unk5) { + _unk5 = 0; + return; + } + + if (!_screen->isMouseVisible()) + return; + + if (_unk3 == -2) { + //snd_playSfx(13); + return; + } + + //setNextIdleAnimTimer(); + + if (x <= 6 || x >= 312 || y <= 6 || y >= 135) { + bool exitOk = false; + assert(_unk3 + 6 >= 0); + switch (_unk3 + 6) { + case 0: + if (_sceneExit1 != 0xFFFF) + exitOk = true; + break; + + case 1: + if (_sceneExit2 != 0xFFFF) + exitOk = true; + break; + + case 2: + if (_sceneExit3 != 0xFFFF) + exitOk = true; + break; + + case 3: + if (_sceneExit4 != 0xFFFF) + exitOk = true; + break; + + default: + break; + } + + if (exitOk) { + inputSceneChange(x, y, 1, 1); + return; + } + } + + if (checkCharCollision(x, y) >= 0 && _unk3 >= -1) { + runSceneScript2(); + return; + } else { + //XXX + } + + //XXX + + inputSceneChange(x, y, 1, 1); +} + +int KyraEngine_v2::update() { + refreshAnimObjectsIfNeed(); + updateMouse(); + updateSpecialSceneScripts(); + _timer->update(); + //sub_274C0(); + //updateInvWsa(); + //sub_1574C(); + //XXX + _screen->updateScreen(); + return 0; +} + +void KyraEngine_v2::updateMouse() { + int shapeIndex = 0; + int type = 0; + int xOffset = 0, yOffset = 0; + Common::Point mouse = getMousePos(); + + if (mouse.y <= 145) { + if (mouse.x <= 6) { + if (_sceneExit4 != 0xFFFF) { + type = -3; + shapeIndex = 4; + xOffset = 1; + yOffset = 5; + } else { + type = -2; + } + } else if (mouse.x >= 312) { + if (_sceneExit2 != 0xFFFF) { + type = -5; + shapeIndex = 2; + xOffset = 7; + yOffset = 5; + } else { + type = -2; + } + } else if (mouse.y >= 135) { + if (_sceneExit3 != 0xFFFF) { + type = -4; + shapeIndex = 3; + xOffset = 5; + yOffset = 10; + } else { + type = -2; + } + } else if (mouse.y <= 6) { + if (_sceneExit1 != 0xFFFF) { + type = -6; + shapeIndex = 1; + xOffset = 5; + yOffset = 1; + } else { + type = -2; + } + } + } + + for (int i = 0; i < _specialExitCount; ++i) { + if (checkSpecialSceneExit(i, mouse.x, mouse.y)) { + switch (_specialExitTable[20+i]) { + case 0: + type = -6; + shapeIndex = 1; + xOffset = 5; + yOffset = 1; + break; + + case 2: + type = -5; + shapeIndex = 2; + xOffset = 7; + yOffset = 5; + break; + + case 4: + type = -4; + shapeIndex = 3; + xOffset = 5; + yOffset = 7; + break; + + case 6: + type = -3; + shapeIndex = 4; + xOffset = 1; + yOffset = 5; + break; + + default: + break; + } + } + } + + if (type == -2) { + shapeIndex = 5; + xOffset = 5; + yOffset = 9; + } + + if (type != 0 && _handItemSet != type) { + _handItemSet = type; + _screen->hideMouse(); + _screen->setMouseCursor(xOffset, yOffset, getShapePtr(shapeIndex)); + _screen->showMouse(); + } + + if (type == 0 && _handItemSet != _itemInHand) { + if ((mouse.y > 145) || (mouse.x > 6 && mouse.x < 312 && mouse.y > 6 && mouse.y < 135)) { + _handItemSet = _itemInHand; + _screen->hideMouse(); + if (_itemInHand == -1) + _screen->setMouseCursor(0, 0, getShapePtr(0)); + else + _screen->setMouseCursor(8, 15, getShapePtr(_itemInHand+64)); + _screen->showMouse(); + } + } +} + +int KyraEngine_v2::checkInput(void *p) { + Common::Event event; + int keys = 0; + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_RETURN) + keys = 199; + break; + + case Common::EVENT_LBUTTONUP: + keys = 198; + break; + + case Common::EVENT_QUIT: + _quitFlag = true; + break; + + default: + break; + } + + //if ( _debugger->isAttached()) + // _debugger->onFrame(); + } + + _system->delayMillis(10); + return keys; +} + +void KyraEngine_v2::cleanup() { + delete [] _gamePlayBuffer; + delete [] _unkBuf500Bytes; + delete [] _screenBuffer; + delete [] _unkBuf200kByte; + + for (int i = 0; i < ARRAYSIZE(_defaultShapeTable); ++i) + delete [] _defaultShapeTable[i]; + freeSceneShapePtrs(); + + delete [] _cCodeBuffer; + delete [] _optionsBuffer; + delete [] _chapterBuffer; + + delete [] _objectList; + delete [] _shapeDescTable; + + delete [] _gfxBackUpRect; + + delete [] _sceneList; + + for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) + delete _sceneAnimMovie[i]; + for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) + delete _wsaSlots[i]; +} + +#pragma mark - Localization + +void KyraEngine_v2::loadCCodeBuffer(const char *file) { + char tempString[13]; + strcpy(tempString, file); + changeFileExtension(tempString); + + delete [] _cCodeBuffer; + _cCodeBuffer = _res->fileData(tempString, 0); +} + +void KyraEngine_v2::loadOptionsBuffer(const char *file) { + char tempString[13]; + strcpy(tempString, file); + changeFileExtension(tempString); + + delete [] _optionsBuffer; + _optionsBuffer = _res->fileData(tempString, 0); +} + +void KyraEngine_v2::loadChapterBuffer(int chapter) { + char tempString[14]; + + static const char *chapterFilenames[] = { + "CH1.XXX", "CH2.XXX", "CH3.XXX", "CH4.XXX", "CH5.XXX" + }; + + assert(chapter >= 1 && chapter <= ARRAYSIZE(chapterFilenames)); + strcpy(tempString, chapterFilenames[chapter-1]); + changeFileExtension(tempString); + + delete [] _chapterBuffer; + _chapterBuffer = _res->fileData(tempString, 0); + _currentChapter = chapter; +} + +void KyraEngine_v2::changeFileExtension(char *buffer) { + while (*buffer != '.') ++buffer; + + ++buffer; + strcpy(buffer, _languageExtension[_lang]); +} + +const uint8 *KyraEngine_v2::getTableEntry(const uint8 *buffer, int id) { + return buffer + READ_LE_UINT16(buffer + (id<<1)); +} + +const char *KyraEngine_v2::getTableString(int id, const uint8 *buffer, int decode) { + const char *string = (const char*)getTableEntry(buffer, id); + + if (decode) { + decodeString1(string, _internStringBuf); + decodeString2(_internStringBuf, _internStringBuf); + string = _internStringBuf; + } + + return string; +} + +const char *KyraEngine_v2::getChapterString(int id) { + if (_currentChapter != _newChapterFile) + loadChapterBuffer(_newChapterFile); + + return getTableString(id, _chapterBuffer, 1); +} + +int KyraEngine_v2::decodeString1(const char *src, char *dst) { + static const uint8 decodeTable1[] = { + 0x20, 0x65, 0x74, 0x61, 0x69, 0x6E, 0x6F, 0x73, 0x72, 0x6C, 0x68, + 0x63, 0x64, 0x75, 0x70, 0x6D + }; + + static const uint8 decodeTable2[] = { + 0x74, 0x61, 0x73, 0x69, 0x6F, 0x20, 0x77, 0x62, 0x20, 0x72, 0x6E, + 0x73, 0x64, 0x61, 0x6C, 0x6D, 0x68, 0x20, 0x69, 0x65, 0x6F, 0x72, + 0x61, 0x73, 0x6E, 0x72, 0x74, 0x6C, 0x63, 0x20, 0x73, 0x79, 0x6E, + 0x73, 0x74, 0x63, 0x6C, 0x6F, 0x65, 0x72, 0x20, 0x64, 0x74, 0x67, + 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x72, 0x20, 0x75, 0x66, 0x6D, 0x73, + 0x77, 0x20, 0x74, 0x65, 0x70, 0x2E, 0x69, 0x63, 0x61, 0x65, 0x20, + 0x6F, 0x69, 0x61, 0x64, 0x75, 0x72, 0x20, 0x6C, 0x61, 0x65, 0x69, + 0x79, 0x6F, 0x64, 0x65, 0x69, 0x61, 0x20, 0x6F, 0x74, 0x72, 0x75, + 0x65, 0x74, 0x6F, 0x61, 0x6B, 0x68, 0x6C, 0x72, 0x20, 0x65, 0x69, + 0x75, 0x2C, 0x2E, 0x6F, 0x61, 0x6E, 0x73, 0x72, 0x63, 0x74, 0x6C, + 0x61, 0x69, 0x6C, 0x65, 0x6F, 0x69, 0x72, 0x61, 0x74, 0x70, 0x65, + 0x61, 0x6F, 0x69, 0x70, 0x20, 0x62, 0x6D + }; + + int size = 0; + uint cChar = 0; + while ((cChar = *src++) != 0) { + if (cChar & 0x80) { + cChar &= 0x7F; + int index = (cChar & 0x78) >> 3; + *dst++ = decodeTable1[index]; + ++size; + assert(cChar < sizeof(decodeTable2)); + cChar = decodeTable2[cChar]; + } + + *dst++ = cChar; + ++size; + } + + *dst++ = 0; + return size; +} + +void KyraEngine_v2::decodeString2(const char *src, char *dst) { + if (!src || !dst) + return; + + char out = 0; + while ((out = *src) != 0) { + if (*src == 0x1B) { + ++src; + out = *src + 0x7F; + } + *dst++ = out; + ++src; + } + + *dst = 0; +} + +#pragma mark - + +void KyraEngine_v2::showMessageFromCCode(int id, int16 palIndex, int) { + const char *string = getTableString(id, _cCodeBuffer, 1); + showMessage(string, palIndex); +} + +void KyraEngine_v2::showMessage(const char *string, int16 palIndex) { + _shownMessage = string; + _screen->hideMouse(); + _screen->fillRect(0, 190, 319, 199, 0xCF); + + if (string) { + if (palIndex != -1 || _msgUnk1) { + palIndex *= 3; + memcpy(_messagePal, _screen->_currentPalette + palIndex, 3); + memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3); + _screen->setScreenPalette(_screen->_currentPalette); + } + + int x = _text->getCenterStringX(string, 0, 320); + _text->printText(string, x, 190, 255, 207, 0); + + setTimer1DelaySecs(7); + } + + _msgUnk1 = 0; + _screen->showMouse(); +} + +void KyraEngine_v2::showChapterMessage(int id, int16 palIndex) { + showMessage(getChapterString(id), palIndex); +} + +void KyraEngine_v2::loadMouseShapes() { + _screen->loadBitmap("_MOUSE.CSH", 3, 3, 0); + + for (int i = 0; i <= 8; ++i) { + _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i); + assert(_defaultShapeTable[i]); + } +} + +void KyraEngine_v2::loadItemShapes() { + _screen->loadBitmap("_ITEMS.CSH", 3, 3, 0); + + for (int i = 64; i <= 239; ++i) { + _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i-64); + assert(_defaultShapeTable[i]); + } + + _res->loadFileToBuf("_ITEMHT.DAT", _itemHtDat, sizeof(_itemHtDat)); + assert(_res->getFileSize("_ITEMHT.DAT") == sizeof(_itemHtDat)); + + _screen->_curPage = 0; +} + +void KyraEngine_v2::loadZShapes(int shapes) { + char file[10]; + strcpy(file, "_ZX.SHP"); + + _loadedZTable = shapes; + file[2] = '0' + shapes; + + uint8 *data = _res->fileData(file, 0); + for (int i = 9; i <= 32; ++i) { + delete [] _defaultShapeTable[i]; + _defaultShapeTable[i] = _screen->makeShapeCopy(data, i-9); + } + delete [] data; + + _loadedZTable = shapes; +} + +void KyraEngine_v2::loadInventoryShapes() { + int curPageBackUp = _screen->_curPage; + _screen->_curPage = 2; + + _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0); + + for (int i = 0; i < 10; ++i) + _defaultShapeTable[240+i] = _screen->encodeShape(_inventoryX[i], _inventoryY[i], 16, 16, 0); + + _screen->_curPage = curPageBackUp; +} + +void KyraEngine_v2::runStartScript(int script, int unk1) { + char filename[14]; + strcpy(filename, "_START0X.EMC"); + filename[7] = script + '0'; + + ScriptData scriptData; + ScriptState scriptState; + + _scriptInterpreter->loadScript(filename, &scriptData, &_opcodes); + _scriptInterpreter->initScript(&scriptState, &scriptData); + scriptState.regs[6] = unk1; + _scriptInterpreter->startScript(&scriptState, 0); + while (_scriptInterpreter->validScript(&scriptState)) + _scriptInterpreter->runScript(&scriptState); + _scriptInterpreter->unloadScript(&scriptData); +} + +void KyraEngine_v2::loadNPCScript() { + char filename[12]; + strcpy(filename, "_NPC.EMC"); + + switch (_lang) { + case 0: + filename[5] = 'E'; + break; + + case 1: + filename[5] = 'F'; + break; + + case 2: + filename[5] = 'G'; + break; + + default: + break; + }; + + _scriptInterpreter->loadScript(filename, &_npcScriptData, &_opcodes); +} + +void KyraEngine_v2::resetScaleTable() { + for (int i = 0; i < ARRAYSIZE(_scaleTable); ++i) + _scaleTable[i] = 0x100; +} + +void KyraEngine_v2::setScaleTableItem(int item, int data) { + if (item >= 1 || item <= 15) + _scaleTable[item-1] = (data << 8) / 100; +} + +int KyraEngine_v2::getScale(int x, int y) { + return _scaleTable[_screen->getLayer(x, y) - 1]; +} + +void KyraEngine_v2::setDrawLayerTableEntry(int entry, int data) { + if (entry >= 1 || entry <= 15) + _drawLayerTable[entry-1] = data; +} + +int KyraEngine_v2::getDrawLayer(int x, int y) { + int layer = _screen->getLayer(x, y); + layer = _drawLayerTable[layer-1]; + if (layer < 0) + layer = 0; + else if (layer >= 7) + layer = 6; + return layer; +} + +void KyraEngine_v2::restorePage3() { + _screen->copyBlockToPage(2, 0, 0, 320, 144, _gamePlayBuffer); +} + +void KyraEngine_v2::updateCharPal(int unk1) { + static bool unkVar1 = false; + + if (!_useCharPal) + return; + + int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1); + int palEntry = _charPalTable[layer]; + + if (palEntry != _charPalEntry && unk1) { + const uint8 *src = &_scenePal[(palEntry << 4) * 3]; + uint8 *ptr = _screen->getPalette(0) + 336; + for (int i = 0; i < 48; ++i) { + *ptr -= (*ptr - *src) >> 1; + ++ptr; + ++src; + } + _screen->setScreenPalette(_screen->getPalette(0)); + unkVar1 = true; + _charPalEntry = palEntry; + } else if (unkVar1 && !unk1) { + memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48); + _screen->setScreenPalette(_screen->getPalette(0)); + unkVar1 = false; + } +} + +int KyraEngine_v2::inputSceneChange(int x, int y, int unk1, int unk2) { + bool refreshNPC = false; + uint16 curScene = _mainCharacter.sceneId; + _pathfinderFlag = 15; + + if (!_unkHandleSceneChangeFlag) { + if (_unk3 == -3) { + if (_sceneList[curScene].exit4 != 0xFFFF) { + x = 4; + y = _sceneEnterY4; + _pathfinderFlag = 7; + } + } else if (_unk3 == -5) { + if (_sceneList[curScene].exit2 != 0xFFFF) { + x = 316; + y = _sceneEnterY2; + _pathfinderFlag = 7; + } + } else if (_unk3 == -6) { + if (_sceneList[curScene].exit1 != 0xFFFF) { + x = _sceneEnterX1; + y = _sceneEnterY1 - 2; + _pathfinderFlag = 14; + } + } else if (_unk3 == -4) { + if (_sceneList[curScene].exit3 != 0xFFFF) { + x = _sceneEnterX3; + y = 147; + _pathfinderFlag = 11; + } + } + } + + if (_pathfinderFlag) { + if (findItem(curScene, 13) >= 0 && _unk3 <= -3) { + //XXX + _pathfinderFlag = 0; + return 0; + } else if (_itemInHand == 72) { + //XXX + _pathfinderFlag = 0; + return 0; + } else if (findItem(curScene, 72) >= 0 && _unk3 <= -3) { + //XXX + _pathfinderFlag = 0; + return 0; + } else if (0/*XXX*/) { + //XXX + _pathfinderFlag = 0; + return 0; + } + } + + if (ABS(_mainCharacter.x1 - x) < 4 || ABS(_mainCharacter.y1 - y) < 2) + return 0; + + int curX = _mainCharacter.x1 & ~3; + int curY = _mainCharacter.y1 & ~1; + int dstX = x & ~3; + int dstY = y & ~1; + + int wayLength = findWay(curX, curY, dstX, dstY, _movFacingTable, 600); + _pathfinderFlag = 0; + _timer->disable(5); + + if (wayLength != 0 && wayLength != 0x7D00) + refreshNPC = (trySceneChange(_movFacingTable, unk1, unk2) != 0); + + //XXX + + if (refreshNPC) + enterNewSceneUnk2(0); + + _pathfinderFlag = 0; + return refreshNPC; +} + +bool KyraEngine_v2::checkSpecialSceneExit(int num, int x, int y) { + if (_specialExitTable[0+num] > x || _specialExitTable[5+num] > y || + _specialExitTable[10+num] < x || _specialExitTable[15+num] < y) + return 0; + return 1; +} + +void KyraEngine_v2::moveCharacter(int facing, int x, int y) { + _mainCharacter.facing = facing; + x &= ~3; + y &= ~1; + + _screen->hideMouse(); + switch (facing) { + case 0: + while (y < _mainCharacter.y1) + updateCharPosWithUpdate(); + break; + + case 2: + while (_mainCharacter.x1 < x) + updateCharPosWithUpdate(); + break; + + case 4: + while (y > _mainCharacter.y1) + updateCharPosWithUpdate(); + break; + + case 6: + while (_mainCharacter.x1 > x) + updateCharPosWithUpdate(); + break; + + default: + break; + } + + _screen->showMouse(); +} + +int KyraEngine_v2::updateCharPos(int *table) { + static uint32 nextUpdate = 0; + static const int updateX[] = { 0, 4, 4, 4, 0, -4, -4, -4 }; + static const int updateY[] = { -2, -2, 0, 2, 2, 2, 0, -2 }; + + if (_system->getMillis() < nextUpdate) + return 0; + + int facing = _mainCharacter.facing; + _mainCharacter.x1 += updateX[facing]; + _mainCharacter.y1 += updateY[facing]; + updateCharAnimFrame(0, table); + nextUpdate = _system->getMillis() + _timer->getDelay(0) * _tickLength; + return 1; +} + +void KyraEngine_v2::updateCharPosWithUpdate() { + updateCharPos(0); + update(); +} + +void KyraEngine_v2::updateCharAnimFrame(int charId, int *table) { + static int unkTable1[] = { 0, 0 }; + static const int unkTable2[] = { 17, 0 }; + static const int unkTable3[] = { 10, 0 }; + static const int unkTable4[] = { 24, 0 }; + static const int unkTable5[] = { 19, 0 }; + static const int unkTable6[] = { 21, 0 }; + static const int unkTable7[] = { 31, 0 }; + static const int unkTable8[] = { 26, 0 }; + + Character *character = &_mainCharacter; + ++character->animFrame; + int facing = character->facing; + + if (table) { + if (table[0] != table[-1] && table[-1] == table[1]) { + facing = getOppositeFacingDirection(table[-1]); + table[0] = table[-1]; + } + } + + if (!facing) { + ++unkTable1[charId]; + } else if (facing == 4) { + ++unkTable1[charId+1]; + } else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) { + if (facing == 7 || facing == 1) { + if (unkTable1[charId] > 2) + facing = 0; + } else { + if (unkTable1[charId+1] > 2) + facing = 4; + } + + unkTable1[charId] = 0; + unkTable1[charId+1] = 0; + } + + if (facing == 0) { + if (character->animFrame < unkTable8[charId]) + character->animFrame = unkTable8[charId]; + + if (character->animFrame > unkTable7[charId]) + character->animFrame = unkTable8[charId]; + } else if (facing == 4) { + if (character->animFrame < unkTable5[charId]) + character->animFrame = unkTable5[charId]; + + if (character->animFrame > unkTable4[charId]) + character->animFrame = unkTable5[charId]; + } else { + if (character->animFrame > unkTable5[charId]) + character->animFrame = unkTable6[charId]; + + if (character->animFrame == unkTable2[charId]) + character->animFrame = unkTable3[charId]; + + if (character->animFrame > unkTable2[charId]) + character->animFrame = unkTable3[charId] + 2; + } + + updateCharacterAnim(charId); +} + +int KyraEngine_v2::checkCharCollision(int x, int y) { + int scale1 = 0, scale2 = 0, scale3 = 0; + int x1 = 0, x2 = 0, y1 = 0, y2 = 0; + scale1 = getScale(_mainCharacter.x1, _mainCharacter.y1); + scale2 = (scale1 * 24) >> 8; + scale3 = (scale1 * 48) >> 8; + + x1 = _mainCharacter.x1 - (scale2 >> 1); + x2 = _mainCharacter.x1 + (scale2 >> 1); + y1 = _mainCharacter.y1 - scale3; + y2 = _mainCharacter.y1; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + return 0; + + return -1; +} + +#pragma mark - + +typedef Functor1Mem<ScriptState*, int, KyraEngine_v2> OpcodeV2; +#define Opcode(x) OpcodeV2(this, &KyraEngine_v2::x) +#define OpcodeUnImpl() OpcodeV2(this, 0) +void KyraEngine_v2::setupOpcodeTable() { + static const OpcodeV2 opcodeTable[] = { + // 0x00 + Opcode(o2_setCharacterFacingRefresh), + OpcodeUnImpl(), + Opcode(o2_defineObject), + Opcode(o2_refreshCharacter), + // 0x04 + Opcode(o2_getCharacterX), + Opcode(o2_getCharacterY), + Opcode(o2_getCharacterFacing), + OpcodeUnImpl(), + // 0x08 + Opcode(o2_setSceneComment), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x0c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x10 + OpcodeUnImpl(), + Opcode(o2_showChapterMessage), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x14 + Opcode(o2_wsaClose), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_displayWsaFrame), + // 0x18 + Opcode(o2_displayWsaSequentialFrames), + Opcode(o2_wsaOpen), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x1c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x20 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_defineItem), + // 0x24 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_queryGameFlag), + // 0x28 + Opcode(o2_resetGameFlag), + Opcode(o2_setGameFlag), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x2c + OpcodeUnImpl(), + Opcode(o2_hideMouse), + Opcode(o2_addSpecialExit), + OpcodeUnImpl(), + // 0x30 + Opcode(o2_showMouse), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x34 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x38 + Opcode(o2_dummy), + OpcodeUnImpl(), + Opcode(o2_setScaleTableItem), + Opcode(o2_setDrawLayerTableItem), + // 0x3c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_drawSceneShapeOnPage), + // 0x40 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_dummy), + OpcodeUnImpl(), + // 0x44 + OpcodeUnImpl(), + Opcode(o2_restoreBackBuffer), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x48 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x4c + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_dummy), + Opcode(o2_dummy), + // 0x50 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x54 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x58 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x5c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x60 + Opcode(o2_getRand), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x64 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x68 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x6c + Opcode(o2_encodeShape), + Opcode(o2_defineRoomEntrance), + OpcodeUnImpl(), + Opcode(o2_setSpecialSceneScriptRunTime), + // 0x70 + Opcode(o2_defineSceneAnim), + Opcode(o2_updateSceneAnim), + Opcode(o2_updateSceneAnim), + OpcodeUnImpl(), + // 0x74 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x78 + OpcodeUnImpl(), + Opcode(o2_defineRoom), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x7c + OpcodeUnImpl(), + Opcode(o2_dummy), + Opcode(o2_dummy), + OpcodeUnImpl(), + // 0x80 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x84 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x88 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x8c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_setSpecialSceneScriptState), + // 0x90 + Opcode(o2_clearSpecialSceneScriptState), + Opcode(o2_querySpecialSceneScriptState), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x94 + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_wsaClose), + OpcodeUnImpl(), + // 0x98 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0x9c + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xa0 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xa4 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xa8 + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + OpcodeUnImpl(), + // 0xac + OpcodeUnImpl(), + OpcodeUnImpl(), + Opcode(o2_dummy), + Opcode(o2_dummy), + }; + + for (int i = 0; i < ARRAYSIZE(opcodeTable); ++i) + _opcodes.push_back(&opcodeTable[i]); } } // end of namespace Kyra diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h index a002baec19..c87eeb66d4 100644 --- a/engines/kyra/kyra_v2.h +++ b/engines/kyra/kyra_v2.h @@ -26,6 +26,10 @@ #ifndef KYRA_KYRA_V2_H #define KYRA_KYRA_V2_H +#include "kyra/kyra.h" +#include "kyra/script.h" +#include "kyra/screen_v2.h" + namespace Kyra { enum kSequences { @@ -82,12 +86,25 @@ class KyraEngine_v2 : public KyraEngine { public: KyraEngine_v2(OSystem *system, const GameFlags &flags); ~KyraEngine_v2(); + + virtual Screen *screen() { return _screen; } + Screen_v2 *screen_v2() { return _screen; } + + Movie *createWSAMovie(); +protected: + // Main menu code, also used for Kyra 3 + static const char *_mainMenuStrings[]; - int go(); - -private: - void setupOpcodeTable() {} + virtual void gui_initMainMenu() {} + int gui_handleMainMenu(); + virtual void gui_updateMainMenuAnimation(); + void gui_drawMainMenu(const char * const *strings, int select); + void gui_drawMainBox(int x, int y, int w, int h, int fill); + bool gui_mainMenuGetInput(); + + void gui_printString(const char *string, int x, int y, int col1, int col2, int flags, ...); + // intro void seq_playSequences(int startSeq, int endSeq = -1); int seq_introWestwood(int seqNum); int seq_introTitle(int seqNum); @@ -111,11 +128,14 @@ private: void seq_setChatEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 unk1); void mainMenu(); + int init(); + int go(); + + Screen_v2 *_screen; ActiveWSA *_activeWSA; ActiveChat *_activeChat; - uint8 *_gameShapes[50]; uint8 *_mouseSHPBuf; static const char *_introSoundList[]; @@ -124,6 +144,351 @@ private: static const int _introStringsSize; int _introStringsDuration[21]; + +protected: + // game initialization + void startup(); + void runLoop(); + void cleanup(); + + void setupTimers(); + void setupOpcodeTable(); + + void loadMouseShapes(); + void loadItemShapes(); + + // run + int update(); + void updateMouse(); + + int checkInput(void *p); + void handleInput(int x, int y); + + int inputSceneChange(int x, int y, int unk1, int unk2); + + // gfx/animation specific + uint8 *_gamePlayBuffer; + void restorePage3(); + + uint8 *_screenBuffer; + uint8 *_maskPage; + uint8 *_gfxBackUpRect; + + uint8 *getShapePtr(int index) { return _defaultShapeTable[index]; } + uint8 *_defaultShapeTable[250]; + uint8 *_sceneShapeTable[50]; + + WSAMovieV2 *_wsaSlots[10]; + + void freeSceneShapePtrs(); + + struct ShapeDesc { + uint8 unk0, unk1, unk2, unk3, unk4; + uint16 unk5, unk7; + int16 xAdd, yAdd; + }; + + ShapeDesc *_shapeDescTable; + + struct SceneAnim { + uint16 flags; + int16 x, y; + int16 x2, y2; + int16 width, height; + uint16 unkE; + uint16 specialSize; + uint16 unk12; + int16 shapeIndex; + uint16 wsaFlag; + char filename[14]; + }; + + SceneAnim _sceneAnims[10]; + WSAMovieV2 *_sceneAnimMovie[10]; + bool _specialSceneScriptState[10]; + ScriptState _sceneSpecialScripts[10]; + uint32 _sceneSpecialScriptsTimer[10]; + int _lastProcessedSceneScript; + bool _specialSceneScriptRunFlag; + + void updateSpecialSceneScripts(); + void freeSceneAnims(); + + int _loadedZTable; + void loadZShapes(int shapes); + void loadInventoryShapes(); + + void resetScaleTable(); + void setScaleTableItem(int item, int data); + int getScale(int x, int y); + uint16 _scaleTable[15]; + + void setDrawLayerTableEntry(int entry, int data); + int getDrawLayer(int x, int y); + int _drawLayerTable[15]; + + // animator + struct AnimObj { + uint16 index; + uint16 type; + uint16 enabled; + uint16 needRefresh; + uint16 unk8; + uint16 animFlags; + uint16 flags; + int16 xPos1, yPos1; + uint8 *shapePtr; + uint16 shapeIndex1; + uint16 animNum; + uint16 shapeIndex3; + uint16 shapeIndex2; + uint16 unk1E; + uint8 unk20; + uint8 unk21; + uint8 unk22; + uint8 unk23; + int16 xPos2, yPos2; + int16 xPos3, yPos3; + int16 width, height; + int16 width2, height2; + AnimObj *nextObject; + }; + + AnimObj _animObjects[42]; + void clearAnimObjects(); + + AnimObj *_animList; + bool _drawNoShapeFlag; + AnimObj *initAnimList(AnimObj *list, AnimObj *entry); + AnimObj *addToAnimListSorted(AnimObj *list, AnimObj *entry); + AnimObj *deleteAnimListEntry(AnimObj *list, AnimObj *entry); + + void drawAnimObjects(); + void drawSceneAnimObject(AnimObj *obj, int x, int y, int drawLayer); + void drawCharacterAnimObject(AnimObj *obj, int x, int y, int drawLayer); + + void refreshAnimObjects(int force); + void refreshAnimObjectsIfNeed(); + + void updateCharacterAnim(int); + void updateSceneAnim(int anim, int newFrame); + + // scene + struct SceneDesc { + char filename[10]; + uint16 exit1, exit2, exit3, exit4; + uint8 flags; + uint8 sound; + }; + + SceneDesc *_sceneList; + const char *_sceneCommentString; + uint16 _sceneExit1, _sceneExit2, _sceneExit3, _sceneExit4; + int _sceneEnterX1, _sceneEnterY1, _sceneEnterX2, _sceneEnterY2, + _sceneEnterX3, _sceneEnterY3, _sceneEnterX4, _sceneEnterY4; + int _specialExitCount; + uint16 _specialExitTable[25]; + bool checkSpecialSceneExit(int num, int x, int y); + uint8 _scenePal[688]; + bool _overwriteSceneFacing; + + void enterNewScene(uint16 newScene, int facing, int unk1, int unk2, int unk3); + void enterNewSceneUnk1(int facing, int unk1, int unk2); + void enterNewSceneUnk2(int unk1); + void unloadScene(); + + void loadScenePal(); + void loadSceneMsc(); + + void startSceneScript(int unk1); + void runSceneScript2(); + void runSceneScript4(int unk1); + void runSceneScript7(); + + void initSceneAnims(int unk1); + void initSceneScreen(int unk1); + + int trySceneChange(int *moveTable, int unk1, int updateChar); + int checkSceneChange(); + + // pathfinder + int _movFacingTable[600]; + int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize); + bool lineIsPassable(int x, int y); + bool directLinePassable(int x, int y, int toX, int toY); + + int pathfinderUnk1(int *moveTable); + int pathfinderUnk2(int index, int v1, int v2); + int pathfinderUnk3(int tableLen, int x, int y); + int pathfinderUnk4(int index, int v); + void pathfinderUnk5(int *moveTable, int unk1, int x, int y, int moveTableSize); + + int _pathfinderUnkTable1[400]; + int _pathfinderUnkTable2[200]; + + // item + uint8 _itemHtDat[176]; + + struct Item { + uint16 id; + uint16 sceneId; + int16 x; + int8 y; + uint16 unk7; + }; + Item *_itemList; + + int findFreeItem(); + int findItem(uint16 sceneId, int id); + void resetItemList(); + + int _itemInHand; + int _handItemSet; + + // inventroy + static int _inventoryX[]; + static int _inventoryY[]; + + // localization + void loadCCodeBuffer(const char *file); + void loadOptionsBuffer(const char *file); + void loadChapterBuffer(int chapter); + uint8 *_optionsBuffer; + uint8 *_cCodeBuffer; + + uint8 *_chapterBuffer; + int _currentChapter; + int _newChapterFile; + + const uint8 *getTableEntry(const uint8 *buffer, int id); + const char *getTableString(int id, const uint8 *buffer, int decode); + const char *getChapterString(int id); + int decodeString1(const char *src, char *dst); + void decodeString2(const char *src, char *dst); + + void changeFileExtension(char *buffer); + + char _internStringBuf[200]; + static const char *_languageExtension[]; + static const char *_scriptLangExt[]; + + // character + struct Character { + uint16 sceneId; + uint16 unk2; + uint8 height; + uint8 facing; + uint16 animFrame; + uint8 unk8; + uint8 unk9; + uint8 unkA; + uint16 inventory[20]; + int16 x1, y1; + int16 x2, y2; + }; + + Character _mainCharacter; + bool _useCharPal; + int _charPalEntry; + uint8 _charPalTable[16]; + void updateCharPal(int unk1); + + void moveCharacter(int facing, int x, int y); + int updateCharPos(int *table); + void updateCharPosWithUpdate(); + void updateCharAnimFrame(int num, int *table); + + int checkCharCollision(int x, int y); + + int _mainCharX, _mainCharY; + int _charScaleX, _charScaleY; + + static int _characterFrameTable[]; + + // text + void showMessageFromCCode(int id, int16 palIndex, int); + void showMessage(const char *string, int16 palIndex); + void showChapterMessage(int id, int16 palIndex); + + const char *_shownMessage; + + byte _messagePal[3]; + int _msgUnk1; + + // timer + void timerFunc2(int); + void timerFunc3(int); + void timerFunc4(int); + void timerFunc5(int); + void timerFunc6(int); + + void setTimer1DelaySecs(int secs); + + // opcodes + int o2_setCharacterFacingRefresh(ScriptState *script); + int o2_defineObject(ScriptState *script); + int o2_refreshCharacter(ScriptState *script); + int o2_getCharacterX(ScriptState *script); + int o2_getCharacterY(ScriptState *script); + int o2_getCharacterFacing(ScriptState *script); + int o2_setSceneComment(ScriptState *script); + int o2_showChapterMessage(ScriptState *script); + int o2_wsaClose(ScriptState *script); + int o2_displayWsaFrame(ScriptState *script); + int o2_displayWsaSequentialFrames(ScriptState *script); + int o2_wsaOpen(ScriptState *script); + int o2_defineItem(ScriptState *script); + int o2_queryGameFlag(ScriptState *script); + int o2_resetGameFlag(ScriptState *script); + int o2_setGameFlag(ScriptState *script); + int o2_hideMouse(ScriptState *script); + int o2_addSpecialExit(ScriptState *script); + int o2_showMouse(ScriptState *script); + int o2_setScaleTableItem(ScriptState *script); + int o2_setDrawLayerTableItem(ScriptState *script); + int o2_drawSceneShapeOnPage(ScriptState *script); + int o2_restoreBackBuffer(ScriptState *script); + int o2_getRand(ScriptState *script); + int o2_encodeShape(ScriptState *script); + int o2_defineRoomEntrance(ScriptState *script); + int o2_setSpecialSceneScriptRunTime(ScriptState *script); + int o2_defineSceneAnim(ScriptState *script); + int o2_updateSceneAnim(ScriptState *script); + int o2_defineRoom(ScriptState *script); + int o2_setSpecialSceneScriptState(ScriptState *script); + int o2_clearSpecialSceneScriptState(ScriptState *script); + int o2_querySpecialSceneScriptState(ScriptState *script); + int o2_dummy(ScriptState *script); + + // script + void runStartScript(int script, int unk1); + void loadNPCScript(); + + bool _noScriptEnter; + + ScriptData _npcScriptData; + + ScriptData _sceneScriptData; + ScriptState _sceneScriptState; + + // pathfinder + int _pathfinderFlag; + + // unk + struct Object { + char filename[13]; + uint8 scriptId; + int16 x, y; + int8 unk12; + }; + Object *_objectList; + + uint8 *_unkBuf500Bytes; + uint8 *_unkBuf200kByte; + bool _unkFlag1; + int _unk3, _unk4, _unk5; + bool _unkSceneScreenFlag1; + bool _unkHandleSceneChangeFlag; }; } // end of namespace Kyra diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index eee901598e..32754ecf2f 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -38,7 +38,7 @@ #include "graphics/cursorman.h" namespace Kyra { -KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) { +KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngine_v2(system, flags) { _soundDigital = 0; _musicSoundChannel = -1; _menuAudioFile = "TITLE1.AUD"; @@ -87,10 +87,6 @@ KyraEngine_v3::~KyraEngine_v3() { delete [] _scenesList; } -Movie *KyraEngine_v3::createWSAMovie() { - return new WSAMovieV2(this); -} - int KyraEngine_v3::init() { KyraEngine::init(); @@ -294,14 +290,14 @@ void KyraEngine_v3::stopMusicTrack() { int KyraEngine_v3::musicUpdate(int forceRestart) { debugC(9, kDebugLevelMain, "KyraEngine::unkUpdate(%d)", forceRestart); - static uint32 timer = 0; + static uint32 mTimer = 0; static uint16 lock = 0; - if (ABS<int>(_system->getMillis() - timer) > (int)(0x0F * _tickLength)) { - timer = _system->getMillis(); + if (ABS<int>(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength)) { + mTimer = _system->getMillis(); } - if (_system->getMillis() < timer && !forceRestart) { + if (_system->getMillis() < mTimer && !forceRestart) { return 1; } @@ -315,7 +311,7 @@ int KyraEngine_v3::musicUpdate(int forceRestart) { } } lock = 0; - timer = _system->getMillis() + 0x0F * _tickLength; + mTimer = _system->getMillis() + 0x0F * _tickLength; } return 1; @@ -324,7 +320,7 @@ int KyraEngine_v3::musicUpdate(int forceRestart) { #pragma mark - void KyraEngine_v3::gui_initMainMenu() { - KyraEngine::gui_initMainMenu(); + KyraEngine_v2::gui_initMainMenu(); _mainMenuFrame = 29; _mainMenuFrameAdd = 1; } diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index eda382d89a..f9b81b5126 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -26,20 +26,17 @@ #ifndef KYRA_KYRA_V3_H #define KYRA_KYRA_V3_H -#include "kyra/kyra.h" +#include "kyra/kyra_v2.h" namespace Kyra { -// maybe subclass KyraEngine_v2 later -class WSAMovieV2; +class SoundDigital; -class KyraEngine_v3 : public KyraEngine { +class KyraEngine_v3 : public KyraEngine_v2 { public: KyraEngine_v3(OSystem *system, const GameFlags &flags); ~KyraEngine_v3(); - - Movie *createWSAMovie(); - + SoundDigital *soundDigital() { return _soundDigital; } int go(); diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index 8303028b27..0517c393a1 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -1,20 +1,28 @@ MODULE := engines/kyra MODULE_OBJS := \ - animator.o \ + animator_v1.o \ + animator_v2.o \ debugger.o \ detection.o \ - gui.o \ - items.o \ + gui_v1.o \ + gui_v2.o \ + items_v1.o \ + items_v2.o \ kyra.o \ kyra_v1.o \ kyra_v2.o \ kyra_v3.o \ resource.o \ - saveload.o \ + saveload_v1.o \ scene.o \ + scene_v1.o \ + scene_v2.o \ screen.o \ + screen_v1.o \ + screen_v2.o \ script_v1.o \ + script_v2.o \ script.o \ seqplayer.o \ sequences_v1.o \ @@ -23,10 +31,14 @@ MODULE_OBJS := \ sound_digital.o \ sound_towns.o \ sound.o \ + sound_v1.o \ sprites.o \ staticres.o \ text.o \ + text_v1.o \ timer.o \ + timer_v1.o \ + timer_v2.o \ vqa.o \ wsamovie.o diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 2425444be1..cb484b6183 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -42,11 +42,11 @@ namespace Kyra { namespace { -struct ResFilenameEqual : public Common::BinaryFunction<ResourceFile*, uint, bool> { +struct ResFilenameEqual : public Common::UnaryFunction<ResourceFile*, bool> { uint _filename; ResFilenameEqual(uint file) : _filename(file) {} - bool operator()(ResourceFile *f) { + bool operator()(const ResourceFile *f) { return f->filename() == _filename; } }; @@ -220,8 +220,11 @@ uint8 *Resource::fileData(const char *file, uint32 *size) const { bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &filehandle) { filehandle.close(); - if (filehandle.open(file)) + if (filehandle.open(file)) { + if (size) + *size = filehandle.size(); return true; + } uint fileHash = Common::hashit_lower(file); for (ResIterator start = _pakfiles.begin() ;start != _pakfiles.end(); ++start) { @@ -229,12 +232,14 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh continue; if ((*start)->getFileHandle(fileHash, filehandle)) { - - *size = (*start)->getFileSize(fileHash); + uint32 tSize = (*start)->getFileSize(fileHash); - if (!(*size)) + if (!tSize) continue; + if (size) + *size = tSize; + return true; } } diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 19855ed9c9..139a7fa72c 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -122,9 +122,8 @@ public: uint32 getFileSize(const char *file) const; uint8* fileData(const char *file, uint32 *size) const; - // it gives back a file handle (used for the speech player) - // it could be that the needed file is embedded in the returned - // handle + // gives back a file handle + // it is possible that the needed file is embedded in the returned handle bool getFileHandle(const char *file, uint32 *size, Common::File &filehandle); bool loadFileToBuf(const char *file, void *buf, uint32 maxSize); diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload_v1.cpp index 95693684a1..c2ceee1d3b 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload_v1.cpp @@ -28,13 +28,14 @@ #include "common/savefile.h" #include "common/system.h" -#include "kyra/kyra.h" -#include "kyra/animator.h" +#include "kyra/kyra_v1.h" +#include "kyra/animator_v1.h" #include "kyra/screen.h" #include "kyra/resource.h" #include "kyra/sound.h" +#include "kyra/timer.h" -#define CURRENT_VERSION 7 +#define CURRENT_VERSION 8 // TODO: our current savefiles still use the old // flag system to check the version, we should @@ -44,7 +45,7 @@ #define GF_FMTOWNS (1 << 2) namespace Kyra { -void KyraEngine::loadGame(const char *fileName) { +void KyraEngine_v1::loadGame(const char *fileName) { debugC(9, kDebugLevelMain, "loadGame('%s')", fileName); Common::InSaveFile *in; @@ -147,14 +148,7 @@ void KyraEngine::loadGame(const char *fileName) { _poisonDeathCounter = in->readByte(); _animator->_brandonDrawFrame = in->readUint16BE(); - for (int i = 0; i < 32; i++) { - _timers[i].active = in->readByte(); - _timers[i].countdown = in->readSint32BE(); - _timers[i].nextRun = in->readUint32BE(); - if (_timers[i].nextRun != 0) - _timers[i].nextRun += _system->getMillis(); - } - _timerNextRun = 0; + _timer->loadDataFromFile(in, version); memset(_flagsTable, 0, sizeof(_flagsTable)); uint32 flagsSize = in->readUint32BE(); @@ -206,7 +200,7 @@ void KyraEngine::loadGame(const char *fileName) { if (version >= 7) { _curSfxFile = in->readByte(); - // In the first version there this entry was introduced, + // In the first version when this entry was introduced, // it wasn't made sure that _curSfxFile was initialized // so if it's out of bounds we just set it to 0. if (_curSfxFile >= _soundFilesTownsCount || _curSfxFile < 0) @@ -266,7 +260,7 @@ void KyraEngine::loadGame(const char *fileName) { delete in; } -void KyraEngine::saveGame(const char *fileName, const char *saveName) { +void KyraEngine_v1::saveGame(const char *fileName, const char *saveName) { debugC(9, kDebugLevelMain, "saveGame('%s', '%s')", fileName, saveName); Common::OutSaveFile *out; if (_quitFlag) return; @@ -323,14 +317,7 @@ void KyraEngine::saveGame(const char *fileName, const char *saveName) { out->writeByte(_poisonDeathCounter); out->writeUint16BE(_animator->_brandonDrawFrame); - for (int i = 0; i < 32; i++) { - out->writeByte(_timers[i].active); - out->writeSint32BE(_timers[i].countdown); - if (_system->getMillis() >= _timers[i].nextRun) - out->writeUint32BE(0); - else - out->writeUint32BE(_timers[i].nextRun - _system->getMillis()); - } + _timer->saveDataToFile(out); out->writeUint32BE(sizeof(_flagsTable)); out->write(_flagsTable, sizeof(_flagsTable)); diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp index a92fd9ce7c..bf85ab1474 100644 --- a/engines/kyra/scene.cpp +++ b/engines/kyra/scene.cpp @@ -11,7 +11,7 @@ * 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 + * 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 @@ -24,1168 +24,10 @@ */ #include "kyra/kyra.h" -#include "kyra/seqplayer.h" #include "kyra/screen.h" -#include "kyra/resource.h" -#include "kyra/sound.h" -#include "kyra/sprites.h" -#include "kyra/wsamovie.h" -#include "kyra/animator.h" -#include "kyra/text.h" -#include "kyra/script.h" - -#include "common/system.h" -#include "common/savefile.h" namespace Kyra { -void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive); - int unkVar1 = 1; - _screen->hideMouse(); - _handleInput = false; - _abortWalkFlag = false; - _abortWalkFlag2 = false; - - if (_flags.platform == Common::kPlatformFMTowns) { - int newSfxFile = -1; - if (_currentCharacter->sceneId == 7 && sceneId == 24) - newSfxFile = 2; - else if (_currentCharacter->sceneId == 25 && sceneId == 109) - newSfxFile = 3; - else if (_currentCharacter->sceneId == 120 && sceneId == 37) - newSfxFile = 4; - else if (_currentCharacter->sceneId == 52 && sceneId == 199) - newSfxFile = 5; - else if (_currentCharacter->sceneId == 37 && sceneId == 120) - newSfxFile = 3; - else if (_currentCharacter->sceneId == 109 && sceneId == 25) - newSfxFile = 2; - else if (_currentCharacter->sceneId == 24 && sceneId == 7) - newSfxFile = 1; - - if (newSfxFile != -1) { - _curSfxFile = newSfxFile; - _sound->loadSoundFile(_curSfxFile); - } - } - - switch (_currentCharacter->sceneId) { - case 1: - if (sceneId == 0) { - moveCharacterToPos(0, 0, _currentCharacter->x1, 84); - unkVar1 = 0; - } - break; - - case 3: - if (sceneId == 2) { - moveCharacterToPos(0, 6, 155, _currentCharacter->y1); - unkVar1 = 0; - } - break; - - case 26: - if (sceneId == 27) { - moveCharacterToPos(0, 6, 155, _currentCharacter->y1); - unkVar1 = 0; - } - break; - - case 44: - if (sceneId == 45) { - moveCharacterToPos(0, 2, 192, _currentCharacter->y1); - unkVar1 = 0; - } - break; - - default: - break; - } - - if (unkVar1 && unk1) { - int xpos = _currentCharacter->x1; - int ypos = _currentCharacter->y1; - switch (facing) { - case 0: - ypos = _currentCharacter->y1 - 6; - break; - - case 2: - xpos = 336; - break; - - case 4: - ypos = 143; - break; - - case 6: - xpos = -16; - break; - - default: - break; - } - - moveCharacterToPos(0, facing, xpos, ypos); - } - - for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) - _movieObjects[i]->close(); - - if (!brandonAlive) { - _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptInterpreter->startScript(_scriptClick, 5); - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); - } - - memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4); - _currentCharacter->sceneId = sceneId; - - assert(sceneId < _roomTableSize); - assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize); - - Room *currentRoom = &_roomTable[sceneId]; - - setupSceneResource(sceneId); - - _currentRoom = sceneId; - - int tableId = _roomTable[sceneId].nameIndex; - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".DAT"); - _sprites->loadDat(fileNameBuffer, _sceneExits); - _sprites->setupSceneAnims(); - _scriptInterpreter->unloadScript(_scriptClickData); - loadSceneMsc(); - - _walkBlockNorth = currentRoom->northExit; - _walkBlockEast = currentRoom->eastExit; - _walkBlockSouth = currentRoom->southExit; - _walkBlockWest = currentRoom->westExit; - - if (_walkBlockNorth == 0xFFFF) - _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3); - if (_walkBlockEast == 0xFFFF) - _screen->blockOutRegion(312, 0, 8, 139); - if (_walkBlockSouth == 0xFFFF) - _screen->blockOutRegion(0, 135, 320, 8); - if (_walkBlockWest == 0xFFFF) - _screen->blockOutRegion(0, 0, 8, 139); - - if (!brandonAlive) - updatePlayerItemsForScene(); - - startSceneScript(brandonAlive); - setupSceneItems(); - - initSceneData(facing, unk2, brandonAlive); - - _loopFlag2 = 0; - _screen->showMouse(); - if (!brandonAlive) - seq_poisonDeathNow(0); - updateMousePointer(true); - _changedScene = true; -} - -void KyraEngine::transcendScenes(int roomIndex, int roomName) { - debugC(9, kDebugLevelMain, "KyraEngine::transcendScenes(%d, %d)", roomIndex, roomName); - assert(roomIndex < _roomTableSize); - - if (_flags.isTalkie) { - char file[32]; - assert(roomIndex < _roomTableSize); - int tableId = _roomTable[roomIndex].nameIndex; - assert(tableId < _roomFilenameTableSize); - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - _res->unloadPakFile(file); - } - - _roomTable[roomIndex].nameIndex = roomName; - _unkScreenVar2 = 1; - _unkScreenVar3 = 1; - _unkScreenVar1 = 0; - _brandonPosX = _currentCharacter->x1; - _brandonPosY = _currentCharacter->y1; - enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0); - _unkScreenVar1 = 1; - _unkScreenVar2 = 0; - _unkScreenVar3 = 0; -} - -void KyraEngine::setSceneFile(int roomIndex, int roomName) { - debugC(9, kDebugLevelMain, "KyraEngine::setSceneFile(%d, %d)", roomIndex, roomName); - assert(roomIndex < _roomTableSize); - _roomTable[roomIndex].nameIndex = roomName; -} - -void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) { - debugC(9, kDebugLevelMain, "KyraEngine::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); - Character *ch = &_characterList[character]; - ch->facing = facing; - _screen->hideMouse(); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - disableTimer(19); - disableTimer(14); - disableTimer(18); - uint32 nextFrame = 0; - - switch (facing) { - case 0: - while (ypos < ch->y1) { - nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 2: - while (ch->x1 < xpos) { - nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 4: - while (ypos > ch->y1) { - nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - case 6: - while (ch->x1 > xpos) { - nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis(); - setCharacterPositionWithUpdate(character); - delayUntil(nextFrame, true); - } - break; - - default: - break; - } - - enableTimer(19); - enableTimer(14); - enableTimer(18); - _screen->showMouse(); -} - -void KyraEngine::setCharacterPositionWithUpdate(int character) { - debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPositionWithUpdate(%d)", character); - setCharacterPosition(character, 0); - _sprites->updateSceneAnims(); - updateGameTimers(); - _animator->updateAllObjectShapes(); - updateTextFade(); - - if (_currentCharacter->sceneId == 210) - updateKyragemFading(); -} - -int KyraEngine::setCharacterPosition(int character, int *facingTable) { - debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPosition(%d, %p)", character, (const void *)facingTable); - - if (character == 0) { - _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing]; - _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing]; - setCharacterPositionHelper(0, facingTable); - return 1; - } else { - _characterList[character].x1 += _charXPosTable[_characterList[character].facing]; - _characterList[character].y1 += _charYPosTable[_characterList[character].facing]; - if (_characterList[character].sceneId == _currentCharacter->sceneId) - setCharacterPositionHelper(character, 0); - } - return 0; -} - -void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) { - debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable); - Character *ch = &_characterList[character]; - ++ch->currentAnimFrame; - int facing = ch->facing; - if (facingTable) { - if (*facingTable != *(facingTable - 1)) { - if (*(facingTable - 1) == *(facingTable + 1)) { - facing = getOppositeFacingDirection(*(facingTable - 1)); - *facingTable = *(facingTable - 1); - } - } - } - - static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - if (facing == 0) { - ++facingIsZero[character]; - } else { - bool resetTables = false; - if (facing != 7) { - if (facing - 1 != 0) { - if (facing != 4) { - if (facing == 3 || facing == 5) { - if (facingIsFour[character] > 2) - facing = 4; - resetTables = true; - } - } else { - ++facingIsFour[character]; - } - } else { - if (facingIsZero[character] > 2) - facing = 0; - resetTables = true; - } - } else { - if (facingIsZero[character] > 2) - facing = 0; - resetTables = true; - } - - if (resetTables) { - facingIsZero[character] = 0; - facingIsFour[character] = 0; - } - } - - static const uint16 maxAnimationFrame[] = { - 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, - 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, - 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, - 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000, - 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000, - 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000, - 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000 - }; - - if (facing == 0) { - if (maxAnimationFrame[36+character] > ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[36+character]; - if (maxAnimationFrame[30+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[36+character]; - } else if (facing == 4) { - if (maxAnimationFrame[18+character] > ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[18+character]; - if (maxAnimationFrame[12+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[18+character]; - } else { - if (maxAnimationFrame[18+character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[30+character]; - if (maxAnimationFrame[character] == ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[6+character]; - if (maxAnimationFrame[character] < ch->currentAnimFrame) - ch->currentAnimFrame = maxAnimationFrame[6+character]+2; - } - - if (character == 0 && (_brandonStatusBit & 0x10)) - ch->currentAnimFrame = 88; - - _animator->animRefreshNPC(character); -} - -int KyraEngine::getOppositeFacingDirection(int dir) { - debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir); - switch (dir) { - case 0: - return 2; - case 1: - return 1; - case 3: - return 7; - case 4: - return 6; - case 5: - return 5; - case 6: - return 4; - case 7: - return 3; - default: - break; - } - return 0; -} - -void KyraEngine::loadSceneMsc() { - assert(_currentCharacter->sceneId < _roomTableSize); - int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".MSC"); - _screen->fillRect(0, 0, 319, 199, 0, 5); - _screen->loadBitmap(fileNameBuffer, 3, 5, 0); -} - -void KyraEngine::startSceneScript(int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine::startSceneScript(%d)", brandonAlive); - assert(_currentCharacter->sceneId < _roomTableSize); - int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - char fileNameBuffer[32]; - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".CPS"); - _screen->clearPage(3); - // FIXME: check this hack for amiga version - _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); - _sprites->loadSceneShapes(); - _exitListPtr = 0; - - _scaleMode = 1; - for (int i = 0; i < 145; ++i) - _scaleTable[i] = 256; - - clearNoDropRects(); - _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - strcpy(fileNameBuffer, _roomFilenameTable[tableId]); - strcat(fileNameBuffer, ".EMC"); - _scriptInterpreter->unloadScript(_scriptClickData); - _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes); - _scriptInterpreter->startScript(_scriptClick, 0); - _scriptClick->regs[0] = _currentCharacter->sceneId; - _scriptClick->regs[7] = brandonAlive; - - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); -} - -void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive); - - int16 xpos2 = 0; - int setFacing = 1; - - int16 xpos = 0, ypos = 0; - - if (_brandonPosX == -1 && _brandonPosY == -1) { - switch (facing + 1) { - case 0: - xpos = ypos = -1; - break; - - case 1: case 2: case 8: - xpos = _sceneExits.southXPos; - ypos = _sceneExits.southYPos; - break; - - case 3: - xpos = _sceneExits.westXPos; - ypos = _sceneExits.westYPos; - break; - - case 4: case 5: case 6: - xpos = _sceneExits.northXPos; - ypos = _sceneExits.northYPos; - break; - - case 7: - xpos = _sceneExits.eastXPos; - ypos = _sceneExits.eastYPos; - break; - - default: - break; - } - - if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) - ypos = (_northExitHeight & 0xFF) + 4; - if (xpos >= 308) - xpos = 304; - if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) - ypos = (_northExitHeight >> 8) - 4; - if (xpos <= 12) - xpos = 16; - } - - if (_brandonPosX > -1) - xpos = _brandonPosX; - if (_brandonPosY > -1) - ypos = _brandonPosY; - - int16 ypos2 = 0; - if (_brandonPosX > -1 && _brandonPosY > -1) { - switch (_currentCharacter->sceneId) { - case 1: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 4; - xpos2 = 192; - ypos2 = 104; - setFacing = 0; - unk1 = 1; - break; - - case 3: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 204; - ypos2 = 94; - setFacing = 0; - unk1 = 1; - break; - - case 26: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 192; - ypos2 = 128; - setFacing = 0; - unk1 = 1; - break; - - case 44: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 6; - xpos2 = 156; - ypos2 = 96; - setFacing = 0; - unk1 = 1; - break; - - case 37: - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - facing = 2; - xpos2 = 148; - ypos2 = 114; - setFacing = 0; - unk1 = 1; - break; - - default: - break; - } - } - - _brandonPosX = _brandonPosY = -1; - - if (unk1 && setFacing) { - ypos2 = ypos; - xpos2 = xpos; - switch (facing) { - case 0: - ypos = 142; - break; - - case 2: - xpos = -16; - break; - - case 4: - ypos = (uint8)(_northExitHeight & 0xFF) - 4; - break; - - case 6: - xpos = 336; - break; - - default: - break; - } - } - - xpos2 = (int16)(xpos2 & 0xFFFC); - ypos2 = (int16)(ypos2 & 0xFFFE); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - _currentCharacter->facing = facing; - _currentCharacter->x1 = xpos; - _currentCharacter->x2 = xpos; - _currentCharacter->y1 = ypos; - _currentCharacter->y2 = ypos; - - initSceneObjectList(brandonAlive); - - if (unk1 && brandonAlive == 0) - moveCharacterToPos(0, facing, xpos2, ypos2); - - _scriptClick->regs[4] = _itemInHand; - _scriptClick->regs[7] = brandonAlive; - _scriptInterpreter->startScript(_scriptClick, 3); - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); -} - -void KyraEngine::initSceneObjectList(int brandonAlive) { - debugC(9, kDebugLevelMain, "KyraEngine::initSceneObjectList(%d)", brandonAlive); - for (int i = 0; i < 28; ++i) - _animator->actors()[i].active = 0; - - int startAnimFrame = 0; - - AnimObject *curAnimState = _animator->actors(); - curAnimState->active = 1; - curAnimState->drawY = _currentCharacter->y1; - curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame]; - curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame; - startAnimFrame = _currentCharacter->currentAnimFrame-7; - int xOffset = _defaultShapeTable[startAnimFrame].xOffset; - int yOffset = _defaultShapeTable[startAnimFrame].yOffset; - - if (_scaleMode) { - curAnimState->x1 = _currentCharacter->x1; - curAnimState->y1 = _currentCharacter->y1; - - _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1]; - _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; - - curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; - curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; - } else { - curAnimState->x1 = _currentCharacter->x1 + xOffset; - curAnimState->y1 = _currentCharacter->y1 + yOffset; - } - - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - _animator->clearQueue(); - _animator->addObjectToQueue(curAnimState); - - int listAdded = 0; - int addedObjects = 1; - - for (int i = 1; i < 5; ++i) { - Character *ch = &_characterList[i]; - curAnimState = &_animator->actors()[addedObjects]; - if (ch->sceneId != _currentCharacter->sceneId) { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - ++addedObjects; - continue; - } - - curAnimState->drawY = ch->y1; - curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame]; - curAnimState->animFrameNumber = ch->currentAnimFrame; - startAnimFrame = ch->currentAnimFrame-7; - xOffset = _defaultShapeTable[startAnimFrame].xOffset; - yOffset = _defaultShapeTable[startAnimFrame].yOffset; - if (_scaleMode) { - curAnimState->x1 = ch->x1; - curAnimState->y1 = ch->y1; - - _animator->_brandonScaleX = _scaleTable[ch->y1]; - _animator->_brandonScaleY = _scaleTable[ch->y1]; - - curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; - curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; - } else { - curAnimState->x1 = ch->x1 + xOffset; - curAnimState->y1 = ch->y1 + yOffset; - } - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - - if (ch->facing >= 1 && ch->facing <= 3) - curAnimState->flags |= 1; - else if (ch->facing >= 5 && ch->facing <= 7) - curAnimState->flags &= 0xFFFFFFFE; - - _animator->addObjectToQueue(curAnimState); - - ++addedObjects; - ++listAdded; - if (listAdded < 2) - i = 5; - } - - for (int i = 0; i < 11; ++i) { - curAnimState = &_animator->sprites()[i]; - - if (_sprites->_anims[i].play) { - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - } else { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - } - curAnimState->height = _sprites->_anims[i].height; - curAnimState->height2 = _sprites->_anims[i].height2; - curAnimState->width = _sprites->_anims[i].width + 1; - curAnimState->width2 = _sprites->_anims[i].width2; - curAnimState->drawY = _sprites->_anims[i].drawY; - curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x; - curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y; - curAnimState->background = _sprites->_anims[i].background; - curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite]; - - curAnimState->disable = _sprites->_anims[i].disable; - - if (_sprites->_anims[i].unk2) - curAnimState->flags = 0x800; - else - curAnimState->flags = 0; - - if (_sprites->_anims[i].flipX) - curAnimState->flags |= 0x1; - - _animator->addObjectToQueue(curAnimState); - } - - for (int i = 0; i < 12; ++i) { - curAnimState = &_animator->items()[i]; - Room *curRoom = &_roomTable[_currentCharacter->sceneId]; - byte curItem = curRoom->itemsTable[i]; - if (curItem != 0xFF) { - curAnimState->drawY = curRoom->itemsYPos[i]; - curAnimState->sceneAnimPtr = _shapes[216+curItem]; - curAnimState->animFrameNumber = (int16)0xFFFF; - curAnimState->y1 = curRoom->itemsYPos[i]; - curAnimState->x1 = curRoom->itemsXPos[i]; - - curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1; - curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]); - - curAnimState->x2 = curAnimState->x1; - curAnimState->y2 = curAnimState->y1; - - curAnimState->active = 1; - curAnimState->refreshFlag = 1; - curAnimState->bkgdChangeFlag = 1; - - _animator->addObjectToQueue(curAnimState); - } else { - curAnimState->active = 0; - curAnimState->refreshFlag = 0; - curAnimState->bkgdChangeFlag = 0; - } - } - - _animator->preserveAnyChangedBackgrounds(); - curAnimState = _animator->actors(); - curAnimState->bkgdChangeFlag = 1; - curAnimState->refreshFlag = 1; - for (int i = 1; i < 28; ++i) { - curAnimState = &_animator->objects()[i]; - if (curAnimState->active) { - curAnimState->bkgdChangeFlag = 1; - curAnimState->refreshFlag = 1; - } - } - _animator->restoreAllObjectBackgrounds(); - _animator->preserveAnyChangedBackgrounds(); - _animator->prepDrawAllObjects(); - initSceneScreen(brandonAlive); - _animator->copyChangedObjectsForward(0); -} - -void KyraEngine::initSceneScreen(int brandonAlive) { - if (_flags.platform == Common::kPlatformAmiga) { - if (_unkScreenVar1 && !queryGameFlag(0xF0)) { - memset(_screen->getPalette(2), 0, 32*3); - if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) - _screen->setScreenPalette(_screen->getPalette(2)); - } - - if (_unkScreenVar2 == 1) - _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); - else - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); - - if (_unkScreenVar1 && !queryGameFlag(0xA0)) { - if (_currentCharacter->sceneId == 45 && _paletteChanged) - memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); - - if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) - memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); - - _screen->setScreenPalette(_screen->getPalette(0)); - } - } else { - if (_unkScreenVar1 && !queryGameFlag(0xA0)) { - for (int i = 0; i < 60; ++i) { - uint16 col = _screen->getPalette(0)[684+i]; - col += _screen->getPalette(1)[684+i] << 1; - col >>= 2; - _screen->getPalette(0)[684+i] = col; - } - _screen->setScreenPalette(_screen->getPalette(0)); - } - - if (_unkScreenVar2 == 1) - _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); - else - _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); - - if (_unkScreenVar1 && _paletteChanged) { - if (!queryGameFlag(0xA0)) { - memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); - _screen->setScreenPalette(_screen->getPalette(0)); - } else { - memset(_screen->getPalette(0), 0, 768); - } - } - } - - // really call this here? - _screen->updateScreen(); - - if (!_scriptInterpreter->startScript(_scriptClick, 2)) - error("Could not start script function 2 of scene script"); - - _scriptClick->regs[7] = brandonAlive; - - while (_scriptInterpreter->validScript(_scriptClick)) - _scriptInterpreter->runScript(_scriptClick); - - setTextFadeTimerCountdown(-1); - if (_currentCharacter->sceneId == 210) { - if (_itemInHand != -1) - magicOutMouseItem(2, -1); - - _screen->hideMouse(); - for (int i = 0; i < 10; ++i) { - if (_currentCharacter->inventoryItems[i] != 0xFF) - magicOutMouseItem(2, i); - } - _screen->showMouse(); - } -} - -int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) { - debugC(9, kDebugLevelMain, "KyraEngine::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset); - if (queryGameFlag(0xEF)) - unk1 = 0; - - int sceneId = _currentCharacter->sceneId; - _pathfinderFlag = 0; - - if (xpos < 12) { - if (_roomTable[sceneId].westExit != 0xFFFF) { - xpos = 12; - ypos = _sceneExits.westYPos; - _pathfinderFlag = 7; - } - } else if (xpos >= 308) { - if (_roomTable[sceneId].eastExit != 0xFFFF) { - xpos = 307; - ypos = _sceneExits.eastYPos; - _pathfinderFlag = 13; - } - } - - if (ypos <= (_northExitHeight&0xFF)+2) { - if (_roomTable[sceneId].northExit != 0xFFFF) { - xpos = _sceneExits.northXPos; - ypos = _northExitHeight & 0xFF; - _pathfinderFlag = 14; - } - } else if (ypos >= 136) { - if (_roomTable[sceneId].southExit != 0xFFFF) { - xpos = _sceneExits.southXPos; - ypos = 136; - _pathfinderFlag = 11; - } - } - - int temp = xpos - _currentCharacter->x1; - if (ABS(temp) < 4) { - temp = ypos - _currentCharacter->y1; - if (ABS(temp) < 2) - return 0; - } - - int x = (int16)(_currentCharacter->x1 & 0xFFFC); - int y = (int16)(_currentCharacter->y1 & 0xFFFE); - xpos = (int16)(xpos & 0xFFFC); - ypos = (int16)(ypos & 0xFFFE); - - int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150); - _pathfinderFlag = 0; - - if (ret >= _lastFindWayRet) - _lastFindWayRet = ret; - - if (ret == 0x7D00 || ret == 0) - return 0; - - return processSceneChange(_movFacingTable, unk1, frameReset); -} - -int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) { - debugC(9, kDebugLevelMain, "KyraEngine::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset); - if (queryGameFlag(0xEF)) - unk1 = 0; - - int *tableStart = table; - _sceneChangeState = 0; - _loopFlag2 = 0; - bool running = true; - int returnValue = 0; - uint32 nextFrame = 0; - _abortWalkFlag = false; - _mousePressFlag = false; - - while (running) { - if (_abortWalkFlag) { - *table = 8; - _currentCharacter->currentAnimFrame = 7; - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - processInput(); - return 0; - } - bool forceContinue = false; - switch (*table) { - case 0: case 1: case 2: - case 3: case 4: case 5: - case 6: case 7: - _currentCharacter->facing = getOppositeFacingDirection(*table); - break; - - case 8: - forceContinue = true; - running = false; - break; - - default: - ++table; - forceContinue = true; - break; - } - - returnValue = changeScene(_currentCharacter->facing); - if (returnValue) { - running = false; - _abortWalkFlag = false; - } - - if (unk1) { - if (_mousePressFlag) { - running = false; - _sceneChangeState = 1; - } - } - - if (forceContinue || !running) - continue; - - int temp = 0; - if (table == tableStart || table[1] == 8) - temp = setCharacterPosition(0, 0); - else - temp = setCharacterPosition(0, table); - - if (temp) - ++table; - - nextFrame = getTimerDelay(5) * _tickLength + _system->getMillis(); - while (_system->getMillis() < nextFrame) { - updateGameTimers(); - - if (_currentCharacter->sceneId == 210) { - updateKyragemFading(); - if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) { - *table = 8; - running = false; - break; - } - } - - if ((nextFrame - _system->getMillis()) >= 10) - delay(10, true); - } - } - - if (frameReset && !(_brandonStatusBit & 2)) - _currentCharacter->currentAnimFrame = 7; - - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - return returnValue; -} - -int KyraEngine::changeScene(int facing) { - debugC(9, kDebugLevelMain, "KyraEngine::changeScene(%d)", facing); - if (queryGameFlag(0xEF)) { - if (_currentCharacter->sceneId == 5) - return 0; - } - - int xpos = _charXPosTable[facing] + _currentCharacter->x1; - int ypos = _charYPosTable[facing] + _currentCharacter->y1; - - if (xpos >= 12 && xpos <= 308) { - if (!lineIsPassable(xpos, ypos)) - return false; - } - - if (_exitListPtr) { - int16 *ptr = _exitListPtr; - // this loop should be only entered one time, seems to be some hack in the original - while (true) { - if (*ptr == -1) - break; - - if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) { - ptr += 10; - break; - } - - _brandonPosX = ptr[6]; - _brandonPosY = ptr[7]; - uint16 sceneId = ptr[5]; - facing = ptr[4]; - int unk1 = ptr[8]; - int unk2 = ptr[9]; - - if (sceneId == 0xFFFF) { - switch (facing) { - case 0: - sceneId = _roomTable[_currentCharacter->sceneId].northExit; - break; - - case 2: - sceneId = _roomTable[_currentCharacter->sceneId].eastExit; - break; - - case 4: - sceneId = _roomTable[_currentCharacter->sceneId].southExit; - break; - - case 6: - sceneId = _roomTable[_currentCharacter->sceneId].westExit; - break; - - default: - break; - } - } - - _currentCharacter->facing = facing; - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - enterNewScene(sceneId, facing, unk1, unk2, 0); - resetGameFlag(0xEE); - return 1; - } - } - - int returnValue = 0; - facing = 0; - - if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) { - facing = 0; - returnValue = 1; - } - - if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) { - facing = 2; - returnValue = 1; - } - - if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) { - facing = 4; - returnValue = 1; - } - - if (xpos <= 12 || _currentCharacter->y1 <= 12) { - facing = 6; - returnValue = 1; - } - - if (!returnValue) - return 0; - - uint16 sceneId = 0xFFFF; - switch (facing) { - case 0: - sceneId = _roomTable[_currentCharacter->sceneId].northExit; - break; - - case 2: - sceneId = _roomTable[_currentCharacter->sceneId].eastExit; - break; - - case 4: - sceneId = _roomTable[_currentCharacter->sceneId].southExit; - break; - - default: - sceneId = _roomTable[_currentCharacter->sceneId].westExit; - break; - } - - if (sceneId == 0xFFFF) - return 0; - - enterNewScene(sceneId, facing, 1, 1, 0); - return returnValue; -} - -void KyraEngine::setCharactersInDefaultScene() { - static const uint32 defaultSceneTable[][4] = { - { 0xFFFF, 0x0004, 0x0003, 0xFFFF }, - { 0xFFFF, 0x0022, 0xFFFF, 0x0000 }, - { 0xFFFF, 0x001D, 0x0021, 0xFFFF }, - { 0xFFFF, 0x0000, 0x0000, 0xFFFF } - }; - - for (int i = 1; i < 5; ++i) { - Character *cur = &_characterList[i]; - //cur->field_20 = 0; - - const uint32 *curTable = defaultSceneTable[i-1]; - cur->sceneId = curTable[0]; - - if (cur->sceneId == _currentCharacter->sceneId) - //++cur->field_20; - cur->sceneId = curTable[1/*cur->field_20*/]; - - //cur->field_23 = curTable[cur->field_20+1]; - } -} - -void KyraEngine::setCharactersPositions(int character) { - static uint16 initXPosTable[] = { - 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, - 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042 - }; - static uint8 initYPosTable[] = { - 0x00, 0xA2, 0x00, 0x42, 0x00, - 0x67, 0x67, 0x60, 0x5A, 0x71, - 0x76 - }; - - assert(character < ARRAYSIZE(initXPosTable)); - Character *edit = &_characterList[character]; - edit->x1 = edit->x2 = initXPosTable[character]; - edit->y1 = edit->y2 = initYPosTable[character]; -} - -#pragma mark - -#pragma mark - Pathfinder -#pragma mark - - int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { debugC(9, kDebugLevelMain, "KyraEngine::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); x &= 0xFFFC; toX &= 0xFFFC; @@ -1199,8 +41,8 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move int curX = x; int curY = y; - int lastUsedEntry = 0; int tempValue = 0; + int lastUsedEntry = 0; int *pathTable1 = new int[0x7D0]; int *pathTable2 = new int[0x7D0]; assert(pathTable1 && pathTable2); @@ -1208,14 +50,14 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move while (true) { int newFacing = getFacingFromPointToPoint(x, y, toX, toY); changePosTowardsFacing(curX, curY, newFacing); - + if (curX == toX && curY == toY) { if (!lineIsPassable(curX, curY)) break; moveTable[lastUsedEntry++] = newFacing; break; } - + if (lineIsPassable(curX, curY)) { if (lastUsedEntry == moveTableSize) { delete [] pathTable1; @@ -1233,7 +75,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move y = curY; continue; } - + int temp = 0; while (true) { newFacing = getFacingFromPointToPoint(curX, curY, toX, toY); @@ -1249,7 +91,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move if (curX != toX || curY != toY) continue; } - + if (curX == toX && curY == toY) { if (!lineIsPassable(curX, curY)) { tempValue = 0; @@ -1298,7 +140,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move delete [] pathTable1; delete [] pathTable2; moveTable[lastUsedEntry] = 8; - return getMoveTableSize(moveTable); + return lastUsedEntry; } int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) { @@ -1312,10 +154,10 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 }; // debug specific - //++unkTable[start]; - //while (_screen->getPalette(0)[unkTable[start]] != 0x0F) { - // ++unkTable[start]; - //} + /*++unkTable[start]; + while (screen()->getPalette(0)[unkTable[start]] != 0x0F) { + ++unkTable[start]; + }*/ int xpos1 = x, xpos2 = x; int ypos1 = y, ypos2 = y; @@ -1338,11 +180,11 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int break; } // debug drawing - //if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) { - // _screen->setPagePixel(0, xpos1, ypos1, unkTable[start]); - // _screen->updateScreen(); - // waitTicks(5); - //} + /*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) { + screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]); + screen()->updateScreen(); + //waitTicks(5); + }*/ if (newFacing & 1) { int temp = xpos1 + addPosTableX[newFacing + start * 8]; if (toX == temp) { @@ -1363,7 +205,7 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int if (xpos1 == xpos2 && ypos1 == ypos2) break; - + newFacing = facingTable3[start*8 + newFacing]; } @@ -1394,7 +236,7 @@ int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) { int temp = ydiff; ydiff = xdiff; xdiff = temp; - + facingEntry <<= 1; } else { facingEntry <<= 1; @@ -1413,71 +255,36 @@ int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) { return facingTable[facingEntry]; } + +int KyraEngine::getOppositeFacingDirection(int dir) { + debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir); + switch (dir) { + case 0: + return 2; + case 1: + return 1; + case 3: + return 7; + case 4: + return 6; + case 5: + return 5; + case 6: + return 4; + case 7: + return 3; + default: + break; + } + return 0; +} + void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) { debugC(9, kDebugLevelMain, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing); x += _addXPosTable[facing]; y += _addYPosTable[facing]; } -bool KyraEngine::lineIsPassable(int x, int y) { - debugC(9, kDebugLevelMain, "KyraEngine::lineIsPassable(%d, %d)", x, y); - if (queryGameFlag(0xEF)) { - if (_currentCharacter->sceneId == 5) - return true; - } - - if (_pathfinderFlag & 2) { - if (x >= 312) - return false; - } - - if (_pathfinderFlag & 4) { - if (y >= 136) - return false; - } - - if (_pathfinderFlag & 8) { - if (x < 8) - return false; - } - - if (_pathfinderFlag2) { - if (x <= 8 || x >= 312) - return true; - if (y < (_northExitHeight & 0xFF) || y > 135) - return true; - } - - if (y > 137) - return false; - - if (y < 0) - y = 0; - - int ypos = 8; - if (_scaleMode) { - ypos = (_scaleTable[y] >> 5) + 1; - if (8 < ypos) - ypos = 8; - } - - x -= (ypos >> 1); - - int xpos = x; - int xtemp = xpos + ypos - 1; - if (x < 0) - xpos = 0; - - if (xtemp > 319) - xtemp = 319; - - for (; xpos < xtemp; ++xpos) { - if (!_screen->getShapeFlag1(xpos, y)) - return false; - } - return true; -} - int KyraEngine::getMoveTableSize(int *moveTable) { debugC(9, kDebugLevelMain, "KyraEngine::getMoveTableSize(%p)", (const void *)moveTable); int retValue = 0; @@ -1573,52 +380,4 @@ int KyraEngine::getMoveTableSize(int *moveTable) { return retValue; } -void KyraEngine::setupSceneResource(int sceneId) { - debugC(9, kDebugLevelMain, "KyraEngine::setupSceneResource(%d)", sceneId); - if (!_flags.isTalkie) - return; - - if (_currentRoom != 0xFFFF) { - assert(_currentRoom < _roomTableSize); - int tableId = _roomTable[_currentRoom].nameIndex; - assert(tableId < _roomFilenameTableSize); - - // unload our old room - char file[64]; - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - _res->unloadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".PAK"); - _res->unloadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".APK"); - _res->unloadPakFile(file); - } - - assert(sceneId < _roomTableSize); - int tableId = _roomTable[sceneId].nameIndex; - assert(tableId < _roomFilenameTableSize); - - // load our new room - char file[64]; - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".VRM"); - if (Common::File::exists(file)) - _res->loadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".PAK"); - if (Common::File::exists(file)) - _res->loadPakFile(file); - - strcpy(file, _roomFilenameTable[tableId]); - strcat(file, ".APK"); - if (Common::File::exists(file)) - _res->loadPakFile(file); -} - } // end of namespace Kyra - diff --git a/engines/kyra/scene_v1.cpp b/engines/kyra/scene_v1.cpp new file mode 100644 index 0000000000..3754d5e2ab --- /dev/null +++ b/engines/kyra/scene_v1.cpp @@ -0,0 +1,1282 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v1.h" +#include "kyra/seqplayer.h" +#include "kyra/screen.h" +#include "kyra/resource.h" +#include "kyra/sound.h" +#include "kyra/sprites.h" +#include "kyra/wsamovie.h" +#include "kyra/animator_v1.h" +#include "kyra/text.h" +#include "kyra/script.h" +#include "kyra/timer.h" + +#include "common/system.h" +#include "common/savefile.h" + +namespace Kyra { + +void KyraEngine_v1::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive); + int unkVar1 = 1; + _screen->hideMouse(); + _handleInput = false; + _abortWalkFlag = false; + _abortWalkFlag2 = false; + + if (_flags.platform == Common::kPlatformFMTowns) { + int newSfxFile = -1; + if (_currentCharacter->sceneId == 7 && sceneId == 24) + newSfxFile = 2; + else if (_currentCharacter->sceneId == 25 && sceneId == 109) + newSfxFile = 3; + else if (_currentCharacter->sceneId == 120 && sceneId == 37) + newSfxFile = 4; + else if (_currentCharacter->sceneId == 52 && sceneId == 199) + newSfxFile = 5; + else if (_currentCharacter->sceneId == 37 && sceneId == 120) + newSfxFile = 3; + else if (_currentCharacter->sceneId == 109 && sceneId == 25) + newSfxFile = 2; + else if (_currentCharacter->sceneId == 24 && sceneId == 7) + newSfxFile = 1; + + if (newSfxFile != -1) { + _curSfxFile = newSfxFile; + _sound->loadSoundFile(_curSfxFile); + } + } + + switch (_currentCharacter->sceneId) { + case 1: + if (sceneId == 0) { + moveCharacterToPos(0, 0, _currentCharacter->x1, 84); + unkVar1 = 0; + } + break; + + case 3: + if (sceneId == 2) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 26: + if (sceneId == 27) { + moveCharacterToPos(0, 6, 155, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + case 44: + if (sceneId == 45) { + moveCharacterToPos(0, 2, 192, _currentCharacter->y1); + unkVar1 = 0; + } + break; + + default: + break; + } + + if (unkVar1 && unk1) { + int xpos = _currentCharacter->x1; + int ypos = _currentCharacter->y1; + switch (facing) { + case 0: + ypos = _currentCharacter->y1 - 6; + break; + + case 2: + xpos = 336; + break; + + case 4: + ypos = 143; + break; + + case 6: + xpos = -16; + break; + + default: + break; + } + + moveCharacterToPos(0, facing, xpos, ypos); + } + + for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) + _movieObjects[i]->close(); + + if (!brandonAlive) { + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + _scriptInterpreter->startScript(_scriptClick, 5); + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); + } + + memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4); + _currentCharacter->sceneId = sceneId; + + assert(sceneId < _roomTableSize); + assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize); + + Room *currentRoom = &_roomTable[sceneId]; + + setupSceneResource(sceneId); + + _currentRoom = sceneId; + + int tableId = _roomTable[sceneId].nameIndex; + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".DAT"); + _sprites->loadDat(fileNameBuffer, _sceneExits); + _sprites->setupSceneAnims(); + _scriptInterpreter->unloadScript(_scriptClickData); + loadSceneMsc(); + + _walkBlockNorth = currentRoom->northExit; + _walkBlockEast = currentRoom->eastExit; + _walkBlockSouth = currentRoom->southExit; + _walkBlockWest = currentRoom->westExit; + + if (_walkBlockNorth == 0xFFFF) + _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3); + if (_walkBlockEast == 0xFFFF) + _screen->blockOutRegion(312, 0, 8, 139); + if (_walkBlockSouth == 0xFFFF) + _screen->blockOutRegion(0, 135, 320, 8); + if (_walkBlockWest == 0xFFFF) + _screen->blockOutRegion(0, 0, 8, 139); + + if (!brandonAlive) + updatePlayerItemsForScene(); + + startSceneScript(brandonAlive); + setupSceneItems(); + + initSceneData(facing, unk2, brandonAlive); + + _loopFlag2 = 0; + _screen->showMouse(); + if (!brandonAlive) + seq_poisonDeathNow(0); + updateMousePointer(true); + _changedScene = true; +} + +void KyraEngine_v1::transcendScenes(int roomIndex, int roomName) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::transcendScenes(%d, %d)", roomIndex, roomName); + assert(roomIndex < _roomTableSize); + + if (_flags.isTalkie) { + char file[32]; + assert(roomIndex < _roomTableSize); + int tableId = _roomTable[roomIndex].nameIndex; + assert(tableId < _roomFilenameTableSize); + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + _res->unloadPakFile(file); + } + + _roomTable[roomIndex].nameIndex = roomName; + _unkScreenVar2 = 1; + _unkScreenVar3 = 1; + _unkScreenVar1 = 0; + _brandonPosX = _currentCharacter->x1; + _brandonPosY = _currentCharacter->y1; + enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0); + _unkScreenVar1 = 1; + _unkScreenVar2 = 0; + _unkScreenVar3 = 0; +} + +void KyraEngine_v1::setSceneFile(int roomIndex, int roomName) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setSceneFile(%d, %d)", roomIndex, roomName); + assert(roomIndex < _roomTableSize); + _roomTable[roomIndex].nameIndex = roomName; +} + +void KyraEngine_v1::moveCharacterToPos(int character, int facing, int xpos, int ypos) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); + Character *ch = &_characterList[character]; + ch->facing = facing; + _screen->hideMouse(); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + _timer->disable(19); + _timer->disable(14); + _timer->disable(18); + uint32 nextFrame = 0; + + switch (facing) { + case 0: + while (ypos < ch->y1) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 2: + while (ch->x1 < xpos) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 4: + while (ypos > ch->y1) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + case 6: + while (ch->x1 > xpos) { + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); + setCharacterPositionWithUpdate(character); + delayUntil(nextFrame, true); + } + break; + + default: + break; + } + + _timer->enable(19); + _timer->enable(14); + _timer->enable(18); + _screen->showMouse(); +} + +void KyraEngine_v1::setCharacterPositionWithUpdate(int character) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionWithUpdate(%d)", character); + setCharacterPosition(character, 0); + _sprites->updateSceneAnims(); + _timer->update(); + _animator->updateAllObjectShapes(); + updateTextFade(); + + if (_currentCharacter->sceneId == 210) + updateKyragemFading(); +} + +int KyraEngine_v1::setCharacterPosition(int character, int *facingTable) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPosition(%d, %p)", character, (const void *)facingTable); + + if (character == 0) { + _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing]; + _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing]; + setCharacterPositionHelper(0, facingTable); + return 1; + } else { + _characterList[character].x1 += _charXPosTable[_characterList[character].facing]; + _characterList[character].y1 += _charYPosTable[_characterList[character].facing]; + if (_characterList[character].sceneId == _currentCharacter->sceneId) + setCharacterPositionHelper(character, 0); + } + return 0; +} + +void KyraEngine_v1::setCharacterPositionHelper(int character, int *facingTable) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable); + Character *ch = &_characterList[character]; + ++ch->currentAnimFrame; + int facing = ch->facing; + if (facingTable) { + if (*facingTable != *(facingTable - 1)) { + if (*(facingTable - 1) == *(facingTable + 1)) { + facing = getOppositeFacingDirection(*(facingTable - 1)); + *facingTable = *(facingTable - 1); + } + } + } + + static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + if (facing == 0) { + ++facingIsZero[character]; + } else { + bool resetTables = false; + if (facing != 7) { + if (facing - 1 != 0) { + if (facing != 4) { + if (facing == 3 || facing == 5) { + if (facingIsFour[character] > 2) + facing = 4; + resetTables = true; + } + } else { + ++facingIsFour[character]; + } + } else { + if (facingIsZero[character] > 2) + facing = 0; + resetTables = true; + } + } else { + if (facingIsZero[character] > 2) + facing = 0; + resetTables = true; + } + + if (resetTables) { + facingIsZero[character] = 0; + facingIsFour[character] = 0; + } + } + + static const uint16 maxAnimationFrame[] = { + 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000, + 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000, + 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000, + 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000, + 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000, + 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000, + 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000 + }; + + if (facing == 0) { + if (maxAnimationFrame[36+character] > ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[36+character]; + if (maxAnimationFrame[30+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[36+character]; + } else if (facing == 4) { + if (maxAnimationFrame[18+character] > ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[18+character]; + if (maxAnimationFrame[12+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[18+character]; + } else { + if (maxAnimationFrame[18+character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[30+character]; + if (maxAnimationFrame[character] == ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[6+character]; + if (maxAnimationFrame[character] < ch->currentAnimFrame) + ch->currentAnimFrame = maxAnimationFrame[6+character]+2; + } + + if (character == 0 && (_brandonStatusBit & 0x10)) + ch->currentAnimFrame = 88; + + _animator->animRefreshNPC(character); +} + +void KyraEngine_v1::loadSceneMsc() { + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".MSC"); + _screen->fillRect(0, 0, 319, 199, 0, 5); + _screen->loadBitmap(fileNameBuffer, 3, 5, 0); +} + +void KyraEngine_v1::startSceneScript(int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::startSceneScript(%d)", brandonAlive); + assert(_currentCharacter->sceneId < _roomTableSize); + int tableId = _roomTable[_currentCharacter->sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + char fileNameBuffer[32]; + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".CPS"); + _screen->clearPage(3); + // FIXME: check this hack for amiga version + _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0)); + _sprites->loadSceneShapes(); + _exitListPtr = 0; + + _scaleMode = 1; + for (int i = 0; i < 145; ++i) + _scaleTable[i] = 256; + + clearNoDropRects(); + _scriptInterpreter->initScript(_scriptClick, _scriptClickData); + strcpy(fileNameBuffer, _roomFilenameTable[tableId]); + strcat(fileNameBuffer, ".EMC"); + _scriptInterpreter->unloadScript(_scriptClickData); + _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes); + _scriptInterpreter->startScript(_scriptClick, 0); + _scriptClick->regs[0] = _currentCharacter->sceneId; + _scriptClick->regs[7] = brandonAlive; + + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); +} + +void KyraEngine_v1::initSceneData(int facing, int unk1, int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive); + + int16 xpos2 = 0; + int setFacing = 1; + + int16 xpos = 0, ypos = 0; + + if (_brandonPosX == -1 && _brandonPosY == -1) { + switch (facing + 1) { + case 0: + xpos = ypos = -1; + break; + + case 1: case 2: case 8: + xpos = _sceneExits.southXPos; + ypos = _sceneExits.southYPos; + break; + + case 3: + xpos = _sceneExits.westXPos; + ypos = _sceneExits.westYPos; + break; + + case 4: case 5: case 6: + xpos = _sceneExits.northXPos; + ypos = _sceneExits.northYPos; + break; + + case 7: + xpos = _sceneExits.eastXPos; + ypos = _sceneExits.eastYPos; + break; + + default: + break; + } + + if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos) + ypos = (_northExitHeight & 0xFF) + 4; + if (xpos >= 308) + xpos = 304; + if ((uint8)(_northExitHeight >> 8) - 2 <= ypos) + ypos = (_northExitHeight >> 8) - 4; + if (xpos <= 12) + xpos = 16; + } + + if (_brandonPosX > -1) + xpos = _brandonPosX; + if (_brandonPosY > -1) + ypos = _brandonPosY; + + int16 ypos2 = 0; + if (_brandonPosX > -1 && _brandonPosY > -1) { + switch (_currentCharacter->sceneId) { + case 1: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 4; + xpos2 = 192; + ypos2 = 104; + setFacing = 0; + unk1 = 1; + break; + + case 3: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 204; + ypos2 = 94; + setFacing = 0; + unk1 = 1; + break; + + case 26: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 192; + ypos2 = 128; + setFacing = 0; + unk1 = 1; + break; + + case 44: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 6; + xpos2 = 156; + ypos2 = 96; + setFacing = 0; + unk1 = 1; + break; + + case 37: + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + facing = 2; + xpos2 = 148; + ypos2 = 114; + setFacing = 0; + unk1 = 1; + break; + + default: + break; + } + } + + _brandonPosX = _brandonPosY = -1; + + if (unk1 && setFacing) { + ypos2 = ypos; + xpos2 = xpos; + switch (facing) { + case 0: + ypos = 142; + break; + + case 2: + xpos = -16; + break; + + case 4: + ypos = (uint8)(_northExitHeight & 0xFF) - 4; + break; + + case 6: + xpos = 336; + break; + + default: + break; + } + } + + xpos2 = (int16)(xpos2 & 0xFFFC); + ypos2 = (int16)(ypos2 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + _currentCharacter->facing = facing; + _currentCharacter->x1 = xpos; + _currentCharacter->x2 = xpos; + _currentCharacter->y1 = ypos; + _currentCharacter->y2 = ypos; + + initSceneObjectList(brandonAlive); + + if (unk1 && brandonAlive == 0) + moveCharacterToPos(0, facing, xpos2, ypos2); + + _scriptClick->regs[4] = _itemInHand; + _scriptClick->regs[7] = brandonAlive; + _scriptInterpreter->startScript(_scriptClick, 3); + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); +} + +void KyraEngine_v1::initSceneObjectList(int brandonAlive) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneObjectList(%d)", brandonAlive); + for (int i = 0; i < 28; ++i) + _animator->actors()[i].active = 0; + + int startAnimFrame = 0; + + AnimObject *curAnimState = _animator->actors(); + curAnimState->active = 1; + curAnimState->drawY = _currentCharacter->y1; + curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame]; + curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame; + startAnimFrame = _currentCharacter->currentAnimFrame-7; + int xOffset = _defaultShapeTable[startAnimFrame].xOffset; + int yOffset = _defaultShapeTable[startAnimFrame].yOffset; + + if (_scaleMode) { + curAnimState->x1 = _currentCharacter->x1; + curAnimState->y1 = _currentCharacter->y1; + + _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1]; + _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1]; + + curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; + curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; + } else { + curAnimState->x1 = _currentCharacter->x1 + xOffset; + curAnimState->y1 = _currentCharacter->y1 + yOffset; + } + + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + _animator->clearQueue(); + _animator->addObjectToQueue(curAnimState); + + int listAdded = 0; + int addedObjects = 1; + + for (int i = 1; i < 5; ++i) { + Character *ch = &_characterList[i]; + curAnimState = &_animator->actors()[addedObjects]; + if (ch->sceneId != _currentCharacter->sceneId) { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + ++addedObjects; + continue; + } + + curAnimState->drawY = ch->y1; + curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame]; + curAnimState->animFrameNumber = ch->currentAnimFrame; + startAnimFrame = ch->currentAnimFrame-7; + xOffset = _defaultShapeTable[startAnimFrame].xOffset; + yOffset = _defaultShapeTable[startAnimFrame].yOffset; + if (_scaleMode) { + curAnimState->x1 = ch->x1; + curAnimState->y1 = ch->y1; + + _animator->_brandonScaleX = _scaleTable[ch->y1]; + _animator->_brandonScaleY = _scaleTable[ch->y1]; + + curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8; + curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8; + } else { + curAnimState->x1 = ch->x1 + xOffset; + curAnimState->y1 = ch->y1 + yOffset; + } + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + + if (ch->facing >= 1 && ch->facing <= 3) + curAnimState->flags |= 1; + else if (ch->facing >= 5 && ch->facing <= 7) + curAnimState->flags &= 0xFFFFFFFE; + + _animator->addObjectToQueue(curAnimState); + + ++addedObjects; + ++listAdded; + if (listAdded < 2) + i = 5; + } + + for (int i = 0; i < 11; ++i) { + curAnimState = &_animator->sprites()[i]; + + if (_sprites->_anims[i].play) { + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + } else { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + } + curAnimState->height = _sprites->_anims[i].height; + curAnimState->height2 = _sprites->_anims[i].height2; + curAnimState->width = _sprites->_anims[i].width + 1; + curAnimState->width2 = _sprites->_anims[i].width2; + curAnimState->drawY = _sprites->_anims[i].drawY; + curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x; + curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y; + curAnimState->background = _sprites->_anims[i].background; + curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite]; + + curAnimState->disable = _sprites->_anims[i].disable; + + if (_sprites->_anims[i].unk2) + curAnimState->flags = 0x800; + else + curAnimState->flags = 0; + + if (_sprites->_anims[i].flipX) + curAnimState->flags |= 0x1; + + _animator->addObjectToQueue(curAnimState); + } + + for (int i = 0; i < 12; ++i) { + curAnimState = &_animator->items()[i]; + Room *curRoom = &_roomTable[_currentCharacter->sceneId]; + byte curItem = curRoom->itemsTable[i]; + if (curItem != 0xFF) { + curAnimState->drawY = curRoom->itemsYPos[i]; + curAnimState->sceneAnimPtr = _shapes[216+curItem]; + curAnimState->animFrameNumber = (int16)0xFFFF; + curAnimState->y1 = curRoom->itemsYPos[i]; + curAnimState->x1 = curRoom->itemsXPos[i]; + + curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1; + curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]); + + curAnimState->x2 = curAnimState->x1; + curAnimState->y2 = curAnimState->y1; + + curAnimState->active = 1; + curAnimState->refreshFlag = 1; + curAnimState->bkgdChangeFlag = 1; + + _animator->addObjectToQueue(curAnimState); + } else { + curAnimState->active = 0; + curAnimState->refreshFlag = 0; + curAnimState->bkgdChangeFlag = 0; + } + } + + _animator->preserveAnyChangedBackgrounds(); + curAnimState = _animator->actors(); + curAnimState->bkgdChangeFlag = 1; + curAnimState->refreshFlag = 1; + for (int i = 1; i < 28; ++i) { + curAnimState = &_animator->objects()[i]; + if (curAnimState->active) { + curAnimState->bkgdChangeFlag = 1; + curAnimState->refreshFlag = 1; + } + } + _animator->restoreAllObjectBackgrounds(); + _animator->preserveAnyChangedBackgrounds(); + _animator->prepDrawAllObjects(); + initSceneScreen(brandonAlive); + _animator->copyChangedObjectsForward(0); +} + +void KyraEngine_v1::initSceneScreen(int brandonAlive) { + if (_flags.platform == Common::kPlatformAmiga) { + if (_unkScreenVar1 && !queryGameFlag(0xF0)) { + memset(_screen->getPalette(2), 0, 32*3); + if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3)) + _screen->setScreenPalette(_screen->getPalette(2)); + } + + if (_unkScreenVar2 == 1) + _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); + else + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + + if (_unkScreenVar1 && !queryGameFlag(0xA0)) { + if (_currentCharacter->sceneId == 45 && _paletteChanged) + memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2); + + if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1)) + memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64); + + _screen->setScreenPalette(_screen->getPalette(0)); + } + } else { + if (_unkScreenVar1 && !queryGameFlag(0xA0)) { + for (int i = 0; i < 60; ++i) { + uint16 col = _screen->getPalette(0)[684+i]; + col += _screen->getPalette(1)[684+i] << 1; + col >>= 2; + _screen->getPalette(0)[684+i] = col; + } + _screen->setScreenPalette(_screen->getPalette(0)); + } + + if (_unkScreenVar2 == 1) + _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false); + else + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + + if (_unkScreenVar1 && _paletteChanged) { + if (!queryGameFlag(0xA0)) { + memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60); + _screen->setScreenPalette(_screen->getPalette(0)); + } else { + memset(_screen->getPalette(0), 0, 768); + } + } + } + + // really call this here? + _screen->updateScreen(); + + if (!_scriptInterpreter->startScript(_scriptClick, 2)) + error("Could not start script function 2 of scene script"); + + _scriptClick->regs[7] = brandonAlive; + + while (_scriptInterpreter->validScript(_scriptClick)) + _scriptInterpreter->runScript(_scriptClick); + + setTextFadeTimerCountdown(-1); + if (_currentCharacter->sceneId == 210) { + if (_itemInHand != -1) + magicOutMouseItem(2, -1); + + _screen->hideMouse(); + for (int i = 0; i < 10; ++i) { + if (_currentCharacter->inventoryItems[i] != 0xFF) + magicOutMouseItem(2, i); + } + _screen->showMouse(); + } +} + +int KyraEngine_v1::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset); + if (queryGameFlag(0xEF)) + unk1 = 0; + + int sceneId = _currentCharacter->sceneId; + _pathfinderFlag = 0; + + if (xpos < 12) { + if (_roomTable[sceneId].westExit != 0xFFFF) { + xpos = 12; + ypos = _sceneExits.westYPos; + _pathfinderFlag = 7; + } + } else if (xpos >= 308) { + if (_roomTable[sceneId].eastExit != 0xFFFF) { + xpos = 307; + ypos = _sceneExits.eastYPos; + _pathfinderFlag = 13; + } + } + + if (ypos <= (_northExitHeight&0xFF)+2) { + if (_roomTable[sceneId].northExit != 0xFFFF) { + xpos = _sceneExits.northXPos; + ypos = _northExitHeight & 0xFF; + _pathfinderFlag = 14; + } + } else if (ypos >= 136) { + if (_roomTable[sceneId].southExit != 0xFFFF) { + xpos = _sceneExits.southXPos; + ypos = 136; + _pathfinderFlag = 11; + } + } + + int temp = xpos - _currentCharacter->x1; + if (ABS(temp) < 4) { + temp = ypos - _currentCharacter->y1; + if (ABS(temp) < 2) + return 0; + } + + int x = (int16)(_currentCharacter->x1 & 0xFFFC); + int y = (int16)(_currentCharacter->y1 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); + + int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150); + _pathfinderFlag = 0; + + if (ret >= _lastFindWayRet) + _lastFindWayRet = ret; + + if (ret == 0x7D00 || ret == 0) + return 0; + + return processSceneChange(_movFacingTable, unk1, frameReset); +} + +int KyraEngine_v1::processSceneChange(int *table, int unk1, int frameReset) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset); + if (queryGameFlag(0xEF)) + unk1 = 0; + + int *tableStart = table; + _sceneChangeState = 0; + _loopFlag2 = 0; + bool running = true; + int returnValue = 0; + uint32 nextFrame = 0; + _abortWalkFlag = false; + _mousePressFlag = false; + + while (running) { + if (_abortWalkFlag) { + *table = 8; + _currentCharacter->currentAnimFrame = 7; + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + processInput(); + return 0; + } + bool forceContinue = false; + switch (*table) { + case 0: case 1: case 2: + case 3: case 4: case 5: + case 6: case 7: + _currentCharacter->facing = getOppositeFacingDirection(*table); + break; + + case 8: + forceContinue = true; + running = false; + break; + + default: + ++table; + forceContinue = true; + break; + } + + returnValue = changeScene(_currentCharacter->facing); + if (returnValue) { + running = false; + _abortWalkFlag = false; + } + + if (unk1) { + if (_mousePressFlag) { + running = false; + _sceneChangeState = 1; + } + } + + if (forceContinue || !running) + continue; + + int temp = 0; + if (table == tableStart || table[1] == 8) + temp = setCharacterPosition(0, 0); + else + temp = setCharacterPosition(0, table); + + if (temp) + ++table; + + nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis(); + while (_system->getMillis() < nextFrame) { + _timer->update(); + + if (_currentCharacter->sceneId == 210) { + updateKyragemFading(); + if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) { + *table = 8; + running = false; + break; + } + } + + if ((nextFrame - _system->getMillis()) >= 10) + delay(10, true); + } + } + + if (frameReset && !(_brandonStatusBit & 2)) + _currentCharacter->currentAnimFrame = 7; + + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + return returnValue; +} + +int KyraEngine_v1::changeScene(int facing) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::changeScene(%d)", facing); + if (queryGameFlag(0xEF)) { + if (_currentCharacter->sceneId == 5) + return 0; + } + + int xpos = _charXPosTable[facing] + _currentCharacter->x1; + int ypos = _charYPosTable[facing] + _currentCharacter->y1; + + if (xpos >= 12 && xpos <= 308) { + if (!lineIsPassable(xpos, ypos)) + return false; + } + + if (_exitListPtr) { + int16 *ptr = _exitListPtr; + // this loop should be only entered one time, seems to be some hack in the original + while (true) { + if (*ptr == -1) + break; + + if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) { + ptr += 10; + break; + } + + _brandonPosX = ptr[6]; + _brandonPosY = ptr[7]; + uint16 sceneId = ptr[5]; + facing = ptr[4]; + int unk1 = ptr[8]; + int unk2 = ptr[9]; + + if (sceneId == 0xFFFF) { + switch (facing) { + case 0: + sceneId = _roomTable[_currentCharacter->sceneId].northExit; + break; + + case 2: + sceneId = _roomTable[_currentCharacter->sceneId].eastExit; + break; + + case 4: + sceneId = _roomTable[_currentCharacter->sceneId].southExit; + break; + + case 6: + sceneId = _roomTable[_currentCharacter->sceneId].westExit; + break; + + default: + break; + } + } + + _currentCharacter->facing = facing; + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + enterNewScene(sceneId, facing, unk1, unk2, 0); + resetGameFlag(0xEE); + return 1; + } + } + + int returnValue = 0; + facing = 0; + + if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) { + facing = 0; + returnValue = 1; + } + + if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) { + facing = 2; + returnValue = 1; + } + + if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) { + facing = 4; + returnValue = 1; + } + + if (xpos <= 12 || _currentCharacter->y1 <= 12) { + facing = 6; + returnValue = 1; + } + + if (!returnValue) + return 0; + + uint16 sceneId = 0xFFFF; + switch (facing) { + case 0: + sceneId = _roomTable[_currentCharacter->sceneId].northExit; + break; + + case 2: + sceneId = _roomTable[_currentCharacter->sceneId].eastExit; + break; + + case 4: + sceneId = _roomTable[_currentCharacter->sceneId].southExit; + break; + + default: + sceneId = _roomTable[_currentCharacter->sceneId].westExit; + break; + } + + if (sceneId == 0xFFFF) + return 0; + + enterNewScene(sceneId, facing, 1, 1, 0); + return returnValue; +} + +void KyraEngine_v1::setCharactersInDefaultScene() { + static const uint32 defaultSceneTable[][4] = { + { 0xFFFF, 0x0004, 0x0003, 0xFFFF }, + { 0xFFFF, 0x0022, 0xFFFF, 0x0000 }, + { 0xFFFF, 0x001D, 0x0021, 0xFFFF }, + { 0xFFFF, 0x0000, 0x0000, 0xFFFF } + }; + + for (int i = 1; i < 5; ++i) { + Character *cur = &_characterList[i]; + //cur->field_20 = 0; + + const uint32 *curTable = defaultSceneTable[i-1]; + cur->sceneId = curTable[0]; + + if (cur->sceneId == _currentCharacter->sceneId) + //++cur->field_20; + cur->sceneId = curTable[1/*cur->field_20*/]; + + //cur->field_23 = curTable[cur->field_20+1]; + } +} + +void KyraEngine_v1::setCharactersPositions(int character) { + static uint16 initXPosTable[] = { + 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B, + 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042 + }; + static uint8 initYPosTable[] = { + 0x00, 0xA2, 0x00, 0x42, 0x00, + 0x67, 0x67, 0x60, 0x5A, 0x71, + 0x76 + }; + + assert(character < ARRAYSIZE(initXPosTable)); + Character *edit = &_characterList[character]; + edit->x1 = edit->x2 = initXPosTable[character]; + edit->y1 = edit->y2 = initYPosTable[character]; +} + +#pragma mark - +#pragma mark - Pathfinder +#pragma mark - + +int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); + return getMoveTableSize(moveTable); +} + +bool KyraEngine_v1::lineIsPassable(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::lineIsPassable(%d, %d)", x, y); + if (queryGameFlag(0xEF)) { + if (_currentCharacter->sceneId == 5) + return true; + } + + if (_pathfinderFlag & 2) { + if (x >= 312) + return false; + } + + if (_pathfinderFlag & 4) { + if (y >= 136) + return false; + } + + if (_pathfinderFlag & 8) { + if (x < 8) + return false; + } + + if (_pathfinderFlag2) { + if (x <= 8 || x >= 312) + return true; + if (y < (_northExitHeight & 0xFF) || y > 135) + return true; + } + + if (y > 137) + return false; + + if (y < 0) + y = 0; + + int ypos = 8; + if (_scaleMode) { + ypos = (_scaleTable[y] >> 5) + 1; + if (8 < ypos) + ypos = 8; + } + + x -= (ypos >> 1); + + int xpos = x; + int xtemp = xpos + ypos - 1; + if (x < 0) + xpos = 0; + + if (xtemp > 319) + xtemp = 319; + + for (; xpos < xtemp; ++xpos) { + if (!_screen->getShapeFlag1(xpos, y)) + return false; + } + return true; +} + +#pragma mark - + +void KyraEngine_v1::setupSceneResource(int sceneId) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneResource(%d)", sceneId); + if (!_flags.isTalkie) + return; + + if (_currentRoom != 0xFFFF) { + assert(_currentRoom < _roomTableSize); + int tableId = _roomTable[_currentRoom].nameIndex; + assert(tableId < _roomFilenameTableSize); + + // unload our old room + char file[64]; + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + _res->unloadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".PAK"); + _res->unloadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".APK"); + _res->unloadPakFile(file); + } + + assert(sceneId < _roomTableSize); + int tableId = _roomTable[sceneId].nameIndex; + assert(tableId < _roomFilenameTableSize); + + // load our new room + char file[64]; + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".VRM"); + if (Common::File::exists(file)) + _res->loadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".PAK"); + if (Common::File::exists(file)) + _res->loadPakFile(file); + + strcpy(file, _roomFilenameTable[tableId]); + strcat(file, ".APK"); + if (Common::File::exists(file)) + _res->loadPakFile(file); +} + +} // end of namespace Kyra + diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp new file mode 100644 index 0000000000..7863fa6638 --- /dev/null +++ b/engines/kyra/scene_v2.cpp @@ -0,0 +1,867 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v2.h" +#include "kyra/screen_v2.h" +#include "kyra/wsamovie.h" + +#include "common/func.h" + +namespace Kyra { + +void KyraEngine_v2::enterNewScene(uint16 newScene, int facing, int unk1, int unk2, int unk3) { + // XXX + _screen->hideMouse(); + + if (!unk3) { + //updateSpecialItems(); + //displayInvWsaLastFrame(); + } + + if (unk1) { + int x = _mainCharacter.x1; + int y = _mainCharacter.y1; + + switch (facing) { + case 0: + y -= 6; + break; + + case 2: + x = 335; + break; + + case 4: + y = 147; + break; + + case 6: + x = -16; + break; + + default: + break; + } + + moveCharacter(facing, x, y); + } + + //XXX sound + + _unkFlag1 = false; + + if (!unk3) { + _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData); + _scriptInterpreter->startScript(&_sceneScriptState, 5); + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); + } + + Common::for_each(_wsaSlots, _wsaSlots+ARRAYSIZE(_wsaSlots), Common::mem_fun(&WSAMovieV2::close)); + _specialExitCount = 0; + memset(_specialExitTable, -1, sizeof(_specialExitTable)); + + _mainCharacter.sceneId = newScene; + _sceneList[newScene].flags &= ~1; + loadScenePal(); + unloadScene(); + loadSceneMsc(); + + SceneDesc &scene = _sceneList[newScene]; + _sceneExit1 = scene.exit1; + _sceneExit2 = scene.exit2; + _sceneExit3 = scene.exit3; + _sceneExit4 = scene.exit4; + + //XXX sound + + startSceneScript(unk3); + + if (_overwriteSceneFacing) { + facing = _mainCharacter.facing; + _overwriteSceneFacing = false; + } + + enterNewSceneUnk1(facing, unk2, unk3); + + setTimer1DelaySecs(-1); + _sceneScriptState.regs[3] = 1; + enterNewSceneUnk2(unk3); + _screen->showMouse(); + _unk5 = 0; + //setNextIdleAnimTimer(); +} + +void KyraEngine_v2::enterNewSceneUnk1(int facing, int unk1, int unk2) { + int x = 0, y = 0; + int x2 = 0, y2 = 0; + bool needProc = true; + + if (_mainCharX == -1 && _mainCharY == -1) { + switch (facing+1) { + case 1: case 2: case 8: + x2 = _sceneEnterX3; + y2 = _sceneEnterY3; + break; + + case 3: + x2 = _sceneEnterX4; + y2 = _sceneEnterY4; + break; + + case 4: case 5: case 6: + x2 = _sceneEnterX1; + y2 = _sceneEnterY1; + break; + + case 7: + x2 = _sceneEnterX2; + y2 = _sceneEnterY2; + break; + + default: + x2 = y2 = -1; + break; + } + + if (x2 >= 316) + x2 = 312; + if (y2 >= 141) + y2 = 139; + if (x2 <= 4) + x2 = 8; + } + + if (_mainCharX >= 0) { + x = x2 = _mainCharX; + needProc = false; + } + + if (_mainCharY >= 0) { + y = y2 = _mainCharY; + needProc = false; + } + + _mainCharX = _mainCharY = -1; + + if (unk1 && needProc) { + x = x2; + y = y2; + + switch (facing) { + case 0: + y2 = 147; + break; + + case 2: + x2 = -16; + break; + + case 4: + y2 = y - 4; + break; + + case 6: + x2 = 335; + break; + + default: + break; + } + } + + x2 &= ~3; + x &= ~3; + y2 &= ~1; + y &= ~1; + + _mainCharacter.facing = facing; + _mainCharacter.x1 = _mainCharacter.x2 = x2; + _mainCharacter.y1 = _mainCharacter.y2 = y2; + initSceneAnims(unk2); + + if (!unk2) { + //XXX sound + } + + if (unk1 && !unk2 && _mainCharacter.animFrame != 32) + moveCharacter(facing, x, y); +} + +void KyraEngine_v2::enterNewSceneUnk2(int unk1) { + _unk3 = -1; + + if (_mainCharX == -1 && _mainCharY == -1 && _mainCharacter.sceneId != 61 && + !queryGameFlag(0x1F1) && !queryGameFlag(0x192) && !queryGameFlag(0x193) && + _mainCharacter.sceneId != 70 && !queryGameFlag(0x159) && _mainCharacter.sceneId != 37) { + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + updateCharacterAnim(0); + refreshAnimObjectsIfNeed(); + } + + if (!unk1) { + runSceneScript4(0); + //XXX sub_27158 + } + + _unk4 = 0; + _unk3 = -1; +} + +int KyraEngine_v2::trySceneChange(int *moveTable, int unk1, int updateChar) { + bool running = true; + bool unkFlag = false; + int8 updateType = -1; + int changedScene = 0; + const int *moveTableStart = moveTable; + _unk4 = 0; + while (running) { + if (*moveTable >= 0 && *moveTable <= 7) { + _mainCharacter.facing = getOppositeFacingDirection(*moveTable); + unkFlag = true; + } else { + if (*moveTable == 8) { + running = false; + } else { + ++moveTable; + unkFlag = false; + } + } + + if (checkSceneChange()) { + running = false; + changedScene = 1; + } + + if (unk1) { + //XXX + } + + if (!unkFlag || !running) + continue; + + int ret = 0; + if (moveTable == moveTableStart || moveTable[1] == 8) + ret = updateCharPos(0); + else + ret = updateCharPos(moveTable); + + if (ret) + ++moveTable; + + ++updateType; + if (!updateType) { + update(); + } else if (updateType == 1) { + refreshAnimObjectsIfNeed(); + updateType = -1; + } + } + + if (updateChar) + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + + updateCharacterAnim(0); + refreshAnimObjectsIfNeed(); + + if (!changedScene && !_unk4) { + //XXX + } + return changedScene; +} + +int KyraEngine_v2::checkSceneChange() { + SceneDesc &curScene = _sceneList[_mainCharacter.sceneId]; + int charX = _mainCharacter.x1, charY = _mainCharacter.y1; + int facing = 0; + int process = 0; + + if (_screen->getLayer(charX, charY) == 1 && _unk3 == -6) { + facing = 0; + process = 1; + } else if (charX >= 316 && _unk3 == -5) { + facing = 2; + process = 1; + } else if (charY >= 142 && _unk3 == -4) { + facing = 4; + process = 1; + } else if (charX <= 4 && _unk3 == -3) { + facing = 6; + process = 1; + } + + if (!process) + return 0; + + uint16 newScene = 0xFFFF; + switch (facing) { + case 0: + newScene = curScene.exit1; + break; + + case 2: + newScene = curScene.exit2; + break; + + case 4: + newScene = curScene.exit3; + break; + + case 6: + newScene = curScene.exit4; + break; + + default: + newScene = _mainCharacter.sceneId; + break; + } + + if (newScene == 0xFFFF) + return 0; + + enterNewScene(newScene, facing, 1, 1, 0); + return 1; +} + +void KyraEngine_v2::unloadScene() { + _scriptInterpreter->unloadScript(&_sceneScriptData); + freeSceneShapePtrs(); + freeSceneAnims(); +} + +void KyraEngine_v2::loadScenePal() { + uint16 sceneId = _mainCharacter.sceneId; + memcpy(_screen->getPalette(1), _screen->getPalette(0), 768); + + char filename[14]; + strcpy(filename, _sceneList[sceneId].filename); + strcat(filename, ".COL"); + _screen->loadBitmap(filename, 3, 3, 0); + memcpy(_screen->getPalette(1), _screen->getCPagePtr(3), 384); + memset(_screen->getPalette(1), 0, 3); + memcpy(_scenePal, _screen->getCPagePtr(3)+336, 432); +} + +void KyraEngine_v2::loadSceneMsc() { + uint16 sceneId = _mainCharacter.sceneId; + char filename[14]; + strcpy(filename, _sceneList[sceneId].filename); + strcat(filename, ".MSC"); + _screen->loadBitmap(filename, 3, 5, 0); +} + +void KyraEngine_v2::startSceneScript(int unk1) { + uint16 sceneId = _mainCharacter.sceneId; + char filename[14]; + + strcpy(filename, _sceneList[sceneId].filename); + if (sceneId == 68 && (queryGameFlag(0x1BC) || queryGameFlag(0x1DC))) + strcpy(filename, "DOORX"); + strcat(filename, ".CPS"); + + _screen->loadBitmap(filename, 3, 3, 0); + resetScaleTable(); + _useCharPal = false; + memset(_charPalTable, 0, sizeof(_charPalTable)); + //XXX _unkTable33 + memset(_specialSceneScriptState, 0, sizeof(_specialSceneScriptState)); + + _sceneEnterX1 = 160; + _sceneEnterY1 = 0; + _sceneEnterX2 = 296; + _sceneEnterY2 = 72; + _sceneEnterX3 = 160; + _sceneEnterY3 = 128; + _sceneEnterX4 = 24; + _sceneEnterY4 = 72; + + _sceneCommentString = "Undefined scene comment string!"; + _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData); + + strcpy(filename, _sceneList[sceneId].filename); + strcat(filename, "."); + strcat(filename, _scriptLangExt[_lang]); + + assert(_res->getFileSize(filename)); + _scriptInterpreter->loadScript(filename, &_sceneScriptData, &_opcodes); + runSceneScript7(); + + _scriptInterpreter->startScript(&_sceneScriptState, 0); + _sceneScriptState.regs[0] = sceneId; + _sceneScriptState.regs[5] = unk1; + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); + + memcpy(_gamePlayBuffer, _screen->getCPagePtr(3), 46080); + + for (int i = 0; i < 10; ++i) { + _scriptInterpreter->initScript(&_sceneSpecialScripts[i], &_sceneScriptData); + _scriptInterpreter->startScript(&_sceneSpecialScripts[i], i+8); + _sceneSpecialScriptsTimer[i] = 0; + } + + _sceneEnterX1 &= ~3; + _sceneEnterX2 &= ~3; + _sceneEnterX3 &= ~3; + _sceneEnterX4 &= ~3; + _sceneEnterY1 &= ~1; + _sceneEnterY2 &= ~1; + _sceneEnterY3 &= ~1; + _sceneEnterY4 &= ~1; +} + +void KyraEngine_v2::runSceneScript2() { + _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData); + _sceneScriptState.regs[4] = _itemInHand; + _scriptInterpreter->startScript(&_sceneScriptState, 2); + + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); +} + +void KyraEngine_v2::runSceneScript4(int unk1) { + _sceneScriptState.regs[4] = _itemInHand; + _sceneScriptState.regs[5] = unk1; + + _scriptInterpreter->startScript(&_sceneScriptState, 4); + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); +} + +void KyraEngine_v2::runSceneScript7() { + int oldPage = _screen->_curPage; + _screen->_curPage = 2; + + _scriptInterpreter->startScript(&_sceneScriptState, 7); + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); + + _screen->_curPage = oldPage; +} + +void KyraEngine_v2::initSceneAnims(int unk1) { + for (int i = 0; i < ARRAYSIZE(_animObjects); ++i) + _animObjects[i].enabled = 0; + + bool animInit = false; + + AnimObj *animState = &_animObjects[0]; + + if (_mainCharacter.animFrame != 32) + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + + animState->enabled = 1; + animState->xPos1 = _mainCharacter.x1; + animState->yPos1 = _mainCharacter.y1; + animState->shapePtr = _defaultShapeTable[_mainCharacter.animFrame]; + animState->shapeIndex1 = animState->shapeIndex2 = _mainCharacter.animFrame; + + int frame = _mainCharacter.animFrame - 9; + int shapeX = _shapeDescTable[frame].xAdd; + int shapeY = _shapeDescTable[frame].yAdd; + + animState->xPos2 = _mainCharacter.x1; + animState->yPos2 = _mainCharacter.y1; + + _charScaleX = _charScaleY = getScale(_mainCharacter.x1, _mainCharacter.y1); + + int shapeXScaled = (shapeX * _charScaleX) >> 8; + int shapeYScaled = (shapeY * _charScaleY) >> 8; + + animState->xPos2 += shapeXScaled; + animState->yPos2 += shapeYScaled; + animState->xPos3 = animState->xPos2; + animState->yPos3 = animState->yPos2; + animState->needRefresh = 1; + animState->unk8 = 1; + + _animList = 0; + + AnimObj *charAnimState = animState; + + for (int i = 0; i < 10; ++i) { + animState = &_animObjects[i+1]; + animState->enabled = 0; + animState->needRefresh = 0; + animState->unk8 = 0; + + if (_sceneAnims[i].flags & 1) { + animState->enabled = 1; + animState->needRefresh = 1; + animState->unk8 = 1; + } + + animState->animFlags = _sceneAnims[i].flags & 8; + + if (_sceneAnims[i].flags & 2) + animState->flags = 0x800; + else + animState->flags = 0; + + if (_sceneAnims[i].flags & 4) + animState->flags |= 1; + + animState->xPos1 = _sceneAnims[i].x; + animState->yPos1 = _sceneAnims[i].y; + + if (_sceneAnims[i].flags & 0x20) + animState->shapePtr = _sceneShapeTable[_sceneAnims[i].shapeIndex]; + else + animState->shapePtr = 0; + + if (_sceneAnims[i].flags & 0x40) { + animState->shapeIndex3 = _sceneAnims[i].shapeIndex; + animState->animNum = i; + } else { + animState->shapeIndex3 = 0xFFFF; + animState->animNum = 0xFFFF; + } + + animState->shapeIndex2 = 0xFFFF; + + animState->xPos3 = animState->xPos2 = _sceneAnims[i].x2; + animState->yPos3 = animState->yPos2 = _sceneAnims[i].y2; + animState->width = _sceneAnims[i].width; + animState->height = _sceneAnims[i].height; + animState->width2 = animState->height2 = _sceneAnims[i].specialSize; + + if (_sceneAnims[i].flags & 1) { + if (animInit) { + _animList = addToAnimListSorted(_animList, animState); + } else { + _animList = initAnimList(_animList, animState); + animInit = true; + } + } + } + + if (animInit) { + _animList = addToAnimListSorted(_animList, charAnimState); + } else { + _animList = initAnimList(_animList, charAnimState); + animInit = true; + } + + for (int i = 0; i < 30; ++i) { + animState = &_animObjects[i+11]; + + uint16 shapeIndex = _itemList[i].id; + if (shapeIndex == 0xFFFF || _itemList[i].sceneId != _mainCharacter.sceneId) { + animState->enabled = 0; + animState->needRefresh = 0; + animState->unk8 = 0; + } else { + animState->xPos1 = _itemList[i].x; + animState->yPos1 = _itemList[i].y; + animState->shapePtr = _defaultShapeTable[64+shapeIndex]; + animState->shapeIndex1 = animState->shapeIndex2 = shapeIndex+64; + + animState->xPos2 = _itemList[i].x; + animState->yPos2 = _itemList[i].y; + int objectScale = getScale(animState->xPos2, animState->yPos2); + + const uint8 *shape = getShapePtr(animState->shapeIndex1); + animState->xPos2 -= (_screen->getShapeScaledWidth(shape, objectScale) >> 1); + animState->yPos2 -= (_screen->getShapeScaledHeight(shape, objectScale) >> 1); + animState->xPos3 = animState->xPos2; + animState->yPos3 = animState->yPos2; + + animState->enabled = 1; + animState->needRefresh = 1; + animState->unk8 = 1; + + if (animInit) { + _animList = addToAnimListSorted(_animList, animState); + } else { + _animList = initAnimList(_animList, animState); + animInit = true; + } + } + } + + _animObjects[0].unk8 = 1; + _animObjects[0].needRefresh = 1; + + for (int i = 1; i < 41; ++i) { + if (_animObjects[i].enabled) { + _animObjects[i].needRefresh = 1; + _animObjects[i].unk8 = 1; + } + } + + restorePage3(); + drawAnimObjects(); + _screen->hideMouse(); + initSceneScreen(unk1); + _screen->showMouse(); + refreshAnimObjects(0); +} + +void KyraEngine_v2::initSceneScreen(int unk1) { + if (_unkSceneScreenFlag1) { + _screen->copyRegion(0, 0, 0, 0, 320, 144, 2, 0); + return; + } + + if (_noScriptEnter) { + memset(_screen->getPalette(0), 0, 384); + _screen->setScreenPalette(_screen->getPalette(0)); + } + + _screen->copyRegion(0, 0, 0, 0, 320, 144, 2, 0); + + if (_noScriptEnter) + memcpy(_screen->getPalette(0), _screen->getPalette(1), 384); + + updateCharPal(0); + + _scriptInterpreter->startScript(&_sceneScriptState, 3); + _sceneScriptState.regs[5] = unk1; + while (_scriptInterpreter->validScript(&_sceneScriptState)) + _scriptInterpreter->runScript(&_sceneScriptState); +} + +void KyraEngine_v2::updateSpecialSceneScripts() { + uint32 nextTime = _system->getMillis() + _tickLength; + const int startScript = _lastProcessedSceneScript; + + while (_system->getMillis() <= nextTime) { + if (_sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis() && + !_specialSceneScriptState[_lastProcessedSceneScript]) { + _specialSceneScriptRunFlag = true; + + while (_specialSceneScriptRunFlag && _sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis()) + _specialSceneScriptRunFlag = _scriptInterpreter->runScript(&_sceneSpecialScripts[_lastProcessedSceneScript]) != 0; + } + + if (!_scriptInterpreter->validScript(&_sceneSpecialScripts[_lastProcessedSceneScript])) { + _scriptInterpreter->startScript(&_sceneSpecialScripts[_lastProcessedSceneScript], 8+_lastProcessedSceneScript); + _specialSceneScriptRunFlag = false; + } + + ++_lastProcessedSceneScript; + if (_lastProcessedSceneScript >= 10) + _lastProcessedSceneScript = 0; + + if (_lastProcessedSceneScript == startScript) + return; + } +} + +void KyraEngine_v2::freeSceneShapePtrs() { + for (int i = 0; i < ARRAYSIZE(_sceneShapeTable); ++i) + delete [] _sceneShapeTable[i]; + memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable)); +} + +void KyraEngine_v2::freeSceneAnims() { + Common::for_each(_sceneAnimMovie, _sceneAnimMovie+ARRAYSIZE(_sceneAnimMovie), Common::mem_fun(&WSAMovieV2::close)); +} + +#pragma mark - +#pragma mark - Pathfinder +#pragma mark - + +int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + x &= ~3; toX &= ~3; + y &= ~1; toY &= ~1; + int size = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); + if (size) { +/* + int temp = pathfinderUnk1(moveTable); + temp = pathfinderUnk3(temp, x, y); + pathfinderUnk5(moveTable, temp, x, y, moveTableSize); +*/ + } + return getMoveTableSize(moveTable); +} + +bool KyraEngine_v2::lineIsPassable(int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::lineIsPassable(%d, %d)", x, y); + static int unkTable[] = { 1, 1, 1, 1, 1, 2, 4, 6, 8 }; + + if (_pathfinderFlag & 2) { + if (x >= 320) + return false; + } + + if (_pathfinderFlag & 4) { + if (y >= 144) + return false; + } + + if (_pathfinderFlag & 8) { + if (x < 0) + return false; + } + + if (y > 143) + return false; + + int unk1 = unkTable[getScale(x, y) >> 5]; + + if (y < 0) + y = 0; + x -= unk1 >> 1; + if (x < 0) + x = 0; + int x2 = x + unk1; + if (x2 > 320) + x2 = 320; + + for (;x < x2; ++x) + if (!_screen->getShapeFlag1(x, y)) + return false; + + return true; +} + +bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) { + while (x != toX && y != toY) { + int facing = getFacingFromPointToPoint(x, y, toX, toY); + x += _addXPosTable[facing]; + y += _addYPosTable[facing]; + if (!_screen->getShapeFlag1(x, y)) + return false; + } + return true; +} + +int KyraEngine_v2::pathfinderUnk1(int *moveTable) { + bool breakLoop = false; + int *moveTableCur = moveTable; + int oldEntry = *moveTableCur, curEntry = *moveTableCur; + int oldX = 0, newX = 0, oldY = 0, newY = 0; + int lastEntry = 0; + lastEntry = pathfinderUnk2(lastEntry, 0, 0); + + while (*moveTableCur != 8) { + oldEntry = curEntry; + + while (true) { + curEntry = *moveTableCur; + if (curEntry >= 0 && curEntry <= 7) + break; + + if (curEntry == 8) { + breakLoop = true; + break; + } else { + ++moveTableCur; + } + } + + if (breakLoop) + break; + + oldX = newX; + oldY = newY; + + newX += _addXPosTable[curEntry]; + newY += _addYPosTable[curEntry]; + + int temp = ABS(curEntry - oldEntry); + if (temp > 4) { + temp = 8 - temp; + } + + if (temp > 1 || oldEntry != curEntry) + lastEntry = pathfinderUnk2(lastEntry, oldX, oldY); + + ++moveTableCur; + } + + lastEntry = pathfinderUnk2(lastEntry, newX, newY); + _pathfinderUnkTable1[lastEntry*2+0] = -1; + _pathfinderUnkTable1[lastEntry*2+1] = -1; + return lastEntry; +} + +int KyraEngine_v2::pathfinderUnk2(int index, int v1, int v2) { + _pathfinderUnkTable1[index<<1] = v1; + _pathfinderUnkTable1[(index<<1)+1] = v2; + ++index; + if (index >= 199) + --index; + return index; +} + +int KyraEngine_v2::pathfinderUnk3(int tableLen, int x, int y) { + int x1 = 0, y1 = 0; + int x2 = 0, y2 = 0; + int lastEntry = 0; + int index2 = tableLen-1, index1 = 0; + while (index2 > index1) { + x1 = _pathfinderUnkTable1[index1*2+0] + x; + y1 = _pathfinderUnkTable1[index1*2+1] + y; + x2 = _pathfinderUnkTable1[index2*2+0] + x; + y2 = _pathfinderUnkTable1[index2*2+0] + x; + + if (directLinePassable(x1, y1, x2, y2)) { + lastEntry = pathfinderUnk4(lastEntry, index2); + if (tableLen-1 == index2) + break; + index1 = index2; + index2 = tableLen-1; + } else if (index1+1 == index2) { + lastEntry = pathfinderUnk4(lastEntry, index2); + index1 = index2; + index2 = tableLen-1; + } else { + --index2; + } + } + return lastEntry; +} + +int KyraEngine_v2::pathfinderUnk4(int index, int v) { + _pathfinderUnkTable2[index] = v; + ++index; + if (index >= 199) + --index; + return index; +} + +void KyraEngine_v2::pathfinderUnk5(int *moveTable, int tableLen, int x, int y, int moveTableSize) { + int x1 = 0, y1 = 0; + int x2 = 0, y2 = 0; + int index1 = 0, index2 = 0; + int sizeLeft = moveTableSize; + for (int i = 0; i < tableLen; ++i) { + index2 = _pathfinderUnkTable2[i]; + x1 = _pathfinderUnkTable1[index1*2+0] + x; + y1 = _pathfinderUnkTable1[index1*2+1] + y; + x2 = _pathfinderUnkTable1[index2*2+0] + x; + y2 = _pathfinderUnkTable1[index2*2+0] + x; + + int wayLen = findWay(x1, y1, x2, y2, moveTable, sizeLeft); + moveTable += wayLen; + sizeLeft -= wayLen; // unlike the original we want to be sure that the size left is correct + index1 = index2; + } +} + +} // end of namespace Kyra diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 641a034eab..a7e9c90824 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -355,46 +355,6 @@ void Screen::fadeToBlack(int delay) { fadePalette(blackPal, delay); } -void Screen::k2IntroFadeToGrey(int delay) { - debugC(9, kDebugLevelScreen, "Screen::k2IntroFadeToGrey()"); - - for (int i = 0; i <= 50; ++i) { - if (i <= 8 || i >= 30) { - _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] + - _currentPalette[3 * i + 1] + - _currentPalette[3 * i + 2]) / 3; - _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0]; - _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0]; - } - } - - // color 71 is the same in both the overview and closeup scenes - // Converting it to greyscale makes the trees in the closeup look dull - for (int i = 71; i < 200; ++i) { - _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] + - _currentPalette[3 * i + 1] + - _currentPalette[3 * i + 2]) / 3; - _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0]; - _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0]; - } - fadePalette(_currentPalette, delay); - // Make the font color white again - setPaletteIndex(254, 254, 254, 254); -} - -void Screen::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { - debugC(9, kDebugLevelScreen, "fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime); - assert(_vm->palTable1()[palIndex]); - assert(_currentPalette); - uint8 tempPal[768]; - memcpy(tempPal, _currentPalette, 768); - memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3); - fadePalette(tempPal, fadeTime*18); - memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3); - setScreenPalette(_currentPalette); - _system->updateScreen(); -} - void Screen::fadePalette(const uint8 *palData, int delay) { debugC(9, kDebugLevelScreen, "Screen::fadePalette(%p, %d)", (const void *)palData, delay); updateScreen(); @@ -1070,13 +1030,8 @@ void Screen::drawCharANSI(uint8 c, int x, int y) { void Screen::setScreenDim(int dim) { debugC(9, kDebugLevelScreen, "Screen::setScreenDim(%d)", dim); - if (_vm->game() == GI_KYRA1) { - assert(dim < _screenDimTableCount); - _curDim = &_screenDimTable[dim]; - } else { - assert(dim < _screenDimTableCountK3); - _curDim = &_screenDimTableK3[dim]; - } + assert(dim < _screenDimTableCount); + _curDim = &_screenDimTable[dim]; // XXX } @@ -2693,38 +2648,6 @@ void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) { } } -// kyra3 specific - -const uint8 *Screen::getPtrToShape(const uint8 *shpFile, int shape) { - debugC(9, kDebugLevelScreen, "KyraEngine::getPtrToShape(%p, %d)", (const void *)shpFile, shape); - uint16 shapes = READ_LE_UINT16(shpFile); - - if (shapes <= shape) - return 0; - - uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); - - return shpFile + offset + 2; -} - -uint8 *Screen::getPtrToShape(uint8 *shpFile, int shape) { - debugC(9, kDebugLevelScreen, "KyraEngine::getPtrToShape(%p, %d)", (void *)shpFile, shape); - uint16 shapes = READ_LE_UINT16(shpFile); - - if (shapes <= shape) - return 0; - - uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); - - return shpFile + offset + 2; -} - -uint16 Screen::getShapeSize(const uint8 *shp) { - debugC(9, kDebugLevelScreen, "KyraEngine::getShapeSize(%p)", (const void *)shp); - - return READ_LE_UINT16(shp+6); -} - // dirty rect handling void Screen::addDirtyRect(int x, int y, int w, int h) { diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index a60cdbd637..b1a1eb7b1a 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -33,7 +33,6 @@ class OSystem; namespace Kyra { class KyraEngine; -class Debugger; struct Rect; struct ScreenDim { @@ -57,7 +56,7 @@ struct Font { }; class Screen { - friend class Debugger; + friend class Debugger_v1; public: enum { @@ -94,7 +93,7 @@ public: }; Screen(KyraEngine *vm, OSystem *system); - ~Screen(); + virtual ~Screen(); bool init(); @@ -134,9 +133,6 @@ public: void fadeFromBlack(int delay=0x54); void fadeToBlack(int delay=0x54); - void k2IntroFadeToGrey(int delay=0x54); - - void fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime); void fadePalette(const uint8 *palData, int delay); void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue); @@ -164,7 +160,7 @@ public: void setTextColorMap(const uint8 *cmap); void setTextColor(const uint8 *cmap, int a, int b); - void setScreenDim(int dim); + virtual void setScreenDim(int dim); // shape handling uint8 *encodeShape(int x, int y, int w, int h, int flags); @@ -172,7 +168,7 @@ public: int setNewShapeHeight(uint8 *shape, int height); int resetShapeHeight(uint8 *shape); - void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...); + virtual void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...); // mouse handling void hideMouse(); @@ -180,7 +176,7 @@ public: void setMouseCursor(int x, int y, byte *shape); // rect handling - int getRectSize(int w, int h); + virtual int getRectSize(int w, int h); void rectClip(int &x, int &y, int w, int h); @@ -210,6 +206,7 @@ public: void copyBackgroundBlock(int x, int page, int flag); void copyBackgroundBlock2(int x); + // kyra1 specific? int getDrawLayer(int x, int y); int getDrawLayer2(int x, int y, int height); @@ -234,16 +231,7 @@ public: static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true); static void convertAmigaMsc(uint8 *data); - // maybe subclass screen for kyra3 - static const ScreenDim _screenDimTableK3[]; - static const int _screenDimTableCountK3; - - uint8 *getPtrToShape(uint8 *shpFile, int shape); - const uint8 *getPtrToShape(const uint8 *shpFile, int shape); - - uint16 getShapeSize(const uint8 *shp); - -private: +protected: uint8 *getPagePtr(int pageNum); void updateDirtyRects(); void updateDirtyRectsOvl(); diff --git a/engines/kyra/screen_v1.cpp b/engines/kyra/screen_v1.cpp new file mode 100644 index 0000000000..dc0fd798fa --- /dev/null +++ b/engines/kyra/screen_v1.cpp @@ -0,0 +1,53 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v1.h" +#include "kyra/screen_v1.h" + +namespace Kyra { + +Screen_v1::Screen_v1(KyraEngine_v1 *vm, OSystem *system) + : Screen(vm, system) { + _vm = vm; +} + +Screen_v1::~Screen_v1() { +} + +void Screen_v1::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) { + debugC(9, kDebugLevelScreen, "Screen_v1::fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime); + + assert(_vm->palTable1()[palIndex]); + assert(_currentPalette); + uint8 tempPal[768]; + memcpy(tempPal, _currentPalette, 768); + memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3); + fadePalette(tempPal, fadeTime*18); + memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3); + setScreenPalette(_currentPalette); + _system->updateScreen(); +} + +} // end of namespace Kyra diff --git a/engines/kyra/screen_v1.h b/engines/kyra/screen_v1.h new file mode 100644 index 0000000000..988e28bfbf --- /dev/null +++ b/engines/kyra/screen_v1.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_SCREEN_V1_H +#define KYRA_SCREEN_V1_H + +#include "kyra/screen.h" + +namespace Kyra { + +class KyraEngine_v1; + +class Screen_v1 : public Screen { +public: + Screen_v1(KyraEngine_v1 *vm, OSystem *system); + virtual ~Screen_v1(); + + void fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime); + +protected: + KyraEngine_v1 *_vm; +}; + +} // end of namespace Kyra + +#endif diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp new file mode 100644 index 0000000000..83c75585a8 --- /dev/null +++ b/engines/kyra/screen_v2.cpp @@ -0,0 +1,561 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "common/endian.h" + +#include "kyra/kyra_v2.h" +#include "kyra/screen_v2.h" + +namespace Kyra { + +Screen_v2::Screen_v2(KyraEngine_v2 *vm, OSystem *system) + : Screen(vm, system) { + _vm = vm; +} + +Screen_v2::~Screen_v2() { +} + +void Screen_v2::setScreenDim(int dim) { + debugC(9, kDebugLevelScreen, "Screen_v2::setScreenDim(%d)", dim); + if (_vm->game() == GI_KYRA2) { + assert(dim < _screenDimTableCount); + _curDim = &_screenDimTable[dim]; + } else { + assert(dim < _screenDimTableCountK3); + _curDim = &_screenDimTableK3[dim]; + } +} + +const ScreenDim *Screen_v2::getScreenDim(int dim) { + debugC(9, kDebugLevelScreen, "Screen_v2::getScreenDim(%d)", dim); + if (_vm->game() == GI_KYRA2) { + assert(dim < _screenDimTableCount); + return &_screenDimTable[dim]; + } else { + assert(dim < _screenDimTableCountK3); + return &_screenDimTableK3[dim]; + } +} + +void Screen_v2::k2IntroFadeToGrey(int delay) { + debugC(9, kDebugLevelScreen, "Screen_v2::k2IntroFadeToGrey(%d)", delay); + + for (int i = 0; i <= 50; ++i) { + if (i <= 8 || i >= 30) { + _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] + + _currentPalette[3 * i + 1] + + _currentPalette[3 * i + 2]) / 3; + _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0]; + _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0]; + } + } + + // color 71 is the same in both the overview and closeup scenes + // Converting it to greyscale makes the trees in the closeup look dull + for (int i = 71; i < 200; ++i) { + _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] + + _currentPalette[3 * i + 1] + + _currentPalette[3 * i + 2]) / 3; + _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0]; + _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0]; + } + fadePalette(_currentPalette, delay); + // Make the font color white again + setPaletteIndex(254, 254, 254, 254); +} + +void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { + uint8 *dstPtr = getPagePtr(_curPage); + uint8 *origDst = dstPtr; + + const ScreenDim *dim = getScreenDim(dimState); + int dimX1 = dim->sx << 3; + int dimX2 = dim->w << 3; + dimX2 += dimX1; + + int dimY1 = dim->sy; + int dimY2 = dim->h; + dimY2 += dimY1; + + int temp = y - dimY1; + if (temp < 0) { + if ((temp += h) <= 0) + return; + else { + SWAP(temp, h); + y += temp - h; + src += (temp - h) * w; + } + } + + temp = dimY2 - y; + if (temp <= 0) + return; + + if (temp < h) + h = temp; + + int srcOffset = 0; + temp = x - dimX1; + if (temp < 0) { + temp = -temp; + srcOffset = temp; + x += temp; + w -= temp; + } + + int srcAdd = 0; + + temp = dimX2 - x; + if (temp <= 0) + return; + + if (temp < w) { + SWAP(w, temp); + temp -= w; + srcAdd = temp; + } + + dstPtr += y * SCREEN_W + x; + uint8 *dst = dstPtr; + + if (_curPage == 0 || _curPage == 1) + addDirtyRect(x, y, w, h); + + clearOverlayRect(_curPage, x, y, w, h); + + temp = h; + while (h--) { + src += srcOffset; + int cW = w; + + switch (plotFunc) { + case 0: + memcpy(dst, src, cW); + dst += cW; src += cW; + break; + + case 1: + while (cW--) { + uint8 d = *src++; + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst++ = d; + } + break; + + case 4: + while (cW--) { + uint8 d = *src++; + if (d) + *dst = d; + ++dst; + } + break; + + case 5: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst = d; + } + ++dst; + } + break; + + case 8: + case 9: + while (cW--) { + uint8 d = *src++; + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + break; + + case 12: + case 13: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } else { + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + } + break; + + default: + break; + } + + dst = (dstPtr += SCREEN_W); + src += srcAdd; + } +} + +const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { + debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (const void *)shpFile, shape); + uint16 shapes = READ_LE_UINT16(shpFile); + + if (shapes <= shape) + return 0; + + uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); + + return shpFile + offset + 2; +} + +uint8 *Screen_v2::getPtrToShape(uint8 *shpFile, int shape) { + debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (void *)shpFile, shape); + uint16 shapes = READ_LE_UINT16(shpFile); + + if (shapes <= shape) + return 0; + + uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); + + return shpFile + offset + 2; +} + +int Screen_v2::getShapeScaledWidth(const uint8 *shpFile, int scale) { + int width = READ_LE_UINT16(shpFile+3); + return (width * scale) >> 8; +} + +int Screen_v2::getShapeScaledHeight(const uint8 *shpFile, int scale) { + int height = shpFile[2]; + return (height * scale) >> 8; +} + +uint16 Screen_v2::getShapeSize(const uint8 *shp) { + debugC(9, kDebugLevelScreen, "Screen_v2::getShapeSize(%p)", (const void *)shp); + + return READ_LE_UINT16(shp+6); +} + +uint8 *Screen_v2::makeShapeCopy(const uint8 *src, int index) { + debugC(9, kDebugLevelScreen, "Screen_v2::makeShapeCopy(%p, %d)", (const void *)src, index); + + const uint8 *shape = getPtrToShape(src, index); + int size = getShapeSize(shape); + + uint8 *copy = new uint8[size]; + assert(copy); + memcpy(copy, shape, size); + + return copy; +} + +void Screen_v2::drawShape(uint8 page, const uint8 *shape, int x, int y, int sd, int flags, ...) { + if (!shape) + return; + + if (*shape & 1) + flags |= 0x400; + + va_list args; + va_start(args, flags); + + static int drawShapeVar1 = 0; + static int drawShapeVar2[] = { + 1, 3, 2, 5, 4, 3, 2, 1 + }; + static int drawShapeVar3 = 1; + static int drawShapeVar4 = 0; + static int drawShapeVar5 = 0; + + uint8 *table = 0; + int tableLoopCount = 0; + int drawLayer = 0; + const uint8 *table2 = 0; + uint8 *table3 = 0; + uint8 *table4 = 0; + + if (flags & 0x8000) { + table2 = va_arg(args, uint8*); + } + if (flags & 0x100) { + table = va_arg(args, uint8*); + tableLoopCount = va_arg(args, int); + if (!tableLoopCount) + flags &= 0xFFFFFEFF; + } + if (flags & 0x1000) { + table3 = va_arg(args, uint8*); + table4 = va_arg(args, uint8*); + } + if (flags & 0x200) { + drawShapeVar1 += 1; + drawShapeVar1 &= 7; + drawShapeVar3 = drawShapeVar2[drawShapeVar1]; + drawShapeVar4 = 0; + drawShapeVar5 = 256; + } + if (flags & 0x4000) { + drawShapeVar5 = va_arg(args, int); + } + if (flags & 0x800) { + drawLayer = va_arg(args, int); + } + int scale_w, scale_h; + if (flags & 0x04) { + scale_w = va_arg(args, int); + scale_h = va_arg(args, int); + } else { + scale_w = 0x100; + scale_h = 0x100; + } + + int ppc = (flags >> 8) & 0x3F; + + const uint8 *src = shape; + uint16 shapeFlags = READ_LE_UINT16(src); src += 2; + + int shapeHeight = *src++; + int scaledShapeHeight = (shapeHeight * scale_h) >> 8; + if (scaledShapeHeight == 0) { + va_end(args); + return; + } + + int shapeWidth = READ_LE_UINT16(src); src += 2; + int scaledShapeWidth = (shapeWidth * scale_w) >> 8; + if (scaledShapeWidth == 0) { + va_end(args); + return; + } + + if (flags & 0x20) { + x -= scaledShapeWidth >> 1; + y -= scaledShapeHeight >> 1; + } + + src += 3; + + uint16 frameSize = READ_LE_UINT16(src); src += 2; + int colorTableColors = 0x10; + + if (shapeFlags & 4) + colorTableColors = *src++; + + if (!(flags & 0x8000) && (shapeFlags & 1)) + table2 = src; + + if ((shapeFlags & 1) || (flags & 0x400)) + src += colorTableColors; + + if (!(shapeFlags & 2)) { + decodeFrame4(src, _animBlockPtr, frameSize); + src = _animBlockPtr; + } + + int shapeSize = shapeWidth * shapeHeight; + if (_decodeShapeBufferSize < shapeSize) { + delete [] _decodeShapeBuffer; + _decodeShapeBuffer = new uint8[shapeSize]; + _decodeShapeBufferSize = shapeSize; + } + if (!_decodeShapeBuffer) { + _decodeShapeBufferSize = 0; + va_end(args); + return; + } + memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize); + uint8 *decodedShapeFrame = _decodeShapeBuffer; + + for (int j = 0; j < shapeHeight; ++j) { + uint8 *dsbNextLine = decodedShapeFrame + shapeWidth; + int count = shapeWidth; + while (count > 0) { + uint8 code = *src++; + if (code != 0) { + *decodedShapeFrame++ = code; + --count; + } else { + code = *src++; + decodedShapeFrame += code; + count -= code; + } + } + decodedShapeFrame = dsbNextLine; + } + + uint16 sx1 = getScreenDim(sd)->sx << 3; + uint16 sy1 = getScreenDim(sd)->sy; + uint16 sx2 = sx1 + (getScreenDim(sd)->w << 3); + uint16 sy2 = sy1 + getScreenDim(sd)->h; + if (flags & 0x10) { + x += sx1; + y += sy1; + } + + int x1, x2; + if (x >= 0) { + x1 = 0; + if (x + scaledShapeWidth < sx2) { + x2 = scaledShapeWidth; + } else { + x2 = sx2 - x; + } + } else { + x2 = scaledShapeWidth; + x1 = -x; + x = 0; + if (x2 > sx2) { + x2 = sx2; + } + } + + int y1, y2; + if (y >= 0) { + y1 = 0; + if (y + scaledShapeHeight < sy2) { + y2 = scaledShapeHeight; + } else { + y2 = sy2 - y; + } + } else { + y2 = scaledShapeHeight; + y1 = -y; + y = 0; + if (y2 > sy2) { + y2 = sy2; + } + } + + uint8 *dst = getPagePtr(page) + y * 320 + x; + uint8 *dstStart = getPagePtr(page); + + int scaleYTable[200]; + for (y = y1; y < y2; ++y) { + scaleYTable[y] = (y << 8) / scale_h; + } + int scaleXTable[320]; + for (x = x1; x < x2; ++x) { + scaleXTable[x] = (x << 8) / scale_w; + } + + const uint8 *shapeBuffer = _decodeShapeBuffer; + if (flags & 0x02) { + shapeBuffer += shapeWidth * (shapeHeight - 1); + } + if (flags & 0x01) { + shapeBuffer += shapeWidth - 1; + } + + for (y = y1; y < y2; ++y) { + uint8 *dstNextLine = dst + 320; + int j = scaleYTable[y]; + if (flags & 0x02) { + j = -j; + } + for (x = x1; x < x2; ++x) { + int xpos = scaleXTable[x]; + if (flags & 0x01) + xpos = -xpos; + uint8 color = shapeBuffer[j * shapeWidth + xpos]; + if (color != 0) { + switch (ppc) { + case 0: + *dst = color; + break; + + case 4: + *dst = table2[color]; + break; + + case 8: { + int layer = _shapePages[0][dst - dstStart] & 7; + if (drawLayer > layer) + color = _shapePages[1][dst - dstStart]; + *dst = color; + } break; + + case 12: { + int layer = _shapePages[0][dst - dstStart] & 7; + if (drawLayer < layer) + color = _shapePages[1][dst - dstStart]; + else + color = table2[color]; + *dst = color; + } break; + + default: + warning("unhandled ppc: %d", ppc); + break; + } + } + ++dst; + } + dst = dstNextLine; + } + va_end(args); +} + +int Screen_v2::getRectSize(int w, int h) { + if (w > 320 || h > 200) + return 0; + return w*h; +} + +int Screen_v2::getLayer(int x, int y) { + if (x < 0) + x = 0; + else if (x >= 320) + x = 319; + if (y < 0) + y = 0; + else if (y >= 144) + y = 143; + + uint8 pixel = *(getCPagePtr(5) + y * 320 + x); + pixel &= 0x7F; + pixel >>= 3; + + if (pixel < 1) + pixel = 1; + else if (pixel > 15) + pixel = 15; + return pixel; +} + +bool Screen_v2::isMouseVisible() const { + return _mouseLockCount == 0; +} + +} // end of namespace Kyra diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h new file mode 100644 index 0000000000..7912d6b999 --- /dev/null +++ b/engines/kyra/screen_v2.h @@ -0,0 +1,84 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_SCREEN_V2_H +#define KYRA_SCREEN_V2_H + +#include "kyra/screen.h" + +namespace Kyra { + +class KyraEngine_v2; + +class Screen_v2 : public Screen { +public: + Screen_v2(KyraEngine_v2 *vm, OSystem *system); + virtual ~Screen_v2(); + + virtual void setScreenDim(int dim); + const ScreenDim *getScreenDim(int dim); + + // palette handling + void k2IntroFadeToGrey(int delay=0x54); + + // screen page handling + void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); + + // shape handling + uint8 *getPtrToShape(uint8 *shpFile, int shape); + const uint8 *getPtrToShape(const uint8 *shpFile, int shape); + + int getShapeScaledWidth(const uint8 *shpFile, int scale); + int getShapeScaledHeight(const uint8 *shpFile, int scale); + + uint16 getShapeSize(const uint8 *shp); + + uint8 *makeShapeCopy(const uint8 *src, int index); + + void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...); + + // rect handling + virtual int getRectSize(int w, int h); + + // layer handling + int getLayer(int x, int y); + + // mouse handling + bool isMouseVisible() const; +private: + KyraEngine_v2 *_vm; + + static const ScreenDim _screenDimTable[]; + static const int _screenDimTableCount; + + // maybe subclass screen for kyra3 + static const ScreenDim _screenDimTableK3[]; + static const int _screenDimTableCountK3; +}; + +} // End of namespace Kyra + +#endif diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index b43cd3b471..5966fa2c25 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -40,64 +40,62 @@ namespace Kyra { ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) { #define COMMAND(x) { &ScriptHelper::x, #x } - // now we create a list of all Command/Opcode procs and so static CommandEntry commandProcs[] = { // 0x00 - COMMAND(c1_jmpTo), - COMMAND(c1_setRetValue), - COMMAND(c1_pushRetOrPos), - COMMAND(c1_push), + COMMAND(cmd_jmpTo), + COMMAND(cmd_setRetValue), + COMMAND(cmd_pushRetOrPos), + COMMAND(cmd_push), // 0x04 - COMMAND(c1_push), - COMMAND(c1_pushReg), - COMMAND(c1_pushBPNeg), - COMMAND(c1_pushBPAdd), + COMMAND(cmd_push), + COMMAND(cmd_pushReg), + COMMAND(cmd_pushBPNeg), + COMMAND(cmd_pushBPAdd), // 0x08 - COMMAND(c1_popRetOrPos), - COMMAND(c1_popReg), - COMMAND(c1_popBPNeg), - COMMAND(c1_popBPAdd), + COMMAND(cmd_popRetOrPos), + COMMAND(cmd_popReg), + COMMAND(cmd_popBPNeg), + COMMAND(cmd_popBPAdd), // 0x0C - COMMAND(c1_addSP), - COMMAND(c1_subSP), - COMMAND(c1_execOpcode), - COMMAND(c1_ifNotJmp), + COMMAND(cmd_addSP), + COMMAND(cmd_subSP), + COMMAND(cmd_execOpcode), + COMMAND(cmd_ifNotJmp), // 0x10 - COMMAND(c1_negate), - COMMAND(c1_eval), - COMMAND(c1_setRetAndJmp) + COMMAND(cmd_negate), + COMMAND(cmd_eval), + COMMAND(cmd_setRetAndJmp) }; _commands = commandProcs; #undef COMMAND } bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, const Common::Array<const Opcode*> *opcodes) { - uint32 size = 0; - uint8 *data = _vm->resource()->fileData(filename, &size); - const byte *curData = data; + ScriptFileParser file(filename, _vm->resource()); + if (!file) { + error("Couldn't open script file '%s'", filename); + return false; + } - uint32 formBlockSize = getFORMBlockSize(curData); + uint32 formBlockSize = file.getFORMBlockSize(); if (formBlockSize == (uint32)-1) { - delete [] data; error("No FORM chunk found in file: '%s'", filename); return false; } - uint32 chunkSize = getIFFBlockSize(data, curData, size, TEXT_CHUNK); + uint32 chunkSize = file.getIFFBlockSize(TEXT_CHUNK); if (chunkSize != (uint32)-1) { scriptData->text = new byte[chunkSize]; - if (!loadIFFBlock(data, curData, size, TEXT_CHUNK, scriptData->text, chunkSize)) { - delete [] data; + if (!file.loadIFFBlock(TEXT_CHUNK, scriptData->text, chunkSize)) { unloadScript(scriptData); error("Couldn't load TEXT chunk from file: '%s'", filename); return false; } } - chunkSize = getIFFBlockSize(data, curData, size, ORDR_CHUNK); + chunkSize = file.getIFFBlockSize(ORDR_CHUNK); if (chunkSize == (uint32)-1) { - delete [] data; unloadScript(scriptData); error("No ORDR chunk found in file: '%s'", filename); return false; @@ -106,8 +104,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons scriptData->ordr = new uint16[chunkSize]; - if (!loadIFFBlock(data, curData, size, ORDR_CHUNK, scriptData->ordr, chunkSize << 1)) { - delete [] data; + if (!file.loadIFFBlock(ORDR_CHUNK, scriptData->ordr, chunkSize << 1)) { unloadScript(scriptData); error("Couldn't load ORDR chunk from file: '%s'", filename); return false; @@ -116,9 +113,8 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons while (chunkSize--) scriptData->ordr[chunkSize] = READ_BE_UINT16(&scriptData->ordr[chunkSize]); - chunkSize = getIFFBlockSize(data, curData, size, DATA_CHUNK); + chunkSize = file.getIFFBlockSize(DATA_CHUNK); if (chunkSize == (uint32)-1) { - delete [] data; unloadScript(scriptData); error("No DATA chunk found in file: '%s'", filename); return false; @@ -127,8 +123,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons scriptData->data = new uint16[chunkSize]; - if (!loadIFFBlock(data, curData, size, DATA_CHUNK, scriptData->data, chunkSize << 1)) { - delete [] data; + if (!file.loadIFFBlock(DATA_CHUNK, scriptData->data, chunkSize << 1)) { unloadScript(scriptData); error("Couldn't load DATA chunk from file: '%s'", filename); return false; @@ -139,8 +134,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons scriptData->data[chunkSize] = READ_BE_UINT16(&scriptData->data[chunkSize]); scriptData->opcodes = opcodes; - - delete [] data; + return true; } @@ -172,10 +166,14 @@ bool ScriptHelper::startScript(ScriptState *script, int function) { if (functionOffset == 0xFFFF) return false; - if (_vm->gameFlags().platform == Common::kPlatformFMTowns) + if (_vm->game() == GI_KYRA1) { + if (_vm->gameFlags().platform == Common::kPlatformFMTowns) + script->ip = &script->dataPtr->data[functionOffset+1]; + else + script->ip = &script->dataPtr->data[functionOffset]; + } else { script->ip = &script->dataPtr->data[functionOffset+1]; - else - script->ip = &script->dataPtr->data[functionOffset]; + } return true; } @@ -217,37 +215,51 @@ bool ScriptHelper::runScript(ScriptState *script) { return _continue; } -uint32 ScriptHelper::getFORMBlockSize(const byte *&data) const { - static const uint32 chunkName = FORM_CHUNK; +#pragma mark - +#pragma mark - ScriptFileParser implementation +#pragma mark - + +void ScriptFileParser::setFile(const char *filename, Resource *res) { + destroy(); + + if (!res->getFileHandle(filename, &_endOffset, _scriptFile)) + return; + _startOffset = _scriptFile.pos(); + _endOffset += _startOffset; +} + +void ScriptFileParser::destroy() { + _scriptFile.close(); + _startOffset = _endOffset = 0; +} + +uint32 ScriptFileParser::getFORMBlockSize() { + uint32 oldOffset = _scriptFile.pos(); + + uint32 data = _scriptFile.readUint32LE(); - if (READ_LE_UINT32(data) != chunkName) + if (data != FORM_CHUNK) { + _scriptFile.seek(oldOffset); return (uint32)-1; + } - data += 4; - uint32 retValue = READ_BE_UINT32(data); data += 4; - return retValue; + data = _scriptFile.readUint32BE(); + return data; } -uint32 ScriptHelper::getIFFBlockSize(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunkName) const { +uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) { uint32 size = (uint32)-1; - bool special = false; - if (data == (start + maxSize)) - data = start + 0x0C; + _scriptFile.seek(_startOffset + 0x0C); - while (data < (start + maxSize)) { - uint32 chunk = READ_LE_UINT32(data); data += 4; - uint32 size_temp = READ_BE_UINT32(data); data += 4; + while (_scriptFile.pos() < _endOffset) { + uint32 chunk = _scriptFile.readUint32LE(); + uint32 size_temp = _scriptFile.readUint32BE(); + if (chunk != chunkName) { - if (special) { - data += (size_temp + 1) & 0xFFFFFFFE; - } else { - data = start + 0x0C; - special = true; - } + _scriptFile.seek((size_temp + 1) & (~1), SEEK_CUR); + assert(_scriptFile.pos() <= _endOffset); } else { - // kill our data - data = start; size = size_temp; break; } @@ -256,32 +268,21 @@ uint32 ScriptHelper::getIFFBlockSize(const byte *start, const byte *&data, uint3 return size; } -bool ScriptHelper::loadIFFBlock(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunkName, void *loadTo, uint32 ptrSize) const { - bool special = false; - - if (data == (start + maxSize)) - data = start + 0x0C; +bool ScriptFileParser::loadIFFBlock(const uint32 chunkName, void *loadTo, uint32 ptrSize) { + _scriptFile.seek(_startOffset + 0x0C); + + while (_scriptFile.pos() < _endOffset) { + uint32 chunk = _scriptFile.readUint32LE(); + uint32 chunkSize = _scriptFile.readUint32BE(); - while (data < (start + maxSize)) { - uint32 chunk = READ_LE_UINT32(data); data += 4; - uint32 chunkSize = READ_BE_UINT32(data); data += 4; if (chunk != chunkName) { - if (special) { - data += (chunkSize + 1) & 0xFFFFFFFE; - } else { - data = start + 0x0C; - special = true; - } + _scriptFile.seek((chunkSize + 1) & (~1), SEEK_CUR); + assert(_scriptFile.pos() <= _endOffset); } else { uint32 loadSize = 0; - if (chunkSize < ptrSize) - loadSize = chunkSize; - else - loadSize = ptrSize; - memcpy(loadTo, data, loadSize); - chunkSize = (chunkSize + 1) & 0xFFFFFFFE; - if (chunkSize > loadSize) - data += (chunkSize - loadSize); + + loadSize = MIN(ptrSize, chunkSize); + _scriptFile.read(loadTo, loadSize); return true; } } @@ -293,15 +294,15 @@ bool ScriptHelper::loadIFFBlock(const byte *start, const byte *&data, uint32 max #pragma mark - Command implementations #pragma mark - -void ScriptHelper::c1_jmpTo(ScriptState* script) { +void ScriptHelper::cmd_jmpTo(ScriptState* script) { script->ip = script->dataPtr->data + _parameter; } -void ScriptHelper::c1_setRetValue(ScriptState* script) { +void ScriptHelper::cmd_setRetValue(ScriptState* script) { script->retValue = _parameter; } -void ScriptHelper::c1_pushRetOrPos(ScriptState* script) { +void ScriptHelper::cmd_pushRetOrPos(ScriptState* script) { switch (_parameter) { case 0: script->stack[--script->sp] = script->retValue; @@ -320,23 +321,23 @@ void ScriptHelper::c1_pushRetOrPos(ScriptState* script) { } } -void ScriptHelper::c1_push(ScriptState* script) { +void ScriptHelper::cmd_push(ScriptState* script) { script->stack[--script->sp] = _parameter; } -void ScriptHelper::c1_pushReg(ScriptState* script) { +void ScriptHelper::cmd_pushReg(ScriptState* script) { script->stack[--script->sp] = script->regs[_parameter]; } -void ScriptHelper::c1_pushBPNeg(ScriptState* script) { +void ScriptHelper::cmd_pushBPNeg(ScriptState* script) { script->stack[--script->sp] = script->stack[(-(int32)(_parameter + 2)) + script->bp]; } -void ScriptHelper::c1_pushBPAdd(ScriptState* script) { +void ScriptHelper::cmd_pushBPAdd(ScriptState* script) { script->stack[--script->sp] = script->stack[(_parameter - 1) + script->bp]; } -void ScriptHelper::c1_popRetOrPos(ScriptState* script) { +void ScriptHelper::cmd_popRetOrPos(ScriptState* script) { switch (_parameter) { case 0: script->retValue = script->stack[script->sp++]; @@ -359,48 +360,48 @@ void ScriptHelper::c1_popRetOrPos(ScriptState* script) { } } -void ScriptHelper::c1_popReg(ScriptState* script) { +void ScriptHelper::cmd_popReg(ScriptState* script) { script->regs[_parameter] = script->stack[script->sp++]; } -void ScriptHelper::c1_popBPNeg(ScriptState* script) { +void ScriptHelper::cmd_popBPNeg(ScriptState* script) { script->stack[(-(int32)(_parameter + 2)) + script->bp] = script->stack[script->sp++]; } -void ScriptHelper::c1_popBPAdd(ScriptState* script) { +void ScriptHelper::cmd_popBPAdd(ScriptState* script) { script->stack[(_parameter - 1) + script->bp] = script->stack[script->sp++]; } -void ScriptHelper::c1_addSP(ScriptState* script) { +void ScriptHelper::cmd_addSP(ScriptState* script) { script->sp += _parameter; } -void ScriptHelper::c1_subSP(ScriptState* script) { +void ScriptHelper::cmd_subSP(ScriptState* script) { script->sp -= _parameter; } -void ScriptHelper::c1_execOpcode(ScriptState* script) { +void ScriptHelper::cmd_execOpcode(ScriptState* script) { uint8 opcode = _parameter; assert(script->dataPtr->opcodes); assert(opcode < script->dataPtr->opcodes->size()); - if ((*script->dataPtr->opcodes)[opcode]) { + if ((*script->dataPtr->opcodes)[opcode] && (bool) *(*script->dataPtr->opcodes)[opcode]) { script->retValue = (*(*script->dataPtr->opcodes)[opcode])(script); } else { script->retValue = 0; - warning("calling unimplemented opcode(0x%.02X)", opcode); + warning("calling unimplemented opcode(0x%.02X/%d)", opcode, opcode); } } -void ScriptHelper::c1_ifNotJmp(ScriptState* script) { +void ScriptHelper::cmd_ifNotJmp(ScriptState* script) { if (!script->stack[script->sp++]) { _parameter &= 0x7FFF; script->ip = script->dataPtr->data + _parameter; } } -void ScriptHelper::c1_negate(ScriptState* script) { +void ScriptHelper::cmd_negate(ScriptState* script) { int16 value = script->stack[script->sp]; switch (_parameter) { case 0: @@ -424,7 +425,7 @@ void ScriptHelper::c1_negate(ScriptState* script) { } } -void ScriptHelper::c1_eval(ScriptState* script) { +void ScriptHelper::cmd_eval(ScriptState* script) { int16 ret = 0; bool error = false; @@ -542,7 +543,7 @@ void ScriptHelper::c1_eval(ScriptState* script) { } } -void ScriptHelper::c1_setRetAndJmp(ScriptState* script) { +void ScriptHelper::cmd_setRetAndJmp(ScriptState* script) { if (script->sp >= 60) { _continue = false; script->ip = 0; diff --git a/engines/kyra/script.h b/engines/kyra/script.h index 5e43039110..3396712a24 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -27,33 +27,11 @@ #define KYRA_SCRIPT_H #include "kyra/kyra.h" +#include "kyra/util.h" -namespace Kyra { - -struct ScriptState; - -struct Opcode { - virtual ~Opcode() {} - - virtual operator bool() const = 0; - - virtual int operator()(ScriptState*) const = 0; -}; +#include "common/file.h" -template<class T> -struct OpcodeImpl : public Opcode { - T *vm; - typedef int (T::*Callback)(ScriptState*); - Callback callback; - - OpcodeImpl(T *v, Callback c) : Opcode(), vm(v), callback(c) {} - - operator bool() const { return callback != 0; } - - int operator()(ScriptState *state) const { - return (vm->*callback)(state); - } -}; +namespace Kyra { struct ScriptData { byte *text; @@ -74,6 +52,31 @@ struct ScriptState { int16 stack[61]; // VM stack }; +#define stackPos(x) script->stack[script->sp+x] +#define stackPosString(x) (const char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])] + +class ScriptFileParser { +public: + ScriptFileParser() : _scriptFile(), _startOffset(0), _endOffset(0) {} + ScriptFileParser(const char *filename, Resource *res) : _scriptFile(), _startOffset(0), _endOffset(0) { setFile(filename, res); } + ~ScriptFileParser() { destroy(); } + + // 'script' must be allocated with new! + void setFile(const char *filename, Resource *res); + + operator bool() const { return (_startOffset != _endOffset) && _scriptFile.isOpen(); } + + uint32 getFORMBlockSize(); + uint32 getIFFBlockSize(const uint32 chunk); + bool loadIFFBlock(const uint32 chunk, void *loadTo, uint32 ptrSize); +private: + void destroy(); + + Common::File _scriptFile; + uint32 _startOffset; + uint32 _endOffset; +}; + class ScriptHelper { public: ScriptHelper(KyraEngine *vm); @@ -88,10 +91,6 @@ public: bool runScript(ScriptState *script); protected: - uint32 getFORMBlockSize(const byte *&data) const; - uint32 getIFFBlockSize(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunk) const; - bool loadIFFBlock(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunk, void *loadTo, uint32 ptrSize) const; - KyraEngine *_vm; int16 _parameter; bool _continue; @@ -104,25 +103,24 @@ protected: const CommandEntry *_commands; private: - void c1_jmpTo(ScriptState*); - void c1_setRetValue(ScriptState*); - void c1_pushRetOrPos(ScriptState*); - void c1_push(ScriptState*); - //void c1_push(); same as 03 - void c1_pushReg(ScriptState*); - void c1_pushBPNeg(ScriptState*); - void c1_pushBPAdd(ScriptState*); - void c1_popRetOrPos(ScriptState*); - void c1_popReg(ScriptState*); - void c1_popBPNeg(ScriptState*); - void c1_popBPAdd(ScriptState*); - void c1_addSP(ScriptState*); - void c1_subSP(ScriptState*); - void c1_execOpcode(ScriptState*); - void c1_ifNotJmp(ScriptState*); - void c1_negate(ScriptState*); - void c1_eval(ScriptState*); - void c1_setRetAndJmp(ScriptState*); + void cmd_jmpTo(ScriptState*); + void cmd_setRetValue(ScriptState*); + void cmd_pushRetOrPos(ScriptState*); + void cmd_push(ScriptState*); + void cmd_pushReg(ScriptState*); + void cmd_pushBPNeg(ScriptState*); + void cmd_pushBPAdd(ScriptState*); + void cmd_popRetOrPos(ScriptState*); + void cmd_popReg(ScriptState*); + void cmd_popBPNeg(ScriptState*); + void cmd_popBPAdd(ScriptState*); + void cmd_addSP(ScriptState*); + void cmd_subSP(ScriptState*); + void cmd_execOpcode(ScriptState*); + void cmd_ifNotJmp(ScriptState*); + void cmd_negate(ScriptState*); + void cmd_eval(ScriptState*); + void cmd_setRetAndJmp(ScriptState*); }; } // end of namespace Kyra diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp index 87123222fb..bd776e2046 100644 --- a/engines/kyra/script_v1.cpp +++ b/engines/kyra/script_v1.cpp @@ -25,21 +25,20 @@ #include "common/stdafx.h" #include "common/endian.h" +#include "common/system.h" + #include "kyra/kyra_v1.h" #include "kyra/script.h" #include "kyra/screen.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" #include "kyra/text.h" -#include "common/system.h" +#include "kyra/timer.h" namespace Kyra { -#define stackPos(x) script->stack[script->sp+x] -#define stackPosString(x) (const char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])] - int KyraEngine_v1::o1_magicInMouseItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); magicInMouseItem(stackPos(0), stackPos(1), -1); return 0; } @@ -47,10 +46,10 @@ int KyraEngine_v1::o1_magicInMouseItem(ScriptState *script) { int KyraEngine_v1::o1_characterSays(ScriptState *script) { _skipFlag = false; if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "o1_characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); characterSays(stackPos(0), stackPosString(1), stackPos(2), stackPos(3)); } else { - debugC(3, kDebugLevelScriptFuncs, "o1_characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2)); const char *string = stackPosString(0); if (_flags.platform == Common::kPlatformFMTowns && _flags.lang == Common::JA_JPN) { @@ -76,7 +75,7 @@ int KyraEngine_v1::o1_characterSays(ScriptState *script) { } int KyraEngine_v1::o1_pauseTicks(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_pauseTicks(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseTicks(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); if (stackPos(1)) { warning("STUB: special o1_pauseTicks"); // delete this after correct implementing @@ -88,23 +87,23 @@ int KyraEngine_v1::o1_pauseTicks(ScriptState *script) { } int KyraEngine_v1::o1_drawSceneAnimShape(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); _screen->drawShape(stackPos(4), _sprites->_sceneShapes[stackPos(0)], stackPos(1), stackPos(2), 0, (stackPos(3) != 0) ? 1 : 0); return 0; } int KyraEngine_v1::o1_queryGameFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); return queryGameFlag(stackPos(0)); } int KyraEngine_v1::o1_setGameFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); return setGameFlag(stackPos(0)); } int KyraEngine_v1::o1_resetGameFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_resetGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetGameFlag(%p) (0x%X)", (const void *)script, stackPos(0)); return resetGameFlag(stackPos(0)); } @@ -114,7 +113,7 @@ int KyraEngine_v1::o1_runNPCScript(ScriptState *script) { } int KyraEngine_v1::o1_setSpecialExitList(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); for (int i = 0; i < 10; ++i) _exitList[i] = stackPos(i); @@ -124,33 +123,33 @@ int KyraEngine_v1::o1_setSpecialExitList(ScriptState *script) { } int KyraEngine_v1::o1_blockInWalkableRegion(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); _screen->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); return 0; } int KyraEngine_v1::o1_blockOutWalkableRegion(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); _screen->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1); return 0; } int KyraEngine_v1::o1_walkPlayerToPoint(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int normalTimers = stackPos(2); if (!normalTimers) { - disableTimer(19); - disableTimer(14); - disableTimer(18); + _timer->disable(19); + _timer->disable(14); + _timer->disable(18); } int reinitScript = handleSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); if (!normalTimers) { - enableTimer(19); - enableTimer(14); - enableTimer(18); + _timer->enable(19); + _timer->enable(14); + _timer->enable(18); } if (reinitScript) @@ -164,7 +163,7 @@ int KyraEngine_v1::o1_walkPlayerToPoint(ScriptState *script) { } int KyraEngine_v1::o1_dropItemInScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); int item = stackPos(0); int xpos = stackPos(1); int ypos = stackPos(2); @@ -189,7 +188,7 @@ int KyraEngine_v1::o1_dropItemInScene(ScriptState *script) { } int KyraEngine_v1::o1_drawAnimShapeIntoScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); _screen->hideMouse(); _animator->restoreAllObjectBackgrounds(); int shape = stackPos(0); @@ -207,49 +206,49 @@ int KyraEngine_v1::o1_drawAnimShapeIntoScene(ScriptState *script) { } int KyraEngine_v1::o1_createMouseItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_createMouseItem(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1createMouseItem(%p) (%d)", (const void *)script, stackPos(0)); createMouseItem(stackPos(0)); return 0; } int KyraEngine_v1::o1_savePageToDisk(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); _screen->savePageToDisk(stackPosString(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_sceneAnimOn(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0)); _sprites->_anims[stackPos(0)].play = true; return 0; } int KyraEngine_v1::o1_sceneAnimOff(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0)); _sprites->_anims[stackPos(0)].play = false; return 0; } int KyraEngine_v1::o1_getElapsedSeconds(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getElapsedSeconds(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getElapsedSeconds(%p) ()", (const void *)script); return _system->getMillis() / 1000; } int KyraEngine_v1::o1_mouseIsPointer(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_mouseIsPointer(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1mouseIsPointer(%p) ()", (const void *)script); if (_itemInHand == -1) return 1; return 0; } int KyraEngine_v1::o1_destroyMouseItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_destroyMouseItem(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1destroyMouseItem(%p) ()", (const void *)script); destroyMouseItem(); return 0; } int KyraEngine_v1::o1_runSceneAnimUntilDone(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0)); _screen->hideMouse(); _animator->restoreAllObjectBackgrounds(); _sprites->_anims[stackPos(0)].play = true; @@ -268,59 +267,59 @@ int KyraEngine_v1::o1_runSceneAnimUntilDone(ScriptState *script) { int KyraEngine_v1::o1_fadeSpecialPalette(ScriptState *script) { if (_flags.platform == Common::kPlatformAmiga) { - debugC(3, kDebugLevelScriptFuncs, "o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); if (_currentCharacter->sceneId != 45) { if (stackPos(0) == 13) { memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3); _screen->setScreenPalette(_screen->getPalette(0)); } } else { - warning("o1_fadeSpecialPalette not implemented"); + warning("KyraEngine_v1::o1fadeSpecialPalette not implemented"); } } else { - debugC(3, kDebugLevelScriptFuncs, "o1_fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); _screen->fadeSpecialPalette(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); } return 0; } int KyraEngine_v1::o1_playAdlibSound(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_playAdlibSound(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playAdlibSound(%p) (%d)", (const void *)script, stackPos(0)); snd_playSoundEffect(stackPos(0)); return 0; } int KyraEngine_v1::o1_playAdlibScore(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_playAdlibScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playAdlibScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); snd_playWanderScoreViaMap(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_phaseInSameScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); transcendScenes(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_setScenePhasingFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setScenePhasingFlag(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScenePhasingFlag(%p) ()", (const void *)script); _scenePhasingFlag = 1; return 1; } int KyraEngine_v1::o1_resetScenePhasingFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_resetScenePhasingFlag(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetScenePhasingFlag(%p) ()", (const void *)script); _scenePhasingFlag = 0; return 0; } int KyraEngine_v1::o1_queryScenePhasingFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_queryScenePhasingFlag(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryScenePhasingFlag(%p) ()", (const void *)script); return _scenePhasingFlag; } int KyraEngine_v1::o1_sceneToDirection(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < _roomTableSize); Room *curRoom = &_roomTable[stackPos(0)]; uint16 returnValue = 0xFFFF; @@ -350,7 +349,7 @@ int KyraEngine_v1::o1_sceneToDirection(ScriptState *script) { } int KyraEngine_v1::o1_setBirthstoneGem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int index = stackPos(0); if (index < 4 && index >= 0) { _birthstoneGemTable[index] = stackPos(1); @@ -360,19 +359,19 @@ int KyraEngine_v1::o1_setBirthstoneGem(ScriptState *script) { } int KyraEngine_v1::o1_placeItemInGenericMapScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); placeItemInGenericMapScene(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_setBrandonStatusBit(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); _brandonStatusBit |= stackPos(0); return 0; } int KyraEngine_v1::o1_pauseSeconds(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_pauseSeconds(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseSeconds(%p) (%d)", (const void *)script, stackPos(0)); if (stackPos(0) > 0 && !_skipFlag) delay(stackPos(0)*1000, true); _skipFlag = false; @@ -380,7 +379,7 @@ int KyraEngine_v1::o1_pauseSeconds(ScriptState *script) { } int KyraEngine_v1::o1_getCharactersLocation(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersLocation(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersLocation(%p) (%d)", (const void *)script, stackPos(0)); return _characterList[stackPos(0)].sceneId; } @@ -390,31 +389,31 @@ int KyraEngine_v1::o1_runNPCSubscript(ScriptState *script) { } int KyraEngine_v1::o1_magicOutMouseItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0)); magicOutMouseItem(stackPos(0), -1); return 0; } int KyraEngine_v1::o1_internalAnimOn(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_internalAnimOn(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1internalAnimOn(%p) (%d)", (const void *)script, stackPos(0)); _animator->sprites()[stackPos(0)].active = 1; return 0; } int KyraEngine_v1::o1_forceBrandonToNormal(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_forceBrandonToNormal(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1forceBrandonToNormal(%p) ()", (const void *)script); checkAmuletAnimFlags(); return 0; } int KyraEngine_v1::o1_poisonDeathNow(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_poisonDeathNow(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1poisonDeathNow(%p) ()", (const void *)script); seq_poisonDeathNow(1); return 0; } int KyraEngine_v1::o1_setScaleMode(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int len = stackPos(0); int setValue1 = stackPos(1); int start2 = stackPos(2); @@ -432,7 +431,7 @@ int KyraEngine_v1::o1_setScaleMode(ScriptState *script) { } int KyraEngine_v1::o1_openWSAFile(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3)); const char *filename = stackPosString(0); int wsaIndex = stackPos(1); @@ -444,7 +443,7 @@ int KyraEngine_v1::o1_openWSAFile(ScriptState *script) { } int KyraEngine_v1::o1_closeWSAFile(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_closeWSAFile(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1closeWSAFile(%p) (%d)", (const void *)script, stackPos(0)); int wsaIndex = stackPos(0); if (_movieObjects[wsaIndex]) @@ -454,7 +453,7 @@ int KyraEngine_v1::o1_closeWSAFile(ScriptState *script) { } int KyraEngine_v1::o1_runWSAFromBeginningToEnd(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); _screen->hideMouse(); @@ -495,7 +494,7 @@ int KyraEngine_v1::o1_runWSAFromBeginningToEnd(ScriptState *script) { } int KyraEngine_v1::o1_displayWSAFrame(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); int frame = stackPos(0); int xpos = stackPos(1); int ypos = stackPos(2); @@ -522,13 +521,13 @@ int KyraEngine_v1::o1_displayWSAFrame(ScriptState *script) { } int KyraEngine_v1::o1_enterNewScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); enterNewScene(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); return 0; } int KyraEngine_v1::o1_setSpecialEnterXAndY(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _brandonPosX = stackPos(0); _brandonPosY = stackPos(1); if (_brandonPosX + 1 == 0 && _brandonPosY + 1 == 0) @@ -537,7 +536,7 @@ int KyraEngine_v1::o1_setSpecialEnterXAndY(ScriptState *script) { } int KyraEngine_v1::o1_runWSAFrames(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int xpos = stackPos(0); int ypos = stackPos(1); int delayTime = stackPos(2); @@ -564,7 +563,7 @@ int KyraEngine_v1::o1_runWSAFrames(ScriptState *script) { } int KyraEngine_v1::o1_popBrandonIntoScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int changeScaleMode = stackPos(3); int xpos = (int16)(stackPos(0) & 0xFFFC); int ypos = (int16)(stackPos(1) & 0xFFFE); @@ -613,7 +612,7 @@ int KyraEngine_v1::o1_popBrandonIntoScene(ScriptState *script) { } int KyraEngine_v1::o1_restoreAllObjectBackgrounds(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0)); int disable = stackPos(0); int activeBackup = 0; if (disable) { @@ -627,13 +626,13 @@ int KyraEngine_v1::o1_restoreAllObjectBackgrounds(ScriptState *script) { } int KyraEngine_v1::o1_setCustomPaletteRange(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3); return 0; } int KyraEngine_v1::o1_loadPageFromDisk(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); _screen->loadPageFromDisk(stackPosString(0), stackPos(1)); _animator->_updateScreen = true; return 0; @@ -641,7 +640,7 @@ int KyraEngine_v1::o1_loadPageFromDisk(ScriptState *script) { int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) { if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "o1_customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF); if (speechEnabled()) { snd_voiceWaitForFinish(); @@ -651,7 +650,7 @@ int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) { if (textEnabled()) _text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2); } else { - debugC(3, kDebugLevelScriptFuncs, "o1_customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF); _skipFlag = false; _text->printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2); } @@ -660,7 +659,7 @@ int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) { } int KyraEngine_v1::o1_restoreCustomPrintBackground(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_restoreCustomPrintBackground(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreCustomPrintBackground(%p) ()", (const void *)script); snd_voiceWaitForFinish(); snd_stopVoice(); _text->restoreTalkTextMessageBkgd(2, 0); @@ -668,29 +667,29 @@ int KyraEngine_v1::o1_restoreCustomPrintBackground(ScriptState *script) { } int KyraEngine_v1::o1_hideMouse(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_hideMouse(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1hideMouse(%p) ()", (const void *)script); _screen->hideMouse(); return 0; } int KyraEngine_v1::o1_showMouse(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_showMouse(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1showMouse(%p) ()", (const void *)script); _screen->showMouse(); return 0; } int KyraEngine_v1::o1_getCharacterX(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getCharacterX(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharacterX(%p) (%d)", (const void *)script, stackPos(0)); return _characterList[stackPos(0)].x1; } int KyraEngine_v1::o1_getCharacterY(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getCharacterY(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharacterY(%p) (%d)", (const void *)script, stackPos(0)); return _characterList[stackPos(0)].y1; } int KyraEngine_v1::o1_changeCharactersFacing(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_changeCharactersFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1changeCharactersFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); int character = stackPos(0); int facing = stackPos(1); int newAnimFrame = stackPos(2); @@ -708,7 +707,7 @@ int KyraEngine_v1::o1_changeCharactersFacing(ScriptState *script) { } int KyraEngine_v1::o1_copyWSARegion(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int xpos = stackPos(0); int ypos = stackPos(1); int width = stackPos(2); @@ -721,7 +720,7 @@ int KyraEngine_v1::o1_copyWSARegion(ScriptState *script) { } int KyraEngine_v1::o1_printText(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); if (_flags.lang == Common::JA_JPN && stackPos(3) == 7) _screen->printText(stackPosString(0), stackPos(1), stackPos(2), 0, 0x80); else @@ -731,7 +730,7 @@ int KyraEngine_v1::o1_printText(ScriptState *script) { } int KyraEngine_v1::o1_random(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_random(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1random(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < stackPos(1)); return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); } @@ -742,7 +741,7 @@ int KyraEngine_v1::o1_loadSoundFile(ScriptState *script) { } int KyraEngine_v1::o1_displayWSAFrameOnHidPage(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); int frame = stackPos(0); int xpos = stackPos(1); int ypos = stackPos(2); @@ -771,7 +770,7 @@ int KyraEngine_v1::o1_displayWSAFrameOnHidPage(ScriptState *script) { } int KyraEngine_v1::o1_displayWSASequentialFrames(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6)); int startFrame = stackPos(0); int endFrame = stackPos(1); int xpos = stackPos(2); @@ -847,7 +846,7 @@ int KyraEngine_v1::o1_displayWSASequentialFrames(ScriptState *script) { } int KyraEngine_v1::o1_drawCharacterStanding(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_drawCharacterStanding(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawCharacterStanding(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int character = stackPos(0); int animFrame = stackPos(1); int newFacing = stackPos(2); @@ -862,13 +861,13 @@ int KyraEngine_v1::o1_drawCharacterStanding(ScriptState *script) { } int KyraEngine_v1::o1_internalAnimOff(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_internalAnimOff(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1internalAnimOff(%p) (%d)", (const void *)script, stackPos(0)); _animator->sprites()[stackPos(0)].active = 0; return 0; } int KyraEngine_v1::o1_changeCharactersXAndY(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); Character *ch = &_characterList[stackPos(0)]; int16 x = stackPos(1); int16 y = stackPos(2); @@ -884,25 +883,25 @@ int KyraEngine_v1::o1_changeCharactersXAndY(ScriptState *script) { } int KyraEngine_v1::o1_clearSceneAnimatorBeacon(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_clearSceneAnimatorBeacon(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1clearSceneAnimatorBeacon(%p) ()", (const void *)script); _sprites->_sceneAnimatorBeaconFlag = 0; return 0; } int KyraEngine_v1::o1_querySceneAnimatorBeacon(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_querySceneAnimatorBeacon(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1querySceneAnimatorBeacon(%p) ()", (const void *)script); return _sprites->_sceneAnimatorBeaconFlag; } int KyraEngine_v1::o1_refreshSceneAnimator(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_refreshSceneAnimator(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1refreshSceneAnimator(%p) ()", (const void *)script); _sprites->updateSceneAnims(); _animator->updateAllObjectShapes(); return 0; } int KyraEngine_v1::o1_placeItemInOffScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int item = stackPos(0); int xpos = stackPos(1); int ypos = stackPos(2); @@ -921,7 +920,7 @@ int KyraEngine_v1::o1_placeItemInOffScene(ScriptState *script) { } int KyraEngine_v1::o1_wipeDownMouseItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); _screen->hideMouse(); wipeDownMouseItem(stackPos(1), stackPos(2)); destroyMouseItem(); @@ -930,7 +929,7 @@ int KyraEngine_v1::o1_wipeDownMouseItem(ScriptState *script) { } int KyraEngine_v1::o1_placeCharacterInOtherScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int id = stackPos(0); int sceneId = stackPos(1); int xpos = (int16)(stackPos(2) & 0xFFFC); @@ -947,7 +946,7 @@ int KyraEngine_v1::o1_placeCharacterInOtherScene(ScriptState *script) { } int KyraEngine_v1::o1_getKey(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getKey(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getKey(%p) ()", (const void *)script); waitForEvent(); return 0; } @@ -958,7 +957,7 @@ int KyraEngine_v1::o1_specificItemInInventory(ScriptState *script) { } int KyraEngine_v1::o1_popMobileNPCIntoScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE)); int character = stackPos(0); int sceneId = stackPos(1); int animFrame = stackPos(2); @@ -994,7 +993,7 @@ int KyraEngine_v1::o1_unhideMobileCharacter(ScriptState *script) { } int KyraEngine_v1::o1_setCharactersLocation(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); Character *ch = &_characterList[stackPos(0)]; AnimObject *animObj = &_animator->actors()[stackPos(0)]; int newScene = stackPos(1); @@ -1011,7 +1010,7 @@ int KyraEngine_v1::o1_setCharactersLocation(ScriptState *script) { } int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); int character = stackPos(0); int toX = stackPos(1); int toY = stackPos(2); @@ -1078,11 +1077,11 @@ int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) { setCharacterPosition(character, 0); ++curPos; - nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis(); + nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis(); while (_system->getMillis() < nextFrame) { _sprites->updateSceneAnims(); updateMousePointer(); - updateGameTimers(); + _timer->update(); _animator->updateAllObjectShapes(); updateTextFade(); if ((nextFrame - _system->getMillis()) >= 10) @@ -1093,12 +1092,12 @@ int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) { } int KyraEngine_v1::o1_specialEventDisplayBrynnsNote(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_specialEventDisplayBrynnsNote(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1specialEventDisplayBrynnsNote(%p) ()", (const void *)script); _screen->hideMouse(); _screen->savePageToDisk("HIDPAGE.TMP", 2); _screen->savePageToDisk("SEENPAGE.TMP", 0); if (_flags.isTalkie) { - if (_flags.lang == Common::EN_ANY) + if (_flags.lang == Common::EN_ANY || _flags.lang == Common::IT_ITA) _screen->loadBitmap("NOTEENG.CPS", 3, 3, 0); else if (_flags.lang == Common::FR_FRA) _screen->loadBitmap("NOTEFRE.CPS", 3, 3, 0); @@ -1115,7 +1114,7 @@ int KyraEngine_v1::o1_specialEventDisplayBrynnsNote(ScriptState *script) { } int KyraEngine_v1::o1_specialEventRemoveBrynnsNote(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_specialEventRemoveBrynnsNote(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1specialEventRemoveBrynnsNote(%p) ()", (const void *)script); _screen->hideMouse(); _screen->loadPageFromDisk("SEENPAGE.TMP", 0); _screen->loadPageFromDisk("HIDPAGE.TMP", 2); @@ -1126,13 +1125,13 @@ int KyraEngine_v1::o1_specialEventRemoveBrynnsNote(ScriptState *script) { } int KyraEngine_v1::o1_setLogicPage(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setLogicPage(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setLogicPage(%p) (%d)", (const void *)script, stackPos(0)); _screen->_curPage = stackPos(0); return stackPos(0); } int KyraEngine_v1::o1_fatPrint(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); // Workround for bug #1582672 ("KYRA1: Text crippled and drawn wrong") // I'm not sure how the original handels this, since it seems to call @@ -1145,13 +1144,13 @@ int KyraEngine_v1::o1_fatPrint(ScriptState *script) { } int KyraEngine_v1::o1_preserveAllObjectBackgrounds(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_preserveAllObjectBackgrounds(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1preserveAllObjectBackgrounds(%p) ()", (const void *)script); _animator->preserveAllBackgrounds(); return 0; } int KyraEngine_v1::o1_updateSceneAnimations(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0)); int times = stackPos(0); while (times--) { _sprites->updateSceneAnims(); @@ -1161,23 +1160,23 @@ int KyraEngine_v1::o1_updateSceneAnimations(ScriptState *script) { } int KyraEngine_v1::o1_sceneAnimationActive(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0)); return _sprites->_anims[stackPos(0)].play; } int KyraEngine_v1::o1_setCharactersMovementDelay(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - setTimerDelay(stackPos(0)+5, stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _timer->setDelay(stackPos(0)+5, stackPos(1)); return 0; } int KyraEngine_v1::o1_getCharactersFacing(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersFacing(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersFacing(%p) (%d)", (const void *)script, stackPos(0)); return _characterList[stackPos(0)].facing; } int KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0)); _screen->copyBackgroundBlock(stackPos(0), 2, 0); _screen->copyBackgroundBlock2(stackPos(0)); // update the whole screen @@ -1187,13 +1186,13 @@ int KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(ScriptState *script) { } int KyraEngine_v1::o1_dispelMagicAnimation(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_dispelMagicAnimation(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dispelMagicAnimation(%p) ()", (const void *)script); seq_dispelMagicAnimation(); return 0; } int KyraEngine_v1::o1_findBrightestFireberry(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_findBrightestFireberry(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1findBrightestFireberry(%p) ()", (const void *)script); if (_currentCharacter->sceneId >= 187 && _currentCharacter->sceneId <= 198) return 29; @@ -1237,7 +1236,7 @@ int KyraEngine_v1::o1_findBrightestFireberry(ScriptState *script) { } int KyraEngine_v1::o1_setFireberryGlowPalette(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0)); int palIndex = 0; switch (stackPos(0)) { case 0x1E: @@ -1274,19 +1273,19 @@ int KyraEngine_v1::o1_setFireberryGlowPalette(ScriptState *script) { } int KyraEngine_v1::o1_setDeathHandlerFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0)); _deathHandler = stackPos(0); return 0; } int KyraEngine_v1::o1_drinkPotionAnimation(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); seq_playDrinkPotionAnim(stackPos(0), stackPos(1), stackPos(2)); return 0; } int KyraEngine_v1::o1_makeAmuletAppear(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_makeAmuletAppear(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1makeAmuletAppear(%p) ()", (const void *)script); WSAMovieV1 amulet(this); amulet.open("AMULET.WSA", 1, 0); amulet.setX(224); @@ -1327,7 +1326,7 @@ int KyraEngine_v1::o1_makeAmuletAppear(ScriptState *script) { } int KyraEngine_v1::o1_drawItemShapeIntoScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); int item = stackPos(0); int x = stackPos(1); int y = stackPos(2); @@ -1354,13 +1353,13 @@ int KyraEngine_v1::o1_drawItemShapeIntoScene(ScriptState *script) { } int KyraEngine_v1::o1_setCharactersCurrentFrame(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _characterList[stackPos(0)].currentAnimFrame = stackPos(1); return 0; } int KyraEngine_v1::o1_waitForConfirmationMouseClick(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_waitForConfirmationMouseClick(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1waitForConfirmationMouseClick(%p) ()", (const void *)script); // if (mouseEnabled) { while (!_mousePressFlag) { updateMousePointer(); @@ -1390,18 +1389,18 @@ int KyraEngine_v1::o1_pageFlip(ScriptState *script) { } int KyraEngine_v1::o1_setSceneFile(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); setSceneFile(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_getItemInMarbleVase(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getItemInMarbleVase(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getItemInMarbleVase(%p) ()", (const void *)script); return _marbleVaseItem; } int KyraEngine_v1::o1_setItemInMarbleVase(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0)); _marbleVaseItem = stackPos(0); return 0; } @@ -1417,7 +1416,7 @@ int KyraEngine_v1::o1_intPrint(ScriptState *script) { } int KyraEngine_v1::o1_shakeScreen(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int waitTicks = stackPos(1); int times = stackPos(0); @@ -1430,57 +1429,57 @@ int KyraEngine_v1::o1_shakeScreen(ScriptState *script) { } int KyraEngine_v1::o1_createAmuletJewel(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0)); seq_createAmuletJewel(stackPos(0), 0, 0, 0); return 0; } int KyraEngine_v1::o1_setSceneAnimCurrXY(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); _sprites->_anims[stackPos(0)].x = stackPos(1); _sprites->_anims[stackPos(0)].y = stackPos(2); return 0; } int KyraEngine_v1::o1_poisonBrandonAndRemaps(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_poisonBrandonAndRemaps(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1poisonBrandonAndRemaps(%p) ()", (const void *)script); setBrandonPoisonFlags(1); return 0; } int KyraEngine_v1::o1_fillFlaskWithWater(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); seq_fillFlaskWithWater(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_getCharactersMovementDelay(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersMovementDelay(%p) (%d)", (const void *)script, stackPos(0)); - return getTimerDelay(stackPos(0)+5); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersMovementDelay(%p) (%d)", (const void *)script, stackPos(0)); + return _timer->getDelay(stackPos(0)+5); } int KyraEngine_v1::o1_getBirthstoneGem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0)); if (stackPos(0) < 4) return _birthstoneGemTable[stackPos(0)]; return 0; } int KyraEngine_v1::o1_queryBrandonStatusBit(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0)); if (_brandonStatusBit & stackPos(0)) return 1; return 0; } int KyraEngine_v1::o1_playFluteAnimation(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_playFluteAnimation(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playFluteAnimation(%p) ()", (const void *)script); seq_playFluteAnimation(); return 0; } int KyraEngine_v1::o1_playWinterScrollSequence(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0)); if (!stackPos(0)) seq_winterScroll2(); else @@ -1489,40 +1488,40 @@ int KyraEngine_v1::o1_playWinterScrollSequence(ScriptState *script) { } int KyraEngine_v1::o1_getIdolGem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getIdolGem(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getIdolGem(%p) (%d)", (const void *)script, stackPos(0)); return _idolGemsTable[stackPos(0)]; } int KyraEngine_v1::o1_setIdolGem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _idolGemsTable[stackPos(0)] = stackPos(1); return 0; } int KyraEngine_v1::o1_totalItemsInScene(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0)); return countItemsInScene(stackPos(0)); } int KyraEngine_v1::o1_restoreBrandonsMovementDelay(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_restoreBrandonsMovementDelay(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreBrandonsMovementDelay(%p) ()", (const void *)script); setWalkspeed(_configWalkspeed); return 0; } int KyraEngine_v1::o1_setMousePos(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _system->warpMouse(stackPos(0), stackPos(1)); return 0; } int KyraEngine_v1::o1_getMouseState(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getMouseState(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getMouseState(%p) ()", (const void *)script); return _mouseState; } int KyraEngine_v1::o1_setEntranceMouseCursorTrack(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); _entranceMouseCursorTracks[0] = stackPos(0); _entranceMouseCursorTracks[1] = stackPos(1); _entranceMouseCursorTracks[2] = stackPos(0) + stackPos(2) - 1; @@ -1532,19 +1531,19 @@ int KyraEngine_v1::o1_setEntranceMouseCursorTrack(ScriptState *script) { } int KyraEngine_v1::o1_itemAppearsOnGround(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); processItemDrop(_currentCharacter->sceneId, stackPos(0), stackPos(1), stackPos(2), 2, 0); return 0; } int KyraEngine_v1::o1_setNoDrawShapesFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0)); _animator->_noDrawShapesFlag = stackPos(0); return 0; } int KyraEngine_v1::o1_fadeEntirePalette(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int cmd = stackPos(0); uint8 *fadePal = 0; @@ -1584,7 +1583,7 @@ int KyraEngine_v1::o1_fadeEntirePalette(ScriptState *script) { } int KyraEngine_v1::o1_itemOnGroundHere(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < _roomTableSize); Room *curRoom = &_roomTable[stackPos(0)]; for (int i = 0; i < 12; ++i) { @@ -1595,18 +1594,18 @@ int KyraEngine_v1::o1_itemOnGroundHere(ScriptState *script) { } int KyraEngine_v1::o1_queryCauldronState(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_queryCauldronState(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryCauldronState(%p) ()", (const void *)script); return _cauldronState; } int KyraEngine_v1::o1_setCauldronState(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCauldronState(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCauldronState(%p) (%d)", (const void *)script, stackPos(0)); _cauldronState = stackPos(0); return _cauldronState; } int KyraEngine_v1::o1_queryCrystalState(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_queryCrystalState(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryCrystalState(%p) (%d)", (const void *)script, stackPos(0)); if (!stackPos(0)) return _crystalState[0]; else if (stackPos(0) == 1) @@ -1615,7 +1614,7 @@ int KyraEngine_v1::o1_queryCrystalState(ScriptState *script) { } int KyraEngine_v1::o1_setCrystalState(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); if (!stackPos(0)) _crystalState[0] = stackPos(1); else if (stackPos(0) == 1) @@ -1629,7 +1628,7 @@ int KyraEngine_v1::o1_setPaletteRange(ScriptState *script) { } int KyraEngine_v1::o1_shrinkBrandonDown(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0)); int delayTime = stackPos(0); checkAmuletAnimFlags(); int scaleValue = _scaleTable[_currentCharacter->y1]; @@ -1655,7 +1654,7 @@ int KyraEngine_v1::o1_shrinkBrandonDown(ScriptState *script) { } int KyraEngine_v1::o1_growBrandonUp(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_growBrandonUp(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1growBrandonUp(%p) ()", (const void *)script); int scaleValue = _scaleTable[_currentCharacter->y1]; int scale = 0; if (_scaleMode) @@ -1676,26 +1675,26 @@ int KyraEngine_v1::o1_growBrandonUp(ScriptState *script) { } int KyraEngine_v1::o1_setBrandonScaleXAndY(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _animator->_brandonScaleX = stackPos(0); _animator->_brandonScaleY = stackPos(1); return 0; } int KyraEngine_v1::o1_resetScaleMode(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_resetScaleMode(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetScaleMode(%p) ()", (const void *)script); _scaleMode = 0; return 0; } int KyraEngine_v1::o1_getScaleDepthTableValue(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0)); assert(stackPos(0) < ARRAYSIZE(_scaleTable)); return _scaleTable[stackPos(0)]; } int KyraEngine_v1::o1_setScaleDepthTableValue(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < ARRAYSIZE(_scaleTable)); _scaleTable[stackPos(0)] = stackPos(1); return stackPos(1); @@ -1703,10 +1702,10 @@ int KyraEngine_v1::o1_setScaleDepthTableValue(ScriptState *script) { int KyraEngine_v1::o1_message(ScriptState *script) { if (_flags.isTalkie) { - debugC(3, kDebugLevelScriptFuncs, "o1_message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2)); drawSentenceCommand(stackPosString(1), stackPos(2)); } else { - debugC(3, kDebugLevelScriptFuncs, "o1_message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); drawSentenceCommand(stackPosString(0), stackPos(1)); } @@ -1714,38 +1713,38 @@ int KyraEngine_v1::o1_message(ScriptState *script) { } int KyraEngine_v1::o1_checkClickOnNPC(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); return checkForNPCScriptRun(stackPos(0), stackPos(1)); } int KyraEngine_v1::o1_getFoyerItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_getFoyerItem(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getFoyerItem(%p) (%d)", (const void *)script, stackPos(0)); assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); return _foyerItemTable[stackPos(0)]; } int KyraEngine_v1::o1_setFoyerItem(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < ARRAYSIZE(_foyerItemTable)); _foyerItemTable[stackPos(0)] = stackPos(1); return stackPos(1); } int KyraEngine_v1::o1_setNoItemDropRegion(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); addToNoDropRects(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); return 0; } int KyraEngine_v1::o1_walkMalcolmOn(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_walkMalcolmOn(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkMalcolmOn(%p) ()", (const void *)script); if (!_malcolmFlag) _malcolmFlag = 1; return 0; } int KyraEngine_v1::o1_passiveProtection(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_passiveProtection(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1passiveProtection(%p) ()", (const void *)script); return 1; } @@ -1755,24 +1754,24 @@ int KyraEngine_v1::o1_setPlayingLoop(ScriptState *script) { } int KyraEngine_v1::o1_brandonToStoneSequence(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_brandonToStoneSequence(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1brandonToStoneSequence(%p) ()", (const void *)script); seq_brandonToStone(); return 0; } int KyraEngine_v1::o1_brandonHealingSequence(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_brandonHealingSequence(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1brandonHealingSequence(%p) ()", (const void *)script); seq_brandonHealing(); return 0; } int KyraEngine_v1::o1_protectCommandLine(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_protectCommandLine(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1protectCommandLine(%p) (%d)", (const void *)script, stackPos(0)); return stackPos(0); } int KyraEngine_v1::o1_pauseMusicSeconds(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_pauseMusicSeconds(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseMusicSeconds(%p) ()", (const void *)script); // if music disabled // return o1_pauseSeconds(script); @@ -1785,13 +1784,13 @@ int KyraEngine_v1::o1_resetMaskRegion(ScriptState *script) { } int KyraEngine_v1::o1_setPaletteChangeFlag(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0)); _paletteChanged = stackPos(0); return _paletteChanged; } int KyraEngine_v1::o1_fillRect(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_fillRect(%p) (%d, %d, %d, %d, %d, 0x%X)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fillRect(%p) (%d, %d, %d, %d, %d, 0x%X)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int videoPageBackup = _screen->_curPage; _screen->_curPage = stackPos(0); _screen->fillRect(stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); @@ -1800,19 +1799,19 @@ int KyraEngine_v1::o1_fillRect(ScriptState *script) { } int KyraEngine_v1::o1_vocUnload(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_vocUnload(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1vocUnload(%p) ()", (const void *)script); // this should unload all voc files (not needed) return 0; } int KyraEngine_v1::o1_vocLoad(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_vocLoad(%p) (%d)", (const void *)script, stackPos(0)); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1vocLoad(%p) (%d)", (const void *)script, stackPos(0)); // this should load the specified voc file (not needed) return 0; } int KyraEngine_v1::o1_dummy(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "o1_dummy(%p) ()", (const void *)script); + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dummy(%p) ()", (const void *)script); return 0; } diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp new file mode 100644 index 0000000000..3e1bc4ed2f --- /dev/null +++ b/engines/kyra/script_v2.cpp @@ -0,0 +1,430 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v2.h" +#include "kyra/wsamovie.h" + +#include "common/endian.h" + +namespace Kyra { + +int KyraEngine_v2::o2_setCharacterFacingRefresh(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setCharacterFacingRefresh(%p) (-, %d, %d)", (const void *)script, stackPos(1), stackPos(2)); + int animFrame = stackPos(2); + if (animFrame >= 0) + _mainCharacter.animFrame = animFrame; + _mainCharacter.facing = stackPos(1); + updateCharacterAnim(0); + refreshAnimObjectsIfNeed(); + return 0; +} + +int KyraEngine_v2::o2_defineObject(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_defineObject(%p) (%d, '%s', %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + Object *object = &_objectList[stackPos(0)]; + strcpy(object->filename, stackPosString(1)); + object->scriptId = stackPos(2); + object->x = stackPos(3); + object->y = stackPos(4); + object->unk12 = stackPos(5); + return 0; +} + +int KyraEngine_v2::o2_refreshCharacter(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_refreshCharacter(%p) (-, %d, %d, %d)", (const void *)script, stackPos(1), stackPos(2), stackPos(3)); + int unk = stackPos(1); + int facing = stackPos(2); + int refresh = stackPos(3); + if (facing >= 0) + _mainCharacter.facing = facing; + if (unk >= 0 && unk != 32) + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + updateCharacterAnim(0); + if (refresh) + refreshAnimObjectsIfNeed(); + return 0; +} + +int KyraEngine_v2::o2_getCharacterX(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterX(%p) ()", (const void *)script); + return _mainCharacter.x1; +} + +int KyraEngine_v2::o2_getCharacterY(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterY(%p) ()", (const void *)script); + return _mainCharacter.y1; +} + +int KyraEngine_v2::o2_getCharacterFacing(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterFacing(%p) ()", (const void *)script); + return _mainCharacter.facing; +} + +int KyraEngine_v2::o2_setSceneComment(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setSceneComment(%p) ('%s')", (const void *)script, stackPosString(0)); + _sceneCommentString = stackPosString(0); + return 0; +} + +int KyraEngine_v2::o2_showChapterMessage(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_showChapterMessage(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + showChapterMessage(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_v2::o2_wsaClose(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_wsaClose(%p) (%d)", (const void *)script, stackPos(0)); + assert(stackPos(0) >= 0 && stackPos(0) < ARRAYSIZE(_wsaSlots)); + _wsaSlots[stackPos(0)]->close(); + return 0; +} + +int KyraEngine_v2::o2_displayWsaFrame(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_displayWsaFrame(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8)); + int frame = stackPos(0); + int x = stackPos(1); + int y = stackPos(2); + int waitTime = stackPos(3); + int slot = stackPos(4); + int copyParam = stackPos(5); + int doUpdate = stackPos(6); + int dstPage = stackPos(7); + int backUp = stackPos(8); + + _screen->hideMouse(); + uint32 endTime = _system->getMillis() + waitTime * _tickLength; + _wsaSlots[slot]->setX(x); + _wsaSlots[slot]->setY(y); + _wsaSlots[slot]->setDrawPage(dstPage); + _wsaSlots[slot]->displayFrame(frame, copyParam | 0xC000); + _screen->updateScreen(); + + if (backUp) + memcpy(_gamePlayBuffer, _screen->getCPagePtr(3), 46080); + + while (_system->getMillis() < endTime) { + if (doUpdate) + update(); + + if (endTime - _system->getMillis() >= 10) + delay(10); + } + _screen->showMouse(); + return 0; +} + +int KyraEngine_v2::o2_displayWsaSequentialFrames(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_displayWsaSequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + int startFrame = stackPos(0); + int endFrame = stackPos(1); + int x = stackPos(2); + int y = stackPos(3); + int waitTime = stackPos(4); + int slot = stackPos(5); + int maxTimes = stackPos(6); + int copyFlags = stackPos(7); + + if (maxTimes > 1) + maxTimes = 1; + + _wsaSlots[slot]->setX(x); + _wsaSlots[slot]->setY(y); + _wsaSlots[slot]->setDrawPage(0); + + _screen->hideMouse(); + int curTime = 0; + while (curTime < maxTimes) { + if (startFrame < endFrame) { + for (int i = startFrame; i <= endFrame; ++i) { + uint32 endTime = _system->getMillis() + waitTime * _tickLength; + _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags); + _screen->updateScreen(); + + do { + update(); + + if (endTime - _system->getMillis() >= 10) + delay(10); + } while (_system->getMillis() < endTime); + } + } else { + for (int i = startFrame; i >= endFrame; --i) { + uint32 endTime = _system->getMillis() + waitTime * _tickLength; + _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags); + _screen->updateScreen(); + + do { + update(); + + if (endTime - _system->getMillis() >= 10) + delay(10); + } while (_system->getMillis() < endTime); + } + } + + ++curTime; + } + _screen->showMouse(); + return 0; +} + +int KyraEngine_v2::o2_wsaOpen(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_wsaOpen(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1)); + assert(stackPos(1) >= 0 && stackPos(1) < ARRAYSIZE(_wsaSlots)); + _wsaSlots[stackPos(1)]->open(stackPosString(0), 1, 0); + return 0; +} + +int KyraEngine_v2::o2_defineItem(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_defineItem(%p) (%d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + int freeItem = findFreeItem(); + + if (freeItem >= 0) { + _itemList[freeItem].id = stackPos(0); + _itemList[freeItem].x = stackPos(1); + _itemList[freeItem].y = stackPos(2); + _itemList[freeItem].sceneId = stackPos(3); + } + + return freeItem; +} + +int KyraEngine_v2::o2_queryGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_queryGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + return queryGameFlag(stackPos(0)); +} + +int KyraEngine_v2::o2_resetGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_resetGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + return resetGameFlag(stackPos(0)); +} + +int KyraEngine_v2::o2_setGameFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setGameFlag(%p) (%d)", (const void *)script, stackPos(0)); + return setGameFlag(stackPos(0)); +} + +int KyraEngine_v2::o2_hideMouse(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_hideMouse(%p) ()", (const void *)script); + _screen->hideMouse(); + return 0; +} + +int KyraEngine_v2::o2_addSpecialExit(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_addSpecialExit(%p) (%d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + if (_specialExitCount < 5) { + _specialExitTable[_specialExitCount+0] = stackPos(0); + _specialExitTable[_specialExitCount+5] = stackPos(1); + _specialExitTable[_specialExitCount+10] = stackPos(2); + _specialExitTable[_specialExitCount+15] = stackPos(3); + _specialExitTable[_specialExitCount+20] = stackPos(4); + ++_specialExitCount; + } + return 0; +} + +int KyraEngine_v2::o2_showMouse(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_showMouse(%p) ()", (const void *)script); + _screen->showMouse(); + return 0; +} + +int KyraEngine_v2::o2_setScaleTableItem(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setScaleTableItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + setScaleTableItem(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_v2::o2_setDrawLayerTableItem(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setDrawLayerTableItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + setDrawLayerTableEntry(stackPos(0), stackPos(1)); + return 0; +} + +int KyraEngine_v2::o2_drawSceneShapeOnPage(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_drawSceneShapeOnPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); + int shape = stackPos(0); + int x = stackPos(1); + int y = stackPos(2); + int flag = stackPos(3); + int drawPage = stackPos(4); + _screen->drawShape(drawPage, _sceneShapeTable[shape], x, y, 2, flag ? 1 : 0); + return 0; +} + +int KyraEngine_v2::o2_restoreBackBuffer(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_restoreBackBuffer(%p) (%d)", (const void *)script, stackPos(0)); + int disable = stackPos(0); + int oldState = 0; + if (disable) { + oldState = _animObjects[0].enabled; + _animObjects[0].enabled = 0; + } + restorePage3(); + if (disable) + _animObjects[0].enabled = oldState; + return 0; +} + +int KyraEngine_v2::o2_getRand(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) < stackPos(1)); + return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); +} + +int KyraEngine_v2::o2_encodeShape(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_encodeShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), + stackPos(2), stackPos(3), stackPos(4)); + _sceneShapeTable[stackPos(0)] = _screen->encodeShape(stackPos(1), stackPos(2), stackPos(3), stackPos(4), 2); + return 0; +} + +int KyraEngine_v2::o2_defineRoomEntrance(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_defineRoomEntrance(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + switch (stackPos(0)) { + case 0: + _sceneEnterX1 = stackPos(1); + _sceneEnterY1 = stackPos(2); + break; + + case 1: + _sceneEnterX2 = stackPos(1); + _sceneEnterY2 = stackPos(2); + break; + + case 2: + _sceneEnterX3 = stackPos(1); + _sceneEnterY3 = stackPos(2); + break; + + case 3: + _sceneEnterX4 = stackPos(1); + _sceneEnterY4 = stackPos(2); + break; + + default: + break; + } + return 0; +} + +int KyraEngine_v2::o2_setSpecialSceneScriptRunTime(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setSpecialSceneScriptRunTime(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + assert(stackPos(0) >= 0 && stackPos(0) < 10); + _sceneSpecialScriptsTimer[stackPos(0)] = _system->getMillis() + stackPos(1) * _tickLength; + return 0; +} + +int KyraEngine_v2::o2_defineSceneAnim(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_defineSceneAnim(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, '%s')", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), + stackPos(9), stackPos(10), stackPos(11), stackPosString(12)); + int animId = stackPos(0); + SceneAnim &anim = _sceneAnims[animId]; + anim.flags = stackPos(1); + anim.x = stackPos(2); + anim.y = stackPos(3); + anim.x2 = stackPos(4); + anim.y2 = stackPos(5); + anim.width = stackPos(6); + anim.height = stackPos(7); + anim.unkE = stackPos(8); + anim.specialSize = stackPos(9); + anim.unk12 = stackPos(10); + anim.shapeIndex = stackPos(11); + if (stackPosString(12) != 0) + strcpy(anim.filename, stackPosString(12)); + + if (anim.flags & 0x40) { + if (!_sceneAnimMovie[animId]->open(anim.filename, 1, 0)) + error("couldn't load '%s'", anim.filename); + + if (_sceneAnimMovie[animId]->xAdd() || _sceneAnimMovie[animId]->yAdd()) + anim.wsaFlag = 1; + else + anim.wsaFlag = 0; + } + + return 0; +} + +int KyraEngine_v2::o2_updateSceneAnim(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_updateSceneAnim(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + updateSceneAnim(stackPos(0), stackPos(1)); + _specialSceneScriptRunFlag = false; + return 0; +} + +int KyraEngine_v2::o2_defineRoom(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_defineRoom(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7)); + SceneDesc *scene = &_sceneList[stackPos(0)]; + strcpy(scene->filename, stackPosString(1)); + scene->exit1 = stackPos(2); + scene->exit2 = stackPos(3); + scene->exit3 = stackPos(4); + scene->exit4 = stackPos(5); + scene->flags = stackPos(6); + scene->sound = stackPos(7); + + if (_mainCharacter.sceneId == stackPos(0)) { + _sceneExit1 = scene->exit1; + _sceneExit2 = scene->exit2; + _sceneExit3 = scene->exit3; + _sceneExit4 = scene->exit4; + } + + return 0; +} + +int KyraEngine_v2::o2_setSpecialSceneScriptState(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_setSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0)); + _specialSceneScriptState[stackPos(0)] = 1; + return 1; +} + +int KyraEngine_v2::o2_clearSpecialSceneScriptState(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_clearSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0)); + _specialSceneScriptState[stackPos(0)] = 0; + return 0; +} + +int KyraEngine_v2::o2_querySpecialSceneScriptState(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_querySpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0)); + return _specialSceneScriptState[stackPos(0)]; +} + +int KyraEngine_v2::o2_dummy(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "o2_dummy(%p) ()", (const void *)script); + return 0; +} + +} // end of namespace Kyra diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp index ba221bf35a..20a98c66c1 100644 --- a/engines/kyra/seqplayer.cpp +++ b/engines/kyra/seqplayer.cpp @@ -28,7 +28,6 @@ #include "engines/engine.h" -#include "kyra/kyra.h" #include "kyra/resource.h" #include "kyra/screen.h" #include "kyra/sound.h" @@ -41,7 +40,7 @@ namespace Kyra { -SeqPlayer::SeqPlayer(KyraEngine* vm, OSystem* system) { +SeqPlayer::SeqPlayer(KyraEngine_v1 *vm, OSystem *system) { _vm = vm; _system = system; diff --git a/engines/kyra/seqplayer.h b/engines/kyra/seqplayer.h index 0fba0403e4..4636a956e9 100644 --- a/engines/kyra/seqplayer.h +++ b/engines/kyra/seqplayer.h @@ -26,11 +26,13 @@ #ifndef KYRA_SEQPLAYER_H #define KYRA_SEQPLAYER_H +#include "kyra/kyra_v1.h" + namespace Kyra { class SeqPlayer { public: - SeqPlayer(KyraEngine* vm, OSystem* system); + SeqPlayer(KyraEngine_v1 *vm, OSystem *system); ~SeqPlayer(); void setCopyViewOffs(bool offs) { @@ -43,9 +45,8 @@ public: bool playSequence(const uint8 *seqData, bool skipSeq); uint8 *setPanPages(int pageNum, int shape); - protected: - KyraEngine *_vm; + KyraEngine_v1 *_vm; OSystem *_system; Screen *_screen; Sound *_sound; diff --git a/engines/kyra/sequences_v1.cpp b/engines/kyra/sequences_v1.cpp index 1b4c0f680a..3bba3406a8 100644 --- a/engines/kyra/sequences_v1.cpp +++ b/engines/kyra/sequences_v1.cpp @@ -25,13 +25,14 @@ #include "kyra/kyra.h" #include "kyra/seqplayer.h" -#include "kyra/screen.h" +#include "kyra/screen_v1.h" #include "kyra/resource.h" #include "kyra/sound.h" #include "kyra/sprites.h" #include "kyra/wsamovie.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" #include "kyra/text.h" +#include "kyra/timer.h" #include "common/events.h" #include "common/system.h" @@ -39,8 +40,8 @@ namespace Kyra { -void KyraEngine::seq_demo() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_demo()"); +void KyraEngine_v1::seq_demo() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_demo()"); snd_playTheme(0, 2); @@ -89,18 +90,18 @@ void KyraEngine::seq_demo() { _sound->haltTrack(); } -void KyraEngine::seq_intro() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_intro()"); +void KyraEngine_v1::seq_intro() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_intro()"); if (_flags.isTalkie) _res->loadPakFile("INTRO.VRM"); static const IntroProc introProcTable[] = { - &KyraEngine::seq_introLogos, - &KyraEngine::seq_introStory, - &KyraEngine::seq_introMalcolmTree, - &KyraEngine::seq_introKallakWriting, - &KyraEngine::seq_introKallakMalcolm + &KyraEngine_v1::seq_introLogos, + &KyraEngine_v1::seq_introStory, + &KyraEngine_v1::seq_introMalcolmTree, + &KyraEngine_v1::seq_introKallakWriting, + &KyraEngine_v1::seq_introKallakMalcolm }; Common::InSaveFile *in; @@ -129,8 +130,8 @@ void KyraEngine::seq_intro() { _res->unloadPakFile("INTRO.VRM"); } -void KyraEngine::seq_introLogos() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_introLogos()"); +void KyraEngine_v1::seq_introLogos() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introLogos()"); if (_flags.platform == Common::kPlatformFMTowns) { _screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette); @@ -231,14 +232,19 @@ void KyraEngine::seq_introLogos() { _seq->playSequence(_seq_Forest, true); } -void KyraEngine::seq_introStory() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_introStory()"); +void KyraEngine_v1::seq_introStory() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introStory()"); _screen->clearPage(3); _screen->clearPage(0); - if (_flags.isTalkie) - return; - else if (_flags.lang == Common::EN_ANY && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) + if (_flags.isTalkie) { + // HACK: The Italian fan translation uses an special text screen here + // so we show it even though it is a talkie version. + if (_flags.lang == Common::IT_ITA) + _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, 0); + else + return; + } else if (_flags.lang == Common::EN_ANY && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) _screen->loadBitmap("TEXT.CPS", 3, 3, _screen->_currentPalette); else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN) _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette); @@ -273,15 +279,15 @@ void KyraEngine::seq_introStory() { delay(360 * _tickLength); } -void KyraEngine::seq_introMalcolmTree() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_introMalcolmTree()"); +void KyraEngine_v1::seq_introMalcolmTree() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introMalcolmTree()"); _screen->_curPage = 0; _screen->clearPage(3); _seq->playSequence(_seq_MalcolmTree, true); } -void KyraEngine::seq_introKallakWriting() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_introKallakWriting()"); +void KyraEngine_v1::seq_introKallakWriting() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakWriting()"); _seq->makeHandShapes(); _screen->setAnimBlockPtr(5060); _screen->_charWidth = -2; @@ -289,13 +295,13 @@ void KyraEngine::seq_introKallakWriting() { _seq->playSequence(_seq_KallakWriting, true); } -void KyraEngine::seq_introKallakMalcolm() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_introKallakMalcolm()"); +void KyraEngine_v1::seq_introKallakMalcolm() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakMalcolm()"); _screen->clearPage(3); _seq->playSequence(_seq_KallakMalcolm, true); } -void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) { +void KyraEngine_v1::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) { debugC(9, kDebugLevelMain, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, drawOnly); static const uint16 specialJewelTable[] = { 0x167, 0x162, 0x15D, 0x158, 0x153, 0xFFFF @@ -355,7 +361,7 @@ void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int dra setGameFlag(0x55+jewel); } -void KyraEngine::seq_brandonHealing() { +void KyraEngine_v1::seq_brandonHealing() { debugC(9, kDebugLevelMain, "seq_brandonHealing()"); if (!(_deathHandler & 8)) return; @@ -386,7 +392,7 @@ void KyraEngine::seq_brandonHealing() { _screen->showMouse(); } -void KyraEngine::seq_brandonHealing2() { +void KyraEngine_v1::seq_brandonHealing2() { debugC(9, kDebugLevelMain, "seq_brandonHealing2()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -410,7 +416,7 @@ void KyraEngine::seq_brandonHealing2() { characterSays(2011, _poisonGone[1], 0, -2); } -void KyraEngine::seq_poisonDeathNow(int now) { +void KyraEngine_v1::seq_poisonDeathNow(int now) { debugC(9, kDebugLevelMain, "seq_poisonDeathNow(%d)", now); if (!(_brandonStatusBit & 1)) return; @@ -431,7 +437,7 @@ void KyraEngine::seq_poisonDeathNow(int now) { } } -void KyraEngine::seq_poisonDeathNowAnim() { +void KyraEngine_v1::seq_poisonDeathNowAnim() { debugC(9, kDebugLevelMain, "seq_poisonDeathNowAnim()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -472,7 +478,7 @@ void KyraEngine::seq_poisonDeathNowAnim() { _screen->showMouse(); } -void KyraEngine::seq_playFluteAnimation() { +void KyraEngine_v1::seq_playFluteAnimation() { debugC(9, kDebugLevelMain, "seq_playFluteAnimation()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -526,7 +532,7 @@ void KyraEngine::seq_playFluteAnimation() { } } -void KyraEngine::seq_winterScroll1() { +void KyraEngine_v1::seq_winterScroll1() { debugC(9, kDebugLevelMain, "seq_winterScroll1()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -607,7 +613,7 @@ void KyraEngine::seq_winterScroll1() { _screen->showMouse(); } -void KyraEngine::seq_winterScroll2() { +void KyraEngine_v1::seq_winterScroll2() { debugC(9, kDebugLevelMain, "seq_winterScroll2()"); _screen->hideMouse(); checkAmuletAnimFlags(); @@ -636,7 +642,7 @@ void KyraEngine::seq_winterScroll2() { _screen->showMouse(); } -void KyraEngine::seq_makeBrandonInv() { +void KyraEngine_v1::seq_makeBrandonInv() { debugC(9, kDebugLevelMain, "seq_makeBrandonInv()"); if (_deathHandler == 8) return; @@ -649,7 +655,7 @@ void KyraEngine::seq_makeBrandonInv() { _screen->hideMouse(); checkAmuletAnimFlags(); _brandonStatusBit |= 0x20; - setTimerCountdown(18, 2700); + _timer->setCountdown(18, 2700); _brandonStatusBit |= 0x40; snd_playSoundEffect(0x77); _brandonInvFlag = 0; @@ -662,7 +668,7 @@ void KyraEngine::seq_makeBrandonInv() { _screen->showMouse(); } -void KyraEngine::seq_makeBrandonNormal() { +void KyraEngine_v1::seq_makeBrandonNormal() { debugC(9, kDebugLevelMain, "seq_makeBrandonNormal()"); _screen->hideMouse(); _brandonStatusBit |= 0x40; @@ -678,7 +684,7 @@ void KyraEngine::seq_makeBrandonNormal() { _screen->showMouse(); } -void KyraEngine::seq_makeBrandonNormal2() { +void KyraEngine_v1::seq_makeBrandonNormal2() { debugC(9, kDebugLevelMain, "seq_makeBrandonNormal2()"); _screen->hideMouse(); assert(_brandonToWispTable); @@ -704,7 +710,7 @@ void KyraEngine::seq_makeBrandonNormal2() { _screen->showMouse(); } -void KyraEngine::seq_makeBrandonWisp() { +void KyraEngine_v1::seq_makeBrandonWisp() { debugC(9, kDebugLevelMain, "seq_makeBrandonWisp()"); if (_deathHandler == 8) return; @@ -727,9 +733,9 @@ void KyraEngine::seq_makeBrandonWisp() { _brandonStatusBit |= 2; if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198) - setTimerCountdown(14, 18000); + _timer->setCountdown(14, 18000); else - setTimerCountdown(14, 7200); + _timer->setCountdown(14, 7200); _animator->_brandonDrawFrame = 113; _brandonStatusBit0x02Flag = 1; @@ -746,7 +752,7 @@ void KyraEngine::seq_makeBrandonWisp() { _screen->showMouse(); } -void KyraEngine::seq_dispelMagicAnimation() { +void KyraEngine_v1::seq_dispelMagicAnimation() { debugC(9, kDebugLevelMain, "seq_dispelMagicAnimation()"); if (_deathHandler == 8) return; @@ -788,7 +794,7 @@ void KyraEngine::seq_dispelMagicAnimation() { _screen->showMouse(); } -void KyraEngine::seq_fillFlaskWithWater(int item, int type) { +void KyraEngine_v1::seq_fillFlaskWithWater(int item, int type) { debugC(9, kDebugLevelMain, "seq_fillFlaskWithWater(%d, %d)", item, type); int newItem = -1; static const uint8 flaskTable1[] = { 0x46, 0x48, 0x4A, 0x4C }; @@ -821,8 +827,8 @@ void KyraEngine::seq_fillFlaskWithWater(int item, int type) { characterSays(voiceEntries[type], _fullFlask[type], 0, -2); } -void KyraEngine::seq_playDrinkPotionAnim(int item, int unk2, int flags) { - debugC(9, kDebugLevelMain, "KyraEngine::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags); +void KyraEngine_v1::seq_playDrinkPotionAnim(int item, int unk2, int flags) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags); uint8 red, green, blue; switch (item) { @@ -913,8 +919,8 @@ void KyraEngine::seq_playDrinkPotionAnim(int item, int unk2, int flags) { _screen->showMouse(); } -int KyraEngine::seq_playEnd() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_playEnd()"); +int KyraEngine_v1::seq_playEnd() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnd()"); if (_endSequenceSkipFlag) return 0; @@ -1006,8 +1012,8 @@ int KyraEngine::seq_playEnd() { return 0; } -void KyraEngine::seq_brandonToStone() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_brandonToStone()"); +void KyraEngine_v1::seq_brandonToStone() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_brandonToStone()"); _screen->hideMouse(); assert(_brandonStoneTable); setupShapes123(_brandonStoneTable, 14, 0); @@ -1022,8 +1028,8 @@ void KyraEngine::seq_brandonToStone() { _screen->showMouse(); } -void KyraEngine::seq_playEnding() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_playEnding()"); +void KyraEngine_v1::seq_playEnding() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnding()"); if (_quitFlag) return; _screen->hideMouse(); @@ -1046,8 +1052,8 @@ void KyraEngine::seq_playEnding() { seq_playCredits(); } -void KyraEngine::seq_playCredits() { - debugC(9, kDebugLevelMain, "KyraEngine::seq_playCredits()"); +void KyraEngine_v1::seq_playCredits() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playCredits()"); static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char stringTerms[] = { 0x5, 0xd, 0x0}; static const int numStrings = 250; @@ -1203,13 +1209,13 @@ void KyraEngine::seq_playCredits() { _screen->showMouse(); } -bool KyraEngine::seq_skipSequence() const { - debugC(9, kDebugLevelMain, "KyraEngine::seq_skipSequence()"); +bool KyraEngine_v1::seq_skipSequence() const { + debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_skipSequence()"); return _quitFlag || _abortIntroFlag; } -int KyraEngine::handleMalcolmFlag() { - debugC(9, kDebugLevelMain, "KyraEngine::handleMalcolmFlag()"); +int KyraEngine_v1::handleMalcolmFlag() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::handleMalcolmFlag()"); static uint16 frame = 0; static uint32 timer1 = 0; static uint32 timer2 = 0; @@ -1377,8 +1383,8 @@ int KyraEngine::handleMalcolmFlag() { return 0; } -int KyraEngine::handleBeadState() { - debugC(9, kDebugLevelMain, "KyraEngine::handleBeadState()"); +int KyraEngine_v1::handleBeadState() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::handleBeadState()"); static uint32 timer1 = 0; static uint32 timer2 = 0; static BeadState beadState1 = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1597,8 +1603,8 @@ int KyraEngine::handleBeadState() { return 0; } -void KyraEngine::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) { - debugC(9, kDebugLevelMain, "KyraEngine::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr); +void KyraEngine_v1::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr); ptr->unk9 = unk; int xDiff = x2 - x; int yDiff = y2 - y; @@ -1631,8 +1637,8 @@ void KyraEngine::initBeadState(int x, int y, int x2, int y2, int unk, BeadState ptr->unk8 = unk2; } -int KyraEngine::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { - debugC(9, kDebugLevelMain, "KyraEngine::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr); +int KyraEngine_v1::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr); if (x == ptr->dstX && y == ptr->dstY) return 1; @@ -1668,8 +1674,8 @@ int KyraEngine::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) { return 0; } -void KyraEngine::setupPanPages() { - debugC(9, kDebugLevelMain, "KyraEngine::setupPanPages()"); +void KyraEngine_v1::setupPanPages() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::setupPanPages()"); _screen->loadBitmap("BEAD.CPS", 3, 3, 0); if (_flags.platform == Common::kPlatformMacintosh || _flags.platform == Common::kPlatformAmiga) { int pageBackUp = _screen->_curPage; @@ -1697,8 +1703,8 @@ void KyraEngine::setupPanPages() { } } -void KyraEngine::freePanPages() { - debugC(9, kDebugLevelMain, "KyraEngine::freePanPages()"); +void KyraEngine_v1::freePanPages() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::freePanPages()"); delete _endSequenceBackUpRect; _endSequenceBackUpRect = 0; for (int i = 0; i <= 19; ++i) { @@ -1707,8 +1713,8 @@ void KyraEngine::freePanPages() { } } -void KyraEngine::closeFinalWsa() { - debugC(9, kDebugLevelMain, "KyraEngine::closeFinalWsa()"); +void KyraEngine_v1::closeFinalWsa() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::closeFinalWsa()"); delete _finalA; _finalA = 0; delete _finalB; @@ -1719,7 +1725,7 @@ void KyraEngine::closeFinalWsa() { _endSequenceNeedLoading = 1; } -void KyraEngine::updateKyragemFading() { +void KyraEngine_v1::updateKyragemFading() { static const uint8 kyraGemPalette[0x28] = { 0x3F, 0x3B, 0x38, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x25, 0x22, 0x1F, 0x1C, 0x19, 0x16, 0x12, 0x0F, 0x0C, 0x0A, 0x06, 0x03, @@ -1789,8 +1795,8 @@ void KyraEngine::updateKyragemFading() { _kyragemFadingState.timerCount = _system->getMillis() + 120 * _tickLength; } -void KyraEngine::drawJewelPress(int jewel, int drawSpecial) { - debugC(9, kDebugLevelMain, "KyraEngine::drawJewelPress(%d, %d)", jewel, drawSpecial); +void KyraEngine_v1::drawJewelPress(int jewel, int drawSpecial) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelPress(%d, %d)", jewel, drawSpecial); _screen->hideMouse(); int shape = 0; @@ -1814,8 +1820,8 @@ void KyraEngine::drawJewelPress(int jewel, int drawSpecial) { _screen->showMouse(); } -void KyraEngine::drawJewelsFadeOutStart() { - debugC(9, kDebugLevelMain, "KyraEngine::drawJewelsFadeOutStart()"); +void KyraEngine_v1::drawJewelsFadeOutStart() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutStart()"); static const uint16 jewelTable1[] = { 0x164, 0x15F, 0x15A, 0x155, 0x150, 0xFFFF }; static const uint16 jewelTable2[] = { 0x163, 0x15E, 0x159, 0x154, 0x14F, 0xFFFF }; static const uint16 jewelTable3[] = { 0x166, 0x160, 0x15C, 0x157, 0x152, 0xFFFF }; @@ -1834,8 +1840,8 @@ void KyraEngine::drawJewelsFadeOutStart() { } } -void KyraEngine::drawJewelsFadeOutEnd(int jewel) { - debugC(9, kDebugLevelMain, "KyraEngine::drawJewelsFadeOutEnd(%d)", jewel); +void KyraEngine_v1::drawJewelsFadeOutEnd(int jewel) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutEnd(%d)", jewel); static const uint16 jewelTable[] = { 0x153, 0x158, 0x15D, 0x162, 0x148, 0xFFFF }; int newDelay = 0; @@ -1853,7 +1859,7 @@ void KyraEngine::drawJewelsFadeOutEnd(int jewel) { } setGameFlag(0xF1); - setTimerCountdown(19, newDelay); + _timer->setCountdown(19, newDelay); _screen->hideMouse(); for (int i = 0; jewelTable[i] != 0xFFFF; ++i) { uint16 shape = jewelTable[i]; diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp index afda1091e6..1c098bf887 100644 --- a/engines/kyra/sequences_v2.cpp +++ b/engines/kyra/sequences_v2.cpp @@ -569,6 +569,7 @@ void KyraEngine_v2::seq_loadWSA(int wsaNum, const char *filename, int frameDelay _activeWSA[wsaNum].movie = new WSAMovieV2(this); assert(_activeWSA[wsaNum].movie); _activeWSA[wsaNum].endFrame = _activeWSA[wsaNum].movie->open(filename, 0, _screen->_currentPalette); + _activeWSA[wsaNum].movie->flagOldOff(true); assert(_activeWSA[wsaNum].movie->opened()); _activeWSA[wsaNum].currentFrame = 0; _activeWSA[wsaNum].frameDelay = frameDelay; diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 8deed22091..562754b9c5 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -61,7 +61,9 @@ void Sound::voicePlay(const char *file) { if (!_compressHandle.isOpen()) continue; - _currentVocFile = _supportedCodes[i].streamFunc(&_compressHandle, fileSize); + Common::MemoryReadStream *tmp = _compressHandle.readStream(fileSize); + assert(tmp); + _currentVocFile = _supportedCodes[i].streamFunc(tmp, true, 0, 0, 1); found = true; break; } @@ -432,117 +434,6 @@ void SoundMidiPC::beginFadeOut() { _fadeStartTime = _vm->_system->getMillis(); } -#pragma mark - - -bool KyraEngine::speechEnabled() { - return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2); -} - -bool KyraEngine::textEnabled() { - return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); -} - -void KyraEngine::snd_playTheme(int file, int track) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playTheme(%d)", file); - _curSfxFile = _curMusicTheme = file; - _sound->loadSoundFile(_curMusicTheme); - _sound->playTrack(track); -} - -void KyraEngine::snd_playSoundEffect(int track) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playSoundEffect(%d)", track); - if (_flags.platform == Common::kPlatformFMTowns && track == 49) { - snd_playWanderScoreViaMap(56, 1); - return; - } - _sound->playSoundEffect(track); -} - -void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playWanderScoreViaMap(%d, %d)", command, restart); - if (restart) - _lastMusicCommand = -1; - - if (_flags.platform == Common::kPlatformFMTowns) { - if (command == 1) { - _sound->beginFadeOut(); - } else if (command >= 35 && command <= 38) { - snd_playSoundEffect(command-20); - } else if (command >= 2) { - if (_lastMusicCommand != command) { - // the original does -2 here we handle this inside _sound->playTrack() - _sound->playTrack(command); - } - } else { - _sound->haltTrack(); - } - } else { - static const int8 soundTable[] = { - -1, 0, -1, 1, 0, 3, 0, 2, - 0, 4, 1, 2, 1, 3, 1, 4, - 1, 92, 1, 6, 1, 7, 2, 2, - 2, 3, 2, 4, 2, 5, 2, 6, - 2, 7, 3, 3, 3, 4, 1, 8, - 1, 9, 4, 2, 4, 3, 4, 4, - 4, 5, 4, 6, 4, 7, 4, 8, - 1, 11, 1, 12, 1, 14, 1, 13, - 4, 9, 5, 12, 6, 2, 6, 6, - 6, 7, 6, 8, 6, 9, 6, 3, - 6, 4, 6, 5, 7, 2, 7, 3, - 7, 4, 7, 5, 7, 6, 7, 7, - 7, 8, 7, 9, 8, 2, 8, 3, - 8, 4, 8, 5, 6, 11, 5, 11 - }; - //if (!_disableSound) { - // XXX - //} - assert(command*2+1 < ARRAYSIZE(soundTable)); - if (_curMusicTheme != soundTable[command*2]+1) { - if (soundTable[command*2] != -1) - snd_playTheme(soundTable[command*2]+1); - } - - if (command != 1) { - if (_lastMusicCommand != command) { - _sound->haltTrack(); - _sound->playTrack(soundTable[command*2+1]); - } - } else { - _sound->beginFadeOut(); - } - } - - _lastMusicCommand = command; -} - -void KyraEngine::snd_playVoiceFile(int id) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playVoiceFile(%d)", id); - char vocFile[9]; - assert(id >= 0 && id < 9999); - sprintf(vocFile, "%03d", id); - _sound->voicePlay(vocFile); -} - -void KyraEngine::snd_voiceWaitForFinish(bool ingame) { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceWaitForFinish(%d)", ingame); - while (_sound->voiceIsPlaying() && !_skipFlag) { - if (ingame) - delay(10, true); - else - _system->delayMillis(10); - } -} - -void KyraEngine::snd_stopVoice() { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_stopVoice()"); - _sound->voiceStop(); -} - -bool KyraEngine::snd_voiceIsPlaying() { - debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceIsPlaying()"); - return _sound->voiceIsPlaying(); -} - // static res const Sound::SpeechCodecs Sound::_supportedCodes[] = { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index 28a9521112..b6c06b493b 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -109,7 +109,12 @@ private: struct SpeechCodecs { const char *fileext; - Audio::AudioStream *(*streamFunc)(Common::File*, uint32); + Audio::AudioStream *(*streamFunc)( + Common::SeekableReadStream *stream, + bool disposeAfterUse, + uint32 startTime, + uint32 duration, + uint numLoops); }; static const SpeechCodecs _supportedCodes[]; diff --git a/engines/kyra/sound_v1.cpp b/engines/kyra/sound_v1.cpp new file mode 100644 index 0000000000..3ea86189b2 --- /dev/null +++ b/engines/kyra/sound_v1.cpp @@ -0,0 +1,140 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/sound.h" +#include "kyra/kyra_v1.h" + +namespace Kyra { + +bool KyraEngine_v1::speechEnabled() { + return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2); +} + +bool KyraEngine_v1::textEnabled() { + return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2); +} + +void KyraEngine_v1::snd_playTheme(int file, int track) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playTheme(%d)", file); + _curSfxFile = _curMusicTheme = file; + _sound->loadSoundFile(_curMusicTheme); + _sound->playTrack(track); +} + +void KyraEngine_v1::snd_playSoundEffect(int track) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playSoundEffect(%d)", track); + if (_flags.platform == Common::kPlatformFMTowns && track == 49) { + snd_playWanderScoreViaMap(56, 1); + return; + } + _sound->playSoundEffect(track); +} + +void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playWanderScoreViaMap(%d, %d)", command, restart); + if (restart) + _lastMusicCommand = -1; + + if (_flags.platform == Common::kPlatformFMTowns) { + if (command == 1) { + _sound->beginFadeOut(); + } else if (command >= 35 && command <= 38) { + snd_playSoundEffect(command-20); + } else if (command >= 2) { + if (_lastMusicCommand != command) { + // the original does -2 here we handle this inside _sound->playTrack() + _sound->playTrack(command); + } + } else { + _sound->haltTrack(); + } + } else { + static const int8 soundTable[] = { + -1, 0, -1, 1, 0, 3, 0, 2, + 0, 4, 1, 2, 1, 3, 1, 4, + 1, 92, 1, 6, 1, 7, 2, 2, + 2, 3, 2, 4, 2, 5, 2, 6, + 2, 7, 3, 3, 3, 4, 1, 8, + 1, 9, 4, 2, 4, 3, 4, 4, + 4, 5, 4, 6, 4, 7, 4, 8, + 1, 11, 1, 12, 1, 14, 1, 13, + 4, 9, 5, 12, 6, 2, 6, 6, + 6, 7, 6, 8, 6, 9, 6, 3, + 6, 4, 6, 5, 7, 2, 7, 3, + 7, 4, 7, 5, 7, 6, 7, 7, + 7, 8, 7, 9, 8, 2, 8, 3, + 8, 4, 8, 5, 6, 11, 5, 11 + }; + //if (!_disableSound) { + // XXX + //} + assert(command*2+1 < ARRAYSIZE(soundTable)); + if (_curMusicTheme != soundTable[command*2]+1) { + if (soundTable[command*2] != -1) + snd_playTheme(soundTable[command*2]+1); + } + + if (command != 1) { + if (_lastMusicCommand != command) { + _sound->haltTrack(); + _sound->playTrack(soundTable[command*2+1]); + } + } else { + _sound->beginFadeOut(); + } + } + + _lastMusicCommand = command; +} + +void KyraEngine_v1::snd_playVoiceFile(int id) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playVoiceFile(%d)", id); + char vocFile[9]; + assert(id >= 0 && id < 9999); + sprintf(vocFile, "%03d", id); + _sound->voicePlay(vocFile); +} + +void KyraEngine_v1::snd_voiceWaitForFinish(bool ingame) { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceWaitForFinish(%d)", ingame); + while (_sound->voiceIsPlaying() && !_skipFlag) { + if (ingame) + delay(10, true); + else + _system->delayMillis(10); + } +} + +void KyraEngine_v1::snd_stopVoice() { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_stopVoice()"); + _sound->voiceStop(); +} + +bool KyraEngine_v1::snd_voiceIsPlaying() { + debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceIsPlaying()"); + return _sound->voiceIsPlaying(); +} + +} // end of namespace Kyra diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp index 0a3f243df2..1a2c7f6146 100644 --- a/engines/kyra/sprites.cpp +++ b/engines/kyra/sprites.cpp @@ -29,14 +29,14 @@ #include "common/util.h" #include "common/system.h" #include "kyra/screen.h" -#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/sprites.h" #include "kyra/resource.h" -#include "kyra/animator.h" +#include "kyra/animator_v1.h" namespace Kyra { -Sprites::Sprites(KyraEngine *vm, OSystem *system) { +Sprites::Sprites(KyraEngine_v1 *vm, OSystem *system) { _vm = vm; _res = vm->resource(); _screen = vm->screen(); diff --git a/engines/kyra/sprites.h b/engines/kyra/sprites.h index 179942d519..255d878635 100644 --- a/engines/kyra/sprites.h +++ b/engines/kyra/sprites.h @@ -26,6 +26,8 @@ #ifndef KYRA_SPRITES_H #define KYRA_SPRITES_H +#include "kyra/kyra_v1.h" + namespace Kyra { #define MAX_NUM_ANIMS 11 @@ -61,10 +63,11 @@ struct Anim { bool disable; }; +class KyraEngine_v1; + class Sprites { public: - - Sprites(KyraEngine *vm, OSystem *system); + Sprites(KyraEngine_v1 *vm, OSystem *system); ~Sprites(); void updateSceneAnims(); @@ -83,7 +86,7 @@ public: protected: void freeSceneShapes(); - KyraEngine *_vm; + KyraEngine_v1 *_vm; Resource *_res; OSystem *_system; Screen *_screen; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 16e3f98791..3cf8648aa8 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -27,6 +27,7 @@ #include "common/endian.h" #include "common/md5.h" #include "kyra/kyra.h" +#include "kyra/kyra_v1.h" #include "kyra/kyra_v2.h" #include "kyra/kyra_v3.h" #include "kyra/screen.h" @@ -617,7 +618,7 @@ uint8 *StaticResource::getFile(const char *name, int &size) { #pragma mark - -void KyraEngine::initStaticResource() { +void KyraEngine_v1::initStaticResource() { int temp = 0; _seq_Forest = _staticres->loadRawData(kForestSeq, temp); _seq_KallakWriting = _staticres->loadRawData(kKallakWritingSeq, temp); @@ -708,7 +709,7 @@ void KyraEngine::initStaticResource() { } } -void KyraEngine::loadMouseShapes() { +void KyraEngine_v1::loadMouseShapes() { _screen->loadBitmap("MOUSE.CPS", 3, 3, 0); _screen->_curPage = 2; _shapes[0] = _screen->encodeShape(0, 0, 8, 10, 0); @@ -724,7 +725,7 @@ void KyraEngine::loadMouseShapes() { _screen->setShapePages(5, 3); } -void KyraEngine::loadCharacterShapes() { +void KyraEngine_v1::loadCharacterShapes() { int curImage = 0xFF; int videoPage = _screen->_curPage; _screen->_curPage = 2; @@ -745,7 +746,7 @@ void KyraEngine::loadCharacterShapes() { _screen->_curPage = videoPage; } -void KyraEngine::loadSpecialEffectShapes() { +void KyraEngine_v1::loadSpecialEffectShapes() { _screen->loadBitmap("EFFECTS.CPS", 3, 3, 0); _screen->_curPage = 2; @@ -763,7 +764,7 @@ void KyraEngine::loadSpecialEffectShapes() { _shapes[currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1); } -void KyraEngine::loadItems() { +void KyraEngine_v1::loadItems() { int shape; _screen->loadBitmap("JEWELS3.CPS", 3, 3, 0); @@ -817,7 +818,7 @@ void KyraEngine::loadItems() { delete[] fileData; } -void KyraEngine::loadButtonShapes() { +void KyraEngine_v1::loadButtonShapes() { _screen->loadBitmap("BUTTONS2.CPS", 3, 3, 0); _screen->_curPage = 2; _scrollUpButton.process0PtrShape = _screen->encodeShape(0, 0, 24, 14, 1); @@ -829,12 +830,12 @@ void KyraEngine::loadButtonShapes() { _screen->_curPage = 0; } -void KyraEngine::loadMainScreen(int page) { +void KyraEngine_v1::loadMainScreen(int page) { _screen->clearPage(page); if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga)) _screen->loadBitmap("MAIN15.CPS", page, page, _screen->getPalette(0)); - else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN) + else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA)) _screen->loadBitmap("MAIN_ENG.CPS", page, page, 0); else if (_flags.lang == Common::FR_FRA) _screen->loadBitmap("MAIN_FRE.CPS", page, page, 0); @@ -867,18 +868,43 @@ const ScreenDim Screen::_screenDimTable[] = { { 0x03, 0x28, 0x22, 0x46, 0x0F, 0x0D, 0x00, 0x00 } }; -const int Screen::_screenDimTableCount = ARRAYSIZE(_screenDimTable); +const int Screen::_screenDimTableCount = ARRAYSIZE(Screen::_screenDimTable); + +const ScreenDim Screen_v2::_screenDimTable[] = { + { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x08, 0x48, 0x18, 0x38, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x00, 0x00, 0x28, 0x90, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x00, 0xC2, 0x28, 0x06, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x00, 0x90, 0x28, 0x38, 0x96, 0xCF, 0x00, 0x00 }, + { 0x01, 0x94, 0x26, 0x30, 0x96, 0x1B, 0x00, 0x00 }, + { 0x00, 0x90, 0x28, 0x38, 0xC7, 0xCC, 0x00, 0x00 }, + { 0x01, 0x96, 0x26, 0x32, 0xC7, 0xCC, 0x00, 0x00 }, + { 0x00, 0x00, 0x28, 0x88, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x00, 0x08, 0x28, 0xB8, 0xC7, 0xCF, 0x00, 0x00 }, + { 0x01, 0x28, 0x26, 0x46, 0xC7, 0xCC, 0x00, 0x00 }, + { 0x0A, 0x96, 0x14, 0x30, 0x19, 0xF0, 0x00, 0x00 } // menu, just present for current menu code +}; + +const int Screen_v2::_screenDimTableCount = ARRAYSIZE(Screen_v2::_screenDimTable); -const ScreenDim Screen::_screenDimTableK3[] = { +const ScreenDim Screen_v2::_screenDimTableK3[] = { { 0x00, 0x00, 0x28, 0xC8, 0xFF, 0xF0, 0x00, 0x00 }, { 0x08, 0x48, 0x18, 0x38, 0xFF, 0xF0, 0x00, 0x00 }, { 0x00, 0x00, 0x28, 0xBC, 0xFF, 0xF0, 0x00, 0x00 }, { 0x0A, 0x96, 0x14, 0x30, 0x19, 0xF0, 0x00, 0x00 } }; -const int Screen::_screenDimTableCountK3 = ARRAYSIZE(_screenDimTableK3); +const int Screen_v2::_screenDimTableCountK3 = ARRAYSIZE(Screen_v2::_screenDimTableK3); + +const int8 KyraEngine::_addXPosTable[] = { + 4, 4, 0, -4, -4, -4, 0, 4 +}; + +const int8 KyraEngine::_addYPosTable[] = { + 0, -2, -2, -2, 0, 2, 2, 2 +}; -const char *KyraEngine::_soundFiles[] = { +const char *KyraEngine_v1::_soundFiles[] = { "INTRO", "KYRA1A", "KYRA1B", @@ -891,9 +917,9 @@ const char *KyraEngine::_soundFiles[] = { "KYRAMISC" }; -const int KyraEngine::_soundFilesCount = ARRAYSIZE(KyraEngine::_soundFiles); +const int KyraEngine_v1::_soundFilesCount = ARRAYSIZE(KyraEngine_v1::_soundFiles); -const char *KyraEngine::_soundFilesTowns[] = { +const char *KyraEngine_v1::_soundFilesTowns[] = { "TW_INTRO.SFX", "TW_SCEN1.SFX", "TW_SCEN2.SFX", @@ -902,49 +928,41 @@ const char *KyraEngine::_soundFilesTowns[] = { "TW_SCEN5.SFX", }; -const int KyraEngine::_soundFilesTownsCount = ARRAYSIZE(KyraEngine::_soundFilesTowns); +const int KyraEngine_v1::_soundFilesTownsCount = ARRAYSIZE(KyraEngine_v1::_soundFilesTowns); -const int8 KyraEngine::_charXPosTable[] = { +const int8 KyraEngine_v1::_charXPosTable[] = { 0, 4, 4, 4, 0, -4, -4, -4 }; -const int8 KyraEngine::_addXPosTable[] = { - 4, 4, 0, -4, -4, -4, 0, 4 -}; - -const int8 KyraEngine::_charYPosTable[] = { +const int8 KyraEngine_v1::_charYPosTable[] = { -2, -2, 0, 2, 2, 2, 0, -2 }; -const int8 KyraEngine::_addYPosTable[] = { - 0, -2, -2, -2, 0, 2, 2, 2 -}; - -const uint16 KyraEngine::_itemPosX[] = { +const uint16 KyraEngine_v1::_itemPosX[] = { 95, 115, 135, 155, 175, 95, 115, 135, 155, 175 }; -const uint8 KyraEngine::_itemPosY[] = { +const uint8 KyraEngine_v1::_itemPosY[] = { 160, 160, 160, 160, 160, 181, 181, 181, 181, 181 }; -void KyraEngine::setupButtonData() { +void KyraEngine_v1::setupButtonData() { static Button buttonData[] = { - { 0, 0x02, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x01, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x009, 0xA4, 0x36, 0x1E, /*XXX,*/ 0, &KyraEngine::buttonMenuCallback/*, XXX*/ }, - { 0, 0x03, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x04, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x05, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x06, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x07, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x08, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x09, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x0A, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x0B, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ }, - { 0, 0x15, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0x9C, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ }, - { 0, 0x16, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0E7, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ }, - { 0, 0x17, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0xB5, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ }, - { 0, 0x18, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x113, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ } + { 0, 0x02, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x01, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x009, 0xA4, 0x36, 0x1E, /*XXX,*/ 0, &KyraEngine_v1::buttonMenuCallback/*, XXX*/ }, + { 0, 0x03, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x04, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x05, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x06, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x07, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x08, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x09, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x0A, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x0B, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ }, + { 0, 0x15, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0x9C, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ }, + { 0, 0x16, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0E7, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ }, + { 0, 0x17, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0xB5, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ }, + { 0, 0x18, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x113, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ } }; static Button *buttonDataListPtr[] = { @@ -969,10 +987,10 @@ void KyraEngine::setupButtonData() { _buttonDataListPtr = buttonDataListPtr; } -Button KyraEngine::_scrollUpButton = {0, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0}; -Button KyraEngine::_scrollDownButton = {0, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0}; +Button KyraEngine_v1::_scrollUpButton = {0, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0}; +Button KyraEngine_v1::_scrollDownButton = {0, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0}; -Button KyraEngine::_menuButtonData[] = { +Button KyraEngine_v1::_menuButtonData[] = { { 0, 0x0c, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ }, { 0, 0x0d, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ }, { 0, 0x0e, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ }, @@ -981,33 +999,33 @@ Button KyraEngine::_menuButtonData[] = { { 0, 0x11, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ } }; -void KyraEngine::setupMenu() { +void KyraEngine_v1::setupMenu() { static Menu menu[] = { { -1, -1, 208, 136, 248, 249, 250, 0, 251, -1, 8, 0, 5, -1, -1, -1, -1, { {1, 0, 0, 0, -1, -1, 30, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_loadGameMenu, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_loadGameMenu, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, -1, -1, 47, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_saveGameMenu, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_saveGameMenu, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, -1, -1, 64, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_gameControlsMenu, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_gameControlsMenu, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, -1, -1, 81, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_quitPlaying, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_quitPlaying, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 86, 0, 110, 92, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_resumeGame, -1, 0, 0, 0, 0, 0} + 248, 249, 250, &KyraEngine_v1::gui_resumeGame, -1, 0, 0, 0, 0, 0} } }, { -1, -1, 288, 56, 248, 249, 250, 0, 254,-1, 8, 0, 2, -1, -1, -1, -1, { {1, 0, 0, 0, 24, 0, 30, 72, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_quitConfirmYes, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_quitConfirmYes, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 192, 0, 30, 72, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_quitConfirmNo, -1, 0, 0, 0, 0, 0} + 248, 249, 250, &KyraEngine_v1::gui_quitConfirmNo, -1, 0, 0, 0, 0, 0} } }, { -1, -1, 288, 160, 248, 249, 250, 0, 251, -1, 8, 0, 6, 132, 22, 132, 124, @@ -1028,46 +1046,46 @@ void KyraEngine::setupMenu() { 248, 249, 250, 0, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 184, 0, 134, 88, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0}, } }, { -1, -1, 288, 67, 248, 249, 250, 0, 251, -1, 8, 0, 3, -1, -1, -1, -1, { {1, 0, 0, 0, 24, 0, 44, 72, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_savegameConfirm, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_savegameConfirm, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 192, 0, 44, 72, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0} + 248, 249, 250, &KyraEngine_v1::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0} } }, { -1, -1, 208, 76, 248, 249, 250, 0, 251, -1, 8, 0, 2, -1, -1, -1, -1, { {1, 0, 0, 0, -1, -1, 30, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_loadGameMenu, -1, 0, 0, 0, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_loadGameMenu, -1, 0, 0, 0, 0, 0}, {1, 0, 0, 0, -1, -1, 47, 148, 15, 252, 253, 24, 0, - 248, 249, 250, &KyraEngine::gui_quitPlaying, -1, 0, 0, 0, 0, 0} + 248, 249, 250, &KyraEngine_v1::gui_quitPlaying, -1, 0, 0, 0, 0, 0} } }, { -1, -1, 208, 153, 248, 249, 250, 0, 251, -1, 8, 0, 6, -1, -1, -1, -1, { {1, 0, 0, 0, 110, 0, 30, 64, 15, 252, 253, 5, 0, - 248, 249, 250, &KyraEngine::gui_controlsChangeMusic, -1, 0, 34, 32, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_controlsChangeMusic, -1, 0, 34, 32, 0, 0}, {1, 0, 0, 0, 110, 0, 47, 64, 15, 252, 253, 5, 0, - 248, 249, 250, &KyraEngine::gui_controlsChangeSounds, -1, 0, 34, 49, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_controlsChangeSounds, -1, 0, 34, 49, 0, 0}, {1, 0, 0, 0, 110, 0, 64, 64, 15, 252, 253, 5, 0, - 248, 249, 250, &KyraEngine::gui_controlsChangeWalk, -1, 0, 34, 66, 0, 0}, + 248, 249, 250, &KyraEngine_v1::gui_controlsChangeWalk, -1, 0, 34, 66, 0, 0}, {1, 0, 0, 0, 110, 0, 81, 64, 15, 252, 253, 5, 0, 248, 249, 250, 0, -1, 0, 34, 83, 0, 0 }, {1, 0, 0, 0, 110, 0, 98, 64, 15, 252, 253, 5, 0, - 248, 249, 250, &KyraEngine::gui_controlsChangeText, -1, 0, 34, 100, 0, 0 }, + 248, 249, 250, &KyraEngine_v1::gui_controlsChangeText, -1, 0, 34, 100, 0, 0 }, {1, 0, 0, 0, 64, 0, 127, 92, 15, 252, 253, -1, 255, - 248, 249, 250, &KyraEngine::gui_controlsApply, -1, -0, 0, 0, 0, 0} + 248, 249, 250, &KyraEngine_v1::gui_controlsApply, -1, -0, 0, 0, 0, 0} } } }; @@ -1075,31 +1093,31 @@ void KyraEngine::setupMenu() { _menu = menu; } -const uint8 KyraEngine::_magicMouseItemStartFrame[] = { +const uint8 KyraEngine_v1::_magicMouseItemStartFrame[] = { 0xAD, 0xB7, 0xBE, 0x00 }; -const uint8 KyraEngine::_magicMouseItemEndFrame[] = { +const uint8 KyraEngine_v1::_magicMouseItemEndFrame[] = { 0xB1, 0xB9, 0xC2, 0x00 }; -const uint8 KyraEngine::_magicMouseItemStartFrame2[] = { +const uint8 KyraEngine_v1::_magicMouseItemStartFrame2[] = { 0xB2, 0xBA, 0xC3, 0x00 }; -const uint8 KyraEngine::_magicMouseItemEndFrame2[] = { +const uint8 KyraEngine_v1::_magicMouseItemEndFrame2[] = { 0xB6, 0xBD, 0xC8, 0x00 }; -const uint16 KyraEngine::_amuletX[] = { 231, 275, 253, 253 }; -const uint16 KyraEngine::_amuletY[] = { 170, 170, 159, 181 }; +const uint16 KyraEngine_v1::_amuletX[] = { 231, 275, 253, 253 }; +const uint16 KyraEngine_v1::_amuletY[] = { 170, 170, 159, 181 }; -const uint16 KyraEngine::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 }; -const uint16 KyraEngine::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 }; +const uint16 KyraEngine_v1::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 }; +const uint16 KyraEngine_v1::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 }; // Kyra 2 and 3 main menu -const char *KyraEngine::_mainMenuStrings[] = { +const char *KyraEngine_v2::_mainMenuStrings[] = { "Start a new game", "Introduction", "Load a game", @@ -1195,6 +1213,34 @@ const char *KyraEngine_v2::_introSoundList[] = { const int KyraEngine_v2::_introSoundListSize = ARRAYSIZE(KyraEngine_v2::_introSoundList); +const char *KyraEngine_v2::_languageExtension[] = { + "ENG", + "FRE", + "GER"/*, + "ITA", Italian and Spanish was never included + "SPA"*/ +}; + +const char *KyraEngine_v2::_scriptLangExt[] = { + "EMC", + "FMC", + "GMC"/*, + "IMC", Italian and Spanish was never included + "SMC"*/ +}; + +int KyraEngine_v2::_characterFrameTable[] = { + 0x19, 0x09, 0x09, 0x12, 0x12, 0x12, 0x09, 0x09 +}; + +int KyraEngine_v2::_inventoryX[] = { + 0x4F, 0x63, 0x77, 0x8B, 0x9F, 0x4F, 0x63, 0x77, 0x8B, 0x9F +}; + +int KyraEngine_v2::_inventoryY[] = { + 0x95, 0x95, 0x95, 0x95, 0x95, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA +}; + // kyra 3 static res const char *KyraEngine_v3::_soundList[] = { diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp index 58ce3c9d1e..e62410ca19 100644 --- a/engines/kyra/text.cpp +++ b/engines/kyra/text.cpp @@ -28,8 +28,6 @@ #include "kyra/kyra.h" #include "kyra/screen.h" #include "kyra/text.h" -#include "kyra/animator.h" -#include "kyra/sprites.h" #include "common/events.h" #include "common/system.h" @@ -37,369 +35,6 @@ namespace Kyra { -void KyraEngine::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) { - debugC(9, kDebugLevelMain, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); - bool hasUpdatedNPCs = false; - bool runLoop = true; - bool drawText = textEnabled(); - uint8 currPage; - Common::Event event; - - //while (towns_isEscKeyPressed() ) - //towns_getKey(); - - uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis(); - - if (_configVoice == 0 && chatDuration != -1) { - switch (_configTextspeed) { - case 0: - chatDuration *= 2; - break; - case 2: - chatDuration /= 4; - break; - case 3: - chatDuration = -1; - break; - } - } - - if (chatDuration != -1) - chatDuration *= _tickLength; - - if (vocFile != -1) { - snd_voiceWaitForFinish(); - snd_playVoiceFile(vocFile); - } - - disableTimer(14); - disableTimer(18); - disableTimer(19); - - uint32 timeAtStart = _system->getMillis(); - uint32 loopStart; - while (runLoop) { - loopStart = _system->getMillis(); - if (_currentCharacter->sceneId == 210) - if (seq_playEnd()) - break; - - if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) { - hasUpdatedNPCs = true; - disableTimer(15); - _currHeadShape = 4; - _animator->animRefreshNPC(0); - _animator->animRefreshNPC(_talkingCharNum); - - if (_charSayUnk2 != -1) { - _animator->sprites()[_charSayUnk2].active = 0; - _sprites->_anims[_charSayUnk2].play = false; - _charSayUnk2 = -1; - } - } - - updateGameTimers(); - _sprites->updateSceneAnims(); - _animator->restoreAllObjectBackgrounds(); - _animator->preserveAnyChangedBackgrounds(); - _animator->prepDrawAllObjects(); - - if (drawText) { - currPage = _screen->_curPage; - _screen->_curPage = 2; - _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1); - _animator->_updateScreen = true; - _screen->_curPage = currPage; - } - - _animator->copyChangedObjectsForward(0); - updateTextFade(); - - if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && (!drawText || !snd_voiceIsPlaying())) - break; - - uint32 nextTime = loopStart + _tickLength; - - while (_system->getMillis() < nextTime) { - while (_eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_KEYDOWN: - if (event.kbd.keycode == '.') - _skipFlag = true; - break; - case Common::EVENT_QUIT: - quitGame(); - runLoop = false; - break; - case Common::EVENT_LBUTTONDOWN: - runLoop = false; - break; - default: - break; - } - } - - if (nextTime - _system->getMillis() >= 10) { - _system->delayMillis(10); - _system->updateScreen(); - } - } - - if (_skipFlag) - runLoop = false; - } - - snd_voiceWaitForFinish(); - snd_stopVoice(); - - enableTimer(14); - enableTimer(15); - enableTimer(18); - enableTimer(19); - //clearKyrandiaButtonIO(); -} - -void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) { - _charSayUnk3 = -1; - - if (charNum > 4 && charNum < 11) { - //TODO: weird _game_inventory stuff here - warning("STUB: endCharacterChat() for high charnums"); - } - - if (convoInitialized != 0) { - _talkingCharNum = -1; - if (_currentCharacter->currentAnimFrame != 88) - _currentCharacter->currentAnimFrame = 7; - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - } -} - -void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) { - _talkingCharNum = -1; - - if (charNum > 0 && charNum < 5) { - _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame; - _animator->animRefreshNPC(charNum); - } - - if (_currentCharacter->currentAnimFrame != 88) - _currentCharacter->currentAnimFrame = 7; - - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); -} - -void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) { - _talkingCharNum = 0; - - if (charNum < 5 && charNum > 0) - _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame; - - if (_currentCharacter->currentAnimFrame != 88) { - _currentCharacter->currentAnimFrame = 16; - if (_scaleMode != 0) - _currentCharacter->currentAnimFrame = 7; - } - - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); -} - -int8 KyraEngine::getChatPartnerNum() { - uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A}; - int pos = 0; - int partner = -1; - - for (int i = 1; i < 6; i++) { - if (_currentCharacter->sceneId == sceneTable[pos]) { - partner = sceneTable[pos+1]; - break; - } - pos += 2; - } - - for (int i = 1; i < 5; i++) { - if (_characterList[i].sceneId == _currentCharacter->sceneId) { - partner = i; - break; - } - } - return partner; -} - -int KyraEngine::initCharacterChat(int8 charNum) { - int returnValue = 0; - - if (_talkingCharNum == -1) { - returnValue = 1; - _talkingCharNum = 0; - - if (_currentCharacter->currentAnimFrame != 88) { - _currentCharacter->currentAnimFrame = 16; - if (_scaleMode != 0) - _currentCharacter->currentAnimFrame = 7; - } - - _animator->animRefreshNPC(0); - _animator->updateAllObjectShapes(); - } - - _charSayUnk2 = -1; - _animator->flagAllObjectsForBkgdChange(); - _animator->restoreAllObjectBackgrounds(); - - if (charNum > 4 && charNum < 11) { - // TODO: Fill in weird _game_inventory stuff here - warning("STUB: initCharacterChat() for high charnums"); - } - - _animator->flagAllObjectsForRefresh(); - _animator->flagAllObjectsForBkgdChange(); - _animator->preserveAnyChangedBackgrounds(); - _charSayUnk3 = charNum; - - return returnValue; -} - -void KyraEngine::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) { - debugC(9, kDebugLevelMain, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration); - uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 }; - - uint16 chatTicks; - int16 convoInitialized; - int8 chatPartnerNum; - - if (_currentCharacter->sceneId == 210) - return; - - convoInitialized = initCharacterChat(charNum); - chatPartnerNum = getChatPartnerNum(); - - if (chatPartnerNum >= 0 && chatPartnerNum < 5) - backupChatPartnerAnimFrame(chatPartnerNum); - - if (charNum < 5) { - _characterList[charNum].currentAnimFrame = startAnimFrames[charNum]; - _charSayUnk3 = charNum; - _talkingCharNum = charNum; - _animator->animRefreshNPC(charNum); - } - - char *processedString = _text->preprocessString(chatStr); - int lineNum = _text->buildMessageSubstrings(processedString); - - int16 yPos = _characterList[charNum].y1; - yPos -= ((_scaleTable[yPos] * _characterList[charNum].height) >> 8); - yPos -= 8; - yPos -= lineNum * 10; - - if (yPos < 11) - yPos = 11; - - if (yPos > 100) - yPos = 100; - - _text->_talkMessageY = yPos; - _text->_talkMessageH = lineNum * 10; - - if (textEnabled()) { - _animator->restoreAllObjectBackgrounds(); - - _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2); - _screen->hideMouse(); - - _text->printCharacterText(processedString, charNum, _characterList[charNum].x1); - _screen->showMouse(); - } - - if (chatDuration == -2) - chatTicks = strlen(processedString) * 9; - else - chatTicks = chatDuration; - - if (!speechEnabled()) - vocFile = -1; - waitForChatToFinish(vocFile, chatTicks, chatStr, charNum); - - if (textEnabled()) { - _animator->restoreAllObjectBackgrounds(); - - _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2); - _animator->preserveAllBackgrounds(); - _animator->prepDrawAllObjects(); - _screen->hideMouse(); - - _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0); - _screen->showMouse(); - _animator->flagAllObjectsForRefresh(); - _animator->copyChangedObjectsForward(0); - } - - if (chatPartnerNum != -1 && chatPartnerNum < 5) - restoreChatPartnerAnimFrame(chatPartnerNum); - - endCharacterChat(charNum, convoInitialized); -} - -void KyraEngine::drawSentenceCommand(const char *sentence, int color) { - debugC(9, kDebugLevelMain, "KyraEngine::drawSentenceCommand('%s', %i)", sentence, color); - _screen->hideMouse(); - _screen->fillRect(8, 143, 311, 152, 12); - - if (_startSentencePalIndex != color || _fadeText != false) { - _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3]; - _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1]; - _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2]; - - _screen->setScreenPalette(_screen->_currentPalette); - _startSentencePalIndex = 0; - } - - _text->printText(sentence, 8, 143, 0xFF, 12, 0); - _screen->showMouse(); - setTextFadeTimerCountdown(15); - _fadeText = false; -} - -void KyraEngine::updateSentenceCommand(const char *str1, const char *str2, int color) { - debugC(9, kDebugLevelMain, "KyraEngine::updateSentenceCommand('%s', '%s', %i)", str1, str2, color); - char sentenceCommand[500]; - strncpy(sentenceCommand, str1, 500); - if (str2) - strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand)); - - drawSentenceCommand(sentenceCommand, color); - _screen->updateScreen(); -} - -void KyraEngine::updateTextFade() { - debugC(9, kDebugLevelMain, "KyraEngine::updateTextFade()"); - if (!_fadeText) - return; - - bool finished = false; - for (int i = 0; i < 3; i++) - if (_currSentenceColor[i] > 4) - _currSentenceColor[i] -= 4; - else - if (_currSentenceColor[i]) { - _currSentenceColor[i] = 0; - finished = true; - } - - _screen->_currentPalette[765] = _currSentenceColor[0]; - _screen->_currentPalette[766] = _currSentenceColor[1]; - _screen->_currentPalette[767] = _currSentenceColor[2]; - _screen->setScreenPalette(_screen->_currentPalette); - - if (finished) { - _fadeText = false; - _startSentencePalIndex = -1; - } -} - TextDisplayer::TextDisplayer(KyraEngine *vm, Screen *screen) { _screen = screen; _vm = vm; diff --git a/engines/kyra/text_v1.cpp b/engines/kyra/text_v1.cpp new file mode 100644 index 0000000000..c04aa2105f --- /dev/null +++ b/engines/kyra/text_v1.cpp @@ -0,0 +1,399 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v1.h" +#include "kyra/screen_v1.h" +#include "kyra/text.h" +#include "kyra/animator_v1.h" +#include "kyra/sprites.h" +#include "kyra/timer.h" + +namespace Kyra { + +void KyraEngine_v1::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum); + bool hasUpdatedNPCs = false; + bool runLoop = true; + bool drawText = textEnabled(); + uint8 currPage; + Common::Event event; + + //while (towns_isEscKeyPressed() ) + //towns_getKey(); + + uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis(); + + if (_configVoice == 0 && chatDuration != -1) { + switch (_configTextspeed) { + case 0: + chatDuration *= 2; + break; + case 2: + chatDuration /= 4; + break; + case 3: + chatDuration = -1; + break; + } + } + + if (chatDuration != -1) + chatDuration *= _tickLength; + + if (vocFile != -1) { + snd_voiceWaitForFinish(); + snd_playVoiceFile(vocFile); + } + + _timer->disable(14); + _timer->disable(18); + _timer->disable(19); + + uint32 timeAtStart = _system->getMillis(); + uint32 loopStart; + while (runLoop) { + loopStart = _system->getMillis(); + if (_currentCharacter->sceneId == 210) + if (seq_playEnd()) + break; + + if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) { + hasUpdatedNPCs = true; + _timer->disable(15); + _currHeadShape = 4; + _animator->animRefreshNPC(0); + _animator->animRefreshNPC(_talkingCharNum); + + if (_charSayUnk2 != -1) { + _animator->sprites()[_charSayUnk2].active = 0; + _sprites->_anims[_charSayUnk2].play = false; + _charSayUnk2 = -1; + } + } + + _timer->update(); + _sprites->updateSceneAnims(); + _animator->restoreAllObjectBackgrounds(); + _animator->preserveAnyChangedBackgrounds(); + _animator->prepDrawAllObjects(); + + if (drawText) { + currPage = _screen->_curPage; + _screen->_curPage = 2; + _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1); + _animator->_updateScreen = true; + _screen->_curPage = currPage; + } + + _animator->copyChangedObjectsForward(0); + updateTextFade(); + + if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && (!drawText || !snd_voiceIsPlaying())) + break; + + uint32 nextTime = loopStart + _tickLength; + + while (_system->getMillis() < nextTime) { + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == '.') + _skipFlag = true; + break; + case Common::EVENT_QUIT: + quitGame(); + runLoop = false; + break; + case Common::EVENT_LBUTTONDOWN: + runLoop = false; + break; + default: + break; + } + } + + if (nextTime - _system->getMillis() >= 10) { + _system->delayMillis(10); + _system->updateScreen(); + } + } + + if (_skipFlag) + runLoop = false; + } + + snd_voiceWaitForFinish(); + snd_stopVoice(); + + _timer->enable(14); + _timer->enable(15); + _timer->enable(18); + _timer->enable(19); + //clearKyrandiaButtonIO(); +} + +void KyraEngine_v1::endCharacterChat(int8 charNum, int16 convoInitialized) { + _charSayUnk3 = -1; + + if (charNum > 4 && charNum < 11) { + //TODO: weird _game_inventory stuff here + warning("STUB: endCharacterChat() for high charnums"); + } + + if (convoInitialized != 0) { + _talkingCharNum = -1; + if (_currentCharacter->currentAnimFrame != 88) + _currentCharacter->currentAnimFrame = 7; + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + } +} + +void KyraEngine_v1::restoreChatPartnerAnimFrame(int8 charNum) { + _talkingCharNum = -1; + + if (charNum > 0 && charNum < 5) { + _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame; + _animator->animRefreshNPC(charNum); + } + + if (_currentCharacter->currentAnimFrame != 88) + _currentCharacter->currentAnimFrame = 7; + + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); +} + +void KyraEngine_v1::backupChatPartnerAnimFrame(int8 charNum) { + _talkingCharNum = 0; + + if (charNum < 5 && charNum > 0) + _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame; + + if (_currentCharacter->currentAnimFrame != 88) { + _currentCharacter->currentAnimFrame = 16; + if (_scaleMode != 0) + _currentCharacter->currentAnimFrame = 7; + } + + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); +} + +int8 KyraEngine_v1::getChatPartnerNum() { + uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A}; + int pos = 0; + int partner = -1; + + for (int i = 1; i < 6; i++) { + if (_currentCharacter->sceneId == sceneTable[pos]) { + partner = sceneTable[pos+1]; + break; + } + pos += 2; + } + + for (int i = 1; i < 5; i++) { + if (_characterList[i].sceneId == _currentCharacter->sceneId) { + partner = i; + break; + } + } + return partner; +} + +int KyraEngine_v1::initCharacterChat(int8 charNum) { + int returnValue = 0; + + if (_talkingCharNum == -1) { + returnValue = 1; + _talkingCharNum = 0; + + if (_currentCharacter->currentAnimFrame != 88) { + _currentCharacter->currentAnimFrame = 16; + if (_scaleMode != 0) + _currentCharacter->currentAnimFrame = 7; + } + + _animator->animRefreshNPC(0); + _animator->updateAllObjectShapes(); + } + + _charSayUnk2 = -1; + _animator->flagAllObjectsForBkgdChange(); + _animator->restoreAllObjectBackgrounds(); + + if (charNum > 4 && charNum < 11) { + // TODO: Fill in weird _game_inventory stuff here + warning("STUB: initCharacterChat() for high charnums"); + } + + _animator->flagAllObjectsForRefresh(); + _animator->flagAllObjectsForBkgdChange(); + _animator->preserveAnyChangedBackgrounds(); + _charSayUnk3 = charNum; + + return returnValue; +} + +void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration); + uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 }; + + uint16 chatTicks; + int16 convoInitialized; + int8 chatPartnerNum; + + if (_currentCharacter->sceneId == 210) + return; + + convoInitialized = initCharacterChat(charNum); + chatPartnerNum = getChatPartnerNum(); + + if (chatPartnerNum >= 0 && chatPartnerNum < 5) + backupChatPartnerAnimFrame(chatPartnerNum); + + if (charNum < 5) { + _characterList[charNum].currentAnimFrame = startAnimFrames[charNum]; + _charSayUnk3 = charNum; + _talkingCharNum = charNum; + _animator->animRefreshNPC(charNum); + } + + char *processedString = _text->preprocessString(chatStr); + int lineNum = _text->buildMessageSubstrings(processedString); + + int16 yPos = _characterList[charNum].y1; + yPos -= ((_scaleTable[yPos] * _characterList[charNum].height) >> 8); + yPos -= 8; + yPos -= lineNum * 10; + + if (yPos < 11) + yPos = 11; + + if (yPos > 100) + yPos = 100; + + _text->_talkMessageY = yPos; + _text->_talkMessageH = lineNum * 10; + + if (textEnabled()) { + _animator->restoreAllObjectBackgrounds(); + + _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2); + _screen->hideMouse(); + + _text->printCharacterText(processedString, charNum, _characterList[charNum].x1); + _screen->showMouse(); + } + + if (chatDuration == -2) + chatTicks = strlen(processedString) * 9; + else + chatTicks = chatDuration; + + if (!speechEnabled()) + vocFile = -1; + waitForChatToFinish(vocFile, chatTicks, chatStr, charNum); + + if (textEnabled()) { + _animator->restoreAllObjectBackgrounds(); + + _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2); + _animator->preserveAllBackgrounds(); + _animator->prepDrawAllObjects(); + _screen->hideMouse(); + + _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0); + _screen->showMouse(); + _animator->flagAllObjectsForRefresh(); + _animator->copyChangedObjectsForward(0); + } + + if (chatPartnerNum != -1 && chatPartnerNum < 5) + restoreChatPartnerAnimFrame(chatPartnerNum); + + endCharacterChat(charNum, convoInitialized); +} + +void KyraEngine_v1::drawSentenceCommand(const char *sentence, int color) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::drawSentenceCommand('%s', %i)", sentence, color); + _screen->hideMouse(); + _screen->fillRect(8, 143, 311, 152, 12); + + if (_startSentencePalIndex != color || _fadeText != false) { + _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3]; + _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1]; + _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2]; + + _screen->setScreenPalette(_screen->_currentPalette); + _startSentencePalIndex = 0; + } + + _text->printText(sentence, 8, 143, 0xFF, 12, 0); + _screen->showMouse(); + setTextFadeTimerCountdown(15); + _fadeText = false; +} + +void KyraEngine_v1::updateSentenceCommand(const char *str1, const char *str2, int color) { + debugC(9, kDebugLevelMain, "KyraEngine_v1::updateSentenceCommand('%s', '%s', %i)", str1, str2, color); + char sentenceCommand[500]; + strncpy(sentenceCommand, str1, 500); + if (str2) + strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand)); + + drawSentenceCommand(sentenceCommand, color); + _screen->updateScreen(); +} + +void KyraEngine_v1::updateTextFade() { + debugC(9, kDebugLevelMain, "KyraEngine_v1::updateTextFade()"); + if (!_fadeText) + return; + + bool finished = false; + for (int i = 0; i < 3; i++) { + if (_currSentenceColor[i] > 4) + _currSentenceColor[i] -= 4; + else + if (_currSentenceColor[i]) { + _currSentenceColor[i] = 0; + finished = true; + } + } + + _screen->_currentPalette[765] = _currSentenceColor[0]; + _screen->_currentPalette[766] = _currSentenceColor[1]; + _screen->_currentPalette[767] = _currSentenceColor[2]; + _screen->setScreenPalette(_screen->_currentPalette); + + if (finished) { + _fadeText = false; + _startSentencePalIndex = -1; + } +} + +} // end of namespace Kyra diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp index a35b701697..dff191cbe0 100644 --- a/engines/kyra/timer.cpp +++ b/engines/kyra/timer.cpp @@ -11,7 +11,7 @@ * 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 + * 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 @@ -24,269 +24,228 @@ */ #include "kyra/kyra.h" -#include "kyra/screen.h" -#include "kyra/animator.h" +#include "kyra/timer.h" -#include "common/system.h" +#include "common/func.h" +#include "common/savefile.h" namespace Kyra { -void KyraEngine::setupTimers() { - debugC(9, kDebugLevelMain, "KyraEngine::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() { - debugC(9, kDebugLevelMain, "KyraEngine::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; - } +namespace { +struct TimerResync : public Common::UnaryFunction<TimerEntry&, void> { + uint32 _tickLength, _curTime; + TimerResync(KyraEngine *vm, uint32 curTime) : _tickLength(vm->tickLength()), _curTime(curTime) {} + + void operator()(TimerEntry &entry) const { + if (entry.lastUpdate < 0) { + if ((entry.lastUpdate + _curTime) <= 0) + entry.nextRun = 0; + else + entry.nextRun = _curTime + entry.lastUpdate + entry.countdown * _tickLength; + } else { + uint32 nextRun = entry.lastUpdate + entry.countdown * _tickLength; + if (_curTime < nextRun) + nextRun = 0; + entry.nextRun = nextRun; } - if (_timers[i].nextRun < _timerNextRun) - _timerNextRun = _timers[i].nextRun; } -} - -void KyraEngine::clearNextEventTickCount() { - debugC(9, kDebugLevelMain, "KyraEngine::clearNextEventTickCount()"); - _timerNextRun = 0; -} +}; -void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTimerDelay(%i, %d)", timer, countdown); - _timers[timer].countdown = countdown; -} +struct TimerEqual : public Common::UnaryFunction<const TimerEntry&, bool> { + uint8 _id; + + TimerEqual(uint8 id) : _id(id) {} -int16 KyraEngine::getTimerDelay(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::getTimerDelay(%i)", timer); - return _timers[timer].countdown; -} + bool operator()(const TimerEntry &entry) const { + return entry.id == _id; + } +}; +} // end of anonymous namespace -void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTimerCountdown(%i, %i)", timer, countdown); - _timers[timer].countdown = countdown; - _timers[timer].nextRun = _system->getMillis() + countdown * _tickLength; +void TimerManager::reset() { + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + delete pos->func; + } - uint32 nextRun = _system->getMillis() + countdown * _tickLength; - if (nextRun < _timerNextRun) - _timerNextRun = nextRun; + _timers.clear(); } -void KyraEngine::enableTimer(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::enableTimer(%i)", timer); - _timers[timer].active = 1; -} +void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled) { + debugC(9, kDebugLevelTimer, "TimerManager::addTimer(%d, %p, %d, %d)", id, (const void*)func, countdown, enabled); -void KyraEngine::disableTimer(uint8 timer) { - debugC(9, kDebugLevelMain, "KyraEngine::disableTimer(%i)", timer); - _timers[timer].active = 0; + TimerEntry newTimer; + + newTimer.id = id; + newTimer.countdown = countdown; + newTimer.enabled = enabled ? 1 : 0; + newTimer.lastUpdate = newTimer.nextRun = 0; + newTimer.func = func; + + _timers.push_back(newTimer); } -void KyraEngine::timerUpdateHeadAnims(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::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}; +void TimerManager::update() { + debugC(9, kDebugLevelTimer, "TimerManager::update()"); - if (_talkingCharNum < 0) + if (_system->getMillis() < _nextRun) return; + + _nextRun += 99999; + + for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + if (pos->enabled && pos->countdown >= 0 && pos->nextRun <= _system->getMillis()) { + if (pos->func && *pos->func) + (*pos->func)(pos->id); + + uint32 curTime = _system->getMillis(); + pos->lastUpdate = curTime; + pos->nextRun = curTime + pos->countdown * _vm->tickLength(); + + _nextRun = MIN(_nextRun, pos->nextRun); + } + } +} - _currHeadShape = frameTable[currentFrame]; - currentFrame++; +void TimerManager::resync() { + debugC(9, kDebugLevelTimer, "TimerManager::resync()"); - if (frameTable[currentFrame] == -1) - currentFrame = 0; + _nextRun = 0; // force rerun + Common::for_each(_timers.begin(), _timers.end(), TimerResync(_vm, _system->getMillis())); +} - _animator->animRefreshNPC(0); - _animator->animRefreshNPC(_talkingCharNum); +void TimerManager::resetNextRun() { + debugC(9, kDebugLevelTimer, "TimerManager::resetNextRun()"); + _nextRun = 0; } -void KyraEngine::timerSetFlags1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags(%i)", timerNum); - if (_currentCharacter->sceneId == 0x1C) - return; +void TimerManager::setCountdown(uint8 id, int32 countdown) { + debugC(9, kDebugLevelTimer, "TimerManager::setCountdown(%d, %d)", id, countdown); - int rndNr = _rnd.getRandomNumberRng(0, 3); + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) { + timer->countdown = countdown; - for (int i = 0; i < 4; i++) { - if (!queryGameFlag(rndNr + 17)) { - setGameFlag(rndNr + 17); - break; - } else { - rndNr++; - if (rndNr > 3) - rndNr = 0; + if (countdown >= 0) { + uint32 curTime = _system->getMillis(); + timer->lastUpdate = curTime; + timer->nextRun = curTime + countdown * _vm->tickLength(); + + _nextRun = MIN(_nextRun, timer->nextRun); } + } else { + warning("TimerManager::setCountdown: No timer %d", id); } } -void KyraEngine::timerFadeText(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerFadeText(%i)", timerNum); - _fadeText = true; -} +void TimerManager::setDelay(uint8 id, int32 countdown) { + debugC(9, kDebugLevelTimer, "TimerManager::setDelay(%d, %d)", id, countdown); -void KyraEngine::updateAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag1(%d)", timerNum); - if (_brandonStatusBit & 2) { - _brandonStatusBit0x02Flag = 1; - } + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->countdown = countdown; + else + warning("TimerManager::setDelay: No timer %d", id); } -void KyraEngine::updateAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag2(%d)", timerNum); - if (_brandonStatusBit & 0x20) { - _brandonStatusBit0x20Flag = 1; - } -} +int32 TimerManager::getDelay(uint8 id) const { + debugC(9, kDebugLevelTimer, "TimerManager::getDelay(%d)", id); -void KyraEngine::setTextFadeTimerCountdown(int16 countdown) { - debugC(9, kDebugLevelMain, "KyraEngine::setTextFadeTimerCountdown(%i)", countdown); - //if (countdown == -1) - //countdown = 32000; + CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + return timer->countdown; - setTimerCountdown(31, countdown*60); + warning("TimerManager::getDelay: No timer %d", id); + return -1; } -void KyraEngine::timerSetFlags2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags2(%i)", timerNum); - if (!((uint32*)(_flagsTable+0x2D))[timerNum]) - ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; -} +bool TimerManager::isEnabled(uint8 id) const { + debugC(9, kDebugLevelTimer, "TimerManager::isEnabled(%d)", id); -void KyraEngine::timerCheckAnimFlag1(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x20) { - checkAmuletAnimFlags(); - setTimerCountdown(18, -1); - } -} + CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + return (timer->enabled == 1); -void KyraEngine::timerCheckAnimFlag2(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum); - if (_brandonStatusBit & 0x2) { - checkAmuletAnimFlags(); - setTimerCountdown(14, -1); - } + warning("TimerManager::isEnabled: No timer %d", id); + return false; } -void KyraEngine::checkAmuletAnimFlags() { - debugC(9, kDebugLevelMain, "KyraEngine::checkSpecialAnimFlags()"); - if (_brandonStatusBit & 2) { - seq_makeBrandonNormal2(); - setTimerCountdown(19, 300); - } - - if (_brandonStatusBit & 0x20) { - seq_makeBrandonNormal(); - setTimerCountdown(19, 300); - } -} +void TimerManager::enable(uint8 id) { + debugC(9, kDebugLevelTimer, "TimerManager::enable(%d)", id); -void KyraEngine::timerRedrawAmulet(int timerNum) { - debugC(9, kDebugLevelMain, "KyraEngine::timerRedrawAmulet(%i)", timerNum); - if (queryGameFlag(0xF1)) { - drawAmulet(); - setTimerCountdown(19, -1); - } + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->enabled = 1; + else + warning("TimerManager::enable: No timer %d", id); } -void KyraEngine::drawAmulet() { - debugC(9, kDebugLevelMain, "KyraEngine::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}; +void TimerManager::disable(uint8 id) { + debugC(9, kDebugLevelTimer, "TimerManager::disable(%d)", id); - resetGameFlag(0xF1); - _screen->hideMouse(); - - int i = 0; - while (amuletTable1[i] != -1) { - if (queryGameFlag(87)) - _screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0); - - if (queryGameFlag(89)) - _screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0); - - if (queryGameFlag(86)) - _screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0); - - if (queryGameFlag(88)) - _screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0); + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) + timer->enabled = 0; + else + warning("TimerManager::disable: No timer %d", id); +} - _screen->updateScreen(); - delayWithTicks(3); - i++; +void TimerManager::loadDataFromFile(Common::InSaveFile *file, int version) { + debugC(9, kDebugLevelTimer, "TimerManager::loadDataFromFile(%p, %d)", (const void*)file, version); + + if (version <= 7) { + _nextRun = 0; + for (int i = 0; i < 32; ++i) { + uint8 enabled = file->readByte(); + int32 countdown = file->readSint32BE(); + uint32 nextRun = file->readUint32BE(); + + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(i)); + if (timer != _timers.end()) { + timer->enabled = enabled; + timer->countdown = countdown; + + if (nextRun) { + timer->nextRun = nextRun + _system->getMillis(); + timer->lastUpdate = timer->nextRun - countdown * _vm->tickLength(); + } else { + uint32 curTime = _system->getMillis(); + timer->nextRun = curTime; + timer->lastUpdate = curTime - countdown * _vm->tickLength(); + } + } else { + warning("Loading timer data for non existing timer %d", i); + } + } + } else { + int entries = file->readByte(); + for (int i = 0; i < entries; ++i) { + uint8 id = file->readByte(); + + Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id)); + if (timer != _timers.end()) { + timer->enabled = file->readByte(); + timer->countdown = file->readSint32BE(); + timer->lastUpdate = file->readSint32BE(); + } else { + warning("Loading timer data for non existing timer %d", id); + file->seek(7, SEEK_CUR); + } + } + + resync(); } - _screen->showMouse(); } -void KyraEngine::setWalkspeed(uint8 newSpeed) { - debugC(9, kDebugLevelMain, "KyraEngine::setWalkspeed(%i)", newSpeed); - static const uint8 speeds[] = {11, 9, 6, 5, 3}; - - assert(newSpeed < ARRAYSIZE(speeds)); - setTimerDelay(5, speeds[newSpeed]); +void TimerManager::saveDataToFile(Common::OutSaveFile *file) const { + debugC(9, kDebugLevelTimer, "TimerManager::saveDataToFile(%p)", (const void*)file); + + file->writeByte(count()); + for (CIterator pos = _timers.begin(); pos != _timers.end(); ++pos) { + file->writeByte(pos->id); + file->writeByte(pos->enabled); + file->writeSint32BE(pos->countdown); + file->writeSint32BE(pos->lastUpdate - _system->getMillis()); + } } } // end of namespace Kyra - diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h new file mode 100644 index 0000000000..1edeb92a42 --- /dev/null +++ b/engines/kyra/timer.h @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_TIMER_H +#define KYRA_TIMER_H + +#include "kyra/kyra.h" +#include "kyra/util.h" + +#include "common/list.h" + +namespace Common { +class InSaveFile; +class OutSaveFile; +} // end of namespace Common + +namespace Kyra { + +typedef Functor1<int, void> TimerFunc; + +struct TimerEntry { + uint8 id; + int32 countdown; + int8 enabled; + + int32 lastUpdate; + uint32 nextRun; + + TimerFunc *func; +}; + +class TimerManager { +public: + TimerManager(KyraEngine *vm, OSystem *sys) : _vm(vm), _system(sys), _timers(), _nextRun(0) {} + ~TimerManager() { reset(); } + + void reset(); + + void addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled); + + int count() const { return _timers.size(); } + + void update(); + + void resetNextRun(); + + void setCountdown(uint8 id, int32 countdown); + void setDelay(uint8 id, int32 countdown); + int32 getDelay(uint8 id) const; + + bool isEnabled(uint8 id) const; + void enable(uint8 id); + void disable(uint8 id); + + void resync(); + + void loadDataFromFile(Common::InSaveFile *file, int version); + void saveDataToFile(Common::OutSaveFile *file) const; +private: + KyraEngine *_vm; + OSystem *_system; + Common::List<TimerEntry> _timers; + uint32 _nextRun; + + typedef Common::List<TimerEntry>::iterator Iterator; + typedef Common::List<TimerEntry>::const_iterator CIterator; +}; + +} // end of namespace Kyra + +#endif diff --git a/engines/kyra/timer_v1.cpp b/engines/kyra/timer_v1.cpp new file mode 100644 index 0000000000..55dab4413f --- /dev/null +++ b/engines/kyra/timer_v1.cpp @@ -0,0 +1,180 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra.h" +#include "kyra/kyra_v1.h" +#include "kyra/screen.h" +#include "kyra/animator_v1.h" +#include "kyra/timer.h" + +#include "common/system.h" + +namespace Kyra { + +#define TimerV1(x) new Functor1Mem<int, void, KyraEngine_v1>(this, &KyraEngine_v1::x) + +void KyraEngine_v1::setupTimers() { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setupTimers()"); + + for (int i = 0; i <= 4; ++i) + _timer->addTimer(i, 0, -1, 1); + + _timer->addTimer(5, 0, 5, 1); + _timer->addTimer(6, 0, 7, 1); + _timer->addTimer(7, 0, 8, 1); + _timer->addTimer(8, 0, 9, 1); + _timer->addTimer(9, 0, 7, 1); + + for (int i = 10; i <= 13; ++i) + _timer->addTimer(i, 0, 420, 1); + + _timer->addTimer(14, TimerV1(timerCheckAnimFlag2), 600, 1); + _timer->addTimer(15, TimerV1(timerUpdateHeadAnims), 11, 1); + _timer->addTimer(16, TimerV1(timerSetFlags1), 7200, 1); + _timer->addTimer(17, 0 /*sub_15120*/, 7200, 1); + _timer->addTimer(18, TimerV1(timerCheckAnimFlag1), 600, 1); + _timer->addTimer(19, TimerV1(timerRedrawAmulet), 600, 1); + + _timer->addTimer(20, 0, 7200, 1); + _timer->addTimer(21, 0/*sub_1517C*/, 18000, 1); + _timer->addTimer(22, 0, 7200, 1); + + for (int i = 23; i <= 27; ++i) + _timer->addTimer(i, 0, 10800, 1); + + _timer->addTimer(28, 0, 21600, 1); + _timer->addTimer(29, 0, 7200, 1); + _timer->addTimer(30, 0, 10800, 1); + + _timer->addTimer(31, TimerV1(timerFadeText), -1, 1); + _timer->addTimer(32, TimerV1(updateAnimFlag1), 9, 1); + _timer->addTimer(33, TimerV1(updateAnimFlag2), 3, 1); +} + +void KyraEngine_v1::timerUpdateHeadAnims(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::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; + + _animator->animRefreshNPC(0); + _animator->animRefreshNPC(_talkingCharNum); +} + +void KyraEngine_v1::timerSetFlags1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::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_v1::timerFadeText(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerFadeText(%i)", timerNum); + _fadeText = true; +} + +void KyraEngine_v1::updateAnimFlag1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag1(%d)", timerNum); + if (_brandonStatusBit & 2) { + _brandonStatusBit0x02Flag = 1; + } +} + +void KyraEngine_v1::updateAnimFlag2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag2(%d)", timerNum); + if (_brandonStatusBit & 0x20) { + _brandonStatusBit0x20Flag = 1; + } +} + +void KyraEngine_v1::setTextFadeTimerCountdown(int16 countdown) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setTextFadeTimerCountdown(%i)", countdown); + if (countdown == -1) + countdown = 32000; + + _timer->setCountdown(31, countdown*60); +} + +void KyraEngine_v1::timerSetFlags2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerSetFlags2(%i)", timerNum); + if (!((uint32*)(_flagsTable+0x2D))[timerNum]) + ((uint32*)(_flagsTable+0x2D))[timerNum] = 1; +} + +void KyraEngine_v1::timerCheckAnimFlag1(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag1(%i)", timerNum); + if (_brandonStatusBit & 0x20) { + checkAmuletAnimFlags(); + _timer->setCountdown(18, -1); + } +} + +void KyraEngine_v1::timerCheckAnimFlag2(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag2(%i)", timerNum); + if (_brandonStatusBit & 0x2) { + checkAmuletAnimFlags(); + _timer->setCountdown(14, -1); + } +} + +void KyraEngine_v1::timerRedrawAmulet(int timerNum) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerRedrawAmulet(%i)", timerNum); + if (queryGameFlag(0xF1)) { + drawAmulet(); + _timer->setCountdown(19, -1); + } +} + +void KyraEngine_v1::setWalkspeed(uint8 newSpeed) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setWalkspeed(%i)", newSpeed); + static const uint8 speeds[] = {11, 9, 6, 5, 3}; + + assert(newSpeed < ARRAYSIZE(speeds)); + _timer->setDelay(5, speeds[newSpeed]); +} + +} // end of namespace Kyra + diff --git a/engines/kyra/timer_v2.cpp b/engines/kyra/timer_v2.cpp new file mode 100644 index 0000000000..2db90f6ecc --- /dev/null +++ b/engines/kyra/timer_v2.cpp @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/kyra_v2.h" +#include "kyra/timer.h" + +namespace Kyra { + +#define TimerV2(x) new Functor1Mem<int, void, KyraEngine_v2>(this, &KyraEngine_v2::x) + +void KyraEngine_v2::setupTimers() { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::setupTimers()"); + + _timer->addTimer(0, 0, 5, 1); + _timer->addTimer(1, TimerV2(timerFunc2), -1, 1); + _timer->addTimer(2, TimerV2(timerFunc3), 1, 1); + _timer->addTimer(3, TimerV2(timerFunc4), 1, 0); + _timer->addTimer(4, TimerV2(timerFunc5), 1, 0); + _timer->addTimer(5, TimerV2(timerFunc6), 1, 0); +} + +void KyraEngine_v2::timerFunc2(int arg) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc2(%d)", arg); + if (_shownMessage) + _msgUnk1 = 1; +} + +void KyraEngine_v2::timerFunc3(int arg) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc3(%d)", arg); + // XXX +} + +void KyraEngine_v2::timerFunc4(int arg) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc4(%d)", arg); + _timer->disable(3); + setGameFlag(0xD8); +} + +void KyraEngine_v2::timerFunc5(int arg) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc5(%d)", arg); + // XXX +} + +void KyraEngine_v2::timerFunc6(int arg) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc6(%d)", arg); + // XXX +} + +void KyraEngine_v2::setTimer1DelaySecs(int secs) { + debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::setTimer1DelaySecs(%d)", secs); + + if (secs == -1) + secs = 32000; + + _timer->setCountdown(1, secs * 60); +} + +} // end of namespace Kyra diff --git a/engines/kyra/util.h b/engines/kyra/util.h new file mode 100644 index 0000000000..98692df015 --- /dev/null +++ b/engines/kyra/util.h @@ -0,0 +1,63 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_UTIL_H +#define KYRA_UTIL_H + +#include "common/func.h" + +namespace Kyra { + +template<class Arg, class Res> +struct Functor1 : public Common::UnaryFunction<Arg, Res> { + virtual ~Functor1() {} + + virtual operator bool() const = 0; + virtual Res operator()(Arg) const = 0; +}; + +template<class Arg, class Res, class T> +class Functor1Mem : public Functor1<Arg, Res> { +public: + typedef Res (T::*FuncType)(Arg); + + Functor1Mem(T *t, const FuncType &func) : _t(t), _func(func) {} + + operator bool() const { return _func != 0; } + Res operator()(Arg v1) const { + return (_t->*_func)(v1); + } +private: + mutable T *_t; + Res (T::*_func)(Arg); +}; + +struct ScriptState; + +typedef Functor1<ScriptState*, int> Opcode; + +} // end of namespace Kyra + +#endif diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp index f0119101fd..7e9ec9b78b 100644 --- a/engines/kyra/wsamovie.cpp +++ b/engines/kyra/wsamovie.cpp @@ -28,10 +28,11 @@ #include "common/system.h" #include "kyra/kyra.h" +#include "kyra/kyra_v2.h" #include "kyra/screen.h" +#include "kyra/screen_v2.h" #include "kyra/wsamovie.h" - namespace Kyra { WSAMovieV1::WSAMovieV1(KyraEngine *vm) : Movie(vm) {} WSAMovieV1::~WSAMovieV1() { close(); } @@ -132,8 +133,8 @@ void WSAMovieV1::close() { } } -void WSAMovieV1::displayFrame(int frameNum) { - debugC(9, kDebugLevelMovie, "WSAMovieV1::displayFrame(%d)", frameNum); +void WSAMovieV1::displayFrame(int frameNum, ...) { + debugC(9, kDebugLevelMovie, "WSAMovieV1::displayFrame(%d, ...)", frameNum); if (frameNum >= _numFrames || !_opened) return; @@ -234,7 +235,7 @@ void WSAMovieAmiga::close() { WSAMovieV1::close(); } -void WSAMovieAmiga::displayFrame(int frameNum) { +void WSAMovieAmiga::displayFrame(int frameNum, ...) { debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d)", frameNum); if (frameNum >= _numFrames || !_opened) return; @@ -340,7 +341,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) { #pragma mark - -WSAMovieV2::WSAMovieV2(KyraEngine *vm) : WSAMovieV1(vm), _xAdd(0), _yAdd(0) {} +WSAMovieV2::WSAMovieV2(KyraEngine_v2 *vm) : WSAMovieV1(vm), _vm(vm), _xAdd(0), _yAdd(0), _oldOff(false) {} int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) { debugC(9, kDebugLevelMovie, "WSAMovieV2::open('%s', %d, %p)", filename, unk1, (const void *)palBuf); @@ -419,5 +420,95 @@ int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) { return _numFrames; } +void WSAMovieV2::displayFrame(int frameNum, ...) { + debugC(9, kDebugLevelMovie, "WSAMovieV2::displayFrame(%d, ...)", frameNum); + if (frameNum >= _numFrames || !_opened) + return; + + uint8 *dst = 0; + if (_flags & WF_OFFSCREEN_DECODE) + dst = _offscreenBuffer; + else + dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height); + + if (_currentFrame == _numFrames) { + if (!(_flags & WF_NO_FIRST_FRAME)) { + if (_flags & WF_OFFSCREEN_DECODE) + Screen::decodeFrameDelta(dst, _deltaBuffer); + else + Screen::decodeFrameDeltaPage(dst, _deltaBuffer, _width, (_flags & WF_XOR) == 0); + } + _currentFrame = 0; + } + + // try to reduce the number of needed frame operations + int diffCount = ABS(_currentFrame - frameNum); + int frameStep = 1; + int frameCount; + if (_currentFrame < frameNum) { + frameCount = _numFrames - frameNum + _currentFrame; + if (diffCount > frameCount) + frameStep = -1; + else + frameCount = diffCount; + } else { + frameCount = _numFrames - _currentFrame + frameNum; + if (frameCount >= diffCount) { + frameStep = -1; + frameCount = diffCount; + } + } + + // process + if (frameStep > 0) { + uint16 cf = _currentFrame; + while (frameCount--) { + cf += frameStep; + processFrame(cf, dst); + if (cf == _numFrames) + cf = 0; + } + } else { + uint16 cf = _currentFrame; + while (frameCount--) { + if (cf == 0) + cf = _numFrames; + processFrame(cf, dst); + cf += frameStep; + } + } + + // display + _currentFrame = frameNum; + if (_flags & WF_OFFSCREEN_DECODE) { + if (_oldOff) { + // Kyrandia 1 offscreen buffer -> screen copy method of Kyrandia 1, needs to be present + // for our intro code that doesn't supply all the needed parameters for the Kyrandia 2 method + _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer); + } else { + // This is the offscreen buffer -> screen copy method of Kyrandia 2 as it's implemented + // in the original, we use this in game + Screen_v2 *screen = _vm->screen_v2(); + int pageBackUp = screen->_curPage; + screen->_curPage = _drawPage; + + va_list args; + va_start(args, frameNum); + + int copyParam = va_arg(args, int); + int plotFunc = (copyParam & 0xFF00) >> 12; + int unk1 = copyParam & 0xFF; + + const uint8 *unkPtr1 = va_arg(args, const uint8*); + const uint8 *unkPtr2 = va_arg(args, const uint8*); + va_end(args); + + screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, unkPtr1, unkPtr2); + + screen->_curPage = pageBackUp; + } + } +} + } // end of namespace Kyra diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h index a3af9f16b7..0e93bd2a93 100644 --- a/engines/kyra/wsamovie.h +++ b/engines/kyra/wsamovie.h @@ -35,6 +35,7 @@ class SoundHandle; namespace Kyra { class KyraEngine; +class KyraEngine_v2; class Movie { public: @@ -48,7 +49,7 @@ public: virtual int frames() = 0; - virtual void displayFrame(int frameNum) = 0; + virtual void displayFrame(int frameNum, ...) = 0; virtual void setX(int x) { _x = x; } virtual void setY(int y) { _y = y; } @@ -71,7 +72,7 @@ public: virtual int frames() { return _opened ? _numFrames : -1; } - virtual void displayFrame(int frameNum); + virtual void displayFrame(int frameNum, ...); enum WSAFlags { WF_OFFSCREEN_DECODE = 0x10, @@ -101,7 +102,7 @@ public: int open(const char *filename, int offscreen, uint8 *palette); void close(); - void displayFrame(int frameNum); + void displayFrame(int frameNum, ...); private: void processFrame(int frameNum, uint8 *dst); @@ -110,9 +111,11 @@ private: class WSAMovieV2 : public WSAMovieV1 { public: - WSAMovieV2(KyraEngine *vm); + WSAMovieV2(KyraEngine_v2 *vm); int open(const char *filename, int unk1, uint8 *palette); + + virtual void displayFrame(int frameNum, ...); void setX(int x) { _x = x + _xAdd; } void setY(int y) { _y = y + _yAdd; } @@ -122,10 +125,15 @@ public: int width() const { return _width; } int height() const { return _height; } -protected: + // HACK for our intro code + void flagOldOff(bool enabled) { _oldOff = enabled; } +protected: + KyraEngine_v2 *_vm; + int16 _xAdd; int16 _yAdd; + bool _oldOff; // old offscreen copy, HACK for our intro code }; } // end of namespace Kyra |