[Scummvm-git-logs] scummvm master -> 5915f6fc1267d3a9d40329eee6b374eb3248ce50

sev- noreply at scummvm.org
Fri Mar 24 20:12:01 UTC 2023


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

Summary:
c8ce35075a COMMON: Add updateStartSettings() method to OSystem
4885225174 COMMON: Move autorun detection code to OSystem::updateStartSettings()
883a68710b MACOSX: Implement autorun and initial config detection in app bundle
41bb796ef6 MACOSX: Use bundle name for config and log file names
3596dce56d MACOSX: Remove wrapper functions for pasteboard access
f34afded5a MACOSX: Support reading scummvm-autorun file in app bundle for additional arguments
ed193bc449 BASE: Add --no-exit command line flag
558db07a6e MACOSX: Automatically add games from bundle Resources/games/ folder on launch
20f7787a12 MACOSX: Only detect games in bundle on first run after version change
4dff8f6220 IOS7: Support detecting, adding, and starting games from bundle
cbd2b736df BACKENDS: Add possibility to specify virtual drive in ChRootFilesystemFactory
308c409a87 IOS7: Fix detecting and running games directly in bundle
5915f6fc12 DOC: Update autostart description for macOS and iOS


Commit: c8ce35075acb0a6f6601ea69a0f7281716ecf73c
    https://github.com/scummvm/scummvm/commit/c8ce35075acb0a6f6601ea69a0f7281716ecf73c
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
COMMON: Add updateStartSettings() method to OSystem

This lets backend customize the start settings. For example
they can auto-start a game under some circumstances.

Changed paths:
    base/main.cpp
    common/system.h


diff --git a/base/main.cpp b/base/main.cpp
index c85d26fc12a..90a1e4d7c53 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -424,15 +424,15 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 	bool autodetect = false;
 
 	// Check for the autorun name
+	Common::String executable;
 	if (argc && argv && argv[0]) {
 		const char *s = strrchr(argv[0], '/');
-
 		if (!s)
 			s = strrchr(argv[0], '\\');
 
-		const char *appName =s ? (s + 1) : argv[0];
+		executable = s ? (s + 1) : argv[0];
 
-		if (!scumm_strnicmp(appName, "scummvm-auto", strlen("scummvm-auto"))) {
+		if (executable.equalsIgnoreCase("scummvm-auto")) {
 			warning("Will run in autodetection mode");
 			autodetect = true;
 		}
@@ -502,6 +502,35 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 
 	command = Base::parseCommandLine(settings, argc, argv);
 
+	Common::StringArray additionalArgs;
+	system.updateStartSettings(executable, command, settings, additionalArgs);
+
+	if (!additionalArgs.empty()) {
+		// Parse those additional command line arguments.
+		additionalArgs.insert_at(0, executable);
+		uint argumentsSize = additionalArgs.size();
+		char **arguments = (char **)malloc(argumentsSize * sizeof(char *));
+		for (uint i = 0; i < argumentsSize; i++) {
+			arguments[i] = (char *)malloc(additionalArgs[i].size() + 1);
+			Common::strlcpy(arguments[i], additionalArgs[i].c_str(), additionalArgs[i].size() + 1);
+		}
+
+		Common::StringMap additionalSettings;
+		Common::String additionalCommand = Base::parseCommandLine(additionalSettings, argumentsSize, arguments);
+
+		for (uint i = 0; i < argumentsSize; i++)
+			free(arguments[i]);
+		free(arguments);
+
+		// Merge additional settings and command with command line. Command line has priority.
+		if (command.empty())
+			command = additionalCommand;
+		for (Common::StringMap::const_iterator x = additionalSettings.begin(); x != additionalSettings.end(); ++x) {
+			if (!settings.contains(x->_key))
+				settings[x->_key] = x->_value;
+		}
+	}
+
 	// We allow overriding the automatic command
 	if (command.empty())
 		command = autoCommand;
diff --git a/common/system.h b/common/system.h
index 478cd2dcf3e..c308ee95a1f 100644
--- a/common/system.h
+++ b/common/system.h
@@ -27,6 +27,7 @@
 #include "common/array.h" // For OSystem::getGlobalKeymaps()
 #include "common/list.h" // For OSystem::getSupportedFormats()
 #include "common/ustr.h"
+#include "common/hash-str.h" // For Common::StringMap used in OSystem::updateStartSettings()
 #include "graphics/pixelformat.h"
 #include "graphics/mode.h"
 #include "graphics/opengl/context.h"
@@ -324,6 +325,15 @@ public:
 	 */
 	virtual void engineDone() { }
 
+	/**
+	 * Allow the backend to customize the start settings, such as for example starting
+	 * automatically a game under certain circumstances.
+	 *
+	 * This function is called after the command line parameters have been parsed,
+	 * and thus the initial value of command and settings will reflect those.
+	 */
+	virtual void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &startSettings, Common::StringArray& additionalArgs) { }
+
 	/**
 	 * @defgroup common_system_flags Feature flags
 	 * @ingroup common_system


Commit: 4885225174265c5d1411b1b9a3e8a2f909566d8a
    https://github.com/scummvm/scummvm/commit/4885225174265c5d1411b1b9a3e8a2f909566d8a
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
COMMON: Move autorun detection code to OSystem::updateStartSettings()

Changed paths:
    base/main.cpp
    common/system.cpp
    common/system.h


diff --git a/base/main.cpp b/base/main.cpp
index 90a1e4d7c53..44098d82e02 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -42,7 +42,6 @@
 #include "common/debug-channels.h" /* for debug manager */
 #include "common/events.h"
 #include "gui/EventRecorder.h"
-#include "common/file.h"
 #include "common/fs.h"
 #ifdef ENABLE_EVENTRECORDER
 #include "common/recorderfile.h"
@@ -420,88 +419,16 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 
 	// Parse the command line
 	Common::StringMap settings;
-	Common::String autoCommand;
-	bool autodetect = false;
+	command = Base::parseCommandLine(settings, argc, argv);
 
-	// Check for the autorun name
+	// Check for backend start settings
 	Common::String executable;
 	if (argc && argv && argv[0]) {
 		const char *s = strrchr(argv[0], '/');
 		if (!s)
 			s = strrchr(argv[0], '\\');
-
 		executable = s ? (s + 1) : argv[0];
-
-		if (executable.equalsIgnoreCase("scummvm-auto")) {
-			warning("Will run in autodetection mode");
-			autodetect = true;
-		}
-	}
-
-	Common::StringArray autorunArgs;
-
-	// Check for the autorun file
-	if (Common::File::exists("scummvm-autorun")) {
-		// Okay, the file exists. We open it and if it is empty, then run in the autorun mode
-		// If the file is not empty, we read command line arguments from it, one per line
-		warning("Autorun file is detected");
-
-		Common::File autorun;
-		Common::String line;
-		Common::String res;
-
-		autorunArgs.push_back(argc && argv ? argv[0] : "");
-
-		if (autorun.open("scummvm-autorun")) {
-			while (!autorun.eos()) {
-				line = autorun.readLine();
-
-				if (!line.empty() && line[0] != '#') {
-					autorunArgs.push_back(line);
-
-					res += Common::String::format("\"%s\" ", line.c_str());
-				}
-			}
-		}
-
-		if (!res.empty())
-			warning("Autorun command: %s", res.c_str());
-		else
-			warning("Empty autorun file");
-
-		autorun.close();
-
-		autodetect = true;
 	}
-
-	if (autodetect) {
-		if (autorunArgs.size() > 1) {
-			uint argumentsSize = autorunArgs.size();
-			char **arguments = (char **)malloc(argumentsSize * sizeof(char *));
-
-			for (uint i = 0; i < argumentsSize; i++) {
-				arguments[i] = (char *)malloc(autorunArgs[i].size() + 1);
-				Common::strlcpy(arguments[i], autorunArgs[i].c_str(), autorunArgs[i].size() + 1);
-			}
-
-			autoCommand = Base::parseCommandLine(settings, argumentsSize, arguments);
-
-			for (uint i = 0; i < argumentsSize; i++)
-				free(arguments[i]);
-
-			free(arguments);
-		} else {
-			// Simulate autodetection
-			const char * const arguments[] = { "scummvm-auto", "-p", ".", "--auto-detect" };
-
-			warning("Running autodetection");
-
-			autoCommand = Base::parseCommandLine(settings, ARRAYSIZE(arguments), arguments);
-		}
-	}
-
-	command = Base::parseCommandLine(settings, argc, argv);
-
 	Common::StringArray additionalArgs;
 	system.updateStartSettings(executable, command, settings, additionalArgs);
 
@@ -531,10 +458,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 		}
 	}
 
