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

sev- noreply at scummvm.org
Mon Mar 11 00:04:55 UTC 2024


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

Summary:
8b9d31eda8 DIRECTOR: XOBJ: Refactor open/close to use ObjectType
366ede608f DEVTOOLS: Add Lingo Xtra support to director-generate-xobj-stub
b782ab4607 DIRECTOR: Update gadgetpaf detection entry
ce2b2354c3 DIRECTOR: Add Xtras folder detection
750566a25f DIRECTOR: XOBJ: Add D5 methods to FileIO
84d009e6b8 DIRECTOR: LINGO: Implement b_member
2ba42271d7 DIRECTOR: Add initial RTE loading support
5d74952707 DIRECTOR: Add "type of member" alias added in D5
a984f36fc2 DIRECTOR: Add "memberNum of sprite" alias added in D5
bf88a47208 DIRECTOR: Add "the rollOver" entity added in D5
7daf4bde43 DIRECTOR: Fix encoding bugs in Cast::getVideoPath()
3123ea69b4 DIRECTOR: Round up fractional tick counts in DigitalVideoCastMember
bb530a8b6d DIRECTOR: Add Mars Attacks Mission Disks to detection
f14649d5a4 DIRECTOR: Set scriptId on sprites even in puppet mode
27cd3a75aa DIRECTOR: Proactively attempt to load DigitalVideoCastMember
e47efa9013 DIRECTOR: Update amber detection entry
10594c29d3 DIRECTOR: Add rough detection for loading an Xtra vs XObject
fa4848cf8c DIRECTOR: XOBJ: Add m_error support to FileIO
885e589356 DIRECTOR: Add script patch for CD detection in AMBER: Journeys Beyond.
f3c3c094e4 DIRECTOR: LINGO: Add ParentScript check to b_script
48d2a760e3 DIRECTOR: XTRA: Add stubs for ScrnUtil
a1b16fa399 DIRECTOR: Preserve trails on screen


Commit: 8b9d31eda88dc75ccb552425cc426109bc3ae60b
    https://github.com/scummvm/scummvm/commit/8b9d31eda88dc75ccb552425cc426109bc3ae60b
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: XOBJ: Refactor open/close to use ObjectType

Changed paths:
    engines/director/lingo/lingo.h
    engines/director/lingo/xlibs/aiff.cpp
    engines/director/lingo/xlibs/aiff.h
    engines/director/lingo/xlibs/applecdxobj.cpp
    engines/director/lingo/xlibs/applecdxobj.h
    engines/director/lingo/xlibs/askuser.cpp
    engines/director/lingo/xlibs/askuser.h
    engines/director/lingo/xlibs/barakeobj.cpp
    engines/director/lingo/xlibs/barakeobj.h
    engines/director/lingo/xlibs/batqt.cpp
    engines/director/lingo/xlibs/batqt.h
    engines/director/lingo/xlibs/blitpict.cpp
    engines/director/lingo/xlibs/blitpict.h
    engines/director/lingo/xlibs/cdromxobj.cpp
    engines/director/lingo/xlibs/cdromxobj.h
    engines/director/lingo/xlibs/colorcursorxobj.cpp
    engines/director/lingo/xlibs/colorcursorxobj.h
    engines/director/lingo/xlibs/colorxobj.cpp
    engines/director/lingo/xlibs/colorxobj.h
    engines/director/lingo/xlibs/consumer.cpp
    engines/director/lingo/xlibs/consumer.h
    engines/director/lingo/xlibs/cursorxobj.cpp
    engines/director/lingo/xlibs/cursorxobj.h
    engines/director/lingo/xlibs/darkenscreen.cpp
    engines/director/lingo/xlibs/darkenscreen.h
    engines/director/lingo/xlibs/developerStack.cpp
    engines/director/lingo/xlibs/developerStack.h
    engines/director/lingo/xlibs/dialogsxobj.cpp
    engines/director/lingo/xlibs/dialogsxobj.h
    engines/director/lingo/xlibs/dirutil.cpp
    engines/director/lingo/xlibs/dirutil.h
    engines/director/lingo/xlibs/dpwavi.cpp
    engines/director/lingo/xlibs/dpwavi.h
    engines/director/lingo/xlibs/dpwqtw.cpp
    engines/director/lingo/xlibs/dpwqtw.h
    engines/director/lingo/xlibs/draw.cpp
    engines/director/lingo/xlibs/draw.h
    engines/director/lingo/xlibs/ednox.cpp
    engines/director/lingo/xlibs/ednox.h
    engines/director/lingo/xlibs/eventq.cpp
    engines/director/lingo/xlibs/eventq.h
    engines/director/lingo/xlibs/fadegammadownxcmd.cpp
    engines/director/lingo/xlibs/fadegammadownxcmd.h
    engines/director/lingo/xlibs/fadegammaupxcmd.cpp
    engines/director/lingo/xlibs/fadegammaupxcmd.h
    engines/director/lingo/xlibs/fadegammaxcmd.cpp
    engines/director/lingo/xlibs/fadegammaxcmd.h
    engines/director/lingo/xlibs/fedracul.cpp
    engines/director/lingo/xlibs/fedracul.h
    engines/director/lingo/xlibs/feimasks.cpp
    engines/director/lingo/xlibs/feimasks.h
    engines/director/lingo/xlibs/feiprefs.cpp
    engines/director/lingo/xlibs/feiprefs.h
    engines/director/lingo/xlibs/fileexists.cpp
    engines/director/lingo/xlibs/fileexists.h
    engines/director/lingo/xlibs/fileio.cpp
    engines/director/lingo/xlibs/fileio.h
    engines/director/lingo/xlibs/findereventsxcmd.cpp
    engines/director/lingo/xlibs/findereventsxcmd.h
    engines/director/lingo/xlibs/findfolder.cpp
    engines/director/lingo/xlibs/findfolder.h
    engines/director/lingo/xlibs/findsys.cpp
    engines/director/lingo/xlibs/findsys.h
    engines/director/lingo/xlibs/findwin.cpp
    engines/director/lingo/xlibs/findwin.h
    engines/director/lingo/xlibs/flushxobj.cpp
    engines/director/lingo/xlibs/flushxobj.h
    engines/director/lingo/xlibs/fplayxobj.cpp
    engines/director/lingo/xlibs/fplayxobj.h
    engines/director/lingo/xlibs/gpid.cpp
    engines/director/lingo/xlibs/gpid.h
    engines/director/lingo/xlibs/hitmap.cpp
    engines/director/lingo/xlibs/hitmap.h
    engines/director/lingo/xlibs/iscd.cpp
    engines/director/lingo/xlibs/iscd.h
    engines/director/lingo/xlibs/ispippin.cpp
    engines/director/lingo/xlibs/ispippin.h
    engines/director/lingo/xlibs/jitdraw3.cpp
    engines/director/lingo/xlibs/jitdraw3.h
    engines/director/lingo/xlibs/jwxini.cpp
    engines/director/lingo/xlibs/jwxini.h
    engines/director/lingo/xlibs/labeldrvxobj.cpp
    engines/director/lingo/xlibs/labeldrvxobj.h
    engines/director/lingo/xlibs/maniacbg.cpp
    engines/director/lingo/xlibs/maniacbg.h
    engines/director/lingo/xlibs/mapnavigatorxobj.cpp
    engines/director/lingo/xlibs/mapnavigatorxobj.h
    engines/director/lingo/xlibs/memcheckxobj.cpp
    engines/director/lingo/xlibs/memcheckxobj.h
    engines/director/lingo/xlibs/memoryxobj.cpp
    engines/director/lingo/xlibs/memoryxobj.h
    engines/director/lingo/xlibs/misc.cpp
    engines/director/lingo/xlibs/misc.h
    engines/director/lingo/xlibs/miscx.cpp
    engines/director/lingo/xlibs/miscx.h
    engines/director/lingo/xlibs/mmaskxobj.cpp
    engines/director/lingo/xlibs/mmaskxobj.h
    engines/director/lingo/xlibs/moovxobj.cpp
    engines/director/lingo/xlibs/moovxobj.h
    engines/director/lingo/xlibs/movemousexobj.cpp
    engines/director/lingo/xlibs/movemousexobj.h
    engines/director/lingo/xlibs/movieidxxobj.cpp
    engines/director/lingo/xlibs/movieidxxobj.h
    engines/director/lingo/xlibs/movutils.cpp
    engines/director/lingo/xlibs/movutils.h
    engines/director/lingo/xlibs/orthoplayxobj.cpp
    engines/director/lingo/xlibs/orthoplayxobj.h
    engines/director/lingo/xlibs/palxobj.cpp
    engines/director/lingo/xlibs/palxobj.h
    engines/director/lingo/xlibs/panel.cpp
    engines/director/lingo/xlibs/panel.h
    engines/director/lingo/xlibs/popupmenuxobj.cpp
    engines/director/lingo/xlibs/popupmenuxobj.h
    engines/director/lingo/xlibs/porta.cpp
    engines/director/lingo/xlibs/porta.h
    engines/director/lingo/xlibs/prefpath.cpp
    engines/director/lingo/xlibs/prefpath.h
    engines/director/lingo/xlibs/printomatic.cpp
    engines/director/lingo/xlibs/printomatic.h
    engines/director/lingo/xlibs/processxobj.cpp
    engines/director/lingo/xlibs/processxobj.h
    engines/director/lingo/xlibs/qtcatmovieplayerxobj.cpp
    engines/director/lingo/xlibs/qtcatmovieplayerxobj.h
    engines/director/lingo/xlibs/qtmovie.cpp
    engines/director/lingo/xlibs/qtmovie.h
    engines/director/lingo/xlibs/qtvr.cpp
    engines/director/lingo/xlibs/qtvr.h
    engines/director/lingo/xlibs/quicktime.cpp
    engines/director/lingo/xlibs/quicktime.h
    engines/director/lingo/xlibs/registercomponent.cpp
    engines/director/lingo/xlibs/registercomponent.h
    engines/director/lingo/xlibs/serialportxobj.cpp
    engines/director/lingo/xlibs/serialportxobj.h
    engines/director/lingo/xlibs/soundjam.cpp
    engines/director/lingo/xlibs/soundjam.h
    engines/director/lingo/xlibs/spacemgr.cpp
    engines/director/lingo/xlibs/spacemgr.h
    engines/director/lingo/xlibs/stagetc.cpp
    engines/director/lingo/xlibs/stagetc.h
    engines/director/lingo/xlibs/unittest.cpp
    engines/director/lingo/xlibs/unittest.h
    engines/director/lingo/xlibs/valkyrie.cpp
    engines/director/lingo/xlibs/valkyrie.h
    engines/director/lingo/xlibs/videodiscxobj.cpp
    engines/director/lingo/xlibs/videodiscxobj.h
    engines/director/lingo/xlibs/vmisonxfcn.cpp
    engines/director/lingo/xlibs/vmisonxfcn.h
    engines/director/lingo/xlibs/volumelist.cpp
    engines/director/lingo/xlibs/volumelist.h
    engines/director/lingo/xlibs/widgetxobj.cpp
    engines/director/lingo/xlibs/widgetxobj.h
    engines/director/lingo/xlibs/window.cpp
    engines/director/lingo/xlibs/window.h
    engines/director/lingo/xlibs/wininfo.cpp
    engines/director/lingo/xlibs/wininfo.h
    engines/director/lingo/xlibs/winxobj.cpp
    engines/director/lingo/xlibs/winxobj.h
    engines/director/lingo/xlibs/xcmdglue.cpp
    engines/director/lingo/xlibs/xcmdglue.h
    engines/director/lingo/xlibs/xio.cpp
    engines/director/lingo/xlibs/xio.h
    engines/director/lingo/xlibs/xplayanim.cpp
    engines/director/lingo/xlibs/xplayanim.h
    engines/director/lingo/xlibs/xsoundxfcn.cpp
    engines/director/lingo/xlibs/xsoundxfcn.h
    engines/director/lingo/xlibs/yasix.cpp
    engines/director/lingo/xlibs/yasix.h


diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index d7b7e6040ea..937f40cbfee 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -235,7 +235,7 @@ typedef Common::HashMap<Common::String, Symbol, Common::IgnoreCase_Hash, Common:
 typedef Common::HashMap<Common::String, Datum, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> DatumHash;
 typedef Common::HashMap<Common::String, Builtin *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> BuiltinHash;
 typedef Common::HashMap<Common::String, VarType, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VarTypeHash;
-typedef void (*XLibFunc)(int);
+typedef void (*XLibFunc)(ObjectType);
 typedef Common::HashMap<Common::String, XLibFunc, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> XLibFuncHash;
 typedef Common::HashMap<Common::String, ObjectType, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> OpenXLibsHash;
 
diff --git a/engines/director/lingo/xlibs/aiff.cpp b/engines/director/lingo/xlibs/aiff.cpp
index a70815f1f14..c835db4c73e 100644
--- a/engines/director/lingo/xlibs/aiff.cpp
+++ b/engines/director/lingo/xlibs/aiff.cpp
@@ -67,7 +67,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void AiffXObj::open(int type) {
+void AiffXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		AiffXObject::initMethods(xlibMethods);
 		AiffXObject *xobj = new AiffXObject(kXObj);
@@ -75,7 +75,7 @@ void AiffXObj::open(int type) {
 	}
 }
 
