[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