[Scummvm-git-logs] scummvm master -> 57985af62151e76cd07bb07432e6e3b4153ffd8a

sev- noreply at scummvm.org
Fri Nov 17 00:20:07 UTC 2023


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:
b167078783 DIRECTOR: Test cast resources for the correct tag before use
57985af621 DIRECTOR: Add better handling for broken factory calls


Commit: b1670787837c5b481be720196885b839d8a08304
    https://github.com/scummvm/scummvm/commit/b1670787837c5b481be720196885b839d8a08304
Author: Scott Percival (code at moral.net.au)
Date: 2023-11-17T01:20:03+01:00

Commit Message:
DIRECTOR: Test cast resources for the correct tag before use

It is possible for cast resource IDs to overlap with non-cast ones.
The most notable example is movie resources, which are hardcoded
to resource ID 1024.

As a precaution, when loading the cast data, iterate through all of
the child resources and search for one with the expected tag.

Fixes loading text cast member 3743 when putting the lamp on the
bedside table in The Dark Eye.

Changed paths:
    engines/director/cast.cpp
    engines/director/castmember/bitmap.cpp
    engines/director/castmember/filmloop.cpp
    engines/director/castmember/palette.cpp
    engines/director/castmember/sound.cpp
    engines/director/castmember/text.cpp


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index ee13c580a5c..90a753f8294 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -557,6 +557,7 @@ void Cast::loadCast() {
 
 		for (auto &iterator : cast) {
 			Resource res = _castArchive->getResourceDetail(MKTAG('C', 'A', 'S', 't'), iterator);
+			debugC(2, kDebugLoading, "CASt: resource %d, castId %d, libId %d", iterator, res.castId, res.libId);
 			// Only load cast members which belong to the requested library ID.
 			// External casts only have one library ID, so instead
 			// we use the movie's mapping.
@@ -606,7 +607,7 @@ void Cast::loadCast() {
 	for (auto &iterator : stxt) {
 		_loadedStxts->setVal(iterator - _castIDoffset,
 				 new Stxt(this, *(r = _castArchive->getResource(MKTAG('S','T','X','T'), iterator))));
-
+		debugC(3, kDebugText, "STXT: id %d", iterator - _castIDoffset);
 		delete r;
 
 		// Try to load movie script, it starts with a comment
@@ -633,8 +634,13 @@ Common::String Cast::getVideoPath(int castId) {
 	uint16 videoId = (uint16)(castId + _castIDoffset);
 
 	if (_version >= kFileVer400 && digitalVideoCast->_children.size() > 0) {
-		videoId = digitalVideoCast->_children[0].index;
-		tag = digitalVideoCast->_children[0].tag;
+		for (auto &it : digitalVideoCast->_children) {
+			if (it.tag == MKTAG('M', 'o', 'o', 'V')) {
+				videoId = it.index;
+				tag = it.tag;
+				break;
+			}
+		}
 	}
 
 	Common::SeekableReadStreamEndian *videoData = nullptr;
diff --git a/engines/director/castmember/bitmap.cpp b/engines/director/castmember/bitmap.cpp
index 6a8ee43dd55..fdd2fd7aacd 100644
--- a/engines/director/castmember/bitmap.cpp
+++ b/engines/director/castmember/bitmap.cpp
@@ -534,11 +534,14 @@ void BitmapCastMember::load() {
 	Common::SeekableReadStream *pic = nullptr;
 
 	if (_cast->_version >= kFileVer400) {
-		if (_children.size() > 0) {
-			imgId = _children[0].index;
-			tag = _children[0].tag;
+		for (auto &it : _children) {
+			if (it.tag == MKTAG('B', 'I', 'T', 'D')) {
+				imgId = it.index;
+				tag = it.tag;
 
-			pic = _cast->getResource(tag, imgId);
+				pic = _cast->getResource(tag, imgId);
+				break;
+			}
 		}
 
 		CastMemberInfo *ci = _cast->getCastMemberInfo(_castId);
diff --git a/engines/director/castmember/filmloop.cpp b/engines/director/castmember/filmloop.cpp
index 71d0452f9ab..cf09e467dd5 100644
--- a/engines/director/castmember/filmloop.cpp
+++ b/engines/director/castmember/filmloop.cpp
@@ -370,19 +370,24 @@ void FilmLoopCastMember::load() {
 			warning("FilmLoopCastMember::load(): Film loop not found");
 		}
 	} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer500) {
-		if (_children.size() == 1) {
-			uint16 filmLoopId = _children[0].index;
-			uint32 tag = _children[0].tag;
-			Common::SeekableReadStreamEndian *loop = _cast->getResource(tag, filmLoopId);
-			if (loop) {
-				debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
-				loadFilmLoopDataD4(*loop);
-				delete loop;
-			} else {
-				warning("FilmLoopCastMember::load(): Film loop not found");
+		Common::SeekableReadStreamEndian *loop = nullptr;
+		uint16 filmLoopId = 0;
+		uint32 tag = 0;
+		for (auto &it : _children) {
+			if (it.tag == MKTAG('S', 'C', 'V', 'W')) {
+				filmLoopId = it.index;
+				tag = it.tag;
+				loop = _cast->getResource(tag, filmLoopId);
+				break;
 			}
+		}
+
+		if (loop) {
+			debugC(2, kDebugLoading, "****** Loading '%s' id: %d, %d bytes", tag2str(tag), filmLoopId, (int)loop->size());
+			loadFilmLoopDataD4(*loop);
+			delete loop;
 		} else {
-			warning("FilmLoopCastMember::load(): Expected 1 child for film loop cast, got %d", _children.size());
+			warning("FilmLoopCastMember::load(): No SCVW resource found in %d children", _children.size());
 		}
 	} else {
 		warning("STUB: FilmLoopCastMember::load(): Film loops not yet supported for version %d", _cast->_version);
diff --git a/engines/director/castmember/palette.cpp b/engines/director/castmember/palette.cpp
index 2ec31d0392e..32bdf7409eb 100644
--- a/engines/director/castmember/palette.cpp
+++ b/engines/director/castmember/palette.cpp
@@ -52,10 +52,14 @@ void PaletteCastMember::load() {
 		// For D3 and below, palette IDs are stored in the CLUT resource as cast ID + 1024
 		paletteId = _castId + _cast->_castIDoffset;
 	} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer600) {
-		if (_children.size() == 1) {
-			paletteId = _children[0].index;
-		} else {
-			warning("PaletteCastMember::load(): Expected 1 child for palette cast, got %d", _children.size());
+		for (auto &it : _children) {
+			if (it.tag == MKTAG('C', 'L', 'U', 'T')) {
+				paletteId = it.index;
+				break;
+			}
+		}
+		if (!paletteId) {
+			warning("PaletteCastMember::load(): No CLUT resource found in %d children", _children.size());
 		}
 	} else {
 		warning("STUB: PaletteCastMember::load(): Palettes not yet supported for version %d", _cast->_version);
diff --git a/engines/director/castmember/sound.cpp b/engines/director/castmember/sound.cpp
index 4cdcf50b3d9..8620b1d9eb2 100644
--- a/engines/director/castmember/sound.cpp
+++ b/engines/director/castmember/sound.cpp
@@ -55,11 +55,15 @@ void SoundCastMember::load() {
 		tag = MKTAG('S', 'N', 'D', ' ');
 		sndId = (uint16)(_castId + _cast->_castIDoffset);
 	} else if (_cast->_version >= kFileVer400 && _cast->_version < kFileVer600) {
-		if (_children.size() > 0) {
-			sndId = _children[0].index;
-			tag = _children[0].tag;
-		} else {
-			warning("SoundCastMember::load(): could not find child reference, falling back to D3");
+		for (auto &it : _children) {
+			if (it.tag == MKTAG('s', 'n', 'd', ' ') || it.tag == MKTAG('S', 'N', 'D', ' ')) {
+				sndId = it.index;
+				tag = it.tag;
+				break;
+			}
+		}
+		if (!sndId) {
+			warning("SoundCastMember::load(): No snd resource found in %d children, falling back to D3", _children.size());
 			tag = MKTAG('S', 'N', 'D', ' ');
 			sndId = (uint16)(_castId + _cast->_castIDoffset);
 		}
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 448f1ab540a..d75037a0849 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -413,11 +413,20 @@ void TextCastMember::load() {
 	if (!_cast->_loadedStxts)
 		return;
 
-	uint stxtid;
-	if (_cast->_version >= kFileVer400 && _children.size() > 0)
-		stxtid = _children[0].index;
-	else
+	uint stxtid = 0;
+	if (_cast->_version >= kFileVer400) {
+		for (auto &it : _children) {
+			if (it.tag == MKTAG('S', 'T', 'X', 'T')) {
+				stxtid = it.index;
+				break;
+			}
+		}
+		if (!stxtid) {
+			warning("TextCastMember::load(): No STXT resource found in %d children", _children.size());
+		}
+	} else {
 		stxtid = _castId;
+	}
 
 	if (_cast->_loadedStxts->contains(stxtid)) {
 		const Stxt *stxt = _cast->_loadedStxts->getVal(stxtid);


Commit: 57985af62151e76cd07bb07432e6e3b4153ffd8a
    https://github.com/scummvm/scummvm/commit/57985af62151e76cd07bb07432e6e3b4153ffd8a
Author: Scott Percival (code at moral.net.au)
Date: 2023-11-17T01:20:03+01:00

Commit Message:
DIRECTOR: Add better handling for broken factory calls

Director is surprisingly lenient about what counts as a valid
method call. In short, if there's a me object, and you're calling a
handler with the same name as one on the me object, it will be used.
You don't have to pass the me object (or even anything!) in
as the first argument, whatever you do pass in will be ignored.

Fixes several scripts in The Dark Eye which rely on typos.

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


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 130a8ed0ca1..fd18ab6c118 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1531,6 +1531,25 @@ void LC::call(const Common::String &name, int nargs, bool allowRetVal) {
 		}
 	}
 
+	// Fallback for the edge case where a local factory method is called,
+	// but with an invalid first argument.
+	// If there is a current me object, and it has a function handler
+	// with a matching name, then the first argument will be replaced with the me object.
+	// If there are no arguments at all, one will be added.
+	if (g_lingo->_state->me.type == OBJECT) {
+		AbstractObject *target = g_lingo->_state->me.u.obj;
+		funcSym = target->getMethod(name);
+		if (funcSym.type != VOIDSYM) {
+			if (nargs == 0) {
+				g_lingo->_stack.push_back(Datum());
+				nargs = 1;
+			}
+			g_lingo->_stack[g_lingo->_stack.size() - nargs] = funcSym.target; // Set first arg to target
+			call(funcSym, nargs, allowRetVal);
+			return;
+		}
+	}
+
 	// Handler
 	funcSym = g_lingo->getHandler(name);
 
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 20a53d0b757..41ac52eda3d 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1653,11 +1653,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
 		{
 			Common::String name = *var.u.s;
 			g_debugger->varReadHook(name);
-			// "me" is a special case; even if there is a local variable or argument called "me",
-			// the current me object will take precedence.
-			if (name == "me" && _state->me.type == OBJECT) {
-				return _state->me;
-			} else if (_state->localVars && _state->localVars->contains(name)) {
+			if (_state->localVars && _state->localVars->contains(name)) {
 				return (*_state->localVars)[name];
 			}
 			debugC(1, kDebugLingoExec, "varFetch: local variable %s not defined", name.c_str());




More information about the Scummvm-git-logs mailing list