diff options
author | athrxx | 2019-12-05 22:47:07 +0100 |
---|---|---|
committer | athrxx | 2019-12-18 20:50:46 +0100 |
commit | f01d432c2529e2a47dcbc2438356b00706b41b68 (patch) | |
tree | 39982b89db66605de53e6a6e78c2058cfb070ef5 | |
parent | fde59250370cb4c1550621a33bf2b5c449e2bcdb (diff) | |
download | scummvm-rg350-f01d432c2529e2a47dcbc2438356b00706b41b68.tar.gz scummvm-rg350-f01d432c2529e2a47dcbc2438356b00706b41b68.tar.bz2 scummvm-rg350-f01d432c2529e2a47dcbc2438356b00706b41b68.zip |
KYRA: (EOB/PC98) - implement ending sequence
(The PC-98 version has its own unique ending sequence)
-rw-r--r-- | engines/kyra/engine/eob.cpp | 1 | ||||
-rw-r--r-- | engines/kyra/engine/eob.h | 2 | ||||
-rw-r--r-- | engines/kyra/engine/eobcommon.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/graphics/screen.cpp | 1 | ||||
-rw-r--r-- | engines/kyra/graphics/screen_eob.cpp | 62 | ||||
-rw-r--r-- | engines/kyra/graphics/screen_eob.h | 11 | ||||
-rw-r--r-- | engines/kyra/sequence/sequences_eob.cpp | 576 |
7 files changed, 636 insertions, 21 deletions
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp index bb8627fb04..cdd49a75fd 100644 --- a/engines/kyra/engine/eob.cpp +++ b/engines/kyra/engine/eob.cpp @@ -46,6 +46,7 @@ EoBEngine::EoBEngine(OSystem *system, const GameFlags &flags) _dscDoorCoordsExt = 0; _useMainMenuGUISettings = false; _ttlCfg = 0; + _xdth = false; } EoBEngine::~EoBEngine() { diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h index 174f9b9c7a..5b06e30f95 100644 --- a/engines/kyra/engine/eob.h +++ b/engines/kyra/engine/eob.h @@ -33,6 +33,7 @@ class EoBEngine : public EoBCoreEngine { friend class GUI_EoB; friend class EoBSeqPlayerCommon; friend class EoBIntroPlayer; +friend class EoBPC98FinalePlayer; friend class EoBAmigaFinalePlayer; public: EoBEngine(OSystem *system, const GameFlags &flags); @@ -86,6 +87,7 @@ private: void seq_xdeath(); const char *const *_finBonusStrings; + bool _xdth; // characters void drawNpcScene(int npcIndex); diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp index 7e180ca8cc..729e59b749 100644 --- a/engines/kyra/engine/eobcommon.cpp +++ b/engines/kyra/engine/eobcommon.cpp @@ -425,7 +425,7 @@ Common::Error EoBCoreEngine::init() { assert(_sound); _sound->init(); - // This if for EOB1 / PC98 only + // This if for EOB1 PC-98 only _sound->loadSfxFile("EFECT.OBJ"); // Setup volume settings (and read in all ConfigManager settings) @@ -450,7 +450,7 @@ Common::Error EoBCoreEngine::init() { assert(_inf); _debugger = new Debugger_EoB(this); assert(_debugger); - + if (_flags.platform == Common::kPlatformAmiga) { if (_res->exists("EOBF6.FONT")) _screen->loadFont(Screen::FID_6_FNT, "EOBF6.FONT"); diff --git a/engines/kyra/graphics/screen.cpp b/engines/kyra/graphics/screen.cpp index dd22507c3e..cd8f9404cc 100644 --- a/engines/kyra/graphics/screen.cpp +++ b/engines/kyra/graphics/screen.cpp @@ -178,6 +178,7 @@ bool Screen::init() { } if (_vm->game() == GI_EOB2 && _vm->gameFlags().platform == Common::kPlatformFMTowns) { + assert(_fonts[FID_SJIS_FNT]); _fonts[FID_SJIS_FNT]->setStyle(Font::kFSFat); _fonts[FID_SJIS_LARGE_FNT] = new SJISFontLarge(font); } diff --git a/engines/kyra/graphics/screen_eob.cpp b/engines/kyra/graphics/screen_eob.cpp index 371b673760..dd794e2fb6 100644 --- a/engines/kyra/graphics/screen_eob.cpp +++ b/engines/kyra/graphics/screen_eob.cpp @@ -63,8 +63,9 @@ Screen_EoB::Screen_EoB(EoBCoreEngine *vm, OSystem *system) : Screen(vm, system, _cgaMappingDefault = 0; _cgaDitheringTables[0] = _cgaDitheringTables[1] = 0; _useHiResEGADithering = _dualPaletteMode = false; - _decodeTempBuffer = 0; + _cyclePalette = 0; _cpsFilePattern = "%s."; + _activePalCycle = 0; for (int i = 0; i < 10; ++i) _palette16c[i] = 0; } @@ -78,7 +79,7 @@ Screen_EoB::~Screen_EoB() { delete[] _egaDitheringTempPage; delete[] _cgaDitheringTables[0]; delete[] _cgaDitheringTables[1]; - delete[] _decodeTempBuffer; + delete[] _cyclePalette; } bool Screen_EoB::init() { @@ -125,7 +126,8 @@ bool Screen_EoB::init() { int ci = 0; if (_vm->game() == GI_EOB1) { if (_vm->gameFlags().platform == Common::kPlatformPC98) { - _decodeTempBuffer = new uint8[2048]; + _cyclePalette = new uint8[48]; + memset(_cyclePalette, 0, 48); ci = 3; } else if (_renderMode == Common::kRenderEGA || _renderMode == Common::kRenderCGA) { ci = 1; @@ -246,8 +248,10 @@ void Screen_EoB::printShadedText(const char *string, int x, int y, int col1, int fillRect(x, y, x + getTextWidth(string) - 1, y + getFontHeight() - 1, col2); } - if (_vm->gameFlags().use16ColorMode) + if (_vm->gameFlags().use16ColorMode) { + assert(_fonts[_currentFont]); _fonts[_currentFont]->setStyle(Font::kFSLeftShadow); + } printText(string, x, y, col1, 0); @@ -268,7 +272,7 @@ void Screen_EoB::loadBitmap(const char *filename, int tempPage, int dstPage, Pal str->skip(2); uint16 imgSize = str->readUint16LE(); assert(imgSize == str->size() - 4); - uint8 *buf = new uint8[SCREEN_W * SCREEN_H]; + uint8 *buf = new uint8[MAX<uint16>(imgSize, SCREEN_W * SCREEN_H)]; str->read(buf, imgSize); delete str; @@ -1594,7 +1598,7 @@ void Screen_EoB::selectPC98Palette(int paletteIndex, Palette &dest, int brightne void Screen_EoB::decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize) { const uint8 *end = src + inSize; - memset(_decodeTempBuffer, 0, 2048); + memset(_dsTempPage, 0, 2048); int tmpDstOffs = 0; while (src < end) { @@ -1608,12 +1612,12 @@ void Screen_EoB::decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize) { const uint8 *tmpSrc2 = dst; for (int len2 = len; len2; len2--) { - *dst++ = _decodeTempBuffer[tmpSrcOffs++]; + *dst++ = _dsTempPage[tmpSrcOffs++]; tmpSrcOffs &= 0x7FF; } while (len--) { - _decodeTempBuffer[tmpDstOffs++] = *tmpSrc2++; + _dsTempPage[tmpDstOffs++] = *tmpSrc2++; tmpDstOffs &= 0x7FF; } @@ -1626,14 +1630,14 @@ void Screen_EoB::decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize) { int planes = ((code >> 3) & 3) + 1; while (len--) { for (int i = 0; i < planes; ++i) { - *dst++ = _decodeTempBuffer[tmpDstOffs++] = src[i]; + *dst++ = _dsTempPage[tmpDstOffs++] = src[i]; tmpDstOffs &= 0x7FF; } } src += planes; } else { for (int len = (code & 0x3F) + 1; len; len--) { - *dst++ = _decodeTempBuffer[tmpDstOffs++] = *src++; + *dst++ = _dsTempPage[tmpDstOffs++] = *src++; tmpDstOffs &= 0x7FF; } } @@ -1664,6 +1668,44 @@ void Screen_EoB::decodePC98PlanarBitmap(uint8 *srcDstBuffer, uint8 *tmpBuffer, u } } +void Screen_EoB::initPC98PaletteCycle(int paletteIndex, PalCycleData *data) { + if (!_use16ColorMode || !_cyclePalette) + return; + + _activePalCycle = data; + + if (data) + memcpy(_cyclePalette, _palette16c[paletteIndex], 48); + else + memset(_cyclePalette, 0, 48); +} + +void Screen_EoB::updatePC98PaletteCycle(int brightness) { + if (_activePalCycle) { + for (int i = 0; i < 48; ++i) { + if (--_activePalCycle[i].delay) + continue; + for (int8 in = 32; in == 32; ) { + in = *_activePalCycle[i].data++; + if (in < 16 && in > -16) { + _cyclePalette[i] += in; + _activePalCycle[i].delay = *_activePalCycle[i].data++; + } else if (in < 32) { + _cyclePalette[i] = in - 16; + _activePalCycle[i].delay = *_activePalCycle[i].data++; + } else if (in == 32) + _activePalCycle[i].data += READ_BE_INT16(_activePalCycle[i].data); + } + } + } + + uint8 pal[48]; + for (int i = 0; i < 48; ++i) + pal[i] = CLIP<int>(_cyclePalette[i] + brightness, 0, 15); + loadPalette(pal, *_palettes[0], 48); + setScreenPalette(*_palettes[0]); +} + static uint32 _decodeFrameAmiga_x = 0; bool decodeFrameAmiga_readNextBit(const uint8 *&data, uint32 &code, uint32 &chk) { diff --git a/engines/kyra/graphics/screen_eob.h b/engines/kyra/graphics/screen_eob.h index 9c6e17caad..2b0622c679 100644 --- a/engines/kyra/graphics/screen_eob.h +++ b/engines/kyra/graphics/screen_eob.h @@ -95,7 +95,16 @@ public: void decodeBIN(const uint8 *src, uint8 *dst, uint16 inSize); void decodePC98PlanarBitmap(uint8 *srcDstBuffer, uint8 *tmpBuffer, uint16 size = 64000); - uint8 *_decodeTempBuffer; + struct PalCycleData { + const int8 *data; + uint8 delay; + }; + + void initPC98PaletteCycle(int paletteIndex, PalCycleData *data); + void updatePC98PaletteCycle(int brightness); + + PalCycleData *_activePalCycle; + uint8 *_cyclePalette; // Amiga specific void loadSpecialAmigaCPS(const char *fileName, int destPage, bool isGraphics); diff --git a/engines/kyra/sequence/sequences_eob.cpp b/engines/kyra/sequence/sequences_eob.cpp index 8bfc393894..6754d364e7 100644 --- a/engines/kyra/sequence/sequences_eob.cpp +++ b/engines/kyra/sequence/sequences_eob.cpp @@ -36,19 +36,26 @@ namespace Kyra { class EoBSeqPlayerCommon { public: EoBSeqPlayerCommon(EoBEngine *vm, Screen_EoB *screen); - virtual ~EoBSeqPlayerCommon() {} + virtual ~EoBSeqPlayerCommon(); protected: void boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH, int fillColor = -1); void printSubtitle(const char *str, int textmodeX, int textmodeY, int col, int mode = 0); + void releaseShapes(); + void clearTextField(); const uint8 _fillColor1; const uint8 _fillColor2; + uint8 **_shapes; + EoBEngine *_vm; Screen_EoB *_screen; + const uint8 _tickLength; private: + virtual void wait(uint32 ticks) { _vm->delay(ticks * _tickLength); } + Common::Array<Common::Rect> _textFields; uint8 _textColor; }; @@ -109,6 +116,48 @@ private: const uint8 *_tvlH; }; +class EoBPC98FinalePlayer : public EoBSeqPlayerCommon { +public: + EoBPC98FinalePlayer(EoBEngine *vm, Screen_EoB *screen); + virtual ~EoBPC98FinalePlayer(); + + void start(bool xdt); + +private: + void beholder(bool xdt); + void teleport(); + void king(); + void inspection(); + void congratulation(); + void credits(); + void bonus(); + + template<int brStart, int brEnd, int inc> void pc98FadePalette(int palId, uint32 del); + void fadeToBlack(int palId, uint32 delay) { pc98FadePalette<0, -16, -1>(palId, delay); } + void fadeFromBlack(int palId, uint32 delay) { pc98FadePalette<-15, 1, 1>(palId, delay); } + void fadeToWhite(int palId, uint32 delay) { pc98FadePalette<0, 16, 1>(palId, delay); } + void fadeFromWhite(int palId, uint32 delay) { pc98FadePalette<15, -1, -1>(palId, delay); } + + void startPaletteCycle(int palId, int style); + void stopPaletteCycle(); + void resetPaletteCycle(); + + virtual void wait(uint32 millis); + + const char *const *_strings; + const uint8 *_eyesAnimData; + const int16 *_handsAnimData; + const int16 *_handsAnimData2; + const int8 *_handsAnimData3; + const uint8 *_creditsStrings; + const uint8 *_creditsCharWdth; + + bool _updatePalCycle; + Screen_EoB::PalCycleData *_palCycleType1, *_palCycleType2; + const uint8 _palCycleDelay; +}; + + class EoBAmigaFinalePlayer : public EoBSeqPlayerCommon { public: EoBAmigaFinalePlayer(EoBEngine *vm, Screen_EoB *screen); @@ -142,7 +191,14 @@ private: EoBSeqPlayerCommon::EoBSeqPlayerCommon(EoBEngine *vm, Screen_EoB *screen) : _vm(vm), _screen(screen), _textColor(0xE1), _fillColor1(vm->gameFlags().platform == Common::kPlatformAmiga ? 19 : (vm->gameFlags().platform == Common::kPlatformPC98 ? 0 : 12)), - _fillColor2(vm->gameFlags().platform == Common::kPlatformAmiga ? 10 : 157) { + _fillColor2(vm->gameFlags().platform == Common::kPlatformAmiga ? 10 : 157), _tickLength(16) { + _shapes = new uint8*[64]; + memset(_shapes, 0, 64 * sizeof(uint8*)); +} + +EoBSeqPlayerCommon::~EoBSeqPlayerCommon() { + releaseShapes(); + delete[] _shapes; } void EoBSeqPlayerCommon::boxMorphTransition(int targetDestX, int targetDestY, int targetFinalX, int targetFinalY, int targetSrcX, int targetSrcY, int targetFinalW, int targetFinalH, int originX1, int originY1, int originW, int originH, int fillColor) { @@ -221,6 +277,9 @@ void EoBSeqPlayerCommon::printSubtitle(const char *str, int textmodeX, int textm Screen::FontId of = _screen->setFont(Screen::FID_SJIS_TEXTMODE_FNT); int cp = _screen->setCurPage(0); + int x1 = textmodeX << 2; + int y1 = textmodeY << 3; + for (int i = 0; str[i] &&!_vm->shouldQuit() && !_vm->skipFlag(); ) { uint8 c = str[i++]; if (c == 13) { @@ -229,8 +288,11 @@ void EoBSeqPlayerCommon::printSubtitle(const char *str, int textmodeX, int textm } else if (c == 10) { _textColor = str[i++]; } else if (c == 7) { - _vm->delay(960); - _screen->fillRect(0, 160, 319, 199, _fillColor1, 0); + wait(120); + int x22 = ((textmodeX << 2) + (curX << 3)) + _screen->getFontWidth() - 1; + int y22 = (textmodeY << 3) + _screen->getFontHeight() - 1; + _textFields.push_back(Common::Rect(x1, y1, x22, y22)); + clearTextField(); curX = 0; } @@ -245,20 +307,40 @@ void EoBSeqPlayerCommon::printSubtitle(const char *str, int textmodeX, int textm } if (mode == 0) { - _vm->_system->delayMillis(40); + wait(5); _screen->updateScreen(); } else if (mode == 1) { - _vm->delay(40); + wait(5); _screen->updateScreen(); } } + int x2 = ((textmodeX << 2) + (curX << 3)) + _screen->getFontWidth() - 1; + int y2 = (textmodeY << 3) + _screen->getFontHeight() - 1; + _textFields.push_back(Common::Rect(x1, y1, x2, y2)); + if (mode == 2) _screen->updateScreen(); _screen->setFont(of); _screen->setCurPage(cp); } +void EoBSeqPlayerCommon::releaseShapes() { + for (int i = 0; i < 64; ++i) { + delete[] _shapes[i]; + _shapes[i] = 0; + } +} +void EoBSeqPlayerCommon::clearTextField() { + for (Common::Array<Common::Rect>::iterator i = _textFields.begin(); i != _textFields.end(); ++i) + _screen->fillRect(i->left, i->top, i->right, i->bottom, 0); + _textFields.clear(); + + if (_vm->shouldQuit() || _vm->skipFlag()) + _screen->clearPage(0); + + _screen->updateScreen(); +} EoBIntroPlayer::EoBIntroPlayer(EoBEngine *vm, Screen_EoB *screen) : EoBSeqPlayerCommon(vm, screen) { int temp = 0; @@ -1105,7 +1187,7 @@ void EoBIntroPlayer::tunnel() { _screen->setCurPage(0); _screen->updateScreen(); - _vm->delay((_vm->gameFlags().platform == Common::kPlatformPC98 ? 130 : 50) * _vm->_tickLength); + _vm->delay(50 * _vm->_tickLength); } void EoBIntroPlayer::loadAndSetPalette(const char *dosPaletteFile, int pc98PaletteID) { @@ -1206,6 +1288,478 @@ void EoBIntroPlayer::whirlTransition() { } } +EoBPC98FinalePlayer::EoBPC98FinalePlayer(EoBEngine *vm, Screen_EoB *screen) : EoBSeqPlayerCommon(vm, screen), _palCycleDelay(16) { + int temp = 0; + _strings = _vm->staticres()->loadStrings(kEoB1FinaleStrings, temp); + _eyesAnimData = _vm->staticres()->loadRawData(kEoB1FinaleEyesAnim, temp); + _handsAnimData = (const int16*)_vm->staticres()->loadRawDataBe16(kEoB1FinaleHandsAnim, temp); + _handsAnimData2 = (const int16*)_vm->staticres()->loadRawDataBe16(kEoB1FinaleHandsAnim2, temp); + _handsAnimData3 = (const int8*)_vm->staticres()->loadRawData(kEoB1FinaleHandsAnim3, temp); + _creditsStrings = _vm->staticres()->loadRawData(kEoB1CreditsStrings, temp); + _creditsCharWdth = _vm->staticres()->loadRawData(kEoB1CreditsCharWdth, temp); + + _palCycleType1 = new Screen_EoB::PalCycleData[48]; + _palCycleType2 = new Screen_EoB::PalCycleData[48]; + _updatePalCycle = false; + + resetPaletteCycle(); +} + +EoBPC98FinalePlayer::~EoBPC98FinalePlayer() { + delete[] _palCycleType1; + delete[] _palCycleType2; +} + +void EoBPC98FinalePlayer::start(bool xdt) { + uint32 tick = _vm->_system->getMillis() + 60 * _vm->_tickLength; + _screen->hideMouse(); + + _screen->fadeToBlack(); + _screen->clearPage(2); + _screen->clearPage(0); + _screen->setScreenDim(0); + + _vm->delayUntil(tick); + _vm->_eventList.clear(); + _vm->_allowSkip = true; + + _vm->snd_playSong(1); + + beholder(xdt); + teleport(); + king(); + inspection(); + congratulation(); + credits(); + bonus(); + + while (!_vm->skipFlag() && !_vm->shouldQuit()) { + _vm->updateInput(); + _vm->delay(10); + } + + _vm->_allowSkip = false; + _vm->_eventList.clear(); + + _screen->fadeToBlack(); +} + +void EoBPC98FinalePlayer::beholder(bool xdt) { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + if (xdt) { + _screen->loadBitmap("END1.BIN", 3, 5, 0); + _screen->convertPage(5, 2, 0); + _screen->copyRegion(0, 0, 56, 0, 216, 200, 2, 0, Screen::CR_NO_P_CHECK); + startPaletteCycle(5, 0); + fadeFromBlack(5, 3); + printSubtitle(_strings[0], 8, 24, 225); + } else { + printSubtitle(_strings[1], 23, 10, 225); + printSubtitle(_strings[2], 15, 12, 225); + printSubtitle(_strings[3], 27, 14, 225); + } + + wait(150); + clearTextField(); + fadeToBlack(5, 3); + stopPaletteCycle(); +} + +void EoBPC98FinalePlayer::teleport() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + _screen->loadBitmap("END2.BIN", 3, 5, 0); + _screen->convertPage(5, 2, 0); + _screen->copyRegion(0, 0, 56, 0, 216, 200, 2, 0, Screen::CR_NO_P_CHECK); + startPaletteCycle(6, 1); + fadeFromBlack(6, 3); + printSubtitle(_strings[4], 14, 24, 225); + wait(150); + fadeToWhite(6, 3); + stopPaletteCycle(); + clearTextField(); +} + +void EoBPC98FinalePlayer::king() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + uint32 xylen = 0; + uint8 *xydata = _vm->resource()->fileData("xytbl.dat", &xylen); + xylen >>= 1; + + _screen->loadBitmap("KING.BIN", 3, 5, 0); + _screen->convertPage(5, 2, 0); + _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK); + + _screen->loadBitmap("KG.BIN", 3, 4, 0); + _screen->setCurPage(4); + + _shapes[0] = _screen->encodeShape(32, 0, 8, 128); + for (int i = 0; i < 4; ++i) { + _shapes[2 + i] = _screen->encodeShape(i << 3, 0, 8, 80); + if (i < 3) + _shapes[6 + i] = _screen->encodeShape(i << 3, 80, 8, 120); + } + _screen->setCurPage(2); + + _screen->drawShape(2, _shapes[0], 0, 0); + _screen->drawShape(2, _shapes[2], 0, 48); + _screen->copyRegion(0, 0, 128, 16, 64, 128, 2, 0, Screen::CR_NO_P_CHECK); + fadeFromWhite(3, 4); + + _screen->loadBitmap("ADVENTUR.BIN", 3, 5, 0); + _screen->convertPage(5, 2, 0); + _shapes[1] = _screen->encodeShape(8, 0, 8, 64); + + static uint8 xOff[] = { 0, 48, 96, 152 }; + static uint8 maxW[] = { 48, 48, 56, 48 }; + + for (int i = 0; i < 4 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) { + const uint8 *xypos = xydata; + uint16 cx = xOff[i]; + uint32 nextDelay = _vm->_system->getMillis() + 5; + for (uint32 ii = 0; ii < xylen && !_vm->skipFlag() && !_vm->shouldQuit(); ++ii) { + uint8 x = *xypos++; + uint8 y = *xypos++; + uint8 col = _screen->getPagePixel(2, cx + x, y); + if (!col || maxW[i] <= x) + continue; + if (col) + _screen->setPagePixel(0, cx + x + 64, y + 84, col); + if (ii % 48 == 0) { + _screen->updateScreen(); + uint32 cur = _vm->_system->getMillis(); + if (nextDelay > cur) + _vm->_system->delayMillis(nextDelay - cur); + nextDelay += 5; + } + } + _screen->updateScreen(); + } + + printSubtitle(_strings[5], 9, 24, 225); + printSubtitle(_strings[6], 18, 24, 225); + printSubtitle(_strings[7], 23, 24, 225); + printSubtitle(_strings[8], 8, 24, 225); + + wait(60); + clearTextField(); + + for (int i = 0; i < 7 && !_vm->skipFlag() && !_vm->shouldQuit(); ++i) { + uint32 end = _vm->_system->getMillis() + 12 * _tickLength; + _screen->fillRect(0, 0, 64, 128, 0, 2); + _screen->drawShape(2, _shapes[0], 0, 0); + _screen->drawShape(2, _shapes[2 + i], 0, i < 4 ? 48 : 16); + _screen->drawShape(2, _shapes[1], 0, 68); + _screen->copyRegion(0, 0, 128, 16, 64, 128, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _vm->delayUntil(end); + } + + wait(150); + fadeToBlack(3, 3); + + delete[] xydata; + releaseShapes(); +} + +void EoBPC98FinalePlayer::inspection() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + _screen->clearPage(0); + _screen->setCurPage(4); + _screen->loadBitmap("CLB.BIN", 3, 5, 0); + + _shapes[2] = _screen->encodeShape(24, 29, 16, 80); + _shapes[1] = _screen->encodeShape(0, 0, 8, 40); + _shapes[0] = _screen->encodeShape(0, 40, 12, 120); + for (int i = 0; i < 5; ++i) + _shapes[3 + i] = _screen->encodeShape(8 + (i << 2), 0, 4, 24); + + _screen->drawShape(2, _shapes[2], 0, 0); + _screen->copyRegion(0, 0, 88, 50, 128, 80, 2, 0, Screen::CR_NO_P_CHECK); + fadeFromBlack(8, 2); + wait(180); + fadeToBlack(8, 0); + + _screen->clearPage(0); + _screen->clearPage(2); + _screen->drawShape(2, _shapes[1], 0, 0); + _screen->drawShape(2, _shapes[1], 64, 0, -1, 1); + _screen->copyRegion(0, 0, 88, 90, 128, 40, 2, 0, Screen::CR_NO_P_CHECK); + fadeFromBlack(7, 0); + + for (const uint8 *e = _eyesAnimData; *e != 100 && !_vm->skipFlag() && !_vm->shouldQuit(); ) { + _screen->drawShape(2, _shapes[3 + *e], 16, 8); + _screen->drawShape(2, _shapes[3 + *e++], 80, 8, -1, 1); + _screen->copyRegion(0, 0, 88, 90, 128, 40, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + wait(*e++); + } + + wait(30); + fadeToBlack(7, 1); + + _screen->clearPage(0); + _screen->drawShape(2, _shapes[0], 0, 0); + _screen->copyRegion(0, 0, 104, 30, 96, 120, 2, 0, Screen::CR_NO_P_CHECK); + fadeFromBlack(7, 1); + + wait(30); + + printSubtitle(_strings[12], 2, 22, 225); + printSubtitle(_strings[13], 18, 22, 225); + printSubtitle(_strings[14], 14, 22, 225); + printSubtitle(_strings[15], 10, 22, 225); + printSubtitle(_strings[16], 3, 22, 225); + + wait(60); + clearTextField(); + fadeToBlack(7, 3); + releaseShapes(); +} + +void EoBPC98FinalePlayer::congratulation() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + _screen->clearPage(0); + _screen->setCurPage(4); + _shapes[0] = _screen->encodeShape(12, 24, 12, 64); + _shapes[1] = _screen->encodeShape(12, 88, 12, 67); + _shapes[2] = _screen->encodeShape(24, 109, 16, 63); + fadeFromBlack(7, 0); + + for (int i = 0; _handsAnimData[i] != 777 && !_vm->skipFlag() && !_vm->shouldQuit(); i += 2) { + uint32 end = _vm->_system->getMillis() + 60; + _screen->fillRect(40, 20, 240, 180, 0, 2); + _screen->drawShape(2, _shapes[1], 80 + _handsAnimData2[i], 20 + _handsAnimData2[i + 1]); + _screen->drawShape(2, _shapes[0], 80 + _handsAnimData[i], 20 + _handsAnimData[i + 1]); + _screen->copyRegion(80, 20, 88, 20, 160, 140, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _vm->delayUntil(end); + } + + for (int i = 0; i < 32 && !_vm->skipFlag() && !_vm->shouldQuit(); i++) { + uint32 end = _vm->_system->getMillis() + 120; + _screen->fillRect(40, 20, 240, 180, 0, 2); + _screen->drawShape(2, _shapes[2], 80, 60 + _handsAnimData3[i]); + _screen->copyRegion(80, 20, 88, 20, 160, 140, 2, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + _vm->delayUntil(end); + } + + fadeToBlack(7, 7); + releaseShapes(); +} + +void EoBPC98FinalePlayer::credits() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + _screen->clearPage(0); + _screen->setCurPage(4); + _screen->loadBitmap("NEWTEXT.BIN", 3, 5, 0); + + for (int i = 0; i < 64; ++i) + _shapes[i] = _screen->encodeShape((i % 8) << 1, (i / 8) << 4, 2, 16); + + _screen->loadBitmap("CLC-2.BIN", 3, 5, 0); + _screen->convertPage(5, 4, 0); + _screen->copyRegion(0, 0, 88, 10, 128, 80, 4, 0, Screen::CR_NO_P_CHECK); + fadeFromBlack(9, 2); + + _screen->setCurPage(2); + _screen->clearPage(2); + int x = 50; + int y = 100; + bool skipPageReset = false; + + for (const uint8 *pos = _creditsStrings; *pos && !_vm->skipFlag() && !_vm->shouldQuit(); ++pos) { + switch (*pos) { + case 8: + x = 50; + y += 8; + if (y > 183) + y = 0; + break; + + case 9: + x = 100; + break; + + case 12: + _screen->crossFadeRegion(50, 100, 50, 100, 200, 17, 2, 0); + _screen->fillRect(50, 100, 249, 116, 0, 2); + _screen->crossFadeRegion(50, 125, 50, 125, 230, 51, 2, 0); + _screen->fillRect(50, 125, 279, 175, 0, 2); + if (!skipPageReset) { + wait(360); + _screen->crossFadeRegion(50, 100, 50, 100, 236, 85, 2, 0); + _screen->fillRect(50, 100, 285, 184, 0, 2); + wait(60); + x = 50; + y = 100; + } + break; + + case 13: + x = 50; + y += 17; + if (y > 183) + y = 0; + break; + + case 32: + x += 12; + break; + + case 64: + skipPageReset = true; + break; + + default: + if (*pos >= 65) { + _screen->drawShape(2, _shapes[*pos - 65], x, y); + x += _creditsCharWdth[*pos - 65]; + } + break; + } + } + + wait(120); + _screen->copyRegion(128, 0, 88, 10, 128, 80, 4, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + wait(20); + _screen->copyRegion(0, 88, 88, 10, 128, 80, 4, 0, Screen::CR_NO_P_CHECK); + _screen->updateScreen(); + + releaseShapes(); +} + +void EoBPC98FinalePlayer::bonus() { + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + wait(300); + if (!_vm->checkScriptFlags(0x1FFE)) + return; + + fadeToBlack(9, 3); + _screen->setCurPage(0); + _screen->clearCurPage(); + _vm->gui_drawBox(40, 30, 241, 151, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill); + _screen->printShadedText(_strings[9], 132, 40, _vm->guiSettings()->colors.guiColorWhite, 0, 0); + _screen->printShadedText(_strings[10], 72, 52, _vm->guiSettings()->colors.guiColorWhite, 0, 0); + _screen->printShadedText(_strings[11], 120, 70, _vm->guiSettings()->colors.guiColorWhite, 0, 0); + _screen->printShadedText(_vm->_finBonusStrings[0], 72, 82, _vm->guiSettings()->colors.guiColorWhite, 0, 0); + + int cnt = 0; + for (int i = 0; i < 6; i++) { + if (_vm->_characters[i].flags & 1) { + _screen->printShadedText(_vm->_characters[i].name, 78 + (cnt / 3) * 90, 104 + (cnt % 3) * 15, _vm->guiSettings()->colors.guiColorLightRed, 0, 0); + cnt++; + } + } + + uint32 password = 0; + for (int i = 0; i < 6; i++) { + if (!(_vm->_characters[i].flags & 1)) + continue; + + int len = strlen(_vm->_characters[i].name); + for (int ii = 0; ii < len; ii++) { + uint32 c = _vm->_characters[i].name[ii]; + password += (c * c); + } + } + + _screen->printShadedText(Common::String::format(_vm->_finBonusStrings[2], password).c_str(), 120, 156, _vm->guiSettings()->colors.guiColorWhite, 0, 0); + fadeFromBlack(0, 3); +} + +template<int brStart, int brEnd, int brInc> void EoBPC98FinalePlayer::pc98FadePalette(int palId, uint32 del) { + if (_vm->gameFlags().platform != Common::kPlatformPC98) + return; + + if (_vm->shouldQuit() || _vm->skipFlag()) + return; + + del = del * _tickLength; + + for (int i = brStart; i != brEnd && !_vm->skipFlag() && !_vm->shouldQuit(); i += brInc) { + uint32 end = _vm->_system->getMillis() + del; + if (_updatePalCycle) { + for (uint32 cur = _vm->_system->getMillis(); end > cur; cur = _vm->_system->getMillis()) { + _screen->updatePC98PaletteCycle(i); + _screen->updateScreen(); + int step = MIN<int>(end - cur, _palCycleDelay); + if (step > 0) + _vm->delay(step); + } + } else { + _screen->selectPC98Palette(palId, _screen->getPalette(0), i, true); + _screen->updateScreen(); + _vm->delayUntil(end); + } + } + + if (_vm->skipFlag() || _vm->shouldQuit()) { + _screen->selectPC98Palette(palId, _screen->getPalette(0), brEnd, true); + _screen->updateScreen(); + } +} + +void EoBPC98FinalePlayer::startPaletteCycle(int palId, int style) { + if (style == 0) + _screen->initPC98PaletteCycle(palId, _palCycleType1); + else if (style == 1) + _screen->initPC98PaletteCycle(palId, _palCycleType2); + + if (style == 0 || style == 1) + resetPaletteCycle(); + + _updatePalCycle = true; +} + +void EoBPC98FinalePlayer::stopPaletteCycle() { + _updatePalCycle = false; + _screen->initPC98PaletteCycle(0, 0); +} + +void EoBPC98FinalePlayer::resetPaletteCycle() { + int temp = 0; + const uint8 *data = _vm->staticres()->loadRawData(kEoB1PalCycleData, temp); + const uint16 *stl1 = _vm->staticres()->loadRawDataBe16(kEoB1PalCycleStyle1, temp); + const uint16 *stl2 = _vm->staticres()->loadRawDataBe16(kEoB1PalCycleStyle2, temp); + + for (int i = 0; i < 48; ++i) { + _palCycleType1[i].data = (const int8*)(data + stl1[i * 2]); + _palCycleType1[i].delay = stl1[i * 2 + 1]; + _palCycleType2[i].data = (const int8*)(data + stl2[i * 2]); + _palCycleType2[i].delay = stl2[i * 2 + 1]; + } +} + +void EoBPC98FinalePlayer::wait(uint32 ticks) { + uint32 millis = ticks * _tickLength; + uint32 end = _vm->_system->getMillis() + millis; + for (uint32 cur = _vm->_system->getMillis(); end > cur && !_vm->skipFlag() && !_vm->shouldQuit(); cur = _vm->_system->getMillis()) { + if (_updatePalCycle) { + _screen->updatePC98PaletteCycle(0); + _screen->updateScreen(); + } + int step = MIN<int>(end - cur, _palCycleDelay); + if (step > 0) + _vm->delay(step); + } +} + EoBAmigaFinalePlayer::EoBAmigaFinalePlayer(EoBEngine *vm, Screen_EoB *screen) : EoBSeqPlayerCommon(vm, screen) { _animCurFrame = 0; int size = 0; @@ -1248,7 +1802,7 @@ void EoBAmigaFinalePlayer::start() { _vm->_eventList.clear(); _vm->_allowSkip = true; - _vm->sound()->playTrack(0); + _vm->snd_playSong(0); entry(); delivery(); @@ -1724,6 +2278,11 @@ void EoBEngine::seq_playIntro(int part) { } void EoBEngine::seq_playFinale() { + if (_flags.platform == Common::kPlatformPC98) { + EoBPC98FinalePlayer(this, _screen).start(_xdth); + return; + } + Common::SeekableReadStream *s = _res->createReadStream("TEXT.DAT"); _screen->loadFileDataToPage(s, 5, 32000); delete s; @@ -1768,6 +2327,7 @@ void EoBEngine::seq_playFinale() { void EoBEngine::seq_xdeath() { uint8 *shapes1[5]; uint8 *shapes2; + _xdth = true; _screen->loadShapeSetBitmap("XDEATH2", 5, 3); for (int i = 0; i < 4; i++) |