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

sev- noreply at scummvm.org
Mon Nov 11 19:40:16 UTC 2024


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

Summary:
6a7a478608 DIRECTOR: Fix buffer overflow in Picture
956bb269ee DIRECTOR: Add Lingo quirk for frankenstein
0dba58f596 DIRECTOR: Prevent RTE loader crash when data is empty
814044fa45 DIRECTOR: LINGO: Add b_castLib
dfa5259c15 DIRECTOR: Change Gothos detection entries to require 32-bit colour
0caf13f309 DIRECTOR: Add duration property to TransitionCastMember
183e257235 DIRECTOR: XOBJ: Fix file handle leak in AiffXObj
a205480946 MACGUI: Fix getBorderFlags for titleless window types
d100210a45 DIRECTOR: Add detection for More Bugs in Boxes
7f5bd8e2c5 DIRECTOR: LINGO: Preserve cast library when changing sprite cast ID
7917ab9405 DIRECTOR: LINGO: Implement b_duplicateList
c6d6785447 DIRECTOR: Fix loading Lingo scripts from different internal casts
ed9fcc1073 DIRECTOR: Fix use-after-free when erasing a cast member
44e7424522 DIRECTOR: Fix selection of D2 external sounds
2874e9bc44 DIRECTOR: Fix off-by-one error when calling marker(1)
a397803b21 DIRECTOR: Add detection table entry for Legends & Myths


Commit: 6a7a4786089b903f0f004a9fa1d2e56ba3bf8a83
    https://github.com/scummvm/scummvm/commit/6a7a4786089b903f0f004a9fa1d2e56ba3bf8a83
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Fix buffer overflow in Picture

Certain code (e.g. ditherFloyd) expects a palette to have up to 256
entries, regardless of how many colors there are.

Changed paths:
    engines/director/picture.cpp


