[Scummvm-cvs-logs] scummvm master -> 562649c7c03a25fc2ea64cb9d1aa4e3f4938d9ea

m-kiewitz m_kiewitz at users.sourceforge.net
Tue Feb 16 03:18:34 CET 2016


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:
562649c7c0 AGI: Change how VM timer vars are handled


Commit: 562649c7c03a25fc2ea64cb9d1aa4e3f4938d9ea
    https://github.com/scummvm/scummvm/commit/562649c7c03a25fc2ea64cb9d1aa4e3f4938d9ea
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2016-02-16T03:18:10+01:00

Commit Message:
AGI: Change how VM timer vars are handled

Instead of directly converting play time to VM timer vars,
we only adjust VM timer vars according to play time seconds delta.
This is needed for at least Mixed Up Mother Goose. The game
sets the VM "second" variable to 0 and then uses it for syncing
the text to the songs. We even adjust second calculation, so
that the timing should always be the same and not depend on
basically luck (seconds may wrap right after setting it, because
internal cycles counter is not changed).

Changed paths:
    engines/agi/agi.h
    engines/agi/global.cpp



diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index fe70c4e..c5db1df 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -870,6 +870,10 @@ private:
 	uint32 _getVarSecondsHeuristicLastInstructionCounter; /**< last time VM_VAR_SECONDS were read */
 	uint16 _getVarSecondsHeuristicCounter; /**< how many times heuristic was triggered */
 
+	uint32 _playTimeInSecondsAdjust; /**< milliseconds to adjust for calculating current play time in seconds, see setVarSecondsTrigger() */
+
+	void setVarSecondsTrigger(byte newSeconds);
+
 public:
 	// Some submethods of testIfCode
 	void skipInstruction(byte op);