-	// We allow overriding the automatic command
-	if (command.empty())
-		command = autoCommand;
-
 	// Load the config file (possibly overridden via command line):
 	Common::String initConfigFilename;
 	if (settings.contains("initial-cfg"))
diff --git a/common/system.cpp b/common/system.cpp
index b9a9d363fc4..07854eab6ed 100644
--- a/common/system.cpp
+++ b/common/system.cpp
@@ -24,6 +24,7 @@
 #include "common/system.h"
 #include "common/events.h"
 #include "common/fs.h"
+#include "common/file.h"
 #include "common/savefile.h"
 #include "common/str.h"
 #include "common/taskbar.h"
@@ -120,6 +121,56 @@ void OSystem::destroy() {
 	delete this;
 }
 
+void OSystem::updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
+	// If a command was explicitly passed on the command line, do not override it
+	if (!command.empty())
+		return;
+
+	bool autodetect = false;
+
+	// Check executable name
+	if (executable.equalsIgnoreCase("scummvm-auto")) {
+		warning("Will run in autodetection mode");
+		autodetect = true;
+	}
+
+	// Check for the autorun file
+	if (Common::File::exists("scummvm-autorun")) {
+		// Okay, the file exists. We open it and if it is empty, then run in the autorun mode
+		// If the file is not empty, we read command line arguments from it, one per line
+		warning("Autorun file is detected");
+
+		Common::File autorun;
+		Common::String line;
+		Common::String res;
+
+		if (autorun.open("scummvm-autorun")) {
+			while (!autorun.eos()) {
+				line = autorun.readLine();
+				if (!line.empty() && line[0] != '#') {
+					additionalArgs.push_back(line);
+					res += Common::String::format("\"%s\" ", line.c_str());
+				}
+			}
+		}
+
+		if (!res.empty())
+			warning("Autorun command: %s", res.c_str());
+		else
+			warning("Empty autorun file");
+
+		autorun.close();
+		autodetect = true;
+	}
+
+	if (autodetect && additionalArgs.empty()) {
+		warning("Running autodetection");
+		command = "auto-detect";
+		if (!settings.contains("path"))
+			settings["path"] = ".";
+	}
+}
+
 bool OSystem::setGraphicsMode(const char *name) {
 	if (!name)
 		return false;
diff --git a/common/system.h b/common/system.h
index c308ee95a1f..e1021926bf3 100644
--- a/common/system.h
+++ b/common/system.h
@@ -27,7 +27,8 @@
 #include "common/array.h" // For OSystem::getGlobalKeymaps()
 #include "common/list.h" // For OSystem::getSupportedFormats()
 #include "common/ustr.h"
-#include "common/hash-str.h" // For Common::StringMap used in OSystem::updateStartSettings()
+#include "common/str-array.h" // For OSystem::updateStartSettings()
+#include "common/hash-str.h" // For OSystem::updateStartSettings()
 #include "graphics/pixelformat.h"
 #include "graphics/mode.h"
 #include "graphics/opengl/context.h"
@@ -331,8 +332,11 @@ public:
 	 *
 	 * This function is called after the command line parameters have been parsed,
 	 * and thus the initial value of command and settings will reflect those.
+	 *
+	 * The default implementation checks if the executable name is "scummvm-auto"
+	 * or if a file named "scummvm-autorun" sits next to it to enable autorun mode.
 	 */
-	virtual void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &startSettings, Common::StringArray& additionalArgs) { }
+	virtual void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &startSettings, Common::StringArray& additionalArgs);
 
 	/**
 	 * @defgroup common_system_flags Feature flags


Commit: 883a68710b9b042713a42695679ae0baa78a61a1
    https://github.com/scummvm/scummvm/commit/883a68710b9b042713a42695679ae0baa78a61a1
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Implement autorun and initial config detection in app bundle

Changed paths:
  A backends/platform/sdl/macosx/macosx_osys_misc.mm
    backends/platform/sdl/macosx/macosx.h
    backends/platform/sdl/module.mk


diff --git a/backends/platform/sdl/macosx/macosx.h b/backends/platform/sdl/macosx/macosx.h
index 0edd35e869a..40235b87d21 100644
--- a/backends/platform/sdl/macosx/macosx.h
+++ b/backends/platform/sdl/macosx/macosx.h
@@ -43,6 +43,7 @@ public:
 	void init() override;
 	void initBackend() override;
 	void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0) override;
+	void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) override;
 
 #ifdef USE_OPENGL
 	GraphicsManagerType getDefaultGraphicsManager() const override;
diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
new file mode 100644
index 00000000000..b14ac7df892
--- /dev/null
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -0,0 +1,57 @@
+/* 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/>.
+ *
+ */
+
+// Disable symbol overrides so that we can use system headers.
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/platform/sdl/macosx/macosx.h"
+
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSFileManager.h>
+
+void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
+	NSBundle* bundle = [NSBundle mainBundle];
+	// Check if scummvm is running from an app bundle
+	if (!bundle || ![bundle bundleIdentifier]) {
+		// Use default autostart implementation
+		OSystem_POSIX::updateStartSettings(executable, command, settings, additionalArgs);
+		return;
+	}
+
+	// If the bundle contains a scummvm.ini, use it as initial config
+	NSString *iniPath = [bundle pathForResource:@"scummvm" ofType:@"ini"];
+	if (iniPath && !settings.contains("initial-cfg"))
+		settings["initial-cfg"] = Common::String([iniPath fileSystemRepresentation]);
+
+	// If a command was specified on the command line, do not override it
+	if (!command.empty())
+		return;
+
+	// If the bundle contains a game directory, auto-detect it
+	NSString *gamePath = [[bundle resourcePath] stringByAppendingPathComponent:@"game"];
+	BOOL isDir = false;
+	BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:gamePath isDirectory:&isDir];
+	if (exists && isDir) {
+		// Ause auto-detection
+		command = "auto-detect";
+		settings["path"] = [gamePath fileSystemRepresentation];
+	}
+}
diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk
index c5095560193..06480af4ce9 100644
--- a/backends/platform/sdl/module.mk
+++ b/backends/platform/sdl/module.mk
@@ -24,6 +24,7 @@ MODULE_OBJS += \
 	macosx/macosx-touchbar.o \
 	macosx/macosx-window.o \
 	macosx/macosx_wrapper.o \
+	macosx/macosx_osys_misc.o \
 	macosx/appmenu_osx.o
 endif
 


Commit: 41bb796ef66890bc5ee0947edc9e95a19703ca7a
    https://github.com/scummvm/scummvm/commit/41bb796ef66890bc5ee0947edc9e95a19703ca7a
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Use bundle name for config and log file names

The idea here is that we can package a game in a custom bundle using
the scummvm executable, and use the game name as bundle name. It will
then use its own config and log files rather than share the ones from
the standalone ScummVM app.

