]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
od-unix: show controller-backed hardfiles like Windows
authorStefan Reinauer <stefan.reinauer@coreboot.org>
Wed, 17 Jun 2026 16:17:38 +0000 (09:17 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Wed, 17 Jun 2026 19:27:31 +0000 (12:27 -0700)
Mirror Windows in the mounted-drive list for hardfiles attached to IDE,
SCSI, or custom controllers. Show the controller target instead of the
Amiga device name, and mark the boot priority as not applicable.

Keep RDB hardfiles on non-UAE controllers in the same state when they
are edited or saved. The Qt dialog clears the Device field, hides the
boot-priority controls, and serializes stale device names back to the
empty Windows-style value.

od-unix/qt/launcher.cpp
od-unix/qt/mount_config.cpp
od-unix/qt/mount_config.h
od-unix/qt/mount_config_test.cpp

index 20fb2d6ca6bca8ed67b9a794db31c6eb31abd791..8ff794ac67e7d44b83567e76ecdb160533216642 100644 (file)
@@ -875,7 +875,12 @@ static QString mountControllerDisplay(const WinUaeQtBoardCatalog &catalog, const
     const QString display = mountControllerDisplayForConfigValue(catalog, value);
     const WinUaeQtMountControllerChoice choice = mountControllerChoiceByDisplay(catalog, display);
     if (choice.valid && !choice.boardKey.isEmpty()) {
-        return QStringLiteral("%1:%2").arg(mountControllerBaseDisplay(display)).arg(mountControllerUnit(entry, fallback));
+        QString board = mountControllerBaseDisplay(display);
+        const QString busSuffix = QStringLiteral(" (%1)").arg(mountControllerBusName(choice.bus));
+        if (board.endsWith(busSuffix)) {
+            board.chop(busSuffix.size());
+        }
+        return QStringLiteral("%1:%2").arg(board).arg(mountControllerUnit(entry, fallback));
     }
     const QString upper = value.toUpper();
     if (upper.startsWith(QStringLiteral("IDE"))) {
@@ -908,10 +913,7 @@ static QStringList hardfileGeometryParts(const WinUaeQtMountEntry &entry)
 
 static bool hardfileIsRdb(const WinUaeQtMountEntry &entry)
 {
-    const QStringList geometry = hardfileGeometryParts(entry);
-    return geometry.value(0).toInt() == 0
-        && geometry.value(1).toInt() == 0
-        && geometry.value(2).toInt() == 0;
+    return winUaeQtHardfileIsRdb(entry);
 }
 
 static bool hardfileHasPhysicalGeometry(const WinUaeQtMountEntry &entry)
@@ -13855,7 +13857,16 @@ private:
             normalized.device = winUaeQtSanitizedAmigaName(normalized.device, nextMountDeviceName(), true);
             normalized.volume = winUaeQtSanitizedAmigaName(normalized.volume, winUaeQtDefaultVolumeName(normalized.path), false);
         } else if (normalized.kind == QStringLiteral("hdf")) {
-            normalized.device = winUaeQtSanitizedAmigaName(normalized.device, nextMountDeviceName(), true);
+            if (winUaeQtHardfileIsRdb(normalized)
+                && winUaeQtHardfileUsesNonUaeController(normalized)) {
+                normalized.device.clear();
+                normalized.bootPri = 0;
+            } else {
+                normalized.device = winUaeQtSanitizedAmigaName(
+                    normalized.device,
+                    nextMountDeviceName(),
+                    true);
+            }
         } else if (normalized.kind == QStringLiteral("cd")) {
             normalized.device.clear();
             normalized.volume = QStringLiteral("CD");
@@ -13890,6 +13901,11 @@ private:
         } else if (normalized.kind == QStringLiteral("hdf")) {
             const QStringList geometry = normalized.hardfileGeometry.split(QLatin1Char(','));
             blockSizeText = geometry.value(3, QStringLiteral("512"));
+            if (winUaeQtHardfileUsesNonUaeController(normalized)) {
+                deviceText = mountControllerDisplay(boardCatalog, normalized);
+                volumeText = QStringLiteral("HDF");
+                bootPriText = QStringLiteral("n/a");
+            }
         }
 
         item->setText(0, QString());
@@ -14184,7 +14200,10 @@ private:
         QLineEdit *path = new QLineEdit(entry->path);
         QLineEdit *geometryFile = new QLineEdit(hardfileTailGeometryFile(*entry));
         QLineEdit *filesys = new QLineEdit(mountControllerParts(entry->hardfileTail).value(0));
-        QLineEdit *device = new QLineEdit(entry->device.isEmpty() ? nextMountDeviceName() : entry->device);
+        const bool controllerBackedRdb = hardfileIsRdb(*entry)
+            && winUaeQtHardfileUsesNonUaeController(*entry);
+        QLineEdit *device = new QLineEdit(
+            entry->device.isEmpty() && !controllerBackedRdb ? nextMountDeviceName() : entry->device);
         QSpinBox *bootPri = new QSpinBox;
         bootPri->setRange(-129, 127);
         bootPri->setValue(entry->bootPri);
@@ -14244,9 +14263,11 @@ private:
         fields->addWidget(label(QStringLiteral("FileSys:")), 2, 0);
         fields->addWidget(filesys, 2, 1, 1, 2);
         fields->addWidget(filesysBrowse, 2, 3);
-        fields->addWidget(label(QStringLiteral("Device:")), 3, 0);
+        QLabel *deviceLabel = label(QStringLiteral("Device:"));
+        QLabel *bootPriLabel = label(QStringLiteral("Boot priority:"));
+        fields->addWidget(deviceLabel, 3, 0);
         fields->addWidget(device, 3, 1);
-        fields->addWidget(label(QStringLiteral("Boot priority:")), 3, 2);
+        fields->addWidget(bootPriLabel, 3, 2);
         fields->addWidget(bootPri, 3, 3);
         fields->addWidget(readWrite, 4, 1);
         fields->addWidget(autoboot, 4, 2);
@@ -14323,12 +14344,40 @@ private:
             readWrite->setEnabled(!nativeDrive);
             browse->setEnabled(!nativeDrive);
         };
+        auto updateControllerBackedRdbControls =
+            [this, controller, sectors, surfaces, reserved, device,
+             deviceLabel, bootPri, bootPriLabel, autoboot, doNotMount]() {
+            const WinUaeQtMountControllerBus bus =
+                mountControllerBusFromDisplay(boardCatalog, controller->currentText());
+            const bool controllerBacked = sectors->value() == 0
+                && surfaces->value() == 0
+                && reserved->value() == 0
+                && bus != MountControllerBusUae
+                && bus != MountControllerBusUnknown;
+
+            if (controllerBacked) {
+                QSignalBlocker blockDevice(device);
+                QSignalBlocker blockBootPri(bootPri);
+                device->clear();
+                bootPri->setValue(0);
+            } else if (device->text().trimmed().isEmpty()) {
+                QSignalBlocker blockDevice(device);
+                device->setText(nextMountDeviceName());
+            }
+            deviceLabel->setEnabled(!controllerBacked);
+            device->setEnabled(!controllerBacked);
+            bootPriLabel->setVisible(!controllerBacked);
+            bootPri->setVisible(!controllerBacked);
+            autoboot->setVisible(!controllerBacked);
+            doNotMount->setVisible(!controllerBacked);
+        };
 
         updateBootChecks();
         updatePhysicalControls();
         updateControllerUnitRange(controllerUnit, controller->currentText());
         setFeatureItems(hardfileFeatureText(boardCatalog, *entry, controller->currentText()));
         updateNativeDriveControls();
+        updateControllerBackedRdbControls();
 
         connect(browse, &QPushButton::clicked, this, [this, path]() {
             const QString initialPath = fileDialogInitialPath(path->text());
@@ -14370,7 +14419,9 @@ private:
                 bootPri->setValue(-128);
             }
         });
