[Scummvm-git-logs] scummvm master -> 647e3e3b15baf8145eb4b0c3a68a8722a602525c

antoniou79 a.antoniou79 at gmail.com
Wed Jun 16 15:25:35 UTC 2021


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

Summary:
647e3e3b15 BLADERUNNER: Fix for resuming while a special loop plays


Commit: 647e3e3b15baf8145eb4b0c3a68a8722a602525c
    https://github.com/scummvm/scummvm/commit/647e3e3b15baf8145eb4b0c3a68a8722a602525c
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2021-06-16T18:25:25+03:00

Commit Message:
BLADERUNNER: Fix for resuming while a special loop plays

This is a better fix for the Zuben soup dump glitch (no exits) if user holds Esc down

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h


diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 4434ec312a..c45f1b2c73 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -1126,6 +1126,7 @@ void BladeRunnerEngine::gameTick() {
 	bool backgroundChanged = false;
 	int frame = _scene->advanceFrame();
 	if (frame >= 0) {
+//		debug("_sceneScript->sceneFrameAdvanced(%d)", frame);
 		_sceneScript->sceneFrameAdvanced(frame);
 		backgroundChanged = true;
 	}
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 16dad7ef88..ace23893ba 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -299,7 +299,6 @@ void Scene::resume(bool isLoadingGame) {
 			loopStartSpecial(_specialLoopMode, _specialLoop, true);
 			if (_specialLoopMode == kSceneLoopModeLoseControl || _specialLoopMode == kSceneLoopModeChangeSet) {
 				_vm->playerGainsControl();
-
 			}
 		}
 		if (_specialLoopMode == kSceneLoopModeChangeSet) {
@@ -307,9 +306,19 @@ void Scene::resume(bool isLoadingGame) {
 		}
 	}
 
-	int frame;
+	int frame, frameStart, frameEnd;
 	do {
+		// fast forward to targetFrame but do, at the very least, one advanceFrame() (with time=false)
 		frame = advanceFrame(false);
+		// check if active loop has changed, and we need to adjust targetFrame
+		if (_vqaPlayer->getCurrentBeginAndEndFrame(frame, &frameStart, &frameEnd)
+		    && targetFrame >= 0
+		    && (targetFrame < frameStart || targetFrame > frameEnd)
+		) {
+			// active loop has changed, and targetFrame has a remnant frame value from the previous loop's frameset,
+			// so set it to the current loop's start
+			targetFrame = frameStart;
+		}
 	} while (frame >= 0 && frame != targetFrame);
 
 	if (!isLoadingGame) {
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 6e8706c5b5..57760868c7 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -567,6 +567,17 @@ bool VQADecoder::getLoopBeginAndEndFrame(int loop, int *begin, int *end) {
 	return true;
 }
 
+int VQADecoder::getLoopIdFromFrame(int frame) {
+	if (frame >= 0) {
+		for (int loopId = 0; loopId < _loopInfo.loopCount; ++loopId) {
+			if (frame >= _loopInfo.loops[loopId].begin && frame <= _loopInfo.loops[loopId].end) {
+				return loopId;
+			}
+		}
+	}
+	return -1;
+}
+
 bool VQADecoder::readCLIP(Common::SeekableReadStream *s, uint32 size) {
 	s->skip(roundup(size));
 	return true;
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 3690b73184..34110d7c0c 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -81,6 +81,7 @@ public:
 	uint16 frequency() const { return _header.freq; }
 
 	bool getLoopBeginAndEndFrame(int loop, int *begin, int *end);
+	int  getLoopIdFromFrame(int frame);
 
 	struct Header {
 		uint16 version;     // 0x00
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index fdf37e27b8..b29cfde1f8 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -62,9 +62,9 @@ bool VQAPlayer::open() {
 	}
 
 	_repeatsCount = 0;
-	_loop = -1;
+	_loopNext = -1;
 	_frame = -1;
-	_frameBegin = -1;
+	_frameBeginNext = -1;
 	_frameEnd = getFrameCount() - 1;
 	_frameEndQueued = -1;
 	_repeatsCountQueued = -1;
@@ -94,7 +94,7 @@ int VQAPlayer::update(bool forceDraw, bool advanceFrame, bool useTime, Graphics:
 	int result = -1;
 
 	if (_frameNext < 0) {
-		_frameNext = _frameBegin;
+		_frameNext = _frameBeginNext;
 	}
 
 	if ((_repeatsCount > 0 || _repeatsCount == -1) && (_frameNext > _frameEnd)) {
@@ -111,16 +111,20 @@ int VQAPlayer::update(bool forceDraw, bool advanceFrame, bool useTime, Graphics:
 			// The code is similar to Scene::advanceFrame()
 			// This will be done once, since this first loop (loopId 1)
 			// is only executed once before moving on to loopId 2
-			if (_name.equals("MA05_3.VQA") && _loop == 1) {
+			if (_name.equals("MA05_3.VQA") && _loopNext == 1) {
 				while (update(false, true, false) != 59) {
 					updateZBuffer(_vm->_zbuffer);
 				}
-				_frameBegin = 60;
+				// This works because the loopId 1 executes once before moving to _loop 2
+				// See Scene::advanceFrame()
+				//     Scene::loopEnded()
+				//
+				_frameBeginNext = 60;
 			}
 #endif
 		}
-		if (_frameNext != _frameBegin) {
-			_frameNext = _frameBegin;
+		if (_frameNext != _frameBeginNext) {
+			_frameNext = _frameBeginNext;
 		}
 
 		if (loopEndQueued == -1) {
@@ -133,10 +137,9 @@ int VQAPlayer::update(bool forceDraw, bool advanceFrame, bool useTime, Graphics:
 			_repeatsCountQueued = -1;
 
 			if (_callbackLoopEnded != nullptr) {
-				_callbackLoopEnded(_callbackData, 0, _loop);
+				_callbackLoopEnded(_callbackData, 0, _loopNext);
 			}
 		}
-
 		result = -1;
 	} else if (_frameNext > _frameEnd) {
 		result = -3;
@@ -254,7 +257,7 @@ bool VQAPlayer::setLoop(int loop, int repeatsCount, int loopSetMode, void (*call
 		return false;
 	}
 	if (setBeginAndEndFrame(begin, end, repeatsCount, loopSetMode, callback, callbackData)) {
-		_loop = loop;
+		_loopNext = loop;
 		return true;
 	}
 	return false;
@@ -276,12 +279,12 @@ bool VQAPlayer::setBeginAndEndFrame(int begin, int end, int repeatsCount, int lo
 	}
 
 	if (_repeatsCount == 0 && loopSetMode == kLoopSetModeEnqueue) {
-		// if the member var _repeatsCount is 0 (which means "don't repeat existing loop")
-		// then execute set the enqueued loop for immediate execution
+		// if the member var _repeatsCount is 0 (which means "current playing loop will not be repeated")
+		// then do not enqueue and, instead, treat the request as kLoopSetModeImmediate
 		loopSetMode = kLoopSetModeImmediate;
 	}
 
-	_frameBegin = begin;
+	_frameBeginNext = begin;
 
 	if (loopSetMode == kLoopSetModeJustStart) {
 		_repeatsCount = repeatsCount;
@@ -307,6 +310,14 @@ bool VQAPlayer::seekToFrame(int frame) {
 	return true;
 }
 
+bool VQAPlayer::getCurrentBeginAndEndFrame(int frame, int *begin, int *end) {
+	int playingLoop = _decoder.getLoopIdFromFrame(frame);
+	if (playingLoop != -1) {
+		return _decoder.getLoopBeginAndEndFrame(playingLoop, begin, end);
+	}
+	return false;
+}
+
 int VQAPlayer::getLoopBeginFrame(int loop) {
 	int begin, end;
 	if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) {
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index c3e1e99fd1..8b7efe6914 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -33,9 +33,9 @@
 namespace BladeRunner {
 
 enum LoopSetModes {
-	kLoopSetModeJustStart = 0,
-	kLoopSetModeEnqueue = 1,
-	kLoopSetModeImmediate = 2
+	kLoopSetModeJustStart = 0, // sets _frameBeginNext, _repeatsCount, _frameEnd
+	kLoopSetModeEnqueue   = 1, // sets _frameBeginNext, _repeatsCountQueued, _frameEndQueued
+	kLoopSetModeImmediate = 2  // like ModeJustStart, but also sets _frameNext to _frameBeginNext and updates _frameNextTime to current
 };
 
 class BladeRunnerEngine;
@@ -58,10 +58,18 @@ class VQAPlayer {
 
 	int _frame;
 	int _frameNext;
-	int _frameBegin;
-	int _frameEnd;
-	int _loop;
-	int _repeatsCount;
+	int _frameBeginNext; // The frame to begin from, after current playing loop ends.
+	                     // Does not necessarily reflect current playing loop's start frame
+	int _frameEnd;       // The frame to end at for current playing loop
+	int _loopNext;       // Does not necessarily reflect current playing loop's id
+	                     // Used: - as param for _callbackLoopEnded() (which typically is loopEnded()), but never actually used in there)
+	                     //       - for the MA05 inshot glitch workaround
+	                     // It is set at every setLoop call except for the _loopInitial case (when no video stream is loaded)
+	int _repeatsCount;   // -1 loop forever
+	                     //  0 final repetition (or don't repeat after playing)
+	                     //    When that repetition is completeed VQAPlayer::update() returns -3 value
+	                     //    See Scene::advanceFrame() and OuttakePlayer::play() for checks for -3 result
+	                     // Value is decreased per completed loop of current playing videoloop until it reaches 0
 
 	int _repeatsCountQueued;
 	int _frameEndQueued;
@@ -90,9 +98,9 @@ public:
 		  _audioStream(nullptr),
 		  _frame(-1),
 		  _frameNext(-1),
-		  _frameBegin(-1),
+		  _frameBeginNext(-1),
 		  _frameEnd(-1),
-		  _loop(-1),
+		  _loopNext(-1),
 		  _repeatsCount(-1),
 		  _repeatsCountQueued(-1),
 		  _frameEndQueued(-1),
@@ -123,6 +131,7 @@ public:
 
 	bool seekToFrame(int frame);
 
+	bool getCurrentBeginAndEndFrame(int frame, int *begin, int *end);
 	int getLoopBeginFrame(int loop);
 	int getLoopEndFrame(int loop);
 




More information about the Scummvm-git-logs mailing list