Changed paths:
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx_wrapper.h
    backends/platform/sdl/macosx/macosx_wrapper.mm


diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index b422722a296..f002b8cc78a 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -231,7 +231,7 @@ Common::String OSystem_MacOSX::getSystemLanguage() const {
 }
 
 Common::String OSystem_MacOSX::getDefaultConfigFileName() {
-	const Common::String baseConfigName = "Library/Preferences/ScummVM Preferences";
+	const Common::String baseConfigName = "Library/Preferences/" + getMacBundleName() + " Preferences";
 
 	Common::String configFile;
 
@@ -258,7 +258,9 @@ Common::String OSystem_MacOSX::getDefaultLogFileName() {
 		return Common::String();
 	}
 
-	return Common::String(prefix) + "/Library/Logs/scummvm.log";
+	Common::String appName = getMacBundleName();
+	appName.toLowercase();
+	return Common::String(prefix) + "/Library/Logs/" + appName + ".log";
 }
 
 Common::String OSystem_MacOSX::getDefaultIconsPath() {
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.h b/backends/platform/sdl/macosx/macosx_wrapper.h
index b454ff5d52c..fffe3586aa5 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.h
+++ b/backends/platform/sdl/macosx/macosx_wrapper.h
@@ -31,5 +31,6 @@ bool setTextInClipboardMacOSX(const Common::U32String &text);
 Common::String getDesktopPathMacOSX();
 Common::String getResourceAppBundlePathMacOSX();
 Common::String getAppSupportPathMacOSX();
+Common::String getMacBundleName();
 
 #endif
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.mm b/backends/platform/sdl/macosx/macosx_wrapper.mm
index f3ad6414b2d..2ab7da4b1b6 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.mm
+++ b/backends/platform/sdl/macosx/macosx_wrapper.mm
@@ -31,6 +31,7 @@
 #include <Foundation/NSPathUtilities.h>
 #include <AvailabilityMacros.h>
 #include <CoreFoundation/CFString.h>
+#include <CoreFoundation/CFBundle.h>
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
 #define NSPasteboardTypeString NSStringPboardType
@@ -134,3 +135,10 @@ Common::String getAppSupportPathMacOSX() {
 		return Common::String();
 	return Common::String([path fileSystemRepresentation]) + "/ScummVM";
 }
+
+Common::String getMacBundleName() {
+	NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(id)kCFBundleNameKey];
+	if (!appName)
+		return Common::String("ScummVM");
+	return Common::String([appName UTF8String]);
+}


Commit: 3596dce56d2fd22d35d02d5e4614cd2f5e863da3
    https://github.com/scummvm/scummvm/commit/3596dce56d2fd22d35d02d5e4614cd2f5e863da3
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Remove wrapper functions for pasteboard access

Instead the OSystem functions are now directly implemented in
Objective C.

Changed paths:
    backends/platform/sdl/macosx/macosx.cpp
    backends/platform/sdl/macosx/macosx_osys_misc.mm
    backends/platform/sdl/macosx/macosx_wrapper.h
    backends/platform/sdl/macosx/macosx_wrapper.mm


diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp
index f002b8cc78a..165efc2db20 100644
--- a/backends/platform/sdl/macosx/macosx.cpp
+++ b/backends/platform/sdl/macosx/macosx.cpp
@@ -164,18 +164,6 @@ bool OSystem_MacOSX::displayLogFile() {
 	return err != noErr;
 }
 
-bool OSystem_MacOSX::hasTextInClipboard() {
-	return hasTextInClipboardMacOSX();
-}
-
-Common::U32String OSystem_MacOSX::getTextFromClipboard() {
-	return getTextFromClipboardMacOSX();
-}
-
-bool OSystem_MacOSX::setTextInClipboard(const Common::U32String &text) {
-	return setTextInClipboardMacOSX(text);
-}
-
 bool OSystem_MacOSX::openUrl(const Common::String &url) {
 	CFURLRef urlRef = CFURLCreateWithBytes (NULL, (const UInt8*)url.c_str(), url.size(), kCFStringEncodingASCII, NULL);
 	OSStatus err = LSOpenCFURLRef(urlRef, NULL);
diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
index b14ac7df892..5a9da750914 100644
--- a/backends/platform/sdl/macosx/macosx_osys_misc.mm
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -26,6 +26,31 @@
 
 #include <Foundation/NSBundle.h>
 #include <Foundation/NSFileManager.h>
+#include <Foundation/NSArray.h>
+#include <AppKit/NSPasteboard.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+#define NSPasteboardTypeString NSStringPboardType
+#endif
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Cocoa64BitGuide/64BitChangesCocoa/64BitChangesCocoa.html
+#if __LP64__ || NS_BUILD_32_LIKE_64
+typedef unsigned long NSUInteger;
+#else
+typedef unsigned int NSUInteger;
+#endif
+
+// Those are not defined in the 10.4 SDK, but they are defined when targeting
+// Mac OS X 10.4 or above in the 10.5 SDK, and they do work with 10.4.
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+enum {
+	NSUTF32StringEncoding = 0x8c000100,
+	NSUTF32BigEndianStringEncoding = 0x98000100,
+	NSUTF32LittleEndianStringEncoding = 0x9c000100
+};
+#endif
+#endif
 
 void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
 	NSBundle* bundle = [NSBundle mainBundle];
@@ -55,3 +80,51 @@ void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Comm
 		settings["path"] = [gamePath fileSystemRepresentation];
 	}
 }
