diff options
author | Robert Špalek | 2009-10-28 07:34:17 +0000 |
---|---|---|
committer | Robert Špalek | 2009-10-28 07:34:17 +0000 |
commit | c781f013210faa35bff381ca2b537e2f40750bf5 (patch) | |
tree | 3ced66c8597cee767d6b9dbe63209cfbde8ef8b4 | |
parent | 4f5a99655caeef5479e42d0472ee3076ae14d59a (diff) | |
download | scummvm-rg350-c781f013210faa35bff381ca2b537e2f40750bf5.tar.gz scummvm-rg350-c781f013210faa35bff381ca2b537e2f40750bf5.tar.bz2 scummvm-rg350-c781f013210faa35bff381ca2b537e2f40750bf5.zip |
Implement palette fading
svn-id: r45455
-rw-r--r-- | engines/draci/draci.cpp | 2 | ||||
-rw-r--r-- | engines/draci/game.cpp | 25 | ||||
-rw-r--r-- | engines/draci/game.h | 11 | ||||
-rw-r--r-- | engines/draci/screen.cpp | 50 | ||||
-rw-r--r-- | engines/draci/screen.h | 5 | ||||
-rw-r--r-- | engines/draci/script.cpp | 28 | ||||
-rw-r--r-- | engines/draci/script.h | 2 |
7 files changed, 101 insertions, 22 deletions
diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index f472592684..71155e6c25 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -365,7 +365,7 @@ void DraciEngine::pauseEngineIntern(bool pause) { // Adjust engine start time const int delta = _system->getMillis() - _pauseStartTime; _engineStartTime += delta / 1000; - _game->shiftSpeechTick(delta); + _game->shiftSpeechAndFadeTick(delta); _pauseStartTime = 0; } } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index b162e0195e..b2e28b70a7 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -165,6 +165,7 @@ void Game::init() { setQuit(false); setExitLoop(false); _scheduledPalette = 0; + _fadePhases = _fadePhase = 0; setLoopStatus(kStatusGate); setLoopSubstatus(kSubstatusOrdinary); @@ -239,6 +240,22 @@ void Game::loop() { if (shouldExitLoop() > 1) // after loading break; + if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) { + _fadeTick = _vm->_system->getMillis(); + --_fadePhase; + const BAFile *startPal = _vm->_paletteArchive->getFile(_currentRoom._palette); + const BAFile *endPal = getScheduledPalette() >= 0 ? _vm->_paletteArchive->getFile(getScheduledPalette()) : NULL; + _vm->_screen->interpolatePalettes(startPal->_data, endPal->_data, 0, kNumColours, _fadePhases - _fadePhase, _fadePhases); + if (_loopSubstatus == kSubstatusFade && _fadePhase == 0) { + setExitLoop(true); + // Rewrite the palette index of the current + // room. This is necessary when two fadings + // are called after each other, such as in the + // intro. We rely on that getScheduledPalette() >= 0. + _currentRoom._palette = getScheduledPalette(); + } + } + // Fetch mouse coordinates int x = _vm->_mouse->getPosX(); int y = _vm->_mouse->getPosY(); @@ -1530,8 +1547,9 @@ void Game::setSpeechTiming(uint tick, uint duration) { _speechDuration = duration; } -void Game::shiftSpeechTick(int delta) { +void Game::shiftSpeechAndFadeTick(int delta) { _speechTick += delta; + _fadeTick += delta; } int Game::getEscRoom() const { @@ -1550,6 +1568,11 @@ int Game::getScheduledPalette() const { return _scheduledPalette; } +void Game::initializeFading(int phases) { + _fadePhases = _fadePhase = phases; + _fadeTick = _vm->_system->getMillis(); +} + /** * The GPL command Mark sets the animation index (which specifies the order in which * animations were loaded in) which is then used by the Release command to delete diff --git a/engines/draci/game.h b/engines/draci/game.h index af0ed6d502..e4d857809b 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -87,6 +87,11 @@ enum SpeechConstants { kSpeechTimeUnit = 2640 }; +// One fading phase is 50ms. +enum FadeConstants { + kFadingTimeUnit = 50 +}; + /** Inventory related magical constants */ enum InventoryConstants { kInventoryItemWidth = 25, @@ -330,7 +335,7 @@ public: void setExitLoop(int exit) { _shouldExitLoop = exit; } void setSpeechTiming(uint tick, uint duration); - void shiftSpeechTick(int delta); + void shiftSpeechAndFadeTick(int delta); void updateTitle(); void updateCursor(); @@ -360,6 +365,7 @@ public: void schedulePalette(int paletteID); int getScheduledPalette() const; + void initializeFading(int phases); void DoSync(Common::Serializer &s); @@ -423,6 +429,9 @@ private: int _markedAnimationIndex; ///< Used by the Mark GPL command int _scheduledPalette; + int _fadePhases; + int _fadePhase; + uint _fadeTick; }; } // End of namespace Draci diff --git a/engines/draci/screen.cpp b/engines/draci/screen.cpp index 7c67b125c0..d7c5dec027 100644 --- a/engines/draci/screen.cpp +++ b/engines/draci/screen.cpp @@ -33,25 +33,18 @@ namespace Draci { Screen::Screen(DraciEngine *vm) : _vm(vm) { _surface = new Surface(kScreenWidth, kScreenHeight); _palette = new byte[4 * kNumColours]; - setPaletteEmpty(); + _blackPalette = new byte[3 * kNumColours]; + for (int i = 0; i < 3 * kNumColours; ++i) { + _blackPalette[i] = 0; + } + setPalette(NULL, 0, kNumColours); this->clearScreen(); } Screen::~Screen() { delete _surface; delete[] _palette; -} - -/** - * @brief Sets the first numEntries of palette to zero - * @param numEntries The number of entries to set to zero (from start) - */ -void Screen::setPaletteEmpty(uint numEntries) { - for (uint i = 0; i < 4 * numEntries; ++i) { - _palette[i] = 0; - } - - _vm->_system->setPalette(_palette, 0, numEntries); + delete[] _blackPalette; } /** @@ -61,7 +54,7 @@ void Screen::setPaletteEmpty(uint numEntries) { * num Number of colours to replace */ void Screen::setPalette(const byte *data, uint16 start, uint16 num) { - Common::MemoryReadStream pal(data, 3 * kNumColours); + Common::MemoryReadStream pal(data ? data : _blackPalette, 3 * kNumColours); pal.seek(start * 4); // Copy the palette @@ -74,13 +67,40 @@ void Screen::setPalette(const byte *data, uint16 start, uint16 num) { // TODO: Investigate why this is needed // Shift the palette two bits to the left to make it brighter - for (uint i = 0; i < 4 * kNumColours; ++i) { + for (int i = start * 4; i < (start + num) * 4; ++i) { + _palette[i] <<= 2; + } + + _vm->_system->setPalette(_palette, start, num); +} + +void Screen::interpolatePalettes(const byte *first, const byte *second, uint16 start, uint16 num, int index, int number) { + Common::MemoryReadStream firstPal(first ? first : _blackPalette, 3 * kNumColours); + Common::MemoryReadStream secondPal(second ? second : _blackPalette, 3 * kNumColours); + firstPal.seek(start * 4); + secondPal.seek(start * 4); + + // Interpolate the palettes + for (uint16 i = start; i < start + num; ++i) { + _palette[i * 4] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number); + _palette[i * 4 + 1] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number); + _palette[i * 4 + 2] = interpolate(firstPal.readByte(), secondPal.readByte(), index, number); + _palette[i * 4 + 3] = 0; + } + + // TODO: Investigate why this is needed + // Shift the palette two bits to the left to make it brighter + for (int i = start * 4; i < (start + num) * 4; ++i) { _palette[i] <<= 2; } _vm->_system->setPalette(_palette, start, num); } +int Screen::interpolate(int first, int second, int index, int number) { + return (second * index + first * (number - index)) / number; +} + /** * @brief Copies the current memory screen buffer to the real screen */ diff --git a/engines/draci/screen.h b/engines/draci/screen.h index bb3ada693c..846b38efa3 100644 --- a/engines/draci/screen.h +++ b/engines/draci/screen.h @@ -46,8 +46,8 @@ public: Screen(DraciEngine *vm); ~Screen(); - void setPaletteEmpty(uint numEntries = kNumColours); void setPalette(const byte *data, uint16 start, uint16 num); + void interpolatePalettes(const byte *first, const byte *second, uint16 start, uint16 num, int index, int number); const byte *getPalette() const; void copyToScreen(); void clearScreen(); @@ -56,8 +56,11 @@ public: void drawRect(Common::Rect r, uint8 colour); private: + int interpolate(int first, int second, int index, int number); + Surface *_surface; byte *_palette; + byte *_blackPalette; DraciEngine *_vm; }; diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index e5dc28e705..b09a9d6298 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -64,8 +64,8 @@ void Script::setupCommandList() { { 11, 1, "LoadPalette", 1, { 2 }, &Script::loadPalette }, { 12, 1, "SetPalette", 0, { 0 }, &Script::setPalette }, { 12, 2, "BlackPalette", 0, { 0 }, &Script::blackPalette }, - { 13, 1, "FadePalette", 3, { 1, 1, 1 }, NULL }, - { 13, 2, "FadePalettePlay", 3, { 1, 1, 1 }, NULL }, + { 13, 1, "FadePalette", 3, { 1, 1, 1 }, &Script::fadePalette }, + { 13, 2, "FadePalettePlay", 3, { 1, 1, 1 }, &Script::fadePalettePlay }, { 14, 1, "NewRoom", 2, { 3, 1 }, &Script::newRoom }, { 15, 1, "ExecInit", 1, { 3 }, &Script::execInit }, { 15, 2, "ExecLook", 1, { 3 }, &Script::execLook }, @@ -840,14 +840,36 @@ void Script::blackPalette(Common::Queue<int> ¶ms) { _vm->_game->schedulePalette(kBlackPalette); } +void Script::fadePalette(Common::Queue<int> ¶ms) { + params.pop(); // unused first and last + params.pop(); + int phases = params.pop(); + _vm->_game->initializeFading(phases); +} + +void Script::fadePalettePlay(Common::Queue<int> ¶ms) { + params.pop(); // unused first and last + params.pop(); + int phases = params.pop(); + _vm->_game->initializeFading(phases); + + _vm->_game->setLoopSubstatus(kSubstatusFade); + _vm->_game->loop(); + _vm->_game->setExitLoop(false); + _vm->_game->setLoopSubstatus(kSubstatusOrdinary); +} + void Script::setPalette(Common::Queue<int> ¶ms) { if (_vm->_game->getScheduledPalette() == -1) { - _vm->_screen->setPaletteEmpty(); + _vm->_screen->setPalette(NULL, 0, kNumColours); } else { const BAFile *f; f = _vm->_paletteArchive->getFile(_vm->_game->getScheduledPalette()); _vm->_screen->setPalette(f->_data, 0, kNumColours); } + // Immediately update the palette + _vm->_screen->copyToScreen(); + _vm->_system->delayMillis(100); } void Script::quitGame(Common::Queue<int> ¶ms) { diff --git a/engines/draci/script.h b/engines/draci/script.h index 1073f2c290..a81b9e3ad5 100644 --- a/engines/draci/script.h +++ b/engines/draci/script.h @@ -138,6 +138,8 @@ private: void resetBlock(Common::Queue<int> ¶ms); void setPalette(Common::Queue<int> ¶ms); void blackPalette(Common::Queue<int> ¶ms); + void fadePalette(Common::Queue<int> ¶ms); + void fadePalettePlay(Common::Queue<int> ¶ms); void loadPalette(Common::Queue<int> ¶ms); void quitGame(Common::Queue<int> ¶ms); void pushNewRoom(Common::Queue<int> ¶ms); |