From: Stefan Reinauer Date: Wed, 17 Jun 2026 16:17:38 +0000 (-0700) Subject: od-unix: show controller-backed hardfiles like Windows X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=049151d611bedd9f2364d624d036e0551523681a;p=francis%2Fwinuae.git od-unix: show controller-backed hardfiles like Windows 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. --- diff --git a/od-unix/qt/launcher.cpp b/od-unix/qt/launcher.cpp index 20fb2d6c..8ff794ac 100644 --- a/od-unix/qt/launcher.cpp +++ b/od-unix/qt/launcher.cpp @@ -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::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; } diff --git a/od-unix/qt/mount_config.cpp b/od-unix/qt/mount_config.cpp index 44bdaef7..80b03788 100644 --- a/od-unix/qt/mount_config.cpp +++ b/od-unix/qt/mount_config.cpp @@ -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; } diff --git a/od-unix/qt/mount_config.h b/od-unix/qt/mount_config.h index c0c3f23d..1157f4e1 100644 --- a/od-unix/qt/mount_config.h +++ b/od-unix/qt/mount_config.h @@ -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); diff --git a/od-unix/qt/mount_config_test.cpp b/od-unix/qt/mount_config_test.cpp index 504535e5..37ee929d 100644 --- a/od-unix/qt/mount_config_test.cpp +++ b/od-unix/qt/mount_config_test.cpp @@ -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; }