+
+bool OSystem_MacOSX::hasTextInClipboard() {
+	return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]] != nil;
+}
+
+Common::U32String OSystem_MacOSX::getTextFromClipboard() {
+	if (!hasTextInClipboard())
+		return Common::U32String();
+
+	NSPasteboard *pb = [NSPasteboard generalPasteboard];
+	NSString *str = [pb  stringForType:NSPasteboardTypeString];
+	if (![str respondsToSelector:@selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:)])
+		return Common::U32String();
+
+	// If translations are supported, use the current TranslationManager charset and otherwise
+	// use ASCII. If the string cannot be represented using the requested encoding we get a null
+	// pointer below, which is fine as ScummVM would not know what to do with the string anyway.
+#ifdef SCUMM_LITTLE_ENDIAN
+	NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
+#else
+	NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
+#endif
+	NSUInteger textLength = [str length];
+	uint32 *text = new uint32[textLength];
+	if (![str getBytes:text maxLength:4*textLength usedLength:NULL encoding: stringEncoding options:0 range:NSMakeRange(0, textLength) remainingRange:NULL]) {
+		delete[] text;
+		return Common::U32String();
+	}
+	Common::U32String u32String(text, textLength);
+	delete[] text;
+
+	return u32String;
+}
+
+bool OSystem_MacOSX::setTextInClipboard(const Common::U32String &text) {
+	NSPasteboard *pb = [NSPasteboard generalPasteboard];
+	[pb declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
+
+#ifdef SCUMM_LITTLE_ENDIAN
+	NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
+#else
+	NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
+#endif
+	NSString *nsstring = [[NSString alloc] initWithBytes:text.c_str() length:4*text.size() encoding: stringEncoding];
+	bool status =  [pb setString:nsstring forType:NSPasteboardTypeString];
+	[nsstring release];
+	return status;
+}
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.h b/backends/platform/sdl/macosx/macosx_wrapper.h
index fffe3586aa5..d081d070045 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.h
+++ b/backends/platform/sdl/macosx/macosx_wrapper.h
@@ -23,11 +23,7 @@
 #define PLATFORM_SDL_MACOSX_WRAPPER_H
 
 #include <common/str.h>
-#include <common/ustr.h>
 
-bool hasTextInClipboardMacOSX();
-Common::U32String getTextFromClipboardMacOSX();
-bool setTextInClipboardMacOSX(const Common::U32String &text);
 Common::String getDesktopPathMacOSX();
 Common::String getResourceAppBundlePathMacOSX();
 Common::String getAppSupportPathMacOSX();
diff --git a/backends/platform/sdl/macosx/macosx_wrapper.mm b/backends/platform/sdl/macosx/macosx_wrapper.mm
index 2ab7da4b1b6..4a27d24dfcb 100644
--- a/backends/platform/sdl/macosx/macosx_wrapper.mm
+++ b/backends/platform/sdl/macosx/macosx_wrapper.mm
@@ -25,7 +25,6 @@
 #include "backends/platform/sdl/macosx/macosx_wrapper.h"
 #include "backends/platform/sdl/macosx/macosx-compat.h"
 
-#include <AppKit/NSPasteboard.h>
 #include <Foundation/NSArray.h>
 #include <Foundation/NSBundle.h>
 #include <Foundation/NSPathUtilities.h>
@@ -33,77 +32,6 @@
 #include <CoreFoundation/CFString.h>
 #include <CoreFoundation/CFBundle.h>
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
-#define NSPasteboardTypeString NSStringPboardType
-#endif
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
-// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Cocoa64BitGuide/64BitChangesCocoa/64BitChangesCocoa.html
-#if __LP64__ || NS_BUILD_32_LIKE_64
-typedef unsigned long NSUInteger;
-#else
-typedef unsigned int NSUInteger;
-#endif
-
-// Those are not defined in the 10.4 SDK, but they are defined when targeting
-// Mac OS X 10.4 or above in the 10.5 SDK, and they do work with 10.4.
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
-enum {
-	NSUTF32StringEncoding = 0x8c000100,
-	NSUTF32BigEndianStringEncoding = 0x98000100,
-	NSUTF32LittleEndianStringEncoding = 0x9c000100
-};
-#endif
-#endif
-
-bool hasTextInClipboardMacOSX() {
-	return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSPasteboardTypeString]] != nil;
-}
-
-Common::U32String getTextFromClipboardMacOSX() {
-	if (!hasTextInClipboardMacOSX())
-		return Common::U32String();
-
-	NSPasteboard *pb = [NSPasteboard generalPasteboard];
-	NSString *str = [pb  stringForType:NSPasteboardTypeString];
-	if (![str respondsToSelector:@selector(getBytes:maxLength:usedLength:encoding:options:range:remainingRange:)])
-		return Common::U32String();
-
-	// If translations are supported, use the current TranslationManager charset and otherwise
-	// use ASCII. If the string cannot be represented using the requested encoding we get a null
-	// pointer below, which is fine as ScummVM would not know what to do with the string anyway.
-#ifdef SCUMM_LITTLE_ENDIAN
-	NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
-#else
-	NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
-#endif
-	NSUInteger textLength = [str length];
-	uint32 *text = new uint32[textLength];
-	if (![str getBytes:text maxLength:4*textLength usedLength:NULL encoding: stringEncoding options:0 range:NSMakeRange(0, textLength) remainingRange:NULL]) {
-		delete[] text;
-		return Common::U32String();
-	}
-	Common::U32String u32String(text, textLength);
-	delete[] text;
-
-	return u32String;
-}
-
-bool setTextInClipboardMacOSX(const Common::U32String &text) {
-	NSPasteboard *pb = [NSPasteboard generalPasteboard];
-	[pb declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
-
-#ifdef SCUMM_LITTLE_ENDIAN
-	NSStringEncoding stringEncoding = NSUTF32LittleEndianStringEncoding;
-#else
-	NSStringEncoding stringEncoding = NSUTF32BigEndianStringEncoding;
-#endif
-	NSString *nsstring = [[NSString alloc] initWithBytes:text.c_str() length:4*text.size() encoding: stringEncoding];
-	bool status =  [pb setString:nsstring forType:NSPasteboardTypeString];
-	[nsstring release];
-	return status;
-}
-
 Common::String getDesktopPathMacOSX() {
 	// The recommended method is to use NSFileManager.
 	// NSUrl *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDesktopDirectory inDomains:NSUserDomainMask] firstObject];


Commit: f34afded5ac5e491cef5932195b6187e8561828a
    https://github.com/scummvm/scummvm/commit/f34afded5ac5e491cef5932195b6187e8561828a
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Support reading scummvm-autorun file in app bundle for additional arguments

Changed paths:
    backends/platform/sdl/macosx/macosx_osys_misc.mm


diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
index 5a9da750914..3982452bee1 100644
--- a/backends/platform/sdl/macosx/macosx_osys_misc.mm
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -22,6 +22,10 @@
 // Disable symbol overrides so that we can use system headers.
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
 
+// Needs to be included first as system headers redefine NO and YES, which clashes
+// with the DisposeAfterUse::Flag enum used in Common stream classes.
+#include "common/file.h"
+
 #include "backends/platform/sdl/macosx/macosx.h"
 
 #include <Foundation/NSBundle.h>
@@ -70,6 +74,21 @@ void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Comm
 	if (!command.empty())
 		return;
 
+	// Check if we have an autorun file with additional arguments
+	NSString *autorunPath = [bundle pathForResource:@"scummvm-autorun" ofType:nil];
+	if (autorunPath) {
+		Common::File autorun;
+		Common::String line;
+		if (autorun.open(Common::FSNode([autorunPath fileSystemRepresentation]))) {
+			while (!autorun.eos()) {
+				line = autorun.readLine();
+				if (!line.empty() && line[0] != '#')
+					additionalArgs.push_back(line);
+			}
+		}
+		autorun.close();
+	}
+
 	// If the bundle contains a game directory, auto-detect it
 	NSString *gamePath = [[bundle resourcePath] stringByAppendingPathComponent:@"game"];
 	BOOL isDir = false;


Commit: ed193bc449621fdb123691f07dc3fc0e5d4ed33e
    https://github.com/scummvm/scummvm/commit/ed193bc449621fdb123691f07dc3fc0e5d4ed33e
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
BASE: Add --no-exit command line flag

This allows opening the launcher after running a command line command,
such as --add. The main use for this would be for backends to be able
to easily add games from a folder on launch.

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 676cc85bfa1..9e5a9fb28d4 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -94,6 +94,8 @@ static const char HELP_STRING1[] =
 	"  --auto-detect            Display a list of games from current or specified directory\n"
 	"                           and start the first one. Use --path=PATH to specify a directory.\n"
 	"  --recursive              In combination with --add or --detect recurse down all subdirectories\n"
+	"  --no-exit                In combination with commands that exit after running, like --add or --list-engines,\n"
+	"                           open the launcher instead of exiting\n"
 #if defined(WIN32)
 	"  --console                Enable the console window (default:enabled)\n"
 #endif
@@ -904,6 +906,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_LONG_OPTION_BOOL("recursive")
 			END_OPTION
 
+			DO_LONG_OPTION_BOOL("exit")
+			END_OPTION
+
 			DO_LONG_OPTION("themepath")
 				Common::FSNode path(option);
 				if (!path.exists()) {
@@ -1730,44 +1735,47 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		}
 	}
 
+	// For commands that normally exit, check if --no-exit was specified
+	bool cmdDoExit = settings.getValOrDefault("exit", "true") == "true";
+
 	// Handle commands passed via the command line (like --list-targets and
 	// --list-games). This must be done after the config file and the plugins
 	// have been loaded.
 	if (command == "list-targets") {
 		listTargets();
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-all-debugflags") {
 		listAllEngineDebugFlags();
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-debugflags") {
 		listDebugFlags(settings["list-debugflags"]);
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-games") {
 		listGames(settings["engine"]);
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-all-games") {
 		listAllGames(settings["engine"]);
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-engines") {
 		listEngines();
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-all-engines") {
 		listAllEngines();
-		return true;
+		return cmdDoExit;
 #ifdef ENABLE_EVENTRECORDER
 	} else if (command == "list-records") {
 		err = listRecords(settings["game"]);
-		return true;
+		return cmdDoExit;
 #endif
 	} else if (command == "list-saves") {
 		err = listSaves(settings["game"]);
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-themes") {
 		listThemes();
-		return true;
+		return cmdDoExit;
 	} else if (command == "list-audio-devices") {
 		listAudioDevices();
-		return true;
+		return cmdDoExit;
 	} else if (command == "version") {
 		printf("%s\n", gScummVMFullVersion);
 #ifdef SDL_BACKEND
@@ -1780,7 +1788,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 #endif
 #endif
 		printf("Features compiled in: %s\n", gScummVMFeatures);
-		return true;
+		return cmdDoExit;
 	} else if (command == "help") {
 #ifndef DISABLE_HELP_STRINGS
 		printf(HELP_STRING1, s_appName);
@@ -1820,7 +1828,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 
 		printf(HELP_STRING4);
 #endif
-		return true;
+		return cmdDoExit;
 	} else if (command == "auto-detect") {
 		bool resursive = settings["recursive"] == "true";
 		// If auto-detects fails (returns an empty ID) return true to close ScummVM.
@@ -1829,7 +1837,7 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		if (resursive) {
 			printf("ERROR: Autodetection not supported with --recursive; are you sure you didn't want --detect?\n");
 			err = Common::kUnknownError;
-			return true;
+			return cmdDoExit;
 			// There is not a particularly good technical reason for this.
 			// From an UX point of view, however, it might get confusing.
 			// Consider removing this if consensus says otherwise.
@@ -1837,15 +1845,15 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 			command = detectGames(settings["path"], gameOption.engineId, gameOption.gameId, resursive);
 			if (command.empty()) {
 				err = Common::kNoGameDataFoundError;
-				return true;
+				return cmdDoExit;
 			}
 		}
 	} else if (command == "detect") {
 		detectGames(settings["path"], gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
-		return true;
+		return cmdDoExit;
 	} else if (command == "add") {
 		addGames(settings["path"], gameOption.engineId, gameOption.gameId, settings["recursive"] == "true");
-		return true;
+		return cmdDoExit;
 	} else if (command == "md5" || command == "md5mac") {
 		Common::String filename = settings.getValOrDefault("md5-path", "scummvm");
 		// Assume '/' separator except on Windows if the path contain at least one `\`
@@ -1882,16 +1890,16 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		} else
 			calcMD5Mac(Filename, md5Length);
 
-		return true;
+		return cmdDoExit;
 #ifdef DETECTOR_TESTING_HACK
 	} else if (command == "test-detector") {
 		runDetectorTest();
-		return true;
+		return cmdDoExit;
 #endif
 #ifdef UPGRADE_ALL_TARGETS_HACK
 	} else if (command == "upgrade-targets") {
 		upgradeTargets();
-		return true;
+		return cmdDoExit;
 #endif
 	}
 
@@ -1949,10 +1957,27 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		nullptr
 	};
 
