[Scummvm-git-logs] scummvm master -> 3b2b138b69f7fa10569f642ebf80dddec107bad6

mgerhardy noreply at scummvm.org
Mon Jan 5 12:25:13 UTC 2026


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

Summary:
1b1a55ad46 COMMON: catch the input error before we are throwing an assert in posix filesystem
bc8208721f BASE: added --list-records-json for the event recorder
54de49d72a BASE: added --list-games-json option
a5d0c880e3 BASE: added json version of --list-targets
f268d17f54 BASE: added json version of --list-engines
6351ce1143 BACKEND: EVENTRECORDER: fixed the logic of the g_eventRec.processDelayMillis call
39682d3769 BASE: EVENTRECORDER: expose fast-mode to the command line
14f00a7e86 DOCS: updated command line paramters for new event recorder args
da02e2bf9a MAKE: adde makefile target to execute the tests
27424c4894 BASE: EVENTRECORDER: control fast mode via record-mode argument
3b2b138b69 DEVTOOLS: added script that executes event recorder tests for configured demos and record files


Commit: 1b1a55ad466499c0cde91abad0ff979b4542dd73
    https://github.com/scummvm/scummvm/commit/1b1a55ad466499c0cde91abad0ff979b4542dd73
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
COMMON: catch the input error before we are throwing an assert in posix filesystem

#7  0x0000555555bc48cd in POSIXFilesystemNode::getChild (this=0x555557decbe0, n=...) at backends/fs/posix/posix-fs.cpp:128
#8  0x0000555555f4debf in Common::FSNode::getChild (this=0x7fffffffb860, n=...) at common/fs.cpp:144
#9  0x0000555555b6cc0c in DefaultSaveFileManager::openForSaving (this=0x555556d22bb0, filename=..., compress=true) at backends/saves/default/default-saves.cpp:161
#10 0x0000555555f80a46 in Common::PlaybackFile::openWrite (this=0x555557e8ef50, fileName=...) at common/recorderfile.cpp:62

Changed paths:
    common/recorderfile.cpp