-        connect(rdbMode, &QCheckBox::toggled, this, [sectors, surfaces, reserved, blockSize, device, filesys, bootPri](bool checked) {
+        connect(rdbMode, &QCheckBox::toggled, this,
+            [sectors, surfaces, reserved, blockSize, device, filesys,
+             bootPri, updateControllerBackedRdbControls](bool checked) {
             if (checked) {
                 sectors->setValue(0);
                 surfaces->setValue(0);
@@ -14385,12 +14436,20 @@ private:
                 reserved->setValue(2);
                 blockSize->setValue(512);
             }
+            updateControllerBackedRdbControls();
         });
         connect(manualGeometry, &QCheckBox::toggled, this, updatePhysicalControls);
-        connect(controller, &QComboBox::currentTextChanged, this, [this, controllerUnit, setFeatureItems](const QString &text) {
+        connect(controller, &QComboBox::currentTextChanged, this,
+            [this, controllerUnit, setFeatureItems,
+             updateControllerBackedRdbControls](const QString &text) {
             updateControllerUnitRange(controllerUnit, text);
             setFeatureItems(QStringLiteral("Default"));
+            updateControllerBackedRdbControls();
         });
+        for (QSpinBox *spin : { sectors, surfaces, reserved }) {
+            connect(spin, QOverload<int>::of(&QSpinBox::valueChanged),
+                this, updateControllerBackedRdbControls);
+        }
         connect(path, &QLineEdit::editingFinished, this, updateNativeDriveControls);
         connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
         connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
@@ -14400,9 +14459,7 @@ private:
         }
 
         entry->kind = QStringLiteral("hdf");
-        entry->device = winUaeQtSanitizedAmigaName(device->text(), nextMountDeviceName(), true);
         entry->path = path->text().trimmed();
-        entry->bootPri = bootPri->value();
         entry->readOnly = !readWrite->isChecked() || entry->path.startsWith(QLatin1Char(':'));
         entry->hardfileGeometry = QStringLiteral("%1,%2,%3,%4")
             .arg(sectors->value())
@@ -14432,6 +14489,13 @@ private:
         }
         tailFields.append(hardfilePreservedTailExtras(*entry));
         entry->hardfileTail = winUaeQtConfigJoinFields(tailFields);
+        const bool acceptedControllerBackedRdb = winUaeQtHardfileIsRdb(*entry)
+            && winUaeQtHardfileUsesNonUaeController(*entry);
+        entry->device = winUaeQtSanitizedAmigaName(
+            device->text(),
+            acceptedControllerBackedRdb ? QString() : nextMountDeviceName(),
+            true);
+        entry->bootPri = acceptedControllerBackedRdb ? 0 : bootPri->value();
         return true;
     }
 
index 44bdaef70cafce5927c3923d04d8c83892d06454..80b037881ef023f0a9ef813430af16e3a16f9e46 100644 (file)
@@ -121,6 +121,35 @@ QString winUaeQtConfigJoinFields(const QStringList &fields)
     return escapedFields.join(QLatin1Char(','));
 }
 