+	// Skip some settings that should only be used for the command-line commands
+	static const char * const skipSettings[] = {
+		"recursive",
+		"exit",
+		"md5-engine",
+		"md5-length",
+		"md5-path",
+		"list-debugflags",
+		nullptr
+	};
+
 	for (Common::StringMap::const_iterator x = settings.begin(); x != settings.end(); ++x) {
 		Common::String key(x->_key);
 		Common::String value(x->_value);
 
+		bool skip = false;
+		for (auto skipKey = skipSettings; *skipKey && !skip; ++skipKey)
+			skip = (x->_key == *skipKey);
+		if (skip)
+			continue;
+
 		// Replace any "-" in the key by "_" (e.g. change "save-slot" to "save_slot").
 		for (Common::String::iterator c = key.begin(); c != key.end(); ++c)
 			if (*c == '-')


Commit: 558db07a6e3a60af602626fa2b4e5637d0b7705b
    https://github.com/scummvm/scummvm/commit/558db07a6e3a60af602626fa2b4e5637d0b7705b
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Automatically add games from bundle Resources/games/ folder on launch

Changed paths:
    backends/platform/sdl/macosx/macosx_osys_misc.mm


diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
index 3982452bee1..45208f5f45c 100644
--- a/backends/platform/sdl/macosx/macosx_osys_misc.mm
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -98,6 +98,24 @@ void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Comm
 		command = "auto-detect";
 		settings["path"] = [gamePath fileSystemRepresentation];
 	}
+
+	// Else if the bundle contains a games directory, add them to the launcher
+	// Should we only do it on first start (if the config file does not yet exist) to avoid adding
+	// backe games removed by the user? That would also speed up subsequent starts.
+	// However doing it always, means that adding more games in the bundle  in the future will
+	// properly add them to the launcher.
+	else {
+		NSString *gamesPath = [[bundle resourcePath] stringByAppendingPathComponent:@"games"];
+		isDir = false;
+		exists = [[NSFileManager defaultManager] fileExistsAtPath:gamesPath isDirectory:&isDir];
+		if (exists && isDir) {
+			// Ause auto-detection
+			command = "add";
+			settings["path"] = [gamesPath fileSystemRepresentation];
+			settings["recursive"] = "true";
+			settings["exit"] = "false";
+		}
+	}
 }
 
 bool OSystem_MacOSX::hasTextInClipboard() {


Commit: 20f7787a1263e8b3ca392290a808e77e35ef170a
    https://github.com/scummvm/scummvm/commit/20f7787a1263e8b3ca392290a808e77e35ef170a
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
MACOSX: Only detect games in bundle on first run after version change

Changed paths:
    backends/platform/sdl/macosx/macosx_osys_misc.mm


diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
index 45208f5f45c..c1d8050dc04 100644
--- a/backends/platform/sdl/macosx/macosx_osys_misc.mm
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -27,10 +27,12 @@
 #include "common/file.h"
 
 #include "backends/platform/sdl/macosx/macosx.h"
+#include "base/version.h"
 
 #include <Foundation/NSBundle.h>
 #include <Foundation/NSFileManager.h>
 #include <Foundation/NSArray.h>
+#include <Foundation/NSUserDefaults.h>
 #include <AppKit/NSPasteboard.h>
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
@@ -97,24 +99,29 @@ void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Comm
 		// Ause auto-detection
 		command = "auto-detect";
 		settings["path"] = [gamePath fileSystemRepresentation];
+		return;
 	}
 
-	// Else if the bundle contains a games directory, add them to the launcher
-	// Should we only do it on first start (if the config file does not yet exist) to avoid adding
-	// backe games removed by the user? That would also speed up subsequent starts.
-	// However doing it always, means that adding more games in the bundle  in the future will
-	// properly add them to the launcher.
-	else {
-		NSString *gamesPath = [[bundle resourcePath] stringByAppendingPathComponent:@"games"];
-		isDir = false;
-		exists = [[NSFileManager defaultManager] fileExistsAtPath:gamesPath isDirectory:&isDir];
-		if (exists && isDir) {
-			// Ause auto-detection
-			command = "add";
-			settings["path"] = [gamesPath fileSystemRepresentation];
-			settings["recursive"] = "true";
-			settings["exit"] = "false";
-		}
+	// The rest of the function has some commands executed only the first time after each version change
+	// Check the last version stored in the user settings.
+	NSString *versionString = [NSString stringWithUTF8String:gScummVMFullVersion];
+	NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+	NSString *lastVersion = [defaults stringForKey:@"lastVersion"];
+	if (lastVersion && [lastVersion isEqualToString:versionString])
+		return;
+	[defaults setObject:versionString forKey:@"lastVersion"];
+
+	// If the bundle contains a games directory, add them to the launcher
+	NSString *gamesPath = [[bundle resourcePath] stringByAppendingPathComponent:@"games"];
+	isDir = false;
+	exists = [[NSFileManager defaultManager] fileExistsAtPath:gamesPath isDirectory:&isDir];
+	if (exists && isDir) {
+		// Detect and add games
+		command = "add";
+		settings["path"] = [gamesPath fileSystemRepresentation];
+		settings["recursive"] = "true";
+		settings["exit"] = "false";
+		return;
 	}
 }
 