-void AiffXObj::close(int type) {
+void AiffXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		AiffXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/aiff.h b/engines/director/lingo/xlibs/aiff.h
index 6dec423fd61..a5ec875ec4b 100644
--- a/engines/director/lingo/xlibs/aiff.h
+++ b/engines/director/lingo/xlibs/aiff.h
@@ -35,8 +35,8 @@ namespace AiffXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 
diff --git a/engines/director/lingo/xlibs/applecdxobj.cpp b/engines/director/lingo/xlibs/applecdxobj.cpp
index fdda01ed3fe..847addb9a3a 100644
--- a/engines/director/lingo/xlibs/applecdxobj.cpp
+++ b/engines/director/lingo/xlibs/applecdxobj.cpp
@@ -124,7 +124,7 @@ static MethodProto xlibMethods[] = {
     { nullptr, nullptr, 0, 0, 0 }
 };
 
-void AppleCDXObj::open(int type) {
+void AppleCDXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		AppleCDXObject::initMethods(xlibMethods);
 		AppleCDXObject *xobj = new AppleCDXObject(kXObj);
@@ -132,7 +132,7 @@ void AppleCDXObj::open(int type) {
 	}
 }
 
-void AppleCDXObj::close(int type) {
+void AppleCDXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		AppleCDXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/applecdxobj.h b/engines/director/lingo/xlibs/applecdxobj.h
index 24f7d521a2d..0ad75e3b145 100644
--- a/engines/director/lingo/xlibs/applecdxobj.h
+++ b/engines/director/lingo/xlibs/applecdxobj.h
@@ -47,8 +47,8 @@ namespace AppleCDXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/askuser.cpp b/engines/director/lingo/xlibs/askuser.cpp
index 9ae487b9da6..38ae2024e72 100644
--- a/engines/director/lingo/xlibs/askuser.cpp
+++ b/engines/director/lingo/xlibs/askuser.cpp
@@ -62,22 +62,18 @@ AskUserXObject::AskUserXObject(ObjectType ObjectType) :Object<AskUserXObject>("A
 	_objType = ObjectType;
 }
 
-void AskUser::open(int type) {
+void AskUser::open(ObjectType type) {
 	if (type == kXObj) {
 		AskUserXObject::initMethods(xlibMethods);
 		AskUserXObject *xobj = new AskUserXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void AskUser::close(int type) {
+void AskUser::close(ObjectType type) {
 	if (type == kXObj) {
 		AskUserXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/askuser.h b/engines/director/lingo/xlibs/askuser.h
index c94f9994f07..de51e726cd0 100644
--- a/engines/director/lingo/xlibs/askuser.h
+++ b/engines/director/lingo/xlibs/askuser.h
@@ -34,8 +34,8 @@ namespace AskUser {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/barakeobj.cpp b/engines/director/lingo/xlibs/barakeobj.cpp
index e3f72cee072..c3880d1f67a 100644
--- a/engines/director/lingo/xlibs/barakeobj.cpp
+++ b/engines/director/lingo/xlibs/barakeobj.cpp
@@ -57,7 +57,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void BarakeObj::open(int type) {
+void BarakeObj::open(ObjectType type) {
 	if (type == kXObj) {
 		BarakeObject::initMethods(xlibMethods);
 		BarakeObject *xobj = new BarakeObject(kXObj);
@@ -65,7 +65,7 @@ void BarakeObj::open(int type) {
 	}
 }
 
-void BarakeObj::close(int type) {
+void BarakeObj::close(ObjectType type) {
 	if (type == kXObj) {
 		BarakeObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/barakeobj.h b/engines/director/lingo/xlibs/barakeobj.h
index 0423c5e965c..dc0191dad00 100644
--- a/engines/director/lingo/xlibs/barakeobj.h
+++ b/engines/director/lingo/xlibs/barakeobj.h
@@ -34,8 +34,8 @@ namespace BarakeObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_clear(int nargs);
diff --git a/engines/director/lingo/xlibs/batqt.cpp b/engines/director/lingo/xlibs/batqt.cpp
index 373b9edeb30..8bd406a2ded 100644
--- a/engines/director/lingo/xlibs/batqt.cpp
+++ b/engines/director/lingo/xlibs/batqt.cpp
@@ -96,7 +96,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void BatQT::open(int type) {
+void BatQT::open(ObjectType type) {
 	if (type == kXObj) {
 		BatQTXObject::initMethods(xlibMethods);
 		BatQTXObject *xobj = new BatQTXObject(kXObj);
@@ -104,7 +104,7 @@ void BatQT::open(int type) {
 	}
 }
 
-void BatQT::close(int type) {
+void BatQT::close(ObjectType type) {
 	if (type == kXObj) {
 		BatQTXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/batqt.h b/engines/director/lingo/xlibs/batqt.h
index 622ee52dea6..2f6d4a3f913 100644
--- a/engines/director/lingo/xlibs/batqt.h
+++ b/engines/director/lingo/xlibs/batqt.h
@@ -44,8 +44,8 @@ namespace BatQT {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/blitpict.cpp b/engines/director/lingo/xlibs/blitpict.cpp
index 7d830d2541c..0b993668eed 100644
--- a/engines/director/lingo/xlibs/blitpict.cpp
+++ b/engines/director/lingo/xlibs/blitpict.cpp
@@ -76,22 +76,18 @@ BlitPictXObject::BlitPictXObject(ObjectType ObjectType) :Object<BlitPictXObject>
 	_objType = ObjectType;
 }
 
-void BlitPictXObj::open(int type) {
+void BlitPictXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		BlitPictXObject::initMethods(xlibMethods);
 		BlitPictXObject *xobj = new BlitPictXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void BlitPictXObj::close(int type) {
+void BlitPictXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		BlitPictXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/blitpict.h b/engines/director/lingo/xlibs/blitpict.h
index fd4d9d9d462..32b55792d61 100644
--- a/engines/director/lingo/xlibs/blitpict.h
+++ b/engines/director/lingo/xlibs/blitpict.h
@@ -34,8 +34,8 @@ namespace BlitPictXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/cdromxobj.cpp b/engines/director/lingo/xlibs/cdromxobj.cpp
index 742971cdc77..e3e82a895db 100644
--- a/engines/director/lingo/xlibs/cdromxobj.cpp
+++ b/engines/director/lingo/xlibs/cdromxobj.cpp
@@ -210,7 +210,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void CDROMXObj::open(int type) {
+void CDROMXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		CDROMXObject::initMethods(xlibMethods);
 		CDROMXObject *xobj = new CDROMXObject(kXObj);
@@ -218,7 +218,7 @@ void CDROMXObj::open(int type) {
 	}
 }
 
-void CDROMXObj::close(int type) {
+void CDROMXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		CDROMXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/cdromxobj.h b/engines/director/lingo/xlibs/cdromxobj.h
index 220b96c6646..3b306eab023 100644
--- a/engines/director/lingo/xlibs/cdromxobj.h
+++ b/engines/director/lingo/xlibs/cdromxobj.h
@@ -37,8 +37,8 @@ namespace CDROMXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_name(int nargs);
diff --git a/engines/director/lingo/xlibs/colorcursorxobj.cpp b/engines/director/lingo/xlibs/colorcursorxobj.cpp
index a73f7b5b28f..96e182ff5f0 100644
--- a/engines/director/lingo/xlibs/colorcursorxobj.cpp
+++ b/engines/director/lingo/xlibs/colorcursorxobj.cpp
@@ -62,22 +62,18 @@ ColorCursorXObject::ColorCursorXObject(ObjectType ObjectType) :Object<ColorCurso
 	_objType = ObjectType;
 }
 
-void ColorCursorXObj::open(int type) {
+void ColorCursorXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ColorCursorXObject::initMethods(xlibMethods);
 		ColorCursorXObject *xobj = new ColorCursorXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void ColorCursorXObj::close(int type) {
+void ColorCursorXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ColorCursorXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/colorcursorxobj.h b/engines/director/lingo/xlibs/colorcursorxobj.h
index 6f49dbf5f45..f7b49003d04 100644
--- a/engines/director/lingo/xlibs/colorcursorxobj.h
+++ b/engines/director/lingo/xlibs/colorcursorxobj.h
@@ -34,8 +34,8 @@ namespace ColorCursorXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/colorxobj.cpp b/engines/director/lingo/xlibs/colorxobj.cpp
index a3ecdd03b05..a6a9d0e6958 100644
--- a/engines/director/lingo/xlibs/colorxobj.cpp
+++ b/engines/director/lingo/xlibs/colorxobj.cpp
@@ -82,22 +82,18 @@ ColorXObject::ColorXObject(ObjectType ObjectType) :Object<ColorXObject>("Color")
 	_objType = ObjectType;
 }
 
-void ColorXObj::open(int type) {
+void ColorXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ColorXObject::initMethods(xlibMethods);
 		ColorXObject *xobj = new ColorXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void ColorXObj::close(int type) {
+void ColorXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ColorXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/colorxobj.h b/engines/director/lingo/xlibs/colorxobj.h
index cb3e332f258..1f0dd198dbc 100644
--- a/engines/director/lingo/xlibs/colorxobj.h
+++ b/engines/director/lingo/xlibs/colorxobj.h
@@ -29,8 +29,8 @@ namespace ColorXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/consumer.cpp b/engines/director/lingo/xlibs/consumer.cpp
index aaa17c444d3..0c25230d999 100644
--- a/engines/director/lingo/xlibs/consumer.cpp
+++ b/engines/director/lingo/xlibs/consumer.cpp
@@ -82,22 +82,18 @@ ConsumerXObject::ConsumerXObject(ObjectType ObjectType) :Object<ConsumerXObject>
 	_objType = ObjectType;
 }
 
-void ConsumerXObj::open(int type) {
+void ConsumerXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ConsumerXObject::initMethods(xlibMethods);
 		ConsumerXObject *xobj = new ConsumerXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void ConsumerXObj::close(int type) {
+void ConsumerXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ConsumerXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/consumer.h b/engines/director/lingo/xlibs/consumer.h
index 513fbbb95ce..43c05cb3ab4 100644
--- a/engines/director/lingo/xlibs/consumer.h
+++ b/engines/director/lingo/xlibs/consumer.h
@@ -34,8 +34,8 @@ namespace ConsumerXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/cursorxobj.cpp b/engines/director/lingo/xlibs/cursorxobj.cpp
index c7253441add..c28d22520a6 100644
--- a/engines/director/lingo/xlibs/cursorxobj.cpp
+++ b/engines/director/lingo/xlibs/cursorxobj.cpp
@@ -61,22 +61,18 @@ CursorXObject::CursorXObject(ObjectType ObjectType) :Object<CursorXObject>("Curs
 	_objType = ObjectType;
 }
 
-void CursorXObj::open(int type) {
+void CursorXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		CursorXObject::initMethods(xlibMethods);
 		CursorXObject *xobj = new CursorXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void CursorXObj::close(int type) {
+void CursorXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		CursorXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/cursorxobj.h b/engines/director/lingo/xlibs/cursorxobj.h
index 49767c5f455..54266c1e397 100644
--- a/engines/director/lingo/xlibs/cursorxobj.h
+++ b/engines/director/lingo/xlibs/cursorxobj.h
@@ -34,8 +34,8 @@ namespace CursorXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/darkenscreen.cpp b/engines/director/lingo/xlibs/darkenscreen.cpp
index 204a794079f..2dc49312ee1 100644
--- a/engines/director/lingo/xlibs/darkenscreen.cpp
+++ b/engines/director/lingo/xlibs/darkenscreen.cpp
@@ -50,11 +50,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void DarkenScreen::open(int type) {
+void DarkenScreen::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void DarkenScreen::close(int type) {
+void DarkenScreen::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/darkenscreen.h b/engines/director/lingo/xlibs/darkenscreen.h
index ba6681f1efe..a2a38c45c7a 100644
--- a/engines/director/lingo/xlibs/darkenscreen.h
+++ b/engines/director/lingo/xlibs/darkenscreen.h
@@ -29,8 +29,8 @@ namespace DarkenScreen {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_darkenscreen(int nargs);
 
diff --git a/engines/director/lingo/xlibs/developerStack.cpp b/engines/director/lingo/xlibs/developerStack.cpp
index 6cec4e835aa..e1945bd56b9 100644
--- a/engines/director/lingo/xlibs/developerStack.cpp
+++ b/engines/director/lingo/xlibs/developerStack.cpp
@@ -141,11 +141,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void DeveloperStack::open(int type) {
+void DeveloperStack::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void DeveloperStack::close(int type) {
+void DeveloperStack::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/developerStack.h b/engines/director/lingo/xlibs/developerStack.h
index c0c9830b6ba..a21b8939326 100644
--- a/engines/director/lingo/xlibs/developerStack.h
+++ b/engines/director/lingo/xlibs/developerStack.h
@@ -29,8 +29,8 @@ namespace DeveloperStack {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void b_setvolume(int nargs);
 
diff --git a/engines/director/lingo/xlibs/dialogsxobj.cpp b/engines/director/lingo/xlibs/dialogsxobj.cpp
index 90d678fb19d..7c85d772d39 100644
--- a/engines/director/lingo/xlibs/dialogsxobj.cpp
+++ b/engines/director/lingo/xlibs/dialogsxobj.cpp
@@ -70,7 +70,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void DialogsXObj::open(int type) {
+void DialogsXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		DialogsXObject::initMethods(xlibMethods);
 		DialogsXObject *xobj = new DialogsXObject(kXObj);
@@ -80,7 +80,7 @@ void DialogsXObj::open(int type) {
 	}
 }
 
-void DialogsXObj::close(int type) {
+void DialogsXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		DialogsXObject::cleanupMethods();
 		for (uint i = 0; xlibNames[i]; i++) {
diff --git a/engines/director/lingo/xlibs/dialogsxobj.h b/engines/director/lingo/xlibs/dialogsxobj.h
index 4db6722ff00..a9c61d59825 100644
--- a/engines/director/lingo/xlibs/dialogsxobj.h
+++ b/engines/director/lingo/xlibs/dialogsxobj.h
@@ -33,8 +33,8 @@ namespace DialogsXObj {
 extern const char *xlibNames[];
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_putFile(int nargs);
diff --git a/engines/director/lingo/xlibs/dirutil.cpp b/engines/director/lingo/xlibs/dirutil.cpp
index 772427e1a97..3a5f725a50f 100644
--- a/engines/director/lingo/xlibs/dirutil.cpp
+++ b/engines/director/lingo/xlibs/dirutil.cpp
@@ -76,22 +76,18 @@ DirUtilXObject::DirUtilXObject(ObjectType ObjectType) :Object<DirUtilXObject>("D
 	_objType = ObjectType;
 }
 
-void DirUtilXObj::open(int type) {
+void DirUtilXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		DirUtilXObject::initMethods(xlibMethods);
 		DirUtilXObject *xobj = new DirUtilXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void DirUtilXObj::close(int type) {
+void DirUtilXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		DirUtilXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/dirutil.h b/engines/director/lingo/xlibs/dirutil.h
index 56e7e0b9a9c..7282ed2d4b5 100644
--- a/engines/director/lingo/xlibs/dirutil.h
+++ b/engines/director/lingo/xlibs/dirutil.h
@@ -34,8 +34,8 @@ namespace DirUtilXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/dpwavi.cpp b/engines/director/lingo/xlibs/dpwavi.cpp
index 442da24efeb..ed89dd8e5d6 100644
--- a/engines/director/lingo/xlibs/dpwavi.cpp
+++ b/engines/director/lingo/xlibs/dpwavi.cpp
@@ -60,7 +60,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void DPwAVI::open(int type) {
+void DPwAVI::open(ObjectType type) {
 	if (type == kXObj) {
 		DPwAVIXObject::initMethods(xlibMethods);
 		DPwAVIXObject *xobj = new DPwAVIXObject(kXObj);
@@ -68,7 +68,7 @@ void DPwAVI::open(int type) {
 	}
 }
 
-void DPwAVI::close(int type) {
+void DPwAVI::close(ObjectType type) {
 	if (type == kXObj) {
 		DPwAVIXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/dpwavi.h b/engines/director/lingo/xlibs/dpwavi.h
index 846cc54ecba..eb38baacc7b 100644
--- a/engines/director/lingo/xlibs/dpwavi.h
+++ b/engines/director/lingo/xlibs/dpwavi.h
@@ -34,8 +34,8 @@ namespace DPwAVI {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_startup(int nargs);
diff --git a/engines/director/lingo/xlibs/dpwqtw.cpp b/engines/director/lingo/xlibs/dpwqtw.cpp
index 0090b6818b9..7eb09b4ccc9 100644
--- a/engines/director/lingo/xlibs/dpwqtw.cpp
+++ b/engines/director/lingo/xlibs/dpwqtw.cpp
@@ -59,7 +59,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void DPwQTw::open(int type) {
+void DPwQTw::open(ObjectType type) {
 	if (type == kXObj) {
 		DPwQTwXObject::initMethods(xlibMethods);
 		DPwQTwXObject *xobj = new DPwQTwXObject(kXObj);
@@ -67,7 +67,7 @@ void DPwQTw::open(int type) {
 	}
 }
 
-void DPwQTw::close(int type) {
+void DPwQTw::close(ObjectType type) {
 	if (type == kXObj) {
 		DPwQTwXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/dpwqtw.h b/engines/director/lingo/xlibs/dpwqtw.h
index a1ac4830f14..0b5b868ce08 100644
--- a/engines/director/lingo/xlibs/dpwqtw.h
+++ b/engines/director/lingo/xlibs/dpwqtw.h
@@ -34,8 +34,8 @@ namespace DPwQTw {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_startup(int nargs);
diff --git a/engines/director/lingo/xlibs/draw.cpp b/engines/director/lingo/xlibs/draw.cpp
index 85eefb6be78..aa94a150a02 100644
--- a/engines/director/lingo/xlibs/draw.cpp
+++ b/engines/director/lingo/xlibs/draw.cpp
@@ -116,7 +116,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void DrawXObj::open(int type) {
+void DrawXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		DrawXObject::initMethods(xlibMethods);
 		DrawXObject *xobj = new DrawXObject(kXObj);
@@ -124,7 +124,7 @@ void DrawXObj::open(int type) {
 	}
 }
 
-void DrawXObj::close(int type) {
+void DrawXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		DrawXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/draw.h b/engines/director/lingo/xlibs/draw.h
index d55ea7a8da6..eed5d9ec6b9 100644
--- a/engines/director/lingo/xlibs/draw.h
+++ b/engines/director/lingo/xlibs/draw.h
@@ -34,8 +34,8 @@ namespace DrawXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/ednox.cpp b/engines/director/lingo/xlibs/ednox.cpp
index ab5544e896d..825849322c2 100644
--- a/engines/director/lingo/xlibs/ednox.cpp
+++ b/engines/director/lingo/xlibs/ednox.cpp
@@ -95,7 +95,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void Ednox::open(int type) {
+void Ednox::open(ObjectType type) {
 	if (type == kXObj) {
 		EdnoxObject::initMethods(xlibMethods);
 		EdnoxObject *xobj = new EdnoxObject(kXObj);
@@ -103,7 +103,7 @@ void Ednox::open(int type) {
 	}
 }
 
-void Ednox::close(int type) {
+void Ednox::close(ObjectType type) {
 	if (type == kXObj) {
 		EdnoxObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/ednox.h b/engines/director/lingo/xlibs/ednox.h
index 334fe240bd3..65aff033971 100644
--- a/engines/director/lingo/xlibs/ednox.h
+++ b/engines/director/lingo/xlibs/ednox.h
@@ -34,8 +34,8 @@ namespace Ednox {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/eventq.cpp b/engines/director/lingo/xlibs/eventq.cpp
index 25dc1fa9389..2c4a789b8b5 100644
--- a/engines/director/lingo/xlibs/eventq.cpp
+++ b/engines/director/lingo/xlibs/eventq.cpp
@@ -70,7 +70,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void EventQXObj::open(int type) {
+void EventQXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		EventQXObject::initMethods(xlibMethods);
 		EventQXObject *xobj = new EventQXObject(kXObj);
@@ -80,7 +80,7 @@ void EventQXObj::open(int type) {
 	}
 }
 
-void EventQXObj::close(int type) {
+void EventQXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		EventQXObject::cleanupMethods();
 		for (uint i = 0; xlibNames[i]; i++) {
diff --git a/engines/director/lingo/xlibs/eventq.h b/engines/director/lingo/xlibs/eventq.h
index d9bf7886f64..59067c6c4f8 100644
--- a/engines/director/lingo/xlibs/eventq.h
+++ b/engines/director/lingo/xlibs/eventq.h
@@ -33,8 +33,8 @@ namespace EventQXObj {
 extern const char *xlibNames[];
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/fadegammadownxcmd.cpp b/engines/director/lingo/xlibs/fadegammadownxcmd.cpp
index c9386aa5041..40df9cf1970 100644
--- a/engines/director/lingo/xlibs/fadegammadownxcmd.cpp
+++ b/engines/director/lingo/xlibs/fadegammadownxcmd.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FadeGammaDownXCMD::open(int type) {
+void FadeGammaDownXCMD::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FadeGammaDownXCMD::close(int type) {
+void FadeGammaDownXCMD::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/fadegammadownxcmd.h b/engines/director/lingo/xlibs/fadegammadownxcmd.h
index d422ebd4e52..0ba5225712d 100644
--- a/engines/director/lingo/xlibs/fadegammadownxcmd.h
+++ b/engines/director/lingo/xlibs/fadegammadownxcmd.h
@@ -29,8 +29,8 @@ namespace FadeGammaDownXCMD {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_FadeGammaDown(int nargs);
 
diff --git a/engines/director/lingo/xlibs/fadegammaupxcmd.cpp b/engines/director/lingo/xlibs/fadegammaupxcmd.cpp
index 7afb86af224..023003964d4 100644
--- a/engines/director/lingo/xlibs/fadegammaupxcmd.cpp
+++ b/engines/director/lingo/xlibs/fadegammaupxcmd.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FadeGammaUpXCMD::open(int type) {
+void FadeGammaUpXCMD::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FadeGammaUpXCMD::close(int type) {
+void FadeGammaUpXCMD::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/fadegammaupxcmd.h b/engines/director/lingo/xlibs/fadegammaupxcmd.h
index 18b4a1d3611..0c3d775fbc5 100644
--- a/engines/director/lingo/xlibs/fadegammaupxcmd.h
+++ b/engines/director/lingo/xlibs/fadegammaupxcmd.h
@@ -29,8 +29,8 @@ namespace FadeGammaUpXCMD {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_FadeGammaUp(int nargs);
 
diff --git a/engines/director/lingo/xlibs/fadegammaxcmd.cpp b/engines/director/lingo/xlibs/fadegammaxcmd.cpp
index db34b9ebcf5..a440c07ba00 100644
--- a/engines/director/lingo/xlibs/fadegammaxcmd.cpp
+++ b/engines/director/lingo/xlibs/fadegammaxcmd.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FadeGammaXCMD::open(int type) {
+void FadeGammaXCMD::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FadeGammaXCMD::close(int type) {
+void FadeGammaXCMD::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/fadegammaxcmd.h b/engines/director/lingo/xlibs/fadegammaxcmd.h
index d85745d26a9..ff6099005d2 100644
--- a/engines/director/lingo/xlibs/fadegammaxcmd.h
+++ b/engines/director/lingo/xlibs/fadegammaxcmd.h
@@ -29,8 +29,8 @@ namespace FadeGammaXCMD {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_FadeGamma(int nargs);
 
diff --git a/engines/director/lingo/xlibs/fedracul.cpp b/engines/director/lingo/xlibs/fedracul.cpp
index d5ce705db86..14981899957 100644
--- a/engines/director/lingo/xlibs/fedracul.cpp
+++ b/engines/director/lingo/xlibs/fedracul.cpp
@@ -66,7 +66,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FEDraculXObj::open(int type) {
+void FEDraculXObj::open(ObjectType type) {
    if (type == kXObj) {
 		FEDraculXObject::initMethods(xlibMethods);
 		FEDraculXObject *xobj = new FEDraculXObject(kXObj);
@@ -74,7 +74,7 @@ void FEDraculXObj::open(int type) {
    }
 }
 
-void FEDraculXObj::close(int type) {
+void FEDraculXObj::close(ObjectType type) {
    if (type == kXObj) {
 		FEDraculXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/fedracul.h b/engines/director/lingo/xlibs/fedracul.h
index e5102c6d966..7fa4472a5c9 100644
--- a/engines/director/lingo/xlibs/fedracul.h
+++ b/engines/director/lingo/xlibs/fedracul.h
@@ -35,8 +35,8 @@ namespace FEDraculXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_AddToInventory(int nargs);
diff --git a/engines/director/lingo/xlibs/feimasks.cpp b/engines/director/lingo/xlibs/feimasks.cpp
index ba2c3e60638..15a7293e498 100644
--- a/engines/director/lingo/xlibs/feimasks.cpp
+++ b/engines/director/lingo/xlibs/feimasks.cpp
@@ -55,7 +55,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FEIMasksXObj::open(int type) {
+void FEIMasksXObj::open(ObjectType type) {
    if (type == kXObj) {
 		FEIMasksXObject::initMethods(xlibMethods);
 		FEIMasksXObject *xobj = new FEIMasksXObject(kXObj);
@@ -63,7 +63,7 @@ void FEIMasksXObj::open(int type) {
    }
 }
 
-void FEIMasksXObj::close(int type) {
+void FEIMasksXObj::close(ObjectType type) {
    if (type == kXObj) {
 		FEIMasksXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/feimasks.h b/engines/director/lingo/xlibs/feimasks.h
index cefcdc2d6a6..879bfd2162c 100644
--- a/engines/director/lingo/xlibs/feimasks.h
+++ b/engines/director/lingo/xlibs/feimasks.h
@@ -35,8 +35,8 @@ namespace FEIMasksXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_MaskID(int nargs);
diff --git a/engines/director/lingo/xlibs/feiprefs.cpp b/engines/director/lingo/xlibs/feiprefs.cpp
index ea3f6949d2a..1362b31a5d5 100644
--- a/engines/director/lingo/xlibs/feiprefs.cpp
+++ b/engines/director/lingo/xlibs/feiprefs.cpp
@@ -60,7 +60,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FEIPrefsXObj::open(int type) {
+void FEIPrefsXObj::open(ObjectType type) {
    if (type == kXObj) {
 		FEIPrefsXObject::initMethods(xlibMethods);
 		FEIPrefsXObject *xobj = new FEIPrefsXObject(kXObj);
@@ -68,7 +68,7 @@ void FEIPrefsXObj::open(int type) {
    }
 }
 
-void FEIPrefsXObj::close(int type) {
+void FEIPrefsXObj::close(ObjectType type) {
    if (type == kXObj) {
 		FEIPrefsXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/feiprefs.h b/engines/director/lingo/xlibs/feiprefs.h
index 50bc75492eb..3073f1f2a2d 100644
--- a/engines/director/lingo/xlibs/feiprefs.h
+++ b/engines/director/lingo/xlibs/feiprefs.h
@@ -35,8 +35,8 @@ namespace FEIPrefsXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_prefAppName(int nargs);
diff --git a/engines/director/lingo/xlibs/fileexists.cpp b/engines/director/lingo/xlibs/fileexists.cpp
index 5f724c18492..2d05a3385b5 100644
--- a/engines/director/lingo/xlibs/fileexists.cpp
+++ b/engines/director/lingo/xlibs/fileexists.cpp
@@ -53,11 +53,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FileExists::open(int type) {
+void FileExists::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FileExists::close(int type) {
+void FileExists::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/fileexists.h b/engines/director/lingo/xlibs/fileexists.h
index bafd52824bb..212e4ffbb66 100644
--- a/engines/director/lingo/xlibs/fileexists.h
+++ b/engines/director/lingo/xlibs/fileexists.h
@@ -29,8 +29,8 @@ namespace FileExists {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_fileexists(int nargs);
 
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index ec08637e0dd..255baa79b40 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -136,7 +136,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FileIO::open(int type) {
+void FileIO::open(ObjectType type) {
 	if (type == kXObj) {
 		FileObject::initMethods(xlibMethods);
 		FileObject *xobj = new FileObject(kXObj);
@@ -146,7 +146,7 @@ void FileIO::open(int type) {
 	}
 }
 
-void FileIO::close(int type) {
+void FileIO::close(ObjectType type) {
 	if (type == kXObj) {
 		FileObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/fileio.h b/engines/director/lingo/xlibs/fileio.h
index 90cdb668b27..ff45b15524d 100644
--- a/engines/director/lingo/xlibs/fileio.h
+++ b/engines/director/lingo/xlibs/fileio.h
@@ -70,8 +70,8 @@ namespace FileIO {
 	extern const char *xlibName;
 	extern const char *fileNames[];
 
-	void open(int type);
-	void close(int type);
+	void open(ObjectType type);
+	void close(ObjectType type);
 
 	bool charInMatchString(char ch, const Common::String &matchString);
 	void saveFileError();
diff --git a/engines/director/lingo/xlibs/findereventsxcmd.cpp b/engines/director/lingo/xlibs/findereventsxcmd.cpp
index ea4fd7c24ab..87b1d31355a 100644
--- a/engines/director/lingo/xlibs/findereventsxcmd.cpp
+++ b/engines/director/lingo/xlibs/findereventsxcmd.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FinderEventsXCMD::open(int type) {
+void FinderEventsXCMD::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FinderEventsXCMD::close(int type) {
+void FinderEventsXCMD::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/findereventsxcmd.h b/engines/director/lingo/xlibs/findereventsxcmd.h
index 028edd1aae9..8104b3277ca 100644
--- a/engines/director/lingo/xlibs/findereventsxcmd.h
+++ b/engines/director/lingo/xlibs/findereventsxcmd.h
@@ -29,8 +29,8 @@ namespace FinderEventsXCMD {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_FinderEvents(int nargs);
 
diff --git a/engines/director/lingo/xlibs/findfolder.cpp b/engines/director/lingo/xlibs/findfolder.cpp
index d4794571c18..cdaaa665c5a 100644
--- a/engines/director/lingo/xlibs/findfolder.cpp
+++ b/engines/director/lingo/xlibs/findfolder.cpp
@@ -101,11 +101,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FindFolder::open(int type) {
+void FindFolder::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FindFolder::close(int type) {
+void FindFolder::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/findfolder.h b/engines/director/lingo/xlibs/findfolder.h
index cf5abd290e7..da782e0f71e 100644
--- a/engines/director/lingo/xlibs/findfolder.h
+++ b/engines/director/lingo/xlibs/findfolder.h
@@ -29,8 +29,8 @@ namespace FindFolder {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_findfolder(int nargs);
 
diff --git a/engines/director/lingo/xlibs/findsys.cpp b/engines/director/lingo/xlibs/findsys.cpp
index 7748aedf943..c7370e260f3 100644
--- a/engines/director/lingo/xlibs/findsys.cpp
+++ b/engines/director/lingo/xlibs/findsys.cpp
@@ -60,7 +60,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FindSys::open(int type) {
+void FindSys::open(ObjectType type) {
 	if (type == kXObj) {
 		FindSysXObject::initMethods(xlibMethods);
 		FindSysXObject *xobj = new FindSysXObject(kXObj);
@@ -68,7 +68,7 @@ void FindSys::open(int type) {
 	}
 }
 
-void FindSys::close(int type) {
+void FindSys::close(ObjectType type) {
 	if (type == kXObj) {
 		FindSysXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/findsys.h b/engines/director/lingo/xlibs/findsys.h
index 821fc019bb8..b5587ac3ab6 100644
--- a/engines/director/lingo/xlibs/findsys.h
+++ b/engines/director/lingo/xlibs/findsys.h
@@ -34,8 +34,8 @@ namespace FindSys {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_do(int nargs);
diff --git a/engines/director/lingo/xlibs/findwin.cpp b/engines/director/lingo/xlibs/findwin.cpp
index c563dc9d30a..6bdfa8a3d85 100644
--- a/engines/director/lingo/xlibs/findwin.cpp
+++ b/engines/director/lingo/xlibs/findwin.cpp
@@ -57,7 +57,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FindWin::open(int type) {
+void FindWin::open(ObjectType type) {
 	if (type == kXObj) {
 		FindWinXObject::initMethods(xlibMethods);
 		FindWinXObject *xobj = new FindWinXObject(kXObj);
@@ -65,7 +65,7 @@ void FindWin::open(int type) {
 	}
 }
 
-void FindWin::close(int type) {
+void FindWin::close(ObjectType type) {
 	if (type == kXObj) {
 		FindWinXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/findwin.h b/engines/director/lingo/xlibs/findwin.h
index 8ce413629d0..f303ea7597d 100644
--- a/engines/director/lingo/xlibs/findwin.h
+++ b/engines/director/lingo/xlibs/findwin.h
@@ -34,8 +34,8 @@ namespace FindWin {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_do(int nargs);
diff --git a/engines/director/lingo/xlibs/flushxobj.cpp b/engines/director/lingo/xlibs/flushxobj.cpp
index 3b681431f16..1814ee4eab5 100644
--- a/engines/director/lingo/xlibs/flushxobj.cpp
+++ b/engines/director/lingo/xlibs/flushxobj.cpp
@@ -84,7 +84,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void FlushXObj::open(int type) {
+void FlushXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		FlushXObject::initMethods(xlibMethods);
 		FlushXObject *xobj = new FlushXObject(kXObj);
@@ -94,7 +94,7 @@ void FlushXObj::open(int type) {
 	}
 }
 
-void FlushXObj::close(int type) {
+void FlushXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		FlushXObject::cleanupMethods();
 		for (uint i = 0; xlibNames[i]; i++) {
diff --git a/engines/director/lingo/xlibs/flushxobj.h b/engines/director/lingo/xlibs/flushxobj.h
index 6c75a16d047..1106fa1493c 100644
--- a/engines/director/lingo/xlibs/flushxobj.h
+++ b/engines/director/lingo/xlibs/flushxobj.h
@@ -34,8 +34,8 @@ namespace FlushXObj {
 extern const char *xlibNames[];
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_clearMask(int nargs);
diff --git a/engines/director/lingo/xlibs/fplayxobj.cpp b/engines/director/lingo/xlibs/fplayxobj.cpp
index 260b9881c99..7f2f344d709 100644
--- a/engines/director/lingo/xlibs/fplayxobj.cpp
+++ b/engines/director/lingo/xlibs/fplayxobj.cpp
@@ -64,11 +64,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void FPlayXObj::open(int type) {
+void FPlayXObj::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void FPlayXObj::close(int type) {
+void FPlayXObj::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/fplayxobj.h b/engines/director/lingo/xlibs/fplayxobj.h
index 98f3619990d..8f4fb1fe5b4 100644
--- a/engines/director/lingo/xlibs/fplayxobj.h
+++ b/engines/director/lingo/xlibs/fplayxobj.h
@@ -29,8 +29,8 @@ namespace FPlayXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void b_fplay(int nargs);
 void b_copysnd(int nargs);
diff --git a/engines/director/lingo/xlibs/gpid.cpp b/engines/director/lingo/xlibs/gpid.cpp
index ad825650dc4..4c4608a9a1e 100644
--- a/engines/director/lingo/xlibs/gpid.cpp
+++ b/engines/director/lingo/xlibs/gpid.cpp
@@ -69,7 +69,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void GpidXObj::open(int type) {
+void GpidXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ProductIdXObject::initMethods(xlibMethods);
 		ProductIdXObject *xobj = new ProductIdXObject(kXObj);
@@ -77,7 +77,7 @@ void GpidXObj::open(int type) {
 	}
 }
 
-void GpidXObj::close(int type) {
+void GpidXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ProductIdXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/gpid.h b/engines/director/lingo/xlibs/gpid.h
index 6186959fdae..b7ebcbb2713 100644
--- a/engines/director/lingo/xlibs/gpid.h
+++ b/engines/director/lingo/xlibs/gpid.h
@@ -35,8 +35,8 @@ namespace GpidXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/hitmap.cpp b/engines/director/lingo/xlibs/hitmap.cpp
index f7e6c00730f..607c9732d5e 100644
--- a/engines/director/lingo/xlibs/hitmap.cpp
+++ b/engines/director/lingo/xlibs/hitmap.cpp
@@ -61,7 +61,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void HitMap::open(int type) {
+void HitMap::open(ObjectType type) {
 	if (type == kXObj) {
 		HitMapObject::initMethods(xlibMethods);
 		HitMapObject *xobj = new HitMapObject(kXObj);
@@ -69,7 +69,7 @@ void HitMap::open(int type) {
 	}
 }
 
-void HitMap::close(int type) {
+void HitMap::close(ObjectType type) {
 	if (type == kXObj) {
 		HitMapObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/hitmap.h b/engines/director/lingo/xlibs/hitmap.h
index c16faac87e5..e4a020c0ab5 100644
--- a/engines/director/lingo/xlibs/hitmap.h
+++ b/engines/director/lingo/xlibs/hitmap.h
@@ -34,8 +34,8 @@ namespace HitMap {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_where(int nargs);
diff --git a/engines/director/lingo/xlibs/iscd.cpp b/engines/director/lingo/xlibs/iscd.cpp
index 762abbf8e1c..62cd883af68 100644
--- a/engines/director/lingo/xlibs/iscd.cpp
+++ b/engines/director/lingo/xlibs/iscd.cpp
@@ -45,11 +45,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void IsCD::open(int type) {
+void IsCD::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void IsCD::close(int type) {
+void IsCD::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/iscd.h b/engines/director/lingo/xlibs/iscd.h
index 310dafe2e29..f3cff380eb8 100644
--- a/engines/director/lingo/xlibs/iscd.h
+++ b/engines/director/lingo/xlibs/iscd.h
@@ -29,8 +29,8 @@ namespace IsCD {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_iscd(int nargs);
 
diff --git a/engines/director/lingo/xlibs/ispippin.cpp b/engines/director/lingo/xlibs/ispippin.cpp
index 14d8b667185..b334cefbb58 100644
--- a/engines/director/lingo/xlibs/ispippin.cpp
+++ b/engines/director/lingo/xlibs/ispippin.cpp
@@ -45,11 +45,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void IsPippin::open(int type) {
+void IsPippin::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void IsPippin::close(int type) {
+void IsPippin::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/ispippin.h b/engines/director/lingo/xlibs/ispippin.h
index 0e44df3626b..b65958e6c47 100644
--- a/engines/director/lingo/xlibs/ispippin.h
+++ b/engines/director/lingo/xlibs/ispippin.h
@@ -29,8 +29,8 @@ namespace IsPippin {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_ispippin(int nargs);
 
diff --git a/engines/director/lingo/xlibs/jitdraw3.cpp b/engines/director/lingo/xlibs/jitdraw3.cpp
index 93494fe45b9..0db9dc934ea 100644
--- a/engines/director/lingo/xlibs/jitdraw3.cpp
+++ b/engines/director/lingo/xlibs/jitdraw3.cpp
@@ -90,7 +90,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void JITDraw3XObj::open(int type) {
+void JITDraw3XObj::open(ObjectType type) {
 	if (type == kXObj) {
 		JITDraw3XObject::initMethods(xlibMethods);
 		JITDraw3XObject *xobj = new JITDraw3XObject(kXObj);
@@ -98,7 +98,7 @@ void JITDraw3XObj::open(int type) {
 	}
 }
 
-void JITDraw3XObj::close(int type) {
+void JITDraw3XObj::close(ObjectType type) {
 	if (type == kXObj) {
 		JITDraw3XObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/jitdraw3.h b/engines/director/lingo/xlibs/jitdraw3.h
index f05c79d062c..2932977f442 100644
--- a/engines/director/lingo/xlibs/jitdraw3.h
+++ b/engines/director/lingo/xlibs/jitdraw3.h
@@ -34,8 +34,8 @@ namespace JITDraw3XObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/jwxini.cpp b/engines/director/lingo/xlibs/jwxini.cpp
index b83beb2c98b..49e951a8e99 100644
--- a/engines/director/lingo/xlibs/jwxini.cpp
+++ b/engines/director/lingo/xlibs/jwxini.cpp
@@ -66,7 +66,7 @@ static MethodProto xlibMethods[] = {
     { nullptr, nullptr, 0, 0, 0 }
 };
 
-void JourneyWareXINIXObj::open(int type) {
+void JourneyWareXINIXObj::open(ObjectType type) {
    if (type == kXObj) {
 	   JourneyWareXINIXObject::initMethods(xlibMethods);
 	   JourneyWareXINIXObject *xobj = new JourneyWareXINIXObject(kXObj);
@@ -74,7 +74,7 @@ void JourneyWareXINIXObj::open(int type) {
    }
 }
 
-void JourneyWareXINIXObj::close(int type) {
+void JourneyWareXINIXObj::close(ObjectType type) {
    if (type == kXObj) {
 	   JourneyWareXINIXObject::cleanupMethods();
 	   g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/jwxini.h b/engines/director/lingo/xlibs/jwxini.h
index c6397cdd236..e10848d9c4b 100644
--- a/engines/director/lingo/xlibs/jwxini.h
+++ b/engines/director/lingo/xlibs/jwxini.h
@@ -35,8 +35,8 @@ namespace JourneyWareXINIXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_clear(int nargs);
diff --git a/engines/director/lingo/xlibs/labeldrvxobj.cpp b/engines/director/lingo/xlibs/labeldrvxobj.cpp
index 0f3031f27e7..ca7aea56a93 100644
--- a/engines/director/lingo/xlibs/labeldrvxobj.cpp
+++ b/engines/director/lingo/xlibs/labeldrvxobj.cpp
@@ -55,7 +55,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void LabelDrvXObj::open(int type) {
+void LabelDrvXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		LabelDrvXObject::initMethods(xlibMethods);
 		LabelDrvXObject *xobj = new LabelDrvXObject(kXObj);
@@ -63,7 +63,7 @@ void LabelDrvXObj::open(int type) {
 	}
 }
 
-void LabelDrvXObj::close(int type) {
+void LabelDrvXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		LabelDrvXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/labeldrvxobj.h b/engines/director/lingo/xlibs/labeldrvxobj.h
index 6c1a77d8694..81672e0a1c9 100644
--- a/engines/director/lingo/xlibs/labeldrvxobj.h
+++ b/engines/director/lingo/xlibs/labeldrvxobj.h
@@ -37,8 +37,8 @@ namespace LabelDrvXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_setRange(int nargs);
diff --git a/engines/director/lingo/xlibs/maniacbg.cpp b/engines/director/lingo/xlibs/maniacbg.cpp
index 1213666d2f5..2d1bbecb818 100644
--- a/engines/director/lingo/xlibs/maniacbg.cpp
+++ b/engines/director/lingo/xlibs/maniacbg.cpp
@@ -62,22 +62,18 @@ ManiacBgXObject::ManiacBgXObject(ObjectType ObjectType) :Object<ManiacBgXObject>
 	_objType = ObjectType;
 }
 
-void ManiacBgXObj::open(int type) {
+void ManiacBgXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ManiacBgXObject::initMethods(xlibMethods);
 		ManiacBgXObject *xobj = new ManiacBgXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void ManiacBgXObj::close(int type) {
+void ManiacBgXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ManiacBgXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/maniacbg.h b/engines/director/lingo/xlibs/maniacbg.h
index ff8632fa1bf..a21a8794636 100644
--- a/engines/director/lingo/xlibs/maniacbg.h
+++ b/engines/director/lingo/xlibs/maniacbg.h
@@ -34,8 +34,8 @@ namespace ManiacBgXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/mapnavigatorxobj.cpp b/engines/director/lingo/xlibs/mapnavigatorxobj.cpp
index 012372447f4..ba210b4de91 100644
--- a/engines/director/lingo/xlibs/mapnavigatorxobj.cpp
+++ b/engines/director/lingo/xlibs/mapnavigatorxobj.cpp
@@ -113,22 +113,18 @@ MapNavigatorXObject::MapNavigatorXObject(ObjectType ObjectType) :Object<MapNavig
 	_objType = ObjectType;
 }
 
-void MapNavigatorXObj::open(int type) {
+void MapNavigatorXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MapNavigatorXObject::initMethods(xlibMethods);
 		MapNavigatorXObject *xobj = new MapNavigatorXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MapNavigatorXObj::close(int type) {
+void MapNavigatorXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MapNavigatorXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/mapnavigatorxobj.h b/engines/director/lingo/xlibs/mapnavigatorxobj.h
index 792453d9f9e..6bfba00c306 100644
--- a/engines/director/lingo/xlibs/mapnavigatorxobj.h
+++ b/engines/director/lingo/xlibs/mapnavigatorxobj.h
@@ -34,8 +34,8 @@ namespace MapNavigatorXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/memcheckxobj.cpp b/engines/director/lingo/xlibs/memcheckxobj.cpp
index 6fe48e2c19f..0ea599c4b3b 100644
--- a/engines/director/lingo/xlibs/memcheckxobj.cpp
+++ b/engines/director/lingo/xlibs/memcheckxobj.cpp
@@ -71,22 +71,18 @@ MemCheckXObject::MemCheckXObject(ObjectType ObjectType) :Object<MemCheckXObject>
 	_objType = ObjectType;
 }
 
-void MemCheckXObj::open(int type) {
+void MemCheckXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MemCheckXObject::initMethods(xlibMethods);
 		MemCheckXObject *xobj = new MemCheckXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MemCheckXObj::close(int type) {
+void MemCheckXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MemCheckXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/memcheckxobj.h b/engines/director/lingo/xlibs/memcheckxobj.h
index 9a183117808..6e8d6773dbd 100644
--- a/engines/director/lingo/xlibs/memcheckxobj.h
+++ b/engines/director/lingo/xlibs/memcheckxobj.h
@@ -34,8 +34,8 @@ namespace MemCheckXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/memoryxobj.cpp b/engines/director/lingo/xlibs/memoryxobj.cpp
index 0057c625968..3fbcca85d2c 100644
--- a/engines/director/lingo/xlibs/memoryxobj.cpp
+++ b/engines/director/lingo/xlibs/memoryxobj.cpp
@@ -80,7 +80,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void MemoryXObj::open(int type) {
+void MemoryXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MemoryXObject::initMethods(xlibMethods);
 		MemoryXObject *xobj = new MemoryXObject(kXObj);
@@ -88,7 +88,7 @@ void MemoryXObj::open(int type) {
 	}
 }
 
-void MemoryXObj::close(int type) {
+void MemoryXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MemoryXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/memoryxobj.h b/engines/director/lingo/xlibs/memoryxobj.h
index ba44aa3f958..6634379d988 100644
--- a/engines/director/lingo/xlibs/memoryxobj.h
+++ b/engines/director/lingo/xlibs/memoryxobj.h
@@ -35,8 +35,8 @@ namespace MemoryXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_clear(int nargs);
diff --git a/engines/director/lingo/xlibs/misc.cpp b/engines/director/lingo/xlibs/misc.cpp
index 050f5b5aa0b..50a6252f161 100644
--- a/engines/director/lingo/xlibs/misc.cpp
+++ b/engines/director/lingo/xlibs/misc.cpp
@@ -49,7 +49,7 @@ static MethodProto xlibMethods[] = {
     { nullptr, nullptr, 0, 0, 0 }
 };
 
-void Misc::open(int type) {
+void Misc::open(ObjectType type) {
     if (type == kXObj) {
         MiscObject::initMethods(xlibMethods);
         MiscObject *xobj = new MiscObject(kXObj);
@@ -57,7 +57,7 @@ void Misc::open(int type) {
     }
 }
 
-void Misc::close(int type) {
+void Misc::close(ObjectType type) {
     if (type == kXObj) {
         MiscObject::cleanupMethods();
         g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/misc.h b/engines/director/lingo/xlibs/misc.h
index 2d4e8166c38..fb815d6dc05 100644
--- a/engines/director/lingo/xlibs/misc.h
+++ b/engines/director/lingo/xlibs/misc.h
@@ -34,8 +34,8 @@ namespace Misc {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_getProfileString(int nargs);
 void m_isFilePresent(int nargs);
diff --git a/engines/director/lingo/xlibs/miscx.cpp b/engines/director/lingo/xlibs/miscx.cpp
index f601fc8a057..86d7407cdf2 100644
--- a/engines/director/lingo/xlibs/miscx.cpp
+++ b/engines/director/lingo/xlibs/miscx.cpp
@@ -103,22 +103,18 @@ MiscXObject::MiscXObject(ObjectType ObjectType) :Object<MiscXObject>("MiscX") {
 	_objType = ObjectType;
 }
 
-void MiscX::open(int type) {
+void MiscX::open(ObjectType type) {
 	if (type == kXObj) {
 		MiscXObject::initMethods(xlibMethods);
 		MiscXObject *xobj = new MiscXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MiscX::close(int type) {
+void MiscX::close(ObjectType type) {
 	if (type == kXObj) {
 		MiscXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/miscx.h b/engines/director/lingo/xlibs/miscx.h
index d25314990e6..6359b5f7820 100644
--- a/engines/director/lingo/xlibs/miscx.h
+++ b/engines/director/lingo/xlibs/miscx.h
@@ -34,8 +34,8 @@ namespace MiscX {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/mmaskxobj.cpp b/engines/director/lingo/xlibs/mmaskxobj.cpp
index 8b76b3188f5..84e65dafdcd 100644
--- a/engines/director/lingo/xlibs/mmaskxobj.cpp
+++ b/engines/director/lingo/xlibs/mmaskxobj.cpp
@@ -59,22 +59,18 @@ MMaskXObject::MMaskXObject(ObjectType ObjectType) :Object<MMaskXObject>("MMaskXO
 	_objType = ObjectType;
 }
 
-void MMaskXObj::open(int type) {
+void MMaskXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MMaskXObject::initMethods(xlibMethods);
 		MMaskXObject *xobj = new MMaskXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MMaskXObj::close(int type) {
+void MMaskXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MMaskXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/mmaskxobj.h b/engines/director/lingo/xlibs/mmaskxobj.h
index 92dbb2ddf89..0caf552b33b 100644
--- a/engines/director/lingo/xlibs/mmaskxobj.h
+++ b/engines/director/lingo/xlibs/mmaskxobj.h
@@ -34,8 +34,8 @@ namespace MMaskXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/moovxobj.cpp b/engines/director/lingo/xlibs/moovxobj.cpp
index 4a0b7f995d6..f7252f49982 100644
--- a/engines/director/lingo/xlibs/moovxobj.cpp
+++ b/engines/director/lingo/xlibs/moovxobj.cpp
@@ -77,7 +77,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void MoovXObj::open(int type) {
+void MoovXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MoovXObject::initMethods(xlibMethods);
 		MoovXObject *xobj = new MoovXObject(kXObj);
@@ -85,7 +85,7 @@ void MoovXObj::open(int type) {
 	}
 }
 
-void MoovXObj::close(int type) {
+void MoovXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MoovXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/moovxobj.h b/engines/director/lingo/xlibs/moovxobj.h
index d89a3d98277..9ef1c0f4b58 100644
--- a/engines/director/lingo/xlibs/moovxobj.h
+++ b/engines/director/lingo/xlibs/moovxobj.h
@@ -44,8 +44,8 @@ namespace MoovXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/movemousexobj.cpp b/engines/director/lingo/xlibs/movemousexobj.cpp
index f4447feb77d..c4e1b8149ab 100644
--- a/engines/director/lingo/xlibs/movemousexobj.cpp
+++ b/engines/director/lingo/xlibs/movemousexobj.cpp
@@ -58,22 +58,18 @@ MoveMouseXObject::MoveMouseXObject(ObjectType ObjectType) :Object<MoveMouseXObje
 	_objType = ObjectType;
 }
 
-void MoveMouseXObj::open(int type) {
+void MoveMouseXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MoveMouseXObject::initMethods(xlibMethods);
 		MoveMouseXObject *xobj = new MoveMouseXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MoveMouseXObj::close(int type) {
+void MoveMouseXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MoveMouseXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/movemousexobj.h b/engines/director/lingo/xlibs/movemousexobj.h
index 8efabd23bc6..24a51003cfe 100644
--- a/engines/director/lingo/xlibs/movemousexobj.h
+++ b/engines/director/lingo/xlibs/movemousexobj.h
@@ -34,8 +34,8 @@ namespace MoveMouseXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/movieidxxobj.cpp b/engines/director/lingo/xlibs/movieidxxobj.cpp
index 34f35b82aad..a6eff7a10c8 100644
--- a/engines/director/lingo/xlibs/movieidxxobj.cpp
+++ b/engines/director/lingo/xlibs/movieidxxobj.cpp
@@ -68,22 +68,18 @@ MovieIdxXObject::MovieIdxXObject(ObjectType ObjectType) :Object<MovieIdxXObject>
 	_objType = ObjectType;
 }
 
-void MovieIdxXObj::open(int type) {
+void MovieIdxXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MovieIdxXObject::initMethods(xlibMethods);
 		MovieIdxXObject *xobj = new MovieIdxXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void MovieIdxXObj::close(int type) {
+void MovieIdxXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MovieIdxXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/movieidxxobj.h b/engines/director/lingo/xlibs/movieidxxobj.h
index c719393633b..d3ffcb7917d 100644
--- a/engines/director/lingo/xlibs/movieidxxobj.h
+++ b/engines/director/lingo/xlibs/movieidxxobj.h
@@ -34,8 +34,8 @@ namespace MovieIdxXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/movutils.cpp b/engines/director/lingo/xlibs/movutils.cpp
index f72e24d8a44..649d139845b 100644
--- a/engines/director/lingo/xlibs/movutils.cpp
+++ b/engines/director/lingo/xlibs/movutils.cpp
@@ -120,7 +120,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void MovUtilsXObj::open(int type) {
+void MovUtilsXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		MovieUtilsXObject::initMethods(xlibMethods);
 		MovieUtilsXObject *xobj = new MovieUtilsXObject(kXObj);
@@ -130,7 +130,7 @@ void MovUtilsXObj::open(int type) {
 	}
 }
 
-void MovUtilsXObj::close(int type) {
+void MovUtilsXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		MovieUtilsXObject::cleanupMethods();
 		for (uint i = 0; xlibNames[i]; i++) {
diff --git a/engines/director/lingo/xlibs/movutils.h b/engines/director/lingo/xlibs/movutils.h
index 6675c2b17b7..7d57e4d3924 100644
--- a/engines/director/lingo/xlibs/movutils.h
+++ b/engines/director/lingo/xlibs/movutils.h
@@ -35,8 +35,8 @@ namespace MovUtilsXObj {
 extern const char *xlibNames[];
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_clear(int nargs);
diff --git a/engines/director/lingo/xlibs/orthoplayxobj.cpp b/engines/director/lingo/xlibs/orthoplayxobj.cpp
index ef3005653df..5094eb37223 100644
--- a/engines/director/lingo/xlibs/orthoplayxobj.cpp
+++ b/engines/director/lingo/xlibs/orthoplayxobj.cpp
@@ -125,7 +125,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void OrthoPlayXObj::open(int type) {
+void OrthoPlayXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		OrthoPlayXObject::initMethods(xlibMethods);
 		OrthoPlayXObject *xobj = new OrthoPlayXObject(kXObj);
@@ -133,7 +133,7 @@ void OrthoPlayXObj::open(int type) {
 	}
 }
 
-void OrthoPlayXObj::close(int type) {
+void OrthoPlayXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		OrthoPlayXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/orthoplayxobj.h b/engines/director/lingo/xlibs/orthoplayxobj.h
index 62cf1879f79..ba5dd7d56fc 100644
--- a/engines/director/lingo/xlibs/orthoplayxobj.h
+++ b/engines/director/lingo/xlibs/orthoplayxobj.h
@@ -34,8 +34,8 @@ namespace OrthoPlayXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_setSerialPort(int nargs);
diff --git a/engines/director/lingo/xlibs/palxobj.cpp b/engines/director/lingo/xlibs/palxobj.cpp
index 29a02bd8d80..d10b4c28bd3 100644
--- a/engines/director/lingo/xlibs/palxobj.cpp
+++ b/engines/director/lingo/xlibs/palxobj.cpp
@@ -70,7 +70,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void PalXObj::open(int type) {
+void PalXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		PalXObject::initMethods(xlibMethods);
 		PalXObject *xobj = new PalXObject(kXObj);
@@ -78,7 +78,7 @@ void PalXObj::open(int type) {
 	}
 }
 
-void PalXObj::close(int type) {
+void PalXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		PalXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/palxobj.h b/engines/director/lingo/xlibs/palxobj.h
index d98a8965502..2222bd79474 100644
--- a/engines/director/lingo/xlibs/palxobj.h
+++ b/engines/director/lingo/xlibs/palxobj.h
@@ -37,8 +37,8 @@ namespace PalXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_patchIt(int nargs);
diff --git a/engines/director/lingo/xlibs/panel.cpp b/engines/director/lingo/xlibs/panel.cpp
index 80c7dc6052c..3c55f1ad975 100644
--- a/engines/director/lingo/xlibs/panel.cpp
+++ b/engines/director/lingo/xlibs/panel.cpp
@@ -94,22 +94,18 @@ PanelXObject::PanelXObject(ObjectType ObjectType) :Object<PanelXObject>("PanelXO
 	_objType = ObjectType;
 }
 
-void PanelXObj::open(int type) {
+void PanelXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		PanelXObject::initMethods(xlibMethods);
 		PanelXObject *xobj = new PanelXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void PanelXObj::close(int type) {
+void PanelXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		PanelXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/panel.h b/engines/director/lingo/xlibs/panel.h
index fd1b6f6eb2d..345e58541cc 100644
--- a/engines/director/lingo/xlibs/panel.h
+++ b/engines/director/lingo/xlibs/panel.h
@@ -34,8 +34,8 @@ namespace PanelXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/popupmenuxobj.cpp b/engines/director/lingo/xlibs/popupmenuxobj.cpp
index afd3a911b3d..99f361c5346 100644
--- a/engines/director/lingo/xlibs/popupmenuxobj.cpp
+++ b/engines/director/lingo/xlibs/popupmenuxobj.cpp
@@ -136,7 +136,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void PopUpMenuXObj::open(int type) {
+void PopUpMenuXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		PopUpMenuXObject::initMethods(xlibMethods);
 		PopUpMenuXObject *xobj = new PopUpMenuXObject(kXObj);
@@ -144,7 +144,7 @@ void PopUpMenuXObj::open(int type) {
 	}
 }
 
-void PopUpMenuXObj::close(int type) {
+void PopUpMenuXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		PopUpMenuXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/popupmenuxobj.h b/engines/director/lingo/xlibs/popupmenuxobj.h
index 418ad31ee18..f94e6c7a95f 100644
--- a/engines/director/lingo/xlibs/popupmenuxobj.h
+++ b/engines/director/lingo/xlibs/popupmenuxobj.h
@@ -35,8 +35,8 @@ namespace PopUpMenuXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_appendMenu(int nargs);
diff --git a/engines/director/lingo/xlibs/porta.cpp b/engines/director/lingo/xlibs/porta.cpp
index b0b59b8df09..399e5294643 100644
--- a/engines/director/lingo/xlibs/porta.cpp
+++ b/engines/director/lingo/xlibs/porta.cpp
@@ -48,11 +48,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void Porta::open(int type) {
+void Porta::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void Porta::close(int type) {
+void Porta::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/porta.h b/engines/director/lingo/xlibs/porta.h
index 97b42c1bf19..27fbad9f352 100644
--- a/engines/director/lingo/xlibs/porta.h
+++ b/engines/director/lingo/xlibs/porta.h
@@ -29,8 +29,8 @@ namespace Porta {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void b_porta(int nargs);
 
diff --git a/engines/director/lingo/xlibs/prefpath.cpp b/engines/director/lingo/xlibs/prefpath.cpp
index 5368adf5568..f136f42027b 100644
--- a/engines/director/lingo/xlibs/prefpath.cpp
+++ b/engines/director/lingo/xlibs/prefpath.cpp
@@ -51,7 +51,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void PrefPath::open(int type) {
+void PrefPath::open(ObjectType type) {
 	if (type == kXObj) {
 		PrefPathObject::initMethods(xlibMethods);
 		PrefPathObject *xobj = new PrefPathObject(kXObj);
@@ -59,7 +59,7 @@ void PrefPath::open(int type) {
 	}
 }
 
-void PrefPath::close(int type) {
+void PrefPath::close(ObjectType type) {
 	if (type == kXObj) {
 		PrefPathObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/prefpath.h b/engines/director/lingo/xlibs/prefpath.h
index 9b18893afe1..577378cbaf4 100644
--- a/engines/director/lingo/xlibs/prefpath.h
+++ b/engines/director/lingo/xlibs/prefpath.h
@@ -34,8 +34,8 @@ namespace PrefPath {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_prefpath(int nargs);
diff --git a/engines/director/lingo/xlibs/printomatic.cpp b/engines/director/lingo/xlibs/printomatic.cpp
index 7060e6d2776..0bb8dec495b 100644
--- a/engines/director/lingo/xlibs/printomatic.cpp
+++ b/engines/director/lingo/xlibs/printomatic.cpp
@@ -141,7 +141,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void PrintOMaticXObj::open(int type) {
+void PrintOMaticXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		PrintOMaticXObject::initMethods(xlibMethods);
 		PrintOMaticXObject *xobj = new PrintOMaticXObject(kXObj);
@@ -149,7 +149,7 @@ void PrintOMaticXObj::open(int type) {
 	}
 }
 
-void PrintOMaticXObj::close(int type) {
+void PrintOMaticXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		PrintOMaticXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/printomatic.h b/engines/director/lingo/xlibs/printomatic.h
index 51428118e48..a68da6db177 100644
--- a/engines/director/lingo/xlibs/printomatic.h
+++ b/engines/director/lingo/xlibs/printomatic.h
@@ -34,8 +34,8 @@ namespace PrintOMaticXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/processxobj.cpp b/engines/director/lingo/xlibs/processxobj.cpp
index 5d01267f0a4..e9d2f31ac29 100644
--- a/engines/director/lingo/xlibs/processxobj.cpp
+++ b/engines/director/lingo/xlibs/processxobj.cpp
@@ -64,22 +64,18 @@ ProcessXObject::ProcessXObject(ObjectType ObjectType) :Object<ProcessXObject>("P
 	_objType = ObjectType;
 }
 
-void ProcessXObj::open(int type) {
+void ProcessXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ProcessXObject::initMethods(xlibMethods);
 		ProcessXObject *xobj = new ProcessXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void ProcessXObj::close(int type) {
+void ProcessXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ProcessXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/processxobj.h b/engines/director/lingo/xlibs/processxobj.h
index cf47aefc033..870a57637f6 100644
--- a/engines/director/lingo/xlibs/processxobj.h
+++ b/engines/director/lingo/xlibs/processxobj.h
@@ -34,8 +34,8 @@ namespace ProcessXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/qtcatmovieplayerxobj.cpp b/engines/director/lingo/xlibs/qtcatmovieplayerxobj.cpp
index de411f49e98..9f36e365a71 100644
--- a/engines/director/lingo/xlibs/qtcatmovieplayerxobj.cpp
+++ b/engines/director/lingo/xlibs/qtcatmovieplayerxobj.cpp
@@ -70,22 +70,18 @@ QTCatMoviePlayerXObject::QTCatMoviePlayerXObject(ObjectType ObjectType) :Object<
 	_objType = ObjectType;
 }
 
-void QTCatMoviePlayerXObj::open(int type) {
+void QTCatMoviePlayerXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		QTCatMoviePlayerXObject::initMethods(xlibMethods);
 		QTCatMoviePlayerXObject *xobj = new QTCatMoviePlayerXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void QTCatMoviePlayerXObj::close(int type) {
+void QTCatMoviePlayerXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		QTCatMoviePlayerXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/qtcatmovieplayerxobj.h b/engines/director/lingo/xlibs/qtcatmovieplayerxobj.h
index 5d05a225e0a..93b78c3e113 100644
--- a/engines/director/lingo/xlibs/qtcatmovieplayerxobj.h
+++ b/engines/director/lingo/xlibs/qtcatmovieplayerxobj.h
@@ -34,8 +34,8 @@ namespace QTCatMoviePlayerXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/qtmovie.cpp b/engines/director/lingo/xlibs/qtmovie.cpp
index da0b64c1cc1..848771f5567 100644
--- a/engines/director/lingo/xlibs/qtmovie.cpp
+++ b/engines/director/lingo/xlibs/qtmovie.cpp
@@ -50,11 +50,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void QTMovie::open(int type) {
+void QTMovie::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void QTMovie::close(int type) {
+void QTMovie::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/qtmovie.h b/engines/director/lingo/xlibs/qtmovie.h
index 66ee58cc85b..8e9bba5198a 100644
--- a/engines/director/lingo/xlibs/qtmovie.h
+++ b/engines/director/lingo/xlibs/qtmovie.h
@@ -29,8 +29,8 @@ namespace QTMovie {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_qtmovie(int nargs);
 
diff --git a/engines/director/lingo/xlibs/qtvr.cpp b/engines/director/lingo/xlibs/qtvr.cpp
index b28c00b6a0a..4b57e9256ac 100644
--- a/engines/director/lingo/xlibs/qtvr.cpp
+++ b/engines/director/lingo/xlibs/qtvr.cpp
@@ -97,22 +97,18 @@ QTVRXObject::QTVRXObject(ObjectType ObjectType) :Object<QTVRXObject>("QTVR") {
 	_objType = ObjectType;
 }
 
-void QTVR::open(int type) {
+void QTVR::open(ObjectType type) {
 	if (type == kXObj) {
 		QTVRXObject::initMethods(xlibMethods);
 		QTVRXObject *xobj = new QTVRXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void QTVR::close(int type) {
+void QTVR::close(ObjectType type) {
 	if (type == kXObj) {
 		QTVRXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/qtvr.h b/engines/director/lingo/xlibs/qtvr.h
index bb7bfdc0075..d77e2328913 100644
--- a/engines/director/lingo/xlibs/qtvr.h
+++ b/engines/director/lingo/xlibs/qtvr.h
@@ -29,8 +29,8 @@ namespace QTVR {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/quicktime.cpp b/engines/director/lingo/xlibs/quicktime.cpp
index 67295524ec8..7dba5a0423d 100644
--- a/engines/director/lingo/xlibs/quicktime.cpp
+++ b/engines/director/lingo/xlibs/quicktime.cpp
@@ -50,7 +50,7 @@ static MethodProto xlibMethods[] = {
     { nullptr, nullptr, 0, 0, 0 }
 };
 
-void Quicktime::open(int type) {
+void Quicktime::open(ObjectType type) {
     if (type == kXObj) {
         QuicktimeObject::initMethods(xlibMethods);
         QuicktimeObject *xobj = new QuicktimeObject(kXObj);
@@ -58,7 +58,7 @@ void Quicktime::open(int type) {
     }
 }
 
-void Quicktime::close(int type) {
+void Quicktime::close(ObjectType type) {
     if (type == kXObj) {
         QuicktimeObject::cleanupMethods();
         g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/quicktime.h b/engines/director/lingo/xlibs/quicktime.h
index 4315c0aa5c7..c7dc8a9196c 100644
--- a/engines/director/lingo/xlibs/quicktime.h
+++ b/engines/director/lingo/xlibs/quicktime.h
@@ -34,8 +34,8 @@ namespace Quicktime {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_playStage(int nargs);
 
diff --git a/engines/director/lingo/xlibs/registercomponent.cpp b/engines/director/lingo/xlibs/registercomponent.cpp
index 4aab22a0da1..97eec0fe230 100644
--- a/engines/director/lingo/xlibs/registercomponent.cpp
+++ b/engines/director/lingo/xlibs/registercomponent.cpp
@@ -43,11 +43,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void RegisterComponent::open(int type) {
+void RegisterComponent::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void RegisterComponent::close(int type) {
+void RegisterComponent::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/registercomponent.h b/engines/director/lingo/xlibs/registercomponent.h
index 7f350288763..d23720714f2 100644
--- a/engines/director/lingo/xlibs/registercomponent.h
+++ b/engines/director/lingo/xlibs/registercomponent.h
@@ -41,8 +41,8 @@ namespace RegisterComponent {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void b_RegisterComponent(int nargs);
 
diff --git a/engines/director/lingo/xlibs/serialportxobj.cpp b/engines/director/lingo/xlibs/serialportxobj.cpp
index 7e75f2ae0c3..bfbeec049a5 100644
--- a/engines/director/lingo/xlibs/serialportxobj.cpp
+++ b/engines/director/lingo/xlibs/serialportxobj.cpp
@@ -64,7 +64,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void SerialPortXObj::open(int type) {
+void SerialPortXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		SerialPortXObject::initMethods(xlibMethods);
 		SerialPortXObject *xobj = new SerialPortXObject(kXObj);
@@ -72,7 +72,7 @@ void SerialPortXObj::open(int type) {
 	}
 }
 
-void SerialPortXObj::close(int type) {
+void SerialPortXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		SerialPortXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/serialportxobj.h b/engines/director/lingo/xlibs/serialportxobj.h
index ba021ba8c93..134143cca1e 100644
--- a/engines/director/lingo/xlibs/serialportxobj.h
+++ b/engines/director/lingo/xlibs/serialportxobj.h
@@ -34,8 +34,8 @@ namespace SerialPortXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_getPortNum(int nargs);
diff --git a/engines/director/lingo/xlibs/soundjam.cpp b/engines/director/lingo/xlibs/soundjam.cpp
index e7f20996ea5..f2fc98e2226 100644
--- a/engines/director/lingo/xlibs/soundjam.cpp
+++ b/engines/director/lingo/xlibs/soundjam.cpp
@@ -76,7 +76,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void SoundJam::open(int type) {
+void SoundJam::open(ObjectType type) {
 	if (type == kXObj) {
 		SoundJamObject::initMethods(xlibMethods);
 		SoundJamObject *xobj = new SoundJamObject(kXObj);
@@ -84,7 +84,7 @@ void SoundJam::open(int type) {
 	}
 }
 
-void SoundJam::close(int type) {
+void SoundJam::close(ObjectType type) {
 	if (type == kXObj) {
 		SoundJamObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/soundjam.h b/engines/director/lingo/xlibs/soundjam.h
index 326a45eaf24..f2f0050e9bd 100644
--- a/engines/director/lingo/xlibs/soundjam.h
+++ b/engines/director/lingo/xlibs/soundjam.h
@@ -37,8 +37,8 @@ namespace SoundJam {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_defineFileSound(int nargs);
diff --git a/engines/director/lingo/xlibs/spacemgr.cpp b/engines/director/lingo/xlibs/spacemgr.cpp
index 9133b1caf6d..b84257f6719 100644
--- a/engines/director/lingo/xlibs/spacemgr.cpp
+++ b/engines/director/lingo/xlibs/spacemgr.cpp
@@ -137,22 +137,18 @@ SpaceMgrXObject::SpaceMgrXObject(ObjectType ObjectType) :Object<SpaceMgrXObject>
 	_objType = ObjectType;
 }
 
-void SpaceMgr::open(int type) {
+void SpaceMgr::open(ObjectType type) {
 	if (type == kXObj) {
 		SpaceMgrXObject::initMethods(xlibMethods);
 		SpaceMgrXObject *xobj = new SpaceMgrXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void SpaceMgr::close(int type) {
+void SpaceMgr::close(ObjectType type) {
 	if (type == kXObj) {
 		SpaceMgrXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/spacemgr.h b/engines/director/lingo/xlibs/spacemgr.h
index 5ec850fc0e1..a16c3fbd8c5 100644
--- a/engines/director/lingo/xlibs/spacemgr.h
+++ b/engines/director/lingo/xlibs/spacemgr.h
@@ -50,8 +50,8 @@ struct SpaceCollection {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/stagetc.cpp b/engines/director/lingo/xlibs/stagetc.cpp
index cbb4f51b843..a19afae5b3a 100644
--- a/engines/director/lingo/xlibs/stagetc.cpp
+++ b/engines/director/lingo/xlibs/stagetc.cpp
@@ -53,7 +53,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void StageTCXObj::open(int type) {
+void StageTCXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		StageTCXObject::initMethods(xlibMethods);
 		StageTCXObject *xobj = new StageTCXObject(kXObj);
@@ -61,7 +61,7 @@ void StageTCXObj::open(int type) {
 	}
 }
 
-void StageTCXObj::close(int type) {
+void StageTCXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		StageTCXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/stagetc.h b/engines/director/lingo/xlibs/stagetc.h
index d259a9fe23c..9913e8fbeaf 100644
--- a/engines/director/lingo/xlibs/stagetc.h
+++ b/engines/director/lingo/xlibs/stagetc.h
@@ -34,8 +34,8 @@ namespace StageTCXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/unittest.cpp b/engines/director/lingo/xlibs/unittest.cpp
index 17fc5683fa0..fc19610d0e0 100644
--- a/engines/director/lingo/xlibs/unittest.cpp
+++ b/engines/director/lingo/xlibs/unittest.cpp
@@ -53,11 +53,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void UnitTest::open(int type) {
+void UnitTest::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void UnitTest::close(int type) {
+void UnitTest::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/unittest.h b/engines/director/lingo/xlibs/unittest.h
index faa445d5523..5d4b9315aad 100644
--- a/engines/director/lingo/xlibs/unittest.h
+++ b/engines/director/lingo/xlibs/unittest.h
@@ -29,8 +29,8 @@ namespace UnitTest {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_UTScreenshot(int nargs);
 
diff --git a/engines/director/lingo/xlibs/valkyrie.cpp b/engines/director/lingo/xlibs/valkyrie.cpp
index 9a563eb4acf..02aaa6dc43f 100644
--- a/engines/director/lingo/xlibs/valkyrie.cpp
+++ b/engines/director/lingo/xlibs/valkyrie.cpp
@@ -65,7 +65,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void ValkyrieXObj::open(int type) {
+void ValkyrieXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		ValkyrieXObject::initMethods(xlibMethods);
 		ValkyrieXObject *xobj = new ValkyrieXObject(kXObj);
@@ -73,7 +73,7 @@ void ValkyrieXObj::open(int type) {
 	}
 }
 
-void ValkyrieXObj::close(int type) {
+void ValkyrieXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		ValkyrieXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/valkyrie.h b/engines/director/lingo/xlibs/valkyrie.h
index 252b124856d..699da38a72a 100644
--- a/engines/director/lingo/xlibs/valkyrie.h
+++ b/engines/director/lingo/xlibs/valkyrie.h
@@ -34,8 +34,8 @@ namespace ValkyrieXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/videodiscxobj.cpp b/engines/director/lingo/xlibs/videodiscxobj.cpp
index c7ebe9d618d..6081ddfb5c7 100644
--- a/engines/director/lingo/xlibs/videodiscxobj.cpp
+++ b/engines/director/lingo/xlibs/videodiscxobj.cpp
@@ -151,7 +151,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void VideodiscXObj::open(int type) {
+void VideodiscXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		VideodiscXObject::initMethods(xlibMethods);
 		VideodiscXObject *xobj = new VideodiscXObject(kXObj);
@@ -159,7 +159,7 @@ void VideodiscXObj::open(int type) {
 	}
 }
 
-void VideodiscXObj::close(int type) {
+void VideodiscXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		VideodiscXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/videodiscxobj.h b/engines/director/lingo/xlibs/videodiscxobj.h
index ac4eeabf07f..66454b6a7dc 100644
--- a/engines/director/lingo/xlibs/videodiscxobj.h
+++ b/engines/director/lingo/xlibs/videodiscxobj.h
@@ -34,8 +34,8 @@ namespace VideodiscXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_name(int nargs);
diff --git a/engines/director/lingo/xlibs/vmisonxfcn.cpp b/engines/director/lingo/xlibs/vmisonxfcn.cpp
index cb93dcb442c..c29c65b0f07 100644
--- a/engines/director/lingo/xlibs/vmisonxfcn.cpp
+++ b/engines/director/lingo/xlibs/vmisonxfcn.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void VMisOnXFCN::open(int type) {
+void VMisOnXFCN::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void VMisOnXFCN::close(int type) {
+void VMisOnXFCN::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/vmisonxfcn.h b/engines/director/lingo/xlibs/vmisonxfcn.h
index f4c23ea2848..f44a9a6f01d 100644
--- a/engines/director/lingo/xlibs/vmisonxfcn.h
+++ b/engines/director/lingo/xlibs/vmisonxfcn.h
@@ -29,8 +29,8 @@ namespace VMisOnXFCN {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_VMisOn(int nargs);
 
diff --git a/engines/director/lingo/xlibs/volumelist.cpp b/engines/director/lingo/xlibs/volumelist.cpp
index a91b9cf255b..12b44e9f9bb 100644
--- a/engines/director/lingo/xlibs/volumelist.cpp
+++ b/engines/director/lingo/xlibs/volumelist.cpp
@@ -50,11 +50,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void VolumeList::open(int type) {
+void VolumeList::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void VolumeList::close(int type) {
+void VolumeList::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/volumelist.h b/engines/director/lingo/xlibs/volumelist.h
index 1ea9277fa98..16ceb95ae5d 100644
--- a/engines/director/lingo/xlibs/volumelist.h
+++ b/engines/director/lingo/xlibs/volumelist.h
@@ -29,8 +29,8 @@ namespace VolumeList {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_volumelist(int nargs);
 
diff --git a/engines/director/lingo/xlibs/widgetxobj.cpp b/engines/director/lingo/xlibs/widgetxobj.cpp
index aa73ac6ee4d..8df0b8b806c 100644
--- a/engines/director/lingo/xlibs/widgetxobj.cpp
+++ b/engines/director/lingo/xlibs/widgetxobj.cpp
@@ -59,7 +59,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void WidgetXObj::open(int type) {
+void WidgetXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		WidgetXObject::initMethods(xlibMethods);
 		WidgetXObject *xobj = new WidgetXObject(kXObj);
@@ -67,7 +67,7 @@ void WidgetXObj::open(int type) {
 	}
 }
 
-void WidgetXObj::close(int type) {
+void WidgetXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		WidgetXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/widgetxobj.h b/engines/director/lingo/xlibs/widgetxobj.h
index d2d1a192e67..c8a6afb72ae 100644
--- a/engines/director/lingo/xlibs/widgetxobj.h
+++ b/engines/director/lingo/xlibs/widgetxobj.h
@@ -34,8 +34,8 @@ namespace WidgetXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/window.cpp b/engines/director/lingo/xlibs/window.cpp
index 090d527fe3d..34711613550 100644
--- a/engines/director/lingo/xlibs/window.cpp
+++ b/engines/director/lingo/xlibs/window.cpp
@@ -107,22 +107,18 @@ WindowXObject::WindowXObject(ObjectType ObjectType) :Object<WindowXObject>("Wind
 	_objType = ObjectType;
 }
 
-void WindowXObj::open(int type) {
+void WindowXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		WindowXObject::initMethods(xlibMethods);
 		WindowXObject *xobj = new WindowXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void WindowXObj::close(int type) {
+void WindowXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		WindowXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/window.h b/engines/director/lingo/xlibs/window.h
index f39acd05ab8..4e5abafa253 100644
--- a/engines/director/lingo/xlibs/window.h
+++ b/engines/director/lingo/xlibs/window.h
@@ -34,8 +34,8 @@ namespace WindowXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/wininfo.cpp b/engines/director/lingo/xlibs/wininfo.cpp
index ae1b4c3c793..5c13ebc5d3e 100644
--- a/engines/director/lingo/xlibs/wininfo.cpp
+++ b/engines/director/lingo/xlibs/wininfo.cpp
@@ -63,22 +63,18 @@ WinInfoXObject::WinInfoXObject(ObjectType ObjectType) : Object<WinInfoXObject>("
 	_objType = ObjectType;
 }
 
-void WinInfoXObj::open(int type) {
+void WinInfoXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		WinInfoXObject::initMethods(xlibMethods);
 		WinInfoXObject *xobj = new WinInfoXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void WinInfoXObj::close(int type) {
+void WinInfoXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		WinInfoXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/wininfo.h b/engines/director/lingo/xlibs/wininfo.h
index 8a8021aa0ba..9fdc77046a3 100644
--- a/engines/director/lingo/xlibs/wininfo.h
+++ b/engines/director/lingo/xlibs/wininfo.h
@@ -34,8 +34,8 @@ namespace WinInfoXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/winxobj.cpp b/engines/director/lingo/xlibs/winxobj.cpp
index 36eb51fe870..fb522c66c16 100644
--- a/engines/director/lingo/xlibs/winxobj.cpp
+++ b/engines/director/lingo/xlibs/winxobj.cpp
@@ -247,7 +247,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void RearWindowXObj::open(int type) {
+void RearWindowXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		RearWindowXObject::initMethods(xlibMethods);
 		RearWindowXObject *xobj = new RearWindowXObject(kXObj);
@@ -255,7 +255,7 @@ void RearWindowXObj::open(int type) {
 	}
 }
 
-void RearWindowXObj::close(int type) {
+void RearWindowXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		RearWindowXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/winxobj.h b/engines/director/lingo/xlibs/winxobj.h
index dd5902a7ef9..59200763915 100644
--- a/engines/director/lingo/xlibs/winxobj.h
+++ b/engines/director/lingo/xlibs/winxobj.h
@@ -35,8 +35,8 @@ namespace RearWindowXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_getAppName(int nargs);
diff --git a/engines/director/lingo/xlibs/xcmdglue.cpp b/engines/director/lingo/xlibs/xcmdglue.cpp
index 343af208084..17091c80ce6 100644
--- a/engines/director/lingo/xlibs/xcmdglue.cpp
+++ b/engines/director/lingo/xlibs/xcmdglue.cpp
@@ -71,22 +71,18 @@ XCMDGlueXObject::XCMDGlueXObject(ObjectType ObjectType) :Object<XCMDGlueXObject>
 	_objType = ObjectType;
 }
 
-void XCMDGlueXObj::open(int type) {
+void XCMDGlueXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		XCMDGlueXObject::initMethods(xlibMethods);
 		XCMDGlueXObject *xobj = new XCMDGlueXObject(kXObj);
 		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
-void XCMDGlueXObj::close(int type) {
+void XCMDGlueXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		XCMDGlueXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
 	}
 }
 
diff --git a/engines/director/lingo/xlibs/xcmdglue.h b/engines/director/lingo/xlibs/xcmdglue.h
index 2987b5d4d37..a6d28ee43ab 100644
--- a/engines/director/lingo/xlibs/xcmdglue.h
+++ b/engines/director/lingo/xlibs/xcmdglue.h
@@ -34,8 +34,8 @@ namespace XCMDGlueXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/xio.cpp b/engines/director/lingo/xlibs/xio.cpp
index 7db98f03dd4..c2d43792220 100644
--- a/engines/director/lingo/xlibs/xio.cpp
+++ b/engines/director/lingo/xlibs/xio.cpp
@@ -60,7 +60,7 @@ static MethodProto xlibMethods[] = {
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
-void XioXObj::open(int type) {
+void XioXObj::open(ObjectType type) {
 	if (type == kXObj) {
 		XioXObject::initMethods(xlibMethods);
 		XioXObject *xobj = new XioXObject(kXObj);
@@ -68,7 +68,7 @@ void XioXObj::open(int type) {
 	}
 }
 
-void XioXObj::close(int type) {
+void XioXObj::close(ObjectType type) {
 	if (type == kXObj) {
 		XioXObject::cleanupMethods();
 		g_lingo->_globalvars[xlibName] = Datum();
diff --git a/engines/director/lingo/xlibs/xio.h b/engines/director/lingo/xlibs/xio.h
index 59d200d0055..15d5b176468 100644
--- a/engines/director/lingo/xlibs/xio.h
+++ b/engines/director/lingo/xlibs/xio.h
@@ -34,8 +34,8 @@ namespace XioXObj {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_new(int nargs);
 void m_dispose(int nargs);
diff --git a/engines/director/lingo/xlibs/xplayanim.cpp b/engines/director/lingo/xlibs/xplayanim.cpp
index 2c9fb8f0d3d..88393000a93 100644
--- a/engines/director/lingo/xlibs/xplayanim.cpp
+++ b/engines/director/lingo/xlibs/xplayanim.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void XPlayAnim::open(int type) {
+void XPlayAnim::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void XPlayAnim::close(int type) {
+void XPlayAnim::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/xplayanim.h b/engines/director/lingo/xlibs/xplayanim.h
index 33dd3ffa050..42c291f3b22 100644
--- a/engines/director/lingo/xlibs/xplayanim.h
+++ b/engines/director/lingo/xlibs/xplayanim.h
@@ -38,8 +38,8 @@ namespace XPlayAnim {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void b_xplayanim(int nargs);
 
diff --git a/engines/director/lingo/xlibs/xsoundxfcn.cpp b/engines/director/lingo/xlibs/xsoundxfcn.cpp
index 6a4cfae707b..022a1228803 100644
--- a/engines/director/lingo/xlibs/xsoundxfcn.cpp
+++ b/engines/director/lingo/xlibs/xsoundxfcn.cpp
@@ -47,11 +47,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void XSoundXFCN::open(int type) {
+void XSoundXFCN::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void XSoundXFCN::close(int type) {
+void XSoundXFCN::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/xsoundxfcn.h b/engines/director/lingo/xlibs/xsoundxfcn.h
index 7d5b7ca2c0a..cb0195a8ee8 100644
--- a/engines/director/lingo/xlibs/xsoundxfcn.h
+++ b/engines/director/lingo/xlibs/xsoundxfcn.h
@@ -29,8 +29,8 @@ namespace XSoundXFCN {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_XSound(int nargs);
 
diff --git a/engines/director/lingo/xlibs/yasix.cpp b/engines/director/lingo/xlibs/yasix.cpp
index 36541e5201c..e719ef65773 100644
--- a/engines/director/lingo/xlibs/yasix.cpp
+++ b/engines/director/lingo/xlibs/yasix.cpp
@@ -49,11 +49,11 @@ static BuiltinProto builtins[] = {
 	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
 };
 
-void Yasix::open(int type) {
+void Yasix::open(ObjectType type) {
 	g_lingo->initBuiltIns(builtins);
 }
 
-void Yasix::close(int type) {
+void Yasix::close(ObjectType type) {
 	g_lingo->cleanupBuiltIns(builtins);
 }
 
diff --git a/engines/director/lingo/xlibs/yasix.h b/engines/director/lingo/xlibs/yasix.h
index 10dab250220..acd8eac2363 100644
--- a/engines/director/lingo/xlibs/yasix.h
+++ b/engines/director/lingo/xlibs/yasix.h
@@ -29,8 +29,8 @@ namespace Yasix {
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 void m_yasix(int nargs);
 


Commit: 366ede608fd967545835a78722e57a806449debe
    https://github.com/scummvm/scummvm/commit/366ede608fd967545835a78722e57a806449debe
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DEVTOOLS: Add Lingo Xtra support to director-generate-xobj-stub

Changed paths:
    devtools/director-generate-xobj-stub.py


diff --git a/devtools/director-generate-xobj-stub.py b/devtools/director-generate-xobj-stub.py
index c2c855e97ea..139e551fcba 100755
--- a/devtools/director-generate-xobj-stub.py
+++ b/devtools/director-generate-xobj-stub.py
@@ -19,12 +19,20 @@ class XCode(TypedDict):
     filename: str
     method_table: list[str]
 
+class PESection(TypedDict):
+    name: str
+    virt_size: int
+    virt_addr: int
+    raw_size: int
+    raw_ptr: int
+
 
 DIRECTOR_SRC_PATH = os.path.abspath(
     os.path.join(__file__, "..", "..", "engines", "director")
 )
 MAKEFILE_PATH = os.path.join(DIRECTOR_SRC_PATH, "module.mk")
 LINGO_XLIBS_PATH = os.path.join(DIRECTOR_SRC_PATH, "lingo", "xlibs")
+LINGO_XTRAS_PATH = os.path.join(DIRECTOR_SRC_PATH, "lingo", "xtras")
 LINGO_OBJECT_PATH = os.path.join(DIRECTOR_SRC_PATH, "lingo", "lingo-object.cpp")
 
 LEGAL = """/* ScummVM - Graphic Adventure Engine
@@ -52,8 +60,8 @@ LEGAL = """/* ScummVM - Graphic Adventure Engine
 TEMPLATE_H = (
     LEGAL
     + """
-#ifndef DIRECTOR_LINGO_XLIBS_{slug_upper}_H
-#define DIRECTOR_LINGO_XLIBS_{slug_upper}_H
+#ifndef DIRECTOR_LINGO_{base_upper}_{slug_upper}_H
+#define DIRECTOR_LINGO_{base_upper}_{slug_upper}_H
 
 namespace Director {{
 
@@ -67,8 +75,8 @@ namespace {xobj_class} {{
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 {methlist}
 
@@ -91,7 +99,7 @@ TEMPLATE = (
 #include "director/lingo/lingo.h"
 #include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-utils.h"
-#include "director/lingo/xlibs/{slug}.h"
+#include "director/lingo/{base}/{slug}.h"
 
 /**************************************************
  *
@@ -117,41 +125,48 @@ static MethodProto xlibMethods[] = {{
 	{{ nullptr, nullptr, 0, 0, 0 }}
 }};
 
+static BuiltinProto xlibBuiltins[] = {{
+{xlib_builtins}
+	{{ nullptr, nullptr, 0, 0, 0, VOIDSYM }}
+}};
+
+static BuiltinProto xlibTopLevel[] = {{
+{xlib_toplevels}
+	{{ nullptr, nullptr, 0, 0, 0, VOIDSYM }}
+}};
+
 {xobject_class}::{xobject_class}(ObjectType ObjectType) :Object<{xobject_class}>("{xobj_class}") {{
 	_objType = ObjectType;
 }}
 
-void {xobj_class}::open(int type) {{
-	if (type == kXObj) {{
-		{xobject_class}::initMethods(xlibMethods);
-		{xobject_class} *xobj = new {xobject_class}(kXObj);
-		g_lingo->exposeXObject(xlibName, xobj);
-	}} else if (type == kXtraObj) {{
-		// TODO - Implement Xtra
-	}}
+void {xobj_class}::open(ObjectType type) {{
+    {xobject_class}::initMethods(xlibMethods);
+    {xobject_class} *xobj = new {xobject_class}(type);
+    g_lingo->exposeXObject(xlibName, xobj);
+    g_lingo->initBuiltIns(xlibBuiltins);
 }}
 
-void {xobj_class}::close(int type) {{
-	if (type == kXObj) {{
-		{xobject_class}::cleanupMethods();
-		g_lingo->_globalvars[xlibName] = Datum();
-	}} else if (type == kXtraObj) {{
-		// TODO - Implement Xtra
-	}}
-}}
+void {xobj_class}::close(ObjectType type) {{
+    {xobject_class}::cleanupMethods();
+    g_lingo->_globalvars[xlibName] = Datum();
 
-void {xobj_class}::m_new(int nargs) {{
-	g_lingo->printSTUBWithArglist("{xobj_class}::m_new", nargs);
-	g_lingo->dropStack(nargs);
-	g_lingo->push(g_lingo->_state->me);
 }}
 
+{xobj_new}
+
 {xobj_stubs}
 
 }}
 """
 )
-XLIB_METHOD_TEMPLATE = """	{{ "{methname}",				{xobj_class}::m_{methname},		 {arg_count}, {arg_count},	{director_version} }},"""
+XLIB_METHOD_TEMPLATE = """	{{ "{methname}",				{xobj_class}::m_{methname},		 {min_args}, {max_args},	{director_version} }},"""
+XLIB_NEW_TEMPLATE = """void {xobj_class}::m_new(int nargs) {{
+	g_lingo->printSTUBWithArglist("{xobj_class}::m_new", nargs);
+	g_lingo->dropStack(nargs);
+	g_lingo->push(g_lingo->_state->me);
+}}"""
+
+
 
 XCMD_TEMPLATE_H = (
     LEGAL
@@ -166,8 +181,8 @@ namespace {xobj_class} {{
 extern const char *xlibName;
 extern const char *fileNames[];
 
-void open(int type);
-void close(int type);
+void open(ObjectType type);
+void close(ObjectType type);
 
 {methlist}
 
@@ -210,11 +225,11 @@ static BuiltinProto builtins[] = {{
 	{{ nullptr, nullptr, 0, 0, 0, VOIDSYM }}
 }};
 
-void {xobj_class}::open(int type) {{
+void {xobj_class}::open(ObjectType type) {{
 	g_lingo->initBuiltIns(builtins);
 }}
 
-void {xobj_class}::close(int type) {{
+void {xobj_class}::close(ObjectType type) {{
 	g_lingo->cleanupBuiltIns(builtins);
 }}
 
@@ -224,7 +239,7 @@ void {xobj_class}::close(int type) {{
 """
 )
 
-XCMD_BUILTIN_TEMPLATE = """	{{ "{name}", {xobj_class}::m_{name}, -1, 0, {director_version}, {methtype} }},"""
+BUILTIN_TEMPLATE = """	{{ "{name}", {xobj_class}::m_{name}, {min_args}, {max_args}, {director_version}, {methtype} }},"""
 
 XOBJ_STUB_TEMPLATE = """XOBJSTUB({xobj_class}::m_{methname}, {default})"""
 
@@ -251,34 +266,37 @@ def read_uint32_be(data: bytes) -> int:
     return struct.unpack(">L", data)[0]
 
 
-def inject_makefile(slug: str) -> None:
+def inject_makefile(slug: str, xcode_type: XCodeType) -> None:
     make_contents = open(MAKEFILE_PATH, "r").readlines()
-    expr = re.compile("^\tlingo/xlibs/([a-zA-Z0-9\\-]+).o( \\\\|)")
+    storage_path = "lingo/xtras" if xcode_type == "Xtra" else "lingo/xlibs"
+    expr = re.compile(f"^\t{storage_path}/([a-zA-Z0-9\\-]+).o( \\\\|)")
     for i in range(len(make_contents)):
         m = expr.match(make_contents[i])
         if m:
             if slug == m.group(1):
                 # file already in makefile
-                print(f"lingo/xlibs/{slug}.o already in {MAKEFILE_PATH}, skipping")
+                print(f"{storage_path}/{slug}.o already in {MAKEFILE_PATH}, skipping")
                 return
             elif slug < m.group(1):
-                make_contents.insert(i, f"\tlingo/xlibs/{slug}.o \\\n")
+                make_contents.insert(i, f"\t{storage_path}/{slug}.o \\\n")
                 with open(MAKEFILE_PATH, "w") as f:
                     f.writelines(make_contents)
                 return
             elif m.group(2) == "":
                 # final entry in the list
                 make_contents[i] += " \\"
-                make_contents.insert(i + 1, f"\tlingo/xlibs/{slug}.o\n")
+                make_contents.insert(i + 1, f"\t{storage_path}/{slug}.o\n")
                 with open(MAKEFILE_PATH, "w") as f:
                     f.writelines(make_contents)
                 return
 
 
-def inject_lingo_object(slug: str, xobj_class: str, director_version: int) -> None:
+def inject_lingo_object(slug: str, xobj_class: str, director_version: int, xcode_type: XCodeType) -> None:
     # write include statement for the object header
     lo_contents = open(LINGO_OBJECT_PATH, "r").readlines()
-    expr = re.compile('^#include "director/lingo/xlibs/([a-zA-Z0-9\\-]+)\\.h"')
+    storage_path = "director/lingo/xtras" if xcode_type == "Xtra" else "director/lingo/xlibs"
+    obj_type = "kXtraObj" if xcode_type == "Xtra" else "kXObj"
+    expr = re.compile(f'^#include "{storage_path}/([a-zA-Z0-9\\-]+)\\.h"')
     in_xlibs = False
     for i in range(len(lo_contents)):
         m = expr.match(lo_contents[i])
@@ -286,17 +304,17 @@ def inject_lingo_object(slug: str, xobj_class: str, director_version: int) -> No
             in_xlibs = True
             if slug == m.group(1):
                 print(
-                    f"lingo/xlibs/{slug}.h import already in {LINGO_OBJECT_PATH}, skipping"
+                    f"{storage_path}/{slug}.h import already in {LINGO_OBJECT_PATH}, skipping"
                 )
                 break
             elif slug < m.group(1):
-                lo_contents.insert(i, f'#include "director/lingo/xlibs/{slug}.h"\n')
+                lo_contents.insert(i, f'#include "{storage_path}/{slug}.h"\n')
                 with open(LINGO_OBJECT_PATH, "w") as f:
                     f.writelines(lo_contents)
                 break
         elif in_xlibs:
             # final entry in the list
-            lo_contents.insert(i, f'#include "director/lingo/xlibs/{slug}.h"\n')
+            lo_contents.insert(i, f'#include "{storage_path}/{slug}.h"\n')
             with open(LINGO_OBJECT_PATH, "w") as f:
                 f.writelines(lo_contents)
                 break
@@ -317,7 +335,7 @@ def inject_lingo_object(slug: str, xobj_class: str, director_version: int) -> No
             elif xobj_class < m.group(1):
                 lo_contents.insert(
                     i,
-                    f"	{{ {xobj_class}::fileNames,			{xobj_class}::open,			{xobj_class}::close,		kXObj,					{director_version} }},	// D{director_version // 100}\n",
+                    f"	{{ {xobj_class}::fileNames,			{xobj_class}::open,			{xobj_class}::close,		{obj_type},					{director_version} }},	// D{director_version // 100}\n",
                 )
                 with open(LINGO_OBJECT_PATH, "w") as f:
                     f.writelines(lo_contents)
@@ -326,7 +344,7 @@ def inject_lingo_object(slug: str, xobj_class: str, director_version: int) -> No
             # final entry in the list
             lo_contents.insert(
                 i,
-                f"	{{ {xobj_class}::fileNames,			{xobj_class}::open,			{xobj_class}::close,		kXObj,					{director_version} }},	// D{director_version // 100}\n",
+                f"	{{ {xobj_class}::fileNames,			{xobj_class}::open,			{xobj_class}::close,		{obj_type},					{director_version} }},	// D{director_version // 100}\n",
             )
             with open(LINGO_OBJECT_PATH, "w") as f:
                 f.writelines(lo_contents)
@@ -506,15 +524,107 @@ def extract_xcode_win16(file: BinaryIO, ne_offset: int) -> XCode:
 
 
 def extract_xcode_win32(file: BinaryIO, pe_offset: int) -> XCode:
-    # get the .data section
-    # find a string b"msgTable\x00", get the offset
-    # get the .text section
-    # find assembly:
-    # 68 [ addr ] 6a 00 6a [ addr 2 ]
-    # lookup addr2 in .data
-    # get c string, split by \x0a
+    file.seek(pe_offset + 4)
+
+    # read the COFF Header, perform basic sanity checks
+    machine_type = read_uint16_le(file.read(0x2))
+    if machine_type != 0x14c:
+        raise ValueError(f"PE file is not 32-bit Intel x86")
+    section_count = read_uint16_le(file.read(0x2))
+    file.seek(12, os.SEEK_CUR)
+    optional_size = read_uint16_le(file.read(0x2))
+    characteristics = read_uint16_le(file.read(0x2))
+    if not (characteristics & 0x2000):
+        raise ValueError("DLL flag not set")
+    if not (characteristics & 0x0100):
+        raise ValueError("32-bit flag not set")
+
+    # read the Optional Header to get the image base address
+    optional = file.read(optional_size)
+    image_base = 0
+    if read_uint16_le(optional[0:2]) == 0x10b:
+        image_base = read_uint32_le(optional[28:32])
+        print(f"Found PE32, image base {image_base:08x}")
+    elif read_uint16_le(optional[0:2]) == 0x20b:
+        raise ValueError("PE32+ not supported")
+    else:
+        raise ValueError("Unknown optional header magic number")
+
+    # read each Section Header from the Section Table
+    sections: dict[str, PESection] = {}
+    for i in range(section_count):
+        segment: PESection = {
+            "name": file.read(0x8).strip(b'\x00').decode('utf8'),
+            "virt_size": read_uint32_le(file.read(0x4)),
+            "virt_addr": read_uint32_le(file.read(0x4)),
+            "raw_size": read_uint32_le(file.read(0x4)),
+            "raw_ptr": read_uint32_le(file.read(0x4)),
+        }
+        file.seek(16, os.SEEK_CUR)
+        sections[segment["name"]] = segment
+        print(f"{segment['name']}: {segment['virt_addr']:08x} {segment['virt_size']:08x}")
+
+    # grab the .text section; this contains the program instructions
+    if ".text" not in sections:
+        raise ValueError(".text section not found")
+    file.seek(sections[".text"]["raw_ptr"])
+    code = file.read(sections[".text"]["raw_size"])
+
+    # Lingo Xtras are COM libraries with a generic calling API.
+    # Director discovers what functions are available by requesting
+    # a msgTable, which unfortunately for us is done with code.
+    # We need to find the following x86 assembly:
+    # 68 [ u32 addr 1 ]  ; push offset "msgTable"
+    # 6a 00              ; push 0
+    # 68 [ u32 addr 2 ]  ; push offset xtra_methtable
+    # 6a 09              ; push 9
+
+    instr = re.compile(rb"\x68(.{4})\x6a\x00\x68(.{4})\x6a\x09", flags=re.DOTALL)
+    methtable_found = False
+    methtable = []
+    for msgtable_raw, methtable_raw in instr.findall(code):
+        # should be the offset to the string "msgTable"
+        msgtable_offset = read_uint32_le(msgtable_raw) - image_base
+        # should be the offset to the full method table
+        methtable_offset = read_uint32_le(methtable_raw) - image_base
+        msgtable_found = False
+        for s in sections.values():
+            if msgtable_offset in range(s["virt_addr"], s["virt_addr"]+s["virt_size"]):
+                file.seek(s["raw_ptr"])
+                data = file.read(s["raw_size"])
+                start = msgtable_offset - s["virt_addr"]
+                end = data.find(b"\x00", start)
+                if data[start:end] != b"msgTable":
+                    continue
+                print(f"Found msgTable!")
+                msgtable_found = True
+        if not msgtable_found:
+            continue
+        # If we found the text "msgTable" at the first address, we know we've found the right call.
+        for s in sections.values():
+            if methtable_offset in range(s["virt_addr"], s["virt_addr"]+s["virt_size"]):
+                file.seek(s["raw_ptr"])
+                data = file.read(s["raw_size"])
+                start = methtable_offset - s["virt_addr"]
+                end = data.find(b"\x00", start)
+                methtable_found = True
+                methtable = data[start:end].decode('iso-8859-1').split('\n')
+    if not methtable_found:
+        raise ValueError("Could not find msgTable!")
+
+    for entry in methtable:
+        print(entry)
+
+    library_name = methtable[0].split()[1].capitalize()
+    methtable[0] = "-- " + methtable[0]
 
-    return {"type": "Xtra", "name": "", "slug": "", "filename": "", "method_table": []}
+    return {
+        "type": "Xtra",
+        "name": library_name,
+        "slug": library_name.lower(),
+        "filename": library_name.lower(),
+        "method_table": methtable
+    }
 
 
 def extract_xcode(path: str, resid: str) -> XCode:
@@ -529,7 +639,8 @@ def extract_xcode(path: str, resid: str) -> XCode:
                 print("Found Win16 NE DLL!")
                 return extract_xcode_win16(file, header_offset)
             elif magic == b"PE":
-                raise ValueError("No support yet for extracting from Win32 DLLs")
+                print("Found Win32 PE DLL!")
+                return extract_xcode_win32(file, header_offset)
         file.seek(0)
         header = file.read(124)
         if (
@@ -585,7 +696,8 @@ def generate_xobject_stubs(
             dict(
                 methname=methname,
                 args=args,
-                arg_count=len(args),
+                min_args=len(args),
+                max_args=len(args),
                 returnval=returnval,
                 default='""' if returnval == "S" else "0",
             )
@@ -594,12 +706,15 @@ def generate_xobject_stubs(
     xobj_class = f"{name}XObj"
 
     cpp_text = TEMPLATE.format(
+        base="xlibs",
         slug=slug,
         name=name,
         filename=filename,
         xmethtable="\n".join(xmethtable),
         xobject_class=xobject_class,
         xobj_class=xobj_class,
+        xlib_builtins="",
+        xlib_toplevels="",
         xlib_methods="\n".join(
             [
                 XLIB_METHOD_TEMPLATE.format(
@@ -608,6 +723,7 @@ def generate_xobject_stubs(
                 for x in meths
             ]
         ),
+		xobj_new=XLIB_NEW_TEMPLATE.format(xobj_class=xobj_class),
         xobj_stubs="\n".join(
             [
                 XOBJ_NR_STUB_TEMPLATE.format(xobj_class=xobj_class, **x)
@@ -627,6 +743,7 @@ def generate_xobject_stubs(
             cpp.write(cpp_text)
 
     header_text = TEMPLATE_H.format(
+        base_upper="XLIBS",
         slug_upper=slug.upper(),
         xobject_class=xobject_class,
         xobj_class=xobj_class,
@@ -641,8 +758,8 @@ def generate_xobject_stubs(
             header.write(header_text)
 
     if not dry_run:
-        inject_makefile(slug)
-        inject_lingo_object(slug, xobj_class, director_version)
+        inject_makefile(slug, "XObject")
+        inject_lingo_object(slug, xobj_class, director_version, "XObject")
 
 
 def generate_xcmd_stubs(
@@ -660,9 +777,11 @@ def generate_xcmd_stubs(
         name=name,
         filename=filename,
         xobj_class=xobj_class,
-        xlib_builtins=XCMD_BUILTIN_TEMPLATE.format(
+        xlib_builtins=BUILTIN_TEMPLATE.format(
             name=name,
             xobj_class=xobj_class,
+            min_args=-1,
+            max_args=0,
             director_version=director_version,
             methtype=methtype,
         ),
@@ -692,8 +811,124 @@ def generate_xcmd_stubs(
             header.write(header_text)
 
     if not dry_run:
-        inject_makefile(slug)
-        inject_lingo_object(slug, xobj_class, director_version)
+        inject_makefile(slug, type)
+        inject_lingo_object(slug, xobj_class, director_version, "XObject")
+
+def generate_xtra_stubs(
+    msgtable: list[str],
+    slug: str,
+    name: str,
+    filename: str,
+    director_version: int = 500,
+    dry_run: bool = False,
+) -> None:
+    meths = []
+    for e in msgtable:
+        elem = e.split("--", 1)[0].strip()
+        if not elem:
+            continue
+        functype = "method"
+        if elem.startswith("+"):
+            elem = elem[1:].strip()
+            functype = "toplevel"
+        elif elem.startswith("*"):
+            elem = elem[1:].strip()
+            functype = "global"
+        if " " not in elem:
+            methname, argv = elem, []
+        else:
+            methname, args = elem.split(" ", 1)
+            argv = args.split(",")
+        min_args = len(argv)
+        max_args = len(argv)
+        if argv and argv[-1].strip() == "*":
+            min_args = -1
+            max_args = 0
+        elif functype == "method":
+            min_args -= 1
+            max_args = 0
+
+        meths.append(
+            dict(
+                functype=functype,
+                methname=methname,
+                args=argv,
+                min_args=min_args,
+                max_args=max_args,
+                default="0",
+            )
+        )
+    xobject_class = f"{name}XtraObject"
+    xobj_class = f"{name}Xtra"
+
+    cpp_text = TEMPLATE.format(
+        base="xtras",
+        slug=slug,
+        name=name,
+        filename=filename,
+        xmethtable="\n".join(msgtable),
+        xobject_class=xobject_class,
+        xobj_class=xobj_class,
+        xlib_methods="\n".join(
+            [
+                XLIB_METHOD_TEMPLATE.format(
+                    xobj_class=xobj_class, director_version=director_version, **x
+                )
+                for x in meths if x["functype"] == "method"
+            ]
+        ),
+        xlib_builtins="\n".join([BUILTIN_TEMPLATE.format(
+            name=x["methname"],
+            xobj_class=xobj_class,
+            min_args=x["min_args"],
+            max_args=x["max_args"],
+            director_version=director_version,
+            methtype="HBLTIN",
+        ) for x in meths if x["functype"] == "global"]),
+        xlib_toplevels="\n".join([BUILTIN_TEMPLATE.format(
+            name=x["methname"],
+            xobj_class=xobj_class,
+            min_args=x["min_args"],
+            max_args=x["max_args"],
+            director_version=director_version,
+            methtype="HBLTIN",
+        ) for x in meths if x["functype"] == "toplevel"]),
+		xobj_new=XLIB_NEW_TEMPLATE.format(xobj_class=xobj_class),
+        xobj_stubs="\n".join(
+            [
+                XOBJ_STUB_TEMPLATE.format(xobj_class=xobj_class, **x)
+                for x in meths
+                if x["methname"] != "new"
+            ]
+        ),
+    )
+    if dry_run:
+        print("C++ output:")
+        print(cpp_text)
+        print()
+    else:
+        with open(os.path.join(LINGO_XTRAS_PATH, f"{slug}.cpp"), "w") as cpp:
+            cpp.write(cpp_text)
+
+    header_text = TEMPLATE_H.format(
+        base_upper="XTRAS",
+        slug_upper=slug.upper(),
+        xobject_class=xobject_class,
+        xobj_class=xobj_class,
+        methlist="\n".join([TEMPLATE_HEADER_METH.format(**x) for x in meths]),
+    )
+    if dry_run:
+        print("Header output:")
+        print(header_text)
+        print()
+    else:
+        with open(os.path.join(LINGO_XTRAS_PATH, f"{slug}.h"), "w") as header:
+            header.write(header_text)
+
+    if not dry_run:
+        inject_makefile(slug, "Xtra")
+        inject_lingo_object(slug, xobj_class, director_version, "Xtra")
+
 
 
 def main() -> None:
@@ -737,6 +972,10 @@ def main() -> None:
             args.version,
             args.dry_run,
         )
+    elif xcode["type"] == "Xtra":
+        generate_xtra_stubs(
+            xcode["method_table"], slug, name, xcode["filename"], args.version, args.dry_run
+        )
     elif xcode["type"] == "XFCN" or xcode["type"] == "XCMD":
         generate_xcmd_stubs(
             xcode["type"], slug, name, xcode["filename"], args.version, args.dry_run


Commit: b782ab4607d5b332c7dd6ef33cad7b833f162fd1
    https://github.com/scummvm/scummvm/commit/b782ab4607d5b332c7dd6ef33cad7b833f162fd1
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Update gadgetpaf detection entry

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index d542f781c84..e52b69027bb 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -6286,10 +6286,12 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	MACGAME1("gadgetpaf",	"",		 "GADGET -Past as Future- (Disc1)", "3b96e0a903130cf68e6f8362bb4d096c", 178907, 501),
 	MACGAME1_l("gadgetpaf", "",		 "GADGET -Past as Future- (Disc1)", "4b2213a9fb04f390ec074c54b916370d", 113169, Common::JA_JPN, 501),
-	WINGAME2("gadgetpaf",	"",		 "GADGET.EXE", "1a7acbba10a7246ba58c1d53fc7203f5", 1411507,
-									 "TEXT_E.Cxt", "5f14330705974a22deb9a12cd8ae6e79", 691046, 501),
-	WINGAME2_l("gadgetpaf", "",		 "GADGET.EXE", "1a7acbba10a7246ba58c1d53fc7203f5", 1411507,
-									 "TEXT_E.Cxt", "056ab5419f65fab51fa50c28ad360e76", 561824, Common::ES_ESP, 501),
+	WINGAME2("gadgetpaf",	"",		 "GADGET/GADGET.EXE", "t:c8a85e9a0eda2b7dd7974197c02d6469", 1411507,
+									 "DATA/TEXT_E.Cxt", "f:e74119685db701dea9f31f91521fd078", 2457643, 501),
+	WINGAME2("gadgetpaf",	"",		 "GADGET/GADGET.EXE", "1a7acbba10a7246ba58c1d53fc7203f5", 1411507,
+									 "DATA/TEXT_E.Cxt", "5f14330705974a22deb9a12cd8ae6e79", 691046, 501),
+	WINGAME2_l("gadgetpaf", "",		 "GADGET/GADGET.EXE", "1a7acbba10a7246ba58c1d53fc7203f5", 1411507,
+									 "DATA/TEXT_E.Cxt", "056ab5419f65fab51fa50c28ad360e76", 561824, Common::ES_ESP, 501),
 	WINDEMO2f_l("gadgetpaf", "Demo", "GADGET.exe", "t:7e393434e06153a6413baf1b448f440e", 1647502,
 									 "TEXT_E.Cxt", "h:f2efb64dc4e3e1ea705309426fff7824", 152776, Common::ES_ESP, 501, GF_32BPP),
 


Commit: ce2b2354c3b6d9f10dd418cce88d1f8693af8b5e
    https://github.com/scummvm/scummvm/commit/ce2b2354c3b6d9f10dd418cce88d1f8693af8b5e
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add Xtras folder detection

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 5f0ca8882eb..f0926a8fbb8 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -114,6 +114,7 @@ static BuiltinProto builtins[] = {
 	{ "showResFile",	LB::b_showResFile,	0, 1, 200, CBLTIN },	// D2 c
 	{ "showXlib",		LB::b_showXlib,		0, 1, 200, CBLTIN },	// D2 c
 	{ "xFactoryList",	LB::b_xFactoryList,	1, 1, 300, FBLTIN },	//		D3 f
+	{ "xtra",			LB::b_xtra,			1, 1, 500, FBLTIN },	//				D5 f
 	// Control
 	{ "abort",			LB::b_abort,		0, 0, 400, CBLTIN },	//			D4 c
 	{ "continue",		LB::b_continue,		0, 0, 200, CBLTIN },	// D2 c
@@ -1381,6 +1382,17 @@ void LB::b_xFactoryList(int nargs) {
 	g_lingo->push(d);
 }
 
+void LB::b_xtra(int nargs) {
+	Common::String name = g_lingo->pop().asString();
+	if (g_lingo->_globalvars.contains(name)) {
+		Datum var = g_lingo->_globalvars[name];
+		if (var.type == OBJECT && var.u.obj->getObjType() == kXtraObj) {
+			g_lingo->push(var);
+		}
+	}
+	g_lingo->lingoError("Xtra not found: %s", name.c_str());
+}
+
 ///////////////////
 // Control
 ///////////////////
diff --git a/engines/director/lingo/lingo-builtins.h b/engines/director/lingo/lingo-builtins.h
index 53f344ceb3d..53df1900aad 100644
--- a/engines/director/lingo/lingo-builtins.h
+++ b/engines/director/lingo/lingo-builtins.h
@@ -157,6 +157,7 @@ void b_saveMovie(int nargs);
 void b_showResFile(int nargs);
 void b_showXlib(int nargs);
 void b_xFactoryList(int nargs);
+void b_xtra(int nargs);
 
 void b_point(int nargs);
 void b_inside(int nargs);
diff --git a/engines/director/resource.cpp b/engines/director/resource.cpp
index a1e32599056..b4bb76749ca 100644
--- a/engines/director/resource.cpp
+++ b/engines/director/resource.cpp
@@ -22,11 +22,13 @@
 #include "common/config-manager.h"
 #include "common/error.h"
 #include "common/file.h"
+#include "common/fs.h"
 #include "common/macresman.h"
 #include "common/memstream.h"
 #include "common/bufferedstream.h"
 #include "common/substream.h"
 #include "common/formats/winexe.h"
+#include "director/types.h"
 #include "graphics/wincursor.h"
 
 #include "director/director.h"
@@ -203,6 +205,34 @@ void Window::probeResources(Archive *archive) {
 		}
 		delete resFork;
 	}
+
+	// Xtras
+	if (g_director->getVersion() >= 500) {
+		Common::Path basePath(g_director->getEXEName(), g_director->_dirSeparator);
+		basePath = basePath.getParent().appendComponent("Xtras");
+		basePath = findPath(basePath, false, false, true);
+		if (!basePath.empty()) {
+			Common::StringArray directory_list = basePath.splitComponents();
+			Common::FSNode d = Common::FSNode(*g_director->getGameDataDir());
+			bool escape = false;
+			for (auto &it : directory_list) {
+				d = d.getChild(it);
+				if (!d.exists()) {
+					escape = true;
+					break;
+				}
+			}
+			if (!escape) {
+				debug(0, "Detected Xtras folder");
+				Common::FSList xtras;
+				d.getChildren(xtras, Common::FSNode::kListFilesOnly);
+				for (auto &it : xtras) {
+					debug(0, "Detected Xtra '%s'", it.getName().c_str());
+					g_lingo->openXLib(it.getName(), kXtraObj);
+				}
+			}
+		}
+	}
 }
 
 void DirectorEngine::addArchiveToOpenList(const Common::Path &path) {


Commit: 750566a25f13ff8b3e7a73b53e43f75e6cb388fd
    https://github.com/scummvm/scummvm/commit/750566a25f13ff8b3e7a73b53e43f75e6cb388fd
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: XOBJ: Add D5 methods to FileIO

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index f0926a8fbb8..7b71cdb3d1d 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1388,6 +1388,7 @@ void LB::b_xtra(int nargs) {
 		Datum var = g_lingo->_globalvars[name];
 		if (var.type == OBJECT && var.u.obj->getObjType() == kXtraObj) {
 			g_lingo->push(var);
+			return;
 		}
 	}
 	g_lingo->lingoError("Xtra not found: %s", name.c_str());
diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 255baa79b40..3593be15c8a 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -27,6 +27,8 @@
  *************************************/
 
 /*
+ * -- XObject version
+ *
  * --FileIO, Tool, 1.5.0 , 31mar92
  * --© 1989-1992 MacroMind, Inc.
  * --by John Thompson and Al McNeil
@@ -85,6 +87,37 @@
  * --  -65 :: No disk in drive
  * --  -120 :: Directory not found
  * V     mReadPICT
+ * II     +mSetOverrideDrive, driveLetter --Set override drive letter ('A' - 'Z') to use when loading linked castmembers.  Use 0x00 to clear override.
+ *
+ * -- Xtra version
+-- xtra fileio -- CH May96
+new object me -- create a new child instance
+-- FILEIO --
+fileName object me -- return fileName string of the open file
+status object me -- return the error code of the last method called
+error object me, int error -- return the error string of the error
+setFilterMask me, string mask -- set the filter mask for dialogs
+openFile object me, string fileName, int mode -- opens named file. valid modes: 0=r/w 1=r 2=w
+closeFile object me -- close the file
+displayOpen object me -- displays an open dialog and returns the selected fileName to lingo
+displaySave object me, string title, string defaultFileName -- displays save dialog and returns selected fileName to lingo
+createFile object me, string fileName -- creates a new file called fileName
+setPosition object me, int position -- set the file position
+getPosition object me -- get the file position
+getLength object me -- get the length of the open file
+writeChar object me, string theChar -- write a single character (by ASCII code) to the file
+writeString object me, string theString -- write a null-terminated string to the file
+readChar object me -- read the next character of the file and return it as an ASCII code value
+readLine object me -- read the next line of the file (including the next RETURN) and return as a string
+readFile object me -- read from current position to EOF and return as a string
+readWord object me -- read the next word of the file and return it as a string
+readToken object me, string skip, string break -- read the next token and return it as a string
+getFinderInfo object me -- get the finder info for the open file (Mac Only)
+setFinderInfo object me, string attributes -- set the finder info for the open file (Mac Only)
+delete object me -- deletes the open file
++ version xtraRef -- display fileIO version and build information in the message window
+* getOSDirectory -- returns the full path to the Mac System Folder or Windows Directory
+
  */
 
 #include "gui/filebrowser-dialog.h"
@@ -98,6 +131,7 @@
 #include "director/lingo/lingo-object.h"
 #include "director/lingo/lingo-utils.h"
 #include "director/lingo/xlibs/fileio.h"
+#include "savestate.h"
 
 namespace Director {
 
@@ -109,13 +143,14 @@ const char *FileIO::fileNames[] = {
 };
 
 static MethodProto xlibMethods[] = {
+	// XObject
 	{ "delete",					FileIO::m_delete,			 0, 0,	200 },	// D2
 	{ "error",					FileIO::m_error,			 1, 1,	200 },	// D2
 	{ "fileName",				FileIO::m_fileName,			 0, 0,	200 },	// D2
 	{ "getFinderInfo",			FileIO::m_getFinderInfo,	 0, 0,	200 },	// D2
 	{ "getLength",				FileIO::m_getLength,		 0, 0,	200 },	// D2
 	{ "getPosition",			FileIO::m_getPosition,		 0, 0,	200 },	// D2
-	{ "new",					FileIO::m_new,				 2, 2,	200 },	// D2
+	{ "new",					FileIO::m_new,				 0, 2,	200 },	// D2
 	{ "readChar",				FileIO::m_readChar,			 0, 0,	200 },	// D2
 	{ "readFile",				FileIO::m_readFile,			 0, 0,	200 },	// D2
 	{ "readLine",				FileIO::m_readLine,			 0, 0,	200 },	// D2
@@ -127,32 +162,34 @@ static MethodProto xlibMethods[] = {
 	{ "status",					FileIO::m_status,			 0, 0,	200 },	// D2
 	{ "writeChar",				FileIO::m_writeChar,		 1, 1,	200 },	// D2
 	{ "writeString",			FileIO::m_writeString,		 1, 1,	200 },	// D2
-
-	// Non-standard extensions
-	// - Used by Maniac Sports
-	// II     +mSetOverrideDrive, driveLetter --Set override drive letter ('A' - 'Z') to use when loading linked castmembers.  Use 0x00 to clear override.
+	// Windows only?
 	{ "setOverrideDrive",		FileIO::m_setOverrideDrive,	 1, 1,	300 },	// D3
-
+	// Xtra
+	{ "closeFile",				FileIO::m_closeFile,		 0, 0,	500 },	// D5
+	{ "createFile",				FileIO::m_createFile,		 1, 1,	500 },	// D5
+	{ "displayOpen",			FileIO::m_displayOpen,		 0, 0,	500 },	// D5
+	{ "displaySave",			FileIO::m_displaySave,		 2, 2,	500 },	// D5
+	{ "openFile",				FileIO::m_openFile,			 2, 2,	500 },	// D5
+	{ "setFilterMask",			FileIO::m_setFilterMask,	 1, 1,	500 },  // D5
 	{ nullptr, nullptr, 0, 0, 0 }
 };
 
+static BuiltinProto xlibBuiltins[] = {
+	{ "getOSDirectory", FileIO::m_getOSDirectory, 0, 0, 500, HBLTIN },
+	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
+};
+
+
 void FileIO::open(ObjectType type) {
-	if (type == kXObj) {
-		FileObject::initMethods(xlibMethods);
-		FileObject *xobj = new FileObject(kXObj);
-		g_lingo->exposeXObject(xlibName, xobj);
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
-	}
+	FileObject::initMethods(xlibMethods);
+	FileObject *xobj = new FileObject(type);
+	g_lingo->exposeXObject(xlibName, xobj);
+	g_lingo->initBuiltIns(xlibBuiltins);
 }
 
 void FileIO::close(ObjectType type) {
-	if (type == kXObj) {
-		FileObject::cleanupMethods();
-		g_lingo->_globalvars[xlibName] = Datum();
-	} else if (type == kXtraObj) {
-		// TODO - Implement Xtra
-	}
+	FileObject::cleanupMethods();
+	g_lingo->_globalvars[xlibName] = Datum();
 }
 
 // Initialization/disposal
@@ -176,50 +213,10 @@ FileObject::~FileObject() {
 	clear();
 }
 
-void FileObject::clear() {
-	if (_filename) {
-		delete _filename;
-		_filename = nullptr;
-	}
-	if (_inStream) {
-		delete _inStream;
-		_inStream = nullptr;
-	}
-	if (_outFile) {
-		_outFile->write(_outStream->getData(), _outStream->size());
-		_outFile->finalize();
-		delete _outFile;
-		delete _outStream;
-		_outFile = nullptr;
-		_outStream = nullptr;
-	}
-}
-
-void FileObject::dispose() {
-	_disposed = true;
-	clear();
-}
-
-void FileIO::saveFileError() {
+FileIOError FileObject::open(const Common::String &origpath, const Common::String &mode) {
 	Common::SaveFileManager *saves = g_system->getSavefileManager();
-	if (saves->getError().getCode()) {
-		warning("SaveFileManager error %d: %s", saves->getError().getCode(), saves->getErrorDesc().c_str());
-		g_lingo->push(Datum(kErrorIO));
-	} else {
-		g_lingo->push(Datum(kErrorFileNotFound));
-	}
-}
-
-void FileIO::m_new(int nargs) {
-	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
-
-	Datum d2 = g_lingo->pop();
-	Datum d1 = g_lingo->pop();
-
-	Common::SaveFileManager *saves = g_system->getSavefileManager();
-	Common::String option = d1.asString();
-	Common::String path = d2.asString();
-	Common::String origpath = path;
+	Common::String path = origpath;
+	Common::String option = mode;
 	char dirSeparator = g_director->_dirSeparator;
 
 	Common::String prefix = g_director->getTargetName() + '-';
@@ -231,8 +228,7 @@ void FileIO::m_new(int nargs) {
 
 		GUI::FileBrowserDialog browser(nullptr, "txt", option.equalsIgnoreCase("write") ? GUI::kFBModeSave : GUI::kFBModeLoad, mask.c_str(), origpath.c_str());
 		if (browser.runModal() <= 0) {
-			g_lingo->push(Datum(kErrorFileNotFound));
-			return;
+			return kErrorFileNotFound;
 		}
 		path = browser.getResult();
 	} else if (!path.hasSuffixIgnoreCase(".txt")) {
@@ -247,28 +243,24 @@ void FileIO::m_new(int nargs) {
 		filename = prefix + filenameOrig;
 
 	if (option.equalsIgnoreCase("read")) {
-		me->_inStream = saves->openForLoading(filename);
-		if (!me->_inStream) {
+		_inStream = saves->openForLoading(filename);
+		if (!_inStream) {
 			// Maybe we're trying to read one of the game files
 			Common::File *f = new Common::File;
 			Common::Path location = findPath(origpath);
 			if (location.empty() || !f->open(location)) {
 				delete f;
-				saveFileError();
-				me->dispose();
-				return;
+				return saveFileError();
 			}
-			me->_inStream = f;
+			_inStream = f;
 		}
 	} else if (option.equalsIgnoreCase("write")) {
 		// OutSaveFile is not seekable so create a separate seekable stream
 		// which will be written to the _outFile upon disposal
-		me->_outFile = saves->openForSaving(filename, false);
-		me->_outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
-		if (!me->_outFile) {
-			saveFileError();
-			me->dispose();
-			return;
+		_outFile = saves->openForSaving(filename, false);
+		_outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+		if (!_outFile) {
+			return saveFileError();
 		}
 	} else if (option.equalsIgnoreCase("append")) {
 		Common::SeekableReadStream *inFile = saves->openForLoading(filename);
@@ -277,34 +269,142 @@ void FileIO::m_new(int nargs) {
 
 			if (!f->open(Common::Path(origpath, g_director->_dirSeparator))) {
 				delete f;
-				saveFileError();
-				me->dispose();
-				return;
+				return saveFileError();
 			}
 			inFile = f;
 		}
-		me->_outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+		_outStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
 		byte b = inFile->readByte();
 		while (!inFile->eos() && !inFile->err()) {
-			me->_outStream->writeByte(b);
+			_outStream->writeByte(b);
 			b = inFile->readByte();
 		}
 		delete inFile;
-		me->_outFile = saves->openForSaving(filename, false);
-		if (!me->_outFile) {
-			saveFileError();
-			me->dispose();
-			return;
+		_outFile = saves->openForSaving(filename, false);
+		if (!_outFile) {
+			return saveFileError();
 		}
 	} else {
 		error("Unsupported FileIO option: '%s'", option.c_str());
 	}
 
-	me->_filename = new Common::String(filename);
+	_filename = new Common::String(filename);
+	return kErrorNone;
+}
 
+void FileObject::clear() {
+	if (_filename) {
+		delete _filename;
+		_filename = nullptr;
+	}
+	if (_inStream) {
+		delete _inStream;
+		_inStream = nullptr;
+	}
+	if (_outFile) {
+		_outFile->write(_outStream->getData(), _outStream->size());
+		_outFile->finalize();
+		delete _outFile;
+		delete _outStream;
+		_outFile = nullptr;
+		_outStream = nullptr;
+	}
+}
+
+void FileObject::dispose() {
+	_disposed = true;
+	clear();
+}
+
+FileIOError FileObject::saveFileError() {
+	Common::SaveFileManager *saves = g_system->getSavefileManager();
+	if (saves->getError().getCode()) {
+		warning("SaveFileManager error %d: %s", saves->getError().getCode(), saves->getErrorDesc().c_str());
+		return kErrorIO;
+	} else {
+		return kErrorFileNotFound;
+	}
+}
+
+void FileIO::m_new(int nargs) {
+	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
+	if (nargs == 2) {
+		Datum d2 = g_lingo->pop();
+		Datum d1 = g_lingo->pop();
+
+		Common::String option = d1.asString();
+		Common::String path = d2.asString();
+		FileIOError result = me->open(path, option);
+		if (result != kErrorNone) {
+			me->dispose();
+			g_lingo->push(Datum(result));
+			return;
+		}
+	}
 	g_lingo->push(g_lingo->_state->me);
 }
 
+void FileIO::m_openFile(int nargs) {
+	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
+	Datum d1 = g_lingo->pop();
+	Datum d2 = g_lingo->pop();
+
+	int mode = d1.asInt();
+	Common::String option;
+	switch (mode) {
+	case 1:
+		option = "read";
+		break;
+	case 2:
+		option = "write";
+		break;
+	case 0:
+	default:
+		warning("FIXME: Mode %d not supported, falling back to read", mode);
+		option = "read";
+		break;
+	}
+	Common::String path = d2.asString();
+	FileIOError result = me->open(path, option);
+	g_lingo->push(Datum(result));
+}
+
+void FileIO::m_closeFile(int nargs) {
+	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
+
+	me->clear();
+	g_lingo->push(Datum(kErrorNone));
+}
+
+// FIXME: split out filename-to-savegame logic from open() so we can implement createFile
+XOBJSTUB(FileIO::m_createFile, 0);
+
+void FileIO::m_displayOpen(int nargs) {
+	Common::String prefix = g_director->getTargetName() + '-';
+	Common::String mask = prefix + "*.txt";
+
+	GUI::FileBrowserDialog browser(nullptr, "txt", GUI::kFBModeLoad, mask.c_str());
+	Datum result("");
+	if (browser.runModal() > 0) {
+		result = browser.getResult();
+	}
+	g_lingo->push(result);
+}
+
+void FileIO::m_displaySave(int nargs) {
+	Common::String prefix = g_director->getTargetName() + '-';
+	Common::String mask = prefix + "*.txt";
+
+	GUI::FileBrowserDialog browser(nullptr, "txt", GUI::kFBModeSave, mask.c_str());
+	Datum result("");
+	if (browser.runModal() > 0) {
+		result = browser.getResult();
+	}
+	g_lingo->push(result);
+}
+
+XOBJSTUB(FileIO::m_setFilterMask, 0)
+
 // Read
 
 void FileIO::m_readChar(int nargs) {
@@ -536,4 +636,6 @@ void FileIO::m_delete(int nargs) {
 // Non-standard extensions
 XOBJSTUBNR(FileIO::m_setOverrideDrive)
 
+XOBJSTUB(FileIO::m_getOSDirectory, "")
+
 } // End of namespace Director
diff --git a/engines/director/lingo/xlibs/fileio.h b/engines/director/lingo/xlibs/fileio.h
index ff45b15524d..c55ce57d2f2 100644
--- a/engines/director/lingo/xlibs/fileio.h
+++ b/engines/director/lingo/xlibs/fileio.h
@@ -62,7 +62,9 @@ public:
 	FileObject(const FileObject &obj);
 	~FileObject() override;
 
+	FileIOError open(const Common::String &origpath, const Common::String &mode);
 	void clear();
+	FileIOError saveFileError();
 	void dispose() override;
 };
 
@@ -74,7 +76,6 @@ namespace FileIO {
 	void close(ObjectType type);
 
 	bool charInMatchString(char ch, const Common::String &matchString);
-	void saveFileError();
 	void m_delete(int nargs);
 	void m_dispose(int nargs);
 	void m_error(int nargs);
@@ -97,6 +98,14 @@ namespace FileIO {
 
 	void m_setOverrideDrive(int nargs);
 
+	void m_closeFile(int nargs);
+	void m_createFile(int nargs);
+	void m_displayOpen(int nargs);
+	void m_displaySave(int nargs);
+	void m_openFile(int nargs);
+	void m_setFilterMask(int nargs);
+	void m_getOSDirectory(int nargs);
+
 } // End of namespace FileIO
 
 } // End of namespace Director


Commit: 84d009e6b8193e7e378fadc89e741c82e1c63566
    https://github.com/scummvm/scummvm/commit/84d009e6b8193e7e378fadc89e741c82e1c63566
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: LINGO: Implement b_member

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 7b71cdb3d1d..57cb12e5524 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -131,6 +131,7 @@ static BuiltinProto builtins[] = {
 		// play done													// D2
 	{ "preLoad",		LB::b_preLoad,		-1,0, 300, CBLTIN },	//		D3.1 c
 	{ "preLoadCast",	LB::b_preLoadCast,	-1,0, 300, CBLTIN },	//		D3.1 c
+	{ "preLoadMember",	LB::b_preLoadCast,	-1,0, 500, CBLTIN },	//				D5 c
 	{ "quit",			LB::b_quit,			0, 0, 200, CBLTIN },	// D2 c
 	{ "restart",		LB::b_restart,		0, 0, 200, CBLTIN },	// D2 c
 	{ "return",			LB::b_return,		0, 1, 200, CBLTIN },	// D2 f
@@ -188,6 +189,7 @@ static BuiltinProto builtins[] = {
 	{ "spriteBox",		LB::b_spriteBox,	5, 5, 200, CBLTIN },	// D2 c
 	{ "unLoad",			LB::b_unLoad,		0, 2, 300, CBLTIN },	//		D3.1 c
 	{ "unLoadCast",		LB::b_unLoadCast,	0, 2, 300, CBLTIN },	//		D3.1 c
+	{ "unLoadMember",	LB::b_unLoadCast,	0, 2, 500, CBLTIN },	//				D5 c
 	{ "updateStage",	LB::b_updateStage,	0, 0, 200, CBLTIN },	// D2 c
 	{ "zoomBox",		LB::b_zoomBox,		-1,0, 200, CBLTIN },	// D2 c
 	{"immediateSprite", LB::b_immediateSprite, -1, 0, 200, CBLTIN}, // D2 c
@@ -216,6 +218,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
+	{ "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
 	// Chunk operations
@@ -3216,6 +3219,38 @@ void LB::b_cast(int nargs) {
 	g_lingo->push(res);
 }
 
+void LB::b_member(int nargs) {
+	Movie *movie = g_director->getCurrentMovie();
+	CastMemberID res;
+	if (nargs == 1) {
+		Datum member = g_lingo->pop();
+		if (member.isNumeric()) {
+			res = movie->getCastMemberIDByMember(member.asInt());
+		} else {
+			res = movie->getCastMemberIDByName(member.asString());
+		}
+	} else if (nargs == 2) {
+		Datum library = g_lingo->pop();
+		Datum member = g_lingo->pop();
+		int libId = -1;
+		if (library.isNumeric()) {
+			libId = library.asInt();
+		} else {
+			libId = movie->getCastLibIDByName(library.asString());
+		}
+		if (member.isNumeric()) {
+			res = CastMemberID(member.asInt(), libId);
+		} else {
+			res = movie->getCastMemberIDByNameAndType(member.asString(), libId, kCastTypeAny);
+		}
+	}
+	if (!movie->getCastMember(res)) {
+		g_lingo->lingoError("No match found for cast member");
+		return;
+	}
+	g_lingo->push(res);
+}
+
 void LB::b_script(int nargs) {
 	Datum d = g_lingo->pop();
 	// FIXME: Check with later versions of director
diff --git a/engines/director/lingo/lingo-builtins.h b/engines/director/lingo/lingo-builtins.h
index 53df1900aad..ad6eee2f40d 100644
--- a/engines/director/lingo/lingo-builtins.h
+++ b/engines/director/lingo/lingo-builtins.h
@@ -167,6 +167,7 @@ void b_offsetRect(int nargs);
 void b_rect(int nargs);
 void b_union(int nargs);
 
+void b_member(int nargs);
 void b_window(int nargs);
 
 void b_beep(int nargs);
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index e8965fef860..6dfea889736 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -177,6 +177,7 @@ void Movie::loadCastLibMapping(Common::SeekableReadStreamEndian &stream) {
 			cast = new Cast(this, libId, false, isExternal);
 			_casts.setVal(libId, cast);
 		}
+		_castNames[name] = libId;
 		cast->setArchive(castArchive);
 	}
 	return;
@@ -436,6 +437,40 @@ bool Movie::eraseCastMember(CastMemberID memberID) {
 	return false;
 }
 
+CastMemberID Movie::getCastMemberIDByMember(int memberID) {
+	CastMemberID result(-1, 0);
+	// Search all cast libraries for a match
+	for (auto &cast : _casts) {
+		CastMember *member = cast._value->getCastMember(memberID);
+		if (member) {
+			result = CastMemberID(member->getID(), cast._key);
+			break;
+		}
+	}
+	if (result.member == -1 && _sharedCast) {
+		CastMember *member = _sharedCast->getCastMember(memberID);
+		if (member)
+			result = CastMemberID(member->getID(), DEFAULT_CAST_LIB);
+	}
+	if (result.member == -1) {
+		warning("Movie::getCastMemberIDByMemberID: No match found for member ID %d", memberID);
+	}
+	return result;
+}
+
+int Movie::getCastLibIDByName(const Common::String &name) {
+	for (auto &it : _castNames) {
+		if (it._key.equalsIgnoreCase(name)) {
+			return it._value;
+		}
+	}
+	return -1;
+}
+
+CastMemberID Movie::getCastMemberIDByName(const Common::String &name) {
+	return getCastMemberIDByNameAndType(name, 0, kCastTypeAny);
+}
+
 CastMemberID Movie::getCastMemberIDByNameAndType(const Common::String &name, int castLib, CastType type) {
 	CastMemberID result(-1, 0);
 	if (_casts.contains(castLib)) {
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 633912a5537..cf42210267f 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -110,6 +110,9 @@ public:
 	CastMember *getCastMember(CastMemberID memberID);
 	CastMember *createOrReplaceCastMember(CastMemberID memberID, CastMember *cast);
 	bool eraseCastMember(CastMemberID memberID);
+	CastMemberID getCastMemberIDByMember(int memberID);
+	int getCastLibIDByName(const Common::String &name);
+	CastMemberID getCastMemberIDByName(const Common::String &name);
 	CastMemberID getCastMemberIDByNameAndType(const Common::String &name, int castLib, CastType type);
 	CastMemberInfo *getCastMemberInfo(CastMemberID memberID);
 	const Stxt *getStxt(CastMemberID memberID);
@@ -188,6 +191,7 @@ private:
 	Lingo *_lingo;
 	Cast *_cast;
 	Common::HashMap<int, Cast *> _casts;
+	Common::HashMap<Common::String, int, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _castNames;
 	Score *_score;
 
 	uint32 _flags;


Commit: 2ba42271d73ef08275299337078ab19ed003b670
    https://github.com/scummvm/scummvm/commit/2ba42271d73ef08275299337078ab19ed003b670
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add initial RTE loading support

Changed paths:
  A engines/director/rte.cpp
  A engines/director/rte.h
    engines/director/cast.cpp
    engines/director/cast.h
    engines/director/castmember/text.cpp
    engines/director/castmember/text.h
    engines/director/module.mk


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 9a4bc799312..79610b7d1db 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -33,6 +33,7 @@
 #include "director/director.h"
 #include "director/cast.h"
 #include "director/movie.h"
+#include "director/rte.h"
 #include "director/score.h"
 #include "director/sound.h"
 #include "director/sprite.h"
@@ -76,7 +77,6 @@ Cast::Cast(Movie *movie, uint16 castLibID, bool isShared, bool isExternal) {
 
 	_stageColor = 0;
 
-	_loadedStxts = nullptr;
 	_loadedCast = nullptr;
 
 	_defaultPalette = CastMemberID(-1, -1);
@@ -84,9 +84,8 @@ Cast::Cast(Movie *movie, uint16 castLibID, bool isShared, bool isExternal) {
 }
 
 Cast::~Cast() {
-	if (_loadedStxts)
-		for (auto &it : *_loadedStxts)
-			delete it._value;
+	for (auto &it : _loadedStxts)
+		delete it._value;
 
 	if (_loadedCast)
 		for (auto &it : *_loadedCast)
@@ -104,7 +103,15 @@ Cast::~Cast() {
 	for (auto &it : _fontMap)
 		delete it._value;
 
-	delete _loadedStxts;
+	for (auto &it : _loadedRTE0s)
+		delete it._value;
+
+	for (auto &it : _loadedRTE1s)
+		delete it._value;
+
+	for (auto &it : _loadedRTE2s)
+		delete it._value;
+
 	delete _loadedCast;
 	delete _lingoArchive;
 }
@@ -169,8 +176,8 @@ CastMemberInfo *Cast::getCastMemberInfo(int castId) {
 const Stxt *Cast::getStxt(int castId) {
 	const Stxt *result = nullptr;
 
-	if (_loadedStxts->contains(castId)) {
-		result = _loadedStxts->getVal(castId);
+	if (_loadedStxts.contains(castId)) {
+		result = _loadedStxts.getVal(castId);
 	}
 	return result;
 }
@@ -603,10 +610,8 @@ void Cast::loadCast() {
 	Common::Array<uint16> stxt = _castArchive->getResourceIDList(MKTAG('S','T','X','T'));
 	debugC(2, kDebugLoading, "****** Loading %d STXT resources", stxt.size());
 
-	_loadedStxts = new Common::HashMap<int, const Stxt *>();
-
 	for (auto &iterator : stxt) {
-		_loadedStxts->setVal(iterator - _castIDoffset,
+		_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;
@@ -619,7 +624,36 @@ void Cast::loadCast() {
 			loadScriptV2(*(r = _castArchive->getResource(MKTAG('S','T','X','T'), iterator)), iterator - _castIDoffset);
 			delete r;
 		}
+	}
+
+	Common::Array<uint16> rte0 = _castArchive->getResourceIDList(MKTAG('R','T','E','0'));
+	debugC(2, kDebugLoading, "****** Loading %d RTE0 resources", rte0.size());
 
+	for (auto &iterator : rte0) {
+		r = _castArchive->getResource(MKTAG('R','T','E','0'), iterator);
+		debugC(3, kDebugText, "RTE0: id %d", iterator - _castIDoffset);
+		_loadedRTE0s.setVal(iterator, new RTE0(this, *r));
+		delete r;
+	}
+
+	Common::Array<uint16> rte1 = _castArchive->getResourceIDList(MKTAG('R','T','E','1'));
+	debugC(2, kDebugLoading, "****** Loading %d RTE1 resources", rte1.size());
+
+	for (auto &iterator : rte1) {
+		r = _castArchive->getResource(MKTAG('R','T','E','1'), iterator);
+		debugC(3, kDebugText, "RTE1: id %d", iterator - _castIDoffset);
+		_loadedRTE1s.setVal(iterator, new RTE1(this, *r));
+		delete r;
+	}
+
+	Common::Array<uint16> rte2 = _castArchive->getResourceIDList(MKTAG('R','T','E','2'));
+	debugC(2, kDebugLoading, "****** Loading %d RTE2 resources", rte2.size());
+
+	for (auto &iterator : rte2) {
+		r = _castArchive->getResource(MKTAG('R','T','E','2'), iterator);
+		debugC(3, kDebugText, "RTE2: id %d", iterator - _castIDoffset);
+		_loadedRTE2s.setVal(iterator, new RTE2(this, *r));
+		delete r;
 	}
 }
 
diff --git a/engines/director/cast.h b/engines/director/cast.h
index 45d84cc42a0..42ded68237d 100644
--- a/engines/director/cast.h
+++ b/engines/director/cast.h
@@ -40,6 +40,9 @@ class Lingo;
 struct LingoArchive;
 struct Resource;
 class Stxt;
+class RTE0;
+class RTE1;
+class RTE2;
 class BitmapCastMember;
 class FilmLoopCastMember;
 class ScriptCastMember;
@@ -143,7 +146,10 @@ public:
 	bool _isProtected;
 
 	Common::HashMap<int, CastMember *> *_loadedCast;
-	Common::HashMap<int, const Stxt *> *_loadedStxts;
+	Common::HashMap<int, const Stxt *> _loadedStxts;
+	Common::HashMap<int, const RTE0 *> _loadedRTE0s;
+	Common::HashMap<int, const RTE1 *> _loadedRTE1s;
+	Common::HashMap<int, const RTE2 *> _loadedRTE2s;
 	uint16 _castIDoffset;
 	uint16 _castArrayStart;
 	uint16 _castArrayEnd;
diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 34051f035b1..668965e36fd 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -420,9 +420,6 @@ void TextCastMember::load() {
 	if (_loaded)
 		return;
 
-	if (!_cast->_loadedStxts)
-		return;
-
 	uint stxtid = 0;
 	if (_cast->_version >= kFileVer400) {
 		for (auto &it : _children) {
@@ -438,8 +435,8 @@ void TextCastMember::load() {
 		stxtid = _castId;
 	}
 
-	if (_cast->_loadedStxts->contains(stxtid)) {
-		const Stxt *stxt = _cast->_loadedStxts->getVal(stxtid);
+	if (_cast->_loadedStxts.contains(stxtid)) {
+		const Stxt *stxt = _cast->_loadedStxts.getVal(stxtid);
 		importStxt(stxt);
 		_size = stxt->_size;
 	} else {
@@ -719,18 +716,43 @@ RTECastMember::RTECastMember(Cast *cast, uint16 castId, Common::SeekableReadStre
 	_type = kCastRTE;
 }
 
-void RTECastMember::loadChunks() {
-	//TODO: Actually load RTEs correctly, don't just make fake STXT.
-#if 0
-	Common::SeekableReadStream *rte1 = _movieArchive->getResource(res->children[child].tag, res->children[child].index);
-	byte *buffer = new byte[rte1->size() + 2];
-	rte1->read(buffer, rte1->size());
-	buffer[rte1->size()] = '\n';
-	buffer[rte1->size() + 1] = '\0';
-	_loadedText->getVal(id)->importRTE(buffer);
-
-	delete rte1;
-#endif
+void RTECastMember::load() {
+	if (_loaded)
+		return;
+
+	uint rte0id = 0;
+	uint rte1id = 0;
+	uint rte2id = 0;
+	for (auto &it : _children) {
+		if (it.tag == MKTAG('R', 'T', 'E', '0')) {
+			rte0id = it.index;
+			break;
+		} else if (it.tag == MKTAG('R', 'T', 'E', '1')) {
+			rte1id = it.index;
+			break;
+		} else if (it.tag == MKTAG('R', 'T', 'E', '2')) {
+			rte2id = it.index;
+			break;
+		}
+	}
+
+	if (_cast->_loadedRTE0s.contains(rte0id)) {
+		// TODO: Copy the formatted text data
+	} else {
+		warning("RTECastMember::load(): rte0tid %i isn't loaded", rte0id);
+	}
+	if (_cast->_loadedRTE1s.contains(rte1id)) {
+		// TODO: Copy the plain text data
+	} else {
+		warning("RTECastMember::load(): rte1tid %i isn't loaded", rte1id);
+	}
+	if (_cast->_loadedRTE2s.contains(rte2id)) {
+		// TODO: Copy the bitmap data
+	} else {
+		warning("RTECastMember::load(): rte2tid %i isn't loaded", rte2id);
+	}
+
+	_loaded = true;
 }
 
 }
diff --git a/engines/director/castmember/text.h b/engines/director/castmember/text.h
index 0fe628a533d..66ed04c976c 100644
--- a/engines/director/castmember/text.h
+++ b/engines/director/castmember/text.h
@@ -103,6 +103,7 @@ public:
 	RTECastMember(Cast *cast, uint16 castId, Common::SeekableReadStreamEndian &stream, uint16 version);
 
 	void loadChunks();
+	void load() override;
 };
 
 } // End of namespace Director
diff --git a/engines/director/module.mk b/engines/director/module.mk
index bc87cdd11cf..258fc76a0a0 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS = \
 	movie.o \
 	picture.o \
 	resource.o \
+	rte.o \
 	score.o \
 	sound.o \
 	sprite.o \
diff --git a/engines/director/rte.cpp b/engines/director/rte.cpp
new file mode 100644
index 00000000000..5f0c347370b
--- /dev/null
+++ b/engines/director/rte.cpp
@@ -0,0 +1,79 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/stream.h"
+#include "common/substream.h"
+
+#include "director/director.h"
+#include "director/cast.h"
+#include "director/rte.h"
+
+namespace Director {
+
+RTE0::RTE0(Cast *cast, Common::SeekableReadStreamEndian &stream) : _cast(cast) {
+	data.resize(stream.size(), 0);
+	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());
+}
+
+RTE2::RTE2(Cast *cast, Common::SeekableReadStreamEndian &stream) : _cast(cast) {
+	stream.hexdump(stream.size());
+	width = stream.readUint16BE();
+	height = stream.readUint16BE();
+	bpp = stream.readUint16BE();
+	int checkMax = (1 << bpp) - 1;
+	debugC(5, kDebugLoading, "RTE2: width: %d, height: %d, bpp: %d", width, height, bpp);
+	alphaMap.resize(width*height, 0);
+	for (int y = 0; y < height; y++) {
+		for (int x = 0; x < width;) {
+			uint32 pos = stream.pos();
+			byte check = stream.readByte();
+			if (check == 0x1f) {
+				debugC(9, kDebugLoading, "(%d, %d): %x -> color %d %d %d", x, y, pos, stream.readByte(), stream.readByte(), stream.readByte());
+				continue;
+			}
+			if (check == 0 || check == checkMax) {
+				byte count = stream.readByte();
+				debugC(9, kDebugLoading, "(%d, %d): %x -> %02x %02x", x, y, pos, check, count);
+				if (count == 0x00 && check == 0x00) {
+					// end of line
+					break;
+				}
+				for (byte j = 0; j < count; j++) {
+					alphaMap[width*y + x] = check;
+					x += 1;
+					if (x >= width)
+						break;
+				}
+			} else {
+				debugC(9, kDebugLoading, "(%d, %d): %x -> %02x", x, y, pos, check);
+				alphaMap[width*y + x] = check;
+				x += 1;
+			}
+		}
+	}
+}
+
+} // End of namespace Director
diff --git a/engines/director/rte.h b/engines/director/rte.h
new file mode 100644
index 00000000000..a16dacae312
--- /dev/null
+++ b/engines/director/rte.h
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_RTE_H
+#define DIRECTOR_RTE_H
+
+#include "common/array.h"
+#include "common/stream.h"
+namespace Common {
+class SeekableReadStreamEndian;
+}
+
+namespace Director {
+
+class Cast;
+
+class RTE0 {
+public:
+	RTE0(Cast *cast, Common::SeekableReadStreamEndian &stream);
+
+	Cast *_cast;
+	Common::Array<byte> data;
+};
+
+class RTE1 {
+public:
+	RTE1(Cast *cast, Common::SeekableReadStreamEndian &stream);
+
+	Cast *_cast;
+	Common::Array<byte> data;
+};
+
+class RTE2 {
+public:
+	RTE2(Cast *cast, Common::SeekableReadStreamEndian &stream);
+
+	Cast *_cast;
+	uint16 width;
+	uint16 height;
+	uint32 bpp;
+	Common::Array<byte> alphaMap;
+};
+
+} // End of namespace Director
+
+#endif


Commit: 5d74952707ecf9be9eb2ef76e789965e82c320d5
    https://github.com/scummvm/scummvm/commit/5d74952707ecf9be9eb2ef76e789965e82c320d5
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add "type of member" alias added in D5

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


diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 63529dd778c..7e199ca608c 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -125,6 +125,7 @@ bool CastMember::hasField(int field) {
 	case kThePurgePriority:
 	case kTheScriptText:
 	case kTheSize:
+	case kTheType:
 	case kTheWidth:
 		return true;
 	default:
@@ -145,6 +146,7 @@ Datum CastMember::getField(int field) {
 		d = (int)getBackColor();
 		break;
 	case kTheCastType:
+	case kTheType:
 		d.type = SYMBOL;
 		d.u.s = new Common::String(castType2str(_type));
 		break;
@@ -204,6 +206,7 @@ bool CastMember::setField(int field, const Datum &d) {
 		_cast->getCastMember(_castId)->setBackColor(d.asInt());
 		return true;
 	case kTheCastType:
+	case kTheType:
 		warning("BUILDBOT: CastMember::setField(): Attempt to set read-only field %s of cast %d", g_lingo->entity2str(field), _castId);
 		return false;
 	case kTheFileName:
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 02414c85a74..8310bcde1a1 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -212,6 +212,7 @@ TheEntityField fields[] = {
 	{ kTheCast,		"purgePriority",kThePurgePriority,400 },//				D4 p // 0 Never purge, 1 Purge Last, 2 Purge next, 2 Purge normal
 	{ kTheCast,		"scriptText",	kTheScriptText,	400 },//				D4 p
 	{ kTheCast,		"size",			kTheSize,		300 },//		D3.1 p
+	{ kTheCast,		"type",			kTheType,		500 },//					D5 p
 	{ kTheCast,		"width",		kTheWidth,		400 },//				D4 p
 
 	// Digital video fields
@@ -1995,6 +1996,7 @@ void Lingo::getObjectProp(Datum &obj, Common::String &propName) {
 				emptyAllowed = true;
 				switch (_theEntityFields[key]->field) {
 				case kTheCastType:
+				case kTheType:
 					d = Datum("empty");
 					d.type = SYMBOL;
 					break;


Commit: a984f36fc26f4bcfbf0bed0ee8b02a1863a269ca
    https://github.com/scummvm/scummvm/commit/a984f36fc26f4bcfbf0bed0ee8b02a1863a269ca
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add "memberNum of sprite" alias added in D5

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


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 5feeebd3c83..e6a1d8d9d43 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -212,7 +212,7 @@ static LingoV4TheEntity lingoV4TheEntity[] = {
 	{ 0x06, 0x20, kTheSprite,			kTheScoreColor,		true, kTEAItemId },
 	{ 0x06, 0x21, kTheSprite,			kTheLoc,			true, kTEAItemId },
 	{ 0x06, 0x22, kTheSprite,			kTheRect,			true, kTEAItemId },
-	{ 0x06, 0x23, kTheSprite,			kTheMemberNum,		true, kTEAItemId },
+	{ 0x06, 0x23, kTheSprite,			kTheMemberNum,		true, kTEAItemId }, // D5
 
 	{ 0x07, 0x01, kTheBeepOn,			kTheNOField,		true, kTEANOArgs },
 	{ 0x07, 0x02, kTheButtonStyle,		kTheNOField,		true, kTEANOArgs },
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 8310bcde1a1..3b3d95a3096 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -183,6 +183,7 @@ TheEntityField fields[] = {
 	{ kTheSprite,	"loc",			kTheLoc,		400 },//				D4 p ???
 	{ kTheSprite,	"locH",			kTheLocH,		200 },// D2 p
 	{ kTheSprite,	"locV",			kTheLocV,		200 },// D2 p
+	{ kTheSprite,	"memberNum",	kTheMemberNum,	500 },//					D5 p
 	{ kTheSprite,	"moveableSprite",kTheMoveableSprite,400 },//			D4 p
 	{ kTheSprite,	"pattern",		kThePattern,	200 },// D2 p
 	{ kTheSprite,	"puppet",		kThePuppet,		200 },// D2 p
@@ -1311,7 +1312,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
 		d = channel->getBbox().bottom;
 		break;
 	case kTheCastNum:
-		// TODO: How is this handled with multiple casts in D5?
+	case kTheMemberNum:
 		d = sprite->_castId.member;
 		break;
 	case kTheConstraint:
@@ -1474,6 +1475,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 		}
 		break;
 	case kTheCastNum:
+	case kTheMemberNum:
 		{
 			CastMemberID castId = d.asMemberID();
 			CastMember *castMember = movie->getCastMember(castId);


Commit: bf88a47208824e51121dd2a0eec31f2557477e48
    https://github.com/scummvm/scummvm/commit/bf88a47208824e51121dd2a0eec31f2557477e48
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add "the rollOver" entity added in D5

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


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 3b3d95a3096..bf69373828c 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -126,6 +126,7 @@ TheEntity entities[] = {
 	{ kTheResult,			"result",			false, 200, true },	// D2 f
 	{ kTheRightMouseDown,	"rightMouseDown",	false, 500, true },	//					D5 f
 	{ kTheRightMouseUp,		"rightMouseUp",		false, 500, true },	//					D5 f
+	{ kTheRollOver,			"rollOver",			false, 500, true },	//					D5 f, undocumented
 	{ kTheRomanLingo,		"romanLingo",		false, 300, false },	//		D3.1 p
 	{ kTheScummvmVersion,	"scummvmVersion",	false, 200, true }, // 					ScummVM only
 	{ kTheSearchCurrentFolder,"searchCurrentFolder",false,400, true },//			D4 f
@@ -769,6 +770,9 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
 	case kTheRightMouseUp:
 		d = g_system->getEventManager()->getButtonState() & (1 << Common::MOUSE_BUTTON_RIGHT) ? 0 : 1;
 		break;
+	case kTheRollOver:
+		d = score->getSpriteIDFromPos(g_director->getCurrentWindow()->getMousePos());
+		break;
 	case kTheRomanLingo:
 		d = g_lingo->_romanLingo;
 		warning("BUILDBOT: the romanLingo is get, value is %d", g_lingo->_romanLingo);
diff --git a/engines/director/lingo/lingo-the.h b/engines/director/lingo/lingo-the.h
index 70e9162a6ec..62764afd0b0 100644
--- a/engines/director/lingo/lingo-the.h
+++ b/engines/director/lingo/lingo-the.h
@@ -110,6 +110,7 @@ enum TheEntityType {
 	kTheResult,
 	kTheRightMouseDown,
 	kTheRightMouseUp,
+	kTheRollOver,
 	kTheRomanLingo,
 	kTheScummvmVersion,			// set the Director version via lingo in tests
 	kTheSearchCurrentFolder,


Commit: 7daf4bde4310c05cf4ceb393cfff8f62ffe0f095
    https://github.com/scummvm/scummvm/commit/7daf4bde4310c05cf4ceb393cfff8f62ffe0f095
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Fix encoding bugs in Cast::getVideoPath()

Fixes video path fetching in Director 3 movies which use MooV stubs
to link to a QuickTime filename with Japanese characters (e.g.
intelligentnote demo).

Fixes video path fetching where the directory in the castInfo ends with
a path separator (e.g. criticalpath).

Changed paths:
    engines/director/cast.cpp


diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 79610b7d1db..05a75e780c0 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -694,13 +694,14 @@ Common::String Cast::getVideoPath(int castId) {
 
 		Common::String filename = _castsInfo[castId]->fileName;
 		Common::String directory = _castsInfo[castId]->directory;
-
-		res = directory + g_director->_dirSeparator + filename;
+		if (directory.lastChar() != g_director->_dirSeparator)
+			directory += g_director->_dirSeparator;
+		res = directory + filename;
 	} else {
 		Video::QuickTimeDecoder qt;
 		qt.loadStream(videoData);
 		videoData = nullptr;
-		res = qt.getAliasPath();
+		res = decodeString(qt.getAliasPath());
 		if (res.empty()) {
 			warning("STUB: Cast::getVideoPath(%d): unsupported non-alias MooV block found", castId);
 		}


Commit: 3123ea69b4c48e5fbe69d592eb38eb2889d4b10d
    https://github.com/scummvm/scummvm/commit/3123ea69b4c48e5fbe69d592eb38eb2889d4b10d
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Round up fractional tick counts in DigitalVideoCastMember

Fixes scene changes in Critical Path, which are based on an embedded
list of video durations.

Changed paths:
    engines/director/castmember/digitalvideo.cpp


diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index 41db77943b3..93d050719da 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -269,8 +269,8 @@ uint DigitalVideoCastMember::getDuration() {
 uint DigitalVideoCastMember::getMovieCurrentTime() {
 	if (!_video)
 		return 0;
-
-	int stamp = MIN<int>(_video->getTime() * 60 / 1000, getMovieTotalTime());
+	int ticks = 1 + ((_video->getTime() * 60 - 1)/1000);
+	int stamp = MIN<int>(ticks, getMovieTotalTime());
 
 	return stamp;
 }
@@ -279,9 +279,8 @@ uint DigitalVideoCastMember::getMovieTotalTime() {
 	if (!_video)
 		return 0;
 
-	int stamp = _video->getDuration().msecs() * 60 / 1000;
-
-	return stamp;
+	int ticks = 1 + ((_video->getDuration().msecs() * 60 - 1)/1000);
+	return ticks;
 }
 
 void DigitalVideoCastMember::seekMovie(int stamp) {


Commit: bb530a8b6d6714594a1b9dd448fcef2ce06278fa
    https://github.com/scummvm/scummvm/commit/bb530a8b6d6714594a1b9dd448fcef2ce06278fa
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add Mars Attacks Mission Disks to detection

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index e52b69027bb..2e5616e0dce 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -280,6 +280,9 @@ static const PlainGameDescriptor directorGames[] = {
 	{ "maisybday",			"Happy Birthday, Maisy!" },
 	{ "majestic",			"Majestic Part I: Alien Encounter" },
 	{ "maniacsports",		"Maniac Sports" },
+	{ "marsp1",				"Mars Attacks Mission Disk 1 - Mission of Doom" },
+	{ "marsp2",				"Mars Attacks Mission Disk 2 - Martian Emergency!" },
+	{ "marsp3",				"Mars Attacks Mission Disk 3 - Attack of the Killer Bugs" },
 	{ "martian",			"Ray Bradbury's The Martian Chronicles Adventure Game" },
 	{ "mask",				"The Mask: The Origin" },
 	{ "mastermansion",		"Masterpiece Mansion" },
@@ -4369,28 +4372,28 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINGAME2("hunchback", "", "HUNCH.EXE",			   "t:27d1a388006a4b2d63b1810248a55b14", 25837061,
 							  "QTMOVIES/HUNCHIN3.MOV", "t:f3ce12ed7e2cd0a52a957388c074e916", 384506, 404),
 
-	WINGAME2("id4p1", "", "SUPREME.EXE", "629eb9a5d991a2dbe380804e8c37043a", 1664965,
-						  "ALIEN.ICO",	 "fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
-	WINGAME2("id4p2", "", "SCIENCE.EXE", "812a4b81b70e61e547c14dbbd507b402", 1766499,
-						  "ALIEN.ICO",	 "fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
-	WINGAME2("id4p3", "", "WARRIOR.EXE", "387245092ce0583c6fd0c54000b1502a", 1751593,
-						  "ALIEN.ICO",	 "fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
-	WINGAME2("id4p4", "", "NAV.EXE", 	 "29de2d1fd34029b3c97ce852a7fc665e", 1834037,
-						  "ALIEN.ICO",	 "fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
-	WINGAME2("id4p5", "", "STEVE.EXE",   "14f19b724dd6361e4bf3cfddbac87d3f", 1797301,
-						  "F18.ICO",	 "02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
-	WINGAME2("id4p6", "", "DAVE.EXE", 	 "237f9db2ea9a38fa6f7292974539f494", 1774167,
-						  "F18.ICO",	 "02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
-	WINGAME2("id4p7", "", "PREZ.EXE",	 "e7d03a6d749d65dbcea7171ec4627e9c", 1666293,
-						  "F18.ICO",	 "02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
-	WINGAME2("id4p8", "", "ALIEN_F.EXE", "ee2eb92900d515ed7872c57f3b89a408", 1754975,
-						  "ID4.ICO",	 "309dc88201ab742ffeb3e77f391cef3d", 766, 404),
-	WINGAME2("id4p9", "", "F18.EXE",	 "7a0292909a5103c89297c40cce1d836c", 1691893,
-						  "F18.ICO",	 "02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
-	WINGAME2("id4p10", "", "BOMBER.EXE", "17758a9f425f7f3e7a926951e6c770f4", 1844189,
-						   "ID4.ICO",	 "309dc88201ab742ffeb3e77f391cef3d", 766, 404),
-	WINGAME2("id4p11", "", "AREA51.EXE", "78be40f9c7e8e1770c388cc16a522aaf", 1776077,
-						   "ID4.ICO",	 "309dc88201ab742ffeb3e77f391cef3d", 766, 404),
+	WINGAME2("id4p1", "", "SUPREME.EXE", "t:c162bb07e8b76d4d4cd5f99d4b5fb6e7", 1664965,
+						  "ALIEN.ICO",	 "f:fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
+	WINGAME2("id4p2", "", "SCIENCE.EXE", "t:40ccf3e0343e346192bb770ac168cee9", 1766499,
+						  "ALIEN.ICO",	 "f:fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
+	WINGAME2("id4p3", "", "WARRIOR.EXE", "t:34572ba5f4c4bc36d87cb8a7eab17faa", 1751593,
+						  "ALIEN.ICO",	 "f:fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
+	WINGAME2("id4p4", "", "NAV.EXE", 	 "t:32f35ec5f7c43a61ac6c8b1d0b1e49d9", 1834037,
+						  "ALIEN.ICO",	 "f:fcd97560b8b3f7404f9119bc06bbd5b5", 766, 404),
+	WINGAME2("id4p5", "", "STEVE.EXE",   "t:c22b1fa84403628f538417f7485642e3", 1797301,
+						  "F18.ICO",	 "f:02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
+	WINGAME2("id4p6", "", "DAVE.EXE", 	 "t:6c2cbc6c565d2d00acd2cb33bd0f25c6", 1774167,
+						  "F18.ICO",	 "f:02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
+	WINGAME2("id4p7", "", "PREZ.EXE",	 "t:64e1740a10d009cb20cb9afef84e8ff1", 1666293,
+						  "F18.ICO",	 "f:02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
+	WINGAME2("id4p8", "", "ALIEN_F.EXE", "t:45b01a105047fad7a7cdceee932615c5", 1754975,
+						  "ID4.ICO",	 "f:309dc88201ab742ffeb3e77f391cef3d", 766, 404),
+	WINGAME2("id4p9", "", "F18.EXE",	 "t:001a71636c9d791b0e12538914713cea", 1691893,
+						  "F18.ICO",	 "f:02a3ae4b3fc4d7dce93542f2345f178d", 766, 404),
+	WINGAME2("id4p10", "", "BOMBER.EXE", "t:dc5ec22e179b88de9ad08b327eeac9b8", 1844189,
+						   "ID4.ICO",	 "f:309dc88201ab742ffeb3e77f391cef3d", 766, 404),
+	WINGAME2("id4p11", "", "AREA51.EXE", "t:0be4cde7353b488bf7a8daaafdfd1321", 1776077,
+						   "ID4.ICO",	 "f:309dc88201ab742ffeb3e77f391cef3d", 766, 404),
 
 	// From More MacCube, disc 3
 	MACGAME1("illusions", "", "ILLUSIONS", "7fd44b6dffa0ea0402eaed4c3769b39b", 285282, 404),
@@ -4724,6 +4727,13 @@ static const DirectorGameDescription gameDescriptions[] = {
 
 	MACGAME1("marathonsecrets", "v1.0", "Marathon Secrets 1.0", "cdb27c916044ae4dceb4b7326063fa03", 301669, 400),
 
+	WINGAME2("marsp1", "", "MARS1.EXE", "t:56ba221b8519c71a9caee102932dc87e", 1775689,
+						   "MARZ.ICO", "f:d34d58615d3d1da0a882366fa626e150", 766, 404),
+	WINGAME2("marsp2", "", "MARS2.EXE", "t:fab984e57ad1e46f4ef2a011e2e1795d", 1771125,
+						   "MARZ.ICO", "f:d34d58615d3d1da0a882366fa626e150", 766, 404),
+	WINGAME2("marsp3", "", "MARS3.EXE", "t:a6eeddd0fd1fb3ffa39ad58cd154ddcc", 1630325,
+						   "MARZ.ICO", "f:d34d58615d3d1da0a882366fa626e150", 766, 404),
+
 	// Windows version on same disc is D3
 	MACGAME1("mask", "", "The Mask", "32a48ccef630fd453ac3501f72474545", 291308, 403),
 


Commit: f14649d5a40d3ba09aaeaa25022fb28e50ccf340
    https://github.com/scummvm/scummvm/commit/f14649d5a40d3ba09aaeaa25022fb28e50ccf340
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Set scriptId on sprites even in puppet mode

Previously, when loading a frame, sprite data would be skipped entirely
if the sprite channel was in puppet mode. This is mostly correct, -except- for
sprite scriptIds: these are always determined by the score.

Unfortunately this means checking for puppet mode in every branch of the
switch statement, which is a bit tedious, but basically what we need to
do anyway for D6 autopuppet mode.

Fixes clickable hotspots in Team Xtreme: Operation Weather Disaster.

Changed paths:
    engines/director/frame.cpp


diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index 04ca634ed7d..ded5cc7bdc0 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -276,11 +276,6 @@ void Frame::readSpriteD2(Common::MemoryReadStreamEndian &stream, uint16 offset,
 
 	Sprite &sprite = *_sprites[spritePosition + 1];
 
-	if (sprite._puppet) {
-		stream.skip(size);
-		return;
-	}
-
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
@@ -299,51 +294,89 @@ void readSpriteDataD2(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 			sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
 			break;
 		case 1:
-			sprite._spriteType = (SpriteType)stream.readByte();
-
-			sprite._enabled = sprite._spriteType != kInactiveSprite;
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._spriteType = (SpriteType)stream.readByte();
+				sprite._enabled = sprite._spriteType != kInactiveSprite;
+			}
 			break;
 		case 2:
-			// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
-			sprite._foreColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
+				sprite._foreColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
+			}
 			break;
 		case 3:
-			// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
-			sprite._backColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				// Normalize D2 and D3 colors from -128 ... 127 to 0 ... 255.
+				sprite._backColor = g_director->transformColor((128 + stream.readByte()) & 0xff);
+			}
 			break;
 		case 4:
-			sprite._thickness = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._thickness = stream.readByte();
+			}
 			break;
 		case 5:
-			sprite._inkData = stream.readByte();
-
-			sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
-			if (sprite._inkData & 0x40)
-				sprite._trails = 1;
-			else
-				sprite._trails = 0;
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._inkData = stream.readByte();
 
+				sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+				if (sprite._inkData & 0x40)
+					sprite._trails = 1;
+				else
+					sprite._trails = 0;
+			}
 			break;
 		case 6:
-			if (sprite.isQDShape()) {
-				sprite._pattern = stream.readUint16();
-				sprite._castId = CastMemberID(0, 0);
+			if (sprite._puppet) {
+				stream.readUint16();
 			} else {
-				sprite._pattern = 0;
-				sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
+				if (sprite.isQDShape()) {
+					sprite._pattern = stream.readUint16();
+					sprite._castId = CastMemberID(0, 0);
+				} else {
+					sprite._pattern = 0;
+					sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
+				}
 			}
 			break;
 		case 8:
-			sprite._startPoint.y = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.y = (int16)stream.readUint16();
+			}
 			break;
 		case 10:
-			sprite._startPoint.x = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.x = (int16)stream.readUint16();
+			}
 			break;
 		case 12:
-			sprite._height = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._height = (int16)stream.readUint16();
+			}
 			break;
 		case 14:
-			sprite._width = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._width = (int16)stream.readUint16();
+			}
 			break;
 		default:
 			// This means that a `case` label has to be split at this position
@@ -555,11 +588,6 @@ void Frame::readSpriteD4(Common::MemoryReadStreamEndian &stream, uint16 offset,
 
 	Sprite &sprite = *_sprites[spritePosition + 1];
 
-	if (sprite._puppet) {
-		stream.skip(size);
-		return;
-	}
-
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
@@ -578,65 +606,111 @@ void readSpriteDataD4(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 			sprite._scriptId = CastMemberID(stream.readByte(), DEFAULT_CAST_LIB);
 			break;
 		case 1:
-			sprite._spriteType = (SpriteType)stream.readByte();
-
-			sprite._enabled = sprite._spriteType != kInactiveSprite;
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._spriteType = (SpriteType)stream.readByte();
+				sprite._enabled = sprite._spriteType != kInactiveSprite;
+			}
 			break;
 		case 2:
-			sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
+			}
 			break;
 		case 3:
-			sprite._backColor = g_director->transformColor((uint8)stream.readByte());
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._backColor = g_director->transformColor((uint8)stream.readByte());
+			}
 			break;
 		case 4:
-			sprite._thickness = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._thickness = stream.readByte();
+			}
 			break;
 		case 5:
-			sprite._inkData = stream.readByte();
-
-			sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
-			if (sprite._inkData & 0x40)
-				sprite._trails = 1;
-			else
-				sprite._trails = 0;
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._inkData = stream.readByte();
 
+				sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+				if (sprite._inkData & 0x40)
+					sprite._trails = 1;
+				else
+					sprite._trails = 0;
+			}
 			break;
 		case 6:
-			if (sprite.isQDShape()) {
-				sprite._pattern = stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
 			} else {
-				sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
+				if (sprite.isQDShape()) {
+					sprite._pattern = stream.readUint16();
+				} else {
+					sprite._castId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
+				}
 			}
 			break;
 		case 8:
-			sprite._startPoint.y = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.y = (int16)stream.readUint16();
+			}
 			break;
 		case 10:
-			sprite._startPoint.x = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.x = (int16)stream.readUint16();
+			}
 			break;
 		case 12:
-			sprite._height = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._height = (int16)stream.readUint16();
+			}
 			break;
 		case 14:
-			sprite._width = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._width = (int16)stream.readUint16();
+			}
 			break;
 		case 16:
 			sprite._scriptId = CastMemberID(stream.readUint16(), DEFAULT_CAST_LIB);
 			break;
 		case 18:
-			// & 0x0f scorecolor
-			// 0x10 forecolor is rgb
-			// 0x20 bgcolor is rgb
-			// 0x40 editable
-			// 0x80 moveable
-			sprite._colorcode = stream.readByte();
-
-			sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
-			sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
-			sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				// & 0x0f scorecolor
+				// 0x10 forecolor is rgb
+				// 0x20 bgcolor is rgb
+				// 0x40 editable
+				// 0x80 moveable
+				sprite._colorcode = stream.readByte();
+
+				sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+				sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+				sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+			}
 			break;
 		case 19:
-			sprite._blendAmount = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._blendAmount = stream.readByte();
+			}
 			break;
 		default:
 			// This means that a `case` label has to be split at this position
@@ -820,11 +894,6 @@ void Frame::readSpriteD5(Common::MemoryReadStreamEndian &stream, uint16 offset,
 
 	Sprite &sprite = *_sprites[spritePosition + 1];
 
-	if (sprite._puppet) {
-		stream.skip(size);
-		return;
-	}
-
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
@@ -845,27 +914,38 @@ void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 	while (stream.pos() < finishPosition) {
 		switch (stream.pos() - startPosition) {
 		case 0:
-			sprite._spriteType = (SpriteType)stream.readByte();
+			if (sprite._puppet) {
+				sprite._spriteType = (SpriteType)stream.readByte();
+			}
 			break;
 		case 1:
-			sprite._inkData = stream.readByte();
-
-			sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
-			if (sprite._inkData & 0x40)
-				sprite._trails = 1;
-			else
-				sprite._trails = 0;
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._inkData = stream.readByte();
 
+				sprite._ink = static_cast<InkType>(sprite._inkData & 0x3f);
+				if (sprite._inkData & 0x40)
+					sprite._trails = 1;
+				else
+					sprite._trails = 0;
+			}
 			break;
-		case 2: {
+		case 2:
+			if (sprite._puppet) {
+				stream.skip(4);
+			} else {
 				uint16 castLib = stream.readUint16();
 				uint16 memberID = stream.readUint16();
 				sprite._castId = CastMemberID(memberID, castLib);
 			}
 			break;
-		case 4: {
+		case 4:
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
 				uint16 memberID = stream.readUint16();
-				sprite._castId = CastMemberID(memberID, sprite._castId.castLib);  // Inherit castLinb from previous frame
+				sprite._castId = CastMemberID(memberID, sprite._castId.castLib);  // Inherit castLib from previous frame
 			}
 			break;
 		case 6: {
@@ -876,44 +956,80 @@ void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 			break;
 		case 8: {
 				uint16 scriptMemberID = stream.readUint16();
-				sprite._scriptId = CastMemberID(scriptMemberID, sprite._scriptId.castLib);  // Inherit castLinb from previous frame
+				sprite._scriptId = CastMemberID(scriptMemberID, sprite._scriptId.castLib);  // Inherit castLib from previous frame
 			}
 			break;
 		case 10:
-			sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._foreColor = g_director->transformColor((uint8)stream.readByte());
+			}
 			break;
 		case 11:
-			sprite._backColor = g_director->transformColor((uint8)stream.readByte());
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._backColor = g_director->transformColor((uint8)stream.readByte());
+			}
 			break;
 		case 12:
-			sprite._startPoint.y = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.y = (int16)stream.readUint16();
+			}
 			break;
 		case 14:
-			sprite._startPoint.x = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._startPoint.x = (int16)stream.readUint16();
+			}
 			break;
 		case 16:
-			sprite._height = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._height = (int16)stream.readUint16();
+			}
 			break;
 		case 18:
-			sprite._width = (int16)stream.readUint16();
+			if (sprite._puppet) {
+				stream.readUint16();
+			} else {
+				sprite._width = (int16)stream.readUint16();
+			}
 			break;
 		case 20:
-			// & 0x0f scorecolor
-			// 0x10 forecolor is rgb
-			// 0x20 bgcolor is rgb
-			// 0x40 editable
-			// 0x80 moveable
-			sprite._colorcode = stream.readByte();
-
-			sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
-			sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
-			sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				// & 0x0f scorecolor
+				// 0x10 forecolor is rgb
+				// 0x20 bgcolor is rgb
+				// 0x40 editable
+				// 0x80 moveable
+				sprite._colorcode = stream.readByte();
+
+				sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
+				sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+				sprite._moveable = ((sprite._colorcode & 0x80) == 0x80);
+			}
 			break;
 		case 21:
-			sprite._blendAmount = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._blendAmount = stream.readByte();
+			}
 			break;
 		case 22:
-			sprite._thickness = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._thickness = stream.readByte();
+			}
 			break;
 		case 23:
 			(void)stream.readByte(); // unused
@@ -978,11 +1094,6 @@ void Frame::readSpriteD6(Common::MemoryReadStreamEndian &stream, uint16 offset,
 
 	Sprite &sprite = *_sprites[spritePosition + 1];
 
-	if (sprite._puppet) {
-		stream.skip(size);
-		return;
-	}
-
 	uint32 initPos = stream.pos();
 	uint32 finishPosition = initPos + size;
 
@@ -1003,12 +1114,16 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 	while (stream.pos() < finishPosition) {
 		switch (stream.pos() - startPosition) {
 		case 0:
-			sprite._spriteType = (SpriteType)stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._spriteType = (SpriteType)stream.readByte();
+			}
 			break;
 		case 1: {
 			byte inkData = stream.readByte();
 
-			if (sprite.getAutoPuppet(kAPInk))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPInk))
 				continue;
 
 			sprite._inkData = inkData;
@@ -1023,7 +1138,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 2: {
 			uint8 foreColor = stream.readByte();
 
-			if (sprite.getAutoPuppet(kAPForeColor))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPForeColor))
 				continue;
 
 			sprite._foreColor = g_director->transformColor(foreColor);
@@ -1032,7 +1147,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 3: {
 			uint8 backColor = stream.readByte();
 
-			if (sprite.getAutoPuppet(kAPBackColor))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPBackColor))
 				continue;
 
 			sprite._backColor = g_director->transformColor(backColor);
@@ -1042,7 +1157,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 				uint16 castLib = stream.readUint16();
 				uint16 memberID = stream.readUint16();
 
-				if (sprite.getAutoPuppet(kAPCast))
+				if (sprite._puppet || sprite.getAutoPuppet(kAPCast))
 					continue;
 
 				sprite._castId = CastMemberID(memberID, castLib);
@@ -1057,7 +1172,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 12: {
 			uint16 startPointY = stream.readUint16();
 
-			if (sprite.getAutoPuppet(kAPLocV) || sprite.getAutoPuppet(kAPLoc))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPLocV) || sprite.getAutoPuppet(kAPLoc))
 				continue;
 
 			sprite._startPoint.y = startPointY;
@@ -1066,7 +1181,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 14: {
 			uint16 startPointX = stream.readUint16();
 
-			if (sprite.getAutoPuppet(kAPLocH) || sprite.getAutoPuppet(kAPLoc))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPLocH) || sprite.getAutoPuppet(kAPLoc))
 				continue;
 
 			sprite._startPoint.x = startPointX;
@@ -1075,7 +1190,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 16: {
 			uint16 height = stream.readUint16();
 
-			if (sprite.getAutoPuppet(kAPHeight))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPHeight))
 				continue;
 
 			sprite._height = height;
@@ -1084,7 +1199,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 18: {
 			uint16 width = stream.readUint16();
 
-			if (sprite.getAutoPuppet(kAPWidth))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPWidth))
 				continue;
 
 			sprite._width = width;
@@ -1098,7 +1213,7 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 			// 0x80 moveable
 			sprite._colorcode = stream.readByte();
 
-			if (sprite.getAutoPuppet(kAPMoveable))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPMoveable))
 				continue;
 
 			sprite._editable = ((sprite._colorcode & 0x40) == 0x40);
@@ -1107,14 +1222,18 @@ void readSpriteDataD6(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		case 21: {
 			byte blendAmount = stream.readByte();
 
-			if (sprite.getAutoPuppet(kAPBlend))
+			if (sprite._puppet || sprite.getAutoPuppet(kAPBlend))
 				continue;
 
 			sprite._blendAmount = blendAmount;
 			}
 			break;
 		case 22:
-			sprite._thickness = stream.readByte();
+			if (sprite._puppet) {
+				stream.readByte();
+			} else {
+				sprite._thickness = stream.readByte();
+			}
 			break;
 		case 23:
 			(void)stream.readByte(); // unused


Commit: 27cd3a75aa0366ca6d3951582728f4c6f086cdec
    https://github.com/scummvm/scummvm/commit/27cd3a75aa0366ca6d3951582728f4c6f086cdec
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Proactively attempt to load DigitalVideoCastMember

Having the loading action only happen in Channel::setClean doesn't cover frame 1,
which is a straight copy from the frame data.

Fixes the logo movie loading in Escape From Planet Arizona.

Changed paths:
    engines/director/castmember/digitalvideo.cpp
    engines/director/castmember/digitalvideo.h
    engines/director/channel.cpp
    engines/director/detection_tables.h
    engines/director/frame.cpp
    engines/director/lingo/lingo-the.cpp


diff --git a/engines/director/castmember/digitalvideo.cpp b/engines/director/castmember/digitalvideo.cpp
index 93d050719da..851839919e5 100644
--- a/engines/director/castmember/digitalvideo.cpp
+++ b/engines/director/castmember/digitalvideo.cpp
@@ -89,6 +89,13 @@ DigitalVideoCastMember::~DigitalVideoCastMember() {
 		delete _video;
 }
 
+bool DigitalVideoCastMember::loadVideoFromCast() {
+	Common::String path = getCast()->getVideoPath(_castId);
+	if (!path.empty())
+		return loadVideo(path);
+	return false;
+}
+
 bool DigitalVideoCastMember::loadVideo(Common::String path) {
 	// TODO: detect file type (AVI, QuickTime, FLIC) based on magic number,
 	// insert the right video decoder
@@ -208,6 +215,11 @@ Graphics::MacWidget *DigitalVideoCastMember::createWidget(Common::Rect &bbox, Ch
 
 	_channel = channel;
 
+	if (!_video || !_video->isVideoLoaded()) {
+		// try and load the video if not already
+		loadVideoFromCast();
+	}
+
 	if (!_video || !_video->isVideoLoaded()) {
 		warning("DigitalVideoCastMember::createWidget: No video decoder");
 		delete widget;
@@ -257,10 +269,7 @@ Graphics::MacWidget *DigitalVideoCastMember::createWidget(Common::Rect &bbox, Ch
 
 uint DigitalVideoCastMember::getDuration() {
 	if (!_video || !_video->isVideoLoaded()) {
-		Common::String path = getCast()->getVideoPath(_castId);
-		if (!path.empty())
-			loadVideo(path);
-
+		loadVideoFromCast();
 		_duration = getMovieTotalTime();
 	}
 	return _duration;
diff --git a/engines/director/castmember/digitalvideo.h b/engines/director/castmember/digitalvideo.h
index 72b093b8f28..8c1d6cab11a 100644
--- a/engines/director/castmember/digitalvideo.h
+++ b/engines/director/castmember/digitalvideo.h
@@ -38,6 +38,7 @@ public:
 	bool isModified() override;
 	Graphics::MacWidget *createWidget(Common::Rect &bbox, Channel *channel, SpriteType spriteType) override;
 
+	bool loadVideoFromCast();
 	bool loadVideo(Common::String path);
 	void startVideo(Channel *channel);
 	void stopVideo();
diff --git a/engines/director/channel.cpp b/engines/director/channel.cpp
index 944c9ec2ab3..6dcd545d93f 100644
--- a/engines/director/channel.cpp
+++ b/engines/director/channel.cpp
@@ -397,10 +397,7 @@ void Channel::setClean(Sprite *nextSprite, bool partial) {
 	if (nextSprite) {
 		if (nextSprite->_cast && (_dirty || _sprite->_castId != nextSprite->_castId)) {
 			if (_sprite->_castId != nextSprite->_castId && nextSprite->_cast->_type == kCastDigitalVideo) {
-				Common::String path = nextSprite->_cast->getCast()->getVideoPath(nextSprite->_castId.member);
-
-				if (!path.empty()) {
-					((DigitalVideoCastMember *)nextSprite->_cast)->loadVideo(path);
+				if (((DigitalVideoCastMember *)nextSprite->_cast)->loadVideoFromCast()) {
 					_movieTime = 0;
 					((DigitalVideoCastMember *)nextSprite->_cast)->startVideo(this);
 				}
diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index 2e5616e0dce..ff005bc8d1d 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -5249,8 +5249,8 @@ static const DirectorGameDescription gameDescriptions[] = {
 	MACGAME1_l("pippi", "v1.3.3", "Pippi Start", "5f48d38b0c9b9c8790796d1eb1525713", 517216, Common::EN_ANY, 404),
 	WINGAME1t_l("pippi", "v1.3.3", "PIPPI.EXE", "2f3533b95406015d03d5dcd8ba7d961f", 691043, Common::EN_ANY, 404),
 
-	MACGAME1("planetarizona", "", "Manual Installation/Planet Arizona", "0c7bbb4b24823e5ab871cb4c1d6f3710", 488433, 400),
-	WINGAME1("planetarizona", "", "INSTALL/ARIZONA.EXE", "a23462ec87eff973d2cdb2ddfd4a59fa", 698651, 400),
+	MACGAME1("planetarizona", "", "Manual Installation/Planet Arizona", "0c7bbb4b24823e5ab871cb4c1d6f3710", 488433, 404),
+	WINGAME1("planetarizona", "", "INSTALL/ARIZONA.EXE", "a23462ec87eff973d2cdb2ddfd4a59fa", 698651, 404),
 
 	// Mac demo from MacFormat #44
 	// Win demo from Computer Buyer v17n68 (January 1997)
diff --git a/engines/director/frame.cpp b/engines/director/frame.cpp
index ded5cc7bdc0..3b376eba6ea 100644
--- a/engines/director/frame.cpp
+++ b/engines/director/frame.cpp
@@ -915,6 +915,8 @@ void readSpriteDataD5(Common::SeekableReadStreamEndian &stream, Sprite &sprite,
 		switch (stream.pos() - startPosition) {
 		case 0:
 			if (sprite._puppet) {
+				stream.readByte();
+			} else {
 				sprite._spriteType = (SpriteType)stream.readByte();
 			}
 			break;
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index bf69373828c..e0fcbc967e7 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -1485,9 +1485,7 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
 			CastMember *castMember = movie->getCastMember(castId);
 
 			if (castMember && castMember->_type == kCastDigitalVideo) {
-				Common::String path = castMember->getCast()->getVideoPath(castId.member);
-				if (!path.empty()) {
-					((DigitalVideoCastMember *)castMember)->loadVideo(path);
+				if (((DigitalVideoCastMember *)castMember)->loadVideoFromCast()) {
 					((DigitalVideoCastMember *)castMember)->startVideo(channel);
 					// b_updateStage needs to have _videoPlayback set to render video
 					// in the regular case Score::renderSprites sets it.


Commit: e47efa9013d4b238d2d99e3c6c0ea3272c15fab6
    https://github.com/scummvm/scummvm/commit/e47efa9013d4b238d2d99e3c6c0ea3272c15fab6
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Update amber detection entry

Changed paths:
    engines/director/detection_tables.h


diff --git a/engines/director/detection_tables.h b/engines/director/detection_tables.h
index ff005bc8d1d..2fa150482d2 100644
--- a/engines/director/detection_tables.h
+++ b/engines/director/detection_tables.h
@@ -3401,7 +3401,7 @@ static const DirectorGameDescription gameDescriptions[] = {
 							 "SHARED.DXR", "4e0c4cda8a75154f568d75095ac1132f", 333196, 404),
 
 	// Windows version is D5
-	MACGAME1("amber", "", "xn--AMBER-Journeys Beyond-yb4m", "a6a7812d8b3de0da884197eb26a1b059", 60086, 404),
+	MACGAME1f("amber", "", "xn--AMBER-Journeys Beyond-yb4m", "a6a7812d8b3de0da884197eb26a1b059", 60086, 404, GF_32BPP),
 
 	// Original filename is 'アメリカ横断ウルトラクイズ Demo'
 	MACDEMO1_l("americaodan", "Demo", "xn-- Demo-g40kn3x3n73alaj4a1a0e1ezj7clw4h", "32cb3a881f2d47a7e525370b198b2c5c", 484095, Common::JA_JPN, 404),
@@ -5913,7 +5913,7 @@ static const DirectorGameDescription gameDescriptions[] = {
 	WINDEMO1_l("almabril98", "Demo", "DEMO AA98 START.EXE", "3460ad87d2ba57104e2810a77b53c220", 4180353, Common::PT_BRA, 500),
 
 	// Mac version is D4
-	WINGAME1("amber", "", "AMBER_JB.EXE", "1a7acbba10a7246ba58c1d53fc7203f5", 1418103, 500),
+	WINGAME1f("amber", "", "AMBER_F/AMBER_JB.EXE", "t:9041928550219b808fd23d96e7ad7c6d", 1418103, 500, GF_32BPP),
 	WINDEMO2t("amber", "Demo", "DEMO.EXE", "98f65233a8d80a75513267fed14c1e18", 1417811,
 							   "AMBERHUB.DXR", "a95601f2521fd00c88ac424d66da1605", 868766, 501),
 


Commit: 10594c29d3e924edff4ea5e2c8726f39de4f0ff2
    https://github.com/scummvm/scummvm/commit/10594c29d3e924edff4ea5e2c8726f39de4f0ff2
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add rough detection for loading an Xtra vs XObject

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 57cb12e5524..b871145bd2f 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1305,8 +1305,6 @@ void LB::b_openResFile(int nargs) {
 }
 
 void LB::b_openXlib(int nargs) {
-	// TODO: When Xtras are implemented, determine whether to initialize
-	// the XObject or Xtra version of FileIO
 	Common::String xlibName;
 
 	Datum d = g_lingo->pop();
@@ -1344,7 +1342,13 @@ void LB::b_openXlib(int nargs) {
 	}
 
 	xlibName = getFileName(d.asString());
-	g_lingo->openXLib(xlibName, kXObj);
+
+	// TODO: Figure out a nicer way of differentiating Xtras from XLibs on Mac
+	if (xlibName.hasSuffixIgnoreCase(".x16") || xlibName.hasSuffixIgnoreCase(".x32")) {
+		g_lingo->openXLib(xlibName, kXtraObj);
+	} else {
+		g_lingo->openXLib(xlibName, kXObj);
+	}
 }
 
 void LB::b_saveMovie(int nargs) {


Commit: fa4848cf8ca6cd7eb4e4db595e8fd79a24fd65a7
    https://github.com/scummvm/scummvm/commit/fa4848cf8ca6cd7eb4e4db595e8fd79a24fd65a7
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: XOBJ: Add m_error support to FileIO

Fixes the CD detection in AMBER: Journeys Beyond.

Changed paths:
    engines/director/lingo/xlibs/fileio.cpp
    engines/director/lingo/xlibs/fileio.h


diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 3593be15c8a..c6fce12970e 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -200,13 +200,16 @@ FileObject::FileObject(ObjectType objType) : Object<FileObject>("FileIO") {
 	_inStream = nullptr;
 	_outFile = nullptr;
 	_outStream = nullptr;
+	_lastError = kErrorNone;
 }
 
 FileObject::FileObject(const FileObject &obj) : Object<FileObject>(obj) {
+	_objType = obj.getObjType();
 	_filename = nullptr;
 	_inStream = nullptr;
 	_outFile = nullptr;
 	_outStream = nullptr;
+	_lastError = kErrorNone;
 }
 
 FileObject::~FileObject() {
@@ -337,6 +340,7 @@ void FileIO::m_new(int nargs) {
 		FileIOError result = me->open(path, option);
 		if (result != kErrorNone) {
 			me->dispose();
+			me->_lastError = result;
 			g_lingo->push(Datum(result));
 			return;
 		}
@@ -365,15 +369,13 @@ void FileIO::m_openFile(int nargs) {
 		break;
 	}
 	Common::String path = d2.asString();
-	FileIOError result = me->open(path, option);
-	g_lingo->push(Datum(result));
+	me->_lastError = me->open(path, option);
 }
 
 void FileIO::m_closeFile(int nargs) {
 	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
 
 	me->clear();
-	g_lingo->push(Datum(kErrorNone));
 }
 
 // FIXME: split out filename-to-savegame logic from open() so we can implement createFile
@@ -611,8 +613,64 @@ void FileIO::m_fileName(int nargs) {
 	}
 }
 
-XOBJSTUB(FileIO::m_error, "")
-XOBJSTUB(FileIO::m_status, 0)
+void FileIO::m_error(int nargs) {
+	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
+	Datum d = g_lingo->pop();
+	Datum result("");
+	switch (d.asInt()) {
+	case kErrorNone:
+		if (me->getObjType() == kXtraObj) {
+			result = Datum("OK");
+		}
+		break;
+	case kErrorMemAlloc:
+		result = Datum("Memory allocation failure");
+		break;
+	case kErrorDirectoryFull:
+		result = Datum("File directory full");
+		break;
+	case kErrorVolumeFull:
+		result = Datum("Volume full");
+		break;
+	case kErrorVolumeNotFound:
+		result = Datum("Volume not found");
+		break;
+	case kErrorIO:
+		result = Datum("I/O Error");
+		break;
+	case kErrorBadFileName:
+		result = Datum("Bad file name");
+		break;
+	case kErrorFileNotOpen:
+		result = Datum("File not open");
+		break;
+	case kErrorTooManyFilesOpen:
+		result = Datum("Too many files open");
+		break;
+	case kErrorFileNotFound:
+		result = Datum("File not found");
+		break;
+	case kErrorNoSuchDrive:
+		result = Datum("No such drive");
+		break;
+	case kErrorNoDiskInDrive:
+		result = Datum("No disk in drive");
+		break;
+	case kErrorDirectoryNotFound:
+		result = Datum("Directory not found");
+		break;
+	default:
+		result = Datum("Unknown error");
+		break;
+	}
+	g_lingo->push(result);
+}
+
+void FileIO::m_status(int nargs) {
+	FileObject *me = static_cast<FileObject *>(g_lingo->_state->me.u.obj);
+
+	g_lingo->push(Datum(me->_lastError));
+}
 
 // Other
 
diff --git a/engines/director/lingo/xlibs/fileio.h b/engines/director/lingo/xlibs/fileio.h
index c55ce57d2f2..374cb688ca0 100644
--- a/engines/director/lingo/xlibs/fileio.h
+++ b/engines/director/lingo/xlibs/fileio.h
@@ -34,6 +34,7 @@ namespace Director {
 
 enum FileIOError {
 	kErrorNone = 0,
+	kErrorMemAlloc = 1,
 	kErrorEOF = -1,
 	kErrorDirectoryFull = -33,
 	kErrorVolumeFull = -34,
@@ -56,6 +57,7 @@ public:
 	Common::SeekableReadStream *_inStream;
 	Common::OutSaveFile *_outFile;
 	Common::MemoryWriteStreamDynamic *_outStream;
+	FileIOError _lastError;
 
 public:
 	FileObject(ObjectType objType);


Commit: 885e589356c4d6bf123d3b154c348ffbc5dd1994
    https://github.com/scummvm/scummvm/commit/885e589356c4d6bf123d3b154c348ffbc5dd1994
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Add script patch for CD detection in AMBER: Journeys Beyond.

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


diff --git a/engines/director/lingo/lingo-patcher.cpp b/engines/director/lingo/lingo-patcher.cpp
index 18cce8e4b55..7f7c7a50eb7 100644
--- a/engines/director/lingo/lingo-patcher.cpp
+++ b/engines/director/lingo/lingo-patcher.cpp
@@ -317,6 +317,16 @@ on checkkaiwa kaiwatrue, kaiwafalse \r\
 end \r\
 ";
 
+/* AMBER: Journeys Beyond has a check to ensure that the CD and hard disk data are on
+ * different drive letters. ScummVM will pretend that every drive letter contains the
+ * game contents, so we need to hotpatch the CD detection routine to return D:.
+ */
+const char *amberDriveDetectionFix = " \
+on GetCDLetter tagFile, discNumber\r\
+  return \"D:\"\r\
+end \r\
+";
+
 struct ScriptHandlerPatch {
 	const char *gameId;
 	const char *extra;
@@ -339,6 +349,7 @@ struct ScriptHandlerPatch {
 	{"kyoto", nullptr, kPlatformWindows, "ck_data\\opening\\shared.dxr", kMovieScript, 802, DEFAULT_CAST_LIB, kyotoTextEntryFix},
 	{"kyoto", nullptr, kPlatformWindows, "ck_data\\rajoumon\\shared.dxr", kMovieScript, 840, DEFAULT_CAST_LIB, kyotoTextEntryFix},
 	{"kyoto", nullptr, kPlatformWindows, "ck_data\\rokudou\\shared.dxr", kMovieScript, 846, DEFAULT_CAST_LIB, kyotoTextEntryFix},
+	{"amber", nullptr, kPlatformWindows, "AMBER_F\\AMBER_JB.EXE", kMovieScript, 7, DEFAULT_CAST_LIB, amberDriveDetectionFix},
 	{nullptr, nullptr, kPlatformUnknown, nullptr, kNoneScript, 0, 0, nullptr},
 
 };


Commit: f3c3c094e42f5d792258c2fbc2780efa9ff63ec2
    https://github.com/scummvm/scummvm/commit/f3c3c094e42f5d792258c2fbc2780efa9ff63ec2
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: LINGO: Add ParentScript check to b_script

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index b871145bd2f..8517c69bfa6 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -3269,10 +3269,12 @@ void LB::b_script(int nargs) {
 		ScriptContext *script = nullptr;
 
 		if (cast->_type == kCastLingoScript) {
-			// script cast can be either a movie script or score script
+			// script cast can be either a movie script, score script, or parent script (D5+)
 			script = g_director->getCurrentMovie()->getScriptContext(kMovieScript, memberID);
 			if (!script)
 				script = g_director->getCurrentMovie()->getScriptContext(kScoreScript, memberID);
+			if (!script)
+				script = g_director->getCurrentMovie()->getScriptContext(kParentScript, memberID);
 		} else {
 			g_director->getCurrentMovie()->getScriptContext(kCastScript, memberID);
 		}
@@ -3282,7 +3284,7 @@ void LB::b_script(int nargs) {
 			return;
 		}
 	}
-
+	warning("b_script(): No script context found for '%s'", d.asString(true).c_str());
 	g_lingo->push(Datum());
 }
 


Commit: 48d2a760e388631d13ae4826de3bcacc2891c191
    https://github.com/scummvm/scummvm/commit/48d2a760e388631d13ae4826de3bcacc2891c191
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: XTRA: Add stubs for ScrnUtil

Changed paths:
  A engines/director/lingo/xtras/scrnutil.cpp
  A engines/director/lingo/xtras/scrnutil.h
    engines/director/lingo/lingo-object.cpp
    engines/director/module.mk


diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 18a688e5ffb..571e44c137a 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -112,6 +112,7 @@
 #include "director/lingo/xlibs/xplayanim.h"
 #include "director/lingo/xlibs/xsoundxfcn.h"
 #include "director/lingo/xlibs/yasix.h"
+#include "director/lingo/xtras/scrnutil.h"
 
 namespace Director {
 
@@ -248,6 +249,7 @@ static struct XLibProto {
 	{ Quicktime::fileNames,				Quicktime::open,			Quicktime::close,			kXObj,					300 },	// D3
 	{ RearWindowXObj::fileNames,		RearWindowXObj::open,		RearWindowXObj::close,		kXObj,					400 },	// D4
 	{ RegisterComponent::fileNames,		RegisterComponent::open,	RegisterComponent::close,	kXObj,					400 },	// D4
+	{ ScrnUtilXtra::fileNames,			ScrnUtilXtra::open,			ScrnUtilXtra::close,		kXtraObj,					500 },	// D5
 	{ SerialPortXObj::fileNames,		SerialPortXObj::open,		SerialPortXObj::close,		kXObj,					200 },	// D2
 	{ SoundJam::fileNames,				SoundJam::open,				SoundJam::close,			kXObj,					400 },	// D4
 	{ SpaceMgr::fileNames,				SpaceMgr::open,				SpaceMgr::close,			kXObj,					400 },	// D4
diff --git a/engines/director/lingo/xtras/scrnutil.cpp b/engines/director/lingo/xtras/scrnutil.cpp
new file mode 100644
index 00000000000..de742610dcf
--- /dev/null
+++ b/engines/director/lingo/xtras/scrnutil.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/system.h"
+
+#include "director/director.h"
+#include "director/lingo/lingo.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-utils.h"
+#include "director/lingo/xtras/scrnutil.h"
+
+/**************************************************
+ *
+ * USED IN:
+ * amber
+ *
+ **************************************************/
+
+/*
+-- xtra ScrnUtil
+-- ScrnUtil Xtra version 1.0 copyright (c) 1996 by g/matter, inc.
+-- Programming copyright (c) 1996 Little Planet Publishing
+-- For technical support or updates, contact http://www.gmatter.com or support at gmatter.com
+--
+-- Picture Capture Functions --
+* ScreenToClipboard integer left, integer top, integer right, integer bottom
+* ScreenToFile integer left, integer top, integer right, integer bottom, string filename
+
+ */
+
+namespace Director {
+
+const char *ScrnUtilXtra::xlibName = "ScrnUtil";
+const char *ScrnUtilXtra::fileNames[] = {
+	"scrnutil",
+	nullptr
+};
+
+static MethodProto xlibMethods[] = {
+	{ nullptr, nullptr, 0, 0, 0 }
+};
+
+static BuiltinProto xlibBuiltins[] = {
+	{ "ScreenToClipboard", ScrnUtilXtra::m_ScreenToClipboard, 4, 4, 500, HBLTIN },
+	{ "ScreenToFile", ScrnUtilXtra::m_ScreenToFile, 5, 5, 500, HBLTIN },
+	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
+};
+
+static BuiltinProto xlibTopLevel[] = {
+	{ nullptr, nullptr, 0, 0, 0, VOIDSYM }
+};
+
+ScrnUtilXtraObject::ScrnUtilXtraObject(ObjectType ObjectType) :Object<ScrnUtilXtraObject>("ScrnUtilXtra") {
+	_objType = ObjectType;
+}
+
+void ScrnUtilXtra::open(ObjectType type) {
+    ScrnUtilXtraObject::initMethods(xlibMethods);
+    ScrnUtilXtraObject *xobj = new ScrnUtilXtraObject(type);
+    g_lingo->exposeXObject(xlibName, xobj);
+    g_lingo->initBuiltIns(xlibBuiltins);
+}
+
+void ScrnUtilXtra::close(ObjectType type) {
+    ScrnUtilXtraObject::cleanupMethods();
+    g_lingo->_globalvars[xlibName] = Datum();
+
+}
+
+XOBJSTUB(ScrnUtilXtra::m_ScreenToClipboard, 0)
+XOBJSTUB(ScrnUtilXtra::m_ScreenToFile, 0)
+
+}
diff --git a/engines/director/lingo/xtras/scrnutil.h b/engines/director/lingo/xtras/scrnutil.h
new file mode 100644
index 00000000000..cd94de83e9a
--- /dev/null
+++ b/engines/director/lingo/xtras/scrnutil.h
@@ -0,0 +1,47 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XTRAS_SCRNUTIL_H
+#define DIRECTOR_LINGO_XTRAS_SCRNUTIL_H
+
+namespace Director {
+
+class ScrnUtilXtraObject : public Object<ScrnUtilXtraObject> {
+public:
+	ScrnUtilXtraObject(ObjectType objType);
+};
+
+namespace ScrnUtilXtra {
+
+extern const char *xlibName;
+extern const char *fileNames[];
+
+void open(ObjectType type);
+void close(ObjectType type);
+
+void m_ScreenToClipboard(int nargs);
+void m_ScreenToFile(int nargs);
+
+} // End of namespace ScrnUtilXtra
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/module.mk b/engines/director/module.mk
index 258fc76a0a0..a769b2dc274 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -135,7 +135,8 @@ MODULE_OBJS = \
 	lingo/xlibs/xio.o \
 	lingo/xlibs/xplayanim.o \
 	lingo/xlibs/xsoundxfcn.o \
-	lingo/xlibs/yasix.o
+	lingo/xlibs/yasix.o \
+	lingo/xtras/scrnutil.o
 
 # HACK: Skip this when including the file for detection objects.
 ifeq "$(USE_RULES)" "1"


Commit: a1b16fa399a088d93476ea79fedf60d4f8ae7489
    https://github.com/scummvm/scummvm/commit/a1b16fa399a088d93476ea79fedf60d4f8ae7489
Author: Scott Percival (code at moral.net.au)
Date: 2024-03-11T01:04:43+01:00

Commit Message:
DIRECTOR: Preserve trails on screen

Several Director titles make use of the "trails" sprite feature to
draw graphics to the framebuffer, strobing multiple sprites with a
single channel. In order for this to work, we need to be careful that
the dirty rectangles list is only updating the bare minimum area.

Extra rectangles were being added by Score::renderSprites; an invalid
cast reference would still add the channel's bbox to the list. This has
been fixed.

Previously, the end of a transition would force a full screen refresh,
even if the update was partial. This should be unneccesary; transitions
shouldn't leave artifacts on the screen.

Fixes many instances of inventory items disappearing in Team Xtreme:
Operation Weather disaster (e.g. clicking the compass in Stonehenge,
clicking an item on the memory game in Stonehenge).

Changed paths:
    engines/director/score.cpp
    engines/director/score.h
    engines/director/transitions.cpp
    engines/director/types.h
    engines/director/window.h


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 3be132d0aa9..aec48c540d2 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -654,7 +654,7 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
 	} else if (g_director->_playbackPaused) {
 		renderSprites(mode);
 		_window->render();
-	} else if (!renderTransition(frameId)) {
+	} else if (!renderTransition(frameId, mode)) {
 		bool skip = renderPrePaletteCycle(mode);
 		setLastPalette();
 		renderSprites(mode);
@@ -675,26 +675,26 @@ void Score::renderFrame(uint16 frameId, RenderMode mode) {
 	debugC(5, kDebugLoading, "Score::renderFrame() finished in %d millis", end - start);
 }
 
-bool Score::renderTransition(uint16 frameId) {
+bool Score::renderTransition(uint16 frameId, RenderMode mode) {
 	Frame *currentFrame = _currentFrame;
 	TransParams *tp = _window->_puppetTransition;
 
 	if (tp) {
 		setLastPalette();
-		_window->playTransition(frameId, tp->duration, tp->area, tp->chunkSize, tp->type, currentFrame->_mainChannels.scoreCachedPaletteId);
+		_window->playTransition(frameId, mode, tp->duration, tp->area, tp->chunkSize, tp->type, currentFrame->_mainChannels.scoreCachedPaletteId);
 		delete _window->_puppetTransition;
 		_window->_puppetTransition = nullptr;
 		return true;
 	} else if (currentFrame->_mainChannels.transType) {
 		setLastPalette();
-		_window->playTransition(frameId, currentFrame->_mainChannels.transDuration, currentFrame->_mainChannels.transArea, currentFrame->_mainChannels.transChunkSize, currentFrame->_mainChannels.transType, currentFrame->_mainChannels.scoreCachedPaletteId);
+		_window->playTransition(frameId, mode, currentFrame->_mainChannels.transDuration, currentFrame->_mainChannels.transArea, currentFrame->_mainChannels.transChunkSize, currentFrame->_mainChannels.transType, currentFrame->_mainChannels.scoreCachedPaletteId);
 		return true;
 	} else if (!currentFrame->_mainChannels.trans.isNull()) {
 		CastMember *member = _movie->getCastMember(currentFrame->_mainChannels.trans);
 		if (member && member->_type == kCastTransition) {
 			TransitionCastMember *trans = static_cast<TransitionCastMember *>(member);
 			setLastPalette();
-			_window->playTransition(frameId, trans->_durationMillis, trans->_area, trans->_chunkSize, trans->_transType, currentFrame->_mainChannels.scoreCachedPaletteId);
+			_window->playTransition(frameId, mode, trans->_durationMillis, trans->_area, trans->_chunkSize, trans->_transType, currentFrame->_mainChannels.scoreCachedPaletteId);
 			return true;
 		}
 	}
@@ -705,6 +705,8 @@ void Score::renderSprites(RenderMode mode) {
 	if (_window->_newMovieStarted)
 		mode = kRenderForceUpdate;
 
+	debugC(5, kDebugImages, "Score::renderSprites(): starting render cycle, mode %d", mode);
+
 	_movie->_videoPlayback = false;
 
 	for (uint16 i = 0; i < _channels.size(); i++) {
@@ -722,7 +724,8 @@ void Score::renderSprites(RenderMode mode) {
 		}
 
 		if (channel->isDirty(nextSprite) || widgetRedrawn || mode == kRenderForceUpdate) {
-			if (currentSprite && !currentSprite->_trails)
+			bool invalidCastMember = currentSprite && currentSprite->_spriteType == kCastMemberSprite && currentSprite->_cast == nullptr;
+			if (currentSprite && !invalidCastMember && !currentSprite->_trails)
 				_window->addDirtyRect(channel->getBbox());
 
 			if (currentSprite && currentSprite->_cast && currentSprite->_cast->_erase) {
@@ -734,16 +737,22 @@ void Score::renderSprites(RenderMode mode) {
 			}
 
 			channel->setClean(nextSprite);
+			invalidCastMember = currentSprite ? (currentSprite->_spriteType == kCastMemberSprite && currentSprite->_cast == nullptr) : false;
 			// Check again to see if a video has just been started by setClean.
 			if (channel->isActiveVideo())
 				_movie->_videoPlayback = true;
 
-			_window->addDirtyRect(channel->getBbox());
+			if (!invalidCastMember)
+				_window->addDirtyRect(channel->getBbox());
+
 			if (currentSprite) {
+				Common::Rect bbox = channel->getBbox();
 				debugC(5, kDebugImages,
-					"Score::renderSprites(): CH: %-3d castId: %s [ink: %d, puppet: %d, moveable: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %s]",
-					i, currentSprite->_castId.asString().c_str(), currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable, channel->_visible,
-					PRINT_RECT(channel->getBbox()), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor,
+					"Score::renderSprites(): CH: %-3d castId: %s invalid: %d [ink: %d, puppet: %d, moveable: %d, trails: %d, visible: %d] [bbox: %d,%d,%d,%d] [type: %d fg: %d bg: %d] [script: %s]",
+					i, currentSprite->_castId.asString().c_str(), invalidCastMember,
+					currentSprite->_ink, currentSprite->_puppet, currentSprite->_moveable,
+					currentSprite->_trails, channel->_visible,
+					PRINT_RECT(bbox), currentSprite->_spriteType, currentSprite->_foreColor, currentSprite->_backColor,
 					currentSprite->_scriptId.asString().c_str());
 			} else {
 				debugC(5, kDebugImages, "Score::renderSprites(): CH: %-3d: No sprite", i);
diff --git a/engines/director/score.h b/engines/director/score.h
index ad52b7159ec..25e89fa7dfe 100644
--- a/engines/director/score.h
+++ b/engines/director/score.h
@@ -53,11 +53,6 @@ class Sprite;
 class CastMember;
 class AudioDecoder;
 
-enum RenderMode {
-	kRenderModeNormal,
-	kRenderForceUpdate
-};
-
 struct Label {
 	Common::String comment;
 	Common::String name;
@@ -121,7 +116,7 @@ public:
 	Common::List<Channel *> getSpriteIntersections(const Common::Rect &r);
 	uint16 getSpriteIdByMemberId(CastMemberID id);
 
-	bool renderTransition(uint16 frameId);
+	bool renderTransition(uint16 frameId, RenderMode mode);
 	void renderFrame(uint16 frameId, RenderMode mode = kRenderModeNormal);
 	void renderSprites(RenderMode mode = kRenderModeNormal);
 	bool renderPrePaletteCycle(RenderMode mode = kRenderModeNormal);
diff --git a/engines/director/transitions.cpp b/engines/director/transitions.cpp
index 2e6a00e19a3..ed56796f6b7 100644
--- a/engines/director/transitions.cpp
+++ b/engines/director/transitions.cpp
@@ -152,7 +152,7 @@ void Window::stepTransition(TransParams &t, int step) {
 	g_director->draw();
 }
 
-void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, CastMemberID paletteId) {
+void Window::playTransition(uint frame, RenderMode mode, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, CastMemberID paletteId) {
 	// Play a transition and return the number of subframes rendered
 	TransParams t;
 
@@ -191,7 +191,7 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
 	Score *score = g_director->getCurrentMovie()->getScore();
 	if (t.area) {
 		// Changed area transition
-		score->renderSprites();
+		score->renderSprites(mode);
 
 		if (_dirtyRects.size() == 0)
 			return;
@@ -217,7 +217,7 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
 		render(false, &nextFrame);
 	} else {
 		// Full stage transition
-		score->renderSprites(kRenderForceUpdate);
+		score->renderSprites(mode);
 		render(true, &nextFrame);
 
 		clipRect = _innerDims;
@@ -240,7 +240,7 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
 			dissolvePatternsTrans(t, clipRect, &nextFrame);
 		else
 			dissolveTrans(t, clipRect, &nextFrame);
-		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, area: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.area, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
 		debugC(2, kDebugImages, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
 		return;
 
@@ -248,13 +248,13 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
 	case kTransAlgoStrips:
 	case kTransAlgoBlinds:
 		transMultiPass(t, clipRect, &nextFrame);
-		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, area: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.area, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
 		debugC(2, kDebugImages, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
 		return;
 
 	case kTransAlgoZoom:
 		transZoom(t, clipRect, &currentFrame, &nextFrame);
-		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+		debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, area: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.area, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
 		debugC(2, kDebugImages, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
 		return;
 
@@ -576,12 +576,7 @@ void Window::playTransition(uint frame, uint16 transDuration, uint8 transArea, u
 		g_lingo->executePerFrameHook(t.frame, i);
 	}
 
-	// re-render the surface to clean the tracks when of transitions
-	render(true, _composeSurface);
-	_contentIsDirty = true;
-	g_director->draw();
-
-	debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
+	debugC(2, kDebugImages, "Window::playTransition(): type: %d, duration: %d, area: %d, chunkSize: %d, steps: %d, stepDuration: %d, xpos: %d, ypos: %d, xStepSize: %d, yStepSize: %d, stripSize: %d", t.type, t.duration, t.area, t.chunkSize, t.steps, t.stepDuration, t.xpos, t.ypos, t.xStepSize, t.yStepSize, t.stripSize);
 	debugC(2, kDebugImages, "Window::playTransition(): Transition %d finished in %d ms", t.type, g_system->getMillis() - transStartTime);
 }
 
diff --git a/engines/director/types.h b/engines/director/types.h
index 52d9f0aa557..df478574b06 100644
--- a/engines/director/types.h
+++ b/engines/director/types.h
@@ -290,6 +290,11 @@ enum TransitionType {
 	kTransDissolveBits
 };
 
+enum RenderMode {
+	kRenderModeNormal,
+	kRenderForceUpdate
+};
+
 // TODO: Can there be any more built-in palette types?
 enum PaletteType {
 	kClutSystemMac = -1,
diff --git a/engines/director/window.h b/engines/director/window.h
index 4fe7dbc3bde..0712edabe25 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -118,7 +118,7 @@ public:
 	// transitions.cpp
 	void exitTransition(TransParams &t, int step, Graphics::ManagedSurface *nextFrame, Common::Rect clipRect);
 	void stepTransition(TransParams &t, int step);
-	void playTransition(uint frame, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, CastMemberID paletteId);
+	void playTransition(uint frame, RenderMode mode, uint16 transDuration, uint8 transArea, uint8 transChunkSize, TransitionType transType, CastMemberID paletteId);
 	void initTransParams(TransParams &t, Common::Rect &clipRect);
 	void dissolveTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);
 	void dissolvePatternsTrans(TransParams &t, Common::Rect &clipRect, Graphics::ManagedSurface *tmpSurface);




More information about the Scummvm-git-logs mailing list