From aaaea78b3bee9ded630258aab24e307c5dd3789f Mon Sep 17 00:00:00 2001 From: Eric Fry Date: Thu, 19 Mar 2020 23:29:07 +1100 Subject: [PATCH] DRAGONS: Added map screen transition effects Fixed overrun bug with loading screen flames --- engines/dragons/dragons.cpp | 4 +- engines/dragons/screen.cpp | 10 +-- engines/dragons/scriptopcodes.cpp | 1 - engines/dragons/specialopcodes.cpp | 121 +++++++++++++++++++++++++++-- engines/dragons/specialopcodes.h | 1 + 5 files changed, 121 insertions(+), 16 deletions(-) diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp index a934ffd3f8d..a3eb89d2b60 100644 --- a/engines/dragons/dragons.cpp +++ b/engines/dragons/dragons.cpp @@ -1639,7 +1639,7 @@ void DragonsEngine::loadingScreenUpdate() { if (_loadingScreenState->loadingFlamesUpdateCounter == 0) { _loadingScreenState->loadingFlamesUpdateCounter = 4; for (int i = 0; i < 10 ; i++) { - flameYOffset = _loadingScreenState->baseYOffset - flameOffsetTbl[(i + _loadingScreenState->flameOffsetIdx) % 27]; + flameYOffset = _loadingScreenState->baseYOffset - flameOffsetTbl[(i + _loadingScreenState->flameOffsetIdx) % 26]; if (_loadingScreenState->flames[i]->_y_pos >= -0xb) { _loadingScreenState->flames[i]->_y_pos = flameYOffset; } @@ -1649,7 +1649,7 @@ void DragonsEngine::loadingScreenUpdate() { quad->points[1].y = flameYOffset + 2; } } - _loadingScreenState->flameOffsetIdx = (_loadingScreenState->flameOffsetIdx + 1) % 27; + _loadingScreenState->flameOffsetIdx = (_loadingScreenState->flameOffsetIdx + 1) % 26; } else { _loadingScreenState->loadingFlamesUpdateCounter--; } diff --git a/engines/dragons/screen.cpp b/engines/dragons/screen.cpp index 0860c853ece..56c84650705 100644 --- a/engines/dragons/screen.cpp +++ b/engines/dragons/screen.cpp @@ -446,10 +446,10 @@ int16 Screen::addFlatQuad(int16 x0, int16 y0, int16 x1, int16 y1, int16 x3, int1 _flatQuads[i].points[0].y = y0; _flatQuads[i].points[1].x = x1; _flatQuads[i].points[1].y = y1; - _flatQuads[i].points[2].x = x3; - _flatQuads[i].points[2].y = y3; - _flatQuads[i].points[3].x = x2; - _flatQuads[i].points[3].y = y2; + _flatQuads[i].points[2].x = x2; + _flatQuads[i].points[2].y = y2; + _flatQuads[i].points[3].x = x3; + _flatQuads[i].points[3].y = y3; _flatQuads[i].colour = colour; _flatQuads[i].priorityLayer = priorityLayer; return i; @@ -464,7 +464,7 @@ void Screen::drawFlatQuads(uint16 priorityLayer) { if (_flatQuads[i].flags & 1u && _flatQuads[i].priorityLayer == priorityLayer) { //TODO need to support semitrans mode. //TODO check if we need to support non-rectangular quads. - fillRect(_flatQuads[i].colour, Common::Rect(_flatQuads[i].points[0].x, _flatQuads[i].points[0].y, _flatQuads[i].points[2].x + 1, _flatQuads[i].points[2].y + 1)); + fillRect(_flatQuads[i].colour, Common::Rect(_flatQuads[i].points[0].x, _flatQuads[i].points[0].y, _flatQuads[i].points[3].x + 1, _flatQuads[i].points[3].y + 1)); } } } diff --git a/engines/dragons/scriptopcodes.cpp b/engines/dragons/scriptopcodes.cpp index c89d6ebfb73..a8981c76fbc 100644 --- a/engines/dragons/scriptopcodes.cpp +++ b/engines/dragons/scriptopcodes.cpp @@ -908,7 +908,6 @@ void ScriptOpcodes::opLoadScene(ScriptOpCall &scriptOpCall) { _vm->_sound->PauseCDMusic(); if (newSceneID != 0) { - // load scene here. _vm->_scene->_mapTransitionEffectSceneID = _vm->_scene->getSceneId(); _vm->_scene->setSceneId(newSceneID); _vm->_flickerInitialSceneDirection = flickerDirection; diff --git a/engines/dragons/specialopcodes.cpp b/engines/dragons/specialopcodes.cpp index aa5116a6e30..e36ff574817 100644 --- a/engines/dragons/specialopcodes.cpp +++ b/engines/dragons/specialopcodes.cpp @@ -1118,17 +1118,19 @@ void SpecialOpcodes::spcKnightsSavedAgainCutScene() { } void SpecialOpcodes::spcTransitionToMap() { - //TODO map transition -// DAT_8006a422 = 0; -// DAT_8006a424 = 0; -// cursorSequenceId = 0; -// _vm->waitForFrames(); -// engine_flags_maybe = engine_flags_maybe | 0x20000000; -// FUN_80023b34(0, 0, 1); + _vm->_scene->setMgLayerPriority(0); + _vm->_scene->setFgLayerPriority(0); + _vm->_cursor->updateSequenceID(0); + _vm->waitForFrames(1); + _vm->setFlags(ENGINE_FLAG_20000000); + mapTransition(1); } void SpecialOpcodes::spcTransitionFromMap() { - //TODO map transition + mapTransition(0); + _vm->_scene->setMgLayerPriority(2); + _vm->_scene->setFgLayerPriority(3); + _vm->clearFlags(ENGINE_FLAG_20000000); } void SpecialOpcodes::spcCaveOfDilemmaSceneLogic() { @@ -1308,6 +1310,109 @@ void SpecialOpcodes::setSpecialOpCounter(int16 newValue) { _specialOpCounter = newValue; } +void SpecialOpcodes::mapTransition(uint16 mode) { + const uint16 mapLookupTbl[26] = { + 160, 100, 45, 100, + 105, 170, 14, 87, + 83, 33, 86, 100, + 25, 180, 161, 156, + 195, 47, 287, 35, + 292, 80, 202, 182, + 127, 78 + }; + + const uint16 mapSceneIdTbl[13] = { + 0, + 0xa, 0x15, 0x1a, + 0x1b, 0x1c, 0x1e, + 0x20, 0x23, 0x25, + 0x2d, 0x30, 0x31 + }; + + bool hasDoneFade = false; + uint16 state = _vm->getINI(0x1e)->objectState; + if (state == 0) { + state = 0xc; + for (int i = 1; i < 0xd; i++) { + if (_vm->_scene->_mapTransitionEffectSceneID < mapSceneIdTbl[i]) { + state = i - 1; + break; + } + } + } + + _vm->_cursor->updatePosition(mapLookupTbl[state * 2], mapLookupTbl[state * 2 + 1]); + _vm->setFlags(ENGINE_FLAG_20); + + int32 uVar14 = (_vm->_cursor->_y << 0x10) >> 4; + int32 uVar6 = (DRAGONS_SCREEN_HEIGHT - _vm->_cursor->_y) * 0x10000 >> 4; + int32 uVar2 = _vm->_cursor->_x; + int32 uVar3 = (DRAGONS_SCREEN_WIDTH - uVar2) * 0x10000 >> 4; + + if (mode == 0) { //Close map + FlatQuad *topQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,0,0x140,0,0x140,0,0,0,1,4,0)); + FlatQuad *bottomQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,200,0x140,200,0x140,200,0,200,1,4,0)); + FlatQuad *leftQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,0,0,0,0,200,0,200,1,4,0)); + FlatQuad *rightQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0x140,0,0x140,0,0x140,200,0x140,200,1,4,0)); + int32 iVar10 = topQuad->points[3].y << 0x10; + int32 iVar13 = bottomQuad->points[0].y << 0x10; + int32 iVar11 = rightQuad->points[0].x << 0x10; + int32 iVar12 = leftQuad->points[1].x << 0x10; + + + + while (iVar10 < (_vm->_cursor->_y << 0x10)) { + iVar10 = iVar10 + uVar14; + iVar13 = iVar13 - uVar6; + iVar12 = iVar12 + uVar2 * 0x1000; + topQuad->points[3].y = iVar10 >> 0x10; + topQuad->points[2].y = iVar10 >> 0x10; + bottomQuad->points[0].y = iVar13 >> 0x10; + bottomQuad->points[1].y = iVar13 >> 0x10; + leftQuad->points[1].x = iVar12 >> 0x10; + leftQuad->points[3].x = iVar12 >> 0x10; + iVar11 = iVar11 - uVar3; + rightQuad->points[0].x = iVar11 >> 0x10; + rightQuad->points[2].x = iVar11 >> 0x10; + _vm->waitForFrames(1); + } + + // fade_related_calls_with_1f(); + } else if (mode == 1) { // Open map + int16 cursorX = _vm->_cursor->_x; + int16 cursorY = _vm->_cursor->_y; + FlatQuad *topQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,0,0x140,0,0x140,cursorY,0,cursorY,1,4,0)); + FlatQuad *topQuad1 = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,cursorY,0x140,cursorY,0x140,200,0,200,1,4,0)); + FlatQuad *bottomQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(0,0,cursorX,0,cursorX,200,0,200,1,4,0)); + FlatQuad *rightQuad = _vm->_screen->getFlatQuad(_vm->_screen->addFlatQuad(cursorX,0,0x140,0,0x140,200,cursorX,200,1,4,0)); + int32 iVar10 = topQuad->points[3].y << 0x10; + int32 iVar11 = topQuad1->points[0].y << 0x10; + int32 iVar12 = bottomQuad->points[1].x << 0x10; + int32 iVar13 = rightQuad->points[0].x << 0x10; + _vm->waitForFrames(2); + while (0 < iVar10) { + iVar10 = iVar10 - uVar14; + iVar11 = iVar11 + uVar6; + iVar12 = iVar12 + uVar2 * -0x1000; + topQuad->points[3].y = iVar10 >> 0x10; + topQuad->points[2].y = iVar10 >> 0x10; + topQuad1->points[0].y = iVar11 >> 0x10; + topQuad1->points[1].y = iVar11 >> 0x10; + bottomQuad->points[1].x = iVar12 >> 0x10; + bottomQuad->points[3].x = iVar12 >> 0x10; + iVar13 = iVar13 + uVar3; + rightQuad->points[0].x = iVar13 >> 0x10; + rightQuad->points[2].x = iVar13 >> 0x10; + _vm->waitForFrames(1); + if (!hasDoneFade) { + // call_fade_related_1f(); + hasDoneFade = true; + } + } + } + _vm->_screen->clearAllFlatQuads(); +} + void pizzaUpdateFunction() { static int16 counter = 0; DragonsEngine *vm = getEngine(); diff --git a/engines/dragons/specialopcodes.h b/engines/dragons/specialopcodes.h index e879ae18ed9..6784ce0cb19 100644 --- a/engines/dragons/specialopcodes.h +++ b/engines/dragons/specialopcodes.h @@ -209,6 +209,7 @@ private: void pizzaMakerStopWorking(); void clearSceneUpdateFunction(); + void mapTransition(uint16 mode); };