diff --git a/common/recorderfile.cpp b/common/recorderfile.cpp
index d123247be7f..7bce79baaff 100644
--- a/common/recorderfile.cpp
+++ b/common/recorderfile.cpp
@@ -58,6 +58,9 @@ PlaybackFile::~PlaybackFile() {
 
 bool PlaybackFile::openWrite(const String &fileName) {
 	close();
+	if (fileName.contains("/")) {
+		error("Filename may not contain a path");
+	}
 	_header.fileName = fileName;
 	_writeStream = wrapBufferedWriteStream(g_system->getSavefileManager()->openForSaving(fileName), 128 * 1024);
 	_headerDumped = false;


Commit: bc8208721fa329e02246975f8646bdbd9ebc28dd
    https://github.com/scummvm/scummvm/commit/bc8208721fa329e02246975f8646bdbd9ebc28dd
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: added --list-records-json for the event recorder

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 7db1d184a13..81142efde72 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -208,6 +208,7 @@ static const char HELP_STRING4[] =
 	"  --screenshot-period=NUM  When recording, trigger a screenshot every NUM milliseconds\n"
 	"                           (default: 60000)\n"
 	"  --list-records           Display a list of recordings for the target specified\n"
+	"  --list-records-json      Display a list of recordings in JSON format for the target specified\n"
 #endif
 	"\n"
 #if defined(ENABLE_SKY) || defined(ENABLE_QUEEN)
@@ -811,6 +812,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_LONG_COMMAND("list-records")
 			END_COMMAND
 
+			DO_LONG_COMMAND("list-records-json")
+			END_COMMAND
+
 			DO_LONG_OPTION_INT("screenshot-period")
 			END_OPTION
 #endif
@@ -1308,7 +1312,7 @@ static void assembleTargets(const Common::String &singleTarget, Common::Array<Co
 }
 
 #ifdef ENABLE_EVENTRECORDER
-static Common::Error listRecords(const Common::String &singleTarget) {
+static Common::Error listRecords(const Common::String &singleTarget, bool jsonOutput) {
 	Common::Error result = Common::kNoError;
 
 	Common::Array<Common::String> targets;
@@ -1318,6 +1322,11 @@ static Common::Error listRecords(const Common::String &singleTarget) {
 	g_system->initBackend();
 
 	Common::String oldDomain = ConfMan.getActiveDomainName();
+	bool first = true;
+
+	if (jsonOutput) {
+		printf("{\n");
+	}
 
 	for (const auto &target : targets) {
 		Common::String currentTarget;
@@ -1341,12 +1350,31 @@ static Common::Error listRecords(const Common::String &singleTarget) {
 		if (files.empty()) {
 			continue;
 		}
-		printf("Recordings for target '%s' (gameid '%s'):\n", target.c_str(), qualifiedGameId.c_str());
-		for (const auto &x : files) {
-			printf("  %s\n", x.c_str());
+		if (jsonOutput) {
+			if (!first)
+				printf(",\n");
+			first = false;
+			printf("  \"%s\": {\n", target.c_str());
+			printf("  \"records\": [\n");
+			for (size_t i = 0; i < files.size(); ++i) {
+				printf("    \"%s\"%s\n", files[i].c_str(), (i + 1 < files.size()) ? "," : "");
+			}
+			printf("  ],\n");
+			printf("  \"engine\": \"%s\",\n", game.engineId.c_str());
+			printf("  \"gameid\": \"%s\"\n", qualifiedGameId.c_str());
+			printf("  }");
+		} else {
+			printf("Recordings for target '%s' (gameid '%s'):\n", target.c_str(), qualifiedGameId.c_str());
+			for (const auto &x : files) {
+				printf("  %s\n", x.c_str());
+			}
 		}
 	}
 
+	if (jsonOutput) {
+		printf("\n}\n");
+	}
+
 	// Revert to the old active domain
 	ConfMan.setActiveDomain(oldDomain);
 
@@ -1949,7 +1977,10 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		return cmdDoExit;
 #ifdef ENABLE_EVENTRECORDER
 	} else if (command == "list-records") {
-		err = listRecords(settings["game"]);
+		err = listRecords(settings["game"], false);
+		return cmdDoExit;
+	} else if (command == "list-records-json") {
+		err = listRecords(settings["game"], true);
 		return cmdDoExit;
 #endif
 	} else if (command == "list-saves") {


Commit: 54de49d72a5b66f145e56df2745f9befbbf57083
    https://github.com/scummvm/scummvm/commit/54de49d72a5b66f145e56df2745f9befbbf57083
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: added --list-games-json option

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 81142efde72..516cfa73d71 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -75,6 +75,7 @@ static const char HELP_STRING1[] =
 	"  -v, --version            Display ScummVM version information and exit\n"
 	"  -h, --help               Display a brief help text and exit\n"
 	"  -z, --list-games         Display list of supported games and exit\n"
+	"  --list-games-json        Display list of supported games in JSON format and exit\n"
 	"  --list-all-games         Display list of all detected games and exit\n"
 	"  -t, --list-targets       Display list of configured targets and exit\n"
 	"  --list-engines           Display list of supported engines and exit\n"
@@ -94,7 +95,7 @@ static const char HELP_STRING1[] =
 	"                           Use --path=PATH to specify a directory.\n"
 	"  --game=ID                In combination with --add or --detect only adds or attempts to\n"
 	"                           detect the game with id ID.\n"
-	"  --engine=ID              In combination with --list-games, --list-all-games, --list-targets, or --stats only\n"
+	"  --engine=ID              In combination with --list-games, --list-games-json, --list-all-games, --list-targets, or --stats only\n"
 	"                           lists games for this engine. Multiple engines can be listed separated by a coma.\n"
 	"  --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"
@@ -680,6 +681,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_COMMAND('z', "list-games")
 			END_COMMAND
 
+			DO_LONG_COMMAND("list-games-json")
+			END_COMMAND
+
 			DO_LONG_COMMAND("list-all-games")
 			END_COMMAND
 
@@ -1056,7 +1060,7 @@ unknownOption:
 }
 
 /** List all available game IDs, i.e. all games which any loaded plugin supports. */
-static void listGames(const Common::String &engineID) {
+static void listGames(const Common::String &engineID, bool jsonOutput) {
 	const bool all = engineID.empty();
 	Common::StringArray engines;
 	if (!all) {
@@ -1064,8 +1068,12 @@ static void listGames(const Common::String &engineID) {
 		engines = tokenizer.split();
 	}
 
-	printf("Game ID                        Full Title                                                 \n"
-	       "------------------------------ -----------------------------------------------------------\n");
+	if (jsonOutput) {
+		printf("{");
+	} else {
+		printf("Game ID                        Full Title                                                 \n"
+			"------------------------------ -----------------------------------------------------------\n");
+	}
 
 	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
 	for (const auto &plugin : plugins) {
@@ -1077,11 +1085,26 @@ static void listGames(const Common::String &engineID) {
 
 		if (all || Common::find(engines.begin(), engines.end(), p->getName()) != engines.end()) {
 			PlainGameList list = p->get<MetaEngineDetection>().getSupportedGames();
+			bool first = true;
 			for (const auto &v : list) {
-				printf("%-30s %s\n", buildQualifiedGameName(p->get<MetaEngineDetection>().getName(), v.gameId).c_str(), v.description);
+				const Common::String &gameId = buildQualifiedGameName(p->get<MetaEngineDetection>().getName(), v.gameId);
+				if (jsonOutput) {
+					if (!first) {
+						printf(",\n");
+					} else {
+						printf("\n");
+					}
+					first = false;
+					printf("  \"%s\": \"%s\"", gameId.c_str(), v.description);
+				} else {
+					printf("%-30s %s\n", gameId.c_str(), v.description);
+				}
 			}
 		}
 	}
+	if (jsonOutput) {
+		printf("\n}\n");
+	}
 }
 
 /** List all known game IDs, i.e. all games which can be detected. */
@@ -1958,7 +1981,10 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		listDebugFlags(settings["list-debugflags"]);
 		return cmdDoExit;
 	} else if (command == "list-games") {
-		listGames(settings["engine"]);
+		listGames(settings["engine"], false);
+		return cmdDoExit;
+	} else if (command == "list-games-json") {
+		listGames(settings["engine"], true);
 		return cmdDoExit;
 	} else if (command == "list-all-games") {
 		listAllGames(settings["engine"]);


Commit: a5d0c880e33bf6c101ac8cc33cc460584f673a0a
    https://github.com/scummvm/scummvm/commit/a5d0c880e33bf6c101ac8cc33cc460584f673a0a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: added json version of --list-targets

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 516cfa73d71..5defcbc93b6 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -78,6 +78,7 @@ static const char HELP_STRING1[] =
 	"  --list-games-json        Display list of supported games in JSON format and exit\n"
 	"  --list-all-games         Display list of all detected games and exit\n"
 	"  -t, --list-targets       Display list of configured targets and exit\n"
+	"  --list-targets-json      Display list of configured targets in JSON format and exit\n"
 	"  --list-engines           Display list of supported engines and exit\n"
 	"  --list-all-engines       Display list of all detection engines and exit\n"
 	"  --dump-all-detection-entries Create a DAT file containing MD5s from detection entries of all engines\n"
@@ -678,6 +679,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_COMMAND('t', "list-targets")
 			END_COMMAND
 
+			DO_LONG_COMMAND("list-targets-json")
+			END_COMMAND
+
 			DO_COMMAND('z', "list-games")
 			END_COMMAND
 
@@ -1162,7 +1166,7 @@ static void listAllEngines() {
 }
 
 /** List all targets which are configured in the config file. */
-static void listTargets(const Common::String &engineID) {
+static void listTargets(const Common::String &engineID, bool jsonOutput) {
 	const bool any = engineID.empty();
 	Common::StringArray engines;
 	if (!any) {
@@ -1170,41 +1174,80 @@ static void listTargets(const Common::String &engineID) {
 		engines = tokenizer.split();
 	}
 
-	printf("Target               Description                                           \n"
-	       "-------------------- ------------------------------------------------------\n");
+	if (jsonOutput) {
+		printf("{");
+	} else {
+		printf("Target               Description                                           \n"
+			"-------------------- ------------------------------------------------------\n");
+	}
 
 	const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
 
-	Common::Array<Common::String> targets;
+	struct Target {
+		Common::String name;
+		Common::String description;
+		Common::String engineId;
+		Common::String gameId;
+
+		Common::String toString() const {
+			return Common::String::format("%-20s %s", name.c_str(), description.c_str());
+		}
+
+		bool operator<(const Target &other) const {
+			return toString() < other.toString();
+		}
+	};
+	Common::Array<Target> targets;
 	targets.reserve(domains.size());
 
 	for (const auto &domain : domains) {
 		Common::String name(domain._key);
 		Common::String description(domain._value.getValOrDefault("description"));
-		Common::String engine;
-		if (!any)
-			engine = domain._value.getValOrDefault("engineid");
+		Common::String engine = domain._value.getValOrDefault("engineid");
+		Common::String gameId = domain._value.getValOrDefault("gameid");
 
 		// If there's no description, fallback on the default description.
-		if (description.empty() || (!any && engine.empty())) {
+		if (description.empty() || engine.empty() || gameId.empty()) {
 			QualifiedGameDescriptor g = EngineMan.findTarget(name);
 			if (description.empty() && !g.description.empty())
 				description = g.description;
-			if (!any && engine.empty() && !g.engineId.empty())
+			if (engine.empty() && !g.engineId.empty())
 				engine = g.engineId;
+			if (gameId.empty() && !g.gameId.empty())
+				gameId = g.gameId;
 		}
 		// If there's still no description, we cannot come up with one. Insert some dummy text.
 		if (description.empty())
 			description = "<Unknown game>";
 
 		if (any || Common::find(engines.begin(), engines.end(), engine) != engines.end())
-			targets.push_back(Common::String::format("%-20s %s", name.c_str(), description.c_str()));
+			targets.push_back({name, description, engine, gameId});
 	}
 
 	Common::sort(targets.begin(), targets.end());
 
-	for (const auto &target : targets)
-		printf("%s\n", target.c_str());
+	bool first = true;
+	for (const auto &target : targets) {
+		if (jsonOutput) {
+			if (!first) {
+				printf(",\n");
+			} else {
+				printf("\n");
+				first = false;
+			}
+			printf("  \"%s\": {\n", target.name.c_str());
+			printf("    \"description\": \"%s\",\n", target.description.c_str());
+			printf("    \"engineId\": \"%s\",\n", target.engineId.c_str());
+			printf("    \"gameId\": \"%s\"\n", target.gameId.c_str());
+			printf("  }");
+		} else {
+			printf("%s\n", target.toString().c_str());
+		}
+	}
+
+	if (jsonOutput) {
+		printf("\n}\n");
+	}
 }
 
 static void printStatistics(const Common::String &engineID) {
@@ -1972,7 +2015,10 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 	// --list-games). This must be done after the config file and the plugins
 	// have been loaded.
 	if (command == "list-targets") {
-		listTargets(settings["engine"]);
+		listTargets(settings["engine"], false);
+		return cmdDoExit;
+	} else if (command == "list-targets-json") {
+		listTargets(settings["engine"], true);
 		return cmdDoExit;
 	} else if (command == "list-all-debugflags") {
 		listAllEngineDebugFlags();


Commit: f268d17f54c1a39e2bcb584bf1abd9678dfb7c23
    https://github.com/scummvm/scummvm/commit/f268d17f54c1a39e2bcb584bf1abd9678dfb7c23
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: added json version of --list-engines

Changed paths:
    base/commandLine.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 5defcbc93b6..a2a7d0f59a7 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -80,6 +80,7 @@ static const char HELP_STRING1[] =
 	"  -t, --list-targets       Display list of configured targets and exit\n"
 	"  --list-targets-json      Display list of configured targets in JSON format and exit\n"
 	"  --list-engines           Display list of supported engines and exit\n"
+	"  --list-engines-json      Display list of supported engines in JSON format and exit\n"
 	"  --list-all-engines       Display list of all detection engines and exit\n"
 	"  --dump-all-detection-entries Create a DAT file containing MD5s from detection entries of all engines\n"
 	"  --stats                  Display statistics about engines and games and exit\n"
@@ -702,6 +703,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 			DO_LONG_COMMAND("list-engines")
 			END_COMMAND
 
+			DO_LONG_COMMAND("list-engines-json")
+			END_COMMAND
+
 			DO_LONG_COMMAND("list-all-engines")
 			END_COMMAND
 
@@ -1137,11 +1141,16 @@ static void listAllGames(const Common::String &engineID) {
 }
 
 /** List all supported engines, i.e. all loaded engine plugins. */
-static void listEngines() {
-	printf("Engine ID       Engine Name                                           \n"
-	       "--------------- ------------------------------------------------------\n");
+static void listEngines(bool jsonOutput) {
+	if (jsonOutput) {
+		printf("{");
+	} else {
+		printf("Engine ID       Engine Name                                           \n"
+			"--------------- ------------------------------------------------------\n");
+	}
 
 	const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
+	bool first = true;
 	for (const auto &plugin : plugins) {
 		const Plugin *p = EngineMan.findDetectionPlugin(plugin->getName());
 		/* If for some reason, we can't find the MetaEngineDetection for this Engine, just ignore it */
@@ -1149,7 +1158,21 @@ static void listEngines() {
 			continue;
 		}
 
-		printf("%-15s %s\n", p->get<MetaEngineDetection>().getName(), p->get<MetaEngineDetection>().getEngineName());
+		if (jsonOutput) {
+			if (!first) {
+				printf(",\n");
+			} else {
+				printf("\n");
+				first = false;
+			}
+			printf("  \"%s\": \"%s\"", p->get<MetaEngineDetection>().getName(),
+			       p->get<MetaEngineDetection>().getEngineName());
+		} else {
+			printf("%-15s %s\n", p->get<MetaEngineDetection>().getName(), p->get<MetaEngineDetection>().getEngineName());
+		}
+	}
+	if (jsonOutput) {
+		printf("\n}\n");
 	}
 }
 
@@ -2036,7 +2059,10 @@ bool processSettings(Common::String &command, Common::StringMap &settings, Commo
 		listAllGames(settings["engine"]);
 		return cmdDoExit;
 	} else if (command == "list-engines") {
-		listEngines();
+		listEngines(false);
+		return cmdDoExit;
+	} else if (command == "list-engines-json") {
+		listEngines(true);
 		return cmdDoExit;
 	} else if (command == "list-all-engines") {
 		listAllEngines();


Commit: 6351ce11432ef1d40f2dea7eda5fc20269fc0e71
    https://github.com/scummvm/scummvm/commit/6351ce11432ef1d40f2dea7eda5fc20269fc0e71
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BACKEND: EVENTRECORDER: fixed the logic of the g_eventRec.processDelayMillis call

Changed paths:
    backends/platform/sdl/sdl.cpp
    gui/EventRecorder.cpp


diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 6085eb840cc..45d4e38b557 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -855,7 +855,7 @@ uint32 OSystem_SDL::getMillis(bool skipRecord) {
 
 void OSystem_SDL::delayMillis(uint msecs) {
 #ifdef ENABLE_EVENTRECORDER
-	if (!g_eventRec.processDelayMillis())
+	if (g_eventRec.processDelayMillis())
 #endif
 		SDL_Delay(msecs);
 }
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 1929508dbca..ff5fad4645f 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -232,7 +232,7 @@ void EventRecorder::processMillis(uint32 &millis, bool skipRecord) {
 }
 
 bool EventRecorder::processDelayMillis() {
-	return _fastPlayback;
+	return !_fastPlayback;
 }
 
 bool EventRecorder::processAutosave() {


Commit: 39682d37690d98f557ad878d1972f45d5f835240
    https://github.com/scummvm/scummvm/commit/39682d37690d98f557ad878d1972f45d5f835240
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: EVENTRECORDER: expose fast-mode to the command line

Changed paths:
    base/commandLine.cpp
    base/main.cpp
    gui/EventRecorder.cpp


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index a2a7d0f59a7..6cb24877d4d 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -212,6 +212,7 @@ static const char HELP_STRING4[] =
 	"                           (default: 60000)\n"
 	"  --list-records           Display a list of recordings for the target specified\n"
 	"  --list-records-json      Display a list of recordings in JSON format for the target specified\n"
+	"  --fast-mode              Enable fast mode for event recorder playback\n"
 #endif
 	"\n"
 #if defined(ENABLE_SKY) || defined(ENABLE_QUEEN)
@@ -382,7 +383,10 @@ void registerDefaults() {
 	ConfMan.registerDefault("disable_sdl_parachute", false);
 	ConfMan.registerDefault("disable_sdl_audio", false);
 
+#ifdef ENABLE_EVENTRECORDER
 	ConfMan.registerDefault("disable_display", false);
+	ConfMan.registerDefault("fast_mode", false);
+#endif
 	ConfMan.registerDefault("record_mode", "none");
 	ConfMan.registerDefault("record_file_name", "record.bin");
 
@@ -829,6 +833,9 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 
 			DO_LONG_OPTION_INT("screenshot-period")
 			END_OPTION
+
+			DO_LONG_OPTION_BOOL("fast-mode")
+			END_OPTION
 #endif
 
 			DO_LONG_OPTION("opl-driver")
diff --git a/base/main.cpp b/base/main.cpp
index b5eed27653d..346c4e77b88 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -583,9 +583,14 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 		}
 		ConfMan.set("gfx_mode", gfxModeSetting, Common::ConfigManager::kSessionDomain);
 	}
+#ifdef ENABLE_EVENTRECORDER
 	if (settings.contains("disable-display")) {
-		ConfMan.setInt("disable-display", 1, Common::ConfigManager::kTransientDomain);
+		ConfMan.setInt("disable_display", 1, Common::ConfigManager::kTransientDomain);
+	}
+	if (settings.contains("fast-mode")) {
+		ConfMan.setInt("fast_mode", 1, Common::ConfigManager::kTransientDomain);
 	}
+#endif
 	setupGraphics(system);
 
 	if (!configLoadStatus) {
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index ff5fad4645f..37594a9e3d8 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -393,6 +393,9 @@ void EventRecorder::init(const Common::String &recordFileName, RecordMode mode)
 		DebugMan.enableDebugChannel("EventRec");
 		gDebugLevel = 1;
 	}
+	if (ConfMan.hasKey("fast_mode")) {
+		_fastPlayback = ConfMan.getInt("fast_mode") != 0;
+	}
 	if ((_recordMode == kRecorderPlayback) || (_recordMode == kRecorderUpdate)) {
 		debugC(1, kDebugLevelEventRec, "playback:action=\"Load file\" filename=%s", recordFileName.c_str());
 		Common::EventDispatcher *eventDispatcher = g_system->getEventManager()->getEventDispatcher();


Commit: 14f00a7e86d86dec44bc1b62b3a02bd39fa2ddb6
    https://github.com/scummvm/scummvm/commit/14f00a7e86d86dec44bc1b62b3a02bd39fa2ddb6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
DOCS: updated command line paramters for new event recorder args

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


diff --git a/doc/docportal/advanced_topics/command_line.rst b/doc/docportal/advanced_topics/command_line.rst
index b25072111b5..2fd527d890c 100755
--- a/doc/docportal/advanced_topics/command_line.rst
+++ b/doc/docportal/advanced_topics/command_line.rst
@@ -167,6 +167,7 @@ Short options are listed where they are available.
         ``--engine=ID``,,"In combination with ``--list-games`` or ``--list-all-games`` only lists games for this engine",
         ``--engine-speed=NUM``,,"Sets frame-per-second limit for Grim Fandango or Escape from Monkey Island. 0 is no limit. Allowed values 0 - 100", 60
         ``--extrapath=PATH``,,":ref:`Extra path to additional game data <extra>`",
+        ``--fast-mode``,, "Enable fast playback mode (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",
         ``--filtering``,,":ref:`Forces filtered graphics mode <filtering>`",false
         ``--fullscreen``,``-f``,":ref:`Forces full-screen mode <fullscreen>`",false
         ``--game=ID``,,"In combination with ``--add`` or ``--detect`` only adds or attempts to detect the game with specified ID.",
@@ -182,10 +183,14 @@ Short options are listed where they are available.
         ``--list-audio-devices``,,"Lists all available audio devices",
         ``--list-debugflags=engine``,,"Lists engine-specific debug flags. If ``engine=global`` or engine is not specified, then it lists global debug flags.",
         ``--list-engines``,,"Lists supported engines, then exits",
+        ``--list-engines-json``,,"Lists supported engines as json, then exits",
         ``--list-games``,``-z``, "Lists supported games, then exits.",
-        ``--list-records=TARGET``,, "Lists recordings for the specified target (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",
+        ``--list-games-json``,, "Lists supported games as json, then exits.",
+        ``--list-records --game=TARGET``,, "Lists recordings for the specified target (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",
+        ``--list-records-json --game=TARGET``,, "Lists recordings as json for the specified target (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",
         ``--list-saves --game=TARGET``,,"Displays a list of saved games for the game specified, or for all targets if no game specified.",
         ``--list-targets``,``-t``,"Lists configured targets, then exits",
+        ``--list-targets-json``,,"Lists configured targets as json, then exits",
         ``--list-themes``,,"Lists all usable GUI themes",
         ``--logfile=PATH``,``-l``,"Uses alternate path for log file (SDL backend only).",
         ``--md5``,,"Shows MD5 hash of the file given by ``--md5-path=PATH``. If ``--md5-length=NUM`` is passed then it shows the MD5 hash of the first or last ``NUM`` bytes of the file given by ``PATH``. If ``--md5-engine=ENGINE_ID`` option is passed then it auto-calculates the required bytes and its hash, overriding ``--md5-length``",
@@ -197,7 +202,7 @@ Short options are listed where they are available.
         ``--multi-midi``,,":ref:`Enables combination AdLib and native MIDI <multi>`",false
         ``--music-driver=MODE``,``-e``,":ref:`Selects preferred music device <device>`",auto
         ``--music-volume=NUM``,``-m``,":ref:`Sets the music volume <music>`, 0-255",192
-    	``--native-mt32``,,":ref:`True Roland MT-32 (disables GM emulation) <mt32>`",false
+        ``--native-mt32``,,":ref:`True Roland MT-32 (disables GM emulation) <mt32>`",false
         ``--no-fullscreen``,``-F``,"Forces windowed mode",
         ``--opl-driver=DRIVER``,,":ref:`Selects AdLib (OPL) emulator <opl>`",
         ``--output-channels=CHANNELS``,,"Select output channel count, for example, 2 for stereo.",


Commit: da02e2bf9a4434294d610be30442138880eac728
    https://github.com/scummvm/scummvm/commit/da02e2bf9a4434294d610be30442138880eac728
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
MAKE: adde makefile target to execute the tests

Changed paths:
    Makefile


diff --git a/Makefile b/Makefile
index b4af9763ed4..3ade2be3467 100644
--- a/Makefile
+++ b/Makefile
@@ -155,3 +155,6 @@ CMakeLists.txt: devtools/create_project/cmake/build/create_project config.mk
 cmake: CMakeLists.txt
 	cmake -H. -Bbuild
 	cmake --build build
+
+test-games: $(EXECUTABLE)
+	devtools/run_event_recorder_tests.py --xunit-output=$(EXECUTABLE).test-results.xml


Commit: 27424c4894cb0738ade3adf4e273bb788f2309dd
    https://github.com/scummvm/scummvm/commit/27424c4894cb0738ade3adf4e273bb788f2309dd
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
BASE: EVENTRECORDER: control fast mode via record-mode argument

Changed paths:
    base/commandLine.cpp
    base/main.cpp
    doc/docportal/advanced_topics/command_line.rst
    gui/EventRecorder.cpp
    gui/EventRecorder.h


diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 6cb24877d4d..cfbc7aa6f5e 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -204,7 +204,7 @@ static const char HELP_STRING4[] =
 	"                           atari, macintosh, macintoshbw, vgaGray)\n"
 #ifdef ENABLE_EVENTRECORDER
 	"  --record-mode=MODE       Specify record mode for event recorder (record, playback,\n"
-	"                           info, update, passthrough [default])\n"
+	"                           fast_playback, info, update, passthrough [default])\n"
 	"  --record-file-name=FILE  Specify record file name\n"
 	"  --disable-display        Disable any gfx output. Used for headless events\n"
 	"                           playback by Event Recorder\n"
@@ -212,7 +212,6 @@ static const char HELP_STRING4[] =
 	"                           (default: 60000)\n"
 	"  --list-records           Display a list of recordings for the target specified\n"
 	"  --list-records-json      Display a list of recordings in JSON format for the target specified\n"
-	"  --fast-mode              Enable fast mode for event recorder playback\n"
 #endif
 	"\n"
 #if defined(ENABLE_SKY) || defined(ENABLE_QUEEN)
@@ -385,7 +384,6 @@ void registerDefaults() {
 
 #ifdef ENABLE_EVENTRECORDER
 	ConfMan.registerDefault("disable_display", false);
-	ConfMan.registerDefault("fast_mode", false);
 #endif
 	ConfMan.registerDefault("record_mode", "none");
 	ConfMan.registerDefault("record_file_name", "record.bin");
@@ -833,9 +831,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
 
 			DO_LONG_OPTION_INT("screenshot-period")
 			END_OPTION
-
-			DO_LONG_OPTION_BOOL("fast-mode")
-			END_OPTION
 #endif
 
 			DO_LONG_OPTION("opl-driver")
diff --git a/base/main.cpp b/base/main.cpp
index 346c4e77b88..7b2c1e7f8e2 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -587,9 +587,6 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 	if (settings.contains("disable-display")) {
 		ConfMan.setInt("disable_display", 1, Common::ConfigManager::kTransientDomain);
 	}
-	if (settings.contains("fast-mode")) {
-		ConfMan.setInt("fast_mode", 1, Common::ConfigManager::kTransientDomain);
-	}
 #endif
 	setupGraphics(system);
 
@@ -791,6 +788,9 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
 				g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderUpdate);
 			} else if (recordMode == "playback") {
 				g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderPlayback);
+			} else if (recordMode == "fast_playback") {
+				g_eventRec.init(recordFileName, GUI::EventRecorder::kRecorderPlayback);
+				g_eventRec.setFastPlayback(true);
 			} else if ((recordMode == "info") && (!recordFileName.empty())) {
 				Common::PlaybackFile record;
 				record.openRead(recordFileName);
diff --git a/doc/docportal/advanced_topics/command_line.rst b/doc/docportal/advanced_topics/command_line.rst
index 2fd527d890c..6a23c2901da 100755
--- a/doc/docportal/advanced_topics/command_line.rst
+++ b/doc/docportal/advanced_topics/command_line.rst
@@ -167,7 +167,6 @@ Short options are listed where they are available.
         ``--engine=ID``,,"In combination with ``--list-games`` or ``--list-all-games`` only lists games for this engine",
         ``--engine-speed=NUM``,,"Sets frame-per-second limit for Grim Fandango or Escape from Monkey Island. 0 is no limit. Allowed values 0 - 100", 60
         ``--extrapath=PATH``,,":ref:`Extra path to additional game data <extra>`",
-        ``--fast-mode``,, "Enable fast playback mode (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",
         ``--filtering``,,":ref:`Forces filtered graphics mode <filtering>`",false
         ``--fullscreen``,``-f``,":ref:`Forces full-screen mode <fullscreen>`",false
         ``--game=ID``,,"In combination with ``--add`` or ``--detect`` only adds or attempts to detect the game with specified ID.",
@@ -228,7 +227,7 @@ Short options are listed where they are available.
         - windows",
         ``--random-seed=SEED``,,":ref:`Sets the random seed used to initialize entropy <seed>`",
         ``--record-file-name=FILE``,,"Specifies recorded file name (`Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_)",record.bin
-        ``--record-mode=MODE``,,"Specifies record mode for `Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_. Allowed values: record, playback, info, update, passthrough.", none
+        ``--record-mode=MODE``,,"Specifies record mode for `Event Recorder <https://wiki.scummvm.org/index.php/Event_Recorder>`_. Allowed values: record, playback, fast_playback, info, update, passthrough.", none
         ``--recursive``,,"In combination with ``--add or ``--detect`` recurses down all subdirectories",
         ``--renderer=RENDERER``,,"Selects 3D renderer. Allowed values: software, opengl, opengl_shaders",
         ``--render-mode=MODE``,,":ref:`Enables additional render modes <render>`.
diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index 37594a9e3d8..e359d162a00 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -379,6 +379,9 @@ Common::String EventRecorder::generateRecordFileName(const Common::String &targe
 	return "";
 }
 
+void EventRecorder::setFastPlayback(bool fastPlayback) {
+	_fastPlayback = fastPlayback;
+}
 
 void EventRecorder::init(const Common::String &recordFileName, RecordMode mode) {
 	_fakeMixerManager = new NullMixerManager();
@@ -389,13 +392,11 @@ void EventRecorder::init(const Common::String &recordFileName, RecordMode mode)
 	_lastScreenshotTime = 0;
 	_recordMode = mode;
 	_needcontinueGame = false;
+	_fastPlayback = false;
 	if (ConfMan.hasKey("disable_display")) {
 		DebugMan.enableDebugChannel("EventRec");
 		gDebugLevel = 1;
 	}
-	if (ConfMan.hasKey("fast_mode")) {
-		_fastPlayback = ConfMan.getInt("fast_mode") != 0;
-	}
 	if ((_recordMode == kRecorderPlayback) || (_recordMode == kRecorderUpdate)) {
 		debugC(1, kDebugLevelEventRec, "playback:action=\"Load file\" filename=%s", recordFileName.c_str());
 		Common::EventDispatcher *eventDispatcher = g_system->getEventManager()->getEventDispatcher();
diff --git a/gui/EventRecorder.h b/gui/EventRecorder.h
index 9beaea8e9d7..a68dd4bbdbe 100644
--- a/gui/EventRecorder.h
+++ b/gui/EventRecorder.h
@@ -80,6 +80,7 @@ public:
 	void init(const Common::String &recordFileName, RecordMode mode);
 	void deinit();
 	bool processDelayMillis();
+	void setFastPlayback(bool fastPlayback);
 	uint32 getRandomSeed(const Common::String &name);
 	void processTimeAndDate(TimeDate &td, bool skipRecord);
 	void processMillis(uint32 &millis, bool skipRecord);


Commit: 3b2b138b69f7fa10569f642ebf80dddec107bad6
    https://github.com/scummvm/scummvm/commit/3b2b138b69f7fa10569f642ebf80dddec107bad6
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2026-01-05T13:25:04+01:00

Commit Message:
DEVTOOLS: added script that executes event recorder tests for configured demos and record files

Changed paths:
  A devtools/run_event_recorder_tests.py


diff --git a/devtools/run_event_recorder_tests.py b/devtools/run_event_recorder_tests.py
new file mode 100755
index 00000000000..8f6252d72e1
--- /dev/null
+++ b/devtools/run_event_recorder_tests.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python3
+
+# To run this in headless mode, set the following environment variables:
+# * SDL_VIDEODRIVER=dummy
+# * SDL_AUDIODRIVER=dummy
+#
+# Also make sure to specify the correct paths to the ScummVM binary, demos, and records if they are not in the default locations.
+# You can also change them via environment variables:
+# * SCUMMVM_BIN - path to the ScummVM binary
+# * GAMES_DIR - path to the games directory that are automatically registered before running tests - defaults to none and is skipped then.
+#               it's assumed that you have already registered the games for playing back the event recorder files.
+#
+# Example usage:
+#   SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy SCUMMVM_BIN=./scummvm \
+#   python3 devtools/run_event_recorder_tests.py --xunit-output=event_recorder_tests.xml \
+#   --filter="*monkey*"
+
+
+import os
+import sys
+import subprocess
+import platform
+import argparse
+import time
+import fnmatch
+import re
+import json
+import xml.etree.ElementTree as ET
+from pathlib import Path
+
+def generate_xunit_report(results, output_file, total_time):
+	testsuites = ET.Element("testsuites")
+	testsuite = ET.SubElement(testsuites, "testsuite", name="EventRecorderTest", tests=str(len(results)), time=str(total_time))
+
+	failures = 0
+	skipped = 0
+	for result in results:
+		# XUnit format: classname="TestSuite", name="TestCase"
+		testcase = ET.SubElement(testsuite, "testcase", name=result['test_case'], classname="EventRecorderTest", time=str(result['duration']))
+		if result.get('skipped'):
+			skipped += 1
+			ET.SubElement(testcase, "skipped", message=result['message'])
+		elif not result['success']:
+			failures += 1
+			failure = ET.SubElement(testcase, "failure", message=result['message'])
+			failure.text = result.get('output', '')
+
+	testsuite.set("failures", str(failures))
+	testsuite.set("skipped", str(skipped))
+
+	tree = ET.ElementTree(testsuites)
+	try:
+		tree.write(output_file, encoding="utf-8", xml_declaration=True)
+		# print(f"XUnit report generated at: {output_file}")
+	except Exception as e:
+		print(f"Error writing XUnit report: {e}")
+
+def main():
+	parser = argparse.ArgumentParser(description="Run ScummVM Event Recorder tests.")
+	parser.add_argument("--xunit-output", help="Path to generate XUnit XML report", default=None)
+	parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose output", default=False)
+	parser.add_argument("--filter", help="Filter tests (glob pattern, e.g. *monkey*)", default="*")
+	parser.add_argument("--list", action="store_true", help="List tests", default=False)
+	args = parser.parse_args()
+
+	# Configuration
+	# Determine default binary name based on OS
+	bin_name = "scummvm.exe" if platform.system() == "Windows" else "./scummvm"
+
+	# Allow overriding via env vars
+	# Default to looking in current directory
+	scummvm_bin = os.getenv("SCUMMVM_BIN", bin_name)
+	if os.getenv("GAMES_DIR", None):
+		games_dir = Path(os.getenv("GAMES_DIR"))
+	else:
+		games_dir = None
+
+	# Check if ScummVM exists
+	if not Path(scummvm_bin).exists():
+		print(f"Error: ScummVM binary not found at {scummvm_bin}")
+		print("Please run this script from the root of the ScummVM source tree where the binary is built.")
+		sys.exit(127)
+
+	# Check if demos directory exists
+	if games_dir is not None:
+		if not games_dir.exists():
+			print(f"Error: Games directory not found at {games_dir}")
+			sys.exit(127)
+
+		# Register games
+		for game_path in sorted(games_dir.iterdir()):
+			if not game_path.is_dir():
+				continue
+
+			try:
+				detect_cmd = [
+					str(scummvm_bin),
+					"--add",
+					f"--path={game_path}"
+				]
+				subprocess.run(detect_cmd, capture_output=True)
+			except Exception as e:
+				print(f"Error detecting games in {game_path}: {e}")
+				continue
+
+	# Get available engines
+	available_engines = set()
+	try:
+		list_engines_cmd = [str(scummvm_bin), "--list-engines-json"]
+		result = subprocess.run(list_engines_cmd, capture_output=True, text=True)
+		if result.returncode == 0:
+			try:
+				engines_map = json.loads(result.stdout)
+				available_engines = set(engines_map.keys())
+			except json.JSONDecodeError:
+				print(f"Warning: Failed to parse engines JSON. Output was:\n{result.stdout}")
+		else:
+			print(f"Warning: Failed to list engines: {result.stderr}")
+	except Exception as e:
+		print(f"Warning: Error executing ScummVM to list engines: {e}")
+
+	# Collect tests
+	test_cases = []
+	try:
+		list_cmd = [str(scummvm_bin), "--list-records-json"]
+		result = subprocess.run(list_cmd, capture_output=True, text=True)
+		if result.returncode != 0:
+			print(f"Error listing records: {result.stderr}")
+			sys.exit(1)
+	except Exception as e:
+		print(f"Error executing ScummVM to list records: {e}")
+		sys.exit(1)
+
+	try:
+		json_output = result.stdout.strip()
+		records_map = json.loads(json_output)
+	except json.JSONDecodeError as e:
+		print(f"Error parsing records JSON: {e}\nOutput was:\n{result.stdout}")
+		sys.exit(1)
+
+	for target, info in records_map.items():
+		engine_id = info.get('engine')
+		for record_file in info.get('records', []):
+			# Test name: EventRecorderTest.<RecordFileName>
+			# We use the filename as the test case name
+			test_case_name = record_file
+			full_test_name = f"EventRecorderTest.{test_case_name}"
+
+			# Check filter
+			# Match against full name or just the test case name
+			if not fnmatch.fnmatch(full_test_name, args.filter) and not fnmatch.fnmatch(test_case_name, args.filter):
+				continue
+
+			test_cases.append({
+				'full_name': full_test_name,
+				'test_case': test_case_name,
+				'record_file': record_file,
+				'target': target,
+				'engine_id': engine_id
+			})
+
+	if args.list:
+		print("EventRecorderTest.")
+		for test in test_cases:
+			print(f"  {test['test_case']}")
+		sys.exit(0)
+
+	total_tests = len(test_cases)
+
+	# Googletest compatible header
+	print(f"[==========] {total_tests} tests from 1 test suite ran.")
+	print(f"[----------] {total_tests} tests from EventRecorderTest")
+
+	start_total_time = time.time()
+	passed_tests = []
+	failed_tests = []
+	skipped_tests = []
+	results_for_xunit = []
+
+	for test in test_cases:
+		print(f"[ RUN      ] {test['full_name']}")
+		sys.stdout.flush()
+
+		test_start_time = time.time()
+		success = False
+		message = ""
+		output = ""
+
+		if available_engines:
+			engine_id = test.get('engine_id')
+			if engine_id and engine_id not in available_engines:
+				print(f"[  SKIPPED ] {test['full_name']} (Engine '{engine_id}' not available)")
+				results_for_xunit.append({
+					'name': test['full_name'],
+					'test_case': test['test_case'],
+					'success': False,
+					'skipped': True,
+					'duration': 0,
+					'message': f"Engine '{engine_id}' not available",
+					'output': ""
+				})
+				skipped_tests.append(test['full_name'])
+				continue
+
+		try:
+			playback_cmd = [
+				str(scummvm_bin),
+				"--record-mode=fast_playback",
+				f"--record-file-name={test['record_file']}",
+				test['target']
+			]
+
+			# Run and capture output
+			if args.verbose:
+				print(f"Executing: {' '.join(playback_cmd)}")
+			playback_result = subprocess.run(playback_cmd, capture_output=True, text=True)
+			output = playback_result.stdout + "\n" + playback_result.stderr
+
+			if args.verbose:
+				if playback_result.stdout.strip():
+					print(playback_result.stdout)
+				if playback_result.stderr.strip():
+					print(playback_result.stderr)
+
+			if playback_result.returncode == 0:
+				success = True
+			else:
+				success = False
+				message = f"Exit Code: {playback_result.returncode}"
+
+		except Exception as e:
+			success = False
+			message = str(e)
+			output += f"\nException: {e}"
+
+		duration_sec = time.time() - test_start_time
+		duration_ms = int(duration_sec * 1000)
+
+		results_for_xunit.append({
+			'name': test['full_name'],
+			'test_case': test['test_case'],
+			'success': success,
+			'duration': duration_sec,
+			'message': message,
+			'output': output
+		})
+
+		if success:
+			print(f"[       OK ] {test['full_name']} ({duration_ms} ms)")
+			passed_tests.append(test['full_name'])
+		else:
+			print(f"[  FAILED  ] {test['full_name']} ({duration_ms} ms)")
+			failed_tests.append(test['full_name'])
+
+	total_duration_sec = time.time() - start_total_time
+	total_duration_ms = int(total_duration_sec * 1000)
+
+	print(f"[----------] {total_tests} tests from EventRecorderTest ({total_duration_ms} ms total)")
+	print(f"[==========] {total_tests} tests from 1 test suite ran. ({total_duration_ms} ms total)")
+	print(f"[  PASSED  ] {len(passed_tests)} tests.")
+
+	if args.xunit_output:
+		generate_xunit_report(results_for_xunit, args.xunit_output, total_duration_sec)
+
+	if failed_tests:
+		print(f"[  FAILED  ] {len(failed_tests)} tests, listed below:")
+		for failed in failed_tests:
+			print(f"[  FAILED  ] {failed}")
+		sys.exit(1)
+
+	if skipped_tests:
+		print(f"[  SKIPPED ] {len(skipped_tests)} tests.")
+		for skipped in skipped_tests:
+			print(f"[  SKIPPED ] {skipped}")
+
+	if total_tests == 0:
+		print("No tests were run.")
+		sys.exit(0)
+
+	sys.exit(0)
+
+if __name__ == "__main__":
+	main()




More information about the Scummvm-git-logs mailing list