aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Hoops2012-07-05 20:36:34 -0400
committerMatthew Hoops2012-07-05 20:36:34 -0400
commit3860f341365a59ff96ec41e61e3952be01915b40 (patch)
treeb0342b8131d54b629c893ae150bb505c9198a2af
parent91efe792d5b231752dd16888729a94f323363fa0 (diff)
downloadscummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.tar.gz
scummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.tar.bz2
scummvm-rg350-3860f341365a59ff96ec41e61e3952be01915b40.zip
PEGASUS: Implement screen fading
This does linear instead of gamma for speed and complexity reasons.
-rw-r--r--engines/pegasus/graphics.cpp35
-rw-r--r--engines/pegasus/graphics.h6
-rw-r--r--engines/pegasus/menu.cpp5
-rw-r--r--engines/pegasus/neighborhood/caldoria/caldoria.cpp21
-rw-r--r--engines/pegasus/pegasus.cpp1
-rw-r--r--engines/pegasus/transition.cpp65
-rw-r--r--engines/pegasus/transition.h19
7 files changed, 112 insertions, 40 deletions
diff --git a/engines/pegasus/graphics.cpp b/engines/pegasus/graphics.cpp
index 175f15e91d..8d0347ebc4 100644
--- a/engines/pegasus/graphics.cpp
+++ b/engines/pegasus/graphics.cpp
@@ -30,6 +30,7 @@
#include "pegasus/elements.h"
#include "pegasus/graphics.h"
+#include "pegasus/transition.h"
namespace Pegasus {
@@ -46,10 +47,13 @@ GraphicsManager::GraphicsManager(PegasusEngine *vm) : _vm(vm) {
_modifiedScreen = false;
_curSurface = &_workArea;
_erase = false;
+ _updatesEnabled = true;
+ _screenFader = new ScreenFader();
}
GraphicsManager::~GraphicsManager() {
_workArea.free();
+ delete _screenFader;
}
void GraphicsManager::invalRect(const Common::Rect &rect) {
@@ -175,7 +179,7 @@ void GraphicsManager::updateDisplay() {
_dirtyRect = Common::Rect();
}
- if (screenDirty || _modifiedScreen)
+ if (_updatesEnabled && (screenDirty || _modifiedScreen))
g_system->updateScreen();
_modifiedScreen = false;
@@ -200,19 +204,14 @@ DisplayElement *GraphicsManager::findDisplayElement(const DisplayElementID id) {
return 0;
}
-void GraphicsManager::doFadeOutSync(const TimeValue, const TimeValue, uint32 color) {
- if (color == 0)
- color = g_system->getScreenFormat().RGBToColor(0, 0, 0);
-
- // HACK: Until fading out is done, white-out the screen here
- Graphics::Surface *screen = g_system->lockScreen();
- screen->fillRect(Common::Rect(0, 0, 640, 480), color);
- g_system->unlockScreen();
- g_system->updateScreen();
+void GraphicsManager::doFadeOutSync(const TimeValue time, const TimeScale scale, uint32 color) {
+ _updatesEnabled = false;
+ _screenFader->doFadeOutSync(time, scale, color == 0);
}
-void GraphicsManager::doFadeInSync(const TimeValue, const TimeValue, uint32) {
- // TODO
+void GraphicsManager::doFadeInSync(const TimeValue time, const TimeScale scale, uint32 color) {
+ _screenFader->doFadeInSync(time, scale, color == 0);
+ _updatesEnabled = true;
}
void GraphicsManager::markCursorAsDirty() {
@@ -333,5 +332,15 @@ void GraphicsManager::enableErase() {
void GraphicsManager::disableErase() {
_erase = false;
}
-
+
+void GraphicsManager::enableUpdates() {
+ _updatesEnabled = true;
+ _screenFader->setFaderValue(100);
+}
+
+void GraphicsManager::disableUpdates() {
+ _updatesEnabled = false;
+ _screenFader->setFaderValue(0);
+}
+
} // End of namespace Pegasus
diff --git a/engines/pegasus/graphics.h b/engines/pegasus/graphics.h
index 502304409a..2d66cd9aaa 100644
--- a/engines/pegasus/graphics.h
+++ b/engines/pegasus/graphics.h
@@ -40,6 +40,7 @@ namespace Pegasus {
class Cursor;
class DisplayElement;
class PegasusEngine;
+class ScreenFader;
class GraphicsManager {
friend class Cursor;
@@ -61,6 +62,8 @@ public:
void shakeTheWorld(TimeValue time, TimeScale scale);
void enableErase();
void disableErase();
+ void enableUpdates();
+ void disableUpdates();
// These default to black
void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, uint32 color = 0);
@@ -82,6 +85,9 @@ private:
static const int kMaxShakeOffsets = 17;
Common::Point _shakeOffsets[kMaxShakeOffsets];
void newShakePoint(int32 index1, int32 index2, int32 maxRadius);
+
+ bool _updatesEnabled;
+ ScreenFader *_screenFader;
};
} // End of namespace Pegasus
diff --git a/engines/pegasus/menu.cpp b/engines/pegasus/menu.cpp
index 5d90f62b14..5076abdaa6 100644
--- a/engines/pegasus/menu.cpp
+++ b/engines/pegasus/menu.cpp
@@ -237,10 +237,7 @@ void MainMenu::startMainMenuLoop() {
_menuLoop.loopSound();
spec.makeTwoKnotFaderSpec(30, 0, 0, 30, 255);
-
- // FIXME: Should be sync, but it's a pain to use the main menu right now
- // with this one.
- _menuFader.startFader(spec);
+ _menuFader.startFaderSync(spec);
}
void MainMenu::stopMainMenuLoop() {
diff --git a/engines/pegasus/neighborhood/caldoria/caldoria.cpp b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
index 0e5868cb7d..817a24a162 100644
--- a/engines/pegasus/neighborhood/caldoria/caldoria.cpp
+++ b/engines/pegasus/neighborhood/caldoria/caldoria.cpp
@@ -204,17 +204,24 @@ void Caldoria::start() {
if (!pullbackMovie->loadFile("Images/Caldoria/Pullback.movie"))
error("Could not load pullback movie");
- bool skipped = false;
- Input input;
-
+ // Draw the first frame so we can fade to it
+ pullbackMovie->pauseVideo(true);
+ const Graphics::Surface *frame = pullbackMovie->decodeNextFrame();
+ assert(frame);
+ assert(frame->format == g_system->getScreenFormat());
+ g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h);
_vm->_gfx->doFadeInSync(kTwoSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond);
+ pullbackMovie->pauseVideo(false);
bool saveAllowed = _vm->swapSaveAllowed(false);
bool openAllowed = _vm->swapLoadAllowed(false);
+ bool skipped = false;
+ Input input;
+
while (!_vm->shouldQuit() && !pullbackMovie->endOfVideo()) {
if (pullbackMovie->needsUpdate()) {
- const Graphics::Surface *frame = pullbackMovie->decodeNextFrame();
+ frame = pullbackMovie->decodeNextFrame();
if (frame) {
g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, 64, 112, frame->w, frame->h);
@@ -233,6 +240,9 @@ void Caldoria::start() {
delete pullbackMovie;
+ if (_vm->shouldQuit())
+ return;
+
_vm->swapSaveAllowed(saveAllowed);
_vm->swapLoadAllowed(openAllowed);
@@ -240,11 +250,8 @@ void Caldoria::start() {
if (!skipped) {
uint32 white = g_system->getScreenFormat().RGBToColor(0xff, 0xff, 0xff);
-
_vm->_gfx->doFadeOutSync(kThreeSeconds * kFifteenTicksPerSecond, kFifteenTicksPerSecond, white);
-
g_system->delayMillis(3 * 1000 / 2);
-
getExtraEntry(kCaldoria00WakeUp1, entry);
_navMovie.setTime(entry.movieStart);
_navMovie.redrawMovieWorld();
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 401a922c74..04b6f36428 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -1479,6 +1479,7 @@ void PegasusEngine::startNewGame() {
_gfx->doFadeOutSync();
useMenu(0);
_gfx->updateDisplay();
+ _gfx->enableUpdates();
createInterface();
diff --git a/engines/pegasus/transition.cpp b/engines/pegasus/transition.cpp
index 24e9aaf4a2..0de63d6080 100644
--- a/engines/pegasus/transition.cpp
+++ b/engines/pegasus/transition.cpp
@@ -24,43 +24,92 @@
*/
#include "common/system.h"
+#include "graphics/surface.h"
#include "pegasus/transition.h"
namespace Pegasus {
ScreenFader::ScreenFader() {
- _fadeTarget = getBlack();
+ _isBlack = true;
// Initially, assume screens are on at full brightness.
Fader::setFaderValue(100);
+ _screen = new Graphics::Surface();
}
-void ScreenFader::doFadeOutSync(const TimeValue duration, const TimeValue scale, const uint32 fadeTarget) {
- _fadeTarget = fadeTarget;
+ScreenFader::~ScreenFader() {
+ _screen->free();
+ delete _screen;
+}
+
+void ScreenFader::doFadeOutSync(const TimeValue duration, const TimeValue scale, bool isBlack) {
+ _isBlack = isBlack;
+ _screen->copyFrom(*g_system->lockScreen());
+ g_system->unlockScreen();
FaderMoveSpec spec;
spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 0);
startFaderSync(spec);
+
+ _screen->free();
}
-void ScreenFader::doFadeInSync(const TimeValue duration, const TimeValue scale, const uint32 fadeTarget) {
- _fadeTarget = fadeTarget;
+void ScreenFader::doFadeInSync(const TimeValue duration, const TimeValue scale, bool isBlack) {
+ _isBlack = isBlack;
+ _screen->copyFrom(*g_system->lockScreen());
+ g_system->unlockScreen();
FaderMoveSpec spec;
spec.makeTwoKnotFaderSpec(scale, 0, getFaderValue(), duration, 100);
startFaderSync(spec);
+
+ _screen->free();
}
void ScreenFader::setFaderValue(const int32 value) {
if (value != getFaderValue()) {
Fader::setFaderValue(value);
- // TODO: Gamma fading
+ if (_screen->pixels) {
+ // The original game does a gamma fade here using the Mac API. In order to do
+ // that, it would require an immense amount of CPU processing. This does a
+ // linear fade instead, which looks fairly well, IMO.
+ Graphics::Surface *screen = g_system->lockScreen();
+
+ for (uint y = 0; y < _screen->h; y++) {
+ for (uint x = 0; x < _screen->w; x++) {
+ if (_screen->format.bytesPerPixel == 2)
+ WRITE_UINT16(screen->getBasePtr(x, y), fadePixel(READ_UINT16(_screen->getBasePtr(x, y)), value));
+ else
+ WRITE_UINT32(screen->getBasePtr(x, y), fadePixel(READ_UINT32(_screen->getBasePtr(x, y)), value));
+ }
+ }
+
+ g_system->unlockScreen();
+ g_system->updateScreen();
+ }
}
}
-uint32 ScreenFader::getBlack() {
- return g_system->getScreenFormat().RGBToColor(0, 0, 0);
+static inline byte fadeComponent(byte comp, int32 percent) {
+ return comp * percent / 100;
+}
+
+uint32 ScreenFader::fadePixel(uint32 color, int32 percent) const {
+ byte r, g, b;
+ g_system->getScreenFormat().colorToRGB(color, r, g, b);
+
+ if (_isBlack) {
+ r = fadeComponent(r, percent);
+ g = fadeComponent(g, percent);
+ b = fadeComponent(b, percent);
+ } else {
+ r = 0xFF - fadeComponent(0xFF - r, percent);
+ g = 0xFF - fadeComponent(0xFF - g, percent);
+ b = 0xFF - fadeComponent(0xFF - b, percent);
+ }
+
+ return g_system->getScreenFormat().RGBToColor(r, g, b);
}
Transition::Transition(const DisplayElementID id) : FaderAnimation(id) {
diff --git a/engines/pegasus/transition.h b/engines/pegasus/transition.h
index 5f2b797d88..a516d58e20 100644
--- a/engines/pegasus/transition.h
+++ b/engines/pegasus/transition.h
@@ -28,23 +28,26 @@
#include "pegasus/fader.h"
+namespace Graphics {
+struct Surface;
+}
+
namespace Pegasus {
class ScreenFader : public Fader {
public:
ScreenFader();
- virtual ~ScreenFader() {}
+ virtual ~ScreenFader();
- void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, const uint32 = getBlack());
- void doFadeInSync(const TimeValue = kHalfSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, const uint32 = getBlack());
-
- void setFaderValue(const int32);
+ void doFadeOutSync(const TimeValue = kOneSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
+ void doFadeInSync(const TimeValue = kHalfSecondPerThirtyTicks, const TimeScale = kThirtyTicksPerSecond, bool isBlack = true);
-protected:
- uint32 _fadeTarget;
+ void setFaderValue(const int32);
private:
- static uint32 getBlack();
+ bool _isBlack;
+ uint32 fadePixel(uint32 color, int32 percent) const;
+ Graphics::Surface *_screen;
};
// Transitions are faders that range over [0,1000], which makes their