[Scummvm-git-logs] scummvm master -> 9702201987467fb6abb3e08d03eaf970fb75326a

sev- noreply at scummvm.org
Mon Sep 8 16:18:16 UTC 2025


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

Summary:
adefcc234b DIRECTOR: Add support for msfile.dll xlib.
477fc5deca DIRECTOR: Channels need to be initialized earlier.
71e9985541 DIRECTOR, COMMON: Add support for The Simpsons Cartoon Studio
c548cede6f DIRECTOR: Fixed sizing issue with text castmembers.
4be5a42d5a DIRECTOR: Improve getFileNameFromModal extension filtering.
8729519410 DIRECTOR: Add missing inflate method.
dd5eb8ea79 DIRECTOR: Fix file encoding for FileIO m_writeString.
ae2fe10f42 DIRECTOR: Add saveFilePaths for The Simpsons Cartoon Studio.
e7125ac2b1 DIRECTOR: Update save file cache when using getNthFileNameInFolder.
9702201987 DIRECTOR: Fix startMovie ordering.


Commit: adefcc234be6f3fc1839efc68889c4bf4bc17c4d
    https://github.com/scummvm/scummvm/commit/adefcc234be6f3fc1839efc68889c4bf4bc17c4d
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Add support for msfile.dll xlib.

This file is used by The Simpsons Cartoon Studio

Changed paths:
  A engines/director/lingo/xlibs/msfile.cpp
  A engines/director/lingo/xlibs/msfile.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 9461001fc3d..59ef6a926e6 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -98,6 +98,7 @@
 #include "director/lingo/xlibs/movemousexobj.h"
 #include "director/lingo/xlibs/movieidxxobj.h"
 #include "director/lingo/xlibs/movutils.h"
+#include "director/lingo/xlibs/msfile.h"
 #include "director/lingo/xlibs/mystisle.h"
 #include "director/lingo/xlibs/openbleedwindowxcmd.h"
 #include "director/lingo/xlibs/orthoplayxobj.h"
