[Scummvm-git-logs] scummvm master -> ea07939c1be5a8bab7263c96163a36e63d41be9f

moralrecordings noreply at scummvm.org
Fri Feb 9 13:18:06 UTC 2024


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

Summary:
10b2abcd9b DIRECTOR: Fix MacArchive::getFileSize()
67562eaded DIRECTOR: Prevent repeats in DirectorSound::playExternalSound
6c6565bbe5 DIRECTOR: Clear cast ID in D2 when sprite is a shape
2efa99bda9 DIRECTOR: Cap palette cycling framerate to _fpsLimit
e03afb0a45 DIRECTOR: Allow calls to b_label with integer argument
d3ffe66fe5 DIRECTOR: Fix handling of relative path markers
b163dba86d DIRECTOR: Add CD loading delay quirk
ea07939c1b DIRECTOR: Fix Channel::setClean resetting the same video


Commit: 10b2abcd9ba4752cc0b77f2de4b51407355caf38
    https://github.com/scummvm/scummvm/commit/10b2abcd9ba4752cc0b77f2de4b51407355caf38
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Fix MacArchive::getFileSize()

Changed paths:
    engines/director/archive.cpp
    engines/director/archive.h
    engines/director/lingo/lingo-the.cpp


diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 9cdcf7ef044..9af5678833b 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -110,7 +110,7 @@ void Archive::listUnaccessedChunks() {
 		debugC(5, kDebugLoading, "Unaccessed Chunks in '%s':\n%s", _pathName.toString(g_director->_dirSeparator).c_str(), s.c_str());
 }
 
