aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Špalek2009-10-28 07:34:17 +0000
committerRobert Špalek2009-10-28 07:34:17 +0000
commitc781f013210faa35bff381ca2b537e2f40750bf5 (patch)
tree3ced66c8597cee767d6b9dbe63209cfbde8ef8b4
parent4f5a99655caeef5479e42d0472ee3076ae14d59a (diff)
downloadscummvm-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.cpp2
-rw-r--r--engines/draci/game.cpp25
-rw-r--r--engines/draci/game.h11
-rw-r--r--engines/draci/screen.cpp50
-rw-r--r--engines/draci/screen.h5
-rw-r--r--engines/draci/script.cpp28
-rw-r--r--engines/draci/script.h2
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> &params) {
_vm->_game->schedulePalette(kBlackPalette);
}
+void Script::fadePalette(Common::Queue<int> &params) {
+ params.pop(); // unused first and last
+ params.pop();
+ int phases = params.pop();
+ _vm->_game->initializeFading(phases);
+}
+
+void Script::fadePalettePlay(Common::Queue<int> &params) {
+ 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> &params) {
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> &params) {
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> &params);
void setPalette(Common::Queue<int> &params);
void blackPalette(Common::Queue<int> &params);
+ void fadePalette(Common::Queue<int> &params);
+ void fadePalettePlay(Common::Queue<int> &params);
void loadPalette(Common::Queue<int> &params);
void quitGame(Common::Queue<int> &params);
void pushNewRoom(Common::Queue<int> &params);