@@ -297,6 +298,7 @@ static const struct XLibProto {
 	XLIBDEF(MoveMouseXObj,		kXObj,			400),	// D4
 	XLIBDEF(MovieIdxXObj,		kXObj,			400),	// D4
 	XLIBDEF(MovUtilsXObj,		kXObj,			400),	// D4
+	XLIBDEF(MSFile,             kXObj,          400),   // D4
 	XLIBDEF(MystIsleXObj,			kXObj,					400),	// D4
 	XLIBDEF(OpenBleedWindowXCMD,kXObj,			300),	// D3
 	XLIBDEF(OpenURLXtra,			kXtraObj,					500),	// D5
diff --git a/engines/director/lingo/xlibs/msfile.cpp b/engines/director/lingo/xlibs/msfile.cpp
new file mode 100644
index 00000000000..935b0a89674
--- /dev/null
+++ b/engines/director/lingo/xlibs/msfile.cpp
@@ -0,0 +1,314 @@
+/* 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/savefile.h"
+#include "common/file.h"
+#include "gui/filebrowser-dialog.h"
+#include "gui/browser.h"
+#include "director/director.h"
+#include "director/picture.h"
+#include "director/types.h"
+#include "director/util.h"
+#include "director/lingo/lingo.h"
+#include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-utils.h"
+#include "director/lingo/xlibs/msfile.h"
+
+/*************************************
+ *
+ * USED IN:
+ * The Simpsons Cartoon Studio
+ *
+ *************************************/
+
+/*
+"I      mNew                      --Instantiates XObject"	1028:0023	string	56
+"X      mDispose                  --Removes XObject Instance"	1028:005b	string	60
+"S      mName                     --Returns XObject Name"	1028:0097	string	56
+"SS     mGetFullDirList, dospath  --Returns MS-DOS Full Directory List (use *.*)"	1028:00cf	string	80
+"SS     mGetFileList, dospath     --Returns MS-DOS File List (use *.*)"	1028:011f	string	70
+"SS     mGetDirList, dospath      --Returns MS-DOS Directory List (use *.*)"	1028:0165	string	75
+"II     mGetDiskFree, drive       --Returns Free disk space, drive is 0 for current, 1 for A, ..."	1028:01b0	string	97
+"SS     mGetVolLabel, drive       --Returns Drive Label (use d:\\*.*)"	1028:0211	string	68
+"IS     mCreateDir, dospath       --Creates an MS-DOS Directory"	1028:0255	string	63
+"IS     mRemoveDir, dospath       --Removes an MS-DOS Directory"	1028:0294	string	63
+"S      mGetCurrDir               --Returns Current Working Directory"	1028:02d3	string	69
+"IS     mSetCurrDir, dospath      --Sets Current Working Directory"	1028:0318	string	66
+"IS     mRemoveFile, dospath      --Deletes File named by dospath"	1028:035a	string	65
+"ISS    mRenameFile, oldpath ,newpath      --Renames File named by oldpath"	1028:039b	string	74
+"ISS    mCopyFile, srcpath, destpath       --Copys srcpath to destpath, overwrites"	1028:03e5	string	82
+"ISSI   mCopyFiles, srcpath, destpath, incsubdir   --Copys srcpath to destpath, overwrites"	1028:0437	string	90
+"ISSSS  mSetAppINI, app, key, string, file --Sets app.ini"	1028:0491	string	57
+"SSSS   mGetAppINI, app, key, file         --Gets app.ini"	1028:04ca	string	57
+"S      mGetWindowsDirectory               --Gets Windows directory path"	1028:0503	string	72
+"I      mGetWinVer                         --Gets Windows major version number"	1028:054b	string	78
+"I      mRestartWindows                    --Gets Windows major version number"	1028:0599	string	78
+"SSSS   mOpenFileDlg, title, defspec, file --Displays Director Open File Dialog Box"	1028:05e7	string	83
+"SSSS   mSaveFileDlg, title, defspec, file --Displays Director Save File Dialog Box"	1028:063a	string	83
+"SSSS   mGetOFileName, deffile, filter, defext --Displays Open File Dialog Box"	1028:068d	string	78
+"SSSS   mGetSFileName, deffile, filter, defext --Displays Save File Dialog Box"	1028:06db	string	78
+"SSSS   mDisplayDlg, title, message, defspec --Displays Dialog Box"	1028:0729	string	66
+"ISSSS  mProgMgrAdd, group, command, title, icon  --\r\r"	1028:076b	string	57
+*/
+
+namespace Director {
+
+const char *const MSFile::xlibName = "MSFile";
+const XlibFileDesc MSFile::fileNames[] = {
+	{"MSFile", nullptr},
+	{"MSFILE16", nullptr},
+	{nullptr, nullptr},
+};
+
+static const MethodProto xlibMethods[] = {
+	// XObject
+	{"new",                 MSFile::m_new,                 0, 0, 400},
+	{"dispose",             MSFile::m_dispose,             0, 0, 400},
+	{"name",                MSFile::m_name,                0, 1, 400},
+	{"getFullDirList",      MSFile::m_getFullDirList,      1, 1, 400},
+	{"getFileList",         MSFile::m_getFileList,         1, 1, 400},
+	{"getDirList",          MSFile::m_getDirList,          1, 1, 400},
+	{"getDiskFree",         MSFile::m_getDiskFree,         1, 1, 400},
+	{"getVolLabel",         MSFile::m_getVolLabel,         1, 1, 400},
+	{"createDir",           MSFile::m_createDir,           1, 1, 400},
+	{"removeDir",           MSFile::m_removeDir,           1, 1, 400},
+	{"getCurrDir",          MSFile::m_getCurrDir,          0, 1, 400},
+	{"setCurrDir",          MSFile::m_setCurrDir,          1, 1, 400},
+	{"removeFile",          MSFile::m_removeFile,          1, 1, 400},
+	{"renameFile",          MSFile::m_renameFile,          2, 1, 400},
+	{"copyFile",            MSFile::m_copyFile,            2, 1, 400},
+	{"copyFiles",           MSFile::m_copyFiles,           3, 1, 400},
+	{"setAppINI",           MSFile::m_setAppINI,           4, 1, 400},
+	{"getAppINI",           MSFile::m_getAppINI,           3, 1, 400},
+	{"getWindowsDirectory", MSFile::m_getWindowsDirectory, 0, 1, 400},
+	{"getWinVer",           MSFile::m_getWinVer,           0, 1, 400},
+	{"restartWindows",      MSFile::m_restartWindows,      0 ,1, 400},
+	{"openFileDlg",         MSFile::m_openFileDlg,         3, 1, 400},
+	{"saveFileDlg",         MSFile::m_saveFileDlg,         3, 1, 400},
+	{"getOFileName",        MSFile::m_getOFileName,        3, 1, 400},
+	{"getSFileName",        MSFile::m_getSFileName,        3, 1, 400},
+	{"displayDlg",          MSFile::m_displayDlg,          3, 1, 400},
+	{"progMgrAdd",          MSFile::m_progMgrAdd,          4, 1, 400},
+	{nullptr, nullptr, 0, 0, 0}};
+
+static const BuiltinProto xlibBuiltins[] = {
+	{nullptr, nullptr, 0, 0, 0, VOIDSYM}};
+
+MSFileObject::MSFileObject(ObjectType objType) : Object<MSFileObject>("MSFile") {
+	_objType = objType;
+	_lastError = msErrorNone;
+}
+
+MSFileObject::MSFileObject(const MSFileObject &obj) : Object<MSFileObject>(obj) {
+	_objType = obj.getObjType();
+	_lastError = msErrorNone;
+}
+
+MSFileObject::~MSFileObject() {
+}
+
+void MSFileObject::dispose() {
+	_disposed = true;
+}
+
+bool MSFileObject::hasProp(const Common::String &propName) {
+	return (propName == "name");
+}
+
+Datum MSFileObject::getProp(const Common::String &propName) {
+	if (propName == "name")
+		return Datum(MSFile::xlibName);
+	warning("MSFile::getProp: unknown property '%s'", propName.c_str());
+	return Datum();
+}
+
+void MSFile::m_new(int nargs) {
+	Datum result = g_lingo->_state->me;
+	g_lingo->push(result);
+}
+
+XOBJSTUB(MSFile::m_dispose, 0)
+XOBJSTUB(MSFile::m_name, "")
+XOBJSTUB(MSFile::m_getFullDirList, "")
+XOBJSTUB(MSFile::m_getFileList, "")
+XOBJSTUB(MSFile::m_getDirList, "")
+
+void MSFile::m_getDiskFree(int nargs) {
+	// We don't care about the drive letter. We will always just return 500 MB.
+	g_lingo->pop();
+
+	// 500 MB in KB
+	g_lingo->push(Datum(500 * 1024 * 1024));
+}
+
+void MSFile::m_getVolLabel(int nargs) {
+	Datum d = g_lingo->pop();
+
+	Common::String volLabel;
+
+	const char *gameId = g_director->getGameId();
+	if (strncmp(gameId, "simpsonsstudio", 14) == 0 || strncmp(gameId, "simpsonsplayer", 14) == 0) {
+		volLabel = "Simpsons";
+	} else {
+		warning("MSFile::m_getVolLabel(): Unsupported gameid '%s'", gameId);
+	}
+
+	g_lingo->push(volLabel);
+}
+
+XOBJSTUB(MSFile::m_createDir, 0)
+XOBJSTUB(MSFile::m_removeDir, 0)
+XOBJSTUB(MSFile::m_getCurrDir, "")
+XOBJSTUB(MSFile::m_setCurrDir, 0)
+XOBJSTUB(MSFile::m_removeFile, 0)
+XOBJSTUB(MSFile::m_renameFile, 0)
+
+Common::Path MSFile::resolveSourceFilePath(const Common::String& srcParam) {
+	return findPath(srcParam);
+}
+
+Common::SeekableReadStream *MSFile::openSourceStream(const Common::Path &srcFilePath, const Common::String &srcParam, char dirSeparator) {
+	Common::SaveFileManager *saves = g_system->getSavefileManager();
+	Common::String prefix = savePrefix();
+
+	// The source file may be a save file in the ScummVM save folder.
+	Common::String saveFileName = lastPathComponent(srcParam, dirSeparator);
+
+	// Modify the source file name to match the name of the potential save file
+	if (!saveFileName.hasSuffixIgnoreCase(".txt")) {
+		saveFileName += ".txt";
+	}
+
+	if (!saveFileName.hasPrefixIgnoreCase(prefix)) {
+		saveFileName = prefix + saveFileName;
+	}
+
+	// Try to open the save file
+	Common::SeekableReadStream *srcReadStream = saves->openForLoading(saveFileName);
+
+	// If the save file was not found then we will try opening the file directly
+	if (!srcReadStream) {
+		// We have a relative path so we can open it using Common::File
+		Common::File *srcFile = new Common::File();
+		if (srcFilePath.empty() || !srcFile->open(srcFilePath)) {
+			warning("MSFile::m_copyFile(): Error opening file %s", srcFilePath.toString(Common::Path::kNativeSeparator).c_str());
+			delete srcFile;
+			return nullptr;
+		}
+		srcReadStream = srcFile;
+	}
+
+	return srcReadStream;
+}
+
+Common::SeekableWriteStream *MSFile::openDestinationStream(Common::String &destFileName) {
+	Common::SaveFileManager *saves = g_system->getSavefileManager();
+	Common::String prefix = savePrefix();
+
+	Common::OutSaveFile *destFile = nullptr;
+
+	if (!destFileName.hasSuffixIgnoreCase(".txt")) {
+		destFileName += ".txt";
+	}
+
+	if (!destFileName.hasPrefixIgnoreCase(prefix)) {
+		destFileName = prefix + destFileName;
+	}
+
+	destFile = saves->openForSaving(destFileName, false);
+
+	return destFile;
+}
+
+bool MSFile::copyStream(Common::SeekableReadStream* srcStream, Common::SeekableWriteStream* destStream) {
+	if (srcStream && destStream) {
+		destStream->writeStream(srcStream);
+		destStream->finalize();
+		bool success = !destStream->err();
+		delete destStream;
+		return success;
+	}
+
+	return false;
+}
+
+bool MSFile::copyGameFile(const Common::String& srcParam, const Common::String& destParam) {
+	char dirSeparator = g_director->_dirSeparator;
+	Common::Path srcFilePath = resolveSourceFilePath(srcParam);
+	Common::String destFileName = Common::lastPathComponent(destParam, dirSeparator);
+
+	Common::SeekableReadStream *srcStream = openSourceStream(srcFilePath, srcParam, dirSeparator);
+	Common::SeekableWriteStream *destStream = openDestinationStream(destFileName);
+
+	return copyStream(srcStream, destStream);
+}
+
+void MSFile::m_copyFile(int nargs) {
+	Datum d2 = g_lingo->pop();
+	Datum d1 = g_lingo->pop();
+
+	// The source and destination file parameters are absolute paths from the games perspective but do not match the paths for ScummVM
+	Common::String srcParam = d1.asString();
+	Common::String destParam = d2.asString();
+
+	bool success = copyGameFile(srcParam, destParam);
+
+	g_lingo->push(Datum(success ? 0 : 1)); // Push 0 for success, 1 for failure
+}
+
+XOBJSTUB(MSFile::m_copyFiles, 0)
+XOBJSTUB(MSFile::m_setAppINI, 0)
+XOBJSTUB(MSFile::m_getAppINI, "")
+XOBJSTUB(MSFile::m_getWindowsDirectory, "")
+XOBJSTUB(MSFile::m_getWinVer, 0)
+XOBJSTUB(MSFile::m_restartWindows, 0)
+XOBJSTUB(MSFile::m_openFileDlg, "")
+XOBJSTUB(MSFile::m_saveFileDlg, "")
+
+void MSFile::m_getOFileName(int nargs) {
+	Datum d3 = g_lingo->pop();
+	Datum d2 = g_lingo->pop();
+	Datum d1 = g_lingo->pop();
+
+	Common::String defFile = d1.asString();
+	Common::String filter = d2.asString();
+	Common::String defExt = d3.asString();
+
+	g_lingo->push(getFileNameFromModal(false, defFile, filter, defExt.c_str()));
+}
+
+XOBJSTUB(MSFile::m_getSFileName, "")
+XOBJSTUB(MSFile::m_displayDlg, "")
+XOBJSTUB(MSFile::m_progMgrAdd, 0)
+
+void MSFile::open(ObjectType type, const Common::Path &path) {
+	MSFileObject::initMethods(xlibMethods);
+	MSFileObject *xobj = new MSFileObject(type);
+	if (g_director->getVersion() >= 500)
+		g_lingo->_openXtras.push_back(xlibName);
+	g_lingo->exposeXObject(xlibName, xobj);
+	g_lingo->initBuiltIns(xlibBuiltins);
+}
+
+void MSFile::close(ObjectType type) {
+	g_lingo->_globalvars[xlibName] = Datum();
+}
+} // End of namespace Director
diff --git a/engines/director/lingo/xlibs/msfile.h b/engines/director/lingo/xlibs/msfile.h
new file mode 100644
index 00000000000..136ad7bd798
--- /dev/null
+++ b/engines/director/lingo/xlibs/msfile.h
@@ -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/>.
+ *
+ */
+
+#ifndef DIRECTOR_LINGO_XLIBS_MSFILE_H
+#define DIRECTOR_LINGO_XLIBS_MSFILE_H
+
+namespace Director {
+
+enum MSFileError {
+	msErrorNone = 0,
+};
+
+class MSFileObject : public Object<MSFileObject> {
+public:
+	MSFileError _lastError;
+
+public:
+	MSFileObject(ObjectType objType);
+	MSFileObject(const MSFileObject &obj);
+	~MSFileObject() override;
+
+	bool hasProp(const Common::String &propName) override;
+	Datum getProp(const Common::String &propName) override;
+
+	void dispose() override;
+};
+
+namespace MSFile {
+extern const char *const xlibName;
+extern const XlibFileDesc fileNames[];
+
+void open(ObjectType type, const Common::Path &path);
+void close(ObjectType type);
+
+Common::Path resolveSourceFilePath(const Common::String &srcParam);
+Common::SeekableReadStream *openSourceStream(const Common::Path &srcFilePath, const Common::String &srcParam, char dirSeperator);
+Common::SeekableWriteStream *openDestinationStream(Common::String &destFileName);
+bool copyStream(Common::SeekableReadStream *srcStream, Common::SeekableWriteStream *destStream);
+bool copyGameFile(const Common::String &srcParam, const Common::String &destParam);
+
+void m_new(int nargs);
+void m_dispose(int nargs);
+void m_name(int nargs);
+void m_getFullDirList(int nargs);
+void m_getFileList(int nargs);
+void m_getDirList(int nargs);
+void m_getDiskFree(int nargs);
+void m_getVolLabel(int nargs);
+void m_createDir(int nargs);
+void m_removeDir(int nargs);
+void m_getCurrDir(int nargs);
+void m_setCurrDir(int nargs);
+void m_removeFile(int nargs);
+void m_renameFile(int nargs);
+void m_copyFile(int nargs);
+void m_copyFiles(int nargs);
+void m_setAppINI(int nargs);
+void m_getAppINI(int nargs);
+void m_getWindowsDirectory(int nargs);
+void m_getWinVer(int nargs);
+void m_restartWindows(int nargs);
+void m_openFileDlg(int nargs);
+void m_saveFileDlg(int nargs);
+void m_getOFileName(int nargs);
+void m_getSFileName(int nargs);
+void m_displayDlg(int nargs);
+void m_progMgrAdd(int args);
+
+} // End of namespace MSFile
+
+} // End of namespace Director
+
+#endif
diff --git a/engines/director/module.mk b/engines/director/module.mk
index fb4fefdd5dd..eb740dcef1a 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -129,6 +129,7 @@ MODULE_OBJS = \
 	lingo/xlibs/movemousexobj.o \
 	lingo/xlibs/movieidxxobj.o \
 	lingo/xlibs/movutils.o \
+	lingo/xlibs/msfile.o \
 	lingo/xlibs/mystisle.o \
 	lingo/xlibs/openbleedwindowxcmd.o \
 	lingo/xlibs/orthoplayxobj.o \


Commit: 477fc5decad8b186d49243958cf55e527a78a149
    https://github.com/scummvm/scummvm/commit/477fc5decad8b186d49243958cf55e527a78a149
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Channels need to be initialized earlier.

This handles cases where we tell a window and then immediately update it. Fixes loading dialog in The Simpsons Cartoon Studio

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index d6bf0e0f996..1ea533cb051 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -326,7 +326,7 @@ void Score::startPlay() {
 	updateCurrentFrame();
 
 	// All frames in the same movie have the same number of channels
-	if (_playState != kPlayStopped)
+	if (_playState != kPlayStopped && _channels.size() == 0)
 		for (uint i = 0; i < _currentFrame->_sprites.size(); i++)
 			_channels.push_back(new Channel(this, _currentFrame->_sprites[i], i));
 
@@ -1988,6 +1988,12 @@ void Score::setSpriteCasts() {
 			 j, _currentFrame->_sprites[j]->_castId.asString().c_str(), _currentFrame->_sprites[j]->_spriteType,
 			spriteType2str(_currentFrame->_sprites[j]->_spriteType));
 	}
+
+	if (_channels.size() == 0) {
+		for (uint i = 0; i < _currentFrame->_sprites.size(); i++) {
+			_channels.push_back(new Channel(this, _currentFrame->_sprites[i], i));
+		}
+	}
 }
 
 void Score::loadLabels(Common::SeekableReadStreamEndian &stream) {


Commit: 71e9985541ebcf7e3cf0d139096040d18bfb05fc
    https://github.com/scummvm/scummvm/commit/71e9985541ebcf7e3cf0d139096040d18bfb05fc
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR, COMMON: Add support for The Simpsons Cartoon Studio

The Simpsons Cartoon Studio checks for a preLoad field but ScummVM does
not do preloading. Always return 0 for the preLoad field.

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


diff --git a/engines/director/castmember/castmember.cpp b/engines/director/castmember/castmember.cpp
index 1e4fba2945b..ce593308e4f 100644
--- a/engines/director/castmember/castmember.cpp
+++ b/engines/director/castmember/castmember.cpp
@@ -155,6 +155,7 @@ bool CastMember::hasField(int field) {
 	case kTheName:
 	case kTheNumber:
 	case kTheRect:
+	case kThePreLoad:
 	case kThePurgePriority:
 	case kTheScriptText:
 	case kTheSize:
@@ -227,6 +228,15 @@ Datum CastMember::getField(int field) {
 		// not sure get the initial rect would be fine to castmember
 		d = Datum(_cast->getCastMember(_castId)->_initialRect);
 		break;
+	/*
+	ScummVM does not do preloading so we will always return false here.
+
+	simpsonscartoonstudio checks this flag and if set to true does an updateStage
+	in a loop which causes performance issues loading cartoons.
+	*/
+	case kThePreLoad:
+		d = 0;
+		break;
 	case kThePurgePriority:
 		d = _purgePriority;
 		break;
@@ -288,6 +298,11 @@ void CastMember::setField(int field, const Datum &d) {
 	case kTheRect:
 		warning("CastMember::setField(): Attempt to set read-only field \"%s\" of cast %d", g_lingo->field2str(field), _castId);
 		return;
+	/*
+	ScummVM does not do preloading so we will make this a no-op.
+	*/
+	case kThePreLoad:
+		return;
 	case kThePurgePriority:
 		_purgePriority = CLIP<int>(d.asInt(), 0, 3);
 		return;


Commit: c548cede6f68d1c63f620966d90b3e47811174b5
    https://github.com/scummvm/scummvm/commit/c548cede6f68d1c63f620966d90b3e47811174b5
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Fixed sizing issue with text castmembers.

In The Simpsons Cartoon Studio the cartoon loading dialog would grow every time the cartoon was changed. Changing MAX to MIN for the right and bottom dims fixed the issue and the loading dialog no longer grows every time the cartoon is changed.

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


diff --git a/engines/director/castmember/text.cpp b/engines/director/castmember/text.cpp
index 8a470dbbbc9..2203e8b57ab 100644
--- a/engines/director/castmember/text.cpp
+++ b/engines/director/castmember/text.cpp
@@ -323,8 +323,8 @@ Graphics::MacWidget *TextCastMember::createWidget(Common::Rect &bbox, Channel *c
 			dims.bottom = MIN<int>(dims.bottom, dims.top + _initialRect.height());
 		} else if (_textType == kTextTypeFixed || _textType == kTextTypeScrolling) {
 			// use initialRect to create widget for fixed style text, this maybe related to version.
-			dims.right = MAX<int>(dims.right, dims.left + _initialRect.width());
-			dims.bottom = MAX<int>(dims.bottom, dims.top + MAX<int>(_initialRect.height(), _maxHeight));
+			dims.right = MIN<int>(dims.right, dims.left + _initialRect.width());
+			dims.bottom = MIN<int>(dims.bottom, dims.top + MAX<int>(_initialRect.height(), _maxHeight));
 		}
 		widget = createWindowOrWidget(bbox, dims, macFont);
 		if (_textType != kTextTypeScrolling) {


Commit: 4be5a42d5a9c3cce3dce6f862cafb1519b73b8fb
    https://github.com/scummvm/scummvm/commit/4be5a42d5a9c3cce3dce6f862cafb1519b73b8fb
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Improve getFileNameFromModal extension filtering.

Add support for filtering by a file extension other than txt in getFileNameFromModal. This is used by The Simpsons Cartoon Studio cartoon import

Changed paths:
    engines/director/util.cpp


diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index aa9a61b1425..d6b553441c3 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -995,6 +995,14 @@ Common::String getFileNameFromModal(bool save, const Common::String &suggested,
 	if (ext) {
 		mask += ".";
 		mask += ext;
+
+		/*
+		 The file browser dialog and the save system forces a .txt file extension.
+		 To support other file extensions we need to add .txt to the end if the file extension is different.
+		*/
+		if (strncmp(ext, "txt", 3) != 0) {
+			mask += ".txt";
+		}
 	}
 	GUI::FileBrowserDialog browser(title.c_str(), "txt", save ? GUI::kFBModeSave : GUI::kFBModeLoad, mask.c_str(), suggested.c_str());
 	if (browser.runModal() <= 0) {


Commit: 8729519410d116976f9d44103afd628508028dad
    https://github.com/scummvm/scummvm/commit/8729519410d116976f9d44103afd628508028dad
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Add missing inflate method.

This is used by The Simpsons Cartoon Studio when a character or prop is selected.

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


diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 125978144ba..edb702ab249 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -210,6 +210,8 @@ static const BuiltinProto builtins[] = {
 	{ "updateFrame",	LB::b_updateFrame,	0, 0, 500, CBLTIN },	//				D5 c
 	// Point
 	{ "point",			LB::b_point,		2, 2, 400, FBLTIN },	//			D4 f
+	// Rect
+	{ "inflate",        LB::b_inflate,      2, 3, 400, FBLTIN },    //			D4 f
 	{ "inside",			LB::b_inside,		2, 2, 400, FBLTIN },	//			D4 f
 	{ "intersect",		LB::b_intersect,	2, 2, 400, FBLTIN },	//			D4 f
 	{ "map",			LB::b_map,			3, 3, 400, FBLTIN },	//			D4 f
@@ -3340,6 +3342,35 @@ void LB::b_intersect(int nargs) {
 	g_lingo->push(d);
 }
 
+void LB::b_inflate(int nargs) {
+	int inflateHeight = g_lingo->pop().asInt();
+	int inflateWidth = g_lingo->pop().asInt();
+	Datum sR = g_lingo->pop();
+
+	TYPECHECK(sR, RECT);
+
+	Common::Rect sourceRect(sR.u.farr->arr[0].asInt(),
+		                    sR.u.farr->arr[1].asInt(),
+		                    sR.u.farr->arr[2].asInt(),
+		                    sR.u.farr->arr[3].asInt());
+
+	int inflatedLeft = sourceRect.left - inflateWidth;
+	int inflatedTop = sourceRect.top - inflateHeight;
+	int inflatedRight = sourceRect.right + inflateWidth;
+	int inflatedBottom = sourceRect.bottom + inflateHeight;
+
+	Datum inflatedRect;
+	inflatedRect.type = RECT;
+
+	inflatedRect.u.farr = new FArray();
+	inflatedRect.u.farr->arr.push_back(Datum(inflatedLeft));
+	inflatedRect.u.farr->arr.push_back(Datum(inflatedTop));
+	inflatedRect.u.farr->arr.push_back(Datum(inflatedRight));
+	inflatedRect.u.farr->arr.push_back(Datum(inflatedBottom));
+
+	g_lingo->push(inflatedRect);
+}
+
 void LB::b_inside(int nargs) {
 	Datum d;
 	Datum r2 = g_lingo->pop();
diff --git a/engines/director/lingo/lingo-builtins.h b/engines/director/lingo/lingo-builtins.h
index f46c49f25fb..f9ea571beea 100644
--- a/engines/director/lingo/lingo-builtins.h
+++ b/engines/director/lingo/lingo-builtins.h
@@ -173,6 +173,7 @@ void b_xFactoryList(int nargs);
 void b_xtra(int nargs);
 
 void b_point(int nargs);
+void b_inflate(int nargs);
 void b_inside(int nargs);
 void b_intersect(int nargs);
 void b_map(int nargs);


Commit: dd5eb8ea799efb94dde9df4036f7b23e5a3f2d9e
    https://github.com/scummvm/scummvm/commit/dd5eb8ea799efb94dde9df4036f7b23e5a3f2d9e
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Fix file encoding for FileIO m_writeString.

Before the writeString method was always writing a UTF-8 file encoding. If a game expects MacRoman encoding and uses non printable characters then using UTF-8 encoding can break save files. This fixes saving cartoons in The Simpsons Cartoon Studio.

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


diff --git a/engines/director/lingo/xlibs/fileio.cpp b/engines/director/lingo/xlibs/fileio.cpp
index 8ef6feca48d..9d74c0341f0 100644
--- a/engines/director/lingo/xlibs/fileio.cpp
+++ b/engines/director/lingo/xlibs/fileio.cpp
@@ -573,7 +573,10 @@ void FileIO::m_writeString(int nargs) {
 		return;
 	}
 
-	me->_outStream->writeString(d.asString());
+	Common::U32String unicodeString = Common::U32String(d.asString(), Common::kUtf8);
+	Common::String encodedString = unicodeString.encode(g_director->getPlatformEncoding());
+	me->_outStream->writeString(encodedString);
+
 	g_lingo->push(Datum(kErrorNone));
 }
 


Commit: ae2fe10f422debb049ceeaab902d8e4bd885aff0
    https://github.com/scummvm/scummvm/commit/ae2fe10f422debb049ceeaab902d8e4bd885aff0
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Add saveFilePaths for The Simpsons Cartoon Studio.

The Simpsons Cartoon Studio expects to save cartoons to the TOONDATA folder.

Changed paths:
    engines/director/game-quirks.cpp


diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index bbd3568a243..11e656cfe44 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -147,6 +147,8 @@ struct SaveFilePath {
 	const char *path;
 } const saveFilePaths[] = {
 	{ "darkeye", Common::kPlatformWindows, "SAVEDDKY/" },
+	{"simpsonsstudio", Common::kPlatformWindows, "SIMPSONS/SUPPORT/TOONDATA/"},
+	{"simpsonsstudio", Common::kPlatformMacintosh, "SIMPSONS/SUPPORT/TOONDATA/"},
 	{ nullptr, Common::kPlatformUnknown, nullptr },
 };
 


Commit: e7125ac2b1991d5f42deb4b9eca3f44ff93ea889
    https://github.com/scummvm/scummvm/commit/e7125ac2b1991d5f42deb4b9eca3f44ff93ea889
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Update save file cache when using getNthFileNameInFolder.

In The Simpsons Cartoon Studio if we save a cartoon and then try to open it up in the same session the cartoon would not show up in the open file dialog unless we update the cache

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


diff --git a/engines/director/game-quirks.cpp b/engines/director/game-quirks.cpp
index 11e656cfe44..70fc5d8657d 100644
--- a/engines/director/game-quirks.cpp
+++ b/engines/director/game-quirks.cpp
@@ -349,6 +349,12 @@ void DirectorEngine::gameQuirks(const char *target, Common::Platform platform) {
 	if (!list.empty()) {
 		CachedArchive *archive = new CachedArchive(list);
 
+		// If gameQuirks is called as an update we need to remove the old quirks cache
+		// archive before adding the new one.
+		if (SearchMan.hasArchive(kQuirksCacheArchive)) {
+			SearchMan.remove(kQuirksCacheArchive);
+		}
+
 		SearchMan.add(kQuirksCacheArchive, archive);
 	}
 }
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index edb702ab249..da127bb4165 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -1493,6 +1493,10 @@ void LB::b_getNthFileNameInFolder(int nargs) {
 	Datum r("");
 	Common::Array<Common::String> fileNameList;
 
+	// Update the game quirks archive in case our save state has changed.
+	// This is necessary because we may save a game and then try to open a game in the same session.
+	g_director->gameQuirks(g_director->getGameId(), g_director->getPlatform());
+
 	// First, mix in any files injected from the quirks
 	Common::Archive *cache = SearchMan.getArchive(kQuirksCacheArchive);
 	if (cache) {


Commit: 9702201987467fb6abb3e08d03eaf970fb75326a
    https://github.com/scummvm/scummvm/commit/9702201987467fb6abb3e08d03eaf970fb75326a
Author: Donald May (donaldmay at acm.org)
Date: 2025-09-08T18:18:07+02:00

Commit Message:
DIRECTOR: Fix startMovie ordering.

The startMovie event needs to be called before we process the first
frame, not after. This fixes dialog buttons on Simpsons Cartoon Studio
where startMovie was being called after the show function which meant
that the sprites did not get puppeted as expected.

Changed paths:
    engines/director/score.cpp


diff --git a/engines/director/score.cpp b/engines/director/score.cpp
index 1ea533cb051..06e526dc2fc 100644
--- a/engines/director/score.cpp
+++ b/engines/director/score.cpp
@@ -322,6 +322,9 @@ void Score::startPlay() {
 		return;
 	}
 
+	if (_vm->getVersion() >= 300)
+		_movie->processEvent(kEventStartMovie);
+
 	// load first frame (either 1 or _nextFrame)
 	updateCurrentFrame();
 
@@ -334,9 +337,6 @@ void Score::startPlay() {
 
 	_soundManager->disablePuppetSound(1);
 	_soundManager->disablePuppetSound(2);
-
-	if (_vm->getVersion() >= 300)
-		_movie->processEvent(kEventStartMovie);
 }
 
 void Score::step() {




More information about the Scummvm-git-logs mailing list