[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