Commit: 4dff8f622043f239f2e088593587e92f0ef8b023
    https://github.com/scummvm/scummvm/commit/4dff8f622043f239f2e088593587e92f0ef8b023
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
IOS7: Support detecting, adding, and starting games from bundle

Changed paths:
    backends/platform/ios7/ios7_osys_main.h
    backends/platform/ios7/ios7_osys_misc.mm
    backends/platform/sdl/macosx/macosx_osys_misc.mm


diff --git a/backends/platform/ios7/ios7_osys_main.h b/backends/platform/ios7/ios7_osys_main.h
index da284f49be6..c59a4b87f1d 100644
--- a/backends/platform/ios7/ios7_osys_main.h
+++ b/backends/platform/ios7/ios7_osys_main.h
@@ -127,6 +127,8 @@ public:
 	void engineInit() override;
 	void engineDone() override;
 
+	void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) override;
+
 	bool hasFeature(Feature f) override;
 	void setFeatureState(Feature f, bool enable) override;
 	bool getFeatureState(Feature f) override;
diff --git a/backends/platform/ios7/ios7_osys_misc.mm b/backends/platform/ios7/ios7_osys_misc.mm
index 214dfebb3b7..aa3493e6dbd 100644
--- a/backends/platform/ios7/ios7_osys_misc.mm
+++ b/backends/platform/ios7/ios7_osys_misc.mm
@@ -22,8 +22,16 @@
 // Disable symbol overrides so that we can use system headers.
 #define FORBIDDEN_SYMBOL_ALLOW_ALL
 
+// Needs to be included first as system headers redefine NO and YES, which clashes
+// with the DisposeAfterUse::Flag enum used in Common stream classes.
+#include "common/file.h"
+
 #include "backends/platform/ios7/ios7_osys_main.h"
+#include "base/version.h"
 
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSUserDefaults.h>
 #include <UIKit/UIKit.h>
 #include <SystemConfiguration/SCNetworkReachability.h>
 #include "backends/platform/ios7/ios7_app_delegate.h"
@@ -37,6 +45,74 @@ static inline void execute_on_main_thread_async(void (^block)(void)) {
 	}
 }
 
+void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
+		NSBundle* bundle = [NSBundle mainBundle];
+		// Check if scummvm is running from an app bundle
+		if (!bundle || ![bundle bundleIdentifier]) {
+			// Use default autostart implementation
+			EventsBaseBackend::updateStartSettings(executable, command, settings, additionalArgs);
+			return;
+		}
+
+		// If the bundle contains a scummvm.ini, use it as initial config
+		NSString *iniPath = [bundle pathForResource:@"scummvm" ofType:@"ini"];
+		if (iniPath && !settings.contains("initial-cfg"))
+			settings["initial-cfg"] = Common::String([iniPath fileSystemRepresentation]);
+
+		// If a command was specified on the command line, do not override it
+		if (!command.empty())
+			return;
+
+		// Check if we have an autorun file with additional arguments
+		NSString *autorunPath = [bundle pathForResource:@"scummvm-autorun" ofType:nil];
+		if (autorunPath) {
+			Common::File autorun;
+			Common::String line;
+			if (autorun.open(Common::FSNode([autorunPath fileSystemRepresentation]))) {
+				while (!autorun.eos()) {
+					line = autorun.readLine();
+					if (!line.empty() && line[0] != '#')
+						additionalArgs.push_back(line);
+				}
+			}
+			autorun.close();
+		}
+
+		// If the bundle contains a game directory, auto-detect it
+		NSString *gamePath = [[bundle resourcePath] stringByAppendingPathComponent:@"game"];
+		BOOL isDir = false;
+		BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:gamePath isDirectory:&isDir];
+		if (exists && isDir) {
+			// Use auto-detection
+			command = "auto-detect";
+			settings["path"] = [gamePath fileSystemRepresentation];
+			return;
+		}
+
+		// The rest of the function has some commands executed only the first time after each version change
+		// Check the last version stored in the user settings.
+		NSString *versionString = [NSString stringWithUTF8String:gScummVMFullVersion];
+		NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+		NSString *lastVersion = [defaults stringForKey:@"lastVersion"];
+		if (lastVersion && [lastVersion isEqualToString:versionString])
+			return;
+		[defaults setObject:versionString forKey:@"lastVersion"];
+
+		// If the bundle contains a games directory, add them to the launcher
+		NSString *gamesPath = [[bundle resourcePath] stringByAppendingPathComponent:@"games"];
+		isDir = false;
+		exists = [[NSFileManager defaultManager] fileExistsAtPath:gamesPath isDirectory:&isDir];
+		if (exists && isDir) {
+			// Detect and add games
+			command = "add";
+			settings["path"] = [gamesPath fileSystemRepresentation];
+			settings["recursive"] = "true";
+			settings["exit"] = "false";
+			return;
+		}
+
+}
+
 Common::String OSystem_iOS7::getSystemLanguage() const {
 	NSString *language = [[NSLocale preferredLanguages] firstObject];
 	if (language == nil)
diff --git a/backends/platform/sdl/macosx/macosx_osys_misc.mm b/backends/platform/sdl/macosx/macosx_osys_misc.mm
index c1d8050dc04..3a6756e2315 100644
--- a/backends/platform/sdl/macosx/macosx_osys_misc.mm
+++ b/backends/platform/sdl/macosx/macosx_osys_misc.mm
@@ -96,7 +96,7 @@ void OSystem_MacOSX::updateStartSettings(const Common::String & executable, Comm
 	BOOL isDir = false;
 	BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:gamePath isDirectory:&isDir];
 	if (exists && isDir) {
-		// Ause auto-detection
+		// Use auto-detection
 		command = "auto-detect";
 		settings["path"] = [gamePath fileSystemRepresentation];
 		return;


Commit: cbd2b736df8d5d2eb4a7468a806fd5b3547afe5c
    https://github.com/scummvm/scummvm/commit/cbd2b736df8d5d2eb4a7468a806fd5b3547afe5c
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
BACKENDS: Add possibility to specify virtual drive in ChRootFilesystemFactory

It allows to get access to additional directories outside of the sandbox root.
This is used on iOS to access files in the app bundle.

Changed paths:
    backends/fs/chroot/chroot-fs-factory.cpp
    backends/fs/chroot/chroot-fs-factory.h
    backends/fs/chroot/chroot-fs.cpp
    backends/fs/chroot/chroot-fs.h
    backends/platform/ios7/ios7_osys_main.cpp


diff --git a/backends/fs/chroot/chroot-fs-factory.cpp b/backends/fs/chroot/chroot-fs-factory.cpp
index 8190e16bd27..7042a579941 100644
--- a/backends/fs/chroot/chroot-fs-factory.cpp
+++ b/backends/fs/chroot/chroot-fs-factory.cpp
@@ -47,16 +47,31 @@ AbstractFSNode *ChRootFilesystemFactory::makeCurrentDirectoryFileNode() const {
 		return NULL;
 	}
 
-	if (Common::String(buf).hasPrefix(_root + Common::String("/"))) {
+	Common::String curPath(buf);
+	if (curPath.hasPrefix(_root + Common::String("/"))) {
 		return new ChRootFilesystemNode(_root, buf + _root.size());
 	}
+	for (auto it = _virtualDrives.begin() ; it != _virtualDrives.end() ; ++it) {
+		if (curPath.hasPrefix(it->_value + Common::String("/")))
+			return new ChRootFilesystemNode(it->_value, buf + it->_value.size(), it->_key);
+	}
 
 	return new ChRootFilesystemNode(_root, "/");
 }
 
 AbstractFSNode *ChRootFilesystemFactory::makeFileNodePath(const Common::String &path) const {
 	assert(!path.empty());
+	size_t driveEnd = path.findFirstOf('/');
+	if (driveEnd != Common::String::npos && driveEnd > 0) {
+		auto it = _virtualDrives.find(path.substr(0, driveEnd));
+		if (it != _virtualDrives.end())
+			return new ChRootFilesystemNode(it->_value, path.substr(driveEnd), it->_key);
+	}
 	return new ChRootFilesystemNode(_root, path);
 }
 
+void ChRootFilesystemFactory::addVirtualDrive(const Common::String &name, const Common::String &path) {
+	_virtualDrives[name] = path;
+}
+
 #endif
diff --git a/backends/fs/chroot/chroot-fs-factory.h b/backends/fs/chroot/chroot-fs-factory.h
index 336a958a2c5..a9ad3e1dbae 100644
--- a/backends/fs/chroot/chroot-fs-factory.h
+++ b/backends/fs/chroot/chroot-fs-factory.h
@@ -37,9 +37,12 @@ public:
 	AbstractFSNode *makeRootFileNode() const override;
 	AbstractFSNode *makeCurrentDirectoryFileNode() const override;
 	AbstractFSNode *makeFileNodePath(const Common::String &path) const override;
+	
+	void addVirtualDrive(const Common::String &name, const Common::String &path);
 
 private:
 	const Common::String _root;
+	Common::StringMap _virtualDrives;
 };
 
 #endif /* BACKENDS_FS_CHROOT_CHROOT_FS_FACTORY_H */
diff --git a/backends/fs/chroot/chroot-fs.cpp b/backends/fs/chroot/chroot-fs.cpp
index efcea8b9d50..5629aebdb74 100644
--- a/backends/fs/chroot/chroot-fs.cpp
+++ b/backends/fs/chroot/chroot-fs.cpp
@@ -23,13 +23,15 @@
 
 #include "backends/fs/chroot/chroot-fs.h"
 
-ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *node) {
+ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *node, const Common::String &drive) {
 	_root = Common::normalizePath(root, '/');
+	_drive = drive;
 	_realNode = node;
 }
 
-ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, const Common::String &path) {
+ChRootFilesystemNode::ChRootFilesystemNode(const Common::String &root, const Common::String &path, const Common::String &drive) {
 	_root = Common::normalizePath(root, '/');
+	_drive = drive;
 	_realNode = new POSIXFilesystemNode(addPathComponent(root, path));
 }
 
@@ -51,10 +53,9 @@ Common::String ChRootFilesystemNode::getName() const {
 
 Common::String ChRootFilesystemNode::getPath() const {
 	Common::String path = _realNode->getPath();
-	if (path.size() > _root.size()) {
-		return Common::String(path.c_str() + _root.size());
-	}
-	return Common::String("/");
+	if (path.size() > _root.size())
+		return _drive + Common::String(path.c_str() + _root.size());
+	return _drive + "/";
 }
 
 bool ChRootFilesystemNode::isDirectory() const {
@@ -66,11 +67,14 @@ bool ChRootFilesystemNode::isReadable() const {
 }
 
 bool ChRootFilesystemNode::isWritable() const {
+	// Assume virtual drives are not writable
+	if (!_drive.empty())
+		return false;
 	return _realNode->isWritable();
 }
 
 AbstractFSNode *ChRootFilesystemNode::getChild(const Common::String &n) const {
-	return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getChild(n));
+	return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getChild(n), _drive);
 }
 
 bool ChRootFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hidden) const {
@@ -80,15 +84,16 @@ bool ChRootFilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool
 	}
 
 	for (AbstractFSList::iterator i=tmp.begin(); i!=tmp.end(); ++i) {
-		list.push_back(new ChRootFilesystemNode(_root, (POSIXFilesystemNode *) *i));
+		list.push_back(new ChRootFilesystemNode(_root, (POSIXFilesystemNode *) *i, _drive));
 	}
 
 	return true;
 }
 
 AbstractFSNode *ChRootFilesystemNode::getParent() const {
-	if (getPath() == "/") return 0;
-	return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getParent());
+	if (getPath() == _drive + "/")
+		return nullptr;
+	return new ChRootFilesystemNode(_root, (POSIXFilesystemNode *)_realNode->getParent(), _drive);
 }
 
 Common::SeekableReadStream *ChRootFilesystemNode::createReadStream() {
diff --git a/backends/fs/chroot/chroot-fs.h b/backends/fs/chroot/chroot-fs.h
index f2d8e7ab8ca..8d80a95769f 100644
--- a/backends/fs/chroot/chroot-fs.h
+++ b/backends/fs/chroot/chroot-fs.h
@@ -26,12 +26,13 @@
 
 class ChRootFilesystemNode final : public AbstractFSNode {
 	Common::String _root;
+	Common::String _drive;
 	POSIXFilesystemNode *_realNode;
 
-	ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *);
+	ChRootFilesystemNode(const Common::String &root, POSIXFilesystemNode *, const Common::String &drive);
 
 public:
-	ChRootFilesystemNode(const Common::String &root, const Common::String &path);
+	ChRootFilesystemNode(const Common::String &root, const Common::String &path, const Common::String &drive = Common::String());
 	~ChRootFilesystemNode() override;
 
 	bool exists() const override;
diff --git a/backends/platform/ios7/ios7_osys_main.cpp b/backends/platform/ios7/ios7_osys_main.cpp
index 4757283df91..d157d93f47d 100644
--- a/backends/platform/ios7/ios7_osys_main.cpp
+++ b/backends/platform/ios7/ios7_osys_main.cpp
@@ -97,7 +97,16 @@ OSystem_iOS7::OSystem_iOS7() :
 	_touchpadModeEnabled = !iOS7_isBigDevice();
 #ifdef IPHONE_SANDBOXED
 	_chrootBasePath = iOS7_getDocumentsDir();
-	_fsFactory = new ChRootFilesystemFactory(_chrootBasePath);
+	ChRootFilesystemFactory *chFsFactory = new ChRootFilesystemFactory(_chrootBasePath);
+	_fsFactory = chFsFactory;
+	// Add virtual drive for bundle path
+	CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+	if (fileUrl) {
+		UInt8 buf[MAXPATHLEN];
+		if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf)))
+			chFsFactory->addVirtualDrive("appbundle:", Common::String((const char *)buf));
+		CFRelease(fileUrl);
+	}
 #else
 	_fsFactory = new POSIXFilesystemFactory();
 #endif


Commit: 308c409a87352cbf166a3c21d5a1001cab1e23c9
    https://github.com/scummvm/scummvm/commit/308c409a87352cbf166a3c21d5a1001cab1e23c9
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
IOS7: Fix detecting and running games directly in bundle

Changed paths:
    backends/platform/ios7/ios7_osys_misc.mm


diff --git a/backends/platform/ios7/ios7_osys_misc.mm b/backends/platform/ios7/ios7_osys_misc.mm
index aa3493e6dbd..d0885120963 100644
--- a/backends/platform/ios7/ios7_osys_misc.mm
+++ b/backends/platform/ios7/ios7_osys_misc.mm
@@ -56,8 +56,13 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 
 		// If the bundle contains a scummvm.ini, use it as initial config
 		NSString *iniPath = [bundle pathForResource:@"scummvm" ofType:@"ini"];