+static QString hardfileControllerValue(const WinUaeQtMountEntry &entry)
+{
+    QString tail = entry.hardfileTail;
+    if (!tail.startsWith(QLatin1Char(','))) {
+        tail.prepend(QLatin1Char(','));
+    }
+    const QStringList fields = winUaeQtConfigFieldList(tail);
+    return fields.value(1, QStringLiteral("uae0")).trimmed();
+}
+
+bool winUaeQtHardfileIsRdb(const WinUaeQtMountEntry &entry)
+{
+    if (entry.hardfileGeometry.trimmed().isEmpty()) {
+        return false;
+    }
+    const QStringList geometry = entry.hardfileGeometry.split(QLatin1Char(','));
+    return geometry.value(0).toInt() == 0
+        && geometry.value(1).toInt() == 0
+        && geometry.value(2).toInt() == 0;
+}
+
+bool winUaeQtHardfileUsesNonUaeController(const WinUaeQtMountEntry &entry)
+{
+    const QString controller = hardfileControllerValue(entry).toLower();
+    return controller.startsWith(QStringLiteral("ide"))
+        || controller.startsWith(QStringLiteral("scsi"))
+        || controller.startsWith(QStringLiteral("custom"));
+}
+
 static bool parseAccessValue(const QString &value, bool *readOnly)
 {
     if (value.compare(QStringLiteral("ro"), Qt::CaseInsensitive) == 0) {
@@ -280,12 +309,18 @@ QString serializeWinUaeQtHardfile2MountValue(const WinUaeQtMountEntry &entry)
 {
     const QString geometry = entry.hardfileGeometry.isEmpty() ? QStringLiteral("32,1,2,512") : entry.hardfileGeometry;
     const QString tail = entry.hardfileGeometry.isEmpty() && entry.hardfileTail.isEmpty() ? QStringLiteral(",uae0") : entry.hardfileTail;
+    const bool controllerBackedRdb = winUaeQtHardfileIsRdb(entry)
+        && winUaeQtHardfileUsesNonUaeController(entry);
+    const QString device = controllerBackedRdb
+        ? QString()
+        : winUaeQtSanitizedAmigaName(entry.device, QStringLiteral("DH0"), true);
+    const int bootPri = controllerBackedRdb ? 0 : entry.bootPri;
     QString value = QStringLiteral("%1,%2:%3,%4,%5")
         .arg(winUaeQtConfigAccessValue(entry.readOnly),
-             winUaeQtSanitizedAmigaName(entry.device, QStringLiteral("DH0"), true),
+             device,
              winUaeQtConfigEscapeMin(entry.path),
              geometry,
-             QString::number(entry.bootPri));
+             QString::number(bootPri));
     if (!tail.isEmpty()) {
         value += QStringLiteral(",") + tail;
     }
index c0c3f23da3bb88a2d758da6f43c4a86c5024309e..1157f4e18da21a4a216e8a0043d27ee9aafafc33 100644 (file)
@@ -22,6 +22,8 @@ QStringList winUaeQtConfigFieldList(QString value);
 QString winUaeQtConfigJoinFields(const QStringList &fields);
 QString winUaeQtSanitizedAmigaName(QString value, const QString &fallback, bool uppercase);
 QString winUaeQtDefaultVolumeName(const QString &path);
+bool winUaeQtHardfileIsRdb(const WinUaeQtMountEntry &entry);
+bool winUaeQtHardfileUsesNonUaeController(const WinUaeQtMountEntry &entry);
 bool parseWinUaeQtUaehfMountValue(const QString &value, WinUaeQtMountEntry *entry);
 bool parseWinUaeQtFilesystem2MountValue(const QString &value, WinUaeQtMountEntry *entry);
 bool parseWinUaeQtHardfile2MountValue(const QString &value, WinUaeQtMountEntry *entry);
index 504535e5af7671f8d4fad7ec745e85e8d99ce9a2..37ee929dfb8043c1f3dd3a24ca13cb8ad71a8e97 100644 (file)
@@ -77,6 +77,21 @@ static bool testHardfileMount()
     ok = require(parseWinUaeQtHardfile2MountValue(expansionConfig, &expansionEntry), "expansion-controller hardfile did not parse") && ok;
     ok = requireText(expansionEntry.hardfileTail, QStringLiteral(",ide0_ripple,ATA2+"), "expansion-controller hardfile tail") && ok;
     ok = requireText(serializeWinUaeQtHardfile2MountValue(expansionEntry), expansionConfig, "expansion-controller hardfile serialized value") && ok;
+    WinUaeQtMountEntry rdbEntry;
+    const QString rdbConfig = QStringLiteral("rw,:/tmp/a4091.hdf,0,0,0,512,0,,scsi0_a4091");
+    ok = require(parseWinUaeQtHardfile2MountValue(rdbConfig, &rdbEntry),
+        "controller-backed RDB hardfile did not parse") && ok;
+    ok = require(winUaeQtHardfileIsRdb(rdbEntry), "controller-backed hardfile should be RDB") && ok;
+    ok = require(winUaeQtHardfileUsesNonUaeController(rdbEntry),
+        "controller-backed hardfile should use non-UAE controller") && ok;
+    ok = requireText(serializeWinUaeQtHardfile2MountValue(rdbEntry),
+        rdbConfig, "controller-backed RDB hardfile serialized value") && ok;
+    WinUaeQtMountEntry staleRdbEntry;
+    ok = require(parseWinUaeQtHardfile2MountValue(
+        QStringLiteral("rw,SCSI_0:/tmp/a4091.hdf,0,0,0,512,5,,scsi0_a4091"),
+        &staleRdbEntry), "stale controller-backed RDB hardfile did not parse") && ok;
+    ok = requireText(serializeWinUaeQtHardfile2MountValue(staleRdbEntry),
+        rdbConfig, "stale controller-backed RDB hardfile serialized value") && ok;
     return ok;
 }