diff options
Diffstat (limited to 'engines/kyra')
-rw-r--r-- | engines/kyra/lol.h | 34 | ||||
-rw-r--r-- | engines/kyra/resource.h | 22 | ||||
-rw-r--r-- | engines/kyra/screen.cpp | 16 | ||||
-rw-r--r-- | engines/kyra/sequences_lok.cpp | 28 | ||||
-rw-r--r-- | engines/kyra/sequences_lol.cpp | 274 | ||||
-rw-r--r-- | engines/kyra/sound.cpp | 5 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 45 |
7 files changed, 372 insertions, 52 deletions
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 06950779b1..1c89a7a1eb 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -301,6 +301,7 @@ friend class GUI_LoL; friend class TextDisplayer_LoL; friend class TIMInterpreter_LoL; friend class Debugger_LoL; +friend class HistoryPlayer; public: LoLEngine(OSystem *system, const GameFlags &flags); ~LoLEngine(); @@ -1124,14 +1125,14 @@ private: uint16 _dmScaleH; int _lastMouseRegion; - int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger; - int _spsWindowX, _spsWindowY, _spsWindowW, _spsWindowH; + int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger; + int _spsWindowX, _spsWindowY, _spsWindowW, _spsWindowH; uint8 *_tempBuffer5120; - const char *const * _levelDatList; + const char * const *_levelDatList; int _levelDatListSize; - const char *const * _levelShpList; + const char * const *_levelShpList; int _levelShpListSize; const int8 *_dscUnk1; @@ -1476,6 +1477,31 @@ private: LevelTempData *_lvlTempData[29]; }; +class HistoryPlayer { +public: + HistoryPlayer(LoLEngine *vm); + ~HistoryPlayer(); + + void play(); +private: + OSystem *_system; + LoLEngine *_vm; + Screen *_screen; + + int _x, _y, _width, _height; + int _frame; + Movie *_wsa; + + void loadWsa(const char *filename); + void playWsa(bool direction); + void restoreWsaBkgd(); + + Movie *_fireWsa; + int _fireFrame; + uint32 _nextFireTime; + void updateFire(); +}; + } // end of namespace Kyra #endif diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 07fb2e05b7..3dc6c5ff2f 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -282,16 +282,18 @@ enum kKyraResources { kLolButtonList7, kLolButtonList8, - lolLegendData, - lolMapCursorOvl, - lolMapStringId, - //lolMapPal, - - lolSpellbookAnim, - lolSpellbookCoords, - lolHealShapeFrames, - lolLightningDefs, - lolFireballCoords, + kLolLegendData, + kLolMapCursorOvl, + kLolMapStringId, + //kLolMapPal, + + kLolSpellbookAnim, + kLolSpellbookCoords, + kLolHealShapeFrames, + kLolLightningDefs, + kLolFireballCoords, + + kLolHistory, #endif // ENABLE_LOL kMaxResIDs diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index bc1ccbb801..52035a49f4 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -658,10 +658,18 @@ int Screen::fadePalStep(const Palette &pal, int diff) { } void Screen::setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue) { - getPalette(0)[index * 3 + 0] = red; - getPalette(0)[index * 3 + 1] = green; - getPalette(0)[index * 3 + 2] = blue; - setScreenPalette(getPalette(0)); + Palette &pal = getPalette(0); + + const int offset = index * 3; + + if (pal[offset + 0] == red && pal[offset + 1] == green && pal[offset + 2] == blue) + return; + + pal[offset + 0] = red; + pal[offset + 1] = green; + pal[offset + 2] = blue; + + setScreenPalette(pal); } void Screen::getRealPalette(int num, uint8 *dst) { diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index 8425bf9b0c..35f434698b 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1135,8 +1135,16 @@ void KyraEngine_LoK::seq_playEnding() { _screen->showMouse(); if (_flags.platform == Common::kPlatformAmiga) { - while (!shouldQuit()) + _screen->_charWidth = -2; + _screen->setCurPage(2); + + _screen->getPalette(2).clear(); + _screen->setScreenPalette(_screen->getPalette(2)); + + while (!shouldQuit()) { seq_playCreditsAmiga(); + delayUntil(_system->getMillis() + 300 * _tickLength); + } } else { seq_playCredits(); } @@ -1287,8 +1295,10 @@ void KyraEngine_LoK::seq_playCredits() { _screen->updateScreen(); } - if (checkInput(0, false)) + if (checkInput(0, false)) { + removeInputTop(); finished = true; + } uint32 now = _system->getMillis(); uint32 nextLoop = startLoop + _tickLength * 5; @@ -1309,17 +1319,14 @@ void KyraEngine_LoK::seq_playCreditsAmiga() { _screen->loadBitmap("CHALET.CPS", 4, 2, &_screen->getPalette(0)); _screen->copyPage(2, 0); - _screen->setCurPage(2); - - _screen->getPalette(2).clear(); - _screen->setScreenPalette(_screen->getPalette(2)); _screen->getPalette(0).fill(16, 1, 63); _screen->fadePalette(_screen->getPalette(0), 0x5A); + _screen->updateScreen(); const char *theEnd = "THE END"; - const int width = _screen->getTextWidth(theEnd); + const int width = _screen->getTextWidth(theEnd) + 1; int x = (320 - width) / 2 + 1; _screen->copyRegion(x, 8, x, 8, width, 56, 0, 2, Screen::CR_NO_P_CHECK); @@ -1351,7 +1358,6 @@ void KyraEngine_LoK::seq_playCreditsAmiga() { char *buffer = new char[size]; assert(buffer); memcpy(buffer, bufferTmp, size); - _staticres->unloadId(k1CreditsStrings); char stringBuffer[81]; memset(stringBuffer, 0, sizeof(stringBuffer)); @@ -1396,7 +1402,7 @@ void KyraEngine_LoK::seq_playCreditsAmiga() { _screen->printText(stringBuffer, x + 8, 0, 31, 0); - for (int i = 0; i < fontHeight; ++i) { + for (int i = 0; i < fontHeight && !shouldQuit(); ++i) { _screen->copyRegion(0, 141, 0, 140, 320, 59, 0, 0, Screen::CR_NO_P_CHECK); _screen->copyRegion(0, i, 0, 198, 320, 3, 2, 0, Screen::CR_NO_P_CHECK); _screen->updateScreen(); @@ -1414,8 +1420,10 @@ void KyraEngine_LoK::seq_playCreditsAmiga() { *specialString = 0; } - if (checkInput(0, false)) + if (checkInput(0, false)) { + removeInputTop(); break; + } } while (++cur != buffer + size && !shouldQuit()); delete[] buffer; diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index 5826b2b09e..ae23d130ef 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -89,8 +89,10 @@ int LoLEngine::processPrologue() { showIntro(); break; - case 2: // "Lore of the Lands" (only CD version) - break; + case 2: { // "Lore of the Lands" (only CD version) + HistoryPlayer history(this); + history.play(); + } break; case 3: // Load game if (_gui->runMenu(_gui->_loadMenu)) @@ -121,7 +123,8 @@ void LoLEngine::setupPrologueData(bool load) { static const char * const fileListCD[] = { "GENERAL.PAK", "INTROVOC.PAK", "STARTUP.PAK", "INTRO1.PAK", "INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "INTRO5.PAK", - "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK", 0 + "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK", + "HISTORY.PAK", 0 }; static const char * const fileListFloppyExtracted[] = { @@ -683,6 +686,271 @@ void LoLEngine::showStarcraftLogo() { delete ci; } +// history player + +HistoryPlayer::HistoryPlayer(LoLEngine *vm) : _system(vm->_system), _vm(vm), _screen(vm->screen()) { + _x = _y = _width = _height = 0; + _frame = _fireFrame = 0; + _nextFireTime = 0; + + _wsa = new WSAMovie_v2(vm); + assert(_wsa); + _fireWsa = new WSAMovie_v2(vm); + assert(_fireWsa); +} + +HistoryPlayer::~HistoryPlayer() { + delete _wsa; + delete _fireWsa; +} + +void HistoryPlayer::play() { + int dataSize = 0; + const char *data = (const char *)_vm->staticres()->loadRawData(kLolHistory, dataSize); + + if (!data) + error("Could not load history data"); + + _screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT"); + + Palette pal(256); + pal.fill(0, 256, 0); + _screen->fadePalette(pal, 0x1E); + + _screen->loadBitmap("BACKGND.CPS", 8, 8, &pal); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 0, Screen::CR_NO_P_CHECK); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 2, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + _screen->fadePalette(pal, 0x82); + + _screen->copyRegion(_x, _y, _x, _y, _width, _height, 2, 0); + _screen->updateScreen(); + + pal.fill(0, 256, 0); + _screen->setFont(Screen::FID_9_FNT); + + char tempWsaFilename[16]; + char voiceFilename[13]; + // the 'a' *has* to be lowercase + strncpy(voiceFilename, "PS_1a", sizeof(voiceFilename)); + + int part = 0; + Sound *sound = _vm->sound(); + + Common::Functor0Mem<void, HistoryPlayer> palFade(this, &HistoryPlayer::updateFire); + + for (; voiceFilename[3] <= '9' && !_vm->shouldQuit() && !_vm->skipFlag(); ++voiceFilename[3], voiceFilename[4] = 'a') { + while (!_vm->shouldQuit() && !_vm->skipFlag()) { + if (!sound->voiceFileIsPresent(voiceFilename)) + break; + + if (data[part * 15] == voiceFilename[3] && data[part * 15 + 1] == voiceFilename[4]) { + switch (part) { + case 0: + loadWsa(&data[part * 15 + 2]); + playWsa(true); + sound->voicePlay(voiceFilename); + break; + + case 1: case 2: case 8: + case 16: case 25: + sound->voicePlay(voiceFilename); + playWsa(true); + break; + + case 3: case 7: case 10: + case 17: case 23: case 26: + sound->voicePlay(voiceFilename); + playWsa(true); + restoreWsaBkgd(); + loadWsa(&data[part * 15 + 2]); + playWsa(true); + break; + + case 6: + sound->voicePlay(voiceFilename); + playWsa(false); + restoreWsaBkgd(); + loadWsa(&data[part * 15 + 2]); + playWsa(true); + _vm->delayWithTicks(30); + playWsa(true); + break; + + case 9: + sound->voicePlay(voiceFilename); + loadWsa(&data[part * 15 + 2]); + playWsa(true); + break; + + case 22: + playWsa(false); + restoreWsaBkgd(); + loadWsa(&data[part * 15 + 2]); + _vm->delayWithTicks(30); + sound->voicePlay(voiceFilename); + playWsa(true); + + strcpy(tempWsaFilename, &data[part * 15]); + + for (int i = 1; i < 4 && !_vm->shouldQuit(); ++i) { + uint32 nextTime = _system->getMillis() + 30 * _vm->tickLength(); + tempWsaFilename[8] = 'a' + i; + + loadWsa(&tempWsaFilename[2]); + _vm->delayUntil(nextTime); + + playWsa(true); + } + + tempWsaFilename[8] = 'e'; + loadWsa(&tempWsaFilename[2]); + break; + + case 29: + sound->voicePlay(voiceFilename); + playWsa(false); + restoreWsaBkgd(); + loadWsa(&data[part * 15 + 2]); + + _fireWsa->open("FIRE.WSA", 0, 0); + playWsa(true); + _fireFrame = 0; + + for (int i = 0; i < 12 && !_vm->shouldQuit(); ++i, ++_fireFrame) { + uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength(); + + if (_fireFrame > 4) + _fireFrame = 0; + + _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0); + _screen->updateScreen(); + _vm->delayUntil(nextTime); + } + + _screen->loadPalette("DRACPAL.PAL", pal); + _screen->fadePalette(pal, 0x78, &palFade); + + while (sound->voiceIsPlaying() && !_vm->shouldQuit()) { + uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength(); + + ++_fireFrame; + if (_fireFrame > 4) + _fireFrame = 0; + + _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0); + _screen->updateScreen(); + _vm->delayUntil(nextTime); + } + + _fireFrame = 0; + for (int i = 0; i < 10; ++i, ++_fireFrame) { + uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength(); + + if (_fireFrame > 4) + _fireFrame = 0; + + _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0); + _screen->updateScreen(); + _vm->delayUntil(nextTime); + } + + break; + + default: + sound->voicePlay(voiceFilename); + playWsa(false); + restoreWsaBkgd(); + loadWsa(&data[part * 15 + 2]); + playWsa(true); + break; + } + + ++part; + } else { + sound->voicePlay(voiceFilename); + } + + while (sound->voiceIsPlaying() && !_vm->shouldQuit() && !_vm->skipFlag()) + _vm->delay(10); + + if (_vm->skipFlag()) { + sound->voiceStop(); + _vm->resetSkipFlag(); + } + + ++voiceFilename[4]; + } + + if (_vm->skipFlag()) + _vm->resetSkipFlag(); + } + + if (_vm->skipFlag()) + _vm->resetSkipFlag(); + + pal.fill(0, 256, 63); + if (_fireWsa->opened()) + _screen->fadePalette(pal, 0x3C, &palFade); + else + _screen->fadePalette(pal, 0x3C); + + _screen->clearPage(0); + pal.fill(0, 256, 0); + _screen->fadePalette(pal, 0x3C); +} + +void HistoryPlayer::loadWsa(const char *filename) { + if (_wsa->opened()) + _wsa->close(); + + Palette pal(256); + if (!_wsa->open(filename, 3, &pal)) + error("Could not load WSA file: '%s'", filename); + _screen->setScreenPalette(pal); + + _x = _wsa->xAdd(); + _y = _wsa->yAdd(); + _width = _wsa->width(); + _height = _wsa->height(); + _frame = 1; +} + +void HistoryPlayer::playWsa(bool direction) { + const int tickLength = _vm->tickLength(); + + for (int i = 0; i < 15 && !_vm->shouldQuit(); ++i) { + uint32 nextTime = _system->getMillis() + 3 * tickLength; + + _wsa->displayFrame(_frame, 2, 0, 0, 0, 0, 0); + _screen->copyRegion(_x, _y, _x, _y, _width, _height, 2, 0); + _screen->updateScreen(); + _vm->delayUntil(nextTime); + + if (direction) + ++_frame; + else + --_frame; + } +} + +void HistoryPlayer::restoreWsaBkgd() { + _screen->copyRegion(_x, _y, _x, _y, _width, _height, 8, 0); + _screen->copyRegion(_x, _y, _x, _y, _width, _height, 8, 2); + _screen->updateScreen(); +} + +void HistoryPlayer::updateFire() { + if (_system->getMillis() > _nextFireTime) { + _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0); + _fireFrame = (_fireFrame + 1) % 5; + _nextFireTime = _system->getMillis() + 4 * _vm->tickLength(); + } + + _screen->updateScreen(); +} + // outro void LoLEngine::setupEpilogueData(bool load) { diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 4d42b1efb7..91945d91ee 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -235,10 +235,15 @@ namespace { // A simple wrapper to create VOC streams the way like creating MP3, OGG/Vorbis and FLAC streams. // Possible TODO: Think of making this complete and moving it to sound/voc.cpp ? Audio::AudioStream *makeVOCStream(Common::SeekableReadStream *stream, bool disposeAfterUse, uint32 startTime, uint32 duration, uint numLoops) { + +#ifdef STREAM_AUDIO_FROM_DISK + Audio::AudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED, 0, 0, disposeAfterUse); +#else Audio::AudioStream *as = Audio::makeVOCStream(*stream, Audio::Mixer::FLAG_UNSIGNED); if (disposeAfterUse) delete stream; +#endif return as; } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index e33d24bf59..51288f31df 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 49 +#define RESFILE_VERSION 50 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -444,16 +444,18 @@ bool StaticResource::init() { { kLolButtonList7, kLolRawDataBe16, "BUTTON7.LST" }, { kLolButtonList8, kLolRawDataBe16, "BUTTON84.LST" }, - { lolLegendData, kRawData, "MAPLGND.DEF" }, - { lolMapCursorOvl, kRawData, "MAPCURSOR.PAL" }, - { lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" }, - //{ lolMapPal, kRawData, "MAP.PAL" }, + { kLolLegendData, kRawData, "MAPLGND.DEF" }, + { kLolMapCursorOvl, kRawData, "MAPCURSOR.PAL" }, + { kLolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" }, + //{ kLolMapPal, kRawData, "MAP.PAL" }, - { lolSpellbookAnim, kRawData, "MBOOKA.DEF" }, - { lolSpellbookCoords, kRawData, "MBOOKC.DEF" }, - { lolHealShapeFrames, kRawData, "MHEAL.SHP" }, - { lolLightningDefs, kRawData, "MLGHTNG.DEF" }, - { lolFireballCoords, kLolRawDataBe16, "MFIREBLL.DEF" }, + { kLolSpellbookAnim, kRawData, "MBOOKA.DEF" }, + { kLolSpellbookCoords, kRawData, "MBOOKC.DEF" }, + { kLolHealShapeFrames, kRawData, "MHEAL.SHP" }, + { kLolLightningDefs, kRawData, "MLGHTNG.DEF" }, + { kLolFireballCoords, kLolRawDataBe16, "MFIREBLL.DEF" }, + + { kLolHistory, kRawData, "HISTORY.FLS" }, { 0, 0, 0 } }; @@ -589,6 +591,7 @@ void StaticResource::unloadId(int id) { if (pos->id == id || id == -1) { const FileType *filetype = getFiletype(pos->type); (this->*(filetype->free))(pos->data, pos->size); + pos = _resList.erase(pos); if (id != -1) break; } @@ -1874,10 +1877,10 @@ void LoLEngine::initStaticResource() { _buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, _buttonList7Size); _buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, _buttonList8Size); - _autoMapStrings = _staticres->loadRawDataBe16(lolMapStringId, _autoMapStringsSize); + _autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, _autoMapStringsSize); int tmpSize = 0; - const uint8 *tmp = _staticres->loadRawData(lolLegendData, tmpSize); + const uint8 *tmp = _staticres->loadRawData(kLolLegendData, tmpSize); tmpSize /= 5; if (tmp) { _defaultLegendData = new MapLegendData[tmpSize]; @@ -1888,19 +1891,19 @@ void LoLEngine::initStaticResource() { _defaultLegendData[i].stringId = READ_LE_UINT16(tmp); tmp += 2; } - _staticres->unloadId(lolLegendData); + _staticres->unloadId(kLolLegendData); } - tmp = _staticres->loadRawData(lolMapCursorOvl, tmpSize); + tmp = _staticres->loadRawData(kLolMapCursorOvl, tmpSize); _mapCursorOverlay = new uint8[tmpSize]; memcpy(_mapCursorOverlay, tmp, tmpSize); - _staticres->unloadId(lolMapCursorOvl); + _staticres->unloadId(kLolMapCursorOvl); - _updateSpellBookCoords = _staticres->loadRawData(lolSpellbookCoords, _updateSpellBookCoordsSize); - _updateSpellBookAnimData = _staticres->loadRawData(lolSpellbookAnim, _updateSpellBookAnimDataSize); - _healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize); + _updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, _updateSpellBookCoordsSize); + _updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, _updateSpellBookAnimDataSize); + _healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, _healShapeFramesSize); - tmp = _staticres->loadRawData(lolLightningDefs, tmpSize); + tmp = _staticres->loadRawData(kLolLightningDefs, tmpSize); if (tmp) { _lightningProps = new LightningProperty[5]; for (int i = 0; i < 5; i++) { @@ -1908,10 +1911,10 @@ void LoLEngine::initStaticResource() { _lightningProps[i].frameDiv = tmp[(i << 2) + 1]; _lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]); } - _staticres->unloadId(lolLightningDefs); + _staticres->unloadId(kLolLightningDefs); } - _fireBallCoords = (const int16*)_staticres->loadRawDataBe16(lolFireballCoords, _fireBallCoordsSize); + _fireBallCoords = (const int16*)_staticres->loadRawDataBe16(kLolFireballCoords, _fireBallCoordsSize); _buttonCallbacks.clear(); _buttonCallbacks.reserve(95); |