-		if (iniPath && !settings.contains("initial-cfg"))
+		if (iniPath && !settings.contains("initial-cfg")) {
+#ifdef IPHONE_SANDBOXED
+			settings["initial-cfg"] = "appbundle:/scummvm.ini";
+#else
 			settings["initial-cfg"] = Common::String([iniPath fileSystemRepresentation]);
+#endif
+		}
 
 		// If a command was specified on the command line, do not override it
 		if (!command.empty())
@@ -68,7 +73,11 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (autorunPath) {
 			Common::File autorun;
 			Common::String line;
+#ifdef IPHONE_SANDBOXED
+			if (autorun.open(Common::FSNode("appbundle:/scummvm-autorun"))) {
+#else
 			if (autorun.open(Common::FSNode([autorunPath fileSystemRepresentation]))) {
+#endif
 				while (!autorun.eos()) {
 					line = autorun.readLine();
 					if (!line.empty() && line[0] != '#')
@@ -85,7 +94,11 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (exists && isDir) {
 			// Use auto-detection
 			command = "auto-detect";
+#ifdef IPHONE_SANDBOXED
+			settings["path"] = "appbundle:/game";
+#else
 			settings["path"] = [gamePath fileSystemRepresentation];
+#endif
 			return;
 		}
 
@@ -105,7 +118,11 @@ void OSystem_iOS7::updateStartSettings(const Common::String &executable, Common:
 		if (exists && isDir) {
 			// Detect and add games
 			command = "add";
+#ifdef IPHONE_SANDBOXED
+			settings["path"] = "appbundle:/games";
+#else
 			settings["path"] = [gamesPath fileSystemRepresentation];
+#endif
 			settings["recursive"] = "true";
 			settings["exit"] = "false";
 			return;


Commit: 5915f6fc1267d3a9d40329eee6b374eb3248ce50
    https://github.com/scummvm/scummvm/commit/5915f6fc1267d3a9d40329eee6b374eb3248ce50
Author: Thierry Crozat (criezy at scummvm.org)
Date: 2023-03-24T21:11:50+01:00

Commit Message:
DOC: Update autostart description for macOS and iOS

Changed paths:
    doc/docportal/advanced_topics/autostart.rst


diff --git a/doc/docportal/advanced_topics/autostart.rst b/doc/docportal/advanced_topics/autostart.rst
index f66eb43deab..62c760e2b1b 100644
--- a/doc/docportal/advanced_topics/autostart.rst
+++ b/doc/docportal/advanced_topics/autostart.rst
@@ -2,12 +2,64 @@
 Autostart
 =========================
 
-Use the autostart feature to automatically start the game located in the same folder as the ScummVM executable, as long as it is a game supported by ScummVM. It is the equivalent of using the ``--path`` and ``--auto-detect`` :doc:`command line options <../advanced_topics/command_line>`.
+Use the autostart feature to automatically start or add games. The available features and the way they work depend on the system on which ScummVM is running.
+
+
+.. tabbed:: General
+
+    .. panels::
+        :column: col-lg-12
+
+        On most systems, such as Windows and Linux, ScummVM can detect and start a game located in the same folder as the ScummVM executable, as long as it is a game supported by ScummVM. It is the equivalent of using the ``--path`` and ``--auto-detect`` :doc:`command line options <../advanced_topics/command_line>`. This also works on macOS when ScummVM is built as a command line application and not as a .app bundle.
+
+        There are two ways to use the autostart feature:
+
+        - Rename the executable file to ``scummvm-auto.xxx``, where ``.xxx`` is the file type extension (if applicable).
+        - Create an empty file named ``scummvm-autorun`` in the same folder as both the executable and the chosen game. Either leave the file empty, or use it to specify any further command line options. Specify one option per line.
+
+.. tabbed:: macOS
+
+    .. panels::
+        :column: col-lg-12
+
+        The following information are only correct when ScummVM is built as a .app bundle. When ScummVM is built as a command line application it behaves as on Windows and Linux.
+
+        ScummVM can automatically detect and run a supported game included in the ScummVM.app bundle. The game files simply need to be in the ``ScummVM.app/Contents/Resources/game/`` folder.
+
+        ScummVM can also automatically detect and add to the launcher supported games included in the ScummVM.app bundle. The games simply need to be in the ``ScummVM.app/Contents/Resources/games/`` folder, or subfolders in that folder (you can for example use one subfolder per game).
+
+        A ``scummvm-autorun`` file can also be used to specify command line options to use, with one option per line. The file should be in the  ``ScummVM.app/Contents/Resources/`` folder.
+
+        In addition if a ``scummvm.ini`` file is present in the ``ScummVM.app/Contents/Resources/`` folder, it will be used as initial config file if no ``ScummVM Preferences`` file exists yet. It is the equivalent of using the ``--initial-cfg`` :doc:`command line option <../advanced_topics/command_line>`.
+
+        Finally it can be noted that the bundle name specified in the ``ScummVM.app/Contents/Info.plist`` file is used for the default config file name. For example by default, when the bundle name is ``ScummVM``, the default config file where settings are saved is ``~/Library/Preferences/ScummVM Preferences``. But if you change the bundle name to ``MyGame``, the default config file used is ``~/Library/Preferences/MyGame Preferences``
+
+        Thus to create a game bundle for a specific game you can:
+
+        1. Copy the ScummVM.app bundle for example to MyGame.app
+        2. Create a MyGame.app/Contents/Resources/game/ folder and copy your game data files to that folder.
+        3. Edit the bundle name and bundle display name in the MyGame.app/Contents/Info.plist file.
+        4. Create a new icons file in MyGame.app/Contents/Resources/ and edit the icon file in the MyGame.app/Contents/Info.plist file.
+        5. Create a MyGame.app/Contents/Resources/scummvm.ini file with the default settings for your game bundle (for example to set fullscreen to true).
+
+        Note that modifying a signed bundle will invalidate the signature. So the bundle needs to be signed again after for example adding a ``game`` folder inside the ScummVM.app bundle.
+
+.. tabbed:: iOS
+
+    .. panels::
+        :column: col-lg-12
+
+        ScummVM can automatically detect and run a supported game included in the ScummVM.app bundle. The game files simply need to be in the ``ScummVM.app/game/`` folder.
+
+        ScummVM can also automatically detect and add to the launcher supported games included in the ScummVM.app bundle. The games simply need to be in the ``ScummVM.app/games/`` folder, or subfolders in that folder (you can for example use one subfolder per game).
+
+        A ``scummvm-autorun`` file can also be used to specify command line options to use, with one option per line. The file should be in the  ``ScummVM.app/`` folder.
+
+        In addition if a ``scummvm.ini`` file is present in the ``ScummVM.app/`` folder, it will be used as initial config file if no config file exists yet. It is the equivalent of using the ``--initial-cfg`` :doc:`command line option <../advanced_topics/command_line>`.
+
+        Note that modifying a signed bundle will invalidate the signature. So the bundle needs to be signed again after for example adding a ``game`` folder inside the ScummVM.app bundle.
 
-There are two ways to use the autostart feature:
 
-- Rename the executable file to ``scummvm-auto.xxx``, where ``.xxx`` is the file type extension (if applicable). On macOS the executable to rename is ``ScummVM.app/Contents/MacOS/scummvm`` and not the ``ScummVM.app`` application.
-- Create an empty file named ``scummvm-autorun`` in the same folder as both the executable and the chosen game. Either leave the file empty, or use it to specify any further command line options. Specify one option per line.
 
 Example of a scummvm-autorun file
 ===================================




More information about the Scummvm-git-logs mailing list