diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp index 0b14946bfff..a4d86656a92 100644 --- a/kyra/kyra.cpp +++ b/kyra/kyra.cpp @@ -899,7 +899,7 @@ void KyraEngine::seq_intro() { if (_features & GF_TALKIE) { _res->unloadPakFile("INTRO.VRM"); } - res_unloadResources(RES_INTRO); + res_unloadResources(RES_INTRO | RES_OUTRO); } void KyraEngine::seq_introLogos() { @@ -1616,7 +1616,7 @@ int KyraEngine::seq_playEnd() { } delete _finalA; _finalA = 0; - // XXX play end sequence here + seq_playEnding(); return 1; } } else { @@ -1644,6 +1644,50 @@ void KyraEngine::seq_brandonToStone() { _screen->showMouse(); } +void KyraEngine::seq_playEnding() { + debug(9, "KyraEngine::seq_playEnding()"); + _screen->hideMouse(); + res_unloadResources(RES_INGAME); + res_loadResources(RES_OUTRO); + loadBitmap("REUNION.CPS", 3, 3, _screen->_currentPalette); + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + _screen->_curPage = 0; + // XXX + assert(_homeString); + drawSentenceCommand(_homeString[0], 179); + _screen->_curPage = 0; + _screen->fadeToBlack(); + _seq->playSequence(_seq_Reunion, false); + _screen->fadeToBlack(); + _screen->showMouse(); + seq_playCredits(); +} + +void KyraEngine::seq_playCredits() { + debug(9, "KyraEngine::seq_playCredits()"); + static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + _screen->hideMouse(); + uint32 sz = 0; + if (_features & GF_FLOPPY) { + _screen->loadFont(Screen::FID_CRED6_FNT, _res->fileData("CREDIT6.FNT", &sz)); + _screen->loadFont(Screen::FID_CRED8_FNT, _res->fileData("CREDIT8.FNT", &sz)); + } + loadBitmap("CHALET.CPS", 2, 2, _screen->_currentPalette); + _screen->setScreenPalette(_screen->_currentPalette); + _screen->setCurPage(0); + _screen->clearCurPage(); + _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); + _screen->setTextColorMap(colorMap); + _screen->_charWidth = -1; + // delete + _screen->updateScreen(); + // XXX + waitTicks(120); // wait until user presses escape normally + _screen->fadeToBlack(); + _screen->clearCurPage(); + _screen->showMouse(); +} + bool KyraEngine::seq_skipSequence() const { debug(9, "KyraEngine::seq_skipSequence()"); return _quitFlag || _abortIntroFlag; @@ -4673,8 +4717,8 @@ int KyraEngine::handleMalcolmFlag() { if (!_beadStateVar) { handleBeadState(); _screen->bitBlitRects(); - //assert(_veryClever); - //_text->printTalkTextMessage(_veryClever, 60, 31, 5, 0, 2); + assert(_veryClever); + _text->printTalkTextMessage(_veryClever[0], 60, 31, 5, 0, 2); timer2 = _system->getMillis() + 180 * _tickLength; _malcolmFlag = 11; } diff --git a/kyra/kyra.h b/kyra/kyra.h index db963c77a4f..e4d64861b92 100644 --- a/kyra/kyra.h +++ b/kyra/kyra.h @@ -530,7 +530,9 @@ protected: void seq_playDrinkPotionAnim(int unk1, int unk2, int flags); int seq_playEnd(); void seq_brandonToStone(); - + void seq_playEnding(); + void seq_playCredits(); + void snd_startTrack(); void snd_haltTrack(); void snd_setSoundEffectFile(int file); @@ -541,7 +543,8 @@ protected: enum { RES_ALL = 0, RES_INTRO = (1 << 0), - RES_INGAME = (1 << 1) + RES_INGAME = (1 << 1), + RES_OUTRO = (1 << 2) }; void res_loadResources(int type = RES_ALL); @@ -749,6 +752,7 @@ protected: uint8 *_seq_Demo2; uint8 *_seq_Demo3; uint8 *_seq_Demo4; + uint8 *_seq_Reunion; char **_seq_WSATable; char **_seq_CPSTable; @@ -776,6 +780,8 @@ protected: char **_magicJewelString; char **_flaskFull; char **_fullFlask; + char **_veryClever; + char **_homeString; int _itemList_Size; int _takenList_Size; @@ -793,6 +799,8 @@ protected: int _magicJewelString_Size; int _flaskFull_Size; int _fullFlask_Size; + int _veryClever_Size; + int _homeString_Size; char **_characterImageTable; int _characterImageTableSize; diff --git a/kyra/screen.cpp b/kyra/screen.cpp index 392c17d793f..14f4bfb5161 100644 --- a/kyra/screen.cpp +++ b/kyra/screen.cpp @@ -235,8 +235,18 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { debug(9, "Screen::copyToPage0(%d, %d, %d, 0x%X)", y, h, page, seqBuf); assert(y + h <= SCREEN_H); const uint8 *src = getPagePtr(page) + y * SCREEN_W; - memcpy(seqBuf, src, h * SCREEN_W); - memcpy(getPagePtr(0) + y * SCREEN_W, src, h * SCREEN_W); + uint8 *dstPage = getPagePtr(0) + y * SCREEN_W; + for (int i = 0; i < h; ++i) { + for (int x = 0; x < SCREEN_W; ++x) { + if (seqBuf[x] != src[x]) { + seqBuf[x] = src[x]; + dstPage[x] = src[x]; + } + } + src += SCREEN_W; + seqBuf += SCREEN_W; + dstPage += SCREEN_W; + } } void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) { diff --git a/kyra/screen.h b/kyra/screen.h index c94bacbb7a0..a59a61f4b84 100644 --- a/kyra/screen.h +++ b/kyra/screen.h @@ -78,6 +78,8 @@ public: enum FontId { FID_6_FNT = 0, FID_8_FNT, + FID_CRED6_FNT, + FID_CRED8_FNT, FID_NUM }; @@ -143,6 +145,8 @@ public: uint8 *_currentPalette; uint8 *_shapePages[2]; + const ScreenDim *_curDim; + static const ScreenDim _screenDimTable[]; static const int _screenDimTableCount; private: @@ -155,7 +159,6 @@ private: uint8 *_pagePtrs[16]; uint8 *_screenPalette; uint8 *_palettes[3]; - const ScreenDim *_curDim; FontId _currentFont; Font _fonts[FID_NUM]; uint8 _textColorsMap[16]; diff --git a/kyra/seqplayer.cpp b/kyra/seqplayer.cpp index 71be508b912..3f7cca9f933 100755 --- a/kyra/seqplayer.cpp +++ b/kyra/seqplayer.cpp @@ -46,6 +46,7 @@ SeqPlayer::SeqPlayer(KyraEngine* vm, OSystem* system) { _res = vm->resource(); _copyViewOffs = false; + _specialBuffer = 0; for (int i = 0; i < ARRAYSIZE(_handShapes); ++i) _handShapes[i] = 0; @@ -180,6 +181,9 @@ void SeqPlayer::s1_copyWaitTicks() { void SeqPlayer::s1_shuffleScreen() { _screen->shuffleScreen(0, 16, 320, 128, 2, 0, 0, false); _screen->_curPage = 2; + if (_specialBuffer) + _screen->copyCurPageBlock(0, 16, 40, 128, _specialBuffer); + _screen->_curPage = 0; } void SeqPlayer::s1_copyView() { @@ -187,7 +191,11 @@ void SeqPlayer::s1_copyView() { if (!_copyViewOffs) { y -= 8; } - _screen->copyRegion(0, 16, 0, 16, 320, y, 2, 0); + if (_specialBuffer) { + _screen->copyToPage0(16, y, 3, _specialBuffer); + } else { + _screen->copyRegion(0, 16, 0, 16, 320, y, 2, 0); + } } void SeqPlayer::s1_loopInit() { @@ -262,7 +270,7 @@ void SeqPlayer::s1_printTalkText() { uint8 fillColor = *_seqData++; int b; if (_seqTalkTextPrinted && !_seqTalkTextRestored) { - if (_seqWsaCurDecodePage != 0) { + if (_seqWsaCurDecodePage != 0 && !_specialBuffer) { b = 2; } else { b = 0; @@ -271,7 +279,7 @@ void SeqPlayer::s1_printTalkText() { } _seqTalkTextPrinted = true; _seqTalkTextRestored = false; - if (_seqWsaCurDecodePage != 0) { + if (_seqWsaCurDecodePage != 0 && !_specialBuffer) { b = 2; } else { b = 0; @@ -282,7 +290,7 @@ void SeqPlayer::s1_printTalkText() { void SeqPlayer::s1_restoreTalkText() { if (_seqTalkTextPrinted && !_seqTalkTextRestored) { int b; - if (_seqWsaCurDecodePage != 0) { + if (_seqWsaCurDecodePage != 0 && !_specialBuffer) { b = 2; } else { b = 0; @@ -409,7 +417,14 @@ void SeqPlayer::s1_allocTempBuffer() { if (_vm->features() & GF_DEMO) { _seqQuitFlag = true; } else { - // allocate offscreen buffer, not needed + if (!_specialBuffer) { + _specialBuffer = new uint8[40960]; + assert(_specialBuffer); + int page = _screen->_curPage; + _screen->_curPage = 0; + _screen->copyCurPageBlock(0, 0, 320, 128, _specialBuffer); + _screen->_curPage = page; + } } } @@ -425,8 +440,8 @@ void SeqPlayer::s1_endOfScript() { _seqQuitFlag = true; } -void SeqPlayer::s1_miscUnk1() { - warning("STUB: s1_miscUnk1"); +void SeqPlayer::s1_loadIntroVRM() { + _res->loadPakFile("INTRO.VRM"); } void SeqPlayer::s1_playVocFile() { @@ -437,9 +452,8 @@ void SeqPlayer::s1_playVocFile() { _vm->snd_playVoiceFile(a); } -void SeqPlayer::s1_displayStory() { - // nothing to do here since we handle it in - // KyraEngine::seq_introStory +void SeqPlayer::s1_miscUnk3() { + warning("STUB: s1_miscUnk3"); } void SeqPlayer::s1_prefetchVocFile() { @@ -502,7 +516,7 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { SEQOP(2, s1_wsaPlayPrevFrame), SEQOP(5, s1_drawShape), SEQOP(3, s1_waitTicks), - SEQOP(3, s1_waitTicks), + SEQOP(3, s1_copyWaitTicks), // 0x08 SEQOP(3, s1_copyWaitTicks), SEQOP(1, s1_shuffleScreen), @@ -535,9 +549,9 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { SEQOP(1, s1_textDisplayDisable), // 0x20 SEQOP(1, s1_endOfScript), - SEQOP(1, s1_miscUnk1), + SEQOP(1, s1_loadIntroVRM), SEQOP(2, s1_playVocFile), - SEQOP(1, s1_displayStory), + SEQOP(1, s1_miscUnk3), // 0x24 SEQOP(2, s1_prefetchVocFile) }; @@ -618,6 +632,8 @@ bool SeqPlayer::playSequence(const uint8 *seqData, bool skipSeq) { _screen->updateScreen(); } + delete [] _specialBuffer; + _specialBuffer = 0; return seqSkippedFlag; } diff --git a/kyra/seqplayer.h b/kyra/seqplayer.h index cfc5a7222a0..102aca64b17 100755 --- a/kyra/seqplayer.h +++ b/kyra/seqplayer.h @@ -89,9 +89,9 @@ protected: void s1_textDisplayEnable(); void s1_textDisplayDisable(); void s1_endOfScript(); - void s1_miscUnk1(); + void s1_loadIntroVRM(); void s1_playVocFile(); - void s1_displayStory(); + void s1_miscUnk3(); void s1_prefetchVocFile(); struct SeqMovie { @@ -103,6 +103,7 @@ protected: }; const uint8 *_seqData; + uint8 *_specialBuffer; SeqMovie _seqMovies[12]; SeqLoop _seqLoopTable[20]; uint16 _seqWsaCurDecodePage; diff --git a/kyra/staticres.cpp b/kyra/staticres.cpp index 791721cc759..2b846dcf3bd 100644 --- a/kyra/staticres.cpp +++ b/kyra/staticres.cpp @@ -26,7 +26,7 @@ namespace Kyra { -#define RESFILE_VERSION 10 +#define RESFILE_VERSION 11 #define GAME_FLAGS (GF_FLOPPY | GF_TALKIE | GF_DEMO | GF_AUDIOCD) #define LANGUAGE_FLAGS (GF_ENGLISH | GF_FRENCH | GF_GERMAN | GF_SPANISH | GF_LNGUNK) @@ -163,7 +163,7 @@ void KyraEngine::res_loadResources(int type) { } - if ((type & RES_INTRO) || type == RES_ALL) { + if ((type & RES_INTRO) || (type & RES_OUTRO) || type == RES_ALL) { loadRawFile(resFile, "FOREST.SEQ", _seq_Forest); loadRawFile(resFile, "KALLAK-WRITING.SEQ", _seq_KallakWriting); loadRawFile(resFile, "KYRANDIA-LOGO.SEQ", _seq_KyrandiaLogo); @@ -180,6 +180,10 @@ void KyraEngine::res_loadResources(int type) { loadTable(resFile, "INTRO-WSA.TXT", (byte***)&_seq_WSATable, &_seq_WSATable_Size); res_loadLangTable("INTRO-STRINGS.", &resFile, (byte***)&_seq_textsTable, &_seq_textsTable_Size, loadNativeLanguage); + + loadRawFile(resFile, "REUNION.SEQ", _seq_Reunion); + + res_loadLangTable("HOME.", &resFile, (byte***)&_homeString, &_homeString_Size, loadNativeLanguage); } if ((type & RES_INGAME) || type == RES_ALL) { @@ -241,6 +245,8 @@ void KyraEngine::res_loadResources(int type) { res_loadLangTable("FLASKFULL.", &resFile, (byte***)&_flaskFull, &_fullFlask_Size, loadNativeLanguage); res_loadLangTable("FULLFLASK.", &resFile, (byte***)&_fullFlask, &_fullFlask_Size, loadNativeLanguage); + + res_loadLangTable("VERYCLEVER.", &resFile, (byte***)&_veryClever, &_veryClever_Size, loadNativeLanguage); } #undef loadRooms @@ -251,7 +257,7 @@ void KyraEngine::res_loadResources(int type) { void KyraEngine::res_unloadResources(int type) { debug(9, "res_unloadResources(%d)", type); - if ((type & RES_INTRO) || type == RES_ALL) { + if ((type & RES_INTRO) || (type & RES_OUTRO) || type == RES_ALL) { res_freeLangTable(&_seq_WSATable, &_seq_WSATable_Size); res_freeLangTable(&_seq_CPSTable, &_seq_CPSTable_Size); res_freeLangTable(&_seq_COLTable, &_seq_COLTable_Size); @@ -267,6 +273,9 @@ void KyraEngine::res_unloadResources(int type) { delete [] _seq_Demo2; _seq_Demo2 = 0; delete [] _seq_Demo3; _seq_Demo3 = 0; delete [] _seq_Demo4; _seq_Demo4 = 0; + + delete [] _seq_Reunion; _seq_Reunion = 0; + res_freeLangTable(&_homeString, &_homeString_Size); } if ((type & RES_INGAME) || type == RES_ALL) { @@ -350,6 +359,8 @@ void KyraEngine::res_unloadResources(int type) { res_freeLangTable(&_flaskFull, &_flaskFull_Size); res_freeLangTable(&_fullFlask, &_fullFlask_Size); + + res_freeLangTable(&_veryClever, &_veryClever_Size); } } diff --git a/kyra/wsamovie.cpp b/kyra/wsamovie.cpp index 8c8141b9931..46b225c71b3 100644 --- a/kyra/wsamovie.cpp +++ b/kyra/wsamovie.cpp @@ -36,7 +36,8 @@ void WSAMovieV1::open(const char *filename, int offscreenDecode, uint8 *palBuf) uint32 flags = 0; uint32 fileSize; uint8 *p = _vm->resource()->fileData(filename, &fileSize); - assert(p); + if (!p) + return; const uint8 *wsaData = p; _numFrames = READ_LE_UINT16(wsaData); wsaData += 2;