]> gitweb.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
qt: restart from in-memory runtime config
authorStefan Reinauer <stefan.reinauer@coreboot.org>
Sun, 21 Jun 2026 18:39:40 +0000 (11:39 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Tue, 7 Jul 2026 21:00:11 +0000 (14:00 -0700)
Stop writing a temporary runtime .uae file just to reopen the Qt

properties dialog. Serialize prefs to an in-memory WinUAE config

snapshot, pass the displayed config path separately, and return the

selected config path to the Unix bridge.

od-unix/gui.cpp
od-unix/qt/config.cpp
od-unix/qt/config.h
od-unix/qt/launcher.cpp
od-unix/qt/launcher.h
od-unix/qt/launcher_bridge.cpp
od-unix/qt/launcher_bridge.h

index d202e080863e5aebb7ed3f818246af2338c50ee2..2ef3564d2548a056035e896daff4c99c23927859 100644 (file)
@@ -26,6 +26,9 @@ unsigned int gui_ledstate;
 
 static int unix_gui_argc;
 static TCHAR **unix_gui_argv;
+#ifdef WINUAE_UNIX_WITH_INTEGRATED_QT_UI
+static TCHAR unix_gui_display_config_path[MAX_DPATH];
+#endif
 
 static bool is_runtime_config_snapshot(const TCHAR *path)
 {
@@ -43,6 +46,49 @@ static bool is_runtime_config_snapshot(const TCHAR *path)
         && !_tcscmp(name + len - suffix_len, suffix);
 }
 
+#ifdef WINUAE_UNIX_WITH_INTEGRATED_QT_UI
+static void copy_gui_config_path(TCHAR *out, size_t out_len, const TCHAR *path)
+{
+    if (!out || out_len == 0) {
+        return;
+    }
+    out[0] = 0;
+    if (!path || !path[0]) {
+        return;
+    }
+    _tcsncpy(out, path, out_len);
+    out[out_len - 1] = 0;
+}
+
+static void remember_gui_display_config_path(const TCHAR *path)
+{
+    if (!path || !path[0] || is_runtime_config_snapshot(path)) {
+        return;
+    }
+    copy_gui_config_path(
+        unix_gui_display_config_path,
+        sizeof unix_gui_display_config_path / sizeof unix_gui_display_config_path[0],
+        path);
+}
+
+static void get_gui_display_config_path(TCHAR *out, size_t out_len, const TCHAR *initial_config)
+{
+    if (!out || out_len == 0) {
+        return;
+    }
+    out[0] = 0;
+    if (unix_gui_display_config_path[0]) {
+        copy_gui_config_path(out, out_len, unix_gui_display_config_path);
+        return;
+    }
+    if (initial_config && initial_config[0] && !is_runtime_config_snapshot(initial_config)) {
+        copy_gui_config_path(out, out_len, initial_config);
+        return;
+    }
+    winUaeQtLauncherInitialConfigPath(unix_gui_argc, unix_gui_argv, out, out_len);
+}
+#endif
+
 void target_main_set_args(int argc, TCHAR **argv)
 {
     unix_gui_argc = argc;
@@ -62,7 +108,7 @@ int gui_init(void)
 
     /* Command-line configs are resolved by the launcher itself and win
      * over default.uae, like on Windows. Otherwise seed the launcher from the
-     * config the core just loaded, which may be a runtime restart snapshot. */
+     * config the core just loaded. */
     if (!winUaeQtLauncherArgumentsSpecifyConfig(unix_gui_argc, unix_gui_argv)) {
         if (optionsfile[0] && access(optionsfile, R_OK) == 0) {
             _tcscpy(initial_config, optionsfile);
@@ -75,13 +121,25 @@ int gui_init(void)
         }
     }
 
-    const int action = runWinUaeQtLauncherForPrefsWithConfig(
+    TCHAR display_config[MAX_DPATH];
+    TCHAR selected_config[MAX_DPATH];
+    get_gui_display_config_path(
+        display_config,
+        sizeof display_config / sizeof display_config[0],
+        initial_config);
+    selected_config[0] = 0;
+
+    const int action = runWinUaeQtLauncherForPrefsWithConfigPaths(
         unix_gui_argc,
         unix_gui_argv,
         &changed_prefs,
         initial_config[0] ? initial_config : nullptr,
+        display_config[0] ? display_config : nullptr,
+        selected_config,
+        sizeof selected_config / sizeof selected_config[0],
         0,
         nullptr);
+    remember_gui_display_config_path(selected_config[0] ? selected_config : display_config);
     if (initial_config[0] && is_runtime_config_snapshot(initial_config)) {
         unlink(initial_config);
     }
@@ -191,24 +249,6 @@ void gui_flicker_led(int led, int, int status)
 void gui_disk_image_change(int, const TCHAR*, bool) {}
 
 #ifdef WINUAE_UNIX_WITH_INTEGRATED_QT_UI
-static bool write_runtime_config_snapshot(TCHAR *path, size_t path_len)
-{
-    const char *tmpdir = getenv("TMPDIR");
-    if (!tmpdir || !tmpdir[0]) {
-        tmpdir = "/tmp";
-    }
-    const int written = snprintf(path, path_len, "%s/winuae-runtime-%ld.uae", tmpdir, (long)getpid());
-    if (written < 0 || size_t(written) >= path_len) {
-        write_log("Unix Qt runtime UI: temporary config path is too long\n");
-        return false;
-    }
-    if (!cfgfile_save(&changed_prefs, path, 0)) {
-        write_log("Unix Qt runtime UI: failed to write temporary config '%s'\n", path);
-        return false;
-    }
-    return true;
-}
-
 static const TCHAR *runtime_shortcut_initial_path(int shortcut)
 {
     if (shortcut >= 0 && shortcut < 4) {
@@ -287,26 +327,28 @@ void gui_display(int shortcut)
     pause_sound();
 
     if (shortcut == -1) {
-        TCHAR snapshot_path[MAX_DPATH];
-        snapshot_path[0] = 0;
-        bool have_snapshot = write_runtime_config_snapshot(snapshot_path, sizeof snapshot_path / sizeof snapshot_path[0]);
+        TCHAR display_config[MAX_DPATH];
+        TCHAR selected_config[MAX_DPATH];
+        get_gui_display_config_path(
+            display_config,
+            sizeof display_config / sizeof display_config[0],
+            nullptr);
+        selected_config[0] = 0;
 
         int exit_code = 0;
-        const int action = runWinUaeQtLauncherForPrefsWithConfig(
+        const int action = runWinUaeQtLauncherForPrefsWithConfigSnapshot(
             unix_gui_argc,
             unix_gui_argv,
             &changed_prefs,
-            have_snapshot ? snapshot_path : nullptr,
+            display_config[0] ? display_config : nullptr,
+            selected_config,
+            sizeof selected_config / sizeof selected_config[0],
             1,
             &exit_code);
-
-        if (have_snapshot && action == WINUAE_QT_LAUNCHER_RESTART
-            && !write_runtime_config_snapshot(snapshot_path, sizeof snapshot_path / sizeof snapshot_path[0])) {
-            unlink(snapshot_path);
-            have_snapshot = false;
-        }
-        if (have_snapshot && action != WINUAE_QT_LAUNCHER_RESTART) {
-            unlink(snapshot_path);
+        if (action == WINUAE_QT_LAUNCHER_START
+            || action == WINUAE_QT_LAUNCHER_RESET
+            || action == WINUAE_QT_LAUNCHER_RESTART) {
+            remember_gui_display_config_path(selected_config[0] ? selected_config : display_config);
         }
 
         if (action == WINUAE_QT_LAUNCHER_START || action == WINUAE_QT_LAUNCHER_RESET) {
@@ -321,7 +363,9 @@ void gui_display(int shortcut)
         } else if (action == WINUAE_QT_LAUNCHER_QUIT) {
             uae_quit();
         } else if (action == WINUAE_QT_LAUNCHER_RESTART) {
-            uae_restart(&changed_prefs, -1, have_snapshot ? snapshot_path : nullptr);
+            fixup_prefs(&changed_prefs, true);
+            copy_prefs(&changed_prefs, &currprefs);
+            uae_restart(&changed_prefs, -1, nullptr);
         } else if (action == WINUAE_QT_LAUNCHER_ERROR) {
             write_log("Unix Qt runtime UI exited with error code %d\n", exit_code);
         }
index 8d709a3d2615e2716edba8974f106753efdee820..2bc5ecb6f1d46c058746e84091207fbf15e052d5 100644 (file)
@@ -281,11 +281,18 @@ bool WinUaeQtConfig::load(const QString &path, QString *error)
         return false;
     }
 
+    return loadFromText(QString::fromUtf8(file.readAll()), error);
+}
+
+bool WinUaeQtConfig::loadFromText(const QString &contents, QString *)
+{
     Settings loaded;
     OrderedSettings ordered;
     QList<DocumentLine> lines;
-    while (!file.atEnd()) {
-        QString text = QString::fromUtf8(file.readLine());
+    QString copy = contents;
+    QTextStream in(&copy, QIODevice::ReadOnly);
+    while (!in.atEnd()) {
+        QString text = in.readLine();
         while (text.endsWith(QLatin1Char('\n')) || text.endsWith(QLatin1Char('\r'))) {
             text.chop(1);
         }
index 2e55c18d5d0afa7e9abc3e7688bce431950db7c6..7a0bf20278b20bdb524c99b2d240f48f25af373f 100644 (file)
@@ -30,6 +30,7 @@ public:
     void removeValue(const QString &key);
 
     bool load(const QString &path, QString *error = nullptr);
+    bool loadFromText(const QString &contents, QString *error = nullptr);
     bool save(const QString &path, QString *error = nullptr) const;
 
     QStringList commandArguments() const;
index 316679ec52adb4bf415322466797a9a05a4db4d1..aefd59523109ba78fe300f7986b0f11e18fa48c9 100644 (file)
@@ -5181,7 +5181,7 @@ static bool isConfigPath(const QString &path)
     return path.endsWith(QStringLiteral(".uae"), Qt::CaseInsensitive);
 }
 
-static QString initialConfigPathFromArguments(const QStringList &arguments)
+QString winUaeQtInitialConfigPathFromArguments(const QStringList &arguments)
 {
     for (int i = 1; i < arguments.size(); i++) {
         const QString arg = arguments[i];
@@ -5271,6 +5271,7 @@ public:
     explicit WinUaeQtDialog(
         QWidget *parent = nullptr,
         const QString &initialConfigPath = QString(),
+        const QString &displayConfigPath = QString(),
         const WinUaeQtHardwareInfoProvider &hardwareInfoProvider = WinUaeQtHardwareInfoProvider())
         : QDialog(parent),
           hardwareProvider(hardwareInfoProvider),
@@ -5380,8 +5381,7 @@ public:
             accept();
         });
         connect(restart, &QPushButton::clicked, this, [this]() {
-            result.status = WinUaeQtLauncherStatus::RestartRequested;
-            accept();
+            requestRestart();
         });
         connect(cancel, &QPushButton::clicked, this, &QDialog::reject);
         connect(start, &QPushButton::clicked, this, [this]() { startEmulator(); });
@@ -5413,7 +5413,9 @@ public:
         resetDefaults();
         navigation->setCurrentItem(quickstartPage);
         if (!initialConfigPath.isEmpty()) {
-            loadConfig(initialConfigPath);
+            if (loadConfig(initialConfigPath)) {
+                setLoadedConfigDisplayPath(displayConfigPath);
+            }
         }
         if (hardwareProvider.pollHostWindowEvents) {
             QTimer *timer = new QTimer(this);
@@ -5439,6 +5441,11 @@ public:
         activateWindow();
     }
 
+    bool loadConfigSnapshot(const WinUaeQtConfig &config, const QString &displayConfigPath)
+    {
+        return loadConfigDocument(config, displayConfigPath);
+    }
+
     bool exportMergedConfig(const QString &path)
     {
         WinUaeQtConfig config = mergedConfig();
@@ -16188,15 +16195,21 @@ private:
         }
     }
 
-    void loadConfig(const QString &path)
+    bool loadConfig(const QString &path)
     {
         const QString expandedPath = expandedPathText(path);
         WinUaeQtConfig config;
         QString error;
         if (!config.load(expandedPath, &error)) {
             QMessageBox::warning(this, windowTitle(), error);
-            return;
+            return false;
         }
+        return loadConfigDocument(config, expandedPath);
+    }
+
+    bool loadConfigDocument(const WinUaeQtConfig &config, const QString &path)
+    {
+        WinUaeQtConfig loaded = config;
         if (mountedDrives) {
             mountedDrives->clear();
         }
@@ -16221,8 +16234,8 @@ private:
                 quickstartSetConfig->setVisible(true);
             }
         }
-        moveQuickstartBeforeOverrides(config);
-        for (const WinUaeQtConfig::Setting &setting : config.orderedSettings()) {
+        moveQuickstartBeforeOverrides(loaded);
+        for (const WinUaeQtConfig::Setting &setting : loaded.orderedSettings()) {
             applySetting(setting.key, setting.value);
         }
         updateOutputControlState();
@@ -16231,14 +16244,41 @@ private:
         updateFpuControls();
         updateCpuControlState();
         updateAdvancedChipsetControlState();
-        loadedConfig = config;
+        loadedConfig = loaded;
         refreshHardwareInfoPage();
+        const QString expandedPath = expandedPathText(path);
+        configPath->setText(expandedPath);
+        if (!expandedPath.isEmpty()) {
+            configName->setCurrentText(QFileInfo(expandedPath).completeBaseName());
+        }
+        refreshConfigList();
+        status->setText(expandedPath.isEmpty()
+            ? QStringLiteral("Loaded running configuration")
+            : QStringLiteral("Loaded %1").arg(expandedPath));
+        return true;
+    }
+
+    void setLoadedConfigDisplayPath(const QString &path)
+    {
+        if (path.isEmpty()) {
+            return;
+        }
+        const QString expandedPath = expandedPathText(path);
         configPath->setText(expandedPath);
         configName->setCurrentText(QFileInfo(expandedPath).completeBaseName());
         refreshConfigList();
         status->setText(QStringLiteral("Loaded %1").arg(expandedPath));
     }
 
+    QString currentConfigPath() const
+    {
+        if (!configPath) {
+            return QString();
+        }
+        const QString path = configPath->text().trimmed();
+        return path.isEmpty() ? QString() : expandedPathText(path);
+    }
+
     void applySetting(const QString &key, const QString &value)
     {
         trackHardwareOrderSetting(key, value);
@@ -17132,7 +17172,17 @@ private:
         requestStart(false);
     }
 
+    void requestRestart()
+    {
+        requestStart(false, WinUaeQtLauncherStatus::RestartRequested);
+    }
+
     void requestStart(bool hardReset)
+    {
+        requestStart(hardReset, WinUaeQtLauncherStatus::StartRequested);
+    }
+
+    void requestStart(bool hardReset, WinUaeQtLauncherStatus status)
     {
         const WinUaeQtConfig config = mergedConfig();
         const QStringList validationErrors = config.validateForLaunch();
@@ -17142,9 +17192,10 @@ private:
             return;
         }
 
-        result.status = WinUaeQtLauncherStatus::StartRequested;
+        result.status = status;
         result.hardReset = hardReset;
         result.config = config;
+        result.configPath = currentConfigPath();
         accept();
     }
 };
@@ -17271,26 +17322,11 @@ static void armQtSmokeExit(QDialog &dialog, QApplication *app = nullptr)
 
 bool winUaeQtArgumentsSpecifyConfig(const QStringList &arguments)
 {
-    return !initialConfigPathFromArguments(arguments).isEmpty();
-}
-
-WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app)
-{
-    return runWinUaeQtLauncherForConfig(app, QString());
-}
-
-WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath)
-{
-    return runWinUaeQtLauncherForConfig(app, initialConfigPath, WinUaeQtHardwareInfoProvider());
+    return !winUaeQtInitialConfigPathFromArguments(arguments).isEmpty();
 }
 
-WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+static WinUaeQtLauncherResult runWinUaeQtLauncherDialog(QApplication &app, WinUaeQtDialog &dialog)
 {
-    setupApplicationStyle(app);
-    WinUaeQtDialog dialog(
-        nullptr,
-        initialConfigPath.isEmpty() ? initialConfigPathFromArguments(app.arguments()) : initialConfigPath,
-        hardwareProvider);
     if (WinUaeQtApplication *qtApp = dynamic_cast<WinUaeQtApplication *>(&app)) {
         qtApp->setConfigOpenHandler([&dialog](const QString &path) {
             dialog.openConfigFile(path);
@@ -17320,6 +17356,40 @@ WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QSt
     return result;
 }
 
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app)
+{
+    return runWinUaeQtLauncherForConfig(app, QString());
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath)
+{
+    return runWinUaeQtLauncherForConfig(app, initialConfigPath, WinUaeQtHardwareInfoProvider());
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+{
+    return runWinUaeQtLauncherForConfig(app, initialConfigPath, QString(), hardwareProvider);
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+{
+    setupApplicationStyle(app);
+    WinUaeQtDialog dialog(
+        nullptr,
+        initialConfigPath.isEmpty() ? winUaeQtInitialConfigPathFromArguments(app.arguments()) : initialConfigPath,
+        displayConfigPath,
+        hardwareProvider);
+    return runWinUaeQtLauncherDialog(app, dialog);
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const WinUaeQtConfig &initialConfig, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+{
+    setupApplicationStyle(app);
+    WinUaeQtDialog dialog(nullptr, QString(), QString(), hardwareProvider);
+    dialog.loadConfigSnapshot(initialConfig, displayConfigPath);
+    return runWinUaeQtLauncherDialog(app, dialog);
+}
+
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv)
 {
     return runWinUaeQtLauncherForConfig(argc, argv, QString());
@@ -17331,9 +17401,20 @@ WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const
 }
 
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const QString &initialConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+{
+    return runWinUaeQtLauncherForConfig(argc, argv, initialConfigPath, QString(), hardwareProvider);
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const QString &initialConfigPath, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
+{
+    WinUaeQtApplication app(argc, argv);
+    return runWinUaeQtLauncherForConfig(app, initialConfigPath, displayConfigPath, hardwareProvider);
+}
+
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const WinUaeQtConfig &initialConfig, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider)
 {
     WinUaeQtApplication app(argc, argv);
-    return runWinUaeQtLauncherForConfig(app, initialConfigPath, hardwareProvider);
+    return runWinUaeQtLauncherForConfig(app, initialConfig, displayConfigPath, hardwareProvider);
 }
 
 static QString runtimeDialogDirectory(const QString &initialPath)
index 381b304ee69276076b09f66135d6de8a369e39ae..77ff34fc83e716857e62aada2aebd8484547bf57 100644 (file)
@@ -19,6 +19,7 @@ struct WinUaeQtLauncherResult {
     bool hardReset = false;
     int exitCode = 0;
     QString error;
+    QString configPath;
     WinUaeQtConfig config;
 };
 
@@ -141,12 +142,17 @@ struct WinUaeQtHardwareInfoProvider {
 };
 
 bool winUaeQtArgumentsSpecifyConfig(const QStringList &arguments);
+QString winUaeQtInitialConfigPathFromArguments(const QStringList &arguments);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const QString &initialConfigPath, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(QApplication &app, const WinUaeQtConfig &initialConfig, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const QString &initialConfigPath);
 WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const QString &initialConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const QString &initialConfigPath, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
+WinUaeQtLauncherResult runWinUaeQtLauncherForConfig(int argc, char **argv, const WinUaeQtConfig &initialConfig, const QString &displayConfigPath, const WinUaeQtHardwareInfoProvider &hardwareProvider);
 WinUaeQtRuntimeFileDialogResult runWinUaeQtRuntimeFileDialog(QApplication &app, int shortcut, const QString &initialPath);
 WinUaeQtRuntimeFileDialogResult runWinUaeQtRuntimeFileDialog(int argc, char **argv, int shortcut, const QString &initialPath);
 int runWinUaeQtMessageBox(QApplication &app, int flags, const QString &message);
index e921f423f283a5d29fe0f8bb22e80747761a86a4..2edb4fa3dd3a8228510602cea4861ab0aabb5d61 100644 (file)
@@ -531,29 +531,71 @@ static WinUaeQtHardwareInfoProvider bridgeHardwareProvider(struct uae_prefs *pre
     return provider;
 }
 
-int winUaeQtLauncherArgumentsSpecifyConfig(int argc, char **argv)
+static QStringList bridgeArguments(int argc, char **argv)
 {
     QStringList arguments;
     arguments.reserve(argc);
     for (int i = 0; i < argc; i++) {
         arguments.append(QString::fromLocal8Bit(argv[i]));
     }
-    return winUaeQtArgumentsSpecifyConfig(arguments) ? 1 : 0;
+    return arguments;
 }
 
-int runWinUaeQtLauncherForPrefs(int argc, char **argv, struct uae_prefs *prefs, int *exitCode)
+static bool bridgeCopyPath(const QString &path, char *out, size_t outLen)
 {
-    return runWinUaeQtLauncherForPrefsWithConfig(argc, argv, prefs, nullptr, 0, exitCode);
+    if (!out || outLen == 0) {
+        return path.isEmpty();
+    }
+    out[0] = 0;
+    if (path.isEmpty()) {
+        return true;
+    }
+    const QByteArray bytes = path.toLocal8Bit();
+    if (size_t(bytes.size()) >= outLen) {
+        return false;
+    }
+    memcpy(out, bytes.constData(), size_t(bytes.size()) + 1);
+    return true;
 }
 
-int runWinUaeQtLauncherForPrefsWithConfig(int argc, char **argv, struct uae_prefs *prefs, const char *initialConfigPath, int runtimeActions, int *exitCode)
+static bool bridgeConfigFromPrefs(struct uae_prefs *prefs, WinUaeQtConfig *config)
+{
+    if (!prefs || !config) {
+        return false;
+    }
+    struct zfile *file = zfile_fopen_empty(nullptr, _T("unix-qt-prefs.uae"), 0);
+    if (!file) {
+        return false;
+    }
+    cfgfile_save_options(file, prefs, CONFIG_TYPE_ALL);
+    size_t len = 0;
+    const uae_u8 *data = zfile_get_data_pointer(file, &len);
+    const QString text = data && len ? QString::fromLocal8Bit((const char *)data, int(len)) : QString();
+    zfile_fclose(file);
+
+    QString error;
+    if (!config->loadFromText(text, &error)) {
+        const QByteArray bytes = error.toLocal8Bit();
+        fprintf(stderr, "Unix Qt UI failed to parse runtime config: %s\n", bytes.constData());
+        return false;
+    }
+    return true;
+}
+
+static int bridgeHandleLauncherResult(
+    const WinUaeQtLauncherResult &result,
+    struct uae_prefs *prefs,
+    char *selectedConfigPath,
+    size_t selectedConfigPathLen,
+    int *exitCode)
 {
-    const QString initialPath = initialConfigPath && initialConfigPath[0]
-        ? QString::fromLocal8Bit(initialConfigPath)
-        : QString();
-    WinUaeQtLauncherResult result = runWinUaeQtLauncherForConfig(argc, argv, initialPath, bridgeHardwareProvider(prefs, runtimeActions != 0));
     if (result.status == WinUaeQtLauncherStatus::StartRequested
         || result.status == WinUaeQtLauncherStatus::RestartRequested) {
+        if (selectedConfigPath
+            && selectedConfigPathLen > 0
+            && !bridgeCopyPath(result.configPath, selectedConfigPath, selectedConfigPathLen)) {
+            fprintf(stderr, "Unix Qt UI warning: selected config path is too long\n");
+        }
         if (!applyWinUaeQtConfigToPrefs(result.config, prefs)) {
             fprintf(stderr, "Unix Qt UI failed: no preferences target available\n");
             if (exitCode) {
@@ -589,6 +631,106 @@ int runWinUaeQtLauncherForPrefsWithConfig(int argc, char **argv, struct uae_pref
     return WINUAE_QT_LAUNCHER_EXIT;
 }
 
+int winUaeQtLauncherArgumentsSpecifyConfig(int argc, char **argv)
+{
+    return winUaeQtArgumentsSpecifyConfig(bridgeArguments(argc, argv)) ? 1 : 0;
+}
+
+int winUaeQtLauncherInitialConfigPath(int argc, char **argv, char *path, size_t pathLen)
+{
+    if (path && pathLen > 0) {
+        path[0] = 0;
+    }
+    const QString initialPath = winUaeQtInitialConfigPathFromArguments(bridgeArguments(argc, argv));
+    if (initialPath.isEmpty()) {
+        return 0;
+    }
+    return bridgeCopyPath(initialPath, path, pathLen) ? 1 : -1;
+}
+
+int runWinUaeQtLauncherForPrefs(int argc, char **argv, struct uae_prefs *prefs, int *exitCode)
+{
+    return runWinUaeQtLauncherForPrefsWithConfig(argc, argv, prefs, nullptr, 0, exitCode);
+}
+
+int runWinUaeQtLauncherForPrefsWithConfig(int argc, char **argv, struct uae_prefs *prefs, const char *initialConfigPath, int runtimeActions, int *exitCode)
+{
+    return runWinUaeQtLauncherForPrefsWithConfigPaths(
+        argc,
+        argv,
+        prefs,
+        initialConfigPath,
+        nullptr,
+        nullptr,
+        0,
+        runtimeActions,
+        exitCode);
+}
+
+int runWinUaeQtLauncherForPrefsWithConfigPaths(
+    int argc,
+    char **argv,
+    struct uae_prefs *prefs,
+    const char *initialConfigPath,
+    const char *displayConfigPath,
+    char *selectedConfigPath,
+    size_t selectedConfigPathLen,
+    int runtimeActions,
+    int *exitCode)
+{
+    if (selectedConfigPath && selectedConfigPathLen > 0) {
+        selectedConfigPath[0] = 0;
+    }
+    const QString initialPath = initialConfigPath && initialConfigPath[0]
+        ? QString::fromLocal8Bit(initialConfigPath)
+        : QString();
+    const QString displayPath = displayConfigPath && displayConfigPath[0]
+        ? QString::fromLocal8Bit(displayConfigPath)
+        : QString();
+    WinUaeQtLauncherResult result = runWinUaeQtLauncherForConfig(
+        argc,
+        argv,
+        initialPath,
+        displayPath,
+        bridgeHardwareProvider(prefs, runtimeActions != 0));
+    return bridgeHandleLauncherResult(result, prefs, selectedConfigPath, selectedConfigPathLen, exitCode);
+}
+
+int runWinUaeQtLauncherForPrefsWithConfigSnapshot(
+    int argc,
+    char **argv,
+    struct uae_prefs *prefs,
+    const char *displayConfigPath,
+    char *selectedConfigPath,
+    size_t selectedConfigPathLen,
+    int runtimeActions,
+    int *exitCode)
+{
+    if (selectedConfigPath && selectedConfigPathLen > 0) {
+        selectedConfigPath[0] = 0;
+    }
+
+    WinUaeQtConfig initialConfig;
+    if (!bridgeConfigFromPrefs(prefs, &initialConfig)) {
+        fprintf(stderr, "Unix Qt UI failed: could not snapshot runtime preferences\n");
+        if (exitCode) {
+            *exitCode = 1;
+        }
+        return WINUAE_QT_LAUNCHER_ERROR;
+    }
+
+    const QString displayPath = displayConfigPath && displayConfigPath[0]
+        ? QString::fromLocal8Bit(displayConfigPath)
+        : QString();
+    WinUaeQtLauncherResult result = runWinUaeQtLauncherForConfig(
+        argc,
+        argv,
+        initialConfig,
+        displayPath,
+        bridgeHardwareProvider(prefs, runtimeActions != 0));
+    return bridgeHandleLauncherResult(result, prefs, selectedConfigPath, selectedConfigPathLen, exitCode);
+}
+
 int runWinUaeQtRuntimeFileDialog(int argc, char **argv, int shortcut, const char *initialPath, char *selectedPath, size_t selectedPathLen, int *exitCode)
 {
     if (!selectedPath || selectedPathLen == 0) {
index 2c04e9b3132a6527763c21e1bc8f12639d6cc43d..d083171eddf3da008b3f4c4fcb1b91954ce7eedd 100644 (file)
@@ -16,7 +16,10 @@ enum {
 };
 
 int winUaeQtLauncherArgumentsSpecifyConfig(int argc, char **argv);
+int winUaeQtLauncherInitialConfigPath(int argc, char **argv, char *path, size_t path_len);
 int runWinUaeQtLauncherForPrefs(int argc, char **argv, struct uae_prefs *prefs, int *exit_code);
 int runWinUaeQtLauncherForPrefsWithConfig(int argc, char **argv, struct uae_prefs *prefs, const char *initial_config_path, int runtime_actions, int *exit_code);
+int runWinUaeQtLauncherForPrefsWithConfigPaths(int argc, char **argv, struct uae_prefs *prefs, const char *initial_config_path, const char *display_config_path, char *selected_config_path, size_t selected_config_path_len, int runtime_actions, int *exit_code);
+int runWinUaeQtLauncherForPrefsWithConfigSnapshot(int argc, char **argv, struct uae_prefs *prefs, const char *display_config_path, char *selected_config_path, size_t selected_config_path_len, int runtime_actions, int *exit_code);
 int runWinUaeQtRuntimeFileDialog(int argc, char **argv, int shortcut, const char *initial_path, char *selected_path, size_t selected_path_len, int *exit_code);
 int runWinUaeQtMessageBox(int argc, char **argv, int flags, const char *message, int *exit_code);