diff options
author | Johannes Schickel | 2009-05-31 19:31:04 +0000 |
---|---|---|
committer | Johannes Schickel | 2009-05-31 19:31:04 +0000 |
commit | ede3dec88a291d7435708deec88f4108e383224b (patch) | |
tree | a04d8271925bb4f222fc90cb27d89742dd25a712 /engines/kyra | |
parent | dad6073548ee02cd81dbfbc8457f6d8c0252d227 (diff) | |
download | scummvm-rg350-ede3dec88a291d7435708deec88f4108e383224b.tar.gz scummvm-rg350-ede3dec88a291d7435708deec88f4108e383224b.tar.bz2 scummvm-rg350-ede3dec88a291d7435708deec88f4108e383224b.zip |
Add support for the Lands of Lore scrolling credits.
svn-id: r41081
Diffstat (limited to 'engines/kyra')
-rw-r--r-- | engines/kyra/lol.h | 18 | ||||
-rw-r--r-- | engines/kyra/sequences_lok.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/sequences_lol.cpp | 271 | ||||
-rw-r--r-- | engines/kyra/sprites_lol.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 76 |
5 files changed, 361 insertions, 8 deletions
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 84b6386ccd..ae80f4384d 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -393,6 +393,24 @@ private: void showOutro(int character, bool maxDifficulty); void setupEpilogueData(bool load); + void showCredits(); + void processCredits(char *text, int dimState, int page, int delay); + void loadOutroShapes(int file, uint8 **storage); + + uint8 _outroShapeTable[256]; + + // TODO: Consider moving these tables to kyra.dat + static const char * const _outroShapeFileTable[]; + static const uint8 _outroFrameTable[]; + + static const int16 _outroRightMonsterPos[]; + static const int16 _outroLeftMonsterPos[]; + static const int16 _outroRightDoorPos[]; + static const int16 _outroLeftDoorPos[]; + + static const int _outroMonsterScaleTableX[]; + static const int _outroMonsterScaleTableY[]; + // timers void setupTimers(); void enableTimer(int id); diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 7e5f4fc517..12ede98ad4 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1024,7 +1024,7 @@ void KyraEngine_LoK::seq_playEnding() { } void KyraEngine_LoK::seq_playCredits() { - static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const char stringTerms[] = { 0x5, 0xd, 0x0}; static const int numStrings = 250; diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index fed09e3c3c..3cb203998a 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -750,9 +750,8 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { assert(outro); outro->lolCharacter = character; - _screen->loadFont(Screen::FID_8_FNT, "NEW8P.FNT"); + _screen->loadFont(Screen::FID_6_FNT, "NEW6P.FNT"); _screen->loadFont(Screen::FID_INTRO_FNT, "INTRO.FNT"); - _screen->setFont(Screen::FID_8_FNT); _tim->resetFinishedFlag(); _tim->setLangData("LOLFINAL.DIP"); @@ -780,6 +779,7 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { _system->delayMillis(10); _screen->updateScreen(); } + removeInputTop(); _screen->showMouse(); _sound->voiceStop(); _sound->beginFadeOut(); @@ -793,7 +793,7 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { _screen->fadeToBlack(30); - //XXX + showCredits(); switch (character) { case 0: @@ -825,7 +825,7 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { _screen->fadePalette(_screen->getPalette(0), 30, 0); while (!checkInput(0) && !shouldQuit()) - delay(1); + delay(_tickLength); _screen->fadeToBlack(30); @@ -835,6 +835,269 @@ void LoLEngine::showOutro(int character, bool maxDifficulty) { setupEpilogueData(false); } +void LoLEngine::showCredits() { + for (int i = 0; i < 255; ++i) + _outroShapeTable[i] = i; + _outroShapeTable[256] = 0; + + _sound->haltTrack(); + _sound->loadSoundFile("LOREFINL"); + _sound->playTrack(4); + + _screen->hideMouse(); + + static const uint8 colorMap[] = { 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6F, 0x6F, 0x6D }; + _screen->setTextColorMap(colorMap); + _screen->_charWidth = 0; + + _screen->loadBitmap("ROOM.CPS", 2, 2, _screen->getPalette(0)); + memset(_screen->getPalette(0) + 764, 0, 3); + _screen->fadeToBlack(30); + + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); + + char *credits = (char *)_res->fileData("CREDITS.TXT", 0); + processCredits(credits, 19, 4, 5); + delete[] credits; + + uint32 endTime = _system->getMillis() + 120 * _tickLength; + while (endTime > _system->getMillis() && !shouldQuit()) { + if (checkInput(0)) + break; + delay(_tickLength); + } + + _sound->beginFadeOut(); + _screen->fadeToBlack(30); + + _screen->clearCurPage(); + _screen->updateScreen(); + _screen->showMouse(); +} + +void LoLEngine::processCredits(char *t, int dimState, int page, int delayTime) { + if (!t) + return; + + _screen->setScreenDim(dimState); + _screen->clearPage(page); + _screen->clearPage(6); + + _screen->loadBitmap("DOOR.SHP", 5, 5, 0); + uint8 *doorShape = _screen->makeShapeCopy(_screen->getCPagePtr(5), 0); + assert(doorShape); + + _screen->drawShape(0, doorShape, 0, 0, 20, 0x10); + _screen->drawShape(0, doorShape, 0, 0, 21, 0x11); + + int curShapeFile = 0; + uint8 *shapes[12]; + memset(shapes, 0, sizeof(shapes)); + + loadOutroShapes(curShapeFile++, shapes); + uint8 *monsterPal = _res->fileData("MONSTERS.PAL", 0); + assert(monsterPal); + + memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + 0 * 3, 40 * 3); + _screen->fadePalette(_screen->getPalette(0), 30); + + uint32 waitTimer = _system->getMillis(); + + struct CreditsString { + int16 x, y; + char *str; + uint8 code; + uint8 height; + uint8 alignment; + } strings[36]; + memset(strings, 0, sizeof(strings)); + + int countStrings = 0; + char *str = t; + + int frameCounter = 0; + int monsterAnimFrame = 0; + bool needNewShape = false; + bool doorRedraw = true; + + uint8 *animBlock = new uint8[40960]; + assert(animBlock); + memset(animBlock, 0, 40960); + + do { + while (_system->getMillis() < waitTimer && !shouldQuit()) + delay(_tickLength); + waitTimer = _system->getMillis() + delayTime * _tickLength; + + while (countStrings < 35 && str[0]) { + int y = 0; + + if (!countStrings) { + y = _screen->_curDim->h; + } else { + y = strings[countStrings].y + strings[countStrings].height; + y += strings[countStrings].height >> 3; + } + + char *curString = str; + str = (char *)strpbrk(str, "\x05\x0D"); + if (!str) + str = strchr(curString, 0); + + CreditsString &s = strings[countStrings + 1]; + s.code = str[0]; + str[0] = 0; + + if (s.code) + ++str; + + s.alignment = 0; + if (*curString == 3 || *curString == 4) + s.alignment = *curString++; + + _screen->setFont(Screen::FID_6_FNT); + + if (*curString == 1 || *curString == 2) + ++curString; + s.height = _screen->getFontHeight(); + + if (s.alignment == 3) + s.x = 0; + else if (s.alignment == 4) + s.x = 300 - _screen->getTextWidth(curString); + else + s.x = ((_screen->_curDim->w << 3) - _screen->getTextWidth(curString)) / 2; + + if (strings[countStrings].code == 5) + y -= strings[countStrings].height + (strings[countStrings].height >> 3); + + s.y = y; + s.str = curString; + ++countStrings; + } + + ++frameCounter; + if (frameCounter % 3) { + _screen->copyRegion(0, 0, 0, 0, 320, 200, 6, page, Screen::CR_NO_P_CHECK); + } else { + if (!monsterAnimFrame && doorRedraw) { + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, page, Screen::CR_NO_P_CHECK); + _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); + _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + + --frameCounter; + doorRedraw = false; + } else { + if (!monsterAnimFrame) + _screen->setScreenPalette(_screen->getPalette(0)); + + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, page, Screen::CR_NO_P_CHECK); + + uint8 *monsterShape = shapes[_outroFrameTable[monsterAnimFrame]]; + + int doorSD = 0; + int doorX = 0, doorY = 0; + int monsterX = 0, monsterY = 0; + + bool isRightMonster = ((curShapeFile - 1) & 1) != 0; + + if (isRightMonster) { + doorSD = 21; + doorX = _outroRightDoorPos[monsterAnimFrame * 2 + 0]; + doorY = _outroRightDoorPos[monsterAnimFrame * 2 + 1]; + + monsterX = _outroRightMonsterPos[monsterAnimFrame * 2 + 0]; + monsterY = _outroRightMonsterPos[monsterAnimFrame * 2 + 1]; + + _screen->drawShape(page, doorShape, 0, 0, 20, 0x10); + } else { + doorSD = 20; + doorX = _outroLeftDoorPos[monsterAnimFrame * 2 + 0]; + doorY = _outroLeftDoorPos[monsterAnimFrame * 2 + 1]; + + monsterX = _outroLeftMonsterPos[monsterAnimFrame * 2 + 0]; + monsterY = _outroLeftMonsterPos[monsterAnimFrame * 2 + 1]; + + _screen->drawShape(page, doorShape, 0, 0, 21, 0x11); + } + + if (monsterAnimFrame >= 8) + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + + _screen->drawShape(page, monsterShape, monsterX, monsterY, 0, 0x104 | ((!isRightMonster | (monsterAnimFrame < 20)) ? 0 : 1), _outroShapeTable, 1, _outroMonsterScaleTableX[monsterAnimFrame], _outroMonsterScaleTableY[monsterAnimFrame]); + + if (monsterAnimFrame < 8) + _screen->drawShape(page, doorShape, doorX, doorY, doorSD, (doorSD == 20) ? 0 : 1); + + _screen->copyRegion(0, 0, 0, 0, 320, 200, page, 6, Screen::CR_NO_P_CHECK); + doorRedraw = true; + + monsterAnimFrame = (monsterAnimFrame + 1) % 24; + needNewShape = !monsterAnimFrame; + } + } + + for (int i = 0; i < countStrings; ++i) { + CreditsString &s = strings[i+1]; + int x = s.x, y = s.y; + + if (y < _screen->_curDim->h) { + _screen->_curPage = page; + _screen->setFont(Screen::FID_6_FNT); + _screen->printText(s.str, (_screen->_curDim->sx << 3) + x, _screen->_curDim->sy + y, 0xDC, 0x00); + _screen->_curPage = 0; + } + + --s.y; + } + + _screen->copyToPage0(_screen->_curDim->sy, _screen->_curDim->h, page, animBlock); + + if (strings[1].y < -10) { + strings[1].str += strlen(strings[1].str); + strings[1].str[0] = strings[1].code; + --countStrings; + memmove(&strings[1], &strings[2], countStrings * sizeof(CreditsString)); + } + + if (needNewShape) { + ++curShapeFile; + if (curShapeFile == 16) + curShapeFile += 2; + if (curShapeFile == 6) + curShapeFile += 2; + curShapeFile = curShapeFile % 28; + + loadOutroShapes(curShapeFile, shapes); + memcpy(_screen->getPalette(0) + 88 * 3, monsterPal + curShapeFile * 40 * 3, 40 * 3); + _screen->setScreenPalette(_screen->getPalette(0)); + + needNewShape = false; + } + + _screen->updateScreen(); + } while (countStrings && !checkInput(0) && !shouldQuit()); + removeInputTop(); + + delete[] animBlock; + delete[] doorShape; + delete[] monsterPal; + for (int i = 0; i < 12; ++i) + delete[] shapes[i]; +} + +void LoLEngine::loadOutroShapes(int file, uint8 **storage) { + _screen->loadBitmap(_outroShapeFileTable[file], 5, 5, 0); + + for (int i = 0; i < 12; ++i) { + delete[] storage[i]; + if (i < 8) + storage[i] = _screen->makeShapeCopy(_screen->getCPagePtr(5), i); + else + storage[i] = _screen->makeShapeCopy(_screen->getCPagePtr(5), i+4); + } +} + } // end of namespace Kyra #endif // ENABLE_LOL diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index df1e062ae2..ccc4725827 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -117,7 +117,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int animTy delete[] tmpPal1; delete[] tmpPal2; delete[] tmpPal3; - delete[] tsh; + delete[] tsh; } void LoLEngine::releaseMonsterShapes(int monsterIndex) { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 6c4985d608..8cc9ba17c2 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -3019,7 +3019,12 @@ const ScreenDim Screen_LoL::_screenDimTable256C[] = { { 0x0F, 0x06, 0x14, 0x6E, 0x01, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0xFE, 0x01, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (5 entries, CD version only) - { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (3 entries, floppy version only) + { 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 }, // Main menu box (3 entries, floppy version only) + + { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits + { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 }, + { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 } }; const ScreenDim Screen_LoL::_screenDimTable16C[] = { @@ -3041,7 +3046,12 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { { 0x0F, 0x06, 0x14, 0x6E, 0x44, 0x00, 0x00, 0x00 }, { 0x1A, 0xBE, 0x0A, 0x07, 0x33, 0x44, 0x00, 0x00 }, { 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here) - { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 } // Main menu box (3 entries) + { 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (3 entries) + + { 0x01, 0x20, 0x26, 0x80, 0xDC, 0xFD, 0x00, 0x00 }, // Credits (TODO: Check this!) + { 0x09, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 }, + { 0x19, 0x29, 0x08, 0x2C, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x02, 0x26, 0x14, 0x00, 0x0F, 0x0E, 0x00 } }; const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C); @@ -3158,6 +3168,68 @@ const int8 LoLEngine::_mapCoords[12][4] = { const uint8 LoLEngine::_numClock2Timers = ARRAYSIZE(LoLEngine::_clock2Timers); +const char * const LoLEngine::_outroShapeFileTable[] = { + "AMAZON.SHP", "ARCHRSLG.SHP", "AVIANWRM.SHP", "BANDIT.SHP", "BOAR.SHP", "CABAL.SHP", + "GUARD.SHP", "HAG.SHP", "HORNET.SHP", "HURZELL.SHP", "IRONGRZR.SHP", "KNOWLES.SHP", + "LIZARD.SHP", "MANTHA.SHP", "MINOTAUR.SHP", "MORIBUND.SHP", "ORC.SHP", "ORCLDR.SHP", + "PENTROG.SHP", "RATMAN.SHP", "ROCKLING.SHP", "SCAVNGR.SHP", "STARK.SHP", + "SWAMPCIT.SHP", "SWAMPMON.SHP", "THUG.SHP", "VIPER.SHP", "XEOB.SHP" +}; + +const uint8 LoLEngine::_outroFrameTable[] = { + 0, 0, 0, 0, 0, 1, 2, 3, + 0, 1, 2, 3, 8, 9, 10, 11, + 8, 9, 10, 11, 4, 5, 6, 7 +}; + +const int16 LoLEngine::_outroRightMonsterPos[] = { + 205, 55, 205, 55, 205, 55, 205, 55, + 205, 56, 207, 57, 208, 58, 210, 59, + 213, 60, 216, 61, 220, 61, 225, 61, + 230, 61, 235, 61, 240, 61, 240, 61, + 240, 61, 240, 61, 240, 61, 240, 61, + 240, 61, 265, 61, 290, 61, 315, 61 +}; + +const int16 LoLEngine::_outroLeftMonsterPos[] = { + 92, 55, 92, 55, 92, 55, 92, 55, + 92, 56, 90, 57, 85, 58, 77, 59, + 67, 60, 57, 61, 47, 61, 35, 61, + 35, 61, 35, 61, 35, 61, 35, 61, + 35, 61, 35, 61, 35, 61, 35, 61, + 35, 61, 10, 61, -20, 61, -45, 61 +}; + +const int16 LoLEngine::_outroRightDoorPos[] = { + 200, 41, 200, 29, 200, 17, 200, 5, + 200, -7, 200, -7, 200, -7, 200, -7, + 200, 5, 200, 17, 200, 29, 200, 41, + 200, 41, 200, 41, 200, 41, 200, 41, + 200, 41, 200, 41, 200, 41, 200, 41, + 200, 41, 200, 41, 200, 41, 200, 41 +}; + +const int16 LoLEngine::_outroLeftDoorPos[] = { + 72, 41, 72, 29, 72, 17, 72, 5, + 72, -7, 72, -7, 72, -7, 72, -7, + 72, 5, 72, 17, 72, 29, 72, 41, + 72, 41, 72, 41, 72, 41, 72, 41, + 72, 41, 72, 41, 72, 41, 72, 41, + 72, 41, 72, 41, 72, 41, 72, 41 +}; + +const int LoLEngine::_outroMonsterScaleTableX[] = { + 0x050, 0x050, 0x050, 0x050, 0x050, 0x05D, 0x070, 0x085, + 0x0A0, 0x0C0, 0x0E2, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 +}; + +const int LoLEngine::_outroMonsterScaleTableY[] = { + 0x04C, 0x04C, 0x04C, 0x04C, 0x04C, 0x059, 0x06B, 0x080, + 0x099, 0x0B8, 0x0D9, 0x100, 0x100, 0x100, 0x100, 0x100, + 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 +}; + #endif // ENABLE_LOL } // End of namespace Kyra |