[Scummvm-git-logs] scummvm master -> 661487c2b5c8376719d994fc9300cf2393dfce9f

bgK bastien.bouclet at gmail.com
Wed Sep 20 07:24:02 CEST 2017


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
56b744f5f1 MOHAWK: Riven: Plug memory leak when saving
661487c2b5 MOHAWK: Riven: Move the water effect to its own class


Commit: 56b744f5f15e15c01fbd89db88a595d95f1c71cb
    https://github.com/scummvm/scummvm/commit/56b744f5f15e15c01fbd89db88a595d95f1c71cb
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2017-09-20T07:12:09+02:00

Commit Message:
MOHAWK: Riven: Plug memory leak when saving

Fixes #10216.

Changed paths:
    engines/mohawk/riven_saveload.cpp


diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp
index 808eff6..7165166 100644
--- a/engines/mohawk/riven_saveload.cpp
+++ b/engines/mohawk/riven_saveload.cpp
@@ -287,7 +287,7 @@ Common::Error RivenSaveLoad::loadGame(const int slot) {
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVERSSection() {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 	if (_vm->getFeatures() & GF_DVD)
 		stream->writeUint32BE(kDVDSaveGameVersion);
 	else
@@ -296,7 +296,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVERSSection() {
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 
 	for (RivenVariableMap::const_iterator it = _vm->_vars.begin(); it != _vm->_vars.end(); it++) {
 		stream->writeUint32BE(1); // Reference counter
@@ -312,7 +312,7 @@ static int stringCompareToIgnoreCase(const Common::String &s1, const Common::Str
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genNAMESection() {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 
 	stream->writeUint16BE(_vm->_vars.size());
 
@@ -354,7 +354,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genNAMESection() {
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genZIPSSection() {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 
 	stream->writeUint16BE(_vm->_zipModeData.size());
 
@@ -368,7 +368,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genZIPSSection() {
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genTHMBSection() const {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 
 	Graphics::saveThumbnail(*stream);
 
@@ -376,7 +376,7 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genTHMBSection() const {
 }
 
 Common::MemoryWriteStreamDynamic *RivenSaveLoad::genMETASection(const Common::String &desc) const {
-	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic();
+	Common::MemoryWriteStreamDynamic *stream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 	Common::Serializer serializer = Common::Serializer(nullptr, stream);
 
 	TimeDate t;


Commit: 661487c2b5c8376719d994fc9300cf2393dfce9f
    https://github.com/scummvm/scummvm/commit/661487c2b5c8376719d994fc9300cf2393dfce9f
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2017-09-20T07:16:20+02:00

Commit Message:
MOHAWK: Riven: Move the water effect to its own class

Fixes the per frame scripts being leaked.
Fixes #10215.

Changed paths:
    engines/mohawk/riven_card.cpp
    engines/mohawk/riven_graphics.cpp
    engines/mohawk/riven_graphics.h


diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp
index feea22a..7a5cd61 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 b9d82fb..c80e9e5 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 62c48d1..31ab840 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.





More information about the Scummvm-git-logs mailing list