-int Archive::getFileSize() {
+uint32 Archive::getFileSize() {
 	if (!_stream)
 		return 0;
 
@@ -301,6 +301,13 @@ MacArchive::~MacArchive() {
 	delete _resFork;
 }
 
+uint32 MacArchive::getFileSize() {
+	if (!_resFork)
+		return 0;
+
+	return _resFork->getResForkDataSize();
+}
+
 void MacArchive::close() {
 	Archive::close();
 	delete _resFork;
diff --git a/engines/director/archive.h b/engines/director/archive.h
index a537287c29d..0336cb1ca81 100644
--- a/engines/director/archive.h
+++ b/engines/director/archive.h
@@ -62,7 +62,7 @@ public:
 	Common::Path getPathName() const { return _pathName; }
 	Common::String getFileName() const;
 	void setPathName(const Common::Path &name) { _pathName = name; }
-	int getFileSize();
+	virtual uint32 getFileSize();
 
 	bool isOpen() const { return _stream != 0; }
 
@@ -102,6 +102,7 @@ public:
 	MacArchive();
 	~MacArchive() override;
 
+	uint32 getFileSize() override;
 	void close() override;
 	bool openFile(const Common::Path &path) override;
 	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0) override;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 14f3be8c617..02414c85a74 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -719,7 +719,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 		d = 0;	// Let's pretend the movie is compactified
 		break;
 	case kTheMovieFileSize:
-		d = movie->getArchive()->getFileSize();
+		d = (int)movie->getArchive()->getFileSize();
 		break;
 	case kTheMoviePath:
 	case kThePathName:


Commit: 67562eaded90f7e24f319e103a96da644b8a560e
    https://github.com/scummvm/scummvm/commit/67562eaded90f7e24f319e103a96da644b8a560e
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Prevent repeats in DirectorSound::playExternalSound

This should give the same behaviour as DirectorSound::playCastMember.

Fixes sounds playing twice if the animation takes too long in Spaceship
Warlock (e.g. the hovertaxi landing in the demo).

Changed paths:
    engines/director/sound.cpp


diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 3c15fc3d59e..f89cb512323 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -431,7 +431,8 @@ void DirectorSound::playExternalSound(uint16 menu, uint16 submenu, uint8 soundCh
 		return;
 
 	SoundID soundId(kSoundExternal, menu, submenu);
-	if (isChannelActive(soundChannel) && isLastPlayedSound(soundChannel, soundId))
+	// If the sound is the same ID ast the last played, do nothing.
+	if (isLastPlayedSound(soundChannel, soundId))
 		return;
 
 	if (menu < kMinSampledMenu || menu > kMaxSampledMenu) {


Commit: 6c6565bbe5eb7204553720452c0d25226bf1d944
    https://github.com/scummvm/scummvm/commit/6c6565bbe5eb7204553720452c0d25226bf1d944
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Clear cast ID in D2 when sprite is a shape

Fixes various graphical artifacts, e.g. movie ENG:J11 at 230
of Spaceship Warlock having a big steam cloud in the top-left instead of
the left-turn hotspot, the Invictus logo in Over-Ring-Under having a
large white box to the right of the text.

Changed paths:
    engines/director/frame.cpp


diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 97de843d10e..04ca634ed7d 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -327,7 +327,9 @@ void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 6:
 			if (sprite.isQDShape()) {
 				sprite._pattern = stream.readUint16();
+				sprite._castId = CastMemberID(0, 0);
 			} else {
+				sprite._pattern = 0;
 				sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
 			}
 			break;


Commit: 2efa99bda936d67f151a40028af27a3f06dac9ff
    https://github.com/scummvm/scummvm/commit/2efa99bda936d67f151a40028af27a3f06dac9ff
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Cap palette cycling framerate to _fpsLimit

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 5db7124993b..3be132d0aa9 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -776,6 +776,9 @@ bool Score::renderPrePaletteCycle(RenderMode mode) {
 		if (debugChannelSet(-1, kDebugFast))
 			frameRate = 30;
 
+		if (g_director->_fpsLimit)
+			frameRate = MIN((int)g_director->_fpsLimit, frameRate);
+
 		int frameDelay = 1000 / 60;
 		int fadeFrames = kFadeColorFrames[frameRate - 1];
 		if (_vm->getVersion() >= 500)
@@ -939,6 +942,10 @@ void Score::renderPaletteCycle(RenderMode mode) {
 	if (speed == 0)
 		return;
 
+	// Apply the global FPS limit if required
+	if (g_director->_fpsLimit)
+		speed = MIN((int)g_director->_fpsLimit, speed);
+
 	if (debugChannelSet(-1, kDebugFast))
 		speed = 30;
 
@@ -963,7 +970,7 @@ void Score::renderPaletteCycle(RenderMode mode) {
 
 			// Do a full color cycle in one frame transition
 			int steps = lastColor - firstColor + 1;
-			debugC(2, kDebugImages, "Score::renderPaletteCycle(): color cycle palette %s, from colors %d to %d, over %d steps %d times", currentPalette.asString().c_str(), firstColor, lastColor, steps, _currentFrame->_mainChannels.palette.cycleCount);
+			debugC(2, kDebugImages, "Score::renderPaletteCycle(): color cycle palette %s, from colors %d to %d, over %d steps %d times (delay: %d ms)", currentPalette.asString().c_str(), firstColor, lastColor, steps, _currentFrame->_mainChannels.palette.cycleCount, delay);
 			for (int i = 0; i < _currentFrame->_mainChannels.palette.cycleCount; i++) {
 				for (int j = 0; j < steps; j++) {
 					uint32 startTime = g_system->getMillis();
@@ -1096,6 +1103,9 @@ void Score::renderPaletteCycle(RenderMode mode) {
 				if (debugChannelSet(-1, kDebugFast))
 					frameRate = 30;
 
+				if (g_director->_fpsLimit)
+					frameRate = MIN((int)g_director->_fpsLimit, frameRate);
+
 				int frameDelay = 1000 / 60;
 				int fadeFrames = kFadeColorFrames[frameRate - 1];
 				if (_vm->getVersion() >= 500)


Commit: e03afb0a457a2639f5ad2d01fdea0f669a9aa0d3
    https://github.com/scummvm/scummvm/commit/e03afb0a457a2639f5ad2d01fdea0f669a9aa0d3
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Allow calls to b_label with integer argument

Fixes the story playback mode in Astrid Lindgren's Pippi.

Changed paths:
    engines/director/lingo/lingo-builtins.cpp


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 7c466b83c32..92ea83bf5b5 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -2276,10 +2276,15 @@ void LB::b_installMenu(int nargs) {
 }
 
 void LB::b_label(int nargs) {
+	// label functions as marker when the input is an int
 	Datum d = g_lingo->pop();
-	uint16 label = g_lingo->func_label(d);
-
-	g_lingo->push(label);
+	int marker;
+	if (d.type == STRING) {
+		marker = g_lingo->func_label(d);
+	} else {
+		marker = g_lingo->func_marker(d.asInt());
+	}
+	g_lingo->push(marker);
 }
 
 void LB::b_marker(int nargs) {


Commit: d3ffe66fe58fd712fae8256b3478edc23437e2e6
    https://github.com/scummvm/scummvm/commit/d3ffe66fe58fd712fae8256b3478edc23437e2e6
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Fix handling of relative path markers

It is possible to use relative path syntax (e.g. multiple colons in Mac
path syntax, . or .. in Windows path syntax) to move up the directory
tree in relation to the current path. Because resolvePath() works from a
fixed base, we have to rectify any paths with relative markers so they
become an absolute path, which is then resolved in the usual way.

Fixes entering the bridge for the Asteroid or Terra missions in
Spaceship Warlock; both of these movies need to jump to a movie
named BBalcView in a different folder, and without rectification it will
select BBalcView in the current (WARLOCKSHIP) folder which is used for
the first mission only.

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/util.cpp
    engines/director/util.h


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 92ea83bf5b5..d4f3290205f 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1210,7 +1210,9 @@ void LB::b_getNthFileNameInFolder(int nargs) {
 		return;
 	}
 
-	Common::Path path = findPath(pathRaw, true, true, true);
+	// getNthFileNameInFolder requires an absolute path as an input.
+	// relative paths will not match anything.
+	Common::Path path = findAbsolutePath(pathRaw, true);
 	// for directory, we either return the correct path, which we can access recursively.
 	// or we get a wrong path, which will lead us to a non-exist file node
 
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 5e5ee913eed..48dc4a8806c 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -24,6 +24,7 @@
 #include "common/macresman.h"
 #include "common/memstream.h"
 #include "common/punycode.h"
+#include "common/str-array.h"
 #include "common/tokenizer.h"
 #include "common/compression/deflate.h"
 
@@ -454,6 +455,55 @@ bool isAbsolutePath(const Common::String &path) {
 	return false;
 }
 
+bool isPathWithRelativeMarkers(const Common::String &path) {
+	if (path.contains("::"))
+		return true;
+	if (path.hasPrefix(".\\") || path.hasSuffix("\\.") || path.contains("\\.\\"))
+		return true;
+	if (path.hasPrefix("..\\") || path.hasSuffix("\\..") || path.contains("\\..\\"))
+		return true;
+	return false;
+}
+
+
+Common::String rectifyRelativePath(const Common::String &path, const Common::Path &base) {
+	Common::StringArray components = base.splitComponents();
+	uint32 idx = 0;
+
+	while (idx < path.size()) {
+		uint32 start = idx;
+		while (idx < path.size() && path[idx] != ':' && path[idx] != '\\')
+			idx++;
+		Common::String comp = path.substr(start, idx - start);
+		if (comp.equals("..") && !components.empty()) {
+			components.pop_back();
+		} else if (!comp.empty() && !comp.equals(".")) {
+			components.push_back(comp);
+		}
+		if (idx >= path.size())
+			break;
+
+		if (path[idx] == ':') {
+			idx += 1;
+			while (idx < path.size() && path[idx] == ':') {
+				if (!components.empty())
+					components.pop_back();
+				idx += 1;
+			}
+			continue;
+		}
+
+		if (path[idx] == '\\') {
+			idx += 1;
+			continue;
+		}
+	}
+	Common::String result = "@:" + Common::Path::joinComponents(components).toString(g_director->_dirSeparator);
+	debug(9, "rectifyRelativePath(): '%s' + '%s' => '%s'", base.toString(g_director->_dirSeparator).c_str(), path.c_str(), result.c_str());
+	return result;
+}
+
+
 Common::Path toSafePath(const Common::String &path) {
 	// Encode a Director raw path as a platform-independent path.
 	// This needs special care, as Mac filenames allow using '/' in them!
@@ -778,6 +828,20 @@ Common::Path resolvePartialPathWithFuzz(const Common::String &path, const Common
 	return result;
 }
 
+Common::Path findAbsolutePath(const Common::String &path, bool directory, const char **exts) {
+	Common::Path result, base;
+	if (isAbsolutePath(path)) {
+		debugN(9, "%s", recIndent());
+		debug(9, "findAbsolutePath(): searching absolute path");
+		result = resolvePathWithFuzz(path, base, directory, exts);
+		if (!result.empty()) {
+			debugN(9, "%s", recIndent());
+			debug(9, "findAbsolutePath(): resolved \"%s\" -> \"%s\"", path.c_str(), result.toString().c_str());
+		}
+	}
+	return result;
+}
+
 Common::Path findPath(const Common::Path &path, bool currentFolder, bool searchPaths, bool directory, const char **exts) {
 	return findPath(path.toString(g_director->_dirSeparator), currentFolder, searchPaths, directory, exts);
 }
@@ -786,28 +850,30 @@ Common::Path findPath(const Common::String &path, bool currentFolder, bool searc
 	Common::Path result, base;
 	debugN(9, "%s", recIndent());
 	debug(9, "findPath(): beginning search for \"%s\"", path.c_str());
+
+	Common::String currentPath = g_director->getCurrentPath();
+	Common::Path current = resolvePath(currentPath, base, true, exts);
+
+	Common::String testPath = path;
+	// If the path contains relative elements, rectify it with respect to the current folder
+	if (isPathWithRelativeMarkers(testPath)) {
+		testPath = rectifyRelativePath(testPath, current);
+	}
+
 	// For an absolute path, first check it relative to the filesystem
-	if (isAbsolutePath(path)) {
-		debugN(9, "%s", recIndent());
-		debug(9, "findPath(): searching absolute path");
-		result = resolvePathWithFuzz(path, base, directory, exts);
-		if (!result.empty()) {
-			debugN(9, "%s", recIndent());
-			debug(9, "findPath(): resolved \"%s\" -> \"%s\"", path.c_str(), result.toString().c_str());
-			return result;
-		}
+	result = findAbsolutePath(testPath, directory, exts);
+	if (!result.empty()) {
+		return result;
 	}
 
 	if (currentFolder) {
-		Common::String currentPath = g_director->getCurrentPath();
-		Common::Path current = resolvePath(currentPath, base, true, exts);
 		debugN(9, "%s", recIndent());
 		debug(9, "findPath(): searching current folder %s", current.toString().c_str());
 		base = current;
-		result = resolvePartialPathWithFuzz(path, base, directory, exts);
+		result = resolvePartialPathWithFuzz(testPath, base, directory, exts);
 		if (!result.empty()) {
 			debugN(9, "%s", recIndent());
-			debug(9, "findPath(): resolved \"%s\" -> \"%s\"", path.c_str(), result.toString().c_str());
+			debug(9, "findPath(): resolved \"%s\" -> \"%s\"", testPath.c_str(), result.toString().c_str());
 			return result;
 		}
 	}
@@ -816,10 +882,10 @@ Common::Path findPath(const Common::String &path, bool currentFolder, bool searc
 	debugN(9, "%s", recIndent());
 	debug(9, "findPath(): searching game root path");
 	base = Common::Path();
-	result = resolvePartialPathWithFuzz(path, base, directory, exts);
+	result = resolvePartialPathWithFuzz(testPath, base, directory, exts);
 	if (!result.empty()) {
 		debugN(9, "%s", recIndent());
-		debug(9, "findPath(): resolved \"%s\" -> \"%s\"", path.c_str(), result.toString().c_str());
+		debug(9, "findPath(): resolved \"%s\" -> \"%s\"", testPath.c_str(), result.toString().c_str());
 		return result;
 	}
 
@@ -845,10 +911,10 @@ Common::Path findPath(const Common::String &path, bool currentFolder, bool searc
 			}
 			debugN(9, "%s", recIndent());
 			debug(9, "findPath(): searching search path folder %s", searchIn.c_str());
-			result = resolvePartialPathWithFuzz(path, base, directory, exts);
+			result = resolvePartialPathWithFuzz(testPath, base, directory, exts);
 			if (!result.empty()) {
 				debugN(9, "%s", recIndent());
-				debug(9, "findPath(): resolved \"%s\" -> \"%s\"", path.c_str(), result.toString().c_str());
+				debug(9, "findPath(): resolved \"%s\" -> \"%s\"", testPath.c_str(), result.toString().c_str());
 				return result;
 			}
 		}
diff --git a/engines/director/util.h b/engines/director/util.h
index 96ff52658cc..fa594324fcc 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -47,6 +47,7 @@ Common::Path resolvePath(const Common::String &path, const Common::Path &base, b
 Common::Path resolvePartialPath(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
 Common::Path resolvePathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
 Common::Path resolvePartialPathWithFuzz(const Common::String &path, const Common::Path &base, bool directory, const char **exts);
+Common::Path findAbsolutePath(const Common::String &path, bool directory = false, const char **exts = nullptr);
 Common::Path findPath(const Common::Path &path, bool currentFolder = true, bool searchPaths = true, bool directory = false, const char **exts = nullptr);
 Common::Path findPath(const Common::String &path, bool currentFolder = true, bool searchPaths = true, bool directory = false, const char **exts = nullptr);
 Common::Path findMoviePath(const Common::String &path, bool currentFolder = true, bool searchPaths = true);


Commit: b163dba86d023fbd8ea1787e7f444e4bef8008d9
    https://github.com/scummvm/scummvm/commit/b163dba86d023fbd8ea1787e7f444e4bef8008d9
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Add CD loading delay quirk

Spaceship Warlock is optimised for very slow disk reads; quite a lot of
movie changes will be preceded by a music cue and a still image, knowing
that the system will take a couple of seconds to read the next file.

As a compromise, add a fake delay of [file size]*1000/150000 ms to movie
switches. This can be short-circuited by clicking the mouse, so it is
still possible to navigate around quickly.

Changed paths:
    engines/director/director.cpp
    engines/director/director.h
    engines/director/events.cpp
    engines/director/game-quirks.cpp
    engines/director/util.cpp
    engines/director/window.cpp


diff --git a/engines/director/director.cpp b/engines/director/director.cpp
index e51c1083584..ff4ab027145 100644
--- a/engines/director/director.cpp
+++ b/engines/director/director.cpp
@@ -101,6 +101,8 @@ DirectorEngine::DirectorEngine(OSystem *syst, const DirectorGameDescription *gam
 	_forceDate.tm_mon = -1;
 	_forceDate.tm_year = -1;
 	_forceDate.tm_wday = -1;
+	_loadSlowdownFactor = 0;
+	_loadSlowdownCooldownTime = 0;
 
 	_wm = nullptr;
 
diff --git a/engines/director/director.h b/engines/director/director.h
index bad39232397..1eaf1c257a2 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -228,12 +228,13 @@ public:
 	bool desktopEnabled();
 
 	// events.cpp
-	bool processEvents(bool captureClick = false);
+	bool processEvents(bool captureClick = false, bool skipWindowManager = false);
 	void processEventQUIT();
 	uint32 getMacTicks();
 
 	// game-quirks.cpp
 	void gameQuirks(const char *target, Common::Platform platform);
+	void loadSlowdownCooloff(uint32 delay = 2000);
 
 	void delayMillis(uint32 delay);
 
@@ -282,6 +283,8 @@ public:
 	// used for quirks
 	byte _fpsLimit;
 	TimeDate _forceDate;
+	uint32 _loadSlowdownFactor;
+	uint32 _loadSlowdownCooldownTime;
 
 private:
 	byte _currentPalette[768];
diff --git a/engines/director/events.cpp b/engines/director/events.cpp
index fb6416b2655..419c7406ccc 100644
--- a/engines/director/events.cpp
+++ b/engines/director/events.cpp
@@ -40,14 +40,14 @@ namespace Director {
 
 uint32 DirectorEngine::getMacTicks() { return (g_system->getMillis() * 60 / 1000.) - _tickBaseline; }
 
-bool DirectorEngine::processEvents(bool captureClick) {
+bool DirectorEngine::processEvents(bool captureClick, bool skipWindowManager) {
 	debugC(5, kDebugEvents, "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 	debugC(5, kDebugEvents, "@@@@   Processing events");
 	debugC(5, kDebugEvents, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
 
 	Common::Event event;
 	while (g_system->getEventManager()->pollEvent(event)) {
-		if (!_wm->processEvent(event)) {
+		if (skipWindowManager || !_wm->processEvent(event)) {
 			// We only want to handle these events if the event
 			// wasn't handled by the window manager.
 			switch (event.type) {
@@ -71,7 +71,7 @@ bool DirectorEngine::processEvents(bool captureClick) {
 			if (captureClick)
 				return true;
 			break;
-		case Common::EVENT_LBUTTONDOWN:
+		case Common::EVENT_LBUTTONUP:
 			if (captureClick)
 				return true;
 			break;
@@ -261,6 +261,7 @@ bool Movie::processEvent(Common::Event &event) {
 
 		_currentHiliteChannelId = 0;
 		_mouseDownWasInButton = false;
+		g_director->loadSlowdownCooloff();
 		return true;
 
 	case Common::EVENT_KEYDOWN:
@@ -276,6 +277,7 @@ bool Movie::processEvent(Common::Event &event) {
 			_lastTimeOut = _lastEventTime;
 
 		queueUserEvent(kEventKeyDown);
+		g_director->loadSlowdownCooloff();
 		return true;
 
 	case Common::EVENT_KEYUP:
diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 5ed1c48b6a2..416a0f74426 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -100,6 +100,11 @@ struct SaveFilePath {
 };
 
 
+static void quirkWarlock() {
+	g_director->_loadSlowdownFactor = 150000;  // emulate a 1x CD drive
+	g_director->_fpsLimit = 15;
+}
+
 static void quirkLimit15FPS() {
 	g_director->_fpsLimit = 15;
 }
@@ -175,6 +180,12 @@ struct Quirk {
 	Common::Platform platform;
 	void (*quirk)();
 } quirks[] = {
+	// Spaceship Warlock is designed to run as quickly as possible on a
+	// single speed CD drive; there's often content just before a movie
+	// transition which would otherwise get skipped past.
+	{ "warlock", Common::kPlatformMacintosh, &quirkWarlock },
+	{ "warlock", Common::kPlatformWindows, &quirkWarlock },
+
 	// Eastern Mind sets the score to play back at a high frame rate,
 	// however the developers were using slow hardware, so some
 	// animations play back much faster than intended.
@@ -253,6 +264,11 @@ void DirectorEngine::gameQuirks(const char *target, Common::Platform platform) {
 	}
 }
 
+void DirectorEngine::loadSlowdownCooloff(uint32 delay) {
+	if (_loadSlowdownFactor)
+		_loadSlowdownCooldownTime = g_system->getMillis() + delay;
+}
+
 /*****************
  * CachedArchive
  *****************/
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 48dc4a8806c..049bf95f922 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -500,6 +500,7 @@ Common::String rectifyRelativePath(const Common::String &path, const Common::Pat
 	}
 	Common::String result = "@:" + Common::Path::joinComponents(components).toString(g_director->_dirSeparator);
 	debug(9, "rectifyRelativePath(): '%s' + '%s' => '%s'", base.toString(g_director->_dirSeparator).c_str(), path.c_str(), result.c_str());
+	warning("rectifyRelativePath(): '%s' + '%s' => '%s'", base.toString(g_director->_dirSeparator).c_str(), path.c_str(), result.c_str());
 	return result;
 }
 
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index abebd3d9793..3083454ce4c 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -443,6 +443,32 @@ bool Window::loadNextMovie() {
 		return false;
 
 	probeResources(mov);
+
+	// Artificial delay for games that expect slow media, e.g. Spaceship Warlock
+	if (g_director->_loadSlowdownFactor && !debugChannelSet(-1, kDebugFast)) {
+		// Check that we're not cooling down from skipping a delay.
+		if (g_system->getMillis() > g_director->_loadSlowdownCooldownTime) {
+			uint32 delay = mov->getFileSize() * 1000 / g_director->_loadSlowdownFactor;
+			debugC(5, kDebugLoading, "Slowing load of next movie by %d ms", delay);
+			while (delay != 0) {
+				uint32 dec = MIN((uint32)10, delay);
+				// Skip delay if mouse is clicked
+				if (g_director->processEvents(true, true)) {
+					g_director->loadSlowdownCooloff();
+					break;
+				}
+				g_director->_wm->replaceCursor(Graphics::kMacCursorWatch);
+				g_director->draw();
+				g_system->delayMillis(dec);
+				delay -= dec;
+			}
+		}
+		// If this movie switch is within the cooldown time,
+		// don't add a delay. This is to allow for rapid navigation.
+		// User input events will call loadSlowdownCooloff() and
+		// extend the cooldown time.
+	}
+
 	_currentMovie = new Movie(this);
 	_currentMovie->setArchive(mov);
 


Commit: ea07939c1be5a8bab7263c96163a36e63d41be9f
    https://github.com/scummvm/scummvm/commit/ea07939c1be5a8bab7263c96163a36e63d41be9f
Author: Scott Percival (code at moral.net.au)
Date: 2024-02-09T21:17:57+08:00

Commit Message:
DIRECTOR: Fix Channel::setClean resetting the same video

Fixes introductory movies in The Dark Eye.

Changed paths:
    engines/director/channel.cpp


diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 0016522e01c..944c9ec2ab3 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -396,7 +396,7 @@ void Channel::setClean(Sprite *nextSprite, bool partial) {
 
 	if (nextSprite) {
 		if (nextSprite->_cast && (_dirty || _sprite->_castId != nextSprite->_castId)) {
-			if (nextSprite->_cast->_type == kCastDigitalVideo) {
+			if (_sprite->_castId != nextSprite->_castId && nextSprite->_cast->_type == kCastDigitalVideo) {
 				Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId.member);
 
 				if (!path.empty()) {




More information about the Scummvm-git-logs mailing list