aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk
diff options
context:
space:
mode:
authorBastien Bouclet2017-09-20 07:10:31 +0200
committerBastien Bouclet2017-09-20 07:16:20 +0200
commit661487c2b5c8376719d994fc9300cf2393dfce9f (patch)
tree9ea971db1fb53b38af394361d477d32527c04e4e /engines/mohawk
parent56b744f5f15e15c01fbd89db88a595d95f1c71cb (diff)
downloadscummvm-rg350-661487c2b5c8376719d994fc9300cf2393dfce9f.tar.gz
scummvm-rg350-661487c2b5c8376719d994fc9300cf2393dfce9f.tar.bz2
scummvm-rg350-661487c2b5c8376719d994fc9300cf2393dfce9f.zip
MOHAWK: Riven: Move the water effect to its own class
Fixes the per frame scripts being leaked. Fixes #10215.
Diffstat (limited to 'engines/mohawk')
-rw-r--r--engines/mohawk/riven_card.cpp2
-rw-r--r--engines/mohawk/riven_graphics.cpp137
-rw-r--r--engines/mohawk/riven_graphics.h45
3 files changed, 102 insertions, 82 deletions
diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp
index feea22a663..7a5cd617a6 100644
--- a/engines/mohawk/riven_card.cpp
+++ b/engines/mohawk/riven_card.cpp
@@ -54,7 +54,7 @@ RivenCard::~RivenCard() {
delete _hotspots[i];
}
- _vm->_gfx->clearWaterEffects();
+ _vm->_gfx->clearWaterEffect();
_vm->_gfx->clearFliesEffect();
_vm->_video->closeVideos();
}
diff --git a/engines/mohawk/riven_graphics.cpp b/engines/mohawk/riven_graphics.cpp
index b9d82fbd39..c80e9e5899 100644
--- a/engines/mohawk/riven_graphics.cpp
+++ b/engines/mohawk/riven_graphics.cpp
@@ -329,6 +329,7 @@ RivenGraphics::RivenGraphics(MohawkEngine_Riven* vm) : GraphicsManager(), _vm(vm
_transitionMode = kRivenTransitionModeFastest;
_transitionOffset = -1;
+ _waterEffect = nullptr;
_fliesEffect = nullptr;
}
@@ -384,93 +385,101 @@ void RivenGraphics::updateScreen() {
}
void RivenGraphics::scheduleWaterEffect(uint16 sfxeID) {
+ clearWaterEffect();
+
+ _waterEffect = new WaterEffect(_vm, sfxeID);
+}
+
+void RivenGraphics::clearWaterEffect() {
+ delete _waterEffect;
+ _waterEffect = nullptr;
+}
+
+WaterEffect::WaterEffect(MohawkEngine_Riven *vm, uint16 sfxeID) :
+ _vm(vm) {
Common::SeekableReadStream *sfxeStream = _vm->getResource(ID_SFXE, sfxeID);
if (sfxeStream->readUint16BE() != 'SL')
error ("Unknown sfxe tag");
// Read in header info
- SFXERecord sfxeRecord;
- sfxeRecord.frameCount = sfxeStream->readUint16BE();
+ uint16 frameCount = sfxeStream->readUint16BE();
uint32 offsetTablePosition = sfxeStream->readUint32BE();
- sfxeRecord.rect.left = sfxeStream->readUint16BE();
- sfxeRecord.rect.top = sfxeStream->readUint16BE();
- sfxeRecord.rect.right = sfxeStream->readUint16BE();
- sfxeRecord.rect.bottom = sfxeStream->readUint16BE();
- sfxeRecord.speed = sfxeStream->readUint16BE();
+ _rect.left = sfxeStream->readUint16BE();
+ _rect.top = sfxeStream->readUint16BE();
+ _rect.right = sfxeStream->readUint16BE();
+ _rect.bottom = sfxeStream->readUint16BE();
+ _speed = sfxeStream->readUint16BE();
// Skip the rest of the fields...
// Read in offsets
sfxeStream->seek(offsetTablePosition);
- uint32 *frameOffsets = new uint32[sfxeRecord.frameCount];
- for (uint16 i = 0; i < sfxeRecord.frameCount; i++)
+ Common::Array<uint32> frameOffsets;
+ frameOffsets.resize(frameCount);
+ for (uint16 i = 0; i < frameCount; i++)
frameOffsets[i] = sfxeStream->readUint32BE();
- sfxeStream->seek(frameOffsets[0]);
// Read in the scripts
- for (uint16 i = 0; i < sfxeRecord.frameCount; i++)
- sfxeRecord.frameScripts.push_back(sfxeStream->readStream((i == sfxeRecord.frameCount - 1) ? sfxeStream->size() - frameOffsets[i] : frameOffsets[i + 1] - frameOffsets[i]));
+ sfxeStream->seek(frameOffsets[0]);
+ for (uint16 i = 0; i < frameCount; i++) {
+ uint scriptLength = (i == frameCount - 1) ? sfxeStream->size() - frameOffsets[i] : frameOffsets[i + 1] - frameOffsets[i];
+ _frameScripts.push_back(sfxeStream->readStream(scriptLength));
+ }
// Set it to the first frame
- sfxeRecord.curFrame = 0;
- sfxeRecord.lastFrameTime = 0;
+ _curFrame = 0;
+ _lastFrameTime = 0;
- delete[] frameOffsets;
delete sfxeStream;
- _waterEffects.push_back(sfxeRecord);
}
-void RivenGraphics::clearWaterEffects() {
- _waterEffects.clear();
-}
-
-void RivenGraphics::runScheduledWaterEffects() {
- // Don't run the effect if it's disabled
- if (_vm->_vars["waterenabled"] == 0)
- return;
-
- Graphics::Surface *screen = NULL;
-
- for (uint16 i = 0; i < _waterEffects.size(); i++) {
- if (_vm->_system->getMillis() > _waterEffects[i].lastFrameTime + 1000 / _waterEffects[i].speed) {
- // Lock the screen!
- if (!screen)
- screen = _vm->_system->lockScreen();
-
- // Make sure the script is at the starting point
- Common::SeekableReadStream *script = _waterEffects[i].frameScripts[_waterEffects[i].curFrame];
- if (script->pos() != 0)
- script->seek(0);
-
- // Run script
- uint16 curRow = 0;
- for (uint16 op = script->readUint16BE(); op != 4; op = script->readUint16BE()) {
- if (op == 1) { // Increment Row
- curRow++;
- } else if (op == 3) { // Copy Pixels
- uint16 dstLeft = script->readUint16BE();
- uint16 srcLeft = script->readUint16BE();
- uint16 srcTop = script->readUint16BE();
- uint16 rowWidth = script->readUint16BE();
- memcpy ((byte *)screen->getBasePtr(dstLeft, curRow + _waterEffects[i].rect.top), (byte *)_mainScreen->getBasePtr(srcLeft, srcTop), rowWidth * _pixelFormat.bytesPerPixel);
- } else if (op != 4) { // End of Script
- error ("Unknown SFXE opcode %d", op);
- }
- }
+void WaterEffect::update() {
+ if (_vm->_system->getMillis() <= _lastFrameTime + 1000 / _speed) {
+ return; // Nothing to do yet
+ }
- // Increment frame
- _waterEffects[i].curFrame++;
- if (_waterEffects[i].curFrame == _waterEffects[i].frameCount)
- _waterEffects[i].curFrame = 0;
+ // Make sure the script is at the starting point
+ Common::SeekableReadStream *script = _frameScripts[_curFrame];
+ script->seek(0);
- // Set the new time
- _waterEffects[i].lastFrameTime = _vm->_system->getMillis();
+ Graphics::Surface *screen = _vm->_system->lockScreen();
+ Graphics::Surface *mainScreen = _vm->_gfx->getBackScreen();
+ assert(screen->format == mainScreen->format);
+
+ // Run script
+ uint16 curRow = 0;
+ for (uint16 op = script->readUint16BE(); op != 4; op = script->readUint16BE()) {
+ if (op == 1) { // Increment Row
+ curRow++;
+ } else if (op == 3) { // Copy Pixels
+ uint16 dstLeft = script->readUint16BE();
+ uint16 srcLeft = script->readUint16BE();
+ uint16 srcTop = script->readUint16BE();
+ uint16 rowWidth = script->readUint16BE();
+
+ byte *src = (byte *)mainScreen->getBasePtr(srcLeft, srcTop);
+ byte *dst = (byte *)screen->getBasePtr(dstLeft, curRow + _rect.top);
+
+ memcpy(dst, src, rowWidth * screen->format.bytesPerPixel);
+ } else if (op != 4) { // End of Script
+ error ("Unknown SFXE opcode %d", op);
}
}
- // Unlock the screen if it has been locked and return true to update the screen
- if (screen) {
- _vm->_system->unlockScreen();
+ _vm->_system->unlockScreen();
+
+ // Increment frame
+ _curFrame++;
+ if (_curFrame == _frameScripts.size())
+ _curFrame = 0;
+
+ // Set the new time
+ _lastFrameTime = _vm->_system->getMillis();
+}
+
+WaterEffect::~WaterEffect() {
+ for (uint i = 0; i < _frameScripts.size(); i++) {
+ delete _frameScripts[i];
}
}
@@ -731,7 +740,9 @@ Graphics::Surface *RivenGraphics::getEffectScreen() {
}
void RivenGraphics::updateEffects() {
- runScheduledWaterEffects();
+ if (_waterEffect && _vm->_vars["waterenabled"] != 0) {
+ _waterEffect->update();
+ }
if (_fliesEffect) {
_fliesEffect->update();
diff --git a/engines/mohawk/riven_graphics.h b/engines/mohawk/riven_graphics.h
index 62c48d1a9e..31ab84038c 100644
--- a/engines/mohawk/riven_graphics.h
+++ b/engines/mohawk/riven_graphics.h
@@ -29,6 +29,7 @@ namespace Mohawk {
class MohawkEngine_Riven;
class FliesEffect;
+class WaterEffect;
enum RivenTransition {
kRivenTransitionNone = -1,
@@ -75,7 +76,7 @@ public:
// Water Effect
void scheduleWaterEffect(uint16);
- void clearWaterEffects();
+ void clearWaterEffect();
// Flies Effect
void setFliesEffect(uint16 count, bool fireflies);
@@ -106,23 +107,8 @@ private:
bool _screenUpdateRunning;
bool _enableCardUpdateScript;
- // Water Effects
- struct SFXERecord {
- // Record values
- uint16 frameCount;
- Common::Rect rect;
- uint16 speed;
- Common::Array<Common::SeekableReadStream *> frameScripts;
-
- // Cur frame
- uint16 curFrame;
- uint32 lastFrameTime;
- };
- Common::Array<SFXERecord> _waterEffects;
-
- void runScheduledWaterEffects();
-
- // Flies Effect
+ // Effects
+ WaterEffect *_waterEffect;
FliesEffect *_fliesEffect;
// Transitions
@@ -147,6 +133,29 @@ private:
};
/**
+ * Move slightly the water portions of a view to simulate waves
+ */
+class WaterEffect {
+public:
+ WaterEffect(MohawkEngine_Riven *vm, uint16 sfxeID);
+ ~WaterEffect();
+
+ void update();
+
+private:
+ MohawkEngine_Riven *_vm;
+
+ // Record values
+ Common::Rect _rect;
+ uint16 _speed;
+ Common::Array<Common::SeekableReadStream *> _frameScripts;
+
+ // Cur frame
+ uint16 _curFrame;
+ uint32 _lastFrameTime;
+};
+
+/**
* The flies effect draws flies in the scene
*
* It can draw either regular flies or fireflies.