From 1c660c452436fbcf2e5d06f1e10cc7c236ee11b5 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:11:55 +0000 Subject: Implemented opcode 56: o3_updateScore. svn-id: r31704 --- engines/kyra/gui_v3.cpp | 66 ++++++++++++++++++++++++++++++++++++++++- engines/kyra/kyra_v3.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++--- engines/kyra/kyra_v3.h | 14 +++++++++ engines/kyra/script_v3.cpp | 7 ++++- engines/kyra/staticres.cpp | 30 +++++++++++++++++++ 5 files changed, 185 insertions(+), 6 deletions(-) diff --git a/engines/kyra/gui_v3.cpp b/engines/kyra/gui_v3.cpp index c797ca0812..9371f3dca2 100644 --- a/engines/kyra/gui_v3.cpp +++ b/engines/kyra/gui_v3.cpp @@ -110,7 +110,7 @@ void KyraEngine_v3::showInventory() { redrawInventory(30); drawMalcolmsMoodPointer(-1, 30); - //XXX + drawScore(30, 215, 191); if (queryGameFlag(0x97)) drawJestersStaff(1, 30); @@ -312,6 +312,70 @@ void KyraEngine_v3::drawJestersStaff(int type, int page) { _screen->drawShape(page, getShapePtr(shape), 217, y, 0, 0); } +void KyraEngine_v3::drawScore(int page, int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::drawScore(%d, %d, %d)", page, x, y); + if (page == 30) { + page = 2; + y -= 144; + } + + int shape1 = _score / 100; + int shape2 = (_score - shape1*100) / 10; + int shape3 = _score % 10; + + _screen->drawShape(page, getShapePtr(shape1+433), x, y, 0, 0); + x += 8; + _screen->drawShape(page, getShapePtr(shape2+433), x, y, 0, 0); + x += 8; + _screen->drawShape(page, getShapePtr(shape3+433), x, y, 0, 0); +} + +void KyraEngine_v3::drawScoreCounting(int oldScore, int newScore, int drawOld, const int x) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::drawScoreCounting(%d, %d, %d, %d)", oldScore, newScore, drawOld, x); + int y = 189; + if (_inventoryState) + y -= 44; + + int old100 = oldScore / 100; + int old010 = (oldScore - old100*100) / 10; + int old001 = oldScore % 10; + + int new100 = newScore / 100; + int new010 = (newScore - new100*100) / 10; + int new001 = newScore % 10; + + if (drawOld) { + _screen->drawShape(0, getShapePtr(old100+433), x + 0, y, 0, 0); + _screen->drawShape(0, getShapePtr(old010+433), x + 8, y, 0, 0); + _screen->drawShape(0, getShapePtr(old001+433), x + 16, y, 0, 0); + } + + if (old100 != new100) + _screen->drawShape(0, getShapePtr(old100+443), x + 0, y, 0, 0); + + if (old010 != new010) + _screen->drawShape(0, getShapePtr(old010+443), x + 8, y, 0, 0); + + _screen->drawShape(0, getShapePtr(old001+443), x + 16, y, 0, 0); + + _screen->drawShape(0, getShapePtr(new100+433), x + 0, y, 0, 0); + _screen->drawShape(0, getShapePtr(new010+433), x + 8, y, 0, 0); + _screen->drawShape(0, getShapePtr(new001+433), x + 16, y, 0, 0); +} + +int KyraEngine_v3::getScoreX(const char *str) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::getScoreX('%s')", str); + Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT); + _screen->_charWidth = -2; + + int width = _screen->getTextWidth(str); + int x = 160 + (width / 2) - 32; + + _screen->setFont(oldFont); + _screen->_charWidth = 0; + return x; +} + void KyraEngine_v3::redrawInventory(int page) { debugC(9, kDebugLevelMain, "KyraEngine_v3::redrawInventory(%d)", page); int yOffset = 0; diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 0fbe3de456..0cabfc36f6 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -128,6 +128,8 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _inventoryScrollSpeed = -1; _invWsa = 0; _invWsaFrame = -1; + _score = 0; + memset(_scoreFlagTable, 0, sizeof(_scoreFlagTable)); } KyraEngine_v3::~KyraEngine_v3() { @@ -544,11 +546,13 @@ void KyraEngine_v3::startup() { musicUpdate(0); if (!loadLanguageFile("ITEMS.", _itemFile)) - error("couldn't load ITEMS"); + error("Couldn't load ITEMS"); + if (!loadLanguageFile("SCORE.", _scoreFile)) + error("Couldn't load SCORE"); if (!loadLanguageFile("C_CODE.", _cCodeFile)) - error("couldn't load C_CODE"); + error("Couldn't load C_CODE"); if (!loadLanguageFile("SCENES.", _scenesFile)) - error("couldn't load SCENES"); + error("Couldn't load SCENES"); //XXX @@ -605,7 +609,11 @@ void KyraEngine_v3::startup() { clearAnimObjects(); - //XXX + _scoreMax = 0; + for (int i = 0; i < _scoreTableSize; ++i) { + if (_scoreTable[i] > 0) + _scoreMax += _scoreTable[i]; + } musicUpdate(0); memset(_hiddenItems, -1, sizeof(_hiddenItems)); @@ -1594,6 +1602,64 @@ void KyraEngine_v3::runTemporaryScript(const char *filename, int allowSkip, int _scriptInterpreter->unloadScript(&_temporaryScriptData); } +#pragma mark - + +bool KyraEngine_v3::updateScore(int scoreId, int strId) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::updateScore(%d, %d)", scoreId, strId); + + int scoreIndex = (scoreId >> 3); + int scoreBit = scoreId & 7; + if ((_scoreFlagTable[scoreIndex] & (1 << scoreBit)) != 0) + return false; + + setNextIdleAnimTimer(); + _scoreFlagTable[scoreIndex] |= (1 << scoreBit); + + _screen->hideMouse(); + strcpy(_stringBuffer, (const char*)getTableEntry(_scoreFile, strId)); + strcat(_stringBuffer, ": "); + + assert(scoreId < _scoreTableSize); + + int count = _scoreTable[scoreId]; + if (count > 0) + scoreIncrease(count, _stringBuffer); + + _screen->showMouse(); + setNextIdleAnimTimer(); + return true; +} + +void KyraEngine_v3::scoreIncrease(int count, const char *str) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::scoreIncrease(%d, '%s')", count, str); + int drawOld = 1; + _screen->hideMouse(); + + showMessage(str, 0xFF, 0xF0); + const int x = getScoreX(str); + + for (int i = 0; i < count; ++i) { + int oldScore = _score; + int newScore = ++_score; + + if (newScore > _scoreMax) { + _score = _scoreMax; + break; + } + + drawScoreCounting(oldScore, newScore, drawOld, x); + if (_inventoryState) + drawScore(0, 215, 191); + _screen->updateScreen(); + delay(20, true); + + playSoundEffect(0x0E, 0xC8); + drawOld = 0; + } + + _screen->showMouse(); +} + #pragma mark - Movie *KyraEngine_v3::createWSAMovie() { diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 440596cb58..2762b80e2b 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -266,6 +266,10 @@ private: void drawMalcolmsMoodText(); void drawMalcolmsMoodPointer(int frame, int page); void drawJestersStaff(int type, int page); + + void drawScore(int page, int x, int y); + void drawScoreCounting(int oldScore, int newScore, int drawOld, const int x); + int getScoreX(const char *str); static const uint8 _inventoryX[]; static const uint8 _inventoryY[]; @@ -650,6 +654,15 @@ private: char *_stringBuffer; + int _score; + int _scoreMax; + + static const int8 _scoreTable[]; + static const int _scoreTableSize; + int8 _scoreFlagTable[26]; + bool updateScore(int scoreId, int strId); + void scoreIncrease(int count, const char *str); + // opcodes int o3_getMalcolmShapes(ScriptState *script); int o3_setCharacterPos(ScriptState *script); @@ -684,6 +697,7 @@ private: int o3_wipeDownMouseItem(ScriptState *script); int o3_setMalcolmsMood(ScriptState *script); int o3_delay(ScriptState *script); + int o3_updateScore(ScriptState *script); int o3_setSceneFilename(ScriptState *script); int o3_drawSceneShape(ScriptState *script); int o3_checkInRect(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 09af5b169e..172645eaad 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -317,6 +317,11 @@ int KyraEngine_v3::o3_delay(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_updateScore(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_updateScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + return updateScore(stackPos(0), stackPos(1)) ? 1 : 0; +} + int KyraEngine_v3::o3_setSceneFilename(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setSceneFilename(%p) (%d, '%s')", (const void *)script, stackPos(0), stackPosString(1)); strcpy(_sceneList[stackPos(0)].filename1, stackPosString(1)); @@ -1093,7 +1098,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_delay); // 0x38 - OpcodeUnImpl(); + Opcode(o3_updateScore); OpcodeUnImpl(); Opcode(o3_setSceneFilename); OpcodeUnImpl(); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index abafeceeb4..0ab1deb9bf 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -2400,5 +2400,35 @@ const uint8 KyraEngine_v3::_itemStringInv[] = { 0x6, 0x9, 0x2, 0xC }; +const int8 KyraEngine_v3::_scoreTable[] = { + 10, 8, 5, 9, 10, 10, 7, 8, + 9, 9, 8, 8, 7, 8, 5, 9, + 6, 10, 7, 8, 5, 9, 6, 6, + 7, 8, 5, 9, 6, 8, 7, 8, + 5, 9, 6, 10, 7, 8, 5, 5, + 5, 7, 5, 7, 10, 5, 10, 5, + 5, 8, 6, 8, 7, 5, 5, 8, + 6, 9, 5, 7, 6, 5, 5, 7, + 7, 7, 6, 5, 8, 6, 10, 5, + 7, 5, 10, 5, 5, 5, 5, 7, + 5, 8, 9, 7, 7, 6, 10, 6, + 5, 10, 8, 5, 8, 6, 10, 5, + 5, 8, 8, 5, 7, 7, 7, 6, + 8, 9, 8, 8, 6, 5, 7, 6, + 5, 8, 15, 7, 9, 6, 6, 8, + 5, 8, 15, 15, 5, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const int KyraEngine_v3::_scoreTableSize = ARRAYSIZE(KyraEngine_v3::_scoreTable); + } // End of namespace Kyra -- cgit v1.2.3 From f0cbfff93e2beb98bd50d86524de1c9f8c0de9bf Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:18:10 +0000 Subject: Implemented opcode 60: o3_removeItemsFromScene. svn-id: r31705 --- engines/kyra/kyra_v3.h | 1 + engines/kyra/script_v3.cpp | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 2762b80e2b..7279b52c5e 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -699,6 +699,7 @@ private: int o3_delay(ScriptState *script); int o3_updateScore(ScriptState *script); int o3_setSceneFilename(ScriptState *script); + int o3_removeItemsFromScene(ScriptState *script); int o3_drawSceneShape(ScriptState *script); int o3_checkInRect(ScriptState *script); int o3_updateConversations(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 172645eaad..cedc182278 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -329,6 +329,26 @@ int KyraEngine_v3::o3_setSceneFilename(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_removeItemsFromScene(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_removeItemsFromScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + const uint16 itemId = stackPos(0); + const uint16 sceneId = stackPos(1); + const bool allItems = (stackPos(2) != 0); + + int retValue = 0; + + for (int i = 0; i < 50; ++i) { + if (_itemList[i].sceneId == sceneId && _itemList[i].id == itemId) { + resetItem(i); + retValue = 1; + if (!allItems) + return 1; + } + } + + return retValue; +} + int KyraEngine_v3::o3_drawSceneShape(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_drawSceneShape(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); const int shape = stackPos(0); @@ -1103,7 +1123,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_setSceneFilename); OpcodeUnImpl(); // 0x3c - OpcodeUnImpl(); + Opcode(o3_removeItemsFromScene); OpcodeUnImpl(); OpcodeUnImpl(); Opcode(o3_drawSceneShape); -- cgit v1.2.3 From 18dde5420cce566889b137aa3685ced4ba420e41 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:20:32 +0000 Subject: Fixed hand item reset on scene enter. svn-id: r31706 --- engines/kyra/scene_v3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index 27144ff505..977d9540f8 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -161,7 +161,7 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 setNextIdleAnimTimer(); - if (_itemInHand <= 0) { + if (_itemInHand < 0) { _itemInHand = -1; _handItemSet = -1; _screen->setMouseCursor(0, 0, _gameShapes[0]); -- cgit v1.2.3 From 44d44ddf05c4572877b3714c829019a2907c9b89 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:27:27 +0000 Subject: Added screen update in KyraEngine_v3::drawScoreCounting. svn-id: r31707 --- engines/kyra/gui_v3.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/engines/kyra/gui_v3.cpp b/engines/kyra/gui_v3.cpp index 9371f3dca2..644c7bb57a 100644 --- a/engines/kyra/gui_v3.cpp +++ b/engines/kyra/gui_v3.cpp @@ -358,6 +358,8 @@ void KyraEngine_v3::drawScoreCounting(int oldScore, int newScore, int drawOld, c _screen->drawShape(0, getShapePtr(old001+443), x + 16, y, 0, 0); + _screen->updateScreen(); + _screen->drawShape(0, getShapePtr(new100+433), x + 0, y, 0, 0); _screen->drawShape(0, getShapePtr(new010+433), x + 8, y, 0, 0); _screen->drawShape(0, getShapePtr(new001+433), x + 16, y, 0, 0); -- cgit v1.2.3 From 2b9a786e795363a627720a08aef8e5ab2fe019de Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:34:07 +0000 Subject: Opcode 53 is o3_playSoundEffect. svn-id: r31708 --- engines/kyra/script_v3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index cedc182278..73fca67b58 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -1114,7 +1114,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_dummy); // 0x34 Opcode(o3_setMalcolmsMood); - OpcodeUnImpl(); + Opcode(o3_playSoundEffect); Opcode(o3_dummy); Opcode(o3_delay); // 0x38 -- cgit v1.2.3 From a546869dac2b455705c3a6db9a86bc7b523e1ea8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:38:08 +0000 Subject: Implemented opcode temporary 4: o3t_setNewShapeFlag. svn-id: r31709 --- engines/kyra/kyra_v3.h | 1 + engines/kyra/script_v3.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 7279b52c5e..2184dc8ae9 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -610,6 +610,7 @@ private: int o3t_defineNewShapes(ScriptState *script); int o3t_setCurrentFrame(ScriptState *script); + int o3t_setNewShapeFlag(ScriptState *script); ScriptData _temporaryScriptData; ScriptState _temporaryScriptState; diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 73fca67b58..18ea960863 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -1015,6 +1015,12 @@ int KyraEngine_v3::o3t_setCurrentFrame(ScriptState *script) { return 0; } +int KyraEngine_v3::o3t_setNewShapeFlag(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3t_setNewShapeFlag(%p) (%d)", (const void *)script, stackPos(0)); + _newShapeFlag = stackPos(0); + return 0; +} + #pragma mark - int KyraEngine_v3::o3d_updateAnim(ScriptState *script) { @@ -1275,7 +1281,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_playSoundEffect); Opcode(o3_dummy); // 0x0a - OpcodeUnImpl(); + Opcode(o3t_setNewShapeFlag); Opcode(o3_getRand); Opcode(o3_getMalcolmShapes); Opcode(o3_dummy); -- cgit v1.2.3 From c05d16826ddced4a968808ceadedcef2e8f7bd9f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Apr 2008 21:48:04 +0000 Subject: - implemented opcode 90: o3_getScore - opcode 103 is yet another dummy opcode svn-id: r31710 --- engines/kyra/kyra_v3.h | 1 + engines/kyra/script_v3.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 2184dc8ae9..20b88733c7 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -711,6 +711,7 @@ private: int o3_stopMusic(ScriptState *script); int o3_playMusicTrack(ScriptState *script); int o3_playSoundEffect(ScriptState *script); + int o3_getScore(ScriptState *script); int o3_blockOutRegion(ScriptState *script); int o3_getRand(ScriptState *script); int o3_waitForConfirmationClick(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 18ea960863..6be5da86cc 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -655,6 +655,11 @@ int KyraEngine_v3::o3_playSoundEffect(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_getScore(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getScore(%p) ()", (const void *)script); + return _score; +} + int KyraEngine_v3::o3_blockOutRegion(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_blockOutRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); const int x1 = stackPos(0); @@ -1166,7 +1171,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x58 Opcode(o3_playMusicTrack); Opcode(o3_playSoundEffect); - OpcodeUnImpl(); + Opcode(o3_getScore); OpcodeUnImpl(); // 0x5c Opcode(o3_blockOutRegion); @@ -1182,7 +1187,7 @@ void KyraEngine_v3::setupOpcodeTable() { OpcodeUnImpl(); OpcodeUnImpl(); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_dummy); // 0x68 Opcode(o3_dummy); Opcode(o3_dummy); -- cgit v1.2.3 From 8b7486b5ca61653250c7168974233932e8248f87 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Apr 2008 23:06:21 +0000 Subject: Implemented opcodes o1_DROPSHADOW, o1_TEXTCOLOR, o1_OUTLINE. Added some initial code for opcode o1_TEXTRECT svn-id: r31711 --- engines/made/screen.h | 14 ++++++++++++++ engines/made/scriptfuncs.cpp | 20 +++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/engines/made/screen.h b/engines/made/screen.h index 543af81bf8..55dd92cabd 100644 --- a/engines/made/screen.h +++ b/engines/made/screen.h @@ -71,6 +71,17 @@ public: void setExclude(uint16 exclude) { _exclude = exclude; } void setGround(uint16 ground) { _ground = ground; } void setFont(uint16 font) { _currentFont = font; } + void setTextColor(int16 color) { _textColor = color; } + + void setOutlineColor(int16 color) { + _outlineColor = color; + _dropshadowColor = -1; + } + + void setDropShadowColor(int16 color) { + _outlineColor = -1; + _dropshadowColor = color; + } uint16 updateChannel(uint16 channelIndex); void deleteChannel(uint16 channelIndex); @@ -117,6 +128,9 @@ protected: int _paletteColorCount, _oldPaletteColorCount; bool _paletteInitialized, _needPalette; uint16 _currentFont; + int16 _textColor; + int16 _outlineColor; + int16 _dropShadowColor; uint16 _clip, _exclude, _ground; int _visualEffectNum; diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp index 7a75e4551c..c0f699dee6 100644 --- a/engines/made/scriptfuncs.cpp +++ b/engines/made/scriptfuncs.cpp @@ -441,6 +441,16 @@ int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) { int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) { warning("Unimplemented opcode: o1_TEXTRECT"); + + int16 x1 = CLIP(argv[0], 1, 318); + int16 y1 = CLIP(argv[1], 1, 198); + int16 x2 = CLIP(argv[2], 1, 318); + int16 y2 = CLIP(argv[3], 1, 198); + int16 textValue = argv[4]; + + printf("Text rect: %i, %i, %i, %i - text value: %i\n", x1, y1, x2, y2, textValue); + // TODO: set text rect + return 0; } @@ -455,17 +465,21 @@ int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) { } int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_DROPSHADOW"); + // if the drop shadow color is -1, then text drop shadow is disabled + // when font drop shadow is enabled, outline is disabled + _vm->_screen->setDropShadowColor(argv[0]); return 0; } int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_TEXTCOLOR"); + _vm->_screen->setTextColor(argv[0]); return 0; } int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) { - warning("Unimplemented opcode: o1_OUTLINE"); + // if the outline color is -1, then text outline is disabled + // when font outline is enabled, drop shadow is disabled + _vm->_screen->setOutlineColor(argv[0]); return 0; } -- cgit v1.2.3 From 673784e6efda006e7da942b0875bda601bd70d97 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Apr 2008 23:07:22 +0000 Subject: Typo svn-id: r31712 --- engines/made/screen.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engines/made/screen.h b/engines/made/screen.h index 55dd92cabd..d95e9440ae 100644 --- a/engines/made/screen.h +++ b/engines/made/screen.h @@ -75,12 +75,12 @@ public: void setOutlineColor(int16 color) { _outlineColor = color; - _dropshadowColor = -1; + _dropShadowColor = -1; } void setDropShadowColor(int16 color) { _outlineColor = -1; - _dropshadowColor = color; + _dropShadowColor = color; } uint16 updateChannel(uint16 channelIndex); -- cgit v1.2.3 From c622414022849f4848cc00cd041816f1713df29f Mon Sep 17 00:00:00 2001 From: Joost Peters Date: Thu, 24 Apr 2008 23:11:34 +0000 Subject: add detection entry for 1.2 CD version. the md5 of rtzcd.dat is identical to the existing entry, so no additional "unpacked" entry was added. svn-id: r31713 --- engines/made/detection.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index ce31b4077d..e3bb4cd1dd 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -90,7 +90,7 @@ static const MadeGameDescription gameDescriptions[] = { }, { - // Return to Zork - English CD version + // Return to Zork - English CD version 1.1 12/7/93 { "rtz", "CD", @@ -105,6 +105,23 @@ static const MadeGameDescription gameDescriptions[] = { 0, }, + { + // Return to Zork - English CD version 1.2 9/29/94 + { + "rtz", + "CD", + AD_ENTRY1("rtzcd.red", "946997d8b0aa6cb4e848bad02a1fc3d2"), + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + 0, + 0, + GF_CD_COMPRESSED, + 0, + }, + + { // Return to Zork - English floppy version { -- cgit v1.2.3 From 9e0cd64629039684e28cd64f20575483e984681e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Apr 2008 07:36:38 +0000 Subject: Implemented cmd_rand() and cmd_randomize() svn-id: r31714 --- engines/made/script.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/engines/made/script.cpp b/engines/made/script.cpp index 579abab7c3..fb5a9aea26 100644 --- a/engines/made/script.cpp +++ b/engines/made/script.cpp @@ -623,13 +623,11 @@ void ScriptInterpreter::cmd_restart() { } void ScriptInterpreter::cmd_rand() { - warning("Unimplemented command: cmd_rand"); + _stack.setTop(_vm->_rnd->getRandomNumber(3)); } void ScriptInterpreter::cmd_randomize() { - warning("Unimplemented command: cmd_randomize"); - // TODO - _stack.setTop(0); + _stack.setTop(_vm->_rnd->getSeed()); } void ScriptInterpreter::cmd_send() { -- cgit v1.2.3 From 2172eee072d0819bea8cf4d1f35926948756a57e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Apr 2008 10:43:47 +0000 Subject: Center videos to screen svn-id: r31715 --- engines/made/pmvplayer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 6faa7f6291..267b6ae8a6 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -198,7 +198,8 @@ void PmvPlayer::handleEvents() { } void PmvPlayer::updateScreen() { - _vm->_system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, 0, 0, _surface->w, _surface->h); + _vm->_system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, + (320 - _surface->w) / 2, (200 - _surface->h) / 2, _surface->w, _surface->h); _vm->_system->updateScreen(); } -- cgit v1.2.3 From 4bcf3ab8233d44ee12d95a9328bec67fc74e1902 Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Fri, 25 Apr 2008 11:02:37 +0000 Subject: (Poissbly) fixed sound glitches due to a non-implemented decoding variant. svn-id: r31716 --- engines/made/sound.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp index 3cb2ea69fd..27cf516b11 100644 --- a/engines/made/sound.cpp +++ b/engines/made/sound.cpp @@ -34,7 +34,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou int16 prevSample = 0, workSample = 0; byte soundBuffer[1025]; - byte soundBuffer3[1024]; + byte deltaSoundBuffer[1024]; int16 soundBuffer2[16]; byte deltaType, type; uint16 workChunkSize, byteCount, bitCount; @@ -106,17 +106,24 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou } - if (deltaType == 1) { - for (i = 0; i < chunkSize - 1; i += 2) { - l = i / 2; - soundBuffer3[i] = soundBuffer[l]; - soundBuffer3[i + 1] = (soundBuffer[l + 1] + soundBuffer[l]) / 2; - } - for (i = 0; i < chunkSize; i++) { - soundBuffer[i] = soundBuffer3[i]; + if (deltaType > 0) { + if (deltaType == 1) { + for (i = 0; i < chunkSize - 1; i += 2) { + l = i / 2; + deltaSoundBuffer[i] = soundBuffer[l]; + deltaSoundBuffer[i + 1] = (soundBuffer[l] + soundBuffer[l + 1]) / 2; + } + } else if (deltaType == 2) { + for (i = 0; i < chunkSize - 1; i += 4) { + l = i / 4; + deltaSoundBuffer[i] = soundBuffer[l]; + deltaSoundBuffer[i + 2] = (soundBuffer[l] + soundBuffer[l + 1]) / 2; + deltaSoundBuffer[i + 1] = (deltaSoundBuffer[i + 2] + soundBuffer[l]) / 2; + deltaSoundBuffer[i + 3] = (deltaSoundBuffer[i + 2] + soundBuffer[l + 1]) / 2; + } } - } else if (deltaType == 2) { - debug(2, "****************************************"); + for (i = 0; i < chunkSize; i++) + soundBuffer[i] = deltaSoundBuffer[i]; } prevSample = workSample; -- cgit v1.2.3 From 5540ef2d67301dbce1941eab9507285dc508f5ba Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Fri, 25 Apr 2008 11:05:56 +0000 Subject: Added FontResource type svn-id: r31717 --- engines/made/resource.cpp | 50 +++++++++++++++++++++++++++++++++++------------ engines/made/resource.h | 25 ++++++++++++------------ 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index f86c6ce371..cfab28cca5 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -205,33 +205,59 @@ const char *MenuResource::getString(uint index) const { return NULL; } -/* XmidiResource */ +/* FontResource */ -XmidiResource::XmidiResource() : _data(NULL), _size(0) { +FontResource::FontResource() : _data(NULL), _size(0) { } -XmidiResource::~XmidiResource() { +FontResource::~FontResource() { if (_data) delete[] _data; } -void XmidiResource::load(byte *source, int size) { +void FontResource::load(byte *source, int size) { _data = new byte[size]; _size = size; memcpy(_data, source, size); } -/* FontResource */ +int FontResource::getHeight() const { + return _data[0]; +} -FontResource::FontResource() : _data(NULL), _size(0) { +int FontResource::getCharWidth(char c) const { + byte *charData = getCharData(c); + if (charData) + return charData[0]; + else + return 0; } -FontResource::~FontResource() { +byte *FontResource::getChar(char c) const { + byte *charData = getCharData(c); + if (charData) + return charData + 1; + else + return NULL; +} + +byte *FontResource::getCharData(char c) const { + if (c < 28 || c > 255) + return NULL; + return _data + 1 + (c - 28) * (getHeight() + 1); +} + +/* XmidiResource */ + +XmidiResource::XmidiResource() : _data(NULL), _size(0) { +} + +XmidiResource::~XmidiResource() { if (_data) delete[] _data; } -void FontResource::load(byte *source, int size) { +void XmidiResource::load(byte *source, int size) { _data = new byte[size]; _size = size; memcpy(_data, source, size); @@ -301,14 +327,14 @@ MenuResource *ProjectReader::getMenu(int index) { return createResource(kResMENU, index); } -XmidiResource *ProjectReader::getXmidi(int index) { - return createResource(kResXMID, index); -} - FontResource *ProjectReader::getFont(int index) { return createResource(kResFONT, index); } +XmidiResource *ProjectReader::getXmidi(int index) { + return createResource(kResXMID, index); +} + void ProjectReader::loadIndex(ResourceSlots *slots) { _fd->readUint32LE(); // skip INDX _fd->readUint32LE(); // skip index size diff --git a/engines/made/resource.h b/engines/made/resource.h index 4e90673f09..93c57818bd 100644 --- a/engines/made/resource.h +++ b/engines/made/resource.h @@ -45,8 +45,8 @@ enum ResourceType { kResSNDS = MKID_BE('SNDS'), kResANIM = MKID_BE('ANIM'), kResMENU = MKID_BE('MENU'), - kResXMID = MKID_BE('XMID'), - kResFONT = MKID_BE('FONT') + kResFONT = MKID_BE('FONT'), + kResXMID = MKID_BE('XMID') }; struct ResourceSlot; @@ -112,23 +112,24 @@ protected: Common::Array _strings; }; -class XmidiResource : public Resource { +class FontResource : public Resource { public: - XmidiResource(); - ~XmidiResource(); + FontResource(); + ~FontResource(); void load(byte *source, int size); - byte *getData() const { return _data; } - int getSize() const { return _size; } + int getHeight() const; + int getCharWidth(char c) const; + byte *getChar(char c) const; protected: byte *_data; int _size; + byte *getCharData(char c) const; }; -// TODO -class FontResource : public Resource { +class XmidiResource : public Resource { public: - FontResource(); - ~FontResource(); + XmidiResource(); + ~XmidiResource(); void load(byte *source, int size); byte *getData() const { return _data; } int getSize() const { return _size; } @@ -160,8 +161,8 @@ public: AnimationResource *getAnimation(int index); SoundResource *getSound(int index); MenuResource *getMenu(int index); - XmidiResource *getXmidi(int index); FontResource *getFont(int index); + XmidiResource *getXmidi(int index); void freeResource(Resource *resource); -- cgit v1.2.3 From 134762be381ef76cb3a13f7ea37e9f0a6464ae00 Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Fri, 25 Apr 2008 11:07:56 +0000 Subject: Fixed cmd_rand and cmd_randomize and some cleanup. svn-id: r31718 --- engines/made/script.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/engines/made/script.cpp b/engines/made/script.cpp index fb5a9aea26..9919570e87 100644 --- a/engines/made/script.cpp +++ b/engines/made/script.cpp @@ -442,7 +442,6 @@ void ScriptInterpreter::cmd_getObjectProperty() { int16 objectIndex = _stack.top(); int16 value = _vm->_dat->getObjectProperty(objectIndex, propertyId); debug(4, "value = %04X(%d)\n", value, value); - //fflush(stdout); g_system->delayMillis(5000); _stack.setTop(value); } @@ -451,7 +450,6 @@ void ScriptInterpreter::cmd_setObjectProperty() { int16 propertyId = _stack.pop(); int16 objectIndex = _stack.top(); value = _vm->_dat->setObjectProperty(objectIndex, propertyId, value); - //fflush(stdout); g_system->delayMillis(5000); _stack.setTop(value); } @@ -481,9 +479,9 @@ void ScriptInterpreter::cmd_printNumber() { } void ScriptInterpreter::cmd_vref() { + int16 value = 0; int16 index = _stack.pop(); int16 objectIndex = _stack.top(); - int16 value = 0; debug(4, "index = %d; objectIndex = %d\n", index, objectIndex); fflush(stdout); if (objectIndex > 0) { Object *obj = _vm->_dat->getObject(objectIndex); @@ -507,9 +505,11 @@ void ScriptInterpreter::cmd_vset() { void ScriptInterpreter::cmd_vsize() { int16 objectIndex = _stack.top(); - if (objectIndex < 1) objectIndex = 1; // HACK - Object *obj = _vm->_dat->getObject(objectIndex); - int16 size = obj->getVectorSize(); + int16 size = 0; + if (objectIndex > 0) { + Object *obj = _vm->_dat->getObject(objectIndex); + size = obj->getVectorSize(); + } _stack.setTop(size); } @@ -522,7 +522,6 @@ void ScriptInterpreter::cmd_return() { int16 funcResult = _stack.top(); _stack.setStackPos(_localStackPos); _localStackPos = kScriptStackLimit - _stack.pop(); - //_localStackPos = _stack.pop(); _runningScriptObjectIndex = _stack.pop(); _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase + _stack.pop(); @@ -544,7 +543,6 @@ void ScriptInterpreter::cmd_call() { debug(4, "argc = %d; _runningScriptObjectIndex = %04X\n", argc, _runningScriptObjectIndex); fflush(stdout); _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData(); _codeIp = _codeBase; - //_vm->_dat->dumpObject(_runningScriptObjectIndex); } void ScriptInterpreter::cmd_svar() { @@ -623,11 +621,12 @@ void ScriptInterpreter::cmd_restart() { } void ScriptInterpreter::cmd_rand() { - _stack.setTop(_vm->_rnd->getRandomNumber(3)); + _stack.setTop(_vm->_rnd->getRandomNumber(_stack.top() - 1)); } void ScriptInterpreter::cmd_randomize() { - _stack.setTop(_vm->_rnd->getSeed()); + _vm->_rnd->setSeed(g_system->getMillis()); + _stack.setTop(0); } void ScriptInterpreter::cmd_send() { -- cgit v1.2.3 From 3dc6263b171f7b351dd13962f1094bb4ee3129a2 Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Fri, 25 Apr 2008 11:20:43 +0000 Subject: Started work on text drawing code. svn-id: r31719 --- engines/made/screen.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ engines/made/screen.h | 13 +++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index ede49e25f4..dc08bc0a88 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -63,6 +63,16 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) { _exclude = 0; _visualEffectNum = 0; + + _textX = 0; + _textY = 0; + _font = NULL; + _currentFontIndex = 0; + _fontDrawCtx.x = 0; + _fontDrawCtx.y = 0; + _fontDrawCtx.w = 320; + _fontDrawCtx.h = 200; + _fontDrawCtx.destSurface = _screen1; clearChannels(); } @@ -455,6 +465,7 @@ void Screen::show() { return; drawSpriteChannels(_clipInfo1, 3, 0); + memcpy(_screen2->pixels, _screen1->pixels, 64000); drawSpriteChannels(_clipInfo2, 1, 2); @@ -488,4 +499,39 @@ void Screen::flash(int flashCount) { } } +void Screen::setFont(int16 fontIndex) { + if (fontIndex == _currentFontIndex) + return; + if (_font) + _vm->_res->freeResource(_font); + _font = _vm->_res->getFont(fontIndex); + _currentFontIndex = fontIndex; +} + +void Screen::printChar(char c, int16 x, int16 y, byte color) { + + if (!_font) + return; + + int height = _font->getHeight(); + byte *charData = _font->getChar(c); + + if (!charData) + return; + + byte p; + byte *dest = (byte*)_fontDrawCtx.destSurface->getBasePtr(x, y); + + for (int16 yc = 0; yc < height; yc++) { + p = charData[yc]; + for (int16 xc = 0; xc < 8; xc++) { + if (p & 0x80) + dest[xc] = color; + p <<= 1; + } + dest += _fontDrawCtx.destSurface->pitch; + } + +} + } // End of namespace Made diff --git a/engines/made/screen.h b/engines/made/screen.h index d95e9440ae..d5dc1bb3e2 100644 --- a/engines/made/screen.h +++ b/engines/made/screen.h @@ -31,6 +31,8 @@ #include "graphics/surface.h" +#include "made/resource.h" + namespace Made { struct SpriteChannel { @@ -70,7 +72,6 @@ public: void setClip(uint16 clip) { _clip = clip; } void setExclude(uint16 exclude) { _exclude = exclude; } void setGround(uint16 ground) { _ground = ground; } - void setFont(uint16 font) { _currentFont = font; } void setTextColor(int16 color) { _textColor = color; } void setOutlineColor(int16 color) { @@ -116,7 +117,9 @@ public: void show(); void flash(int count); - byte _screenPalette[256 * 4]; + void setFont(int16 fontIndex); + void printChar(char c, int16 x, int16 y, byte color); + protected: MadeEngine *_vm; @@ -124,6 +127,7 @@ protected: bool _screenLock; bool _paletteLock; + byte _screenPalette[256 * 4]; byte _palette[768], _newPalette[768], _fxPalette[768]; int _paletteColorCount, _oldPaletteColorCount; bool _paletteInitialized, _needPalette; @@ -132,6 +136,11 @@ protected: int16 _outlineColor; int16 _dropShadowColor; + int16 _textX, _textY; + int16 _currentFontIndex; + FontResource *_font; + ClipInfo _fontDrawCtx; + uint16 _clip, _exclude, _ground; int _visualEffectNum; -- cgit v1.2.3 From fd5064b0694b8a671c132be52bcdbf72f9b057c4 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 12:20:06 +0000 Subject: Renamed opcode 63 to o3_drawSceneShapeOnPage. svn-id: r31720 --- engines/kyra/kyra_v3.h | 2 +- engines/kyra/script_v3.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 20b88733c7..5f411d7cea 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -701,7 +701,7 @@ private: int o3_updateScore(ScriptState *script); int o3_setSceneFilename(ScriptState *script); int o3_removeItemsFromScene(ScriptState *script); - int o3_drawSceneShape(ScriptState *script); + int o3_drawSceneShapeOnPage(ScriptState *script); int o3_checkInRect(ScriptState *script); int o3_updateConversations(ScriptState *script); int o3_setSceneDim(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 6be5da86cc..d82e848f3e 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -349,8 +349,8 @@ int KyraEngine_v3::o3_removeItemsFromScene(ScriptState *script) { return retValue; } -int KyraEngine_v3::o3_drawSceneShape(ScriptState *script) { - debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_drawSceneShape(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); +int KyraEngine_v3::o3_drawSceneShapeOnPage(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_drawSceneShapeOnPage(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); const int shape = stackPos(0); int x = _sceneShapeDescs[shape].drawX; @@ -1137,7 +1137,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_removeItemsFromScene); OpcodeUnImpl(); OpcodeUnImpl(); - Opcode(o3_drawSceneShape); + Opcode(o3_drawSceneShapeOnPage); // 0x40 Opcode(o3_checkInRect); Opcode(o3_updateConversations); -- cgit v1.2.3 From 425c87481618bbff5a2b5c7ba867ab523b5ed430 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 15:41:06 +0000 Subject: - Implemented opcodes: -> 30: o3_addItemToCurScene -> 62: o3_drawSceneShape - Fixed bug in KyraEngine_v3::exchangeMouseItem, fixes user input after combining items svn-id: r31721 --- engines/kyra/items_v3.cpp | 2 +- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp index 23162514c2..655511e006 100644 --- a/engines/kyra/items_v3.cpp +++ b/engines/kyra/items_v3.cpp @@ -391,7 +391,6 @@ void KyraEngine_v3::itemDropDown(int startX, int startY, int dstX, int dstY, int void KyraEngine_v3::exchangeMouseItem(int itemPos, int runScript) { debugC(9, kDebugLevelMain, "KyraEngine_v3::exchangeMouseItem(%d, %d)", itemPos, runScript); - _screen->hideMouse(); if (itemListMagic(_itemInHand, itemPos)) return; @@ -401,6 +400,7 @@ void KyraEngine_v3::exchangeMouseItem(int itemPos, int runScript) { return; } + _screen->hideMouse(); deleteItemAnimEntry(itemPos); int itemId = _itemList[itemPos].id; diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 5f411d7cea..5d82bad67d 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -680,6 +680,7 @@ private: int o3_showSceneFileMessage(ScriptState *script); int o3_showBadConscience(ScriptState *script); int o3_hideBadConscience(ScriptState *script); + int o3_addItemToCurScene(ScriptState *script); int o3_objectChat(ScriptState *script); int o3_checkForItem(ScriptState *script); int o3_defineItem(ScriptState *script); @@ -701,6 +702,7 @@ private: int o3_updateScore(ScriptState *script); int o3_setSceneFilename(ScriptState *script); int o3_removeItemsFromScene(ScriptState *script); + int o3_drawSceneShape(ScriptState *script); int o3_drawSceneShapeOnPage(ScriptState *script); int o3_checkInRect(ScriptState *script); int o3_updateConversations(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index d82e848f3e..3a1914c7d1 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -162,6 +162,35 @@ int KyraEngine_v3::o3_hideBadConscience(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_addItemToCurScene(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_addItemToCurScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); + const uint16 item = stackPos(0); + int x = stackPos(1); + int y = stackPos(2); + int itemSlot = findFreeItem(); + + if (x < 20) + x = 20; + else if (x > 299) + x = 299; + + if (y < 18) + y = 18; + else if (y > 187) + y = 187; + + if (itemSlot >= 0) { + _itemList[itemSlot].x = x; + _itemList[itemSlot].y = y; + _itemList[itemSlot].id = item; + _itemList[itemSlot].sceneId = _mainCharacter.sceneId; + addItemToAnimList(itemSlot); + refreshAnimObjectsIfNeed(); + } + + return itemSlot; +} + int KyraEngine_v3::o3_objectChat(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_objectChat(%p) (%d)", (const void *)script, stackPos(0)); int id = stackPos(0); @@ -349,6 +378,30 @@ int KyraEngine_v3::o3_removeItemsFromScene(ScriptState *script) { return retValue; } +int KyraEngine_v3::o3_drawSceneShape(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o3_drawSceneShape(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + + int shape = stackPos(0); + int flag = (stackPos(1) != 0) ? 1 : 0; + + _screen->hideMouse(); + restorePage3(); + + const int x = _sceneShapeDescs[shape].drawX; + const int y = _sceneShapeDescs[shape].drawY; + + _screen->drawShape(2, _sceneShapes[shape], x, y, 2, flag); + + _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _gamePlayBuffer); + + _screen->drawShape(0, _sceneShapes[shape], x, y, 2, flag); + + flagAnimObjsForRefresh(); + refreshAnimObjectsIfNeed(); + _screen->showMouse(); + return 0; +} + int KyraEngine_v3::o3_drawSceneShapeOnPage(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_drawSceneShapeOnPage(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); const int shape = stackPos(0); @@ -1096,7 +1149,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x1c OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_addItemToCurScene); Opcode(o3_objectChat); // 0x20 Opcode(o3_checkForItem); @@ -1136,7 +1189,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x3c Opcode(o3_removeItemsFromScene); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_drawSceneShape); Opcode(o3_drawSceneShapeOnPage); // 0x40 Opcode(o3_checkInRect); -- cgit v1.2.3 From 671e475567607764f513cd8c558a4961cf02efa8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 15:46:07 +0000 Subject: Implmented opcodes: - 11: o3_getCharacterFrameFromFacing - 12: o3_setCharacterFacingOverwrite svn-id: r31722 --- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 5d82bad67d..54ad1b39fb 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -674,6 +674,8 @@ private: int o3_getCharacterFacing(ScriptState *script); int o3_getCharacterScene(ScriptState *script); int o3_getMalcolmsMood(ScriptState *script); + int o3_getCharacterFrameFromFacing(ScriptState *script); + int o3_setCharacterFacingOverwrite(ScriptState *script); int o3_trySceneChange(ScriptState *script); int o3_moveCharacter(ScriptState *script); int o3_setCharacterFacing(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 3a1914c7d1..349e0ab237 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -113,6 +113,18 @@ int KyraEngine_v3::o3_getMalcolmsMood(ScriptState *script) { return _malcolmsMood; } +int KyraEngine_v3::o3_getCharacterFrameFromFacing(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getCharacterFrameFromFacing(%p) ()", (const void *)script); + return _characterFrameTable[_mainCharacter.facing]; +} + +int KyraEngine_v3::o3_setCharacterFacingOverwrite(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setCharacterFacingOverwrite(%p) (%d)", (const void *)script, stackPos(0)); + _mainCharacter.facing = stackPos(0); + _overwriteSceneFacing = true; + return 0; +} + int KyraEngine_v3::o3_trySceneChange(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_trySceneChange(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); @@ -1125,9 +1137,9 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_getMalcolmsMood); Opcode(o3_dummy); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_getCharacterFrameFromFacing); // 0x0c - OpcodeUnImpl(); + Opcode(o3_setCharacterFacingOverwrite); Opcode(o3_trySceneChange); Opcode(o3_moveCharacter); Opcode(o3_setCharacterFacing); -- cgit v1.2.3 From 3150313377653bb756874aeefe0493f6aeba3d6f Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 16:02:20 +0000 Subject: - Committed slightly modified patch #1951735 "kyra3: debugger and "give" command" - Added some more commands to new kyra3 debugger - Cleaned up some debugger code svn-id: r31723 --- engines/kyra/debugger.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++--- engines/kyra/debugger.h | 17 +++++++ engines/kyra/kyra_v3.cpp | 20 +++++--- engines/kyra/kyra_v3.h | 4 ++ 4 files changed, 144 insertions(+), 13 deletions(-) diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index ab49f18e97..ae07197ad8 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -29,6 +29,7 @@ #include "kyra/debugger.h" #include "kyra/kyra_v1.h" #include "kyra/kyra_v2.h" +#include "kyra/kyra_v3.h" #include "kyra/screen.h" #include "kyra/timer.h" #include "kyra/resource.h" @@ -39,6 +40,7 @@ Debugger::Debugger(KyraEngine *vm) : ::GUI::Debugger() { _vm = vm; + DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit)); DCmd_Register("screen_debug_mode", WRAP_METHOD(Debugger, cmd_setScreenDebug)); DCmd_Register("load_palette", WRAP_METHOD(Debugger, cmd_loadPalette)); DCmd_Register("facings", WRAP_METHOD(Debugger, cmd_showFacings)); @@ -189,11 +191,7 @@ bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { #pragma mark - Debugger_v1::Debugger_v1(KyraEngine_v1 *vm) - : Debugger(vm) { - _vm = vm; - - DCmd_Register("continue", WRAP_METHOD(Debugger_v1, Cmd_Exit)); - DCmd_Register("enter", WRAP_METHOD(Debugger_v1, cmd_enterRoom)); + : Debugger(vm), _vm(vm) { DCmd_Register("rooms", WRAP_METHOD(Debugger_v1, cmd_listRooms)); DCmd_Register("give", WRAP_METHOD(Debugger_v1, cmd_giveItem)); DCmd_Register("birthstones", WRAP_METHOD(Debugger_v1, cmd_listBirthstones)); @@ -235,7 +233,8 @@ bool Debugger_v1::cmd_enterRoom(int argc, const char **argv) { _vm->_currentCharacter->facing = direction; _vm->enterNewScene(room, _vm->_currentCharacter->facing, 0, 0, 1); - _vm->_screen->_mouseLockCount = 0; + while (!_vm->_screen->isMouseVisible()) + _vm->_screen->showMouse(); _detach_now = true; return false; @@ -285,7 +284,6 @@ bool Debugger_v1::cmd_listBirthstones(int argc, const char **argv) { #pragma mark - Debugger_v2::Debugger_v2(KyraEngine_v2 *vm) : Debugger(vm), _vm(vm) { - DCmd_Register("continue", WRAP_METHOD(Debugger_v2, Cmd_Exit)); DCmd_Register("character_info", WRAP_METHOD(Debugger_v2, cmd_characterInfo)); DCmd_Register("enter", WRAP_METHOD(Debugger_v2, cmd_enterScene)); DCmd_Register("rooms", WRAP_METHOD(Debugger_v2, cmd_listScenes)); // for consistency with kyra_v1 @@ -454,5 +452,109 @@ bool Debugger_v2::cmd_passcodes(int argc, const char **argv) { return true; } +Debugger_v3::Debugger_v3(KyraEngine_v3 *vm) : Debugger(vm), _vm(vm) { + DCmd_Register("give", WRAP_METHOD(Debugger_v3, cmd_giveItem)); + DCmd_Register("enter", WRAP_METHOD(Debugger_v3, cmd_enterScene)); + DCmd_Register("rooms", WRAP_METHOD(Debugger_v3, cmd_listScenes)); // for consistency with kyra_v1 + DCmd_Register("scenes", WRAP_METHOD(Debugger_v3, cmd_listScenes)); + DCmd_Register("scene_info", WRAP_METHOD(Debugger_v3, cmd_sceneInfo)); + DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v3, cmd_sceneToFacing)); +} + +bool Debugger_v3::cmd_giveItem(int argc, const char **argv) { + if (argc == 2) { + int item = atoi(argv[1]); + + // Kyrandia 3 has only 73 items (-1 to 71), otherwise it will crash + if (item < -1 || item > 71) { + DebugPrintf("itemid must be any value between (including) -1 and 71\n"); + return true; + } + + _vm->setHandItem(item); + } else { + DebugPrintf("Syntax: give \n"); + } + + return true; +} + +bool Debugger_v3::cmd_enterScene(int argc, const char **argv) { + uint direction = 0; + if (argc > 1) { + int scene = atoi(argv[1]); + + // game will crash if entering a non-existent scene + if (scene >= _vm->_sceneListSize) { + DebugPrintf("scene number must be any value between (including) 0 and %d\n", _vm->_sceneListSize-1); + return true; + } + + if (argc > 2) { + direction = atoi(argv[2]); + } else { + if (_vm->_sceneList[scene].exit1 != 0xFFFF) + direction = 4; + else if (_vm->_sceneList[scene].exit2 != 0xFFFF) + direction = 6; + else if (_vm->_sceneList[scene].exit3 != 0xFFFF) + direction = 0; + else if (_vm->_sceneList[scene].exit4 != 0xFFFF) + direction = 2; + } + + _vm->_system->hideOverlay(); + _vm->_mainCharacter.facing = direction; + + _vm->enterNewScene(scene, _vm->_mainCharacter.facing, 0, 0, 1); + while (!_vm->_screen->isMouseVisible()) + _vm->_screen->showMouse(); + + _detach_now = true; + return false; + } + + DebugPrintf("Syntax: %d \n", argv[0]); + return true; +} + +bool Debugger_v3::cmd_listScenes(int argc, const char **argv) { + int shown = 1; + for (int i = 0; i < _vm->_sceneListSize; ++i) { + if (_vm->_sceneList[i].filename1[0]) { + DebugPrintf("%-2i: %-10s", i, _vm->_sceneList[i].filename1); + if (!(shown % 5)) + DebugPrintf("\n"); + ++shown; + } + } + DebugPrintf("\n"); + DebugPrintf("Current scene: %i\n", _vm->_mainCharacter.sceneId); + return true; +} + +bool Debugger_v3::cmd_sceneInfo(int argc, const char **argv) { + DebugPrintf("Current scene: %d '%s'\n", _vm->_mainCharacter.sceneId, _vm->_sceneList[_vm->_mainCharacter.sceneId].filename1); + DebugPrintf("\n"); + DebugPrintf("Exit information:\n"); + DebugPrintf("Exit1: leads to %d, position %dx%d\n", int16(_vm->_sceneExit1), _vm->_sceneEnterX1, _vm->_sceneEnterY1); + DebugPrintf("Exit2: leads to %d, position %dx%d\n", int16(_vm->_sceneExit2), _vm->_sceneEnterX2, _vm->_sceneEnterY2); + DebugPrintf("Exit3: leads to %d, position %dx%d\n", int16(_vm->_sceneExit3), _vm->_sceneEnterX3, _vm->_sceneEnterY3); + DebugPrintf("Exit4: leads to %d, position %dx%d\n", int16(_vm->_sceneExit4), _vm->_sceneEnterX4, _vm->_sceneEnterY4); + DebugPrintf("Special exit information:\n"); + if (!_vm->_specialExitCount) { + DebugPrintf("No special exits.\n"); + } else { + DebugPrintf("This scene has %d special exits.\n", _vm->_specialExitCount); + for (int i = 0; i < _vm->_specialExitCount; ++i) { + DebugPrintf("SpecialExit%d: facing %d, position (x1/y1/x2/y2): %d/%d/%d/%d\n", i, + _vm->_specialExitTable[20+i], _vm->_specialExitTable[0+i], _vm->_specialExitTable[5+i], + _vm->_specialExitTable[10+i], _vm->_specialExitTable[15+i]); + } + } + + return true; +} + } // End of namespace Kyra diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h index dedcd672c7..85c4902e42 100644 --- a/engines/kyra/debugger.h +++ b/engines/kyra/debugger.h @@ -33,6 +33,7 @@ namespace Kyra { class KyraEngine; class KyraEngine_v1; class KyraEngine_v2; +class KyraEngine_v3; class Debugger : public ::GUI::Debugger { public: @@ -87,6 +88,22 @@ protected: bool cmd_passcodes(int argc, const char **argv); }; +class Debugger_v3 : public Debugger { +public: + Debugger_v3(KyraEngine_v3 *vm); + virtual ~Debugger_v3() {} + +protected: + KyraEngine_v3 *_vm; + + bool cmd_giveItem(int argc, const char **argv); + bool cmd_enterScene(int argc, const char **argv); + bool cmd_listScenes(int argc, const char **argv); + bool cmd_sceneInfo(int argc, const char **argv); + bool cmd_sceneToFacing(int argc, const char **argv); +}; + + } // End of namespace Kyra #endif diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 0cabfc36f6..6fb23e6568 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -32,6 +32,7 @@ #include "kyra/vqa.h" #include "kyra/gui.h" #include "kyra/timer.h" +#include "kyra/debugger.h" #include "common/system.h" #include "common/config-manager.h" @@ -130,6 +131,7 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _invWsaFrame = -1; _score = 0; memset(_scoreFlagTable, 0, sizeof(_scoreFlagTable)); + _debugger = 0; } KyraEngine_v3::~KyraEngine_v3() { @@ -188,6 +190,7 @@ KyraEngine_v3::~KyraEngine_v3() { delete [] _stringBuffer; delete [] _newShapeFiledata; delete _invWsa; + delete _debugger; } int KyraEngine_v3::init() { @@ -197,6 +200,9 @@ int KyraEngine_v3::init() { error("_screen->init() failed"); KyraEngine::init(); + + _debugger = new Debugger_v3(this); + assert(_debugger); _soundDigital = new SoundDigital(this, _mixer); assert(_soundDigital); @@ -622,6 +628,8 @@ void KyraEngine_v3::startup() { memset(_conversationState, -1, sizeof(_conversationState)); _sceneList = new SceneDesc[98]; + _sceneListSize = 98; + musicUpdate(0); runStartupScript(1, 0); _res->exists("MOODOMTR.WSA", true); @@ -1359,9 +1367,9 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { switch (event.type) { case Common::EVENT_KEYDOWN: - /*if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && + if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' && (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && mainLoop) { - const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); + /*const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); if (event.kbd.flags == Common::KBD_CTRL) { loadGame(saveLoadSlot); @@ -1371,11 +1379,11 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { char savegameName[14]; 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(); - }*/ + } break; case Common::EVENT_MOUSEMOVE: { @@ -1398,8 +1406,8 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { break; } - //if (_debugger->isAttached()) - // _debugger->onFrame(); + if (_debugger->isAttached()) + _debugger->onFrame(); if (breakLoop) break; diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 54ad1b39fb..2967a9e18d 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -40,9 +40,11 @@ class Screen_v3; class MainMenu; class WSAMovieV2; class TextDisplayer_v3; +class Debugger_v3; struct Button; class KyraEngine_v3 : public KyraEngine { +friend class Debugger_v3; friend class TextDisplayer_v3; public: KyraEngine_v3(OSystem *system, const GameFlags &flags); @@ -407,6 +409,7 @@ private: }; SceneDesc *_sceneList; + int _sceneListSize; uint16 _sceneExit1, _sceneExit2, _sceneExit3, _sceneExit4; int _sceneEnterX1, _sceneEnterY1; int _sceneEnterX2, _sceneEnterY2; @@ -746,6 +749,7 @@ private: // misc TextDisplayer_v3 *_text; + Debugger_v3 *_debugger; bool _wsaPlayingVQA; // resource specific -- cgit v1.2.3 From 66518b5be01b23195ae7a2e683ff3d27defcb231 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 16:09:30 +0000 Subject: Oops... fixes compiling. svn-id: r31724 --- engines/kyra/debugger.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp index ae07197ad8..b59e7e9c84 100644 --- a/engines/kyra/debugger.cpp +++ b/engines/kyra/debugger.cpp @@ -458,7 +458,6 @@ Debugger_v3::Debugger_v3(KyraEngine_v3 *vm) : Debugger(vm), _vm(vm) { DCmd_Register("rooms", WRAP_METHOD(Debugger_v3, cmd_listScenes)); // for consistency with kyra_v1 DCmd_Register("scenes", WRAP_METHOD(Debugger_v3, cmd_listScenes)); DCmd_Register("scene_info", WRAP_METHOD(Debugger_v3, cmd_sceneInfo)); - DCmd_Register("scene_to_facing", WRAP_METHOD(Debugger_v3, cmd_sceneToFacing)); } bool Debugger_v3::cmd_giveItem(int argc, const char **argv) { -- cgit v1.2.3 From 2479b03fbf94d6e565d3e83d5c70857ef02805e0 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 17:36:43 +0000 Subject: Implemented opcodes: - 156: o3_disableTimer - 157: o3_enableTimer - 158: o3_setTimerCountdown svn-id: r31725 --- engines/kyra/kyra_v3.h | 3 +++ engines/kyra/script_v3.cpp | 25 ++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 2967a9e18d..13214062ec 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -743,6 +743,9 @@ private: int o3_getHiddenItemsEntry(ScriptState *script); int o3_setupSceneAnimObject(ScriptState *script); int o3_removeSceneAnimObject(ScriptState *script); + int o3_disableTimer(ScriptState *script); + int o3_enableTimer(ScriptState *script); + int o3_setTimerCountdown(ScriptState *script); int o3_setVocHigh(ScriptState *script); int o3_getVocHigh(ScriptState *script); int o3_dummy(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 349e0ab237..881fee2c56 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -27,6 +27,7 @@ #include "kyra/script.h" #include "kyra/screen_v3.h" #include "kyra/wsamovie.h" +#include "kyra/timer.h" #include "common/endian.h" @@ -1040,6 +1041,24 @@ int KyraEngine_v3::o3_removeSceneAnimObject(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_disableTimer(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_disableTimer(%p) (%d)", (const void *)script, stackPos(0)); + _timer->disable(stackPos(0)); + return 0; +} + +int KyraEngine_v3::o3_enableTimer(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_enableTimer(%p) (%d)", (const void *)script, stackPos(0)); + _timer->enable(stackPos(0)); + return 0; +} + +int KyraEngine_v3::o3_setTimerCountdown(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setTimerCountdown(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + _timer->setCountdown(stackPos(0), stackPos(1)); + return 0; +} + int KyraEngine_v3::o3_setVocHigh(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setVocHigh(%p) (%d)", (const void *)script, stackPos(0)); _vocHigh = stackPos(0); @@ -1319,9 +1338,9 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_setupSceneAnimObject); Opcode(o3_removeSceneAnimObject); // 0x9c - OpcodeUnImpl(); - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_disableTimer); + Opcode(o3_enableTimer); + Opcode(o3_setTimerCountdown); OpcodeUnImpl(); // 0xa0 Opcode(o3_dummy); -- cgit v1.2.3 From c10f59d358c1ad8221b2151faa7cf4f5c43b5628 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 17:43:40 +0000 Subject: Implemented opcodes: - 152: o3_customChat - 153: o3_customChatFinish svn-id: r31726 --- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 31 +++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 13214062ec..a0844ca7e2 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -741,6 +741,8 @@ private: int o3_querySpecialSceneScriptState(ScriptState *script); int o3_setHiddenItemsEntry(ScriptState *script); int o3_getHiddenItemsEntry(ScriptState *script); + int o3_customChat(ScriptState *script); + int o3_customChatFinish(ScriptState *script); int o3_setupSceneAnimObject(ScriptState *script); int o3_removeSceneAnimObject(ScriptState *script); int o3_disableTimer(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 881fee2c56..12ba3c7da5 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -26,6 +26,7 @@ #include "kyra/kyra_v3.h" #include "kyra/script.h" #include "kyra/screen_v3.h" +#include "kyra/text_v3.h" #include "kyra/wsamovie.h" #include "kyra/timer.h" @@ -1025,6 +1026,32 @@ int KyraEngine_v3::o3_getHiddenItemsEntry(ScriptState *script) { return (int16)_hiddenItems[stackPos(0)]; } +int KyraEngine_v3::o3_customChat(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_customChat(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + const int id = stackPos(0); + const int object = stackPos(1); + const char *str = (const char *)getTableEntry(_sceneStrings, id); + + if (!str) + return 0; + + strcpy(_stringBuffer, str); + _chatText = _stringBuffer; + _chatObject = object; + _chatVocHigh = _chatVocLow = -1; + objectChatInit(_stringBuffer, object, _vocHigh, id); + playVoice(_vocHigh, id); + return 0; +} + +int KyraEngine_v3::o3_customChatFinish(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_customChatFinish(%p) ()", (const void *)script); + _text->restoreScreen(); + _chatText = 0; + _chatObject = -1; + return 0; +} + int KyraEngine_v3::o3_setupSceneAnimObject(ScriptState *script) { debugC(9, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setupSceneAnimObject(%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), @@ -1333,8 +1360,8 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_dummy); OpcodeUnImpl(); // 0x98 - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_customChat); + Opcode(o3_customChatFinish); Opcode(o3_setupSceneAnimObject); Opcode(o3_removeSceneAnimObject); // 0x9c -- cgit v1.2.3 From 7fb4a87c2415f3ba5bc92d572788adc34a15f577 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Fri, 25 Apr 2008 17:59:38 +0000 Subject: Implemented opcodes: - 20: o3_setCharacterAnimFrameFromFacing - 61: o3_disguiseMalcolm svn-id: r31727 --- engines/kyra/kyra_v3.h | 3 +++ engines/kyra/script_v3.cpp | 20 ++++++++++++++++++-- engines/kyra/text_v3.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index a0844ca7e2..fd20585d85 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -565,6 +565,7 @@ private: int8 _conversationState[30][30]; bool _chatAltFlag; void setDlgIndex(uint16 index); + void updateDlgIndex(); Common::SeekableReadStream *_cnvFile; Common::SeekableReadStream *_dlgBuffer; @@ -683,6 +684,7 @@ private: int o3_moveCharacter(ScriptState *script); int o3_setCharacterFacing(ScriptState *script); int o3_showSceneFileMessage(ScriptState *script); + int o3_setCharacterAnimFrameFromFacing(ScriptState *script); int o3_showBadConscience(ScriptState *script); int o3_hideBadConscience(ScriptState *script); int o3_addItemToCurScene(ScriptState *script); @@ -707,6 +709,7 @@ private: int o3_updateScore(ScriptState *script); int o3_setSceneFilename(ScriptState *script); int o3_removeItemsFromScene(ScriptState *script); + int o3_disguiseMalcolm(ScriptState *script); int o3_drawSceneShape(ScriptState *script); int o3_drawSceneShapeOnPage(ScriptState *script); int o3_checkInRect(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 12ba3c7da5..74a8187278 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -164,6 +164,15 @@ int KyraEngine_v3::o3_showSceneFileMessage(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_setCharacterAnimFrameFromFacing(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setCharacterAnimFrameFromFacing(%p) ()", (const void *)script); + updateCharPal(0); + _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing]; + updateCharacterAnim(0); + refreshAnimObjectsIfNeed(); + return 0; +} + int KyraEngine_v3::o3_showBadConscience(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_showBadConscience(%p) ()", (const void *)script); showBadConscience(); @@ -392,6 +401,13 @@ int KyraEngine_v3::o3_removeItemsFromScene(ScriptState *script) { return retValue; } +int KyraEngine_v3::o3_disguiseMalcolm(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o3_disguiseMalcolm(%p) (%d)", (const void *)script, stackPos(0)); + loadMalcolmShapes(stackPos(0)); + updateDlgIndex(); + return 0; +} + int KyraEngine_v3::o3_drawSceneShape(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o3_drawSceneShape(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); @@ -1195,7 +1211,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_dummy); Opcode(o3_dummy); // 0x14 - OpcodeUnImpl(); + Opcode(o3_setCharacterAnimFrameFromFacing); Opcode(o3_showBadConscience); Opcode(o3_dummy); Opcode(o3_hideBadConscience); @@ -1246,7 +1262,7 @@ void KyraEngine_v3::setupOpcodeTable() { OpcodeUnImpl(); // 0x3c Opcode(o3_removeItemsFromScene); - OpcodeUnImpl(); + Opcode(o3_disguiseMalcolm); Opcode(o3_drawSceneShape); Opcode(o3_drawSceneShapeOnPage); // 0x40 diff --git a/engines/kyra/text_v3.cpp b/engines/kyra/text_v3.cpp index 3b8c69177f..640095ff1c 100644 --- a/engines/kyra/text_v3.cpp +++ b/engines/kyra/text_v3.cpp @@ -508,6 +508,46 @@ void KyraEngine_v3::setDlgIndex(uint16 index) { } } +void KyraEngine_v3::updateDlgIndex() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::updateDlgIndex()"); + uint16 dlgIndex = _mainCharacter.dlgIndex; + + if (_curChapter == 1) { + static const uint8 dlgIndexMoodNice[] = { 0x0C, 0x0E, 0x10, 0x0F, 0x11 }; + static const uint8 dlgIndexMoodNormal[] = { 0x00, 0x02, 0x04, 0x03, 0x05 }; + static const uint8 dlgIndexMoodEvil[] = { 0x06, 0x08, 0x0A, 0x09, 0x0B }; + + if (_malcolmsMood == 0) + dlgIndex = dlgIndexMoodNice[_malcolmShapes]; + else if (_malcolmsMood == 1) + dlgIndex = dlgIndexMoodNormal[_malcolmShapes]; + else if (_malcolmsMood == 2) + dlgIndex = dlgIndexMoodEvil[_malcolmShapes]; + } else if (_curChapter == 2) { + if (dlgIndex >= 8) + dlgIndex -= 4; + if (dlgIndex >= 4) + dlgIndex -= 4; + + if (_malcolmsMood == 0) + dlgIndex += 8; + else if (_malcolmsMood == 2) + dlgIndex += 4; + } else if (_curChapter == 4) { + if (dlgIndex >= 10) + dlgIndex -= 5; + if (dlgIndex >= 5) + dlgIndex -= 5; + + if (_malcolmsMood == 0) + dlgIndex += 10; + else if (_malcolmsMood == 2) + dlgIndex += 5; + } + + _mainCharacter.dlgIndex = dlgIndex; +} + void KyraEngine_v3::processDialog(int vocHighIndex, int vocHighBase, int funcNum) { debugC(9, kDebugLevelMain, "KyraEngine_v3::processDialog(%d, %d, %d)", vocHighIndex, vocHighBase, funcNum); bool running = true; -- cgit v1.2.3 From 13ef28215d69c2c841af719aff62b508e42bcb60 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Apr 2008 22:38:40 +0000 Subject: minor drawShape() bug fix for Malcolm's shadow svn-id: r31728 --- engines/kyra/screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 6ffd0ace79..b7536803a8 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -1181,7 +1181,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int &Screen::drawShapePlotType0, // used by Kyra 1 + 2 &Screen::drawShapePlotType1, // used by Kyra 3 0, - &Screen::drawShapePlotType3_7, // used by Kyra 1 (invisibility) + &Screen::drawShapePlotType3_7, // used by Kyra 3 (shadow) &Screen::drawShapePlotType4, // used by Kyra 1, 2 + 3 &Screen::drawShapePlotType5, // used by Kyra 1 &Screen::drawShapePlotType6, // used by Kyra 1 (invisibility) @@ -1189,7 +1189,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int &Screen::drawShapePlotType8, // used by Kyra 2 &Screen::drawShapePlotType9, // used by Kyra 1 + 3 0, - &Screen::drawShapePlotType11_15, // used by Kyra 1 /invisibility) + &Screen::drawShapePlotType11_15, // used by Kyra 1 (invisibility) + Kyra 3 (shadow) &Screen::drawShapePlotType12, // used by Kyra 2 &Screen::drawShapePlotType13, // used by Kyra 1 &Screen::drawShapePlotType14, // used by Kyra 1 (invisibility) @@ -1635,7 +1635,7 @@ void Screen::drawShapePlotType1(uint8 *dst, uint8 cmd) { } void Screen::drawShapePlotType3_7(uint8 *dst, uint8 cmd) { - cmd = dst[cmd]; + cmd = *dst; for (int i = 0; i < _dsTableLoopCount; ++i) cmd = _dsTable[cmd]; -- cgit v1.2.3 From 0bb41c23cab40792a43dceeaf7d7759cd971d622 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Sat, 26 Apr 2008 09:52:17 +0000 Subject: Call _screen->Init(). Fixes segfaults when trying to start via a command line. svn-id: r31729 --- engines/kyra/kyra_v1.cpp | 2 ++ engines/kyra/kyra_v2.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 90e62895d0..719132929c 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -168,6 +168,8 @@ KyraEngine_v1::~KyraEngine_v1() { 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); diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 56512eb030..a144f71056 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -193,6 +193,8 @@ Movie *KyraEngine_v2::createWSAMovie() { int KyraEngine_v2::init() { _screen = new Screen_v2(this, _system); assert(_screen); + if (!_screen->init()) + error("_screen->init() failed"); KyraEngine::init(); initStaticResource(); -- cgit v1.2.3 From 61101b6dcef33d99f53705e40c9214ccd63fe847 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 10:15:54 +0000 Subject: Fixed kyra screen initialization. svn-id: r31730 --- engines/kyra/kyra_v1.cpp | 4 ++-- engines/kyra/kyra_v2.cpp | 3 +-- engines/kyra/kyra_v3.cpp | 3 +-- engines/kyra/screen.cpp | 55 ++++++++++++++++++++++++------------------------ engines/kyra/screen.h | 8 +++---- 5 files changed, 35 insertions(+), 38 deletions(-) diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 719132929c..f9a9f6320c 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -168,8 +168,8 @@ KyraEngine_v1::~KyraEngine_v1() { int KyraEngine_v1::init() { _screen = new Screen_v1(this, _system); assert(_screen); - if (!_screen->init()) - error("_screen->init() failed"); + _screen->setResolution(); + KyraEngine::init(); _sprites = new Sprites(this, _system); diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index a144f71056..26c6753031 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -193,8 +193,7 @@ Movie *KyraEngine_v2::createWSAMovie() { int KyraEngine_v2::init() { _screen = new Screen_v2(this, _system); assert(_screen); - if (!_screen->init()) - error("_screen->init() failed"); + _screen->setResolution(); KyraEngine::init(); initStaticResource(); diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 6fb23e6568..2edb0aabf7 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -196,8 +196,7 @@ KyraEngine_v3::~KyraEngine_v3() { int KyraEngine_v3::init() { _screen = new Screen_v3(this, _system); assert(_screen); - if (!_screen->init()) - error("_screen->init() failed"); + _screen->setResolution(); KyraEngine::init(); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index b7536803a8..00312dc711 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -75,7 +75,34 @@ bool Screen::init() { _useSJIS = false; _sjisTempPage = _sjisFontData = 0; - setResolution(); + if (_vm->gameFlags().useHiResOverlay) { + _useOverlays = true; + _useSJIS = (_vm->gameFlags().lang == Common::JA_JPN); + _sjisInvisibleColor = (_vm->gameFlags().gameID == GI_KYRA1) ? 0x80 : 0xF6; + + for (int i = 0; i < SCREEN_OVLS_NUM; ++i) { + if (!_sjisOverlayPtrs[i]) { + _sjisOverlayPtrs[i] = new uint8[SCREEN_OVL_SJIS_SIZE]; + assert(_sjisOverlayPtrs[i]); + memset(_sjisOverlayPtrs[i], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE); + } + } + + if (_useSJIS) { + if (!_sjisFontData) { + _sjisFontData = _vm->resource()->fileData("FMT_FNT.ROM", 0); + if (!_sjisFontData) + error("missing font rom ('FMT_FNT.ROM') required for this version"); + } + + if (!_sjisTempPage) { + _sjisTempPage = new uint8[420]; + assert(_sjisTempPage); + _sjisTempPage2 = _sjisTempPage + 60; + _sjisSourceChar = _sjisTempPage + 384; + } + } + } _curPage = 0; uint8 *pagePtr = new uint8[SCREEN_PAGE_SIZE * 8]; @@ -155,32 +182,6 @@ void Screen::setResolution() { else _system->initSize(640, 400); _system->endGFXTransaction(); - - _useOverlays = true; - _useSJIS = (_vm->gameFlags().lang == Common::JA_JPN); - _sjisInvisibleColor = (_vm->gameFlags().gameID == GI_KYRA1) ? 0x80 : 0xF6; - - for (int i = 0; i < SCREEN_OVLS_NUM; ++i) { - if (!_sjisOverlayPtrs[i]) { - _sjisOverlayPtrs[i] = new uint8[SCREEN_OVL_SJIS_SIZE]; - assert(_sjisOverlayPtrs[i]); - memset(_sjisOverlayPtrs[i], _sjisInvisibleColor, SCREEN_OVL_SJIS_SIZE); - } - } - if (_useSJIS) { - if (!_sjisFontData) { - _sjisFontData = _vm->resource()->fileData("FMT_FNT.ROM", 0); - if (!_sjisFontData) - error("missing font rom ('FMT_FNT.ROM') required for this version"); - } - - if (!_sjisTempPage) { - _sjisTempPage = new uint8[420]; - assert(_sjisTempPage); - _sjisTempPage2 = _sjisTempPage + 60; - _sjisSourceChar = _sjisTempPage + 384; - } - } } else { _system->beginGFXTransaction(); _vm->initCommonGFX(false); diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index ed69e9260e..9eb2c835a4 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -59,9 +59,7 @@ struct Font { }; class Screen { - friend class Debugger_v1; public: - enum { SCREEN_W = 320, SCREEN_H = 200, @@ -97,7 +95,10 @@ public: Screen(KyraEngine *vm, OSystem *system); virtual ~Screen(); + // init virtual bool init(); + virtual void setResolution(); + void updateScreen(); @@ -349,9 +350,6 @@ protected: int _drawShapeVar4; int _drawShapeVar5; - // init - virtual void setResolution(); - // debug bool _debugEnabled; }; -- cgit v1.2.3 From bba003e53a13b16a2584bf4aec7bc79c949924ae Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 10:21:53 +0000 Subject: Fixed segfault when trying to start invalid gameid from command line. svn-id: r31731 --- base/main.cpp | 6 +++--- common/singleton.h | 11 ++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/base/main.cpp b/base/main.cpp index a53595ffca..9129fcc7e1 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -330,9 +330,9 @@ extern "C" int scummvm_main(int argc, char *argv[]) { launcherDialog(system); } PluginManager::instance().unloadPluginsExcept(NULL); - PluginManager::instance().destroy(); - ConfMan.destroy(); - g_gui.destroy(); + PluginManager::destroy(); + Common::ConfigManager::destroy(); + GUI::NewGui::destroy(); return 0; } diff --git a/common/singleton.h b/common/singleton.h index 849bf208bb..be9f5d6dba 100644 --- a/common/singleton.h +++ b/common/singleton.h @@ -57,6 +57,11 @@ public: return new T(); } + static void destroyInstance() { + delete _singleton; + _singleton = 0; + } + public: static T& instance() { @@ -71,9 +76,9 @@ public: _singleton = T::makeInstance(); return *_singleton; } - virtual void destroy() { - delete _singleton; - _singleton = 0; + + static void destroy() { + T::destroyInstance(); } protected: Singleton() { } -- cgit v1.2.3 From 3bde19a137134379513ddc0e209c818dff6b1914 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 10:28:23 +0000 Subject: Fixed unitialized variable in Screen. svn-id: r31732 --- engines/kyra/screen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 00312dc711..de0c079293 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -34,7 +34,8 @@ namespace Kyra { Screen::Screen(KyraEngine *vm, OSystem *system) -: _system(system), _vm(vm), _sjisInvisibleColor(0) { + : _system(system), _vm(vm), _sjisInvisibleColor(0) { + _debugEnabled = false; } Screen::~Screen() { -- cgit v1.2.3 From 2ae81f0096086f726373582a4c0292a99c939ddb Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 19:00:22 +0000 Subject: Implemented opcodes: - 76: o3_removeItemInstances - 94: o3_showSceneStringsMessage svn-id: r31733 --- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index fd20585d85..70b6ba87d9 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -716,6 +716,7 @@ private: int o3_updateConversations(ScriptState *script); int o3_setSceneDim(ScriptState *script); int o3_update(ScriptState *script); + int o3_removeItemInstances(ScriptState *script); int o3_enterNewScene(ScriptState *script); int o3_setMalcolmPos(ScriptState *script); int o3_stopMusic(ScriptState *script); @@ -723,6 +724,7 @@ private: int o3_playSoundEffect(ScriptState *script); int o3_getScore(ScriptState *script); int o3_blockOutRegion(ScriptState *script); + int o3_showSceneStringsMessage(ScriptState *script); int o3_getRand(ScriptState *script); int o3_waitForConfirmationClick(ScriptState *script); int o3_defineRoomEntrance(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 74a8187278..c4bba4c81d 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -689,6 +689,34 @@ int KyraEngine_v3::o3_update(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_removeItemInstances(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_removeItemInstances(%p) (%d)", (const void *)script, stackPos(0)); + const int16 item = stackPos(0); + + int deleted = 0; + + for (int i = 0; i < 10; ++i) { + if (_mainCharacter.inventory[i] == item) { + _mainCharacter.inventory[i] = 0xFFFF; + ++deleted; + } + } + + if (_itemInHand == item) { + removeHandItem(); + ++deleted; + } + + for (int i = 0; i < 50; ++i) { + if (_itemList[i].id == item) { + _itemList[i].id = 0xFFFF; + ++deleted; + } + } + + return deleted; +} + int KyraEngine_v3::o3_enterNewScene(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); @@ -759,6 +787,12 @@ int KyraEngine_v3::o3_blockOutRegion(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_showSceneStringsMessage(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_showSceneStringsMessage(%p) (%d)", (const void *)script, stackPos(0)); + showMessage((const char*)getTableEntry(_sceneStrings, stackPos(0)), 0xFF, 0xF0); + return 0; +} + int KyraEngine_v3::o3_getRand(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); assert(stackPos(0) < stackPos(1)); @@ -1281,7 +1315,7 @@ void KyraEngine_v3::setupOpcodeTable() { OpcodeUnImpl(); Opcode(o3_update); // 0x4c - OpcodeUnImpl(); + Opcode(o3_removeItemInstances); OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); @@ -1303,7 +1337,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x5c Opcode(o3_blockOutRegion); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_showSceneStringsMessage); OpcodeUnImpl(); // 0x60 Opcode(o3_getRand); -- cgit v1.2.3 From 8c9311280ff782554beb4d30446dcc561f12fef8 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sat, 26 Apr 2008 20:33:59 +0000 Subject: Fix Kanji rendering svn-id: r31734 --- engines/scumm/charset.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 6fadcd171c..bf3f7ed66e 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -74,7 +74,7 @@ void ScummEngine::loadCJKFont() { break; case Common::JA_JPN: fontFile = (_game.id == GID_DIG) ? "kanji16.fnt" : "japanese.fnt"; - numChar = 1024; + numChar = 8192; break; case Common::ZH_TWN: if (_game.id == GID_CMI) { @@ -217,7 +217,7 @@ byte *ScummEngine::get2byteCharPtr(int idx) { int high = 0; if (low >= 0x20 && low <= 0x7e) { - base = (low + low * 2 + 81012) * 5; + base = (3 * low + 81012) * 5; } else { if (low >= 0xa1 && low <= 0xa3) { base = 392820; -- cgit v1.2.3 From 7eef295729e079434aa981d828e03767a1e13c6c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 21:08:47 +0000 Subject: Added support for kyra3 inventory. (jesters staff not supported yet) svn-id: r31735 --- engines/kyra/gui_v3.cpp | 414 ++++++++++++++++++++++++++++++++++++++++++++- engines/kyra/gui_v3.h | 98 +++++++++++ engines/kyra/items_v3.cpp | 75 +++++++- engines/kyra/kyra_v3.cpp | 15 +- engines/kyra/kyra_v3.h | 16 +- engines/kyra/staticres.cpp | 37 ++++ 6 files changed, 648 insertions(+), 7 deletions(-) create mode 100644 engines/kyra/gui_v3.h diff --git a/engines/kyra/gui_v3.cpp b/engines/kyra/gui_v3.cpp index 644c7bb57a..6024673dbb 100644 --- a/engines/kyra/gui_v3.cpp +++ b/engines/kyra/gui_v3.cpp @@ -23,6 +23,7 @@ * */ +#include "kyra/gui_v3.h" #include "kyra/kyra_v3.h" #include "kyra/text_v3.h" #include "kyra/wsamovie.h" @@ -168,7 +169,7 @@ void KyraEngine_v3::showInventory() { _screen->copyRegion(0, 0, 0, 144, 320, 56, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); - //initInventoryButtonList(0); + initMainButtonList(false); restorePage3(); _screen->showMouse(); @@ -181,7 +182,7 @@ void KyraEngine_v3::hideInventory() { _inventoryState = false; updateCLState(); - //initInventoryButtonList(1); + initMainButtonList(true); _screen->copyBlockToPage(3, 0, 0, 320, 56, _interface); _screen->hideMouse(); @@ -428,5 +429,414 @@ void KyraEngine_v3::drawInventorySlot(int page, int item, int slot) { _screen->drawShape(page, getShapePtr(item+248), _inventoryX[slot], _inventoryY[slot] + yOffset, 0, 0); } +int KyraEngine_v3::buttonInventory(Button *button) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::buttonInventory(%p)", (const void*)button); + setNextIdleAnimTimer(); + if (!_enableInventory || !_inventoryState || !_screen->isMouseVisible()) + return 0; + + const int slot = button->index - 5; + const int16 slotItem = (int16)_mainCharacter.inventory[slot]; + if (_itemInHand == -1) { + if (slotItem == -1) + return 0; + + _screen->hideMouse(); + clearInventorySlot(slot, 0); + playSoundEffect(0x0B, 0xC8); + setMouseCursor(slotItem); + updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF); + _itemInHand = slotItem; + _mainCharacter.inventory[slot] = 0xFFFF; + _screen->showMouse(); + } else if (_itemInHand == 27) { + if (_chatText) + return 0; + //XXX + } else { + if (slotItem >= 0) { + if (itemInventoryMagic(_itemInHand, slot)) + return 0; + + playSoundEffect(0x0B, 0xC8); + + _screen->hideMouse(); + clearInventorySlot(slot, 0); + drawInventorySlot(0, _itemInHand, slot); + setMouseCursor(slotItem); + updateItemCommand(slotItem, (_lang == 1) ? getItemCommandStringPickUp(slotItem) : 0, 0xFF); + _mainCharacter.inventory[slot] = _itemInHand; + _itemInHand = slotItem; + _screen->showMouse(); + } else { + playSoundEffect(0x0C, 0xC8); + _screen->hideMouse(); + drawInventorySlot(0, _itemInHand, slot); + _screen->setMouseCursor(0, 0, getShapePtr(0)); + updateItemCommand(_itemInHand, (_lang == 1) ? getItemCommandStringInv(_itemInHand) : 2, 0xFF); + _screen->showMouse(); + _mainCharacter.inventory[slot] = _itemInHand; + _itemInHand = -1; + } + } + + return 0; +} + +#pragma mark - + +GUI_v3::GUI_v3(KyraEngine_v3 *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { + _backUpButtonList = _unknownButtonList = 0; + _buttonListChanged = false; +} + +Button *GUI_v3::addButtonToList(Button *list, Button *newButton) { + list = GUI::addButtonToList(list, newButton); + _buttonListChanged = true; + return list; +} + +void GUI_v3::processButton(Button *button) { + if (!button) + return; + + if (button->flags & 8) { + if (button->flags & 0x10) { + // XXX + } + return; + } + + int entry = button->flags2 & 5; + + byte val1 = 0, val2 = 0, val3 = 0; + const uint8 *dataPtr = 0; + Button::Callback callback; + if (entry == 1) { + val1 = button->data1Val1; + dataPtr = button->data1ShapePtr; + callback = button->data1Callback; + val2 = button->data1Val2; + val3 = button->data1Val3; + } else if (entry == 4 || entry == 5) { + val1 = button->data2Val1; + dataPtr = button->data2ShapePtr; + callback = button->data2Callback; + val2 = button->data2Val2; + val3 = button->data2Val3; + } else { + val1 = button->data0Val1; + dataPtr = button->data0ShapePtr; + callback = button->data0Callback; + val2 = button->data0Val2; + val3 = button->data0Val3; + } + + int x = 0, y = 0, x2 = 0, y2 = 0; + + x = button->x; + if (x < 0) + x += _screen->getScreenDim(button->dimTableIndex)->w << 3; + x += _screen->getScreenDim(button->dimTableIndex)->sx << 3; + x2 = x + button->width - 1; + + y = button->y; + if (y < 0) + y += _screen->getScreenDim(button->dimTableIndex)->h << 3; + y += _screen->getScreenDim(button->dimTableIndex)->sy << 3; + y2 = y + button->height - 1; + + switch (val1 - 1) { + case 0: + _screen->hideMouse(); + _screen->drawShape(_screen->_curPage, dataPtr, x, y, button->dimTableIndex, 0x10); + _screen->showMouse(); + break; + + case 1: + _screen->hideMouse(); + _screen->printText((const char*)dataPtr, x, y, val2, val3); + _screen->showMouse(); + break; + + case 3: + if (callback) + (*callback)(button); + break; + + case 4: + _screen->hideMouse(); + _screen->drawBox(x, y, x2, y2, val2); + _screen->showMouse(); + break; + + case 5: + _screen->hideMouse(); + _screen->fillRect(x, y, x2, y2, val2, -1, true); + _screen->showMouse(); + break; + + default: + break; + } + + _screen->updateScreen(); +} + +int GUI_v3::processButtonList(Button *buttonList, uint16 inputFlag) { + static uint16 flagsModifier = 0; + + if (!buttonList) + return inputFlag & 0x7FFF; + + if (_backUpButtonList != buttonList || _buttonListChanged) { + _unknownButtonList = 0; + //flagsModifier |= 0x2200; + _backUpButtonList = buttonList; + _buttonListChanged = false; + + while (buttonList) { + processButton(buttonList); + buttonList = buttonList->nextButton; + } + } + + int mouseX = _vm->_mouseX; + int mouseY = _vm->_mouseY; + + uint16 flags = 0; + + if (1/*!_screen_cursorDisable*/) { + uint16 inFlags = inputFlag & 0xFF; + uint16 temp = 0; + + // HACK: inFlags == 200 is our left button (up) + if (inFlags == 199 || inFlags == 200) + temp = 0x1000; + if (inFlags == 198) + temp = 0x100; + + if (inputFlag & 0x800) + temp <<= 2; + + flags |= temp; + + flagsModifier &= ~((temp & 0x4400) >> 1); + flagsModifier |= (temp & 0x1100) * 2; + flags |= flagsModifier; + flags |= (flagsModifier << 2) ^ 0x8800; + } + + buttonList = _backUpButtonList; + if (_unknownButtonList) { + buttonList = _unknownButtonList; + if (_unknownButtonList->flags & 8) + _unknownButtonList = 0; + } + + int returnValue = 0; + while (buttonList) { + if (buttonList->flags & 8) { + buttonList = buttonList->nextButton; + continue; + } + buttonList->flags2 &= ~0x18; + buttonList->flags2 |= (buttonList->flags2 & 3) << 3; + + int x = buttonList->x; + if (x < 0) + x += _screen->getScreenDim(buttonList->dimTableIndex)->w << 3; + x += _screen->getScreenDim(buttonList->dimTableIndex)->sx << 3; + + int y = buttonList->y; + if (y < 0) + y += _screen->getScreenDim(buttonList->dimTableIndex)->h; + y += _screen->getScreenDim(buttonList->dimTableIndex)->sy; + + bool progress = false; + + if (mouseX >= x && mouseY >= y && mouseX <= x+buttonList->width && mouseY <= y+buttonList->height) + progress = true; + + buttonList->flags2 &= ~0x80; + uint16 inFlags = inputFlag & 0x7FFF; + if (inFlags) { + if (buttonList->unk6 == inFlags) { + progress = true; + flags = buttonList->flags & 0x0F00; + buttonList->flags2 |= 0x80; + inputFlag = 0; + _unknownButtonList = buttonList; + } else if (buttonList->unk8 == inFlags) { + flags = buttonList->flags & 0xF000; + if (!flags) + flags = buttonList->flags & 0x0F00; + progress = true; + buttonList->flags2 |= 0x80; + inputFlag = 0; + _unknownButtonList = buttonList; + } + } + + bool unk1 = false; + if (!progress) + buttonList->flags2 &= ~6; + + if ((flags & 0x3300) && (buttonList->flags & 4) && progress && (buttonList == _unknownButtonList || !_unknownButtonList)) { + buttonList->flags |= 6; + if (!_unknownButtonList) + _unknownButtonList = buttonList; + } else if ((flags & 0x8800) && !(buttonList->flags & 4) && progress) { + buttonList->flags2 |= 6; + } else { + buttonList->flags2 &= ~6; + } + + bool progressSwitch = false; + if (!_unknownButtonList) { + progressSwitch = progress; + } else { + if (_unknownButtonList->flags & 0x40) + progressSwitch = (_unknownButtonList == buttonList); + else + progressSwitch = progress; + } + + if (progressSwitch) { + if ((flags & 0x1100) && progress && !_unknownButtonList) { + inputFlag = 0; + _unknownButtonList = buttonList; + } + + if ((buttonList->flags & flags) && (progress || !(buttonList->flags & 1))) { + uint16 combinedFlags = (buttonList->flags & flags); + combinedFlags = ((combinedFlags & 0xF000) >> 4) | (combinedFlags & 0x0F00); + combinedFlags >>= 8; + + static const uint16 flagTable[] = { + 0x000, 0x100, 0x200, 0x100, 0x400, 0x100, 0x400, 0x100, 0x800, 0x100, + 0x200, 0x100, 0x400, 0x100, 0x400, 0x100 + }; + + assert(combinedFlags < ARRAYSIZE(flagTable)); + + switch (flagTable[combinedFlags]) { + case 0x400: + if (!(buttonList->flags & 1) || ((buttonList->flags & 1) && _unknownButtonList == buttonList)) { + buttonList->flags2 ^= 1; + returnValue = buttonList->index | 0x8000; + unk1 = true; + } + + if (!(buttonList->flags & 4)) { + buttonList->flags2 &= ~4; + buttonList->flags2 &= ~2; + } + break; + + case 0x800: + if (!(buttonList->flags & 4)) { + buttonList->flags2 |= 4; + buttonList->flags2 |= 2; + } + + if (!(buttonList->flags & 1)) + unk1 = true; + break; + + case 0x200: + if (buttonList->flags & 4) { + buttonList->flags2 |= 4; + buttonList->flags2 |= 2; + } + + if (!(buttonList->flags & 1)) + unk1 = true; + break; + + case 0x100: + default: + buttonList->flags2 ^= 1; + returnValue = buttonList->index | 0x8000; + unk1 = true; + if (buttonList->flags & 4) { + buttonList->flags2 |= 4; + buttonList->flags2 |= 2; + } + _unknownButtonList = buttonList; + break; + } + } + } + + bool unk2 = false; + if ((flags & 0x2200) && progress) { + buttonList->flags2 |= 6; + if (!(buttonList->flags & 4) && !(buttonList->flags2 & 1)) { + unk2 = true; + buttonList->flags2 |= 1; + } + } + + if ((flags & 0x8800) == 0x8800) { + _unknownButtonList = 0; + if (!progress || (buttonList->flags & 4)) + buttonList->flags2 &= ~6; + } + + if (!progress && buttonList == _unknownButtonList && !(buttonList->flags & 0x40)) + _unknownButtonList = 0; + + if ((buttonList->flags2 & 0x18) != ((buttonList->flags2 & 3) << 3)) + processButton(buttonList); + + if (unk2) + buttonList->flags2 &= ~1; + + if (unk1) { + buttonList->flags2 &= 0xFF; + buttonList->flags2 |= flags; + + if (buttonList->buttonCallback) { + _vm->removeInputTop(); + if ((*buttonList->buttonCallback.get())(buttonList)) + break; + } + + if (buttonList->flags & 0x20) + break; + } + + if (_unknownButtonList == buttonList && (buttonList->flags & 0x40)) + break; + + buttonList = buttonList->nextButton; + } + + if (!returnValue) + returnValue = inputFlag & 0x7FFF; + return returnValue; +} + +void GUI_v3::flagButtonEnable(Button *button) { + if (!button) + return; + + if (button->flags & 8) { + button->flags &= ~8; + processButton(button); + } +} + +void GUI_v3::flagButtonDisable(Button *button) { + if (!button) + return; + + if (!(button->flags & 8)) { + button->flags |= 8; + processButton(button); + } +} + } // end of namespace Kyra diff --git a/engines/kyra/gui_v3.h b/engines/kyra/gui_v3.h new file mode 100644 index 0000000000..acf3d948f8 --- /dev/null +++ b/engines/kyra/gui_v3.h @@ -0,0 +1,98 @@ +/* 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_GUI_V3_H +#define KYRA_GUI_V3_H + +#include "kyra/gui.h" + +namespace Kyra { + +#define GUI_V3_BUTTON(button, a, b, c, d, e, f, h, i, j, k, l, m, n, o, p, q, r, s, t) \ + button.nextButton = 0; \ + button.index = a; \ + button.unk6 = b; \ + button.unk8 = c; \ + button.data0Val1 = d; \ + button.data1Val1 = e; \ + button.data2Val1 = f; \ + button.flags = h; \ + button.data0ShapePtr = button.data1ShapePtr = button.data2ShapePtr = 0; \ + button.dimTableIndex = i; \ + button.x = j; \ + button.y = k; \ + button.width = l; \ + button.height = m; \ + button.data0Val2 = n; \ + button.data0Val3 = o; \ + button.data1Val2 = p; \ + button.data1Val3 = q; \ + button.data2Val2 = r; \ + button.data2Val3 = s; \ + button.flags2 = t; + +class KyraEngine_v3; +class Screen_v3; + +class GUI_v3 : public GUI { +friend class KyraEngine_v3; +public: + GUI_v3(KyraEngine_v3 *engine); + + Button *addButtonToList(Button *list, Button *newButton); + + void processButton(Button *button); + int processButtonList(Button *button, uint16 inputFlag); + + void flagButtonEnable(Button *button); + void flagButtonDisable(Button *button); +private: + const char *getMenuTitle(const Menu &menu) { return 0; } + const char *getMenuItemTitle(const MenuItem &menuItem) { return 0; } + const char *getMenuItemLabel(const MenuItem &menuItem) { return 0; } + + Button *getButtonListData() { return 0; } + + Button *getScrollUpButton() { return 0; } + Button *getScrollDownButton() { return 0; } + + Button::Callback getScrollUpButtonHandler() const { return Button::Callback(); } + Button::Callback getScrollDownButtonHandler() const { return Button::Callback(); } + + uint8 defaultColor1() const { return 0xCF; } + uint8 defaultColor2() const { return 0xF8; } + + KyraEngine_v3 *_vm; + Screen_v3 *_screen; + + bool _buttonListChanged; + Button *_backUpButtonList; + Button *_unknownButtonList; +}; + +} // end of namespace Kyra + +#endif + diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp index 655511e006..4417ba4aa5 100644 --- a/engines/kyra/items_v3.cpp +++ b/engines/kyra/items_v3.cpp @@ -522,7 +522,7 @@ bool KyraEngine_v3::itemListMagic(int handItem, int itemSlot) { playSoundEffect(0x0F, 0xC8); - _itemList[itemSlot].id = resItem; + _itemList[itemSlot].id = (resItem == 0xFF) ? 0xFFFF : resItem; _screen->hideMouse(); deleteItemAnimEntry(itemSlot); @@ -543,6 +543,79 @@ bool KyraEngine_v3::itemListMagic(int handItem, int itemSlot) { return false; } +bool KyraEngine_v3::itemInventoryMagic(int handItem, int invSlot) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::itemInventoryMagic(%d, %d)", handItem, invSlot); + + uint16 item = _mainCharacter.inventory[invSlot]; + if (_curChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { + //eelScript(); + return true; + } else if ((handItem == 6 || handItem == 7) && item == 2) { + _screen->hideMouse(); + playSoundEffect(0x93, 0xC8); + for (int i = 109; i <= 141; ++i) { + _mainCharacter.inventory[invSlot] = i; + _screen->drawShape(2, getShapePtr(invSlot+422), 0, 144, 0, 0); + _screen->drawShape(2, getShapePtr(i+248), 0, 144, 0, 0); + _screen->copyRegion(0, 144, _inventoryX[invSlot], _inventoryY[invSlot], 24, 20, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + delay(1, true); + } + + _mainCharacter.inventory[invSlot] = 0xFFFF; + clearInventorySlot(invSlot, 0); + _screen->showMouse(); + return true; + } + + if (_mainCharacter.sceneId == 51 && queryGameFlag(0x19B) && !queryGameFlag(0x19C) + && ((item == 63 && handItem == 56) || (item == 56 && handItem == 63))) { + if (queryGameFlag(0x1AC)) { + setGameFlag(0x19C); + setGameFlag(0x1AD); + } else { + setGameFlag(0x1AE); + } + + _timer->setCountdown(12, 1); + _timer->enable(12); + } + + for (int i = 0; _itemMagicTable[i] != 0xFF; i += 4) { + if (_itemMagicTable[i+0] != handItem || _itemMagicTable[i+1] != item) + continue; + + uint8 resItem = _itemMagicTable[i+2]; + uint8 newItem = _itemMagicTable[i+3]; + + playSoundEffect(0x0F, 0xC8); + + _mainCharacter.inventory[invSlot] = (resItem == 0xFF) ? 0xFFFF : resItem; + + _screen->hideMouse(); + clearInventorySlot(invSlot, 0); + drawInventorySlot(0, resItem, invSlot); + + if (newItem == 0xFE) + removeHandItem(); + else if (newItem != 0xFF) + setHandItem(newItem); + _screen->showMouse(); + + if (_lang != 1) { + if (resItem == 7) { + updateScore(35, 100); + delay(60, true); + } + updateItemCommand(resItem, 3, 0xFF); + } + + return true; + } + + return false; +} + int KyraEngine_v3::getItemCommandStringDrop(uint16 item) { debugC(9, kDebugLevelMain, "KyraEngine_v3::getItemCommandStringDrop(%u)", item); assert(item < _itemStringMapSize); diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 2edb0aabf7..a93375d286 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -33,6 +33,7 @@ #include "kyra/gui.h" #include "kyra/timer.h" #include "kyra/debugger.h" +#include "kyra/gui_v3.h" #include "common/system.h" #include "common/config-manager.h" @@ -132,6 +133,10 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _score = 0; memset(_scoreFlagTable, 0, sizeof(_scoreFlagTable)); _debugger = 0; + _mainButtonData = 0; + _mainButtonList = 0; + _mainButtonListInitialized = false; + _enableInventory = true; } KyraEngine_v3::~KyraEngine_v3() { @@ -191,6 +196,8 @@ KyraEngine_v3::~KyraEngine_v3() { delete [] _newShapeFiledata; delete _invWsa; delete _debugger; + delete [] _mainButtonData; + delete _gui; } int KyraEngine_v3::init() { @@ -209,6 +216,8 @@ int KyraEngine_v3::init() { error("_soundDigital->init() failed"); KyraEngine::_text = _text = new TextDisplayer_v3(this, _screen); assert(_text); + _gui = new GUI_v3(this); + assert(_gui); _screen->loadFont(Screen::FID_6_FNT, "6.FNT"); _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT"); @@ -601,7 +610,7 @@ void KyraEngine_v3::startup() { musicUpdate(0); loadMalcolmShapes(_malcolmShapes); musicUpdate(0); - //initInventoryButtonList(1); + initMainButtonList(true); loadInterfaceShapes(); musicUpdate(0); @@ -1004,7 +1013,7 @@ void KyraEngine_v3::runLoop() { if (_system->getMillis() >= _nextIdleAnim) showIdleAnim(); - int inputFlag = checkInput(0/*_mainButtonList*/); + int inputFlag = checkInput(_mainButtonList); removeInputTop(); update(); @@ -1414,7 +1423,7 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { _eventList.erase(_eventList.begin()); } - return /*_gui->processButtonList(buttonList, */keys/* | 0x8000)*/; + return _gui->processButtonList(buttonList, keys | 0x8000); } void KyraEngine_v3::removeInputTop() { diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 70b6ba87d9..946344cdb1 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -41,11 +41,13 @@ class MainMenu; class WSAMovieV2; class TextDisplayer_v3; class Debugger_v3; +class GUI_v3; struct Button; class KyraEngine_v3 : public KyraEngine { friend class Debugger_v3; friend class TextDisplayer_v3; +friend class GUI_v3; public: KyraEngine_v3(OSystem *system, const GameFlags &flags); ~KyraEngine_v3(); @@ -145,7 +147,18 @@ private: int _curStudioSFX; void playStudioSFX(const char *str); - // main menu + // gui + GUI_v3 *_gui; + + Button *_mainButtonData; + Button *_mainButtonList; + bool _mainButtonListInitialized; + void initMainButtonList(bool disable); + + bool _enableInventory; + int buttonInventory(Button *button); + + // -> main menu void initMainMenu(); void uninitMainMenu(); @@ -332,6 +345,7 @@ private: static const uint8 _itemMagicTable[]; bool itemListMagic(int handItem, int itemSlot); + bool itemInventoryMagic(int handItem, int invSlot); static const uint8 _itemStringMap[]; static const uint _itemStringMapSize; diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 0ab1deb9bf..18386e29a7 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -36,6 +36,8 @@ #include "kyra/screen_v3.h" #include "kyra/resource.h" #include "kyra/gui_v1.h" +#include "kyra/gui_v2.h" +#include "kyra/gui_v3.h" #include "gui/message.h" @@ -2430,5 +2432,40 @@ const int8 KyraEngine_v3::_scoreTable[] = { const int KyraEngine_v3::_scoreTableSize = ARRAYSIZE(KyraEngine_v3::_scoreTable); +void KyraEngine_v3::initMainButtonList(bool disable) { + if (!_mainButtonListInitialized) { + _mainButtonData = new Button[14]; + assert(_mainButtonData); + + GUI_V3_BUTTON(_mainButtonData[0], 1, 0, 0, 4, 4, 4, 0x4487, 0, 5, 162, 50, 25, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + GUI_V3_BUTTON(_mainButtonData[1], 2, 0, 0, 1, 1, 1, 0x4487, 0, 245, 156, 69, 33, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + GUI_V3_BUTTON(_mainButtonData[2], 3, 0, 0, 1, 1, 1, 0x4487, 0, 215, 191, 24, 9, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + GUI_V3_BUTTON(_mainButtonData[3], 4, 0, 0, 1, 1, 1, 0x4487, 0, 215, 155, 25, 36, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + + Button::Callback buttonInventoryFunctor = BUTTON_FUNCTOR(KyraEngine_v3, this, &KyraEngine_v3::buttonInventory); + for (int i = 0; i < 5; ++i) { + GUI_V3_BUTTON(_mainButtonData[i+4], i+5, 0, 0, 0, 0, 0, 0x1100, 0, 67+i*28, 155, 27, 21, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + _mainButtonData[i+4].buttonCallback = buttonInventoryFunctor; + } + + for (int i = 0; i < 5; ++i) { + GUI_V3_BUTTON(_mainButtonData[i+9], i+10, 0, 0, 0, 0, 0, 0x1100, 0, 67+i*28, 177, 27, 21, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + _mainButtonData[i+9].buttonCallback = buttonInventoryFunctor; + } + + for (int i = 0; i < 14; ++i) + _mainButtonList = _gui->addButtonToList(_mainButtonList, &_mainButtonData[i]); + + _mainButtonListInitialized = true; + } + + for (int i = 0; i < 14; ++i) { + if (disable) + _gui->flagButtonDisable(&_mainButtonData[i]); + else + _gui->flagButtonEnable(&_mainButtonData[i]); + } +} + } // End of namespace Kyra -- cgit v1.2.3 From fa208a43867f2c0763ef6e21d31c5015438f921b Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 21:52:15 +0000 Subject: - Implemented support for jesters staff, mood change and score displaying - Fixed bug in KyraEngine_v3::loadMalcolmShapes svn-id: r31736 --- engines/kyra/gui_v3.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++++- engines/kyra/kyra_v3.cpp | 2 +- engines/kyra/kyra_v3.h | 3 ++ engines/kyra/staticres.cpp | 3 ++ engines/kyra/text_v3.cpp | 2 +- 5 files changed, 131 insertions(+), 4 deletions(-) diff --git a/engines/kyra/gui_v3.cpp b/engines/kyra/gui_v3.cpp index 6024673dbb..9e5546763a 100644 --- a/engines/kyra/gui_v3.cpp +++ b/engines/kyra/gui_v3.cpp @@ -276,7 +276,7 @@ void KyraEngine_v3::drawMalcolmsMoodText() { void KyraEngine_v3::drawMalcolmsMoodPointer(int frame, int page) { debugC(9, kDebugLevelMain, "KyraEngine_v3::drawMalcolmsMoodPointer(%d, %d)", frame, page); - static const int stateTable[] = { + static const uint8 stateTable[] = { 1, 6, 11 }; @@ -452,7 +452,7 @@ int KyraEngine_v3::buttonInventory(Button *button) { } else if (_itemInHand == 27) { if (_chatText) return 0; - //XXX + return buttonJesterStaff(&_mainButtonData[3]); } else { if (slotItem >= 0) { if (itemInventoryMagic(_itemInHand, slot)) @@ -483,6 +483,127 @@ int KyraEngine_v3::buttonInventory(Button *button) { return 0; } +int KyraEngine_v3::buttonMoodChange(Button *button) { + if (queryGameFlag(0x219)) { + playSoundEffect(0x0D, 0xC8); + return 0; + } + + static const uint8 frameTable[] = { 1, 6, 11 }; + + if (_mouseX >= 245 && _mouseX <= 267 && _mouseY >= 159 && _mouseY <= 198) + _malcolmsMood = 0; + else if (_mouseX >= 268 && _mouseX <= 289 && _mouseY >= 159 && _mouseY <= 198) + _malcolmsMood = 1; + else if (_mouseX >= 290 && _mouseX <= 312 && _mouseY >= 159 && _mouseY <= 198) + _malcolmsMood = 2; + + int direction = (_invWsaFrame > frameTable[_malcolmsMood]) ? -1 : 1; + + if (_invWsaFrame != frameTable[_malcolmsMood]) { + _screen->hideMouse(); + setGameFlag(3); + + playSoundEffect(0x2E, 0xC8); + + while (_invWsaFrame != frameTable[_malcolmsMood]) { + uint32 endTime = _system->getMillis() + 2 * _tickLength; + _invWsaFrame += direction; + + drawMalcolmsMoodPointer(_invWsaFrame, 0); + _screen->updateScreen(); + + while (endTime > _system->getMillis()) { + update(); + _system->delayMillis(10); + } + } + + resetGameFlag(3); + _screen->showMouse(); + + drawMalcolmsMoodText(); + updateDlgIndex(); + + ScriptData data; + ScriptState state; + memset(&data, 0, sizeof(data)); + memset(&state, 0, sizeof(state)); + + _res->exists("_ACTOR.EMC", true); + _scriptInterpreter->loadScript("_ACTOR.EMC", &data, &_opcodes); + _scriptInterpreter->initScript(&state, &data); + _scriptInterpreter->startScript(&state, 1); + + int vocHigh = _vocHigh; + _vocHigh = 200; + _useActorBuffer = true; + + while (_scriptInterpreter->validScript(&state)) + _scriptInterpreter->runScript(&state); + + _useActorBuffer = false; + _vocHigh = vocHigh; + _scriptInterpreter->unloadScript(&data); + } + + return 0; +} + +int KyraEngine_v3::buttonShowScore(Button *button) { + strcpy(_stringBuffer, (const char*)getTableEntry(_cCodeFile, 18)); + + char *buffer = _stringBuffer; + + while (*buffer != '%') + ++buffer; + + buffer[0] = (_score / 100) + '0'; + buffer[1] = ((_score % 100) / 10) + '0'; + buffer[2] = (_score % 10) + '0'; + + while (*buffer != '%') + ++buffer; + + buffer[0] = (_scoreMax / 100) + '0'; + buffer[1] = ((_scoreMax % 100) / 10) + '0'; + buffer[2] = (_scoreMax % 10) + '0'; + + showMessage(_stringBuffer, 0xFF, 0xF0); + return 0; +} + +int KyraEngine_v3::buttonJesterStaff(Button *button) { + makeCharFacingMouse(); + if (_itemInHand == 27) { + _screen->hideMouse(); + removeHandItem(); + playSoundEffect(0x0C, 0xC8); + drawJestersStaff(1, 0); + updateItemCommand(27, 2, 0xFF); + setGameFlag(0x97); + _screen->showMouse(); + } else if (_itemInHand == -1) { + if (queryGameFlag(0x97)) { + _screen->hideMouse(); + playSoundEffect(0x0B, 0xC8); + setHandItem(27); + drawJestersStaff(0, 0); + updateItemCommand(27, 0, 0xFF); + resetGameFlag(0x97); + _screen->showMouse(); + } else { + if (queryGameFlag(0x2F)) + objectChat((const char*)getTableEntry(_cCodeFile, 20), 0, 204, 20); + else + objectChat((const char*)getTableEntry(_cCodeFile, 25), 0, 204, 25); + } + } else { + objectChat((const char*)getTableEntry(_cCodeFile, 30), 0, 204, 30); + } + return 0; +} + #pragma mark - GUI_v3::GUI_v3(KyraEngine_v3 *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) { diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index a93375d286..b1204db6e4 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -809,7 +809,7 @@ void KyraEngine_v3::loadMalcolmShapes(int newShapes) { filename[numberOffset[i]+1] = lowNum; _res->exists(filename, true); _res->loadFileToBuf(filename, _screenBuffer, 64000); - for (int j = startShape[i]; j < endShape[i]; ++j) { + for (int j = startShape[i]; j <= endShape[i]; ++j) { if (j == 87) continue; addShapeToPool(_screenBuffer, j, j-startShape[i]); diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 946344cdb1..bb99f1f39d 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -157,6 +157,9 @@ private: bool _enableInventory; int buttonInventory(Button *button); + int buttonMoodChange(Button *button); + int buttonShowScore(Button *button); + int buttonJesterStaff(Button *button); // -> main menu void initMainMenu(); diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 18386e29a7..e079bf4636 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -2439,8 +2439,11 @@ void KyraEngine_v3::initMainButtonList(bool disable) { GUI_V3_BUTTON(_mainButtonData[0], 1, 0, 0, 4, 4, 4, 0x4487, 0, 5, 162, 50, 25, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); GUI_V3_BUTTON(_mainButtonData[1], 2, 0, 0, 1, 1, 1, 0x4487, 0, 245, 156, 69, 33, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + _mainButtonData[1].buttonCallback = BUTTON_FUNCTOR(KyraEngine_v3, this, &KyraEngine_v3::buttonMoodChange); GUI_V3_BUTTON(_mainButtonData[2], 3, 0, 0, 1, 1, 1, 0x4487, 0, 215, 191, 24, 9, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + _mainButtonData[2].buttonCallback = BUTTON_FUNCTOR(KyraEngine_v3, this, &KyraEngine_v3::buttonShowScore); GUI_V3_BUTTON(_mainButtonData[3], 4, 0, 0, 1, 1, 1, 0x4487, 0, 215, 155, 25, 36, 0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF0, 0); + _mainButtonData[3].buttonCallback = BUTTON_FUNCTOR(KyraEngine_v3, this, &KyraEngine_v3::buttonJesterStaff); Button::Callback buttonInventoryFunctor = BUTTON_FUNCTOR(KyraEngine_v3, this, &KyraEngine_v3::buttonInventory); for (int i = 0; i < 5; ++i) { diff --git a/engines/kyra/text_v3.cpp b/engines/kyra/text_v3.cpp index 640095ff1c..834903b18f 100644 --- a/engines/kyra/text_v3.cpp +++ b/engines/kyra/text_v3.cpp @@ -223,7 +223,7 @@ void KyraEngine_v3::objectChat(const char *str, int object, int vocHigh, int voc static const char *talkFilenameTable[] = { "MTFL00S.EMC", "MTFL00Q.EMC", "MTFL00E.EMC", "MTFL00T.EMC", - "MTFR00S.EMC", "MTFR00Q.EMC", "MTFR00E.EMC", "MTRF00T.EMC", + "MTFR00S.EMC", "MTFR00Q.EMC", "MTFR00E.EMC", "MTFR00T.EMC", "MTL00S.EMC", "MTL00Q.EMC", "MTL00E.EMC", "MTL00T.EMC", "MTR00S.EMC", "MTR00Q.EMC", "MTR00E.EMC", "MTR00T.EMC", "MTA00S.EMC", "MTA00Q.EMC", "MTA00Q.EMC", "MTA00T.EMC" -- cgit v1.2.3 From 6ed2d9c28701931b3633b638ad736f371f4024cf Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:13:19 +0000 Subject: Implemented opcodes: - 26: o3_setInventorySlot - 27: o3_getInventorySlot - 28: o3_addItemToInventory svn-id: r31737 --- engines/kyra/items_v3.cpp | 9 +++++++++ engines/kyra/kyra_v3.h | 5 +++++ engines/kyra/script_v3.cpp | 31 ++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp index 4417ba4aa5..aecf4337ce 100644 --- a/engines/kyra/items_v3.cpp +++ b/engines/kyra/items_v3.cpp @@ -64,6 +64,15 @@ int KyraEngine_v3::findFreeItem() { return -1; } +int KyraEngine_v3::findFreeInventorySlot() { + debugC(9, kDebugLevelMain, "KyraEngine_v3::findFreeInventorySlot()"); + for (int i = 0; i < 10; ++i) { + if (_mainCharacter.inventory[i] == 0xFFFF) + return i; + } + return -1; +} + int KyraEngine_v3::findItem(uint16 sceneId, uint16 id) { debugC(9, kDebugLevelMain, "KyraEngine_v3::findItem(%u, %u)", sceneId, id); for (int i = 0; i < 50; ++i) { diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index bb99f1f39d..ac7625e8ee 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -539,6 +539,8 @@ private: void makeCharFacingMouse(); + int findFreeInventorySlot(); + // talk object struct TalkObject { char filename[13]; @@ -704,6 +706,9 @@ private: int o3_setCharacterAnimFrameFromFacing(ScriptState *script); int o3_showBadConscience(ScriptState *script); int o3_hideBadConscience(ScriptState *script); + int o3_setInventorySlot(ScriptState *script); + int o3_getInventorySlot(ScriptState *script); + int o3_addItemToInventory(ScriptState *script); int o3_addItemToCurScene(ScriptState *script); int o3_objectChat(ScriptState *script); int o3_checkForItem(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index c4bba4c81d..fd9f95faf0 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -185,6 +185,31 @@ int KyraEngine_v3::o3_hideBadConscience(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_setInventorySlot(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setInventorySlot(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + const int slot = MAX(0, MIN(10, stackPos(0))); + return (_mainCharacter.inventory[slot] = stackPos(1)); +} + +int KyraEngine_v3::o3_getInventorySlot(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getInventorySlot(%p) (%d)", (const void *)script, stackPos(0)); + return _mainCharacter.inventory[stackPos(0)]; +} + +int KyraEngine_v3::o3_addItemToInventory(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_addItemToInventory(%p) (%d)", (const void *)script, stackPos(0)); + int slot = findFreeInventorySlot(); + if (slot >= 0) { + _mainCharacter.inventory[slot] = stackPos(0); + if (_inventoryState) { + _screen->hideMouse(); + redrawInventory(0); + _screen->showMouse(); + } + } + return slot; +} + int KyraEngine_v3::o3_addItemToCurScene(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_addItemToCurScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2)); const uint16 item = stackPos(0); @@ -1252,10 +1277,10 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x18 OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_setInventorySlot); + Opcode(o3_getInventorySlot); // 0x1c - OpcodeUnImpl(); + Opcode(o3_addItemToInventory); OpcodeUnImpl(); Opcode(o3_addItemToCurScene); Opcode(o3_objectChat); -- cgit v1.2.3 From 71f4dee9ae22431ff78e8b46cf1a1feca173dae8 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:22:21 +0000 Subject: Implemented opcode 129 o3_chapterChange. svn-id: r31738 --- engines/kyra/kyra_v3.cpp | 19 +++++++++++++++++++ engines/kyra/kyra_v3.h | 3 +++ engines/kyra/script_v3.cpp | 8 +++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index b1204db6e4..574ffd24d3 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -1678,6 +1678,25 @@ void KyraEngine_v3::scoreIncrease(int count, const char *str) { #pragma mark - +void KyraEngine_v3::changeChapter(int newChapter, int sceneId, int malcolmShapes, int facing) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::changeChapter(%d, %d, %d, %d)", newChapter, sceneId, malcolmShapes, facing); + resetItemList(); + + _curChapter = newChapter; + runStartupScript(newChapter, 0); + _mainCharacter.dlgIndex = 0; + + _malcolmsMood = 1; + memset(_newSceneDlgState, 0, sizeof(_newSceneDlgState)); + + if (malcolmShapes >= 0) + loadMalcolmShapes(malcolmShapes); + + enterNewScene(sceneId, facing, 0, 0, 0); +} + +#pragma mark - + Movie *KyraEngine_v3::createWSAMovie() { WSAMovieV2 *movie = new WSAMovieV2(this, _screen); assert(movie); diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index ac7625e8ee..fbd9bcd487 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -662,7 +662,9 @@ private: uint8 *_screenBuffer; uint8 *_paletteOverlay; bool _useActorBuffer; + int _curChapter; + void changeChapter(int newChapter, int sceneId, int malcolmShapes, int facing); static const uint8 _chapterLowestScene[]; @@ -760,6 +762,7 @@ private: int o3_setDlgIndex(ScriptState *script); int o3_getDlgIndex(ScriptState *script); int o3_defineScene(ScriptState *script); + int o3_changeChapter(ScriptState *script); int o3_countItemInstances(ScriptState *script); int o3_dialogStartScript(ScriptState *script); int o3_dialogEndScript(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index fd9f95faf0..3cc2fd5b17 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -1041,6 +1041,12 @@ int KyraEngine_v3::o3_defineScene(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_changeChapter(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_changeChapter(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + changeChapter(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + return 0; +} + int KyraEngine_v3::o3_countItemInstances(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_countItemInstances(%p) (%d)", (const void *)script, stackPos(0)); int count = 0; @@ -1406,7 +1412,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_dummy); // 0x80 Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_changeChapter); Opcode(o3_dummy); Opcode(o3_dummy); // 0x84 -- cgit v1.2.3 From dd98898a23d8dfffcfe95c70fa0b528e3f418332 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:29:27 +0000 Subject: Implemented opcodes: - 78: o3_disableInventory - 79: o3_enableInventory svn-id: r31739 --- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index fbd9bcd487..e22340491b 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -741,6 +741,8 @@ private: int o3_setSceneDim(ScriptState *script); int o3_update(ScriptState *script); int o3_removeItemInstances(ScriptState *script); + int o3_disableInventory(ScriptState *script); + int o3_enableInventory(ScriptState *script); int o3_enterNewScene(ScriptState *script); int o3_setMalcolmPos(ScriptState *script); int o3_stopMusic(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 3cc2fd5b17..288b6720f9 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -742,6 +742,18 @@ int KyraEngine_v3::o3_removeItemInstances(ScriptState *script) { return deleted; } +int KyraEngine_v3::o3_disableInventory(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_disableInventory(%p) ()", (const void *)script); + _enableInventory = false; + return 0; +} + +int KyraEngine_v3::o3_enableInventory(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_enableInventory(%p) ()", (const void *)script); + _enableInventory = true; + return 1; +} + int KyraEngine_v3::o3_enterNewScene(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4)); @@ -1347,9 +1359,9 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_update); // 0x4c Opcode(o3_removeItemInstances); - OpcodeUnImpl(); - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_dummy); + Opcode(o3_disableInventory); + Opcode(o3_enableInventory); // 0x50 Opcode(o3_enterNewScene); OpcodeUnImpl(); -- cgit v1.2.3 From 99307976d5afc6896fe00f9906a3355fd543a839 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:30:55 +0000 Subject: Finished o3_delay implementation. svn-id: r31740 --- engines/kyra/script_v3.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 288b6720f9..3db0d4c23c 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -384,13 +384,24 @@ int KyraEngine_v3::o3_setMalcolmsMood(ScriptState *script) { int KyraEngine_v3::o3_delay(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_delay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); - const uint32 delayTime = stackPos(0) * _tickLength; - const int delayFunc = stackPos(1); + if (stackPos(1)) { + uint32 maxWaitTime = _system->getMillis() + stackPos(0) * _tickLength; + while (_system->getMillis() < maxWaitTime) { + int inputFlag = checkInput(0); + removeInputTop(); - if (delayFunc) - warning("STUB o3_delay func 1"); + if (inputFlag == 198 || inputFlag == 199) + return 1; - delay(delayTime, true); + if (_chatText) + updateWithText(); + else + update(); + _system->delayMillis(10); + } + } else { + delay(stackPos(0) * _tickLength, true); + } return 0; } -- cgit v1.2.3 From b179320edf55db93133dd118be116ede16795fb1 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:33:07 +0000 Subject: Implemented opcode 34: o3_resetInventory. svn-id: r31741 --- engines/kyra/kyra_v3.h | 1 + engines/kyra/script_v3.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index e22340491b..a8bf4baab6 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -714,6 +714,7 @@ private: int o3_addItemToCurScene(ScriptState *script); int o3_objectChat(ScriptState *script); int o3_checkForItem(ScriptState *script); + int o3_resetInventory(ScriptState *script); int o3_defineItem(ScriptState *script); int o3_npcChatSequence(ScriptState *script); int o3_queryGameFlag(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 3db0d4c23c..e05bc3b471 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -255,6 +255,12 @@ int KyraEngine_v3::o3_checkForItem(ScriptState *script) { return findItem(stackPos(0), stackPos(1)) == -1 ? 0 : 1; } +int KyraEngine_v3::o3_resetInventory(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_resetInventory(%p) ()", (const void *)script); + memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory)); + return 0; +} + int KyraEngine_v3::o3_defineItem(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_defineItem(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int freeItem = findFreeItem(); @@ -1316,7 +1322,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x20 Opcode(o3_checkForItem); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_resetInventory); Opcode(o3_defineItem); // 0x24 OpcodeUnImpl(); -- cgit v1.2.3 From c0f4b3faa7c1b49e4e0a92703de2a3b6ef5b1bb0 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 22:53:00 +0000 Subject: - load new tlk file on chapter change - added warning when trying to play non-existent soundfile svn-id: r31742 --- engines/kyra/resource.cpp | 1 - engines/kyra/scene_v3.cpp | 7 +++++-- engines/kyra/sound_digital.cpp | 4 +++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 0a07392d8d..b2564221fc 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -716,7 +716,6 @@ bool ResLoaderTlk::loadFile(const Common::String &filename, Common::SeekableRead char realFilename[20]; snprintf(realFilename, 20, "%u.AUD", resFilename); - uint32 curOffset = stream.pos(); stream.seek(resOffset, SEEK_SET); entry.size = stream.readUint32LE(); diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index 977d9540f8..8463fc3cb5 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -42,7 +42,10 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 } musicUpdate(0); - //XXX + if (_curChapter != _currentTalkFile) { + _currentTalkFile = _curChapter; + openTalkFile(_currentTalkFile); + } musicUpdate(0); if (!unk3) { @@ -445,7 +448,7 @@ void KyraEngine_v3::initSceneScript(int unk1) { _res->exists(filename, true); _scriptInterpreter->loadScript(filename, &_sceneScriptData, &_opcodes); - strcpy(filename, scene.filename1); + strcpy(filename, scene.filename2); strcat(filename, "."); loadLanguageFile(filename, _sceneStrings); musicUpdate(0); diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index 24a33e5539..3a4eeba0f5 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -366,8 +366,10 @@ int SoundDigital::playSound(const char *filename, uint8 priority, Audio::Mixer:: } Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filename); - if (!stream) + if (!stream) { + warning("Couldn't find soundfile '%s'", filename); return -1; + } strncpy(use->filename, filename, sizeof(use->filename)); use->priority = priority; -- cgit v1.2.3 From 567c7312356d8f9e8207c4d5ef476a8235591fcb Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 23:01:06 +0000 Subject: Added code to play VQA files when entering new scenes. svn-id: r31743 --- engines/kyra/scene_v3.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index 8463fc3cb5..529ee0f3e3 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -116,7 +116,6 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 musicUpdate(0); unloadScene(); musicUpdate(0); - //XXX resetMaskPage(); for (int i = 0; i < 4; ++i) { if (i != _musicSoundChannel && i != _fadeOutMusicChannel) @@ -128,7 +127,27 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 musicUpdate(0); if (queryGameFlag(0x1D9)) { - //XXX VQA code here + char filename[20]; + if (queryGameFlag(0x20D)) { + resetGameFlag(0x20D); + strcpy(filename, "COW1_"); + } else if (queryGameFlag(0x20E)) { + resetGameFlag(0x20E); + strcpy(filename, "COW2_"); + } else if (queryGameFlag(0x20F)) { + resetGameFlag(0x20F); + strcpy(filename, "COW3_"); + } else if (queryGameFlag(0x20C)) { + resetGameFlag(0x20C); + strcpy(filename, "BOAT"); + } else if (queryGameFlag(0x210)) { + resetGameFlag(0x210); + strcpy(filename, "JUNG"); + } + + playVQA(filename); + + resetGameFlag(0x1D9); } musicUpdate(0); -- cgit v1.2.3 From 9b3edffa8dcc532370d3e8d924610642701237bf Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 23:26:47 +0000 Subject: Implemented opcodes: - 74: o3_setSceneAnimPosAndFrame - 81: o3_switchScene svn-id: r31744 --- engines/kyra/kyra_v3.h | 4 +++ engines/kyra/script_v3.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index a8bf4baab6..ae5b9040de 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -716,6 +716,8 @@ private: int o3_checkForItem(ScriptState *script); int o3_resetInventory(ScriptState *script); int o3_defineItem(ScriptState *script); + int o3_removeInventoryItemInstances(ScriptState *script); + int o3_countInventoryItemInstances(ScriptState *script); int o3_npcChatSequence(ScriptState *script); int o3_queryGameFlag(ScriptState *script); int o3_resetGameFlag(ScriptState *script); @@ -741,10 +743,12 @@ private: int o3_updateConversations(ScriptState *script); int o3_setSceneDim(ScriptState *script); int o3_update(ScriptState *script); + int o3_setSceneAnimPosAndFrame(ScriptState *script); int o3_removeItemInstances(ScriptState *script); int o3_disableInventory(ScriptState *script); int o3_enableInventory(ScriptState *script); int o3_enterNewScene(ScriptState *script); + int o3_switchScene(ScriptState *script); int o3_setMalcolmPos(ScriptState *script); int o3_stopMusic(ScriptState *script); int o3_playMusicTrack(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index e05bc3b471..f620750891 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -273,6 +273,32 @@ int KyraEngine_v3::o3_defineItem(ScriptState *script) { return freeItem; } +int KyraEngine_v3::o3_removeInventoryItemInstances(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_removeInventoryItemInstances(%p) (%d)", (const void *)script, stackPos(0)); + const int item = stackPos(0); + for (int i = 0; i < 10; ++i) { + if (_mainCharacter.inventory[i] == item) + _mainCharacter.inventory[i] = 0xFFFF; + } + return 0; +} + +int KyraEngine_v3::o3_countInventoryItemInstances(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_countInventoryItemInstances(%p) (%d)", (const void *)script, stackPos(0)); + const int item = stackPos(0); + int count = 0; + + for (int i = 0; i < 10; ++i) { + if (_mainCharacter.inventory[i] == item) + ++count; + } + + if (_itemInHand == item) + ++count; + + return count; +} + int KyraEngine_v3::o3_npcChatSequence(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_npcChatSequence(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); const int id = stackPos(0); @@ -720,6 +746,35 @@ int KyraEngine_v3::o3_setSceneDim(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_setSceneAnimPosAndFrame(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setSceneAnimPosAndFrame(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, + stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); + SceneAnim &anim = _sceneAnims[stackPos(0)]; + const int newX2 = stackPos(1); + const int newY2 = stackPos(2); + const int newX = stackPos(3); + const int newY = stackPos(4); + + if (newX2 >= 0) + anim.x2 = newX2; + if (newY2 >= 0) + anim.y2 = newY2; + + if (newX >= 0) + anim.x = newX; + else + anim.x = anim.x2 + (anim.width >> 1); + + if (newY >= 0) + anim.y = newY; + else + anim.y = anim.y2 + anim.height - 1; + + updateSceneAnim(stackPos(0), stackPos(5)); + _specialSceneScriptRunFlag = false; + return 0; +} + int KyraEngine_v3::o3_update(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_update(%p) (%d)", (const void *)script, stackPos(0)); for (int times = stackPos(0); times != 0; --times) { @@ -789,6 +844,17 @@ int KyraEngine_v3::o3_enterNewScene(ScriptState *script) { return 0; } +int KyraEngine_v3::o3_switchScene(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_switchScene(%p) (%d)", (const void *)script, stackPos(0)); + setGameFlag(1); + _mainCharX = _mainCharacter.x1; + _mainCharY = _mainCharacter.y1; + _noScriptEnter = false; + enterNewScene(stackPos(0), _mainCharacter.facing, 0, 0, 0); + _noScriptEnter = true; + return 0; +} + int KyraEngine_v3::o3_setMalcolmPos(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setMalcolmPos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); _mainCharX = stackPos(0); @@ -1325,8 +1391,8 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_resetInventory); Opcode(o3_defineItem); // 0x24 - OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(o3_removeInventoryItemInstances); + Opcode(o3_countInventoryItemInstances); Opcode(o3_npcChatSequence); Opcode(o3_queryGameFlag); // 0x28 @@ -1372,7 +1438,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x48 Opcode(o3_dummy); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_setSceneAnimPosAndFrame); Opcode(o3_update); // 0x4c Opcode(o3_removeItemInstances); @@ -1381,7 +1447,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_enableInventory); // 0x50 Opcode(o3_enterNewScene); - OpcodeUnImpl(); + Opcode(o3_switchScene); OpcodeUnImpl(); Opcode(o3_dummy); // 0x54 -- cgit v1.2.3 From f6e622e303fa6ef58d479d7be098f188741b7e5c Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Apr 2008 23:43:12 +0000 Subject: Cleanup. svn-id: r31745 --- engines/kyra/kyra_v3.cpp | 9 --------- engines/kyra/kyra_v3.h | 1 - engines/kyra/scene_v3.cpp | 5 ----- 3 files changed, 15 deletions(-) diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index 574ffd24d3..cd624b27d8 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -73,7 +73,6 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _inventoryState = false; memset(&_sceneScriptState, 0, sizeof(_sceneScriptState)); memset(&_sceneScriptData, 0, sizeof(_sceneScriptData)); - memset(_wsaSlots, 0, sizeof(_wsaSlots)); _updateCharPosNextUpdate = 0; memset(_characterAnimTable, 0, sizeof(_characterAnimTable)); _overwriteSceneFacing = false; @@ -175,9 +174,6 @@ KyraEngine_v3::~KyraEngine_v3() { _scriptInterpreter->unloadScript(&_sceneScriptData); - for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) - delete _wsaSlots[i]; - delete [] _sceneStrings; delete [] _talkObjectList; delete [] _moveFacingTable; @@ -524,11 +520,6 @@ void KyraEngine_v3::initMouseShapes() { void KyraEngine_v3::startup() { debugC(9, kDebugLevelMain, "KyraEngine_v3::startup()"); - for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i) { - _wsaSlots[i] = new WSAMovieV2(this, _screen); - assert(_wsaSlots[i]); - } - musicUpdate(0); memset(_flagsTable, 0, sizeof(_flagsTable)); diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index ae5b9040de..f4a8ed39dd 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -463,7 +463,6 @@ private: ScriptState _sceneScriptState; ScriptData _sceneScriptData; - WSAMovieV2 *_wsaSlots[10]; bool _specialSceneScriptState[10]; bool _specialSceneScriptStateBackup[10]; diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index 529ee0f3e3..3485e95d1c 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -101,11 +101,6 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 musicUpdate(0); - for (int i = 0; i < 10; ++i) - _wsaSlots[i]->close(); - - musicUpdate(0); - _specialExitCount = 0; Common::set_to(_specialExitTable, _specialExitTable+ARRAYSIZE(_specialExitTable), 0xFFFF); -- cgit v1.2.3 From 78ee2e449e2c5062b41b197600b82e9d986f4075 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 27 Apr 2008 00:38:01 +0000 Subject: Implemented (quick-)save/load support for kyra3. svn-id: r31747 --- engines/kyra/kyra_v3.cpp | 6 +- engines/kyra/kyra_v3.h | 8 +- engines/kyra/module.mk | 1 + engines/kyra/saveload_v3.cpp | 262 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 engines/kyra/saveload_v3.cpp diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index cd624b27d8..c162209b5e 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -1004,7 +1004,7 @@ void KyraEngine_v3::runLoop() { if (_system->getMillis() >= _nextIdleAnim) showIdleAnim(); - int inputFlag = checkInput(_mainButtonList); + int inputFlag = checkInput(_mainButtonList, true); removeInputTop(); update(); @@ -1368,7 +1368,7 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { 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) && mainLoop) { - /*const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); + const char *saveLoadSlot = getSavegameFilename(9 - (event.kbd.keycode - '0') + 990); if (event.kbd.flags == Common::KBD_CTRL) { loadGame(saveLoadSlot); @@ -1378,7 +1378,7 @@ int KyraEngine_v3::checkInput(Button *buttonList, bool mainLoop) { char savegameName[14]; 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(); diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index f4a8ed39dd..58fbbdace6 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -502,7 +502,7 @@ private: uint8 facing; uint16 animFrame; //uint8 unk8, unk9; - uint32 walkspeed; + byte walkspeed; uint16 inventory[10]; int16 x1, y1; int16 x2, y2; @@ -579,7 +579,7 @@ private: void malcolmSceneStartupChat(); - bool _newSceneDlgState[40]; + byte _newSceneDlgState[40]; int8 _conversationState[30][30]; bool _chatAltFlag; void setDlgIndex(uint16 index); @@ -688,6 +688,10 @@ private: bool updateScore(int scoreId, int strId); void scoreIncrease(int count, const char *str); + // save/load + void saveGame(const char *fileName, const char *saveName); + void loadGame(const char *fileName); + // opcodes int o3_getMalcolmShapes(ScriptState *script); int o3_setCharacterPos(ScriptState *script); diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index bfb0e057fe..d53479b133 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -21,6 +21,7 @@ MODULE_OBJS := \ saveload.o \ saveload_v1.o \ saveload_v2.o \ + saveload_v3.o \ scene.o \ scene_v1.o \ scene_v2.o \ diff --git a/engines/kyra/saveload_v3.cpp b/engines/kyra/saveload_v3.cpp new file mode 100644 index 0000000000..09d7d244e0 --- /dev/null +++ b/engines/kyra/saveload_v3.cpp @@ -0,0 +1,262 @@ +/* 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/endian.h" +#include "common/savefile.h" +#include "common/system.h" + +#include "kyra/kyra_v3.h" +#include "kyra/timer.h" + +namespace Kyra { + +void KyraEngine_v3::saveGame(const char *fileName, const char *saveName) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::saveGame('%s', '%s')", fileName, saveName); + + Common::OutSaveFile *out = openSaveForWriting(fileName, saveName); + if (!out) { + warning("Can't open file '%s', game not loadable", fileName); + return; + } + + _timer->saveDataToFile(*out); + + out->writeUint32BE(sizeof(_flagsTable)); + out->write(_flagsTable, sizeof(_flagsTable)); + + out->writeSint16BE(_curMusicTrack); + out->writeByte(_curChapter); + out->writeByte(_malcolmShapes); + //XXX + out->writeSint16BE(_score); + out->writeSint16BE(_scoreMax); + out->writeByte(_malcolmsMood); + out->write(_conversationState, sizeof(_conversationState)); + out->write(_newSceneDlgState, sizeof(_newSceneDlgState)); + for (int i = 0; i < 100; ++i) + out->writeUint16BE(_hiddenItems[i]); + out->write(_scoreFlagTable, sizeof(_scoreFlagTable)); + + out->writeUint16BE(_mainCharacter.sceneId); + out->writeUint16BE(_mainCharacter.dlgIndex); + out->writeByte(_mainCharacter.height); + out->writeByte(_mainCharacter.facing); + out->writeUint16BE(_mainCharacter.animFrame); + out->writeByte(_mainCharacter.walkspeed); + for (int i = 0; i < 10; ++i) + out->writeUint16BE(_mainCharacter.inventory[i]); + out->writeSint16BE(_mainCharacter.x1); + out->writeSint16BE(_mainCharacter.y1); + out->writeSint16BE(_mainCharacter.x2); + out->writeSint16BE(_mainCharacter.y2); + out->writeSint16BE(_mainCharacter.x3); + out->writeSint16BE(_mainCharacter.y3); + + for (int i = 0; i < 50; ++i) { + out->writeUint16BE(_itemList[i].id); + out->writeUint16BE(_itemList[i].sceneId); + out->writeSint16BE(_itemList[i].x); + out->writeSint16BE(_itemList[i].y); + out->writeUint16BE(_itemList[i].unk8); + } + + for (int i = 0; i < 88; ++i) { + out->write(_talkObjectList[i].filename, 13); + out->writeByte(_talkObjectList[i].sceneAnim); + out->writeByte(_talkObjectList[i].sceneScript); + out->writeSint16BE(_talkObjectList[i].x); + out->writeSint16BE(_talkObjectList[i].y); + out->writeByte(_talkObjectList[i].color); + } + + for (int i = 0; i < 98; ++i) { + out->write(_sceneList[i].filename1, 10); + out->write(_sceneList[i].filename2, 10); + out->writeUint16BE(_sceneList[i].exit1); + out->writeUint16BE(_sceneList[i].exit2); + out->writeUint16BE(_sceneList[i].exit3); + out->writeUint16BE(_sceneList[i].exit4); + out->writeByte(_sceneList[i].flags); + out->writeByte(_sceneList[i].sound); + } + + out->writeSint16BE(_itemInHand); + out->writeUint16BE(_sceneExit1); + out->writeUint16BE(_sceneExit2); + out->writeUint16BE(_sceneExit3); + out->writeUint16BE(_sceneExit4); + + out->finalize(); + + // check for errors + if (out->ioFailed()) + warning("Can't write file '%s'. (Disk full?)", fileName); + else + debugC(1, kDebugLevelMain, "Saved game '%s.'", saveName); + + delete out; +} + +void KyraEngine_v3::loadGame(const char *fileName) { + debugC(9, kDebugLevelMain, "KyraEngine_v3::loadGame('%s')", fileName); + + SaveHeader header; + Common::InSaveFile *saveFile = openSaveForReading(fileName, header); + if (!saveFile) { + showMessageFromCCode(17, 0xB3, 0); + playSoundEffect(0x0D, 0xC8); + return; + } + + if (_inventoryState) { + updateCharacterAnim(0); + restorePage3(); + drawAnimObjects(); + _inventoryState = true; + refreshAnimObjects(0); + hideInventory(); + } + + _deathHandler = -1; + if (!_unkSceneScreenFlag1) + _curMusicTrack = -1; + + int curShapes = _malcolmShapes; + + Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, true); + + _screen->hideMouse(); + + _timer->loadDataFromFile(in, header.version); + + uint32 flagsSize = in.readUint32BE(); + assert(flagsSize <= sizeof(_flagsTable)); + in.read(_flagsTable, flagsSize); + + // usually we have to save the flag set by opcode 10 here + _curMusicTrack = in.readSint16(); + _curChapter = in.readByte(); + _malcolmShapes = in.readByte(); + //XXX + _score = in.readSint16(); + _scoreMax = in.readSint16(); + _malcolmsMood = in.readByte(); + in.read(_conversationState, sizeof(_conversationState)); + in.read(_newSceneDlgState, sizeof(_newSceneDlgState)); + for (int i = 0; i < 100; ++i) + _hiddenItems[i] = in.readUint16(); + in.read(_scoreFlagTable, sizeof(_scoreFlagTable)); + + _mainCharacter.sceneId = in.readUint16(); + _mainCharacter.dlgIndex = in.readUint16(); + _mainCharacter.height = in.readByte(); + _mainCharacter.facing = in.readByte(); + _mainCharacter.animFrame = in.readUint16(); + _mainCharacter.walkspeed = in.readByte(); + for (int i = 0; i < 10; ++i) + _mainCharacter.inventory[i] = in.readUint16(); + _mainCharacter.x1 = in.readSint16(); + _mainCharacter.y1 = in.readSint16(); + _mainCharacter.x2 = in.readSint16(); + _mainCharacter.y2 = in.readSint16(); + _mainCharacter.x3 = in.readSint16(); + _mainCharacter.y3 = in.readSint16(); + + for (int i = 0; i < 50; ++i) { + _itemList[i].id = in.readUint16(); + _itemList[i].sceneId = in.readUint16(); + _itemList[i].x = in.readSint16(); + _itemList[i].y = in.readSint16(); + _itemList[i].unk8 = in.readUint16(); + } + + for (int i = 0; i < 88; ++i) { + in.read(_talkObjectList[i].filename, 13); + _talkObjectList[i].sceneAnim = in.readByte(); + _talkObjectList[i].sceneScript = in.readByte(); + _talkObjectList[i].x = in.readSint16(); + _talkObjectList[i].y = in.readSint16(); + _talkObjectList[i].color = in.readByte(); + } + + for (int i = 0; i < 86; ++i) { + in.read(_sceneList[i].filename1, 10); + in.read(_sceneList[i].filename2, 10); + _sceneList[i].exit1 = in.readUint16(); + _sceneList[i].exit2 = in.readUint16(); + _sceneList[i].exit3 = in.readUint16(); + _sceneList[i].exit4 = in.readUint16(); + _sceneList[i].flags = in.readByte(); + _sceneList[i].sound = in.readByte(); + } + + _itemInHand = in.readSint16(); + _sceneExit1 = in.readUint16(); + _sceneExit2 = in.readUint16(); + _sceneExit3 = in.readUint16(); + _sceneExit4 = in.readUint16(); + + if (saveFile->ioFailed()) + error("Load failed ('%s', '%s').", fileName, header.description.c_str()); + else + debugC(1, kDebugLevelMain, "Loaded savegame '%s.'", header.description.c_str()); + + _loadingState = true; + updateCharacterAnim(0); + _loadingState = false; + + if (curShapes != _malcolmShapes) + loadMalcolmShapes(_malcolmShapes); + + _mainCharX = _mainCharacter.x2 = _mainCharacter.x1; + _mainCharY = _mainCharacter.y2 = _mainCharacter.y1; + _mainCharacter.facing = 4; + _badConscienceShown = false; + _badConsciencePosition = false; + //_goodConscienceShown = false; + //_goodConsciencePosition = false; + + enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); + setHandItem(_itemInHand); + + if (_curMusicTrack >= 0 && !_unkSceneScreenFlag1) + playMusicTrack(_curMusicTrack, 1); + else if (_curMusicTrack == -1) + playMusicTrack(28, 1); + + while (!_screen->isMouseVisible()) + _screen->showMouse(); + + setCommandLineRestoreTimer(7); + _shownMessage = " "; + _restoreCommandLine = false; + + // We didn't explicitly set the walk speed, but it's saved as part of + // the _timers array, so we need to re-sync it with _configWalkspeed. + setWalkspeed(_configWalkspeed); +} + +} // end of namespace Kyra + -- cgit v1.2.3 From d49dd4e2fa51eb64d57e88600ef8ea00a63e761a Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 27 Apr 2008 00:42:17 +0000 Subject: Renamed some kyra3 variables to match kyra2/kyra1 names. svn-id: r31748 --- engines/kyra/items_v3.cpp | 4 ++-- engines/kyra/kyra_v3.cpp | 18 +++++++++--------- engines/kyra/kyra_v3.h | 4 +--- engines/kyra/saveload_v3.cpp | 16 ++++++++-------- engines/kyra/scene_v3.cpp | 6 +++--- engines/kyra/script_v3.cpp | 8 ++++---- engines/kyra/sequences_v3.cpp | 8 ++++---- engines/kyra/text_v3.cpp | 18 +++++++++--------- 8 files changed, 40 insertions(+), 42 deletions(-) diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp index aecf4337ce..5aec674546 100644 --- a/engines/kyra/items_v3.cpp +++ b/engines/kyra/items_v3.cpp @@ -482,7 +482,7 @@ bool KyraEngine_v3::itemListMagic(int handItem, int itemSlot) { debugC(9, kDebugLevelMain, "KyraEngine_v3::itemListMagic(%d, %d)", handItem, itemSlot); uint16 item = _itemList[itemSlot].id; - if (_curChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { + if (_currentChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { //eelScript(); return true; } else if ((handItem == 6 || handItem == 7) && item == 2) { @@ -556,7 +556,7 @@ bool KyraEngine_v3::itemInventoryMagic(int handItem, int invSlot) { debugC(9, kDebugLevelMain, "KyraEngine_v3::itemInventoryMagic(%d, %d)", handItem, invSlot); uint16 item = _mainCharacter.inventory[invSlot]; - if (_curChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { + if (_currentChapter == 1 && handItem == 3 && item == 3 && queryGameFlag(0x76)) { //eelScript(); return true; } else if ((handItem == 6 || handItem == 7) && item == 2) { diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index c162209b5e..c08d75fb24 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -43,7 +43,7 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _soundDigital = 0; _musicSoundChannel = -1; _menuAudioFile = "TITLE1.AUD"; - _curMusicTrack = -1; + _lastMusicCommand = -1; _itemBuffer1 = _itemBuffer2 = 0; _scoreFile = 0; _cCodeFile = 0; @@ -108,7 +108,7 @@ KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngi _useActorBuffer = false; _curStudioSFX = 283; _badConscienceShown = false; - _curChapter = 1; + _currentChapter = 1; _deathHandler = -1; _moveFacingTable = 0; _unkHandleSceneChangeFlag = false; @@ -386,7 +386,7 @@ void KyraEngine_v3::playMusicTrack(int track, int force) { else if (_musicSoundChannel == -1) force = 1; - if (track == _curMusicTrack && !force) + if (track == _lastMusicCommand && !force) return; stopMusicTrack(); @@ -397,7 +397,7 @@ void KyraEngine_v3::playMusicTrack(int track, int force) { _musicSoundChannel = _soundDigital->playSound(_soundList[track], 0xFF, Audio::Mixer::kMusicSoundType); } - _curMusicTrack = track; + _lastMusicCommand = track; } void KyraEngine_v3::stopMusicTrack() { @@ -406,7 +406,7 @@ void KyraEngine_v3::stopMusicTrack() { if (_musicSoundChannel != -1 && _soundDigital->isPlaying(_musicSoundChannel)) _soundDigital->stopSound(_musicSoundChannel); - _curMusicTrack = -1; + _lastMusicCommand = -1; _musicSoundChannel = -1; } @@ -426,8 +426,8 @@ int KyraEngine_v3::musicUpdate(int forceRestart) { lock = 1; if (_musicSoundChannel >= 0) { if (!_soundDigital->isPlaying(_musicSoundChannel)) { - if (_curMusicTrack != -1) - playMusicTrack(_curMusicTrack, 1); + if (_lastMusicCommand != -1) + playMusicTrack(_lastMusicCommand, 1); } } lock = 0; @@ -442,7 +442,7 @@ void KyraEngine_v3::fadeOutMusic(int ticks) { if (_musicSoundChannel >= 0) { _fadeOutMusicChannel = _musicSoundChannel; _soundDigital->beginFadeOut(_musicSoundChannel, ticks); - _curMusicTrack = -1; + _lastMusicCommand = -1; } } @@ -1673,7 +1673,7 @@ void KyraEngine_v3::changeChapter(int newChapter, int sceneId, int malcolmShapes debugC(9, kDebugLevelMain, "KyraEngine_v3::changeChapter(%d, %d, %d, %d)", newChapter, sceneId, malcolmShapes, facing); resetItemList(); - _curChapter = newChapter; + _currentChapter = newChapter; runStartupScript(newChapter, 0); _mainCharacter.dlgIndex = 0; diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index 58fbbdace6..cdbdc11998 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -122,8 +122,6 @@ private: static const char *_soundList[]; static const int _soundListSize; - int _curMusicTrack; - void playMusicTrack(int track, int force); void stopMusicTrack(); @@ -662,7 +660,7 @@ private: uint8 *_paletteOverlay; bool _useActorBuffer; - int _curChapter; + int _currentChapter; void changeChapter(int newChapter, int sceneId, int malcolmShapes, int facing); static const uint8 _chapterLowestScene[]; diff --git a/engines/kyra/saveload_v3.cpp b/engines/kyra/saveload_v3.cpp index 09d7d244e0..67868e3f22 100644 --- a/engines/kyra/saveload_v3.cpp +++ b/engines/kyra/saveload_v3.cpp @@ -46,8 +46,8 @@ void KyraEngine_v3::saveGame(const char *fileName, const char *saveName) { out->writeUint32BE(sizeof(_flagsTable)); out->write(_flagsTable, sizeof(_flagsTable)); - out->writeSint16BE(_curMusicTrack); - out->writeByte(_curChapter); + out->writeSint16BE(_lastMusicCommand); + out->writeByte(_currentChapter); out->writeByte(_malcolmShapes); //XXX out->writeSint16BE(_score); @@ -141,7 +141,7 @@ void KyraEngine_v3::loadGame(const char *fileName) { _deathHandler = -1; if (!_unkSceneScreenFlag1) - _curMusicTrack = -1; + _lastMusicCommand = -1; int curShapes = _malcolmShapes; @@ -156,8 +156,8 @@ void KyraEngine_v3::loadGame(const char *fileName) { in.read(_flagsTable, flagsSize); // usually we have to save the flag set by opcode 10 here - _curMusicTrack = in.readSint16(); - _curChapter = in.readByte(); + _lastMusicCommand = in.readSint16(); + _currentChapter = in.readByte(); _malcolmShapes = in.readByte(); //XXX _score = in.readSint16(); @@ -241,9 +241,9 @@ void KyraEngine_v3::loadGame(const char *fileName) { enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1); setHandItem(_itemInHand); - if (_curMusicTrack >= 0 && !_unkSceneScreenFlag1) - playMusicTrack(_curMusicTrack, 1); - else if (_curMusicTrack == -1) + if (_lastMusicCommand >= 0 && !_unkSceneScreenFlag1) + playMusicTrack(_lastMusicCommand, 1); + else if (_lastMusicCommand == -1) playMusicTrack(28, 1); while (!_screen->isMouseVisible()) diff --git a/engines/kyra/scene_v3.cpp b/engines/kyra/scene_v3.cpp index 3485e95d1c..46e1ca5206 100644 --- a/engines/kyra/scene_v3.cpp +++ b/engines/kyra/scene_v3.cpp @@ -42,8 +42,8 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 } musicUpdate(0); - if (_curChapter != _currentTalkFile) { - _currentTalkFile = _curChapter; + if (_currentChapter != _currentTalkFile) { + _currentTalkFile = _currentChapter; openTalkFile(_currentTalkFile); } musicUpdate(0); @@ -82,7 +82,7 @@ void KyraEngine_v3::enterNewScene(uint16 sceneId, int facing, int unk1, int unk2 musicUpdate(0); uint32 waitUntilTimer = 0; bool newSoundFile = false; - if (_curMusicTrack != _sceneList[sceneId].sound) { + if (_lastMusicCommand != _sceneList[sceneId].sound) { fadeOutMusic(60); waitUntilTimer = _system->getMillis() + 60 * _tickLength; newSoundFile = true; diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index f620750891..2eb141310a 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -538,7 +538,7 @@ int KyraEngine_v3::o3_checkInRect(ScriptState *script) { int KyraEngine_v3::o3_updateConversations(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_updateConversations(%p) (%d)", (const void *)script, stackPos(0)); int dlgIndex = stackPos(0); - switch (_curChapter-2) { + switch (_currentChapter-2) { case 0: dlgIndex -= 34; break; @@ -562,7 +562,7 @@ int KyraEngine_v3::o3_updateConversations(ScriptState *script) { int convs[4]; Common::set_to(convs, convs+4, -1); - if (_curChapter == 1) { + if (_currentChapter == 1) { switch (_mainCharacter.dlgIndex) { case 0: convs[0] = 6; @@ -642,7 +642,7 @@ int KyraEngine_v3::o3_updateConversations(ScriptState *script) { default: break; } - } else if (_curChapter == 2) { + } else if (_currentChapter == 2) { switch (_mainCharacter.dlgIndex) { case 0: convs[0] = 4; @@ -718,7 +718,7 @@ int KyraEngine_v3::o3_updateConversations(ScriptState *script) { default: break; } - } else if (_curChapter == 4) { + } else if (_currentChapter == 4) { if (_malcolmsMood == 0) { convs[0] = _mainCharacter.dlgIndex - 10; convs[1] = _mainCharacter.dlgIndex - 5; diff --git a/engines/kyra/sequences_v3.cpp b/engines/kyra/sequences_v3.cpp index 16fd991022..972b6a027e 100644 --- a/engines/kyra/sequences_v3.cpp +++ b/engines/kyra/sequences_v3.cpp @@ -34,13 +34,13 @@ void KyraEngine_v3::showBadConscience() { _badConscienceShown = true; _badConscienceAnim = _rnd.getRandomNumberRng(0, 2); - if (_curChapter == 2) + if (_currentChapter == 2) _badConscienceAnim = 5; - else if (_curChapter == 3) + else if (_currentChapter == 3) _badConscienceAnim = 3; - else if (_curChapter == 4 && _rnd.getRandomNumberRng(1, 100) <= 25) + else if (_currentChapter == 4 && _rnd.getRandomNumberRng(1, 100) <= 25) _badConscienceAnim = 6; - else if (_curChapter == 5 && _rnd.getRandomNumberRng(1, 100) <= 25) + else if (_currentChapter == 5 && _rnd.getRandomNumberRng(1, 100) <= 25) _badConscienceAnim = 7; else if (_malcolmShapes == 9) _badConscienceAnim = 4; diff --git a/engines/kyra/text_v3.cpp b/engines/kyra/text_v3.cpp index 834903b18f..2aa05a6359 100644 --- a/engines/kyra/text_v3.cpp +++ b/engines/kyra/text_v3.cpp @@ -444,7 +444,7 @@ void KyraEngine_v3::malcolmSceneStartupChat() { if (_noStartupChat) return; - int index = _mainCharacter.sceneId - _chapterLowestScene[_curChapter]; + int index = _mainCharacter.sceneId - _chapterLowestScene[_currentChapter]; if (_newSceneDlgState[index]) return; @@ -471,12 +471,12 @@ void KyraEngine_v3::updateDlgBuffer() { if (_cnvFile) _cnvFile->seek(0, SEEK_SET); - if (_curDlgIndex == _mainCharacter.dlgIndex && _curDlgChapter == _curChapter && _curDlgLang == _lang) + if (_curDlgIndex == _mainCharacter.dlgIndex && _curDlgChapter == _currentChapter && _curDlgLang == _lang) return; - snprintf(dlgFile, 16, "CH%.02d-S%.02d.", _curChapter, _mainCharacter.dlgIndex); + snprintf(dlgFile, 16, "CH%.02d-S%.02d.", _currentChapter, _mainCharacter.dlgIndex); appendLanguage(dlgFile, _lang, 16); - snprintf(cnvFile, 16, "CH%.02d-S%.02d.CNV", _curChapter, _mainCharacter.dlgIndex); + snprintf(cnvFile, 16, "CH%.02d-S%.02d.CNV", _currentChapter, _mainCharacter.dlgIndex); delete _cnvFile; delete _dlgBuffer; @@ -512,7 +512,7 @@ void KyraEngine_v3::updateDlgIndex() { debugC(9, kDebugLevelMain, "KyraEngine_v3::updateDlgIndex()"); uint16 dlgIndex = _mainCharacter.dlgIndex; - if (_curChapter == 1) { + if (_currentChapter == 1) { static const uint8 dlgIndexMoodNice[] = { 0x0C, 0x0E, 0x10, 0x0F, 0x11 }; static const uint8 dlgIndexMoodNormal[] = { 0x00, 0x02, 0x04, 0x03, 0x05 }; static const uint8 dlgIndexMoodEvil[] = { 0x06, 0x08, 0x0A, 0x09, 0x0B }; @@ -523,7 +523,7 @@ void KyraEngine_v3::updateDlgIndex() { dlgIndex = dlgIndexMoodNormal[_malcolmShapes]; else if (_malcolmsMood == 2) dlgIndex = dlgIndexMoodEvil[_malcolmShapes]; - } else if (_curChapter == 2) { + } else if (_currentChapter == 2) { if (dlgIndex >= 8) dlgIndex -= 4; if (dlgIndex >= 4) @@ -533,7 +533,7 @@ void KyraEngine_v3::updateDlgIndex() { dlgIndex += 8; else if (_malcolmsMood == 2) dlgIndex += 4; - } else if (_curChapter == 4) { + } else if (_currentChapter == 4) { if (dlgIndex >= 10) dlgIndex -= 5; if (dlgIndex >= 5) @@ -692,7 +692,7 @@ void KyraEngine_v3::malcolmRandomChat() { debugC(9, kDebugLevelMain, "KyraEngine_v3::malcolmRandomChat()"); updateDlgBuffer(); - int index = (_mainCharacter.sceneId - _chapterLowestScene[_curChapter]) * 2; + int index = (_mainCharacter.sceneId - _chapterLowestScene[_currentChapter]) * 2; int vocHighBase = 0, vocHighIndex = 0, index1 = 0, index2 = 0; loadDlgHeader(vocHighBase, vocHighIndex, index1, index2); @@ -711,7 +711,7 @@ void KyraEngine_v3::malcolmRandomChat() { void KyraEngine_v3::runDialog(int dlgIndex, int funcNum) { debugC(9, kDebugLevelMain, "KyraEngine_v3::runDialog(%d, %d)", dlgIndex, funcNum); - switch (_curChapter-2) { + switch (_currentChapter-2) { case 0: dlgIndex -= 34; break; -- cgit v1.2.3 From 1d167da633a7dd666bb946156dd9e0ec29be2b53 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 27 Apr 2008 00:50:13 +0000 Subject: - Implemented opcodes -> 57: o3_makeSecondChanceSave -> 98: o3_setDeathHandler - Made game automatically reload second chance save on death for now svn-id: r31749 --- engines/kyra/kyra_v3.cpp | 5 ++++- engines/kyra/kyra_v3.h | 2 ++ engines/kyra/script_v3.cpp | 16 ++++++++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp index c08d75fb24..017594b459 100644 --- a/engines/kyra/kyra_v3.cpp +++ b/engines/kyra/kyra_v3.cpp @@ -999,7 +999,10 @@ void KyraEngine_v3::runLoop() { _runFlag = true; while (_runFlag && !_quitFlag) { - //XXX deathHandler + if (_deathHandler >= 0) { + // TODO: add menu etc. + loadGame(getSavegameFilename(999)); + } if (_system->getMillis() >= _nextIdleAnim) showIdleAnim(); diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h index cdbdc11998..cc7fab388a 100644 --- a/engines/kyra/kyra_v3.h +++ b/engines/kyra/kyra_v3.h @@ -735,6 +735,7 @@ private: int o3_setMalcolmsMood(ScriptState *script); int o3_delay(ScriptState *script); int o3_updateScore(ScriptState *script); + int o3_makeSecondChanceSave(ScriptState *script); int o3_setSceneFilename(ScriptState *script); int o3_removeItemsFromScene(ScriptState *script); int o3_disguiseMalcolm(ScriptState *script); @@ -758,6 +759,7 @@ private: int o3_blockOutRegion(ScriptState *script); int o3_showSceneStringsMessage(ScriptState *script); int o3_getRand(ScriptState *script); + int o3_setDeathHandler(ScriptState *script); int o3_waitForConfirmationClick(ScriptState *script); int o3_defineRoomEntrance(ScriptState *script); int o3_runTemporaryScript(ScriptState *script); diff --git a/engines/kyra/script_v3.cpp b/engines/kyra/script_v3.cpp index 2eb141310a..574c105481 100644 --- a/engines/kyra/script_v3.cpp +++ b/engines/kyra/script_v3.cpp @@ -442,6 +442,12 @@ int KyraEngine_v3::o3_updateScore(ScriptState *script) { return updateScore(stackPos(0), stackPos(1)) ? 1 : 0; } +int KyraEngine_v3::o3_makeSecondChanceSave(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_makeSecondChanceSave(%p) ()", (const void *)script); + saveGame(getSavegameFilename(999), "SECOND CHANCE SAVE GAME"); + return 0; +} + int KyraEngine_v3::o3_setSceneFilename(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setSceneFilename(%p) (%d, '%s')", (const void *)script, stackPos(0), stackPosString(1)); strcpy(_sceneList[stackPos(0)].filename1, stackPosString(1)); @@ -919,6 +925,12 @@ int KyraEngine_v3::o3_getRand(ScriptState *script) { return _rnd.getRandomNumberRng(stackPos(0), stackPos(1)); } +int KyraEngine_v3::o3_setDeathHandler(ScriptState *script) { + debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setDeathHandler(%p) (%d)", (const void *)script, stackPos(0)); + _deathHandler = stackPos(0); + return 0; +} + int KyraEngine_v3::o3_waitForConfirmationClick(ScriptState *script) { debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o2_waitForConfirmationClick(%p) (%d)", (const void *)script, stackPos(0)); resetSkipFlag(); @@ -1417,7 +1429,7 @@ void KyraEngine_v3::setupOpcodeTable() { Opcode(o3_delay); // 0x38 Opcode(o3_updateScore); - OpcodeUnImpl(); + Opcode(o3_makeSecondChanceSave); Opcode(o3_setSceneFilename); OpcodeUnImpl(); // 0x3c @@ -1468,7 +1480,7 @@ void KyraEngine_v3::setupOpcodeTable() { // 0x60 Opcode(o3_getRand); Opcode(o3_dummy); - OpcodeUnImpl(); + Opcode(o3_setDeathHandler); OpcodeUnImpl(); // 0x64 OpcodeUnImpl(); -- cgit v1.2.3 From ab1a3b0cc89686fa2e9ef864a429ae27ed7b2d2f Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Sun, 27 Apr 2008 03:19:19 +0000 Subject: Implemented support for VMDs substituting object animations. Still far from being complete (and correct), but it's a start... - Only VMD "command" -3 is followed - Not all animation types are working - Timing is still off in most cases - Offsets are generally OK, but not always - No sound yet - Shouldn't segfault randomly, but I'm not entirely sure ;) svn-id: r31750 --- engines/gob/coktelvideo.cpp | 85 ++++-- engines/gob/coktelvideo.h | 28 +- engines/gob/game_v2.cpp | 2 +- engines/gob/goblin.h | 14 + engines/gob/goblin_v2.cpp | 2 +- engines/gob/goblin_v4.cpp | 635 +++++++++++++++++++++++++++++++++++++++++++ engines/gob/init.cpp | 6 +- engines/gob/inter_bargon.cpp | 48 ++-- engines/gob/inter_v2.cpp | 29 +- engines/gob/inter_v4.cpp | 33 ++- engines/gob/module.mk | 1 + engines/gob/mult.h | 3 +- engines/gob/mult_v2.cpp | 67 ++++- engines/gob/scenery.cpp | 153 ++++++++++- engines/gob/scenery.h | 1 + engines/gob/util.cpp | 4 +- engines/gob/videoplayer.cpp | 366 +++++++++++++++++++------ engines/gob/videoplayer.h | 67 ++++- 18 files changed, 1351 insertions(+), 193 deletions(-) create mode 100644 engines/gob/goblin_v4.cpp diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp index c6286fba3b..d508dc75f9 100644 --- a/engines/gob/coktelvideo.cpp +++ b/engines/gob/coktelvideo.cpp @@ -333,41 +333,44 @@ void Imd::waitEndFrame() { g_system->delayMillis(_frameLength); } -void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp) { +void Imd::copyCurrentFrame(byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp) { + if (!_vidMem) return; - dest += width * y; + if (((left + width) > _width) || ((top + height) > _height)) + return; - uint16 copyWidth = MIN(width - x, _width); - uint16 destPitch = width - x; - byte *vidMem = _vidMem; + dest += pitch * y; + byte *vidMem = _vidMem + _width * top; if (transp < 0) { // No transparency - if ((x > 0) || (_width != width)) { + if ((x > 0) || (left > 0) || (pitch != _width) || (width != _width)) { // Copy row-by-row - for (int i = 0; i < _height; i++) { - dest += x; - memcpy(dest, vidMem, copyWidth); - dest += destPitch; + for (int i = 0; i < height; i++) { + byte *d = dest + x; + byte *s = vidMem + left; + + memcpy(d, s, width); + + dest += pitch; vidMem += _width; } - } else // Dimensions fit, copy everything at once - memcpy(dest, _vidMem, _width * _height); + memcpy(dest, vidMem, width * height); return; } - // Transparency, copy per pixel - for (int i = 0; i < _height; i++) { - byte *s = vidMem; - byte *d = dest; + for (int i = 0; i < height; i++) { + byte *d = dest + x; + byte *s = vidMem + left; - d += x; - for (int j = 0; j < _width; j++) { + for (int j = 0; j < width; j++) { if (*s != transp) *d = *s; @@ -375,9 +378,10 @@ void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 t d++; } - dest += width; + dest += pitch; vidMem += _width; } + } void Imd::deleteVidMem(bool del) { @@ -938,9 +942,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) { } else _frameLength = 1000 / _frameRate; - uint32 frameInfoOffset = _stream->readUint32LE(); + _frameInfoOffset = _stream->readUint32LE(); - _stream->seek(frameInfoOffset); + _stream->seek(_frameInfoOffset); _frames = new Frame[_framesCount]; for (uint16 i = 0; i < _framesCount; i++) { _frames[i].parts = new Part[_partsPerFrame]; @@ -1350,4 +1354,43 @@ void Vmd::deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) { } } +bool Vmd::getAnchor(int16 frame, uint16 partType, + int16 &x, int16 &y, int16 &width, int16 &height) { + + uint32 pos = _stream->pos(); + + _stream->seek(_frameInfoOffset); + // Offsets to frames + _stream->skip(_framesCount * 6); + // Jump to the specified frame + _stream->skip(_partsPerFrame * frame * 16); + + // Find the anchor part + uint16 i; + for (i = 0; i < _partsPerFrame; i++) { + byte type = _stream->readByte(); + + if ((type == 0) || (type == partType)) + break; + + _stream->skip(15); + } + + if (i == _partsPerFrame) { + // No anchor + + _stream->seek(pos); + return false; + } + + _stream->skip(5); + x = _stream->readSint16LE(); + y = _stream->readSint16LE(); + width = _stream->readSint16LE() - x + 1; + height = _stream->readSint16LE() - y + 1; + + _stream->seek(pos); + return true; +} + } // End of namespace Gob diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h index 84271073f6..4f9543e8d0 100644 --- a/engines/gob/coktelvideo.h +++ b/engines/gob/coktelvideo.h @@ -90,6 +90,8 @@ public: /** Returns the features the loaded video possesses. */ virtual uint16 getFeatures() const = 0; + /** Returns the flags the loaded video possesses. */ + virtual uint16 getFlags() const = 0; /** Returns the x coordinate of the video. */ virtual int16 getX() const = 0; /** Returns the y coordinate of the video. */ @@ -113,6 +115,10 @@ public: /** Returns the current frame's palette. */ virtual const byte *getPalette() const = 0; + /** Reads the video's anchor pointer */ + virtual bool getAnchor(int16 frame, uint16 partType, + int16 &x, int16 &y, int16 &width, int16 &height) = 0; + /** Load a video out of a stream. */ virtual bool load(Common::SeekableReadStream &stream) = 0; /** Unload the currently loaded video. */ @@ -148,13 +154,19 @@ public: /** Copy the current frame. * - * @param dest The memory to which to copy the current frame + * @param dest The memory to which to copy the current frame. + * @param left The x position within the frame. + * @param top The y position within the frame. + * @param width The width of the area to copy. + * @param height The height of the area to copy. * @param x The x position to where to copy. * @param y The y position to where to copy. * @param pitch The buffer's width. * @param transp Which color should be seen as transparent? */ - virtual void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1) = 0; + virtual void copyCurrentFrame(byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp = -1) = 0; }; /** Coktel Vision's IMD files. @@ -165,6 +177,7 @@ public: ~Imd(); uint16 getFeatures() const { return _features; } + uint16 getFlags() const { return _flags; } int16 getX() const { return _x; } int16 getY() const { return _y; } int16 getWidth() const { return _width; } @@ -175,6 +188,9 @@ public: uint32 getSyncLag() const { return _skipFrames; } const byte *getPalette() const { return _palette; } + bool getAnchor(int16 frame, uint16 partType, + int16 &x, int16 &y, int16 &width, int16 &height) { return false; } + void setFrameRate(int16 frameRate); bool load(Common::SeekableReadStream &stream); @@ -192,7 +208,9 @@ public: State nextFrame(); void waitEndFrame(); - void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1); + void copyCurrentFrame(byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp = -1); protected: struct Coord { @@ -260,6 +278,9 @@ public: Vmd(); ~Vmd(); + bool getAnchor(int16 frame, uint16 partType, + int16 &x, int16 &y, int16 &width, int16 &height); + bool load(Common::SeekableReadStream &stream); void unload(); @@ -295,6 +316,7 @@ protected: bool _hasVideo; + uint32 _frameInfoOffset; uint16 _partsPerFrame; Frame *_frames; diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index c69db45f15..45542541e3 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -272,7 +272,7 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_snd->freeSample(_soundSamples[i]); } - _vm->_vidPlayer->closeVideo(); + _vm->_vidPlayer->primaryClose(); if (_totToLoad[0] == 0) break; diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index 0da4b5ace5..f7ac4aa549 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -315,6 +315,20 @@ protected: virtual void advMovement(Mult::Mult_Object *obj, int8 state); }; +class Goblin_v4 : public Goblin_v3 { +public: + virtual void movePathFind(Mult::Mult_Object *obj, + Gob_Object *gobDesc, int16 nextAct); + virtual void moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, + int16 nextAct, int16 framesCount); + + Goblin_v4(GobEngine *vm); + virtual ~Goblin_v4() {} + +private: + int16 sub_20430(int16 state, uint16 dir); +}; + } // End of namespace Gob #endif // GOB_GOBLIN_H diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index c9e155ad08..8af4015c1b 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -266,7 +266,7 @@ void Goblin_v2::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 if (_vm->_map->_screenWidth == 640) { if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) animData->nextState = 41; - if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY) != 10) animData->nextState = 7; } break; diff --git a/engines/gob/goblin_v4.cpp b/engines/gob/goblin_v4.cpp new file mode 100644 index 0000000000..0defd32289 --- /dev/null +++ b/engines/gob/goblin_v4.cpp @@ -0,0 +1,635 @@ +/* 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 "gob/gob.h" +#include "gob/goblin.h" +#include "gob/global.h" +#include "gob/mult.h" +#include "gob/map.h" +#include "gob/scenery.h" + +namespace Gob { + +Goblin_v4::Goblin_v4(GobEngine *vm) : Goblin_v3(vm) { +} + +void Goblin_v4::movePathFind(Mult::Mult_Object *obj, Gob_Object *gobDesc, int16 nextAct) { + Mult::Mult_AnimData *animData; + int16 framesCount; + int16 gobX; + int16 gobY; + int16 gobDestX; + int16 gobDestY; + int16 destX; + int16 destY; + int16 dir; + + dir = 0; + animData = obj->pAnimData; + framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount; + animData->newCycle = framesCount; + gobX = obj->goblinX; + gobY = obj->goblinY; + animData->order = gobY; + gobDestX = obj->gobDestX; + gobDestY = obj->gobDestY; + animData->destX = gobDestX; + animData->destY = gobDestY; + destX = obj->destX; + destY = obj->destY; + + if (animData->pathExistence == 1) { + dir = _vm->_map->getDirection(gobX, gobY, destX, destY); + if (dir == 0) + animData->pathExistence = 0; + if ((gobX == destX) && (gobY == destY)) + animData->pathExistence = 4; + } else if (animData->pathExistence == 3) { + if ((gobX == gobDestX) && (gobY == gobDestY)) { + animData->pathExistence = 4; + destX = gobDestX; + destY = gobDestY; + } else { + if (_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) != 1) { + if ((gobX == destX) && (gobY == destY)) { + if (obj->nearestWayPoint > obj->nearestDest) { + _vm->_map->optimizePoints(obj, gobX, gobY); + destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; + destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { + WRITE_VAR(56, 1); + animData->pathExistence = 0; + } + if (obj->nearestWayPoint > obj->nearestDest) + obj->nearestWayPoint--; + } else if (obj->nearestWayPoint < obj->nearestDest) { + _vm->_map->optimizePoints(obj, gobX, gobY); + destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; + destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + if (_vm->_map->checkDirectPath(obj, gobX, gobY, destX, destY) == 3) { + WRITE_VAR(56, 1); + animData->pathExistence = 0; + } + if (obj->nearestWayPoint < obj->nearestDest) + obj->nearestWayPoint++; + } else { + if ((_vm->_map->checkDirectPath(obj, gobX, gobY, gobDestX, gobDestY) == 3) && + (_vm->_map->getPass(gobDestX, gobDestY) != 0)) { + destX = _vm->_map->_wayPoints[obj->nearestWayPoint].x; + destY = _vm->_map->_wayPoints[obj->nearestWayPoint].y; + WRITE_VAR(56, 1); + } else { + animData->pathExistence = 1; + destX = gobDestX; + destY = gobDestY; + } + } + } + } else { + destX = gobDestX; + destY = gobDestY; + } + dir = _vm->_map->getDirection(gobX, gobY, destX, destY); + } + } + + obj->goblinX = gobX; + obj->goblinY = gobY; + obj->gobDestX = gobDestX; + obj->gobDestY = gobDestY; + obj->destX = destX; + obj->destY = destY; + + if (_vm->_map->_widthByte == 4) { + switch (dir) { + case Map::kDirNW: + animData->nextState = sub_20430(animData->state, Map::kDirNW); + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && + (animData->nextState == 1)) + animData->nextState = 40; + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) + animData->nextState = sub_20430(animData->state, Map::kDirNW); + break; + + case Map::kDirN: + animData->nextState = + (animData->curLookDir == 2) ? 2 : sub_20430(animData->state, Map::kDirN); + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) { + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) + animData->nextState = 42; + else + animData->nextState = 2; + } else + animData->nextState = 40; + } + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) && + (animData->nextState == 2)) + animData->nextState = 38; + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) && + (animData->nextState == 2)) + animData->nextState = 26; + break; + + case Map::kDirNE: + animData->nextState = sub_20430(animData->state, Map::kDirNE); + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && + (animData->nextState == 3)) + animData->nextState = 42; + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10) + animData->nextState = sub_20430(animData->state, Map::kDirNE); + break; + + case Map::kDirW: + animData->nextState = sub_20430(animData->state, Map::kDirW); + break; + + case Map::kDirE: + animData->nextState = sub_20430(animData->state, Map::kDirE); + break; + + case Map::kDirSW: + animData->nextState = sub_20430(animData->state, Map::kDirSW); + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && + (animData->nextState == 7)) + animData->nextState = 41; + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY) != 10) + animData->nextState = sub_20430(animData->state, Map::kDirSW); + break; + + case Map::kDirS: + animData->nextState = + (animData->curLookDir == 6) ? 6 : sub_20430(animData->state, Map::kDirS); + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) { + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) == 10) + animData->nextState = 43; + else + animData->nextState = 6; + } else + animData->nextState = 41; + } + // loc_20AAD + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) && + (animData->nextState == 6)) + animData->nextState = 39; + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) && + (animData->nextState == 6)) + animData->nextState = 27; + break; + + case Map::kDirSE: + animData->nextState = sub_20430(animData->state, Map::kDirSE); + if ((_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) && + (animData->nextState == 5)) + animData->nextState = 43; + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY) != 10) + animData->nextState = sub_20430(animData->state, Map::kDirSE); + break; + + default: + // loc_20D18 + switch (animData->state) { + case 0: + case 8: + // loc_21134 + animData->nextState = 8; + break; + + case 1: + case 10: + case 40: + // loc_21152 + animData->nextState = 10; + break; + + case 2: + case 29: + // loc_2113E + animData->nextState = 29; + break; + + case 3: + case 11: + case 42: + // loc_2115C + animData->nextState = 11; + break; + + case 4: + case 9: + // loc_2112A + animData->nextState = 9; + break; + + case 5: + case 30: + case 43: + // loc_21166 + animData->nextState = 30; + break; + + case 6: + case 28: + // loc_21148 + animData->nextState = 28; + break; + + case 7: + case 31: + case 41: + // loc_21170 + animData->nextState = 31; + break; + } + break; + } + } else { + switch (dir) { + case Map::kDirNW: + animData->nextState = 1; + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) + animData->nextState = 40; + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) + animData->nextState = 1; + } + break; + + case Map::kDirN: + animData->nextState = + (animData->curLookDir == 2) ? 2 : rotateState(animData->curLookDir, 2); + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) { + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY - 2) != 10) { + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) == 10) + animData->nextState = 42; + else + animData->nextState = 2; + } else + animData->nextState = 40; + } else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) + animData->nextState = 38; + else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) + animData->nextState = 26; + } + break; + + case Map::kDirNE: + animData->nextState = 3; + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) + animData->nextState = 42; + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY - 2) != 10) + animData->nextState = 3; + } + break; + + case Map::kDirW: + animData->nextState = rotateState(animData->curLookDir, 0); + break; + + case Map::kDirE: + animData->nextState = rotateState(animData->curLookDir, 4); + break; + + case Map::kDirSW: + animData->nextState = 7; + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) + animData->nextState = 41; + if (_vm->_map->getPass(obj->goblinX - 1, obj->goblinY + 2) != 10) + animData->nextState = 7; + } + break; + + case Map::kDirS: + animData->nextState = + (animData->curLookDir == 6) ? 6 : rotateState(animData->curLookDir, 6); + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 20) + animData->nextState = 39; + else if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 19) + animData->nextState = 27; + } + break; + + case Map::kDirSE: + animData->nextState = 5; + if (_vm->_map->_screenWidth == 640) { + if (_vm->_map->getPass(obj->goblinX, obj->goblinY) == 10) + animData->nextState = 43; + if (_vm->_map->getPass(obj->goblinX + 1, obj->goblinY + 2) != 10) + animData->nextState = 5; + } + break; + + default: + switch (animData->curLookDir) { + case 0: + animData->nextState = 8; + break; + case 1: + animData->nextState = 10; + break; + case 2: + animData->nextState = 29; + break; + case 3: + animData->nextState = 11; + break; + case 4: + animData->nextState = 9; + break; + case 5: + animData->nextState = 30; + break; + case 6: + animData->nextState = 28; + break; + case 7: + animData->nextState = 31; + break; + } + break; + } + } +} + +void Goblin_v4::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, + int16 nextAct, int16 framesCount) { + Mult::Mult_AnimData *animData; + int16 gobX; + int16 gobY; + int16 animation; + int16 state; + int16 layer; + + if (!obj->goblinStates) + return; + + movePathFind(obj, 0, 0); + playSounds(obj); + + animData = obj->pAnimData; + + framesCount = _vm->_scenery->getAnimLayer(animData->animation, animData->layer)->framesCount; + + if (animData->isPaused == 0) + animData->frame++; + + switch (animData->stateType) { + case 0: + case 1: + animData->isPaused = 0; + break; + + case 4: + if (animData->frame == 0) + animData->isPaused = 1; + break; + + case 6: + if (animData->frame >= framesCount) + animData->isPaused = 1; + break; + } + + switch (animData->state) { + case 0: + case 1: + case 7: + case 13: + case 16: + case 23: + animData->curLookDir = 0; + break; + + case 2: + case 15: + case 18: + case 21: + animData->curLookDir = 2; + break; + + case 3: + case 4: + case 5: + case 12: + case 19: + case 22: + animData->curLookDir = 4; + break; + + case 6: + case 14: + case 17: + case 20: + animData->curLookDir = 6; + break; + + case 8: + case 9: + case 28: + case 29: + if (animData->pathExistence == 4) + animData->pathExistence = 5; + break; + } + + if ((animData->newState != -1) && (animData->frame == framesCount) && + (animData->newState != animData->state)) { + animData->nextState = animData->newState; + animData->newState = -1; + animData->state = animData->nextState; + + Scenery::AnimLayer *animLayer = + _vm->_scenery->getAnimLayer(animData->animation, animData->layer); + *obj->pPosX += animLayer->animDeltaX; + *obj->pPosY += animLayer->animDeltaY; + + animation = obj->goblinStates[animData->nextState][0].animation; + layer = obj->goblinStates[animData->nextState][0].layer; + animData->layer = layer; + animData->animation = animation; + animData->frame = 0; + } else { + if (isMovement(animData->state)) { + state = animData->nextState; + if (animData->frame == ((framesCount + 1) / 2)) { + gobX = obj->goblinX; + gobY = obj->goblinY; + + advMovement(obj, state); + + if (animData->state != state) { + animation = obj->goblinStates[state][0].animation; + layer = obj->goblinStates[state][0].layer; + animData->layer = layer; + animData->animation = animation; + animData->frame = 0; + animData->state = state; + _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); + if (_vm->_map->_bigTiles) + *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; + else + *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + *obj->pPosX = gobX * _vm->_map->_tilesWidth; + } + } + } + + if (animData->frame >= framesCount) { + state = animData->nextState; + animation = obj->goblinStates[state][0].animation; + layer = obj->goblinStates[state][0].layer; + animData->layer = layer; + animData->animation = animation; + animData->frame = 0; + animData->state = state; + gobX = obj->goblinX; + gobY = obj->goblinY; + + advMovement(obj, state); + + _vm->_scenery->updateAnim(layer, 0, animation, 0, *obj->pPosX, *obj->pPosY, 0); + if (_vm->_map->_bigTiles) + *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop) - (gobY + 1) / 2; + else + *obj->pPosY = ((gobY + 1) * _vm->_map->_tilesHeight) - + (_vm->_scenery->_animBottom - _vm->_scenery->_animTop); + *obj->pPosX = gobX * _vm->_map->_tilesWidth; + } + } +} + +int16 Goblin_v4::sub_20430(int16 state, uint16 dir) { + static const int16 word_3F25E[8][8] = { + {0, 1, 10, 10, 10, 31, 31, 7}, + {0, 1, 2, 29, 29, 29, 8, 8}, + {10, 1, 2, 3, 11, 11, 11, 10}, + {29, 29, 2, 3, 4, 9, 9, 9}, + {30, 11, 11, 3, 4, 5, 30, 30}, + {28, 28, 9, 9, 4, 5, 6, 28}, + {31, 31, 31, 30, 30, 5, 6, 7}, + {0, 8, 8, 8, 28, 28, 6, 7} + }; + int16 dx = state, cx = 0; + + switch (state) { + case 0: + case 8: + // loc_20447 + dx = 0; + break; + + case 1: + case 10: + case 40: + // loc_2044B + dx = 1; + break; + + case 3: + case 11: + case 42: + // loc_20455 + dx = 3; + break; + + case 5: + case 30: + case 43: + // loc_2045F + dx = 5; + break; + + case 7: + case 31: + case 41: + // loc_20469 + dx = 7; + break; + + case 9: + // loc_2045A + dx = 4; + break; + + case 28: + // loc_20464 + dx = 6; + break; + + case 29: + // loc_20450 + dx = 2; + break; + } + + // loc_2046C + + + switch (dir) { + case Map::kDirNW: + cx = 1; + break; + + case Map::kDirN: + cx = 2; + break; + + case Map::kDirNE: + cx = 3; + break; + + case Map::kDirW: + cx = 0; + break; + + case Map::kDirE: + cx = 4; + break; + + case Map::kDirSW: + cx = 7; + break; + + case Map::kDirS: + cx = 6; + break; + + case Map::kDirSE: + cx = 5; + break; + } + + return word_3F25E[dx][cx]; +} + +} // End of namespace Gob diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index f38d5ac115..4d184c53d3 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -181,9 +181,9 @@ void Init::initGame(const char *totName) { _vm->_util->longDelay(200); // Letting everything settle - if (_vm->_vidPlayer->openVideo("coktel.imd")) { - _vm->_vidPlayer->play(); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("coktel.imd")) { + _vm->_vidPlayer->primaryPlay(); + _vm->_vidPlayer->primaryClose(); } _vm->_draw->closeScreen(); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 0de8245dea..702950d539 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -717,16 +717,16 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) { } void Inter_Bargon::oBargon_intro0(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) { - _vm->_vidPlayer->play(0, 92, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) { + _vm->_vidPlayer->primaryPlay(0, 92, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro1(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true, 23); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scaa", 0, 160)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true, 23); + _vm->_vidPlayer->primaryClose(); } } @@ -819,44 +819,44 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { } void Inter_Bargon::oBargon_intro4(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scba", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scba", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0, 0, 0, true); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro5(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scbb", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scbb", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro6(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro7(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scbf", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scbf", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro8(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scbc", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } void Inter_Bargon::oBargon_intro9(OpGobParams ¶ms) { - if (_vm->_vidPlayer->openVideo("scbd", 191, 54)) { - _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0); - _vm->_vidPlayer->closeVideo(); + if (_vm->_vidPlayer->primaryOpen("scbd", 191, 54)) { + _vm->_vidPlayer->primaryPlay(0, -1, 27, 0, 0, 0); + _vm->_vidPlayer->primaryClose(); } } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 46d40d1553..9b474a08d6 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -988,12 +988,10 @@ void Inter_v2::o2_loadMultObject() { _vm->_global->_inter_execPtr++; } - if (_vm->_goblin->_gobsCount <= objIndex) - return; - Mult::Mult_Object &obj = _vm->_mult->_objects[objIndex]; Mult::Mult_AnimData &objAnim = *(obj.pAnimData); - if (objAnim.animType == 100) { + + if ((objAnim.animType == 100) && (objIndex < _vm->_goblin->_gobsCount)) { val = *(obj.pPosX) % 256; obj.destX = val; @@ -1029,7 +1027,7 @@ void Inter_v2::o2_loadMultObject() { ((obj.goblinY + 1) / 2); *(obj.pPosX) = obj.goblinX * _vm->_map->_tilesWidth; - } else if (objAnim.animType == 101) { + } else if ((objAnim.animType == 101) && (objIndex < _vm->_goblin->_gobsCount)) { layer = objAnim.layer; animation = obj.goblinStates[layer][0].animation; @@ -1048,6 +1046,21 @@ void Inter_v2::o2_loadMultObject() { } _vm->_scenery->updateAnim(layer, 0, animation, 0, *(obj.pPosX), *(obj.pPosY), 0); + + } else if ((objAnim.animType != 100) && (objAnim.animType != 101)) { + + if ((*(obj.pPosX) == -1234) && (*(obj.pPosY) == -4321)) { + + if (obj.videoSlot > 0) + _vm->_vidPlayer->slotClose(obj.videoSlot - 1); + + obj.videoSlot = 0; + obj.lastLeft = -1; + obj.lastTop = -1; + obj.lastBottom = -1; + obj.lastRight = -1; + } + } } @@ -1519,7 +1532,7 @@ void Inter_v2::o2_playImd() { palEnd = _vm->_parse->parseValExpr(); palCmd = 1 << (flags & 0x3F); - if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) { + if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) { WRITE_VAR(11, -1); return; } @@ -1532,12 +1545,12 @@ void Inter_v2::o2_playImd() { if (startFrame >= 0) { _vm->_game->_preventScroll = true; - _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0); + _vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0); _vm->_game->_preventScroll = false; } if (close) - _vm->_vidPlayer->closeVideo(); + _vm->_vidPlayer->primaryClose(); } void Inter_v2::o2_getImdInfo() { diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index d2269e5b2c..71c0f293ec 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -544,9 +544,9 @@ void Inter_v4::setupOpcodes() { static const OpcodeGoblinEntryV4 opcodesGoblin[71] = { /* 00 */ - OPCODE(o2_loadInfogramesIns), - OPCODE(o2_startInfogrames), - OPCODE(o2_stopInfogrames), + {NULL, ""}, + {NULL, ""}, + {NULL, ""}, {NULL, ""}, /* 04 */ {NULL, ""}, @@ -555,7 +555,7 @@ void Inter_v4::setupOpcodes() { {NULL, ""}, /* 08 */ {NULL, ""}, - OPCODE(o2_playInfogrames), + {NULL, ""}, {NULL, ""}, {NULL, ""}, /* 0C */ @@ -592,7 +592,7 @@ void Inter_v4::setupOpcodes() { {NULL, ""}, {NULL, ""}, {NULL, ""}, - OPCODE(o2_handleGoblins), + {NULL, ""}, /* 28 */ {NULL, ""}, {NULL, ""}, @@ -723,7 +723,6 @@ void Inter_v4::o4_playVmdOrMusic() { bool close; evalExpr(0); - _vm->_global->_inter_resStr[8] = 0; strncpy0(fileName, _vm->_global->_inter_resStr, 127); x = _vm->_parse->parseValExpr(); @@ -740,8 +739,20 @@ void Inter_v4::o4_playVmdOrMusic() { if (lastFrame == -1) { close = true; } else if (lastFrame == -3) { - warning("Woodruff Stub: Video/Music command -3: Play background video %s", fileName); -// return; + warning("Woodruff Stub: Video/Music command -3: Play background video %s, %d, %d", fileName, x, y); + + _vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1; + + if (_vm->_mult->_objects[startFrame].videoSlot > 0) + _vm->_vidPlayer->slotClose(_vm->_mult->_objects[startFrame].videoSlot - 1); + _vm->_mult->_objects[startFrame].videoSlot = _vm->_vidPlayer->slotOpen(fileName) + 1; + + if (x != -1) { + *_vm->_mult->_objects[startFrame].pPosX = x; + *_vm->_mult->_objects[startFrame].pPosY = y; + } + + return; } else if (lastFrame == -4) { warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName); return; @@ -767,19 +778,19 @@ void Inter_v4::o4_playVmdOrMusic() { close = false; } - if ((fileName[0] != 0) && !_vm->_vidPlayer->openVideo(fileName, x, y, flags)) { + if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) { WRITE_VAR(11, -1); return; } if (startFrame >= 0) { _vm->_game->_preventScroll = true; - _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0); + _vm->_vidPlayer->primaryPlay(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0); _vm->_game->_preventScroll = false; } if (close) - _vm->_vidPlayer->closeVideo(); + _vm->_vidPlayer->primaryClose(); } } // End of namespace Gob diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 8a428b4d34..734996ddd5 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -18,6 +18,7 @@ MODULE_OBJS := \ goblin_v1.o \ goblin_v2.o \ goblin_v3.o \ + goblin_v4.o \ coktelvideo.o \ videoplayer.o \ init.o \ diff --git a/engines/gob/mult.h b/engines/gob/mult.h index 90f6e61f9a..9d43435184 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -36,7 +36,7 @@ public: #include "common/pack-start.h" // START STRUCT PACKING struct Mult_AnimData { - uint8 animation; + int8 animation; uint8 layer; uint8 frame; int8 animType; @@ -104,6 +104,7 @@ public: int16 newTop; int16 newRight; int16 newBottom; + uint32 videoSlot; } PACKED_STRUCT; struct Mult_StaticKey { diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 37c360d53a..95617a704a 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -463,8 +463,7 @@ void Mult_v2::multSub(uint16 multIndex) { int obj = _multData->animObjs[index][i]; if ((obj != -1) && (obj != 1024)) - _objects[obj].pAnimData->animTypeBak = - _objects[obj].pAnimData->animType; + _objects[obj].pAnimData->animTypeBak = _objects[obj].pAnimData->animType; } } @@ -472,8 +471,10 @@ void Mult_v2::multSub(uint16 multIndex) { _multData->animKeysIndices[index][i] = 0; for (int j = 0; j < _multData->animKeysCount[i]; j++) - if (_multData->animKeys[i][j].frame == startFrame) + if (_multData->animKeys[i][j].frame >= startFrame) { _multData->animKeysIndices[index][i] = j; + break; + } } if (_multData->animDirection == -1) { @@ -487,6 +488,7 @@ void Mult_v2::multSub(uint16 multIndex) { firstFrame = (_multData->animDirection == 1) ? startFrame : stopFrame; for (int i = 0; i < 4; i++) { _multData->imdKeysIndices[index][i] = 0; + for (int j = 0; j < _multData->imdKeysCount[i]; j++) if (_multData->imdKeys[i][j].frame >= firstFrame) { _multData->imdKeysIndices[index][i] = j; @@ -675,28 +677,54 @@ void Mult_v2::drawAnims(bool &stop) { // loc_50D5 void Mult_v2::newCycleAnim(Mult_Object &animObj) { Mult_AnimData &animData = *(animObj.pAnimData); - int nAnim = animData.animation; - int nLayer = animData.layer; + Scenery::AnimLayer *animLayer = 0; - if (_vm->_scenery->getAnimLayersCount(nAnim) <= nLayer) - return; + if (animData.animation >= 0) { + int nAnim = animData.animation, nLayer = animData.layer; + + if (_vm->_scenery->getAnimLayersCount(nAnim) <= nLayer) + return; - Scenery::AnimLayer *animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer); + animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer); + } if (animData.animType == 4) { + // loc_1E091 animData.frame = 0; animData.isPaused = 1; + if (animData.animation < 0) + warning("TODO: AnimType 4, animation: %d", animData.animation); + return; + } + + if (animData.animType == 12) + animData.animType = 11; + + if (animData.animType == 11) { + if (animData.isBusy != 0) { + warning("TODO: AnimType 11"); + } return; } if (animData.animType != 8) animData.frame++; - if (animData.frame < animLayer->framesCount) { - animData.newCycle = 0; - return; + if (animData.animation < 0) { + if ((animObj.videoSlot > 0) && + (_vm->_vidPlayer->getCurrentFrame(animObj.videoSlot - 1) < + _vm->_vidPlayer->getFramesCount(animObj.videoSlot - 1))) { + animData.newCycle = 0; + return; + } + } else { + if (animData.frame < animLayer->framesCount) { + animData.newCycle = 0; + return; + } } + switch (animData.animType) { case 0: animData.frame = 0; @@ -728,6 +756,12 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) { case 7: animData.frame--; animData.isPaused = 1; + if ((animData.animation < 0) && (animObj.videoSlot > 0)) { + if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) { + _vm->_vidPlayer->slotClose(animObj.videoSlot - 1); + animObj.videoSlot = 0; + } + } break; } animData.newCycle = 1; @@ -897,6 +931,9 @@ void Mult_v2::animate() { Mult_Object &animObj1 = *_renderObjs[orderArray[i]]; Mult_AnimData &animData1 = *(animObj1.pAnimData); + if (!animObj1.goblinStates) + continue; + for (int j = i+1; j < orderArrayPos; j++) { Mult_Object &animObj2 = *_renderObjs[orderArray[j]]; Mult_AnimData &animData2 = *(animObj2.pAnimData); @@ -1043,7 +1080,7 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir, x = y = -1; if (key.imdFile == -1) { - _vm->_vidPlayer->closeVideo(); + _vm->_vidPlayer->primaryClose(); _vm->_game->_preventScroll = false; return; } @@ -1061,11 +1098,11 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir, if ((lastFrame - palFrame) < startFrame) if (!(key.flags & 0x4000)) { _vm->_game->_preventScroll = false; - _vm->_vidPlayer->closeVideo(); + _vm->_vidPlayer->primaryClose(); return; } - if (!_vm->_vidPlayer->openVideo(imdFile, x, y, flags)) { + if (!_vm->_vidPlayer->primaryOpen(imdFile, x, y, flags)) { _vm->_game->_preventScroll = false; return; } @@ -1077,7 +1114,7 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir, lastFrame = _vm->_vidPlayer->getFramesCount() - 1; baseFrame = startFrame % (lastFrame - palFrame + 1); - _vm->_vidPlayer->play(baseFrame + palFrame, baseFrame + palFrame, 0, + _vm->_vidPlayer->primaryPlay(baseFrame + palFrame, baseFrame + palFrame, 0, flags & 0x7F, palStart, palEnd, palFrame, lastFrame); } diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 5979927dfa..7338dab15b 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -33,6 +33,8 @@ #include "gob/draw.h" #include "gob/game.h" #include "gob/inter.h" +#include "gob/map.h" +#include "gob/videoplayer.h" namespace Gob { @@ -454,6 +456,7 @@ int16 Scenery::loadAnim(char search) { ptr->layers = new AnimLayer[ptr->layersCount]; ptr->pieces = new PieceDesc*[picsCount]; ptr->piecesFromExt = new bool[picsCount]; + ptr->sizes = new uint16[picsCount]; for (i = 0; i < ptr->layersCount; i++) { int16 offset = READ_LE_UINT16(dataPtr + i * 2); @@ -492,13 +495,19 @@ int16 Scenery::loadAnim(char search) { for (i = 0; i < picsCount; i++) { pictDescId = _vm->_inter->load16(); if (pictDescId >= 30000) { + uint32 size; + ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0); + (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0, &size); ptr->piecesFromExt[i] = true; + ptr->sizes[i] = size / 8; } else { + int16 size; + ptr->pieces[i] = - (PieceDesc *) _vm->_game->loadTotResource(pictDescId); + (PieceDesc *) _vm->_game->loadTotResource(pictDescId, &size); ptr->piecesFromExt[i] = false; + ptr->sizes[i] = size / 8; } width = _vm->_inter->load16(); @@ -561,6 +570,7 @@ void Scenery::freeAnim(int16 index) { delete[] _animations[index].layers; delete[] _animations[index].pieces; delete[] _animations[index].piecesFromExt; + delete[] _animations[index].sizes; _animPictCount[index] = 0; } @@ -592,6 +602,135 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, int16 destX; int16 destY; + if (animation < 0) { + // Object video + + if (flags & 1) { // Do capture + updateAnim(layer, frame, animation, 0, drawDeltaX, drawDeltaY, 0); + + if (_toRedrawLeft == -12345) + return; + + _vm->_game->capturePush(_toRedrawLeft, _toRedrawTop, + _toRedrawRight - _toRedrawLeft + 1, + _toRedrawBottom - _toRedrawTop + 1); + + *_pCaptureCounter = *_pCaptureCounter + 1; + } + + Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1]; + + if (!_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) { + _toRedrawLeft = -1234; + return; + } + + // Seek to frame + while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame) + _vm->_vidPlayer->slotPlay(obj.videoSlot - 1); + + destX = 0; + destY = 0; + left = *(obj.pPosX); + top = *(obj.pPosY); + right = left + _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - 1; + bottom = top + _vm->_vidPlayer->getHeight(obj.videoSlot - 1) - 1; + + if (flags & 2) { + if (left < _vm->_mult->_animLeft) { + destX += _vm->_mult->_animLeft - left; + left = _vm->_mult->_animLeft; + } + + if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) + right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1; + + if (top < _vm->_mult->_animTop) { + destY += _vm->_mult->_animTop - top; + top = _vm->_mult->_animTop; + } + + if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) + bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1; + + } else if (flags & 4) { + if (left < _toRedrawLeft) { + destX += _toRedrawLeft - left; + left = _toRedrawLeft; + } + + if (right > _toRedrawRight) + right = _toRedrawRight; + + if (top < _toRedrawTop) { + destY += _toRedrawTop - top; + top = _toRedrawTop; + } + + if (bottom > _toRedrawBottom) + bottom = _toRedrawBottom; + + } else { + _toRedrawTop = top; + _toRedrawLeft = left; + _toRedrawRight = right; + _toRedrawBottom = bottom; + } + + if (doDraw) { + if ((left > right) || (top > bottom)) + return; + + if (left < _vm->_mult->_animLeft) { + destX += _vm->_mult->_animLeft - left; + left = _vm->_mult->_animLeft; + } + + if ((_vm->_mult->_animLeft + _vm->_mult->_animWidth) <= right) + right = _vm->_mult->_animLeft + _vm->_mult->_animWidth - 1; + + if (top < _vm->_mult->_animTop) { + destY += _vm->_mult->_animTop - top; + top = _vm->_mult->_animTop; + } + + if ((_vm->_mult->_animTop + _vm->_mult->_animHeight) <= bottom) + bottom = _vm->_mult->_animTop + _vm->_mult->_animHeight - 1; + + _vm->_draw->_spriteLeft = destX; + _vm->_draw->_spriteTop = destY; + _vm->_draw->_spriteRight = right - left + 1; + _vm->_draw->_spriteBottom = bottom - top + 1; + _vm->_draw->_destSpriteX = left; + _vm->_draw->_destSpriteY = top; + _vm->_draw->_transparency = layer; + if (layer & 0x80) + _vm->_draw->_spriteLeft = _vm->_vidPlayer->getWidth(obj.videoSlot - 1) - + (destX + _vm->_draw->_spriteRight); + + _vm->_vidPlayer->slotCopyFrame(obj.videoSlot - 1, _vm->_draw->_backSurface->getVidMem(), + _vm->_draw->_spriteLeft, _vm->_draw->_spriteTop, + _vm->_draw->_spriteRight, _vm->_draw->_spriteBottom, + _vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, + _vm->_draw->_backSurface->getWidth(), + (_vm->_draw->_transparency != 0) ? 0 : -1); + + _vm->_draw->invalidateRect(_vm->_draw->_destSpriteX, _vm->_draw->_destSpriteY, + _vm->_draw->_destSpriteX + _vm->_draw->_spriteRight - 1, + _vm->_draw->_destSpriteY + _vm->_draw->_spriteBottom - 1); + + } + + if (flags & 4) { + _animLeft = _toRedrawLeft = left; + _animTop = _toRedrawTop = top; + _animRight = _toRedrawRight = right; + _animBottom = _toRedrawBottom = bottom; + } + + return; + } + if ((_animPictCount[animation] == 0) || (layer < 0)) return; if (layer >= _animations[animation].layersCount) @@ -670,6 +809,16 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags, pictIndex = (pictIndex & 15) - 1; + if ((pictIndex == 0xFFFF) || (_animPictCount[animation] <= pictIndex)) { + warning("Scenery::updateAnim: pictIndex out of range"); + return; + } + + if (_animations[animation].sizes[pictIndex] <= pieceIndex) { + warning("Scenery::updateAnim: pieceIndex out of range"); + continue; + } + left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left); right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right); top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top); diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h index 290d67d2d5..a1a1304d4d 100644 --- a/engines/gob/scenery.h +++ b/engines/gob/scenery.h @@ -92,6 +92,7 @@ public: AnimLayer *layers; PieceDesc **pieces; bool *piecesFromExt; + uint16 *sizes; Animation() : layersCount(0), layers(0), pieces(0), piecesFromExt(0) {} }; diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 6ca694c11a..7ed2fb044b 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -331,12 +331,12 @@ void Util::waitEndFrame() { void Util::setScrollOffset(int16 x, int16 y) { processInput(); - if(x >= 0) + if (x >= 0) _vm->_video->_scrollOffsetX = x; else _vm->_video->_scrollOffsetX = _vm->_draw->_scrollOffsetX; - if(y >= 0) + if (y >= 0) _vm->_video->_scrollOffsetY = y; else _vm->_video->_scrollOffsetY = _vm->_draw->_scrollOffsetY; diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index c3cecea318..25b80c89d9 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -32,29 +32,105 @@ #include "gob/game.h" #include "gob/palanim.h" #include "gob/inter.h" +#include "gob/map.h" namespace Gob { const char *VideoPlayer::_extensions[] = { "IMD", "VMD" }; -VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) { - _curFile[0] = 0; - _stream = 0; +VideoPlayer::Video::Video(GobEngine *vm) : _vm(vm), _fileName(0), _stream(0), _video(0) { +} + +VideoPlayer::Video::~Video() { + close(); +} + +bool VideoPlayer::Video::open(const char *fileName, Type which) { + close(); + + int16 handle = _vm->_dataIO->openData(fileName); + + if (handle < 0) { + warning("Couldn't open video \"%s\": No such file", fileName); + return false; + } + + _stream = _vm->_dataIO->openAsStream(handle, true); + + if (which == kVideoTypeIMD) { + _video = new Imd(); + } else if (which == kVideoTypeVMD) { + _video = new Vmd(); + } else { + warning("Couldn't open video \"%s\": Invalid video Type", fileName); + close(); + return false; + } + + if (!_video->load(*_stream)) { + warning("While loading video \"%s\"", fileName); + close(); + return false; + } + + _fileName = new char[strlen(fileName) + 1]; + strcpy(_fileName, fileName); + + return true; +} + +void VideoPlayer::Video::close() { + delete _video; + delete _stream; + delete[] _fileName; + _video = 0; + _stream = 0; + _fileName = 0; + memset(&_state, 0, sizeof(CoktelVideo::State)); +} + +bool VideoPlayer::Video::isOpen() const { + return (_video != 0); +} + +const char *VideoPlayer::Video::getFileName() const { + return _fileName ? _fileName : ""; +} + +CoktelVideo *VideoPlayer::Video::getVideo() { + return _video; +} + +const CoktelVideo *VideoPlayer::Video::getVideo() const { + return _video; +} + +CoktelVideo::State VideoPlayer::Video::getState() const { + return _state; +} + +CoktelVideo::State VideoPlayer::Video::nextFrame() { + if (_video) + _state = _video->nextFrame(); + + return _state; +} + +VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) { + _primaryVideo = new Video(vm); _backSurf = false; _needBlit = false; _noCursorSwitch = false; } VideoPlayer::~VideoPlayer() { - closeVideo(); + delete _primaryVideo; + for (uint i = 0; i < _videoSlots.size(); i++) + delete _videoSlots[i]; } -bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) { - char fileName[256]; - - strncpy0(fileName, video, 250); - +bool VideoPlayer::findFile(char *fileName, Type &which) { char *extStart = strrchr(fileName, '.'); // There's no empty extension if (extStart == (fileName + strlen(fileName) - 1)) { @@ -112,33 +188,22 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty } - if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) { - closeVideo(); + return true; +} - int16 handle = _vm->_dataIO->openData(fileName); +bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y, + int16 flags, Type which) { - if (handle < 0) { - warning("Couldn't open video \"%s\": No such file", fileName); - return false; - } + char fileName[256]; - _stream = _vm->_dataIO->openAsStream(handle, true); + strncpy0(fileName, videoFile, 250); - if (which == kVideoTypeIMD) { - _video = new Imd(); - } else if (which == kVideoTypeVMD) { - _video = new Vmd(); - } else { - warning("Couldn't open video \"%s\": Invalid video Type", fileName); - closeVideo(); - return false; - } + if (!findFile(fileName, which)) + return false; - if (!_video->load(*_stream)) { - warning("While loading video \"%s\"", fileName); - closeVideo(); + if (scumm_strnicmp(_primaryVideo->getFileName(), fileName, strlen(fileName))) { + if (!_primaryVideo->open(fileName, which)) return false; - } // WORKAROUND: In some rare cases, the cursor should still be // displayed while a video is playing. @@ -153,53 +218,54 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty _noCursorSwitch = true; } - strcpy(_curFile, fileName); - if (!(flags & kFlagNoVideo)) { _backSurf = ((flags & kFlagFrontSurface) == 0); SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20]; - _video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight()); + _primaryVideo->getVideo()->setVideoMemory(surf->getVidMem(), + surf->getWidth(), surf->getHeight()); } else - _video->setVideoMemory(); + _primaryVideo->getVideo()->setVideoMemory(); _needBlit = ((flags & kFlagUseBackSurfaceContent) != 0) && ((flags & kFlagFrontSurface) != 0); - _video->enableSound(*_vm->_mixer); + _primaryVideo->getVideo()->enableSound(*_vm->_mixer); } - if (!_video) + if (!_primaryVideo->isOpen()) return false; - _video->setFrameRate(_vm->_util->getFrameRate()); - _video->setXY(x, y); - WRITE_VAR(7, _video->getFramesCount()); + _primaryVideo->getVideo()->setFrameRate(_vm->_util->getFrameRate()); + _primaryVideo->getVideo()->setXY(x, y); + WRITE_VAR(7, _primaryVideo->getVideo()->getFramesCount()); return true; } -void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey, +void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey, uint16 palCmd, int16 palStart, int16 palEnd, int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) { - if (!_video) + if (!_primaryVideo->isOpen()) return; + CoktelVideo &video = *(_primaryVideo->getVideo()); + breakKey = 27; if (startFrame < 0) - startFrame = _video->getCurrentFrame(); + startFrame = video.getCurrentFrame(); if (lastFrame < 0) - lastFrame = _video->getFramesCount() - 1; + lastFrame = video.getFramesCount() - 1; if (palFrame < 0) palFrame = startFrame; if (endFrame < 0) endFrame = lastFrame; palCmd &= 0x3F; - if (_video->getCurrentFrame() != startFrame) { - if (_video->getFeatures() & CoktelVideo::kFeaturesSound) - startFrame = _video->getCurrentFrame(); + if (video.getCurrentFrame() != startFrame) { + if (video.getFeatures() & CoktelVideo::kFeaturesSound) + startFrame = video.getCurrentFrame(); else - _video->seekFrame(startFrame); + video.seekFrame(startFrame); } _vm->_draw->_showCursor = _noCursorSwitch ? 3 : 0; @@ -217,36 +283,156 @@ void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey, } if (!_noCursorSwitch) - _video->waitEndFrame(); + video.waitEndFrame(); startFrame++; } if (reverseTo >= 0) { - int16 toFrame = _video->getFramesCount() - reverseTo; - for (int i = _video->getCurrentFrame(); i >= toFrame; i--) { - _video->seekFrame(i, SEEK_SET, true); + int16 toFrame = video.getFramesCount() - reverseTo; + for (int i = video.getCurrentFrame(); i >= toFrame; i--) { + video.seekFrame(i, SEEK_SET, true); if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) { _vm->_palAnim->fade(0, -2, 0); memset((char *) _vm->_draw->_vgaPalette, 0, 768); } if (!_noCursorSwitch) - _video->waitEndFrame(); + video.waitEndFrame(); } } } -int16 VideoPlayer::getFramesCount() const { - if (!_video) - return 0; +void VideoPlayer::primaryClose() { + _primaryVideo->close(); +} + +int VideoPlayer::slotOpen(const char *videoFile, Type which) { + Video *video = new Video(_vm); + char fileName[256]; + + strncpy0(fileName, videoFile, 250); + + if (!findFile(fileName, which)) { + delete video; + return -1; + } + + if (!video->open(fileName, which)) { + delete video; + return -1; + } + + video->getVideo()->setVideoMemory(); + video->getVideo()->disableSound(); + + _videoSlots.push_back(video); + + WRITE_VAR(7, video->getVideo()->getFramesCount()); + + return _videoSlots.size() - 1; +} + +void VideoPlayer::slotPlay(int slot, int16 frame) { + if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + return; + + CoktelVideo &video = *(_videoSlots[slot]->getVideo()); + + if (frame < 0) + frame = video.getCurrentFrame(); + + if (video.getCurrentFrame() != frame) + video.seekFrame(frame); + + _videoSlots[slot]->nextFrame(); + WRITE_VAR(11, frame); +} + +void VideoPlayer::slotClose(int slot) { + if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + return; + + delete _videoSlots[slot]; + _videoSlots.remove_at(slot); +} + +void VideoPlayer::slotCopyFrame(int slot, byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp) { + + if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + return; + + _videoSlots[slot]->getVideo()->copyCurrentFrame(dest, + left, top, width, height, x, y, pitch, transp); +} + +void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) { + if ((slot < 0) || (((uint) slot) >= _videoSlots.size())) + return; + + copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd); +} + +bool VideoPlayer::slotIsOpen(int slot) const { + if ((slot >= 0) && (((uint) slot) < _videoSlots.size())) + return true; + + return false; +} + +const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const { + if (slot < 0) { + if (_primaryVideo->isOpen()) + return _primaryVideo; + } else if (((uint) slot) < _videoSlots.size()) + return _videoSlots[slot]; + + return 0; +} + +uint16 VideoPlayer::getFlags(int slot) const { + const Video *video = getVideoBySlot(slot); + + if (video) + return video->getVideo()->getFlags(); + + return 0; +} + +int16 VideoPlayer::getFramesCount(int slot) const { + const Video *video = getVideoBySlot(slot); + + if (video) + return video->getVideo()->getFramesCount(); + + return 0; +} + +int16 VideoPlayer::getCurrentFrame(int slot) const { + const Video *video = getVideoBySlot(slot); + + if (video) + return video->getVideo()->getCurrentFrame(); + + return 0; +} + +int16 VideoPlayer::getWidth(int slot) const { + const Video *video = getVideoBySlot(slot); - return _video->getFramesCount(); + if (video) + return video->getVideo()->getWidth(); + + return 0; } -int16 VideoPlayer::getCurrentFrame() const { - if (!_video) - return 0; +int16 VideoPlayer::getHeight(int slot) const { + const Video *video = getVideoBySlot(slot); + + if (video) + return video->getVideo()->getHeight(); - return _video->getCurrentFrame(); + return 0; } bool VideoPlayer::doPlay(int16 frame, int16 breakKey, @@ -260,7 +446,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_draw->_applyPal = true; if (palCmd >= 4) - copyPalette(palStart, palEnd); + copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd); } if (modifiedPal && (palCmd == 8) && !_backSurf) @@ -270,7 +456,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, if (_needBlit) _vm->_draw->forceBlit(); - CoktelVideo::State state = _video->nextFrame(); + CoktelVideo::State state = _primaryVideo->nextFrame(); WRITE_VAR(11, frame); if (_needBlit) @@ -285,7 +471,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, } if (state.flags & CoktelVideo::kStatePalette) { - copyPalette(palStart, palEnd); + copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd); if (!_backSurf) _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); @@ -311,7 +497,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_util->processInput(); if (_vm->_quitRequested) { - _video->disableSound(); + _primaryVideo->getVideo()->disableSound(); return true; } @@ -321,7 +507,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, _vm->_inter->storeKey(_vm->_util->checkKey()); if (VAR(0) == (unsigned) breakKey) { - _video->disableSound(); + _primaryVideo->getVideo()->disableSound(); return true; } } @@ -329,26 +515,37 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey, return false; } -void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) { - if ((palStart == -1) || (palEnd == -1)) - memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, - _video->getPalette(), 768); - else - memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + - palStart * 3, _video->getPalette() + palStart * 3, +void VideoPlayer::copyPalette(CoktelVideo &video, int16 palStart, int16 palEnd) { + if ((palStart != -1) && (palEnd != -1)) + memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) + palStart * 3, + video.getPalette() + palStart * 3, (palEnd - palStart + 1) * 3); + else + memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal, video.getPalette(), 768); } -void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY, +void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY, int16 varFrames, int16 varWidth, int16 varHeight) { - if (openVideo(video)) { - WRITE_VAR_OFFSET(varX, _video->getX()); - WRITE_VAR_OFFSET(varY, _video->getY()); - WRITE_VAR_OFFSET(varFrames, _video->getFramesCount()); - WRITE_VAR_OFFSET(varWidth, _video->getWidth()); - WRITE_VAR_OFFSET(varHeight, _video->getHeight()); - closeVideo(); + if (primaryOpen(videoFile)) { + int16 x, y, width, height; + + if ((VAR_OFFSET(varX) != 0xFFFFFFFF) || + !_primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height)) { + + x = _primaryVideo->getVideo()->getX(); + y = _primaryVideo->getVideo()->getY(); + width = _primaryVideo->getVideo()->getWidth(); + height = _primaryVideo->getVideo()->getHeight(); + } + + WRITE_VAR_OFFSET(varX, x); + WRITE_VAR_OFFSET(varY, y); + WRITE_VAR_OFFSET(varFrames, _primaryVideo->getVideo()->getFramesCount()); + WRITE_VAR_OFFSET(varWidth, width); + WRITE_VAR_OFFSET(varHeight, height); + + primaryClose(); } else { WRITE_VAR_OFFSET(varX, -1); WRITE_VAR_OFFSET(varY, -1); @@ -358,13 +555,4 @@ void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY, } } -void VideoPlayer::closeVideo() { - delete _video; - delete _stream; - - _video = 0; - _stream = 0; - *_curFile = 0; -} - } // End of namespace Gob diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index 7b9a3ca687..3a6ec0d9da 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -26,6 +26,8 @@ #ifndef GOB_VIDEOPLAYER_H #define GOB_VIDEOPLAYER_H +#include "common/array.h" + #include "gob/coktelvideo.h" #include "gob/dataio.h" @@ -51,34 +53,75 @@ public: VideoPlayer(GobEngine *vm); ~VideoPlayer(); - bool openVideo(const char *video, int16 x = -1, int16 y = -1, + bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1, int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry); - - void play(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27, + void primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1, int16 endFrame = -1, bool fade = false, int16 reverseTo = -1); + void primaryClose(); - int16 getFramesCount() const; - int16 getCurrentFrame() const; - void writeVideoInfo(const char *video, int16 varX, int16 varY, - int16 varFrames, int16 varWidth, int16 varHeight); + int slotOpen(const char *videoFile, Type which = kVideoTypeTry); + void slotPlay(int slot, int16 frame = -1); + void slotClose(int slot); + void slotCopyFrame(int slot, byte *dest, + uint16 left, uint16 top, uint16 width, uint16 height, + uint16 x, uint16 y, uint16 pitch, int16 transp = -1); + void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1); + + bool slotIsOpen(int slot) const; - void closeVideo(); + uint16 getFlags(int slot = -1) const; + int16 getFramesCount(int slot = -1) const; + int16 getCurrentFrame(int slot = -1) const; + int16 getWidth(int slot = -1) const; + int16 getHeight(int slot = -1) const; + + void writeVideoInfo(const char *videoFile, int16 varX, int16 varY, + int16 varFrames, int16 varWidth, int16 varHeight); private: + class Video { + public: + Video(GobEngine *vm); + ~Video(); + + bool open(const char *fileName, Type which); + void close(); + + bool isOpen() const; + + const char *getFileName() const; + CoktelVideo *getVideo(); + const CoktelVideo *getVideo() const; + CoktelVideo::State getState() const; + + CoktelVideo::State nextFrame(); + + private: + GobEngine *_vm; + + char *_fileName; + DataStream *_stream; + CoktelVideo *_video; + CoktelVideo::State _state; + }; + static const char *_extensions[]; GobEngine *_vm; - char _curFile[256]; - DataStream *_stream; - CoktelVideo *_video; + Common::Array