diff --git a/engines/agi/global.cpp b/engines/agi/global.cpp
index a7a39e9..48e1c22 100644
--- a/engines/agi/global.cpp
+++ b/engines/agi/global.cpp
@@ -54,8 +54,13 @@ void AgiBase::flipFlag(int16 flagNr) {
 void AgiEngine::setVar(int16 varNr, byte newValue) {
 	_game.vars[varNr] = newValue;
 
-	if (varNr == VM_VAR_VOLUME) {
+	switch (varNr) {
+	case VM_VAR_SECONDS:
+		setVarSecondsTrigger(newValue);
+		break;
+	case VM_VAR_VOLUME:
 		setVolumeViaScripts(newValue);
+		break;
 	}
 }
 
@@ -173,6 +178,7 @@ void AgiEngine::getVarSecondsHeuristicTrigger() {
 void AgiEngine::inGameTimerReset(uint32 newPlayTime) {
 	_lastUsedPlayTimeInCycles = newPlayTime / 50;
 	_lastUsedPlayTimeInSeconds = newPlayTime / 1000;
+	_playTimeInSecondsAdjust = 0; // no adjust for now
 	setTotalPlayTime(newPlayTime);
 	inGameTimerResetPassedCycles();
 }
@@ -192,6 +198,24 @@ uint32 AgiEngine::inGameTimerGetPassedCycles() {
 	return _passedPlayTimeCycles;
 }
 
+// Seconds got set by the game
+// This happens in Mixed Up Mother Goose. The game syncs the songs to VM_VAR_SECONDS, but instead
+// of only reading them, it sets it to 0 and then checks if it reached a certain second.
+// The original interpreter didn't reset the internal cycles counter. Which means the timing was never accurate,
+// because the cycles counter may just overflow right after setting the seconds, which means a second
+// increase almost immediately happened. We even fix this issue by adjusting for it.
+void AgiEngine::setVarSecondsTrigger(byte newSeconds) {
+	// Adjust in game timer, so that VM timer variables are accurate
+	inGameTimerUpdate();
+
+	// Adjust VM seconds again
+	_game.vars[VM_VAR_SECONDS] = newSeconds;
+
+	// Calculate milliseconds adjust (see comment above)
+	uint32 curPlayTimeMilliseconds = inGameTimerGet();
+	_playTimeInSecondsAdjust = curPlayTimeMilliseconds % 1000;
+}
+
 // This is called, when one of the timer variables is read
 // We calculate the latest variables, according to current official playtime
 // This is also called in the main loop, because the game needs to be sync'd to 20 cycles per second
@@ -212,6 +236,14 @@ void AgiEngine::inGameTimerUpdate() {
 	_lastUsedPlayTimeInCycles = curPlayTimeCycles;
 
 	// Now calculate current play time in seconds
+	if (_playTimeInSecondsAdjust) {
+		// Apply adjust from setVarSecondsTrigger()
+		if (curPlayTimeMilliseconds >= _playTimeInSecondsAdjust) {
+			curPlayTimeMilliseconds -= _playTimeInSecondsAdjust;
+		} else {
+			curPlayTimeMilliseconds = 0;
+		}
+	}
 	uint32 curPlayTimeSeconds = curPlayTimeMilliseconds / 1000;
 
 	if (curPlayTimeSeconds == _lastUsedPlayTimeInSeconds) {
@@ -219,26 +251,50 @@ void AgiEngine::inGameTimerUpdate() {
 		return;
 	}
 
-	uint32 secondsLeft = 0;
-	byte   curDays = 0;
-	byte   curHours = 0;
-	byte   curMinutes = 0;
-	byte   curSeconds = 0;
+	int32 playTimeSecondsDelta = curPlayTimeSeconds - _lastUsedPlayTimeInSeconds;
 
-	curDays = curPlayTimeSeconds / 86400;
-	secondsLeft = curPlayTimeSeconds % 86400;
+	if (playTimeSecondsDelta > 0) {
+		// Read and write to VM vars directly to avoid endless loop
+		uint32 secondsLeft = playTimeSecondsDelta;
+		byte   curSeconds = _game.vars[VM_VAR_SECONDS];
+		byte   curMinutes = _game.vars[VM_VAR_MINUTES];
+		byte   curHours = _game.vars[VM_VAR_HOURS];
+		byte   curDays = _game.vars[VM_VAR_DAYS];
 
-	curHours = secondsLeft / 3600;
-	secondsLeft = secondsLeft % 3600;
+		// Add delta to VM variables
+		if (secondsLeft >= 86400) {
+			curDays += secondsLeft / 86400;
+			secondsLeft = secondsLeft % 86400;
+		}
+		if (secondsLeft >= 3600) {
+			curHours += secondsLeft / 3600;
+			secondsLeft = secondsLeft % 3600;
+		}
+		if (secondsLeft >= 60) {
+			curMinutes += secondsLeft / 60;
+			secondsLeft = secondsLeft % 60;
+		}
+		curSeconds += secondsLeft;
 
-	curMinutes = secondsLeft / 60;
-	curSeconds = secondsLeft % 60;
+		while (curSeconds > 59) {
+			curSeconds -= 60;
+			curMinutes++;
+		}
+		while (curMinutes > 59) {
+			curMinutes -= 60;
+			curHours++;
+		}
+		while (curHours > 23) {
+			curHours -= 24;
+			curDays++;
+		}
 
-	// directly set them, otherwise we would go into an endless loop
-	_game.vars[VM_VAR_SECONDS] = curSeconds;
-	_game.vars[VM_VAR_MINUTES] = curMinutes;
-	_game.vars[VM_VAR_HOURS] = curHours;
-	_game.vars[VM_VAR_DAYS] = curDays;
+		// directly set them
+		_game.vars[VM_VAR_SECONDS] = curSeconds;
+		_game.vars[VM_VAR_MINUTES] = curMinutes;
+		_game.vars[VM_VAR_HOURS] = curHours;
+		_game.vars[VM_VAR_DAYS] = curDays;
+	}
 
 	_lastUsedPlayTimeInSeconds = curPlayTimeSeconds;
 }






More information about the Scummvm-git-logs mailing list