diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 45c9d1d77..0e1193a69 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -18,7 +18,8 @@ add_library(ui STATIC qt_mainwindow.ui qt_machinestatus.cpp qt_machinestatus.hpp - #qt_machinestatus.ui + qt_mediamenu.cpp + qt_mediamenu.hpp qt_gleswidget.cpp qt_gleswidget.hpp @@ -67,6 +68,9 @@ add_library(ui STATIC qt_filefield.cpp qt_filefield.hpp qt_filefield.ui + qt_newfloppydialog.cpp + qt_newfloppydialog.hpp + qt_newfloppydialog.ui qt_harddiskdialog.cpp qt_harddiskdialog.hpp qt_harddiskdialog.ui diff --git a/src/qt/qt_cdrom.c b/src/qt/qt_cdrom.c index 9eb3d962a..a15e9c600 100644 --- a/src/qt/qt_cdrom.c +++ b/src/qt/qt_cdrom.c @@ -39,83 +39,6 @@ #include <86box/plat.h> #include <86box/ui.h> - - -void -cassette_mount(char *fn, uint8_t wp) -{ - pc_cas_set_fname(cassette, NULL); - memset(cassette_fname, 0, sizeof(cassette_fname)); - cassette_ui_writeprot = wp; - pc_cas_set_fname(cassette, fn); - if (fn != NULL) - memcpy(cassette_fname, fn, MIN(511, strlen(fn))); - ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0); - //media_menu_update_cassette(); - ui_sb_update_tip(SB_CASSETTE); - config_save(); -} - - -void -cassette_eject(void) -{ - pc_cas_set_fname(cassette, NULL); - memset(cassette_fname, 0x00, sizeof(cassette_fname)); - ui_sb_update_icon_state(SB_CASSETTE, 1); - //media_menu_update_cassette(); - ui_sb_update_tip(SB_CASSETTE); - config_save(); -} - - -void -cartridge_mount(uint8_t id, char *fn, uint8_t wp) -{ - cart_close(id); - cart_load(id, fn); - ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1); - //media_menu_update_cartridge(id); - ui_sb_update_tip(SB_CARTRIDGE | id); - config_save(); -} - - -void -cartridge_eject(uint8_t id) -{ - cart_close(id); - ui_sb_update_icon_state(SB_CARTRIDGE | id, 1); - //media_menu_update_cartridge(id); - ui_sb_update_tip(SB_CARTRIDGE | id); - config_save(); -} - - -void -floppy_mount(uint8_t id, char *fn, uint8_t wp) -{ - fdd_close(id); - ui_writeprot[id] = wp; - fdd_load(id, fn); - ui_sb_update_icon_state(SB_FLOPPY | id, strlen(floppyfns[id]) ? 0 : 1); - //media_menu_update_floppy(id); - ui_sb_update_tip(SB_FLOPPY | id); - config_save(); -} - - -void -floppy_eject(uint8_t id) -{ - fdd_close(id); - ui_sb_update_icon_state(SB_FLOPPY | id, 1); - //media_menu_update_floppy(id); - ui_sb_update_tip(SB_FLOPPY | id); - config_save(); -} - - void plat_cdrom_ui_update(uint8_t id, uint8_t reload) { @@ -130,135 +53,3 @@ plat_cdrom_ui_update(uint8_t id, uint8_t reload) //media_menu_update_cdrom(id); ui_sb_update_tip(SB_CDROM|id); } - -void -cdrom_mount(uint8_t id, char *fn) -{ - cdrom[id].prev_host_drive = cdrom[id].host_drive; - strcpy(cdrom[id].prev_image_path, cdrom[id].image_path); - if (cdrom[id].ops && cdrom[id].ops->exit) - cdrom[id].ops->exit(&(cdrom[id])); - cdrom[id].ops = NULL; - memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path)); - cdrom_image_open(&(cdrom[id]), fn); - /* Signal media change to the emulated machine. */ - if (cdrom[id].insert) - cdrom[id].insert(cdrom[id].priv); - cdrom[id].host_drive = (strlen(cdrom[id].image_path) == 0) ? 0 : 200; - if (cdrom[id].host_drive == 200) { - ui_sb_update_icon_state(SB_CDROM | id, 0); - } else { - ui_sb_update_icon_state(SB_CDROM | id, 1); - } - //media_menu_update_cdrom(id); - ui_sb_update_tip(SB_CDROM | id); - config_save(); -} - -void -mo_eject(uint8_t id) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_close(dev); - if (mo_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - mo_insert(dev); - } - - ui_sb_update_icon_state(SB_MO | id, 1); - //media_menu_update_mo(id); - ui_sb_update_tip(SB_MO | id); - config_save(); -} - - -void -mo_mount(uint8_t id, char *fn, uint8_t wp) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_close(dev); - mo_drives[id].read_only = wp; - mo_load(dev, fn); - mo_insert(dev); - - ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1); - //media_menu_update_mo(id); - ui_sb_update_tip(SB_MO | id); - - config_save(); -} - - -void -mo_reload(uint8_t id) -{ - mo_t *dev = (mo_t *) mo_drives[id].priv; - - mo_disk_reload(dev); - if (strlen(mo_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_MO|id, 1); - } else { - ui_sb_update_icon_state(SB_MO|id, 0); - } - - //media_menu_update_mo(id); - ui_sb_update_tip(SB_MO|id); - - config_save(); -} - -void -zip_eject(uint8_t id) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_close(dev); - if (zip_drives[id].bus_type) { - /* Signal disk change to the emulated machine. */ - zip_insert(dev); - } - - ui_sb_update_icon_state(SB_ZIP | id, 1); - //media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP | id); - config_save(); -} - - -void -zip_mount(uint8_t id, char *fn, uint8_t wp) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_close(dev); - zip_drives[id].read_only = wp; - zip_load(dev, fn); - zip_insert(dev); - - ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1); - //media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP | id); - - config_save(); -} - - -void -zip_reload(uint8_t id) -{ - zip_t *dev = (zip_t *) zip_drives[id].priv; - - zip_disk_reload(dev); - if (strlen(zip_drives[id].image_path) == 0) { - ui_sb_update_icon_state(SB_ZIP|id, 1); - } else { - ui_sb_update_icon_state(SB_ZIP|id, 0); - } - - //media_menu_update_zip(id); - ui_sb_update_tip(SB_ZIP|id); - - config_save(); -} diff --git a/src/qt/qt_filefield.cpp b/src/qt/qt_filefield.cpp index 39387fb05..bbc581182 100644 --- a/src/qt/qt_filefield.cpp +++ b/src/qt/qt_filefield.cpp @@ -23,9 +23,9 @@ void FileField::setFileName(const QString &fileName) { void FileField::on_pushButton_clicked() { QString fileName; if (createFile_) { - fileName = QFileDialog::getSaveFileName(this, "Create..."); + fileName = QFileDialog::getSaveFileName(this, "Create...", QString(), filter_, &selectedFilter_); } else { - fileName = QFileDialog::getOpenFileName(this, "Open..."); + fileName = QFileDialog::getOpenFileName(this, "Open...", QString(), filter_, &selectedFilter_); } fileName_ = fileName; diff --git a/src/qt/qt_filefield.hpp b/src/qt/qt_filefield.hpp index 24e3870a3..df68c1e02 100644 --- a/src/qt/qt_filefield.hpp +++ b/src/qt/qt_filefield.hpp @@ -18,6 +18,9 @@ public: QString fileName() const { return fileName_; } void setFileName(const QString& fileName); + void setFilter(const QString& filter) { filter_ = filter; } + QString selectedFilter() const { return selectedFilter_; } + void setCreateFile(bool createFile) { createFile_ = createFile; } signals: @@ -29,6 +32,8 @@ private slots: private: Ui::FileField *ui; QString fileName_; + QString selectedFilter_; + QString filter_; bool createFile_ = false; }; diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index 659c27ea4..8a9cb7c3b 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -337,7 +337,7 @@ void HarddiskDialog::onCreateNewFile() { _86box_geometry = create_drive_vhd_dynamic(fileName, cylinders_, heads_, sectors_, block_size); break; case 5: - QString vhdParent = QFileDialog::getOpenFileName(this, "Select the parent VHD", QString(), "VHD files (*.vhd);;All files (*.*)"); + QString vhdParent = QFileDialog::getOpenFileName(this, "Select the parent VHD", QString(), "VHD files (*.vhd);;All files (*)"); if (vhdParent.isEmpty()) { return; } diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index b2c8d0ad1..a3aad56a4 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -196,6 +196,7 @@ struct MachineStatus::States { std::array hdds; StateActive net; std::unique_ptr sound; + std::unique_ptr text; }; MachineStatus::MachineStatus(QObject *parent) : @@ -206,6 +207,81 @@ MachineStatus::MachineStatus(QObject *parent) : MachineStatus::~MachineStatus() = default; +bool MachineStatus::hasCassette() { + return cassette_enable > 0 ? true : false; +} + +bool MachineStatus::hasCartridge() { + return machines[machine].flags & MACHINE_CARTRIDGE; +} + +bool MachineStatus::hasIDE() { + return machines[machine].flags & MACHINE_IDE_QUAD; +} + +bool MachineStatus::hasSCSI() { + return machines[machine].flags & MACHINE_SCSI_DUAL; +} + +void MachineStatus::iterateFDD(const std::function &cb) { + for (int i = 0; i < FDD_NUM; ++i) { + if (fdd_get_type(i) != 0) { + cb(i); + } + } +} + +void MachineStatus::iterateCDROM(const std::function &cb) { + auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + for (size_t i = 0; i < CDROM_NUM; i++) { + /* Could be Internal or External IDE.. */ + if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && + !hasIDE() && hdc_name != QStringLiteral("ide")) + continue; + if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !hasSCSI() && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + continue; + if (cdrom[i].bus_type != 0) { + cb(i); + } + } +} + +void MachineStatus::iterateZIP(const std::function &cb) { + auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + for (size_t i = 0; i < ZIP_NUM; i++) { + /* Could be Internal or External IDE.. */ + if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && + !hasIDE() && hdc_name != QStringLiteral("ide")) + continue; + if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !hasSCSI() && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + continue; + if (zip_drives[i].bus_type != 0) { + cb(i); + } + } +} + +void MachineStatus::iterateMO(const std::function &cb) { + auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + for (size_t i = 0; i < MO_NUM; i++) { + /* Could be Internal or External IDE.. */ + if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && + !hasIDE() && hdc_name != QStringLiteral("ide")) + continue; + if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !hasSCSI() && + (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && + (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) + continue; + if (mo_drives[i].bus_type != 0) { + cb(i); + } + } +} + static int hdd_count(int bus) { int c = 0; int i; @@ -220,12 +296,9 @@ static int hdd_count(int bus) { } void MachineStatus::refresh(QStatusBar* sbar) { - bool has_cart = machines[machine].flags & MACHINE_CARTRIDGE; bool has_mfm = machines[machine].flags & MACHINE_MFM; bool has_xta = machines[machine].flags & MACHINE_XTA; bool has_esdi = machines[machine].flags & MACHINE_ESDI; - bool has_ide = machines[machine].flags & MACHINE_IDE_QUAD; - bool has_scsi = machines[machine].flags & MACHINE_SCSI_DUAL; int c_mfm = hdd_count(HDD_BUS_MFM); int c_esdi = hdd_count(HDD_BUS_ESDI); @@ -262,7 +335,7 @@ void MachineStatus::refresh(QStatusBar* sbar) { sbar->addWidget(d->cassette.label.get()); } - if (has_cart) { + if (hasCartridge()) { for (int i = 0; i < 2; ++i) { d->cartridge[i].label = std::make_unique(); d->cartridge[i].setEmpty(QString(cart_fns[i]).isEmpty()); @@ -270,73 +343,43 @@ void MachineStatus::refresh(QStatusBar* sbar) { } } - for (size_t i = 0; i < FDD_NUM; ++i) { - if (fdd_get_type(i) != 0) { - d->fdd[i].label = std::make_unique(); - int t = fdd_get_type(i); - if (t == 0) { - d->fdd[i].pixmaps = &d->pixmaps.floppy_disabled; - } else if (t >= 1 && t <= 6) { - d->fdd[i].pixmaps = &d->pixmaps.floppy_525; - } else { - d->fdd[i].pixmaps = &d->pixmaps.floppy_35; - } - d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); - d->fdd[i].setActive(false); - sbar->addWidget(d->fdd[i].label.get()); + iterateFDD([this, sbar](int i) { + int t = fdd_get_type(i); + if (t == 0) { + d->fdd[i].pixmaps = &d->pixmaps.floppy_disabled; + } else if (t >= 1 && t <= 6) { + d->fdd[i].pixmaps = &d->pixmaps.floppy_525; + } else { + d->fdd[i].pixmaps = &d->pixmaps.floppy_35; } - } + d->fdd[i].label = std::make_unique(); + d->fdd[i].setEmpty(QString(floppyfns[i]).isEmpty()); + d->fdd[i].setActive(false); + sbar->addWidget(d->fdd[i].label.get()); + }); + + iterateCDROM([this, sbar](int i) { + d->cdrom[i].label = std::make_unique(); + d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty()); + d->cdrom[i].setActive(false); + sbar->addWidget(d->cdrom[i].label.get()); + }); + + iterateZIP([this, sbar](int i) { + d->zip[i].label = std::make_unique(); + d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); + d->zip[i].setActive(false); + sbar->addWidget(d->zip[i].label.get()); + }); + + iterateMO([this, sbar](int i) { + d->mo[i].label = std::make_unique(); + d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); + d->mo[i].setActive(false); + sbar->addWidget(d->mo[i].label.get()); + }); auto hdc_name = QString(hdc_get_internal_name(hdc_current)); - for (size_t i = 0; i < CDROM_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && - !has_ide && hdc_name != QStringLiteral("ide")) - continue; - if ((cdrom[i].bus_type == CDROM_BUS_SCSI) && !has_scsi && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - continue; - if (cdrom[i].bus_type != 0) { - d->cdrom[i].label = std::make_unique(); - d->cdrom[i].setEmpty(cdrom[i].host_drive != 200 || QString(cdrom[i].image_path).isEmpty()); - d->cdrom[i].setActive(false); - sbar->addWidget(d->cdrom[i].label.get()); - } - } - for (size_t i = 0; i < ZIP_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && - !has_ide && hdc_name != QStringLiteral("ide")) - continue; - if ((zip_drives[i].bus_type == ZIP_BUS_SCSI) && !has_scsi && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - continue; - if (zip_drives[i].bus_type != 0) { - d->zip[i].label = std::make_unique(); - d->zip[i].setEmpty(QString(zip_drives[i].image_path).isEmpty()); - d->zip[i].setActive(false); - sbar->addWidget(d->zip[i].label.get()); - } - } - for (size_t i = 0; i < MO_NUM; i++) { - /* Could be Internal or External IDE.. */ - if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && - !has_ide && hdc_name != QStringLiteral("ide")) - continue; - if ((mo_drives[i].bus_type == MO_BUS_SCSI) && !has_scsi && - (scsi_card_current[0] == 0) && (scsi_card_current[1] == 0) && - (scsi_card_current[2] == 0) && (scsi_card_current[3] == 0)) - continue; - if (mo_drives[i].bus_type != 0) { - d->mo[i].label = std::make_unique(); - d->mo[i].setEmpty(QString(mo_drives[i].image_path).isEmpty()); - d->mo[i].setActive(false); - sbar->addWidget(d->mo[i].label.get()); - } - } - if ((has_mfm || hdc_name == QStringLiteral("st506")) && c_mfm > 0) { d->hdds[HDD_BUS_MFM].label = std::make_unique(); d->hdds[HDD_BUS_MFM].setActive(false); @@ -352,12 +395,12 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->hdds[HDD_BUS_XTA].setActive(false); sbar->addWidget(d->hdds[HDD_BUS_XTA].label.get()); } - if ((has_ide || hdc_name == QStringLiteral("xtide") || hdc_name == QStringLiteral("ide")) && c_ide > 0) { + if ((hasIDE() || hdc_name == QStringLiteral("xtide") || hdc_name == QStringLiteral("ide")) && c_ide > 0) { d->hdds[HDD_BUS_IDE].label = std::make_unique(); d->hdds[HDD_BUS_IDE].setActive(false); sbar->addWidget(d->hdds[HDD_BUS_IDE].label.get()); } - if ((has_scsi || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || + if ((hasSCSI() || (scsi_card_current[0] != 0) || (scsi_card_current[1] != 0) || (scsi_card_current[2] != 0) || (scsi_card_current[3] != 0)) && c_scsi > 0) { d->hdds[HDD_BUS_SCSI].label = std::make_unique(); d->hdds[HDD_BUS_SCSI].setActive(false); @@ -372,6 +415,8 @@ void MachineStatus::refresh(QStatusBar* sbar) { d->sound = std::make_unique(); d->sound->setPixmap(d->pixmaps.sound); sbar->addWidget(d->sound.get()); + d->text = std::make_unique(); + sbar->addWidget(d->text.get()); } void MachineStatus::setActivity(int tag, bool active) { @@ -440,3 +485,7 @@ void MachineStatus::setEmpty(int tag, bool empty) { } } +void MachineStatus::message(const QString &msg) { + d->text->setText(msg); +} + diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index 7ca07255c..ea48178ed 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -13,10 +13,19 @@ public: explicit MachineStatus(QObject *parent = nullptr); ~MachineStatus(); + static bool hasCassette(); + static bool hasCartridge(); + static bool hasIDE(); + static bool hasSCSI(); + static void iterateFDD(const std::function& cb); + static void iterateCDROM(const std::function& cb); + static void iterateZIP(const std::function& cb); + static void iterateMO(const std::function& cb); public slots: void refresh(QStatusBar* sbar); void setActivity(int tag, bool active); void setEmpty(int tag, bool active); + void message(const QString& msg); private: struct States; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 8e5b5a450..f8a80d5fc 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -24,6 +24,7 @@ extern "C" { #include "qt_settings.hpp" #include "qt_gleswidget.hpp" #include "qt_machinestatus.hpp" +#include "qt_mediamenu.hpp" #ifdef __unix__ #include @@ -40,6 +41,8 @@ MainWindow::MainWindow(QWidget *parent) : { Q_INIT_RESOURCE(qt_resources); status = std::make_unique(this); + mm = std::make_shared(this); + MediaMenu::ptr = mm; ui->setupUi(this); video_setblit(qt_blit); @@ -84,12 +87,10 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, &MainWindow::updateStatusBarPanes, this, [this] { status->refresh(ui->statusbar); }); - connect(this, &MainWindow::updateStatusBarActivity, this, [this](int i, bool b) { - status->setActivity(i, b); - }); - connect(this, &MainWindow::updateStatusBarEmpty, this, [this](int i, bool b) { - status->setEmpty(i, b); - }); + connect(this, &MainWindow::updateStatusBarPanes, this, &MainWindow::refreshMediaMenu); + connect(this, &MainWindow::updateStatusBarActivity, status.get(), &MachineStatus::setActivity); + connect(this, &MainWindow::updateStatusBarEmpty, status.get(), &MachineStatus::setEmpty); + connect(this, &MainWindow::statusBarMessage, status.get(), &MachineStatus::message); ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture); ui->actionRight_CTRL_is_left_ALT->setChecked(rctrl_is_lalt); @@ -684,6 +685,10 @@ void MainWindow::getTitle(wchar_t *title) } } +void MainWindow::refreshMediaMenu() { + mm->refresh(ui->menuMedia); +} + void MainWindow::showMessage(const QString& header, const QString& message) { if (QThread::currentThread() == this->thread()) { showMessage_(header, message); diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 3c5055027..816f7f568 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -5,6 +5,10 @@ #include #include +#include + +class MediaMenu; + namespace Ui { class MainWindow; } @@ -27,6 +31,7 @@ signals: void paint(const QImage& image); void resizeContents(int w, int h); void pollMouse(); + void statusBarMessage(const QString& msg); void updateStatusBarPanes(); void updateStatusBarActivity(int tag, bool active); void updateStatusBarEmpty(int tag, bool empty); @@ -48,6 +53,7 @@ private slots: void on_actionRight_CTRL_is_left_ALT_triggered(); void on_actionKeyboard_requires_capture_triggered(); + void refreshMediaMenu(); void showMessage_(const QString& header, const QString& message); void setTitle_(const wchar_t* title); void getTitle_(wchar_t* title); @@ -57,6 +63,7 @@ protected: private: Ui::MainWindow *ui; std::unique_ptr status; + std::shared_ptr mm; }; #endif // QT_MAINWINDOW_HPP diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 9c055ef62..50fc3fa49 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -78,8 +78,14 @@ + + + Media + + + diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp new file mode 100644 index 000000000..6a4406b47 --- /dev/null +++ b/src/qt/qt_mediamenu.cpp @@ -0,0 +1,533 @@ +#include "qt_mediamenu.hpp" + +#include "qt_machinestatus.hpp" + +#include +#include +#include + +extern "C" { +#include <86box/config.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/plat.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> +#include <86box/fdd.h> +#include <86box/fdd_86f.h> +#include <86box/cdrom.h> +#include <86box/scsi_device.h> +#include <86box/zip.h> +#include <86box/mo.h> +#include <86box/sound.h> +#include <86box/ui.h> +}; + +#include "qt_newfloppydialog.hpp" + +std::shared_ptr MediaMenu::ptr; + +MediaMenu::MediaMenu(QWidget* parent) : QObject(parent) { + parentWidget = parent; +} + +void MediaMenu::refresh(QMenu *parentMenu) { + parentMenu->clear(); + + if(MachineStatus::hasCassette()) { + cassetteMenu = parentMenu->addMenu(""); + cassetteMenu->addAction("New Image", [this]() { cassetteNewImage(); }); + cassetteMenu->addSeparator(); + cassetteMenu->addAction("Existing Image", [this]() { cassetteSelectImage(false); }); + cassetteMenu->addAction("Existing Image (Write Protected)", [this]() { cassetteSelectImage(true); }); + cassetteMenu->addSeparator(); + cassetteMenu->addAction("Record")->setCheckable(true); + cassetteMenu->addAction("Play")->setCheckable(true); + cassetteMenu->addAction("Rewing"); + cassetteMenu->addAction("Fast Forward"); + cassetteMenu->addSeparator(); + cassetteMenu->addAction("Eject", [this]() { cassetteEject(); }); + cassetteUpdateMenu(); + } + + cartridgeMenus.clear(); + if (MachineStatus::hasCartridge()) { + for(int i = 0; i < 2; i++) { + auto* menu = parentMenu->addMenu(""); + menu->addAction("Image", [this, i]() { cartridgeSelectImage(i); }); + menu->addSeparator(); + menu->addAction("Eject", [this, i]() { cartridgeEject(i); }); + cartridgeMenus.append(menu); + cartridgeUpdateMenu(i); + } + } + + floppyMenus.clear(); + MachineStatus::iterateFDD([this, parentMenu](int i) { + auto* menu = parentMenu->addMenu(""); + menu->addAction("New Image", [this, i]() { floppyNewImage(i); }); + menu->addSeparator(); + menu->addAction("Existing Image", [this, i]() { floppySelectImage(i, false); }); + menu->addAction("Existing Image (Write Protected)", [this, i]() { floppySelectImage(i, true); }); + menu->addSeparator(); + menu->addAction("Export to 86F", [this, i]() { floppyExportTo86f(i); }); + menu->addSeparator(); + menu->addAction("Eject", [this, i]() { floppyEject(i); }); + floppyMenus.append(menu); + floppyUpdateMenu(i); + }); + + cdromMenus.clear(); + MachineStatus::iterateCDROM([this, parentMenu](int i) { + auto* menu = parentMenu->addMenu(""); + cdromMutePos = menu->children().count(); + menu->addAction("Mute", [this, i]() { cdromMute(i); })->setCheckable(true); + menu->addSeparator(); + cdromEmptyPos = menu->children().count(); + menu->addAction("Empty", [this, i]() { cdromEject(i); })->setCheckable(true); + cdromReloadPos = menu->children().count(); + menu->addAction("Reload previous image", [this, i]() { cdromReload(i); }); + menu->addSeparator(); + cdromImagePos = menu->children().count(); + menu->addAction("Image", [this, i]() { cdromMount(i); })->setCheckable(true); + cdromMenus.append(menu); + cdromUpdateMenu(i); + }); + + zipMenus.clear(); + MachineStatus::iterateZIP([this, parentMenu](int i) { + auto* menu = parentMenu->addMenu(""); + menu->addAction("New Image", [this, i]() { zipNewImage(i); }); + menu->addSeparator(); + menu->addAction("Existing Image", [this, i]() { zipSelectImage(i, false); }); + menu->addAction("Existing Image (Write Protected)", [this, i]() { zipSelectImage(i, true); }); + menu->addSeparator(); + zipEjectPos = menu->children().count(); + menu->addAction("Eject", [this, i]() { zipEject(i); }); + zipReloadPos = menu->children().count(); + menu->addAction("Reload previous image", [this, i]() { zipReload(i); }); + zipMenus.append(menu); + zipUpdateMenu(i); + }); + + moMenus.clear(); + MachineStatus::iterateMO([this, parentMenu](int i) { + auto* menu = parentMenu->addMenu(""); + menu->addAction("New Image", [this, i]() { moNewImage(i); }); + menu->addSeparator(); + menu->addAction("Existing Image", [this, i]() { moSelectImage(i, false); }); + menu->addAction("Existing Image (Write Protected)", [this, i]() { moSelectImage(i, true); }); + menu->addSeparator(); + moEjectPos = menu->children().count(); + menu->addAction("Eject", [this, i]() { moEject(i); }); + moReloadPos = menu->children().count(); + menu->addAction("Reload previous image", [this, i]() { moReload(i); }); + moMenus.append(menu); + moUpdateMenu(i); + }); +} + +void MediaMenu::cassetteNewImage() { + auto filename = QFileDialog::getSaveFileName(parentWidget, "Create..."); + QFileInfo fileinfo(filename); + if (fileinfo.suffix().isEmpty()) { + filename.append(".cas"); + } + cassetteMount(filename, false); +} + +void MediaMenu::cassetteSelectImage(bool wp) { + auto filename = QFileDialog::getOpenFileName(parentWidget, "Open", QString(), "Cassette images (*.pcm;*.raw;*.wav;*.cas);;All files (*)"); + cassetteMount(filename, wp); +} + +void MediaMenu::cassetteMount(const QString& filename, bool wp) { + pc_cas_set_fname(cassette, nullptr); + memset(cassette_fname, 0, sizeof(cassette_fname)); + cassette_ui_writeprot = wp ? 1 : 0; + + if (! filename.isEmpty()) { + QByteArray filenameBytes = filename.toUtf8(); + strncpy(cassette_fname, filenameBytes.data(), sizeof(cassette_fname)); + pc_cas_set_fname(cassette, cassette_fname); + } + + ui_sb_update_icon_state(SB_CASSETTE, filename.isEmpty() ? 1 : 0); + ui_sb_update_tip(SB_CASSETTE); + cassetteUpdateMenu(); + config_save(); +} + +void MediaMenu::cassetteEject() { + pc_cas_set_fname(cassette, nullptr); + memset(cassette_fname, 0, sizeof(cassette_fname)); + ui_sb_update_icon_state(SB_CASSETTE, 1); + ui_sb_update_tip(SB_CASSETTE); + cassetteUpdateMenu(); + config_save(); +} + +void MediaMenu::cassetteUpdateMenu() { + QString name = cassette_fname; + cassetteMenu->setTitle(QString("Cassette: %1").arg(name.isEmpty() ? "(empty)" : name)); +} + +void MediaMenu::cartridgeSelectImage(int i) { + auto filename = QFileDialog::getOpenFileName(parentWidget, "Open", QString(), "Cartridge images (*.a;*.b;*.jrc);;All files (*)"); + if (filename.isEmpty()) { + return; + } + cart_close(i); + QByteArray filenameBytes = filename.toUtf8(); + cart_load(i, filenameBytes.data()); + + ui_sb_update_icon_state(SB_CARTRIDGE | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_tip(SB_CARTRIDGE | i); + cartridgeUpdateMenu(i); + config_save(); +} + +void MediaMenu::cartridgeEject(int i) { + cart_close(i); + ui_sb_update_icon_state(SB_CARTRIDGE | i, 1); + ui_sb_update_tip(SB_CARTRIDGE | i); + cartridgeUpdateMenu(i); + config_save(); +} + +void MediaMenu::cartridgeUpdateMenu(int i) { + QString name = cart_fns[i]; + cartridgeMenus[i]->setTitle(QString("Cartridge %1: %2").arg(QString::number(i+1), name.isEmpty() ? "(empty)" : name)); +} + +void MediaMenu::floppyNewImage(int i) { + NewFloppyDialog dialog(NewFloppyDialog::MediaType::Floppy, parentWidget); + switch (dialog.exec()) { + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + floppyMount(i, filename, false); + break; + } +} + +void MediaMenu::floppySelectImage(int i, bool wp) { + auto filename = QFileDialog::getOpenFileName(parentWidget, "Open", QString(), "All images (*.0??;*.1??;*.??0;*.86F;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.JSON;*.TD0;*.*FD?;*.MFM;*.XDF);;Advanced sector images (*.IMD;*.JSON;*.TD0);;Basic sector images (*.0??;*.1??;*.??0;*.BIN;*.CQ?;*.D??;*.FLP;*.HDM;*.IM?;*.XDF;*.*FD?);;Flux images (*.FDI);;Surface images (*.86F;*.MFM);;All files (*)"); + floppyMount(i, filename, wp); +} + +void MediaMenu::floppyMount(int i, const QString &filename, bool wp) { + fdd_close(i); + ui_writeprot[i] = wp ? 1 : 0; + if (! filename.isEmpty()) { + QByteArray filenameBytes = filename.toUtf8(); + fdd_load(i, filenameBytes.data()); + } + ui_sb_update_icon_state(SB_FLOPPY | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_tip(SB_FLOPPY | i); + floppyUpdateMenu(i); + config_save(); +} + +void MediaMenu::floppyEject(int i) { + fdd_close(i); + ui_sb_update_icon_state(SB_FLOPPY | i, 1); + ui_sb_update_tip(SB_FLOPPY | i); + floppyUpdateMenu(i); + config_save(); +} + +void MediaMenu::floppyExportTo86f(int i) { + auto filename = QFileDialog::getSaveFileName(parentWidget, "Save as 86f", QString(), "Surface images (*.86f)"); + if (! filename.isEmpty()) { + QByteArray filenameBytes = filename.toUtf8(); + plat_pause(1); + if (d86f_export(i, filenameBytes.data()) == 0) { + QMessageBox::critical(parentWidget, "Unable to write file", "Make sure the file is being saved to a writable directory"); + } + plat_pause(0); + } +} + +void MediaMenu::floppyUpdateMenu(int i) { + QString name = floppyfns[i]; + int type = fdd_get_type(i); + floppyMenus[i]->setTitle(QString("Floppy %1 (%2): %3").arg(QString::number(i+1), fdd_getname(type), name.isEmpty() ? "(empty)" : name)); +} + +void MediaMenu::cdromMute(int i) { + cdrom[i].sound_on ^= 1; + config_save(); + cdromUpdateMenu(i); + sound_cd_thread_reset(); +} + +void MediaMenu::cdromMount(int i) { + QString dir; + QFileInfo fi(cdrom[i].image_path); + + auto filename = QFileDialog::getOpenFileName(parentWidget, "CD-ROM images (*.ISO;*.CUE)\0*.ISO;*.CUE\0All files (*.*)\0*.*\0", fi.canonicalPath()); + if (filename.isEmpty()) { + auto* imageMenu = dynamic_cast(cdromMenus[i]->children()[cdromImagePos]); + imageMenu->setChecked(false); + return; + } + QByteArray fn = filename.toUtf8().data(); + + cdrom[i].prev_host_drive = cdrom[i].host_drive; + strcpy(cdrom[i].prev_image_path, cdrom[i].image_path); + if (cdrom[i].ops && cdrom[i].ops->exit) + cdrom[i].ops->exit(&(cdrom[i])); + + cdrom[i].ops = nullptr; + memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path)); + cdrom_image_open(&(cdrom[i]), fn.data()); + /* Signal media change to the emulated machine. */ + if (cdrom[i].insert) + cdrom[i].insert(cdrom[i].priv); + cdrom[i].host_drive = (strlen(cdrom[i].image_path) == 0) ? 0 : 200; + if (cdrom[i].host_drive == 200) { + ui_sb_update_icon_state(SB_CDROM | i, 0); + } else { + ui_sb_update_icon_state(SB_CDROM | i, 1); + } + ui_sb_update_tip(SB_CDROM | i); + cdromUpdateMenu(i); + config_save(); +} + +void MediaMenu::cdromEject(int i) { + cdrom_eject(i); + cdromUpdateMenu(i); +} + +void MediaMenu::cdromReload(int i) { + cdrom_reload(i); + cdromUpdateMenu(i); +} + +void MediaMenu::cdromUpdateMenu(int i) { + QString name = cdrom[i].image_path; + auto* menu = cdromMenus[i]; + auto childs = menu->children(); + + auto* muteMenu = dynamic_cast(childs[cdromMutePos]); + muteMenu->setChecked(cdrom[i].sound_on == 0); + + auto* imageMenu = dynamic_cast(childs[cdromImagePos]); + auto* emptyMenu = dynamic_cast(childs[cdromEmptyPos]); + imageMenu->setChecked(cdrom[i].host_drive == 200); + emptyMenu->setChecked(cdrom[i].host_drive != 200); + + auto* prevMenu = dynamic_cast(childs[cdromReloadPos]); + prevMenu->setEnabled(cdrom[i].prev_host_drive != 0); + + QString busName = "Unknown Bus"; + switch (cdrom[i].bus_type) { + case CDROM_BUS_ATAPI: + busName = "ATAPI"; + break; + case CDROM_BUS_SCSI: + busName = "SCSI"; + break; + } + + menu->setTitle(QString("CD-ROM %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? "(empty)" : name)); +} + +void MediaMenu::zipNewImage(int i) { + NewFloppyDialog dialog(NewFloppyDialog::MediaType::Zip, parentWidget); + switch (dialog.exec()) { + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + zipMount(i, filename, false); + break; + } +} + +void MediaMenu::zipSelectImage(int i, bool wp) { + auto filename = QFileDialog::getOpenFileName(parentWidget, "Open", QString(), "ZIP images (*.im?;*.zdi);;All files (*)"); + zipMount(i, filename, wp); +} + +void MediaMenu::zipMount(int i, const QString &filename, bool wp) { + zip_t *dev = (zip_t *) zip_drives[i].priv; + + zip_disk_close(dev); + zip_drives[i].read_only = wp; + if (! filename.isEmpty()) { + QByteArray filenameBytes = filename.toUtf8(); + zip_load(dev, filenameBytes.data()); + zip_insert(dev); + } + + ui_sb_update_icon_state(SB_ZIP | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_tip(SB_ZIP | i); + zipUpdateMenu(i); + + config_save(); +} + +void MediaMenu::zipEject(int i) { + zip_t *dev = (zip_t *) zip_drives[i].priv; + + zip_disk_close(dev); + if (zip_drives[i].bus_type) { + /* Signal disk change to the emulated machine. */ + zip_insert(dev); + } + + ui_sb_update_icon_state(SB_ZIP | i, 1); + ui_sb_update_tip(SB_ZIP | i); + zipUpdateMenu(i); + config_save(); +} + +void MediaMenu::zipReload(int i) { + zip_t *dev = (zip_t *) zip_drives[i].priv; + + zip_disk_reload(dev); + if (strlen(zip_drives[i].image_path) == 0) { + ui_sb_update_icon_state(SB_ZIP|i, 1); + } else { + ui_sb_update_icon_state(SB_ZIP|i, 0); + } + + ui_sb_update_tip(SB_ZIP|i); + zipUpdateMenu(i); + + config_save(); +} + +void MediaMenu::zipUpdateMenu(int i) { + QString name = zip_drives[i].image_path; + QString prev_name = zip_drives[i].prev_image_path; + auto* menu = zipMenus[i]; + auto childs = menu->children(); + + auto* ejectMenu = dynamic_cast(childs[zipEjectPos]); + auto* reloadMenu = dynamic_cast(childs[zipReloadPos]); + ejectMenu->setEnabled(!name.isEmpty()); + reloadMenu->setEnabled(!prev_name.isEmpty()); + + QString busName = "Unknown Bus"; + switch (zip_drives[i].bus_type) { + case ZIP_BUS_ATAPI: + busName = "ATAPI"; + break; + case ZIP_BUS_SCSI: + busName = "SCSI"; + break; + } + + menu->setTitle(QString("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? "250" : "100", QString::number(i+1), busName, name.isEmpty() ? "(empty)" : name)); +} + +void MediaMenu::moNewImage(int i) { + NewFloppyDialog dialog(NewFloppyDialog::MediaType::Mo, parentWidget); + switch (dialog.exec()) { + case QDialog::Accepted: + QByteArray filename = dialog.fileName().toUtf8(); + moMount(i, filename, false); + break; + } +} + +void MediaMenu::moSelectImage(int i, bool wp) { + auto filename = QFileDialog::getOpenFileName(parentWidget, "Open", QString(), "MO images (*.im?;*.mdi);;All files (*)"); + moMount(i, filename, wp); +} + +void MediaMenu::moMount(int i, const QString &filename, bool wp) { + mo_t *dev = (mo_t *) mo_drives[i].priv; + + mo_disk_close(dev); + mo_drives[i].read_only = wp; + if (! filename.isEmpty()) { + QByteArray filenameBytes = filename.toUtf8(); + mo_load(dev, filenameBytes.data()); + mo_insert(dev); + } + + ui_sb_update_icon_state(SB_MO | i, filename.isEmpty() ? 1 : 0); + ui_sb_update_tip(SB_MO | i); + moUpdateMenu(i); + + config_save(); +} + +void MediaMenu::moEject(int i) { + mo_t *dev = (mo_t *) mo_drives[i].priv; + + mo_disk_close(dev); + if (mo_drives[i].bus_type) { + /* Signal disk change to the emulated machine. */ + mo_insert(dev); + } + + ui_sb_update_icon_state(SB_MO | i, 1); + ui_sb_update_tip(SB_MO | i); + moUpdateMenu(i); + config_save(); +} + +void MediaMenu::moReload(int i) { + mo_t *dev = (mo_t *) mo_drives[i].priv; + + mo_disk_reload(dev); + if (strlen(mo_drives[i].image_path) == 0) { + ui_sb_update_icon_state(SB_MO|i, 1); + } else { + ui_sb_update_icon_state(SB_MO|i, 0); + } + + ui_sb_update_tip(SB_MO|i); + moUpdateMenu(i); + + config_save(); +} + +void MediaMenu::moUpdateMenu(int i) { + QString name = mo_drives[i].image_path; + QString prev_name = mo_drives[i].prev_image_path; + auto* menu = moMenus[i]; + auto childs = menu->children(); + + auto* ejectMenu = dynamic_cast(childs[moEjectPos]); + auto* reloadMenu = dynamic_cast(childs[moReloadPos]); + ejectMenu->setEnabled(!name.isEmpty()); + reloadMenu->setEnabled(!prev_name.isEmpty()); + + QString busName = "Unknown Bus"; + switch (mo_drives[i].bus_type) { + case MO_BUS_ATAPI: + busName = "ATAPI"; + break; + case MO_BUS_SCSI: + busName = "SCSI"; + break; + } + + menu->setTitle(QString("MO %1 (%2): %3").arg(QString::number(i+1), busName, name.isEmpty() ? "(empty)" : name)); +} + + +// callbacks from 86box C code +extern "C" { + +void zip_eject(uint8_t id) { + MediaMenu::ptr->zipEject(id); +} + +void zip_reload(uint8_t id) { + MediaMenu::ptr->zipReload(id); +} + +void mo_eject(uint8_t id) { + MediaMenu::ptr->moEject(id); +} + +void mo_reload(uint8_t id) { + MediaMenu::ptr->moReload(id); +} + +} diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp new file mode 100644 index 000000000..7a21f288c --- /dev/null +++ b/src/qt/qt_mediamenu.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +class QMenu; + +class MediaMenu : QObject +{ + Q_OBJECT +public: + MediaMenu(QWidget* parent); + + void refresh(QMenu* parentMenu); + + // because some 86box C-only code needs to call zip and + // mo eject directly + static std::shared_ptr ptr; + + void cassetteNewImage(); + void cassetteSelectImage(bool wp); + void cassetteMount(const QString& filename, bool wp); + void cassetteEject(); + void cassetteUpdateMenu(); + + void cartridgeSelectImage(int i); + void cartridgeEject(int i); + void cartridgeUpdateMenu(int i); + + void floppyNewImage(int i); + void floppySelectImage(int i, bool wp); + void floppyMount(int i, const QString& filename, bool wp); + void floppyEject(int i); + void floppyExportTo86f(int i); + void floppyUpdateMenu(int i); + + void cdromMute(int i); + void cdromMount(int i); + void cdromEject(int i); + void cdromReload(int i); + void cdromUpdateMenu(int i); + + void zipNewImage(int i); + void zipSelectImage(int i, bool wp); + void zipMount(int i, const QString& filename, bool wp); + void zipEject(int i); + void zipReload(int i); + void zipUpdateMenu(int i); + + void moNewImage(int i); + void moSelectImage(int i, bool wp); + void moMount(int i, const QString& filename, bool wp); + void moEject(int i); + void moReload(int i); + void moUpdateMenu(int i); +private: + QWidget* parentWidget = nullptr; + + QMenu* cassetteMenu = nullptr; + QList cartridgeMenus; + QList floppyMenus; + QList cdromMenus; + QList zipMenus; + QList moMenus; + + int cdromMutePos; + int cdromEmptyPos; + int cdromReloadPos; + int cdromImagePos; + + int zipEjectPos; + int zipReloadPos; + + int moEjectPos; + int moReloadPos; +}; diff --git a/src/qt/qt_newfloppydialog.cpp b/src/qt/qt_newfloppydialog.cpp new file mode 100644 index 000000000..2ffd95950 --- /dev/null +++ b/src/qt/qt_newfloppydialog.cpp @@ -0,0 +1,648 @@ +#include "qt_newfloppydialog.hpp" +#include "ui_qt_newfloppydialog.h" + +#include "qt_models_common.hpp" + +extern "C" { +#include <86box/random.h> +#include <86box/scsi_device.h> +#include <86box/zip.h> +#include <86box/mo.h> +} + +#include +#include +#include +#include +#include + +struct disk_size_t { + int hole; + int sides; + int data_rate; + int encoding; + int rpm; + int tracks; + int sectors; /* For IMG and Japanese FDI only. */ + int sector_len; /* For IMG and Japanese FDI only. */ + int media_desc; + int spc; + int num_fats; + int spfat; + int root_dir_entries; +}; + +static const disk_size_t disk_sizes[14] = { { 0, 1, 2, 1, 0, 40, 8, 2, 0xfe, 2, 2, 1, 64 }, /* 160k */ + { 0, 1, 2, 1, 0, 40, 9, 2, 0xfc, 2, 2, 1, 64 }, /* 180k */ + { 0, 2, 2, 1, 0, 40, 8, 2, 0xff, 2, 2, 1, 112 }, /* 320k */ + { 0, 2, 2, 1, 0, 40, 9, 2, 0xfd, 2, 2, 2, 112 }, /* 360k */ + { 0, 2, 2, 1, 0, 80, 8, 2, 0xfb, 2, 2, 2, 112 }, /* 640k */ + { 0, 2, 2, 1, 0, 80, 9, 2, 0xf9, 2, 2, 3, 112 }, /* 720k */ + { 1, 2, 0, 1, 1, 80, 15, 2, 0xf9, 1, 2, 7, 224 }, /* 1.2M */ + { 1, 2, 0, 1, 1, 77, 8, 3, 0xfe, 1, 2, 2, 192 }, /* 1.25M */ + { 1, 2, 0, 1, 0, 80, 18, 2, 0xf0, 1, 2, 9, 224 }, /* 1.44M */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 2, 2, 5, 16 }, /* DMF cluster 1024 */ + { 1, 2, 0, 1, 0, 80, 21, 2, 0xf0, 4, 2, 3, 16 }, /* DMF cluster 2048 */ + { 2, 2, 3, 1, 0, 80, 36, 2, 0xf0, 2, 2, 9, 240 }, /* 2.88M */ + { 0, 64, 0, 0, 0, 96, 32, 2, 0, 0, 0, 0, 0 }, /* ZIP 100 */ + { 0, 64, 0, 0, 0, 239, 32, 2, 0, 0, 0, 0, 0 } }; /* ZIP 250 */ + +static const QStringList rpmModes = { + "Perfect RPM", + "1%% below perfect RPM", + "1.5%% below perfect RPM", + "2%% below perfect RPM", +}; + +static const QStringList floppyTypes = { + "160 kB", + "180 kB", + "320 kB", + "360 kB", + "640 kB", + "720 kB", + "1.2 MB", + "1.25 MB", + "1.44 MB", + "DMF (cluster 1024)", + "DMF (cluster 2048)", + "2.88 MB", +}; + +static const QStringList zipTypes = { + "ZIP 100", + "ZIP 250", +}; + +static const QStringList moTypes = { + "3.5\" 128Mb M.O. (ISO 10090)", + "3.5\" 230Mb M.O. (ISO 13963)", + "3.5\" 540Mb M.O. (ISO 15498)", + "3.5\" 640Mb M.O. (ISO 15498)", + "3.5\" 1.3Gb M.O. (GigaMO)", + "3.5\" 2.3Gb M.O. (GigaMO 2)", + "5.25\" 600Mb M.O.", + "5.25\" 650Mb M.O.", + "5.25\" 1Gb M.O.", + "5.25\" 1.3Gb M.O.", +}; + +NewFloppyDialog::NewFloppyDialog(MediaType type, QWidget *parent) : + QDialog(parent), + ui(new Ui::NewFloppyDialog), + mediaType_(type) +{ + ui->setupUi(this); + ui->fileField->setCreateFile(true); + + auto* model = ui->comboBoxSize->model(); + switch (type) { + case MediaType::Floppy: + for (int i = 0; i < floppyTypes.size(); ++i) { + Models::AddEntry(model, floppyTypes[i], i); + } + break; + case MediaType::Zip: + for (int i = 0; i < zipTypes.size(); ++i) { + Models::AddEntry(model, zipTypes[i], i); + } + break; + case MediaType::Mo: + for (int i = 0; i < moTypes.size(); ++i) { + Models::AddEntry(model, moTypes[i], i); + } + break; + } + + model = ui->comboBoxRpm->model(); + for (int i = 0; i < rpmModes.size(); ++i) { + Models::AddEntry(model, rpmModes[i], i); + } + + connect(ui->fileField, &FileField::fileSelected, this, [this](const QString& filename) { + bool hide = true; + if (mediaType_ == MediaType::Floppy) { + if (QFileInfo(filename).suffix().toLower() == QStringLiteral("86f")) { + hide = false; + } + } + + ui->labelRpm->setHidden(hide); + ui->comboBoxRpm->setHidden(hide); + }); + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &NewFloppyDialog::onCreate); + + ui->labelRpm->setHidden(true); + ui->comboBoxRpm->setHidden(true); +} + +NewFloppyDialog::~NewFloppyDialog() { + delete ui; +} + +QString NewFloppyDialog::fileName() const{ + return ui->fileField->fileName(); +} + +void NewFloppyDialog::onCreate() { + auto filename = ui->fileField->fileName(); + QFileInfo fi(filename); + FileType fileType; + + QProgressDialog progress("Creating floppy image", QString(), 0, 100, this); + connect(this, &NewFloppyDialog::fileProgress, &progress, &QProgressDialog::setValue); + switch (mediaType_) { + case MediaType::Floppy: + if (fi.suffix().toLower() == QStringLiteral("86f")) { + if (create86f(filename, disk_sizes[ui->comboBoxSize->currentIndex()], ui->comboBoxRpm->currentIndex())) { + return; + } + } else { + fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Fdi : FileType::Img; + if (createSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex()], fileType)) { + return; + } + } + break; + case MediaType::Zip: + { + fileType = fi.suffix().toLower() == QStringLiteral("zdi") ? FileType::Zdi: FileType::Img; + + std::atomic_bool res; + std::thread t([this, &res, filename, fileType, &progress] { + res = createZipSectorImage(filename, disk_sizes[ui->comboBoxSize->currentIndex() + 12], fileType, progress); + }); + progress.exec(); + t.join(); + + if (res) { + return; + } + } + break; + case MediaType::Mo: + { + fileType = fi.suffix().toLower() == QStringLiteral("mdi") ? FileType::Mdi: FileType::Img; + + std::atomic_bool res; + std::thread t([this, &res, filename, fileType, &progress] { + res = createMoSectorImage(filename, ui->comboBoxSize->currentIndex(), fileType, progress); + }); + progress.exec(); + t.join(); + + if (res) { + return; + } + } + break; + } + + QMessageBox::critical(this, "Unable to write file", "Make sure the file is being saved to a writable directory"); + reject(); +} + +bool NewFloppyDialog::create86f(const QString& filename, const disk_size_t& disk_size, uint8_t rpm_mode) +{ + uint32_t magic = 0x46423638; + uint16_t version = 0x020C; + uint16_t dflags = 0; + uint16_t tflags = 0; + uint32_t index_hole_pos = 0; + uint32_t tarray[512]; + uint32_t array_size; + uint32_t track_base, track_size; + int i; + uint32_t shift = 0; + + dflags = 0; /* Has surface data? - Assume no for now. */ + dflags |= (disk_size.hole << 1); /* Hole */ + dflags |= ((disk_size.sides - 1) << 3); /* Sides. */ + dflags |= (0 << 4); /* Write protect? - Assume no for now. */ + dflags |= (rpm_mode << 5); /* RPM mode. */ + dflags |= (0 << 7); /* Has extra bit cells? - Assume no for now. */ + + tflags = disk_size.data_rate; /* Data rate. */ + tflags |= (disk_size.encoding << 3); /* Encoding. */ + tflags |= (disk_size.rpm << 5); /* RPM. */ + + switch (disk_size.hole) { + case 0: + case 1: + default: + switch(rpm_mode) { + case 1: + array_size = 25250; + break; + case 2: + array_size = 25374; + break; + case 3: + array_size = 25750; + break; + default: + array_size = 25000; + break; + } + break; + case 2: + switch(rpm_mode) { + case 1: + array_size = 50500; + break; + case 2: + array_size = 50750; + break; + case 3: + array_size = 51000; + break; + default: + array_size = 50000; + break; + } + break; + } + + QByteArray bytes(array_size, 0); + memset(tarray, 0, 2048); + + QFile file(filename); + if (! file.open(QIODevice::WriteOnly)) { + return false; + } + QDataStream stream(&file); + + stream << magic; + stream << version; + stream << dflags; + + track_size = array_size + 6; + track_base = 8 + ((disk_size.sides == 2) ? 2048 : 1024); + + if (disk_size.tracks <= 43) + shift = 1; + + for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) + tarray[i] = track_base + (i * track_size); + + stream.writeRawData(reinterpret_cast(tarray), (disk_size.sides == 2) ? 2048 : 1024); + + int max = i < (disk_size.tracks * disk_size.sides) << shift; + for (i = 0; i < max; i++) { + stream << tflags; + stream << index_hole_pos; + stream.writeRawData(bytes, bytes.size()); + } + + return true; +} + +bool NewFloppyDialog::createSectorImage(const QString &filename, const disk_size_t& disk_size, FileType type) +{ + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint32_t root_dir_bytes = 0; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; + + QFile file(filename); + if (! file.open(QIODevice::WriteOnly)) { + return false; + } + QDataStream stream(&file); + + sector_bytes = (128 << disk_size.sector_len); + total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; + if (total_sectors > ZIP_SECTORS) + total_sectors = ZIP_250_SECTORS; + total_size = total_sectors * sector_bytes; + root_dir_bytes = (disk_size.root_dir_entries << 5); + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; + + if (type == FileType::Fdi) { + QByteArray bytes(base, 0); + auto empty = bytes.data(); + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + stream.writeRawData(empty, base); + } + + QByteArray bytes(total_size, 0); + auto empty = bytes.data(); + + memset(empty + zero_bytes, 0xF6, total_size - zero_bytes); + + empty[0x00] = 0xEB; /* Jump to make MS-DOS happy. */ + empty[0x01] = 0x58; + empty[0x02] = 0x90; + + empty[0x03] = 0x38; /* '86BOX5.0' OEM ID. */ + empty[0x04] = 0x36; + empty[0x05] = 0x42; + empty[0x06] = 0x4F; + empty[0x07] = 0x58; + empty[0x08] = 0x35; + empty[0x09] = 0x2E; + empty[0x0A] = 0x30; + + *(uint16_t *) &(empty[0x0B]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x0D]) = (uint8_t) disk_size.spc; + *(uint16_t *) &(empty[0x0E]) = (uint16_t) 1; + *(uint8_t *) &(empty[0x10]) = (uint8_t) disk_size.num_fats; + *(uint16_t *) &(empty[0x11]) = (uint16_t) disk_size.root_dir_entries; + *(uint16_t *) &(empty[0x13]) = (uint16_t) total_sectors; + *(uint8_t *) &(empty[0x15]) = (uint8_t) disk_size.media_desc; + *(uint16_t *) &(empty[0x16]) = (uint16_t) disk_size.spfat; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x1A]) = (uint8_t) disk_size.sides; + + empty[0x26] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x27] = random_generate(); + empty[0x28] = random_generate(); + empty[0x29] = random_generate(); + empty[0x2A] = random_generate(); + + memset(&(empty[0x2B]), 0x20, 11); + + empty[0x36] = 'F'; + empty[0x37] = 'A'; + empty[0x38] = 'T'; + empty[0x39] = '1'; + empty[0x3A] = '2'; + memset(&(empty[0x3B]), 0x20, 0x0003); + + empty[0x1FE] = 0x55; + empty[0x1FF] = 0xAA; + + empty[fat1_offs + 0x00] = empty[fat2_offs + 0x00] = empty[0x15]; + empty[fat1_offs + 0x01] = empty[fat2_offs + 0x01] = 0xFF; + empty[fat1_offs + 0x02] = empty[fat2_offs + 0x02] = 0xFF; + + stream.writeRawData(empty, total_size); + return true; +} + +bool NewFloppyDialog::createZipSectorImage(const QString &filename, const disk_size_t& disk_size, FileType type, QProgressDialog& pbar) +{ + uint32_t total_size = 0; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint32_t root_dir_bytes = 0; + uint32_t fat_size = 0; + uint32_t fat1_offs = 0; + uint32_t fat2_offs = 0; + uint32_t zero_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0; + + QFile file(filename); + if (! file.open(QIODevice::WriteOnly)) { + return false; + } + QDataStream stream(&file); + + sector_bytes = (128 << disk_size.sector_len); + total_sectors = disk_size.sides * disk_size.tracks * disk_size.sectors; + if (total_sectors > ZIP_SECTORS) + total_sectors = ZIP_250_SECTORS; + total_size = total_sectors * sector_bytes; + root_dir_bytes = (disk_size.root_dir_entries << 5); + fat_size = (disk_size.spfat * sector_bytes); + fat1_offs = sector_bytes; + fat2_offs = fat1_offs + fat_size; + zero_bytes = fat2_offs + fat_size + root_dir_bytes; + + pbar_max = total_size; + if (type == FileType::Zdi) { + pbar_max += base; + } + pbar_max >>= 11; + + if (type == FileType::Zdi) { + QByteArray data(base, 0); + auto empty = data.data(); + + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) disk_size.sectors; + *(uint8_t *) &(empty[0x18]) = (uint8_t) disk_size.sides; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) disk_size.tracks; + + stream.writeRawData(empty, base); + pbar_max -= 2; + } + + QByteArray bytes(total_size, 0); + auto empty = bytes.data(); + + if (total_sectors == ZIP_SECTORS) { + /* ZIP 100 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; + *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; + *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E90644LL; + *(uint64_t *) &(empty[0x01B6]) = 0xED08BBE5014E0135LL; + *(uint64_t *) &(empty[0x01BE]) = 0xFFFFFE06FFFFFE80LL; + *(uint64_t *) &(empty[0x01C6]) = 0x0002FFE000000020LL; + + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + + /* 31 sectors filled with 0x48 */ + memset(&(empty[0x0200]), 0x48, 0x3E00); + + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0008040200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00C0F80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000FF003FLL; + *(uint32_t *) &(empty[0x4020]) = 0x0002FFE0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; + + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); + + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); + + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + memset(&(empty[0x403B]), 0x20, 0x0003); + + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; + + empty[0x5000] = empty[0x1D000] = empty[0x4015]; + empty[0x5001] = empty[0x1D001] = 0xFF; + empty[0x5002] = empty[0x1D002] = 0xFF; + empty[0x5003] = empty[0x1D003] = 0xFF; + + /* Root directory = 0x35000 + Data = 0x39000 */ + } else { + /* ZIP 250 */ + /* MBR */ + *(uint64_t *) &(empty[0x0000]) = 0x2054524150492EEBLL; + *(uint64_t *) &(empty[0x0008]) = 0x3930302065646F63LL; + *(uint64_t *) &(empty[0x0010]) = 0x67656D6F49202D20LL; + *(uint64_t *) &(empty[0x0018]) = 0x726F70726F432061LL; + *(uint64_t *) &(empty[0x0020]) = 0x202D206E6F697461LL; + *(uint64_t *) &(empty[0x0028]) = 0x30392F33322F3131LL; + + *(uint64_t *) &(empty[0x01AE]) = 0x0116010100E900E9LL; + *(uint64_t *) &(empty[0x01B6]) = 0x2E32A7AC014E0135LL; + + *(uint64_t *) &(empty[0x01EE]) = 0xEE203F0600010180LL; + *(uint64_t *) &(empty[0x01F6]) = 0x000777E000000020LL; + *(uint16_t *) &(empty[0x01FE]) = 0xAA55; + + /* 31 sectors filled with 0x48 */ + memset(&(empty[0x0200]), 0x48, 0x3E00); + + /* The second sector begins with some strange data + in my reference image. */ + *(uint64_t *) &(empty[0x0200]) = 0x3831393230334409LL; + *(uint64_t *) &(empty[0x0208]) = 0x6A57766964483130LL; + *(uint64_t *) &(empty[0x0210]) = 0x3C3A34676063653FLL; + *(uint64_t *) &(empty[0x0218]) = 0x586A56A8502C4161LL; + *(uint64_t *) &(empty[0x0220]) = 0x6F2D702535673D6CLL; + *(uint64_t *) &(empty[0x0228]) = 0x255421B8602D3456LL; + *(uint64_t *) &(empty[0x0230]) = 0x577B22447B52603ELL; + *(uint64_t *) &(empty[0x0238]) = 0x46412CC871396170LL; + *(uint64_t *) &(empty[0x0240]) = 0x704F55237C5E2626LL; + *(uint64_t *) &(empty[0x0248]) = 0x6C7932C87D5C3C20LL; + *(uint64_t *) &(empty[0x0250]) = 0x2C50503E47543D6ELL; + *(uint64_t *) &(empty[0x0258]) = 0x46394E807721536ALL; + *(uint64_t *) &(empty[0x0260]) = 0x505823223F245325LL; + *(uint64_t *) &(empty[0x0268]) = 0x365C79B0393B5B6ELL; + + /* Boot sector */ + *(uint64_t *) &(empty[0x4000]) = 0x584F4236389058EBLL; + *(uint64_t *) &(empty[0x4008]) = 0x0001080200302E35LL; + *(uint64_t *) &(empty[0x4010]) = 0x00EFF80000020002LL; + *(uint64_t *) &(empty[0x4018]) = 0x0000002000400020LL; + *(uint32_t *) &(empty[0x4020]) = 0x000777E0; + *(uint16_t *) &(empty[0x4024]) = 0x0080; + + empty[0x4026] = 0x29; /* ')' followed by randomly-generated volume serial number. */ + empty[0x4027] = random_generate(); + empty[0x4028] = random_generate(); + empty[0x4029] = random_generate(); + empty[0x402A] = random_generate(); + + memset(&(empty[0x402B]), 0x00, 0x000B); + memset(&(empty[0x4036]), 0x20, 0x0008); + + empty[0x4036] = 'F'; + empty[0x4037] = 'A'; + empty[0x4038] = 'T'; + empty[0x4039] = '1'; + empty[0x403A] = '6'; + memset(&(empty[0x403B]), 0x20, 0x0003); + + empty[0x41FE] = 0x55; + empty[0x41FF] = 0xAA; + + empty[0x4200] = empty[0x22000] = empty[0x4015]; + empty[0x4201] = empty[0x22001] = 0xFF; + empty[0x4202] = empty[0x22002] = 0xFF; + empty[0x4203] = empty[0x22003] = 0xFF; + + /* Root directory = 0x3FE00 + Data = 0x38200 */ + } + + pbar.setMaximum(pbar_max); + for (uint32_t i = 0; i < pbar_max; i++) { + stream.writeRawData(&empty[i << 11], 2048); + fileProgress(i); + } + fileProgress(pbar_max); + + return true; +} + + +bool NewFloppyDialog::createMoSectorImage(const QString& filename, int8_t disk_size, FileType type, QProgressDialog& pbar) +{ + const mo_type_t *dp = &mo_types[disk_size]; + uint32_t total_size = 0, total_size2; + uint32_t total_sectors = 0; + uint32_t sector_bytes = 0; + uint16_t base = 0x1000; + uint32_t pbar_max = 0, blocks_num; + + QFile file(filename); + if (! file.open(QIODevice::WriteOnly)) { + return false; + } + QDataStream stream(&file); + + sector_bytes = dp->bytes_per_sector; + total_sectors = dp->sectors; + total_size = total_sectors * sector_bytes; + + total_size2 = (total_size >> 20) << 20; + total_size2 = total_size - total_size2; + + pbar_max = total_size; + pbar_max >>= 20; + blocks_num = pbar_max; + if (type == FileType::Mdi) + pbar_max++; + if (total_size2 == 0) + pbar_max++; + + if (type == FileType::Mdi) { + QByteArray bytes(base, 0); + auto empty = bytes.data(); + + *(uint32_t *) &(empty[0x08]) = (uint32_t) base; + *(uint32_t *) &(empty[0x0C]) = total_size; + *(uint16_t *) &(empty[0x10]) = (uint16_t) sector_bytes; + *(uint8_t *) &(empty[0x14]) = (uint8_t) 25; + *(uint8_t *) &(empty[0x18]) = (uint8_t) 64; + *(uint8_t *) &(empty[0x1C]) = (uint8_t) (dp->sectors / 64) / 25; + + stream.writeRawData(empty, base); + } + + QByteArray bytes(1048576, 0); + auto empty = bytes.data(); + + pbar.setMaximum(blocks_num); + for (uint32_t i = 0; i < blocks_num; i++) { + stream.writeRawData(empty, bytes.size()); + fileProgress(i); + } + + if (total_size2 > 0) { + QByteArray extra_bytes(total_size2, 0); + stream.writeRawData(extra_bytes.data(), total_size2); + } + fileProgress(blocks_num); + + return true; +} diff --git a/src/qt/qt_newfloppydialog.hpp b/src/qt/qt_newfloppydialog.hpp new file mode 100644 index 000000000..12e761cdf --- /dev/null +++ b/src/qt/qt_newfloppydialog.hpp @@ -0,0 +1,50 @@ +#ifndef QT_NEWFLOPPYDIALOG_HPP +#define QT_NEWFLOPPYDIALOG_HPP + +#include + +namespace Ui { +class NewFloppyDialog; +} + +struct disk_size_t; +class QProgressDialog; + +class NewFloppyDialog : public QDialog +{ + Q_OBJECT + +public: + enum class MediaType { + Floppy, + Zip, + Mo, + }; + enum class FileType { + Img, + Fdi, + Zdi, + Mdi, + }; + explicit NewFloppyDialog(MediaType type, QWidget *parent = nullptr); + ~NewFloppyDialog(); + + QString fileName() const; + +signals: + void fileProgress(int i); + +private slots: + void onCreate(); + +private: + Ui::NewFloppyDialog *ui; + MediaType mediaType_; + + bool create86f(const QString& filename, const disk_size_t& disk_size, uint8_t rpm_mode); + bool createSectorImage(const QString& filename, const disk_size_t& disk_size, FileType type); + bool createZipSectorImage(const QString& filename, const disk_size_t& disk_size, FileType type, QProgressDialog& pbar); + bool createMoSectorImage(const QString& filename, int8_t disk_size, FileType type, QProgressDialog& pbar); +}; + +#endif // QT_NEWFLOPPYDIALOG_HPP diff --git a/src/qt/qt_newfloppydialog.ui b/src/qt/qt_newfloppydialog.ui new file mode 100644 index 000000000..5e39e8848 --- /dev/null +++ b/src/qt/qt_newfloppydialog.ui @@ -0,0 +1,115 @@ + + + NewFloppyDialog + + + + 0 + 0 + 287 + 140 + + + + New Image + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + File Name + + + + + + + Disk Size + + + + + + + + + + RPM Mode + + + + + + + + + + + FileField + QWidget +
qt_filefield.hpp
+ 1 +
+
+ + + + buttonBox + accepted() + NewFloppyDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + NewFloppyDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index c4de70282..cb9646660 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -91,7 +91,7 @@ ui_sb_update_panes() { } void ui_sb_bugui(char *str) { - main_window->statusBar()->showMessage(str); + main_window->statusBarMessage(str); } void ui_sb_set_ready(int ready) {