diff --git a/engines/director/picture.cpp b/engines/director/picture.cpp
index c720a775996..c7d72a4bd2a 100644
--- a/engines/director/picture.cpp
+++ b/engines/director/picture.cpp
@@ -43,7 +43,7 @@ void Picture::copyPalette(const byte *src, int numColors) {
 	delete[] _palette;
 	if (src) {
 		_paletteColors = numColors;
-		_palette = new byte[getPaletteSize()]();
+		_palette = new byte[3*256]();
 		memcpy(_palette, src, getPaletteSize());
 	} else {
 		_paletteColors = 0;


Commit: 956bb269ee2b8193c55cc752bee9407a564d490a
    https://github.com/scummvm/scummvm/commit/956bb269ee2b8193c55cc752bee9407a564d490a
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Add Lingo quirk for frankenstein

Changed paths:
    engines/director/lingo/lingo-patcher.cpp
    engines/director/lingo/xlibs/henry.cpp


diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index 17c5bd00a19..493508a154a 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -370,6 +370,16 @@ on GetCDLetter tagFile, discNumber\r\
 end \r\
 ";
 
+/* Frankenstein: Through The Eyes Of The Monster uses a projector FRANKIE.EXE, which calls an
+ * identically-named submovie FRANKIE.DIR. For now we can work around this mess by referring to
+ * the full "path" of the embedded submovie so path detection doesn't collide with FRANKIE.EXE.
+ */
+const char *frankensteinSwapFix = " \
+on exitFrame \r\
+  go(1, \"FRANKIE\\FRANKIE.DIR\")\r\
+end \r\
+";
+
 struct ScriptHandlerPatch {
 	const char *gameId;
 	const char *extra;
@@ -395,6 +405,7 @@ struct ScriptHandlerPatch {
 	{"vnc", nullptr, kPlatformWindows, "VNC\\VNC.EXE", kMovieScript, 57, DEFAULT_CAST_LIB, &vncSkipDetection},
 	{"vnc", nullptr, kPlatformWindows, "VNC2\\SHARED.DXR", kMovieScript, 1248, DEFAULT_CAST_LIB, &vncEnableCheats},
 	{"amber", nullptr, kPlatformWindows, "AMBER_F\\AMBER_JB.EXE", kMovieScript, 7, DEFAULT_CAST_LIB, &amberDriveDetectionFix},
+	{"frankenstein", nullptr, kPlatformWindows, "FRANKIE.EXE", kScoreScript, 21, DEFAULT_CAST_LIB, &frankensteinSwapFix},
 	{nullptr, nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, nullptr},
 
 };
diff --git a/engines/director/lingo/xlibs/henry.cpp b/engines/director/lingo/xlibs/henry.cpp
index 470615758d2..d854e19a3dd 100644
--- a/engines/director/lingo/xlibs/henry.cpp
+++ b/engines/director/lingo/xlibs/henry.cpp
@@ -31,6 +31,7 @@
  *
  * USED IN:
  * Mummy: Tomb of the Pharaoh
+ * Frankenstein: Through the Eyes of the Monster
  *
  **************************************************/
 


Commit: 0dba58f59643c3317df6f41e075dfff10bf46002
    https://github.com/scummvm/scummvm/commit/0dba58f59643c3317df6f41e075dfff10bf46002
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Prevent RTE loader crash when data is empty

Changed paths:
    engines/director/rte.cpp


diff --git a/engines/director/rte.cpp b/engines/director/rte.cpp
index 8ffa1bd0b34..e79a6a6803b 100644
--- a/engines/director/rte.cpp
+++ b/engines/director/rte.cpp
@@ -30,17 +30,21 @@ namespace Director {
 
 RTE0::RTE0(Cast *cast, Common::SeekableReadStreamEndian &stream) : _cast(cast) {
 	data.resize(stream.size(), 0);
-	stream.read(&data[0], stream.size());
+	if (stream.size())
+		stream.read(&data[0], stream.size());
 }
 
 RTE1::RTE1(Cast *cast, Common::SeekableReadStreamEndian &stream) : _cast(cast) {
 	data.resize(stream.size(), 0);
-	stream.read(&data[0], stream.size());
+	if (stream.size())
+		stream.read(&data[0], stream.size());
 }
 
 RTE2::RTE2(Cast *cast, Common::SeekableReadStreamEndian &stream) : _cast(cast) {
 	if (debugChannelSet(2, kDebugText))
 		stream.hexdump(stream.size());
+	if (!stream.size())
+		return;
 
 	width = stream.readUint16BE();
 	height = stream.readUint16BE();


Commit: 814044fa456ad7e4b985b1f6fa28f3b8fe1b2975
    https://github.com/scummvm/scummvm/commit/814044fa456ad7e4b985b1f6fa28f3b8fe1b2975
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: LINGO: Add b_castLib

Changed paths:
    engines/director/lingo/lingo-builtins.cpp
    engines/director/lingo/lingo-builtins.h
    engines/director/lingo/lingo-bytecode.cpp
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-the.cpp
    engines/director/lingo/lingo-the.h
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h
    engines/director/types.h


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 2de6cd99813..97adf7e9a73 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -219,6 +219,7 @@ static BuiltinProto builtins[] = {
 	{ "version",		LB::b_version,		0, 0, 300, KBLTIN },	//		D3 k
 	// References
 	{ "cast",			LB::b_cast,			1, 1, 400, FBLTIN },	//			D4 f
+	{ "castLib",		LB::b_castLib,		1, 1, 500, FBLTIN },	//				D5 f
 	{ "member",			LB::b_member,		1, 2, 500, FBLTIN },	//				D5 f
 	{ "script",			LB::b_script,		1, 1, 400, FBLTIN },	//			D4 f
 	{ "window",			LB::b_window,		1, 1, 400, FBLTIN },	//			D4 f
@@ -3355,6 +3356,13 @@ void LB::b_cast(int nargs) {
 	g_lingo->push(res);
 }
 
+void LB::b_castLib(int nargs) {
+	Datum d = g_lingo->pop();
+	Datum res = d.asInt();
+	res.type = CASTLIBREF;
+	g_lingo->push(res);
+}
+
 void LB::b_member(int nargs) {
 	Movie *movie = g_director->getCurrentMovie();
 	CastMemberID res;
@@ -3371,7 +3379,9 @@ void LB::b_member(int nargs) {
 		Datum library = g_lingo->pop();
 		Datum member = g_lingo->pop();
 		int libId = -1;
-		if (library.isNumeric()) {
+		if (library.type == CASTLIBREF) {
+			libId = library.u.i;
+		} else if (library.isNumeric()) {
 			libId = library.asInt();
 		} else {
 			libId = movie->getCastLibIDByName(library.asString());
diff --git a/engines/director/lingo/lingo-builtins.h b/engines/director/lingo/lingo-builtins.h
index b2ed4f3eef6..e2c801c8258 100644
--- a/engines/director/lingo/lingo-builtins.h
+++ b/engines/director/lingo/lingo-builtins.h
@@ -187,6 +187,7 @@ void b_true(int nargs);
 void b_version(int nargs);
 
 void b_cast(int nargs);
+void b_castLib(int nargs);
 void b_script(int nargs);
 
 void b_numberofchars(int nargs);
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 39dfbad0b57..7355c295ca8 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -254,7 +254,7 @@ static LingoV4TheEntity lingoV4TheEntity[] = {
 	{ 0x08, 0x01, kThePerFrameHook,		kTheNOField,		true, kTEANOArgs },
 	{ 0x08, 0x02, kTheCastMembers,		kTheNumber,			false, kTEANOArgs },
 	{ 0x08, 0x03, kTheMenus,			kTheNumber,			false, kTEANOArgs },
-	{ 0x08, 0x04, kTheCastlibs,			kTheNumber,			false, kTEANOArgs }, // D5
+	{ 0x08, 0x04, kTheCastLibs,			kTheNumber,			false, kTEANOArgs }, // D5
 	{ 0x08, 0x05, kTheXtras,			kTheNumber,			false, kTEANOArgs }, // D5
 
 	{ 0x09, 0x01, kTheCast,				kTheName,			true, kTEAItemId },
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 9d4f91e07e4..142c1330762 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -1501,7 +1501,7 @@ bool LingoCompiler::visitTheNumberOfNode(TheNumberOfNode *node) {
 	case kNumberOfCastlibs:
 		codeInt(0); // Put dummy id
 		code1(LC::c_theentitypush);
-		codeInt(kTheCastlibs);
+		codeInt(kTheCastLibs);
 		codeInt(kTheNumber);
 		break;
 	case kNumberOfChars:
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 04e985d5d94..616490cb93f 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -404,8 +404,8 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 	case kTheCast:
 		d = getTheCast(id, field);
 		break;
-	case kTheCastlibs: // D5
-		d = getCastlibsNum();
+	case kTheCastLibs: // D5
+		d = getCastLibsNum();
 		break;
 	case kTheCastMembers:
 		d = getMembersNum();
@@ -1268,7 +1268,7 @@ int Lingo::getMenuNum() {
 	return g_director->_wm->getMenu()->numberOfMenus();
 }
 
-int Lingo::getCastlibsNum() {
+int Lingo::getCastLibsNum() {
 	return _vm->getCurrentMovie()->getCasts()->size();
 }
 
diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h
index e50347042f9..2db85743d98 100644
--- a/engines/director/lingo/lingo-the.h
+++ b/engines/director/lingo/lingo-the.h
@@ -31,7 +31,7 @@ enum TheEntityType {
 	kTheBeepOn,
 	kTheButtonStyle,
 	kTheCast,
-	kTheCastlibs,
+	kTheCastLibs,
 	kTheCastMembers,
 	kTheCenterStage,
 	kTheChars,
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 77be64bd11d..5e8c65e5b7c 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -973,6 +973,7 @@ void Datum::reset() {
 		case FLOAT:
 		case ARGC:
 		case ARGCNORET:
+		case CASTLIBREF:
 			break;
 		case VARREF:
 		case GLOBALREF:
@@ -1170,6 +1171,9 @@ Common::String Datum::asString(bool printonly) const {
 	case CASTREF:
 		s = Common::String::format("member %d of castLib %d", u.cast->member, u.cast->castLib);
 		break;
+	case CASTLIBREF:
+		s = Common::String::format("castLib %d", u.i);
+		break;
 	case FIELDREF:
 		s = Common::String::format("field %d of castLib %d", u.cast->member, u.cast->castLib);
 		break;
@@ -1302,6 +1306,8 @@ const char *Datum::type2str(bool ilk) const {
 		return ilk ? "linearlist" : "ARRAY";
 	case CASTREF:
 		return "CASTREF";
+	case CASTLIBREF:
+		return "CASTLIBREF";
 	case CHUNKREF:
 		return "CHUNKREF";
 	case FIELDREF:
@@ -1369,6 +1375,7 @@ int Datum::equalTo(Datum &d, bool ignoreCase) const {
 		return u.obj == d.u.obj;
 	case CASTREF:
 		return *u.cast == *d.u.cast;
+	case CASTLIBREF:
 	case PICTUREREF:
 		return 0; // Original always returns 0 on picture reference comparison
 	default:
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 185893fab3e..48591a1fccd 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -356,7 +356,7 @@ public:
 	int getMenuNum();
 	int getMenuItemsNum(Datum &d);
 	int getXtrasNum();
-	int getCastlibsNum();
+	int getCastLibsNum();
 	int getMembersNum();
 
 	void executeHandler(const Common::String &name);
diff --git a/engines/director/types.h b/engines/director/types.h
index 0ec907e62ef..5782d42da56 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -375,6 +375,7 @@ enum DatumType {
 	ARGCNORET,
 	ARRAY,
 	CASTREF,
+	CASTLIBREF,
 	CHUNKREF,
 	FIELDREF,
 	FLOAT,


Commit: dfa5259c1592eb05d1b413b35821165f76da3cf0
    https://github.com/scummvm/scummvm/commit/dfa5259c1592eb05d1b413b35821165f76da3cf0
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Change Gothos detection entries to require 32-bit colour

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 52b15df741b..d50583613bd 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -6621,8 +6621,8 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINGAME2tf("gondwana",  "", "MOVIE/MOVIE.EXE",	  "t:dfce572624ed9816e7268ac8f5ef7d2b", 5647741,
 								"MOVIE/GONDWANA.DXR", "t:beee5b25488c1d4c30d81b78ae8d9368",  626006, 505, GF_32BPP),
 
-	WINGAME1("gothos", "", "gothos.exe", "6199bb7cabc7f636394cacffd6a71fa9", 1788333, 501),
-	MACGAME1("gothos", "", "MACINST/GOTHOS", "1d08e56a4c7ba60a67417c7988cd3ffe", 718097, 501),
+	WINGAME1tf("gothos", "", "gothos.exe", "6199bb7cabc7f636394cacffd6a71fa9", 1788333, 501, GF_32BPP),
+	MACGAME1tf("gothos", "", "MACINST/GOTHOS", "1d08e56a4c7ba60a67417c7988cd3ffe", 718097, 501, GF_32BPP),
 
 	// Green Eggs and Hamulator mini-game
 	// Demo for a Living Books game that is supported in MOHAWK engine


Commit: 0caf13f3099a162ec831c83178bd67bf77592dfc
    https://github.com/scummvm/scummvm/commit/0caf13f3099a162ec831c83178bd67bf77592dfc
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Add duration property to TransitionCastMember

Changed paths:
    engines/director/castmember/transition.cpp
    engines/director/castmember/transition.h


diff --git a/engines/director/castmember/transition.cpp b/engines/director/castmember/transition.cpp
index ff6b120a866..9e3690394d7 100644
--- a/engines/director/castmember/transition.cpp
+++ b/engines/director/castmember/transition.cpp
@@ -23,6 +23,7 @@
 #include "director/cast.h"
 #include "director/movie.h"
 #include "director/castmember/transition.h"
+#include "director/lingo/lingo-the.h"
 
 namespace Director {
 
@@ -62,6 +63,43 @@ TransitionCastMember::TransitionCastMember(Cast *cast, uint16 castId, Transition
 	_area = source._area;
 }
 
+bool TransitionCastMember::hasField(int field) {
+	switch (field) {
+	case kTheDuration:
+		return true;
+	default:
+		break;
+	}
+	return CastMember::hasField(field);
+}
+
+Datum TransitionCastMember::getField(int field) {
+	Datum d;
+
+	switch (field) {
+	case kTheDuration:
+		d = Datum(_durationMillis);
+		break;
+	default:
+		d = CastMember::getField(field);
+		break;
+	}
+
+	return d;
+}
+
+bool TransitionCastMember::setField(int field, const Datum &d) {
+	switch (field) {
+	case kTheDuration:
+		_durationMillis = (bool)d.asInt();
+		return true;
+	default:
+		break;
+	}
+
+	return CastMember::setField(field, d);
+}
+
 Common::String TransitionCastMember::formatInfo() {
 	return Common::String::format("transType: %d, durationMillis: %d, flags: %d, chunkSize: %d", _transType, _durationMillis, _flags, _chunkSize);
 }
diff --git a/engines/director/castmember/transition.h b/engines/director/castmember/transition.h
index 63f6a5e761e..b45781eb6c0 100644
--- a/engines/director/castmember/transition.h
+++ b/engines/director/castmember/transition.h
@@ -31,6 +31,10 @@ public:
 	TransitionCastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
 	TransitionCastMember(Cast *cast, uint16 castId, TransitionCastMember &source);
 
+	bool hasField(int field) override;
+	Datum getField(int field) override;
+	bool setField(int field, const Datum &value) override;
+
 	Common::String formatInfo() override;
 
 	TransitionType _transType;


Commit: 183e257235375341837ca1d7fa440307e157880b
    https://github.com/scummvm/scummvm/commit/183e257235375341837ca1d7fa440307e157880b
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: XOBJ: Fix file handle leak in AiffXObj

Changed paths:
    engines/director/lingo/xlibs/aiff.cpp


diff --git a/engines/director/lingo/xlibs/aiff.cpp b/engines/director/lingo/xlibs/aiff.cpp
index d8670571cf3..849a61d91c5 100644
--- a/engines/director/lingo/xlibs/aiff.cpp
+++ b/engines/director/lingo/xlibs/aiff.cpp
@@ -108,6 +108,7 @@ void AiffXObj::m_duration(int nargs) {
 	int duration = (aiffHeader->getFrameCount() / (float)aiffHeader->getFrameRate()) * 60;
 
 	delete aiffHeader;
+	delete aiffStream;
 	g_lingo->push(Datum(duration));
 }
 


Commit: a2054809462ca0df085dc6b5f9881f6d37fa1759
    https://github.com/scummvm/scummvm/commit/a2054809462ca0df085dc6b5f9881f6d37fa1759
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
MACGUI: Fix getBorderFlags for titleless window types

Fixes rendering of game viewport in Zeddas: Servant of Sheol.

Changed paths:
    graphics/macgui/macwindow.cpp


diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp
index e811ade9594..4c4dc4b985e 100644
--- a/graphics/macgui/macwindow.cpp
+++ b/graphics/macgui/macwindow.cpp
@@ -202,7 +202,7 @@ uint32 MacWindow::getBorderFlags() const {
 	uint32 flags = 0;
 	if (_active)
 		flags |= kWindowBorderActive;
-	if (!_title.empty())
+	if (!_title.empty() && _borderType != 0x02 && _borderType != 0x03 && _borderType != 0x0a && _borderType != 0x0b)
 		flags |= kWindowBorderTitle;
 	if (_hasScrollBar)
 		flags |= kWindowBorderScrollbar;


Commit: d100210a45573f97f81cdb9a60578f69aa9a3aa6
    https://github.com/scummvm/scummvm/commit/d100210a45573f97f81cdb9a60578f69aa9a3aa6
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Add detection for More Bugs in Boxes

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index d50583613bd..80ba633fa72 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -339,6 +339,7 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "mode",				"MODE" },
 	{ "moominhide",			"Hide and Seek with Moomin"},
 	{ "moominparty",		"The Great Moomin Party" },
+	{ "morebugs",			"More Bugs in Boxes" },
 	{ "mrsquack",			"Reading with Peter Cottontail: The Story of Mrs. Quack" },
 	{ "mummy",				"Mummy: Tomb of the Pharaoh" },
 	{ "muppetkidsearly5",	"Muppets Kids Early Learning Series Volume 5: Sound Patterns: Phonics" },
@@ -5042,6 +5043,10 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINGAME2t_l("moominhide", "", "MUMIN.EXE", "c51444be1e70bb731d0c465d5bdd8ed2", 696095,
 				"01DALEN.DXR", "a100f801a8f0408a286d84c51e822182", 4016704, Common::NB_NOR, 404),
 
+	WINGAME2("morebugs", "", "START.EXE", "t:e8fe58e5f33d4e4b0884e1244706520d", 690647,
+				"START.DIR", "f:f9d3bf8fc0d98550d80f7585fb97d8a6", 24232, 404),
+	MACGAME1("morebugs", "", "More Bugs in Boxes", "r:9e9696433d18629b88714089034c086b", 306032, 404),
+
 	MACGAME1_l("moritaka", "", "WATARASE-BASHI", "c761bfe3a0865ca0f43cb5556230ed5b", 107527, Common::JA_JPN, 404),
 	PIPGAME1_l("moritaka", "", "Pippin Projector", "b708dcf9cdc19e6e186000ad93e41997", 73705, Common::JA_JPN, 404),
 


Commit: 7f5bd8e2c593783a1f8e6362ce52c9244a5bd2ab
    https://github.com/scummvm/scummvm/commit/7f5bd8e2c593783a1f8e6362ce52c9244a5bd2ab
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: LINGO: Preserve cast library when changing sprite cast ID

Fixes buttons glitching when pressed in Fisher-Price Learning in Toyland.

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


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 616490cb93f..af1be11ab82 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1533,6 +1533,10 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 	case kTheMemberNum:
 		{
 			CastMemberID castId = d.asMemberID();
+			// Setting the cast ID as a number will preserve whatever is in castLib
+			if (d.isNumeric() && (sprite->_castId.castLib != 0)) {
+				castId = CastMemberID(d.asInt(), sprite->_castId.castLib);
+			}
 			CastMember *castMember = movie->getCastMember(castId);
 
 			if (castMember && castMember->_type == kCastDigitalVideo) {


Commit: 7917ab940503b3921ffef1713cb84aea55ed6f60
    https://github.com/scummvm/scummvm/commit/7917ab940503b3921ffef1713cb84aea55ed6f60
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: LINGO: Implement b_duplicateList

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 97adf7e9a73..46aef678659 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -84,6 +84,7 @@ static BuiltinProto builtins[] = {
 	{ "deleteAt",		LB::b_deleteAt,		2, 2, 400, HBLTIN_LIST },	//			D4 h
 	{ "deleteOne",		LB::b_deleteOne,	2, 2, 400, HBLTIN_LIST },	//			D4 h, undocumented?
 	{ "deleteProp",		LB::b_deleteProp,	2, 2, 400, HBLTIN_LIST },	//			D4 h
+	{ "duplicate",		LB::b_duplicateList,1, 1, 500, FBLTIN_LIST },	//				D5 f
 	{ "findPos",		LB::b_findPos,		2, 2, 400, FBLTIN_LIST },	//			D4 f
 	{ "findPosNear",	LB::b_findPosNear,	2, 2, 400, FBLTIN_LIST },	//			D4 f
 	{ "getaProp",		LB::b_getaProp,		2, 2, 400, FBLTIN_LIST },	//			D4 f
@@ -773,6 +774,14 @@ void LB::b_deleteProp(int nargs) {
 	}
 }
 
+
+void LB::b_duplicateList(int nargs) {
+	Datum list = g_lingo->pop();
+	TYPECHECK2(list, ARRAY, PARRAY);
+	g_lingo->push(list.clone());
+}
+
+
 void LB::b_findPos(int nargs) {
 	Datum prop = g_lingo->pop();
 	Datum list = g_lingo->pop();
diff --git a/engines/director/lingo/lingo-builtins.h b/engines/director/lingo/lingo-builtins.h
index e2c801c8258..8014e9c520c 100644
--- a/engines/director/lingo/lingo-builtins.h
+++ b/engines/director/lingo/lingo-builtins.h
@@ -56,6 +56,7 @@ void b_count(int nargs);
 void b_deleteAt(int nargs);
 void b_deleteOne(int nargs);
 void b_deleteProp(int nargs);
+void b_duplicateList(int nargs);
 void b_findPos(int nargs);
 void b_findPosNear(int nargs);
 void b_getaProp(int nargs);
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 5e8c65e5b7c..caa26dba69c 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1274,6 +1274,30 @@ Common::Point Datum::asPoint() const {
 	return Common::Point(u.farr->arr[0].asInt(), u.farr->arr[1].asInt());
 }
 
+Datum Datum::clone() const {
+	Datum result;
+	switch (type) {
+		case ARRAY:
+			result.type = ARRAY;
+			result.u.farr = new FArray;
+			for (auto &it : u.farr->arr) {
+				result.u.farr->arr.push_back(it.clone());
+			}
+			break;
+		case PARRAY:
+			result.type = PARRAY;
+			result.u.parr = new PArray;
+			for (auto &it : u.parr->arr) {
+				result.u.parr->arr.push_back(PCell(it.p.clone(), it.v.clone()));
+			}
+			break;
+		default:
+			result = *this;
+			break;
+	}
+	return result;
+}
+
 bool Datum::isRef() const {
 	return (isVarRef() || isCastRef() || type == CHUNKREF);
 }
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 48591a1fccd..3295877d408 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -169,6 +169,7 @@ struct Datum {	/* interpreter stack type */
 	Common::String asString(bool printonly = false) const;
 	CastMemberID asMemberID(CastType castType = kCastTypeAny, int castLib = 0) const;
 	Common::Point asPoint() const;
+	Datum clone() const;
 
 	bool isRef() const;
 	bool isVarRef() const;


Commit: c6d67854474923a6597742e7ce9c34fb930ba2f8
    https://github.com/scummvm/scummvm/commit/c6d67854474923a6597742e7ce9c34fb930ba2f8
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Fix loading Lingo scripts from different internal casts

Fixes the block minigame in Fisher Price Learning in Toyland.

Changed paths:
    engines/director/archive.cpp
    engines/director/archive.h
    engines/director/cast.cpp
    engines/director/cast.h
    engines/director/debugger.cpp
    engines/director/lingo/lingo-events.cpp
    engines/director/movie.cpp
    engines/director/movie.h


diff --git a/engines/director/archive.cpp b/engines/director/archive.cpp
index 22d2cb5af51..fa374b1b5c9 100644
--- a/engines/director/archive.cpp
+++ b/engines/director/archive.cpp
@@ -144,6 +144,10 @@ Common::SeekableReadStreamEndian *Archive::getFirstResource(uint32 tag) {
 	return getResource(tag, getResourceIDList(tag)[0]);
 }
 
+Common::SeekableReadStreamEndian *Archive::getFirstResource(uint32 tag, uint16 parentId) {
+	return getResource(tag, getResourceIDList(tag)[0]);
+}
+
 Common::SeekableReadStreamEndian *Archive::getResource(uint32 tag, uint16 id) {
 	if (!_types.contains(tag))
 		error("Archive::getResource(): Archive does not contain '%s' %d", tag2str(tag), id);
@@ -757,11 +761,10 @@ bool RIFXArchive::openStream(Common::SeekableReadStream *stream, uint32 startOff
 	uint32 casTag = MKTAG('C', 'A', 'S', '*');
 	if (_keyData.contains(casTag)) {
 		for (auto &it : _keyData[casTag]) {
-			uint32 libId = it._key - CAST_LIB_OFFSET;
 			for (auto &jt : it._value) {
 				if (Common::SeekableReadStreamEndian *casStream = getResource(casTag, jt)) {
 					Resource res = getResourceDetail(casTag, jt);
-					readCast(*casStream, libId);
+					readCast(*casStream, it._key);
 					delete casStream;
 				}
 			}
@@ -997,12 +1000,12 @@ bool RIFXArchive::readAfterburnerMap(Common::SeekableReadStreamEndian &stream, u
 	return true;
 }
 
-void RIFXArchive::readCast(Common::SeekableReadStreamEndian &casStream, uint16 libId) {
+void RIFXArchive::readCast(Common::SeekableReadStreamEndian &casStream, uint16 libResourceId) {
 	uint castTag = MKTAG('C', 'A', 'S', 't');
 
 	uint casSize = casStream.size() / 4;
 
-	debugCN(2, kDebugLoading, "CAS*: libId %d, %d members [", libId, casSize);
+	debugCN(2, kDebugLoading, "CAS*: libResourceId %d, %d members [", libResourceId, casSize);
 
 	for (uint i = 0; i < casSize; i++) {
 		uint32 castIndex = casStream.readUint32BE();
@@ -1013,7 +1016,7 @@ void RIFXArchive::readCast(Common::SeekableReadStreamEndian &casStream, uint16 l
 		}
 		Resource &res = _types[castTag][castIndex];
 		res.castId = i;
-		res.libId = libId;
+		res.libResourceId = libResourceId;
 	}
 	debugC(2, kDebugLoading, "]");
 }
@@ -1054,7 +1057,7 @@ void RIFXArchive::readKeyTable(Common::SeekableReadStreamEndian &keyStream) {
 		// The movie has the hardcoded ID 1024, which may collide with a cast member's ID
 		// when there are many chunks. This is not a problem since cast members and
 		// movies use different resource types, so we can tell them apart.
-		if (parentIndex == DEFAULT_CAST_LIB + CAST_LIB_OFFSET) {
+		if (parentIndex == 1024) {
 			_movieChunks.setVal(childTag, childIndex);
 		}
 	}
@@ -1068,6 +1071,17 @@ Common::SeekableReadStreamEndian *RIFXArchive::getFirstResource(uint32 tag, bool
 	return getResource(tag, getResourceIDList(tag)[0], fileEndianness);
 }
 
+Common::SeekableReadStreamEndian *RIFXArchive::getFirstResource(uint32 tag, uint16 parentId) {
+	if (!_keyData.contains(tag))
+		return nullptr;
+	if (!_keyData[tag].contains(parentId))
+		return nullptr;
+	if (_keyData[tag][parentId].empty())
+		return nullptr;
+	return getResource(tag, _keyData[tag][parentId][0], false);
+}
+
+
 Common::SeekableReadStreamEndian *RIFXArchive::getResource(uint32 tag, uint16 id) {
 	return getResource(tag, id, false);
 }
diff --git a/engines/director/archive.h b/engines/director/archive.h
index 0336cb1ca81..987574f6078 100644
--- a/engines/director/archive.h
+++ b/engines/director/archive.h
@@ -43,7 +43,7 @@ struct Resource {
 	uint32 uncompSize;
 	uint32 compressionType;
 	uint32 castId;
-	uint32 libId;
+	uint32 libResourceId;
 	uint32 tag;
 	Common::String name;
 	Common::Array<Resource> children;
@@ -70,6 +70,7 @@ public:
 	bool hasResource(uint32 tag, const Common::String &resName) const;
 	virtual Common::SeekableReadStreamEndian *getResource(uint32 tag, uint16 id);
 	virtual Common::SeekableReadStreamEndian *getFirstResource(uint32 tag);
+	virtual Common::SeekableReadStreamEndian *getFirstResource(uint32 tag, uint16 parentId);
 	virtual Resource getResourceDetail(uint32 tag, uint16 id);
 	uint32 getOffset(uint32 tag, uint16 id) const;
 	uint16 findResourceID(uint32 tag, const Common::String &resName, bool ignoreCase = false) const;
@@ -135,6 +136,7 @@ public:
 	bool openStream(Common::SeekableReadStream *stream, uint32 startOffset = 0) override;
 	Common::SeekableReadStreamEndian *getFirstResource(uint32 tag) override;
 	virtual Common::SeekableReadStreamEndian *getFirstResource(uint32 tag, bool fileEndianness);
+	Common::SeekableReadStreamEndian *getFirstResource(uint32 tag, uint16 parentId) override;
 	Common::SeekableReadStreamEndian *getResource(uint32 tag, uint16 id) override;
 	virtual Common::SeekableReadStreamEndian *getResource(uint32 tag, uint16 id, bool fileEndianness);
 	Resource getResourceDetail(uint32 tag, uint16 id) override;
@@ -143,7 +145,7 @@ public:
 private:
 	bool readMemoryMap(Common::SeekableReadStreamEndian &stream, uint32 moreOffset, Common::SeekableMemoryWriteStream *dumpStream, uint32 movieStartOffset);
 	bool readAfterburnerMap(Common::SeekableReadStreamEndian &stream, uint32 moreOffset);
-	void readCast(Common::SeekableReadStreamEndian &casStream, uint16 libId);
+	void readCast(Common::SeekableReadStreamEndian &casStream, uint16 libResourceId);
 	void readKeyTable(Common::SeekableReadStreamEndian &keyStream);
 
 protected:
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 47157c423ae..15b36205436 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -59,12 +59,13 @@
 
 namespace Director {
 
-Cast::Cast(Movie *movie, uint16 castLibID, bool isShared, bool isExternal) {
+Cast::Cast(Movie *movie, uint16 castLibID, bool isShared, bool isExternal, uint16 libResourceId) {
 	_movie = movie;
 	_vm = _movie->getVM();
 	_lingo = _vm->getLingo();
 
 	_castLibID = castLibID;
+	_libResourceId = libResourceId;
 	_isShared = isShared;
 	_isExternal = isExternal;
 	_loadMutex = true;
@@ -638,11 +639,11 @@ 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);
+			debugC(2, kDebugLoading, "CASt: resource %d, castId %d, libResourceId %d", iterator, res.castId, res.libResourceId);
 			// 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.
-			if (res.libId != _castLibID && !_isExternal)
+			if (res.libResourceId != _libResourceId && !_isExternal)
 				continue;
 			Common::SeekableReadStreamEndian *stream = _castArchive->getResource(MKTAG('C', 'A', 'S', 't'), iterator);
 			loadCastData(*stream, res.castId, &res);
@@ -716,7 +717,7 @@ void Cast::loadCast() {
 	// For D4+ we may request to force Lingo scripts and skip precompiled bytecode
 	if (_version >= kFileVer400 && !debugChannelSet(-1, kDebugNoBytecode)) {
 		// Try to load script context
-		if ((r = _castArchive->getMovieResourceIfPresent(MKTAG('L', 'c', 't', 'x'))) != nullptr) {
+		if ((r = _castArchive->getFirstResource(MKTAG('L', 'c', 't', 'x'), _libResourceId)) != nullptr) {
 			loadLingoContext(*r);
 			delete r;
 		}
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 3e1bbbc5ada..ad79eeace73 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -84,7 +84,7 @@ struct TilePatternEntry {
 
 class Cast {
 public:
-	Cast(Movie *movie, uint16 castLibID, bool isShared = false, bool isExternal = false);
+	Cast(Movie *movie, uint16 castLibID, bool isShared = false, bool isExternal = false, uint16 libResourceId = 1024);
 	~Cast();
 
 	void loadArchive();
@@ -145,6 +145,7 @@ public:
 	uint16 _version;
 	Common::Platform _platform;
 	uint16 _castLibID;
+	uint16 _libResourceId;
 	bool _isExternal;
 
 	CharMap _macCharsToWin;
diff --git a/engines/director/debugger.cpp b/engines/director/debugger.cpp
index 26da79edc1a..76c82ae443a 100644
--- a/engines/director/debugger.cpp
+++ b/engines/director/debugger.cpp
@@ -341,7 +341,6 @@ bool Debugger::cmdChannels(int argc, const char **argv) {
 		Frame *frame = score->_scoreCache[frameId - 1];
 		if (frame) {
 			debugPrintf("%s\n", frame->formatChannelInfo().c_str());
-			delete frame;
 		} else {
 			debugPrintf("  not found\n");
 		}
@@ -360,7 +359,7 @@ bool Debugger::cmdCast(int argc, const char **argv) {
 		castId = atoi(argv[1]);
 
 	for (auto it : *movie->getCasts()) {
-		debugPrintf("Cast %d:\n", it._key);
+		debugPrintf("Cast %d (%s):\n", it._key, it._value->getMacName().c_str());
 		Cast *cast = it._value;
 		if (!cast) {
 			debugPrintf("[empty]\n");
diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 1e36ac4956d..eed6ad8ff3c 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -326,12 +326,14 @@ void Movie::resolveScriptEvent(LingoEvent &event) {
 
 			// FIXME: shared cast movie scripts could come before main movie ones
 			// Movie scripts are fixed, so it's fine to look them up in advance.
-			LingoArchive *mainArchive = getMainLingoArch();
-			for (auto &it : mainArchive->scriptContexts[kMovieScript]) {
-				if (it._value->_eventHandlers.contains(event.event)) {
-					event.scriptType = kMovieScript;
-					event.scriptId = CastMemberID(it._key, DEFAULT_CAST_LIB);
-					return;
+			for (auto &cast : _casts) {
+				LingoArchive *archive = cast._value->_lingoArchive;
+				for (auto &it : archive->scriptContexts[kMovieScript]) {
+					if (it._value->_eventHandlers.contains(event.event)) {
+						event.scriptType = kMovieScript;
+						event.scriptId = CastMemberID(it._key, cast._key);
+						return;
+					}
 				}
 			}
 			LingoArchive *sharedArchive = getSharedLingoArch();
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index bba3f452ab3..92cfae68f01 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -180,7 +180,7 @@ void Movie::loadCastLibMapping(Common::SeekableReadStreamEndian &stream) {
 		if (_casts.contains(libId)) {
 			cast = _casts.getVal(libId);
 		} else {
-			cast = new Cast(this, libId, false, isExternal);
+			cast = new Cast(this, libId, false, isExternal, libResourceId);
 			_casts.setVal(libId, cast);
 		}
 		_castNames[name] = libId;
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 9de05a99af7..4fa3c688ec2 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -24,7 +24,6 @@
 
 #define DEFAULT_CAST_LIB 1
 #define SHARED_CAST_LIB -1337
-#define CAST_LIB_OFFSET 1023
 
 namespace Common {
 struct Event;


Commit: ed9fcc1073899988941c83a1a29e3288c63a3f5e
    https://github.com/scummvm/scummvm/commit/ed9fcc1073899988941c83a1a29e3288c63a3f5e
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Fix use-after-free when erasing a cast member

Changed paths:
    engines/director/movie.cpp
    engines/director/score.cpp


diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 92cfae68f01..adc17735151 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -459,7 +459,9 @@ CastMember* Movie::createOrReplaceCastMember(CastMemberID memberID, CastMember*
 
 bool Movie::eraseCastMember(CastMemberID memberID) {
 	if (_casts.contains(memberID.castLib)) {
-		return _casts.getVal(memberID.castLib)->eraseCastMember(memberID.member);
+		bool result = _casts.getVal(memberID.castLib)->eraseCastMember(memberID.member);
+		_score->refreshPointersForCastMemberID(memberID);
+		return result;
 	}
 
 	return false;
@@ -490,7 +492,9 @@ bool Movie::duplicateCastMember(CastMemberID source, CastMemberID target) {
 		CastMember *sourceMember = sourceCast->getCastMember(source.member);
 		CastMemberInfo *sourceInfo = sourceCast->getCastMemberInfo(source.member);
 		debugC(3, kDebugLoading, "Movie::DuplicateCastMember(): copying cast data from %s to %s (%s)", source.asString().c_str(), target.asString().c_str(), castType2str(sourceMember->_type));
-		return targetCast->duplicateCastMember(sourceMember, sourceInfo, target.member);
+		bool result = targetCast->duplicateCastMember(sourceMember, sourceInfo, target.member);
+		_score->refreshPointersForCastMemberID(target);
+		return result;
 	}
 	return false;
 }
diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 1db4230ec65..8b2b05cee2f 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -806,8 +806,8 @@ void Score::updateSprites(RenderMode mode) {
 				_window->addDirtyRect(channel->getBbox());
 
 			if (currentSprite && currentSprite->_cast && currentSprite->_cast->_erase) {
-				_movie->eraseCastMember(currentSprite->_castId);
 				currentSprite->_cast->_erase = false;
+				_movie->eraseCastMember(currentSprite->_castId);
 
 				currentSprite->setCast(currentSprite->_castId);
 				nextSprite->setCast(nextSprite->_castId);


Commit: 44e742452276e66225c7f80a09d364327c901ed2
    https://github.com/scummvm/scummvm/commit/44e742452276e66225c7f80a09d364327c901ed2
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Fix selection of D2 external sounds

When an archive is loaded, it is moved to the front of
g_director->_allSeenResFiles. This is used by the code in
DirectorSound::loadSampleSounds to determine priority when selecting
external sounds to play back. Due to a typo, it would instead pick
the -last- archive to feature the sound ID.

Fixes the incorrect sound effects playing during the second loop of
the Spaceship Warlock demo.

Changed paths:
    engines/director/sound.cpp


diff --git a/engines/director/sound.cpp b/engines/director/sound.cpp
index 6854b65ddff..a3f462cca97 100644
--- a/engines/director/sound.cpp
+++ b/engines/director/sound.cpp
@@ -378,6 +378,8 @@ void DirectorSound::loadSampleSounds(uint type) {
 				break;
 			}
 		}
+		if (id != 0xFF)
+			break;
 	}
 
 	if (!archive) {


Commit: 2874e9bc44b8fcf05ad565b6f84472e7bf4108e0
    https://github.com/scummvm/scummvm/commit/2874e9bc44b8fcf05ad565b6f84472e7bf4108e0
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Fix off-by-one error when calling marker(1)

If called at the start of the movie, marker would return
the second-nearest marker.

Fixes the Kroll jumping about forever on the second loop of the Spaceship
Warlock demo.

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 8b2b05cee2f..1c3a9f97dc6 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -268,26 +268,14 @@ int Score::getNextLabelNumber(int referenceFrame) {
 	if (_labels == nullptr || _labels->size() == 0)
 		return 0;
 
-	Common::SortedArray<Label *>::iterator i;
-
-	for (i = _labels->begin(); i != _labels->end(); ++i) {
-		if ((*i)->number >= referenceFrame) {
-			int n = (*i)->number;
-			++i;
-			if (i != _labels->end()) {
-				// return to the first marker to to the right
-				return (*i)->number;
-			} else {
-				// if no markers are to the right of the playback head,
-				// the playback head goes to the first marker to the left
-				return n;
-			}
+	for (auto &it : *_labels) {
+		if (it->number > referenceFrame) {
+			return it->number;
 		}
 	}
-
-	// If there are not markers to the left,
-	// the playback head goes to frame 1, (Director frame array start from 1, engine from 0)
-	return 0;
+	// if no markers are to the right of the playback head,
+	// return the last marker
+	return _labels->back()->number;
 }
 
 int Score::getPreviousLabelNumber(int referenceFrame) {


Commit: a397803b21a974ca62cdaeb1bd823e43e8cc8824
    https://github.com/scummvm/scummvm/commit/a397803b21a974ca62cdaeb1bd823e43e8cc8824
Author: Scott Percival (code at moral.net.au)
Date: 2024-11-11T20:40:06+01:00

Commit Message:
DIRECTOR: Add detection table entry for Legends & Myths

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 80ba633fa72..bc02aed0f99 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -289,6 +289,7 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "lbpre",				"Maurice Sendak's Little Bear Preschool Thinking Adventures" },
 	{ "lbtpreschool",		"The Land Before Time: Preschool Adventure" },
 	{ "legendsofoz",		"The Legends of Oz" },
+	{ "legendsmyths",		"Legends & Myths" },
 	{ "letsdiscover",		"Let's Discover" },
 	{ "letters",			"Letters" },
 	{ "louiscatorze",		"Louis Cat Orze: The Mystery of the Queen's Necklace" },
@@ -4776,6 +4777,9 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	WINGAME1t("learningcoreldraw3", "", "PROGRAM/LRNDRAW3.EXE", "aa6fa44a1161fe91f3be54ded6b53cbf", 1152788, 404),
 
+	WINGAME1("legendsmyths", "", "LEGENDS.EXE", "t:284de969ddebeb649530f80c74a8e961", 691607, 404),
+	MACGAME1("legendsmyths", "", "Legends & Myths", "r:67f572196550aedb1f9523d782022be0", 482610, 404),
+
 	WINGAME2("leonardo", "2.0",			  "LEO.EXE", "t:d39f3010cadcb7204ceb8f00c3d41fb3", 692403,
 										  "LEOWINMV/INDEX.DIR", "t:17356e4b7703c1267b5dec7e7acd03eb", 779440, 404),
 	WINGAME2("leonardo", "2.0, No intro", "NO_INTRO.EXE", "t:966ea4aaa0fb3a23c3fd55e0134b81cf", 692411,




More information about the Scummvm-git-logs mailing list