diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index b1f37c4dc..f87a76fcc 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -71,6 +71,8 @@ add_library(ui STATIC qt_settingsotherperipherals.cpp qt_settingsotherperipherals.hpp qt_settingsotherperipherals.ui + qt_settings_bus_tracking.cpp + qt_settings_bus_tracking.hpp qt_deviceconfig.cpp qt_deviceconfig.hpp diff --git a/src/qt/qt_harddrive_common.hpp b/src/qt/qt_harddrive_common.hpp index 0e0164d54..5d4bbc9e0 100644 --- a/src/qt/qt_harddrive_common.hpp +++ b/src/qt/qt_harddrive_common.hpp @@ -4,10 +4,12 @@ class QString; class QAbstractItemModel; +class SettingsBusTracking; namespace Harddrives { void populateBuses(QAbstractItemModel* model); void populateRemovableBuses(QAbstractItemModel* model); void populateBusChannels(QAbstractItemModel* model, int bus); QString BusChannelName(uint8_t bus, uint8_t channel); + inline SettingsBusTracking* busTrackClass = nullptr; }; diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index 388a843b8..3c8a074db 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -14,6 +14,8 @@ #include "qt_settingsotherperipherals.hpp" #include "qt_progsettings.hpp" +#include "qt_harddrive_common.hpp" +#include "qt_settings_bus_tracking.hpp" extern "C" { @@ -85,6 +87,7 @@ Settings::Settings(QWidget *parent) : ui->listView->setModel(new SettingsModel(this)); + Harddrives::busTrackClass = new SettingsBusTracking; machine = new SettingsMachine(this); display = new SettingsDisplay(this); input = new SettingsInput(this); @@ -124,6 +127,8 @@ Settings::Settings(QWidget *parent) : Settings::~Settings() { delete ui; + delete Harddrives::busTrackClass; + Harddrives::busTrackClass = nullptr; } void Settings::save() { diff --git a/src/qt/qt_settings_bus_tracking.cpp b/src/qt/qt_settings_bus_tracking.cpp new file mode 100644 index 000000000..f6a1c184e --- /dev/null +++ b/src/qt/qt_settings_bus_tracking.cpp @@ -0,0 +1,257 @@ +#include +#include +#include +#include + +#include "86box/hdd.h" +#include "qt_settings_bus_tracking.hpp" + + +SettingsBusTracking::SettingsBusTracking() +{ + int i; + + mfm_tracking = 0x0000000000000000ULL; + esdi_tracking = 0x0000000000000000ULL; + xta_tracking = 0x0000000000000000ULL; + + for (i = 0; i < 8; i++) { + if (i < 4) + ide_tracking[i] = 0x0000000000000000ULL; + + scsi_tracking[i] = 0x0000000000000000ULL; + } +} + + +uint8_t +SettingsBusTracking::next_free_mfm_channel() +{ + if ((mfm_tracking & 0xff00ULL) && !(mfm_tracking & 0x00ffULL)) + return 0; + + if (!(mfm_tracking & 0xff00ULL) && (mfm_tracking & 0x00ffULL)) + return 1; + + return CHANNEL_NONE; +} + + +uint8_t +SettingsBusTracking::next_free_esdi_channel() +{ + if ((esdi_tracking & 0xff00ULL) && !(esdi_tracking & 0x00ffULL)) + return 0; + + if (!(esdi_tracking & 0xff00ULL) && (esdi_tracking & 0x00ffULL)) + return 1; + + return CHANNEL_NONE; +} + + +uint8_t +SettingsBusTracking::next_free_xta_channel() +{ + if ((xta_tracking & 0xff00ULL) && !(xta_tracking & 0x00ffULL)) + return 0; + + if (!(xta_tracking & 0xff00ULL) && (xta_tracking & 0x00ffULL)) + return 1; + + return CHANNEL_NONE; +} + + +uint8_t +SettingsBusTracking::next_free_ide_channel() +{ + int i, element; + uint64_t mask; + uint8_t ret = CHANNEL_NONE; + + for (i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (ide_tracking[element] & mask) { + ret = (uint8_t) i; + break; + } + } + + return ret; +} + + +uint8_t +SettingsBusTracking::next_free_scsi_id() +{ + int i, element; + uint64_t mask; + uint8_t ret = CHANNEL_NONE; + + for (i = 0; i < 64; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (scsi_tracking[element] & mask) { + ret = (uint8_t) i; + break; + } + } + + return ret; +} + + +int +SettingsBusTracking::mfm_bus_full() +{ + int i; + uint64_t mask; + uint8_t count = 0; + + for (i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (mfm_tracking & mask) + count++; + } + + return (count == 2); +} + + +int +SettingsBusTracking::esdi_bus_full() +{ + int i; + uint64_t mask; + uint8_t count = 0; + + for (i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (esdi_tracking & mask) + count++; + } + + return (count == 2); +} + + +int +SettingsBusTracking::xta_bus_full() +{ + int i; + uint64_t mask; + uint8_t count = 0; + + for (i = 0; i < 2; i++) { + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (xta_tracking & mask) + count++; + } + + return (count == 2); +} + + +int +SettingsBusTracking::ide_bus_full() +{ + int i, element; + uint64_t mask; + uint8_t count = 0; + + for (i = 0; i < 32; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (ide_tracking[element] & mask) + count++; + } + + return (count == 32); +} + + +int +SettingsBusTracking::scsi_bus_full() +{ + int i, element; + uint64_t mask; + uint8_t count = 0; + + for (i = 0; i < 64; i++) { + element = ((i << 3) >> 6); + mask = 0xffULL << ((uint64_t) ((i << 3) & 0x3f)); + + if (scsi_tracking[element] & mask) + count++; + } + + return (count == 64); +} + + +void +SettingsBusTracking::device_track(int set, uint8_t dev_type, int bus, int channel) +{ + int i, element; + uint64_t mask; + uint8_t count = 0; + fprintf(stderr, "set: %d, dev_type: %hd, bus: %d, channel: %d\n", set, dev_type, bus, channel); + + switch (bus) { + case HDD_BUS_MFM: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + mfm_tracking |= mask; + else + mfm_tracking &= ~mask; + break; + + case HDD_BUS_ESDI: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + esdi_tracking |= mask; + else + esdi_tracking &= ~mask; + break; + + case HDD_BUS_XTA: + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + xta_tracking |= mask; + else + xta_tracking &= ~mask; + break; + + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + element = ((channel << 3) >> 6); + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + ide_tracking[element] |= mask; + else + ide_tracking[element] &= ~mask; + break; + + case HDD_BUS_SCSI: + element = ((channel << 3) >> 6); + mask = ((uint64_t) dev_type) << ((uint64_t) ((channel << 3) & 0x3f)); + + if (set) + scsi_tracking[element] |= mask; + else + scsi_tracking[element] &= ~mask; + break; + } +} diff --git a/src/qt/qt_settings_bus_tracking.hpp b/src/qt/qt_settings_bus_tracking.hpp new file mode 100644 index 000000000..614e18d8d --- /dev/null +++ b/src/qt/qt_settings_bus_tracking.hpp @@ -0,0 +1,63 @@ +#ifndef QT_SETTINGS_BUS_TRACKING_HPP +#define QT_SETTINGS_BUS_TRACKING_HPP + +#include + +#define TRACK_CLEAR 0 +#define TRACK_SET 1 + +#define DEV_HDD 0x01 +#define DEV_CDROM 0x02 +#define DEV_ZIP 0x04 +#define DEV_MO 0x08 + +#define BUS_MFM 0 +#define BUS_ESDI 1 +#define BUS_XTA 2 +#define BUS_IDE 3 +#define BUS_SCSI 4 + +#define CHANNEL_NONE 0xff + +namespace Ui { +class SettingsBusTracking; +} + +class SettingsBusTracking +{ +public: + explicit SettingsBusTracking(); + ~SettingsBusTracking() = default; + + /* These return 0xff is none is free. */ + uint8_t next_free_mfm_channel(); + uint8_t next_free_esdi_channel(); + uint8_t next_free_xta_channel(); + uint8_t next_free_ide_channel(); + uint8_t next_free_scsi_id(); + + int mfm_bus_full(); + int esdi_bus_full(); + int xta_bus_full(); + int ide_bus_full(); + int scsi_bus_full(); + + /* Set: 0 = Clear the device from the tracking, 1 = Set the device on the tracking. + Device type: 1 = Hard Disk, 2 = CD-ROM, 4 = ZIP, 8 = Magneto-Optical. + Bus: 0 = MFM, 1 = ESDI, 2 = XTA, 3 = IDE, 4 = SCSI. */ + void device_track(int set, uint8_t dev_type, int bus, int channel); + +private: + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t mfm_tracking; + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t esdi_tracking; + /* 1 channel, 2 devices per channel, 8 bits per device = 16 bits. */ + uint64_t xta_tracking; + /* 16 channels (prepatation for that weird IDE card), 2 devices per channel, 8 bits per device = 256 bits. */ + uint64_t ide_tracking[4]; + /* 4 buses, 16 devices per bus, 8 bits per device (future-proofing) = 512 bits. */ + uint64_t scsi_tracking[8]; +}; + +#endif // QT_SETTINGS_BUS_TRACKING_HPP diff --git a/src/qt/qt_settingsharddisks.cpp b/src/qt/qt_settingsharddisks.cpp index 1e9d11350..9c9afaf14 100644 --- a/src/qt/qt_settingsharddisks.cpp +++ b/src/qt/qt_settingsharddisks.cpp @@ -10,6 +10,7 @@ extern "C" { #include "qt_harddiskdialog.hpp" #include "qt_harddrive_common.hpp" +#include "qt_settings_bus_tracking.hpp" #include "qt_progsettings.hpp" const int ColumnBus = 0; @@ -21,6 +22,8 @@ const int ColumnSize = 5; const int DataBus = Qt::UserRole; const int DataBusChannel = Qt::UserRole + 1; +const int DataBusPrevious = Qt::UserRole + 2; +const int DataBusChannelPrevious = Qt::UserRole + 3; /* static void @@ -57,7 +60,10 @@ static void addRow(QAbstractItemModel* model, hard_disk_t* hd) { model->setData(model->index(row, ColumnBus), busName); model->setData(model->index(row, ColumnBus), ProgSettings::loadIcon( "/hard_disk.ico"), Qt::DecorationRole); model->setData(model->index(row, ColumnBus), hd->bus, DataBus); + model->setData(model->index(row, ColumnBus), hd->bus, DataBusPrevious); model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel); + model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannelPrevious); + Harddrives::busTrackClass->device_track(1, DEV_HDD, hd->bus, hd->channel); QString fileName = hd->fn; if (fileName.startsWith(userPath, Qt::CaseInsensitive)) { model->setData(model->index(row, ColumnFilename), fileName.mid(userPath.size())); @@ -132,15 +138,47 @@ void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) { return; } + buschangeinprogress = true; auto idx = ui->tableView->selectionModel()->currentIndex(); if (idx.isValid()) { auto* model = ui->tableView->model(); auto col = idx.siblingAtColumn(ColumnBus); model->setData(col, ui->comboBoxBus->currentData(Qt::UserRole), DataBus); model->setData(col, busChannelName(col), Qt::DisplayRole); + Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBusPrevious).toInt(), model->data(col, DataBusChannelPrevious).toInt()); + model->setData(col, ui->comboBoxBus->currentData(Qt::UserRole), DataBusPrevious); } Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt()); + int chanIdx = 0; + + switch (ui->comboBoxBus->currentData().toInt()) + { + case HDD_BUS_MFM: + chanIdx = (Harddrives::busTrackClass->next_free_mfm_channel()); + break; + case HDD_BUS_XTA: + chanIdx = (Harddrives::busTrackClass->next_free_xta_channel()); + break; + case HDD_BUS_ESDI: + chanIdx = (Harddrives::busTrackClass->next_free_esdi_channel()); + break; + case HDD_BUS_ATAPI: + case HDD_BUS_IDE: + chanIdx = (Harddrives::busTrackClass->next_free_ide_channel()); + break; + case HDD_BUS_SCSI: + chanIdx = (Harddrives::busTrackClass->next_free_scsi_id()); + break; + } + + if (idx.isValid()) { + auto* model = ui->tableView->model(); + auto col = idx.siblingAtColumn(ColumnBus); + model->setData(col, chanIdx, DataBusChannelPrevious); + } + ui->comboBoxChannel->setCurrentIndex(chanIdx); + buschangeinprogress = false; } void SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) { @@ -154,6 +192,9 @@ void SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) { auto col = idx.siblingAtColumn(ColumnBus); model->setData(col, ui->comboBoxChannel->currentData(Qt::UserRole), DataBusChannel); model->setData(col, busChannelName(col), Qt::DisplayRole); + if (!buschangeinprogress) Harddrives::busTrackClass->device_track(0, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannelPrevious).toUInt()); + Harddrives::busTrackClass->device_track(1, DEV_HDD, model->data(col, DataBus).toInt(), model->data(col, DataBusChannel).toUInt()); + model->setData(col, ui->comboBoxChannel->currentData(Qt::UserRole), DataBusChannelPrevious); } } diff --git a/src/qt/qt_settingsharddisks.hpp b/src/qt/qt_settingsharddisks.hpp index 0289d2ccb..b10e79029 100644 --- a/src/qt/qt_settingsharddisks.hpp +++ b/src/qt/qt_settingsharddisks.hpp @@ -30,6 +30,7 @@ private slots: private: Ui::SettingsHarddisks *ui; + bool buschangeinprogress = false; }; #endif // QT_SETTINGSHARDDISKS_HPP