biossettingswidget.cpp (6215B)
1 // SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "biossettingswidget.h" 5 #include "qthost.h" 6 #include "qtutils.h" 7 #include "settingswindow.h" 8 #include "settingwidgetbinder.h" 9 10 #include "core/bios.h" 11 #include "core/settings.h" 12 13 #include <QtWidgets/QFileDialog> 14 #include <algorithm> 15 16 BIOSSettingsWidget::BIOSSettingsWidget(SettingsWindow* dialog, QWidget* parent) : QWidget(parent), m_dialog(dialog) 17 { 18 SettingsInterface* sif = dialog->getSettingsInterface(); 19 20 m_ui.setupUi(this); 21 22 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableTTYLogging, "BIOS", "TTYLogging", false); 23 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastBoot, "BIOS", "PatchFastBoot", false); 24 25 dialog->registerWidgetHelp(m_ui.fastBoot, tr("Fast Boot"), tr("Unchecked"), 26 tr("Patches the BIOS to skip the console's boot animation. Does not work with all games, " 27 "but usually safe to enable.")); 28 dialog->registerWidgetHelp(m_ui.enableTTYLogging, tr("Enable TTY Logging"), tr("Unchecked"), 29 tr("Logs BIOS calls to printf(). Not all games contain debugging messages.")); 30 31 connect(m_ui.imageNTSCJ, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { 32 if (m_dialog->isPerGameSettings() && index == 0) 33 { 34 m_dialog->removeSettingValue("BIOS", "PathNTSCJ"); 35 } 36 else 37 { 38 m_dialog->setStringSettingValue("BIOS", "PathNTSCJ", 39 m_ui.imageNTSCJ->itemData(index).toString().toStdString().c_str()); 40 } 41 }); 42 connect(m_ui.imageNTSCU, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { 43 if (m_dialog->isPerGameSettings() && index == 0) 44 { 45 m_dialog->removeSettingValue("BIOS", "PathNTSCU"); 46 } 47 else 48 { 49 m_dialog->setStringSettingValue("BIOS", "PathNTSCU", 50 m_ui.imageNTSCU->itemData(index).toString().toStdString().c_str()); 51 } 52 }); 53 connect(m_ui.imagePAL, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { 54 if (m_dialog->isPerGameSettings() && index == 0) 55 { 56 m_dialog->removeSettingValue("BIOS", "PathPAL"); 57 } 58 else 59 { 60 m_dialog->setStringSettingValue("BIOS", "PathPAL", 61 m_ui.imagePAL->itemData(index).toString().toStdString().c_str()); 62 } 63 }); 64 65 connect(m_ui.refresh, &QPushButton::clicked, this, &BIOSSettingsWidget::refreshList); 66 67 if (!m_dialog->isPerGameSettings()) 68 { 69 SettingWidgetBinder::BindWidgetToFolderSetting( 70 sif, m_ui.searchDirectory, m_ui.browseSearchDirectory, tr("Select BIOS Directory"), m_ui.openSearchDirectory, 71 nullptr, "BIOS", "SearchDirectory", Path::Combine(EmuFolders::DataRoot, "bios")); 72 connect(m_ui.searchDirectory, &QLineEdit::textChanged, this, &BIOSSettingsWidget::refreshList); 73 } 74 else 75 { 76 m_ui.mainLayout->removeWidget(m_ui.directoryGroupBox); 77 delete m_ui.directoryGroupBox; 78 m_ui.directoryGroupBox = nullptr; 79 m_ui.directoryGroupBoxLabel = nullptr; 80 m_ui.directoryGroupBoxLayout = nullptr; 81 m_ui.directoryGroupBoxHorizontalLayout = nullptr; 82 m_ui.searchDirectory = nullptr; 83 m_ui.browseSearchDirectory = nullptr; 84 } 85 86 refreshList(); 87 } 88 89 BIOSSettingsWidget::~BIOSSettingsWidget() = default; 90 91 void BIOSSettingsWidget::refreshList() 92 { 93 auto images = BIOS::FindBIOSImagesInDirectory(EmuFolders::Bios.c_str()); 94 populateDropDownForRegion(ConsoleRegion::NTSC_J, m_ui.imageNTSCJ, images, m_dialog->isPerGameSettings()); 95 populateDropDownForRegion(ConsoleRegion::NTSC_U, m_ui.imageNTSCU, images, m_dialog->isPerGameSettings()); 96 populateDropDownForRegion(ConsoleRegion::PAL, m_ui.imagePAL, images, m_dialog->isPerGameSettings()); 97 98 setDropDownValue(m_ui.imageNTSCJ, m_dialog->getStringValue("BIOS", "PathNTSCJ", std::nullopt), 99 m_dialog->isPerGameSettings()); 100 setDropDownValue(m_ui.imageNTSCU, m_dialog->getStringValue("BIOS", "PathNTSCU", std::nullopt), 101 m_dialog->isPerGameSettings()); 102 setDropDownValue(m_ui.imagePAL, m_dialog->getStringValue("BIOS", "PathPAL", std::nullopt), 103 m_dialog->isPerGameSettings()); 104 } 105 106 void BIOSSettingsWidget::populateDropDownForRegion(ConsoleRegion region, QComboBox* cb, 107 std::vector<std::pair<std::string, const BIOS::ImageInfo*>>& images, 108 bool per_game) 109 { 110 QSignalBlocker sb(cb); 111 cb->clear(); 112 113 if (per_game) 114 cb->addItem(QIcon(QStringLiteral(":/icons/system-search.png")), tr("Use Global Setting")); 115 116 cb->addItem(QIcon(QStringLiteral(":/icons/system-search.png")), tr("Auto-Detect")); 117 118 std::sort(images.begin(), images.end(), [region](const auto& left, const auto& right) { 119 const bool left_region_match = (left.second && left.second->region == region); 120 const bool right_region_match = (right.second && right.second->region == region); 121 if (left_region_match && !right_region_match) 122 return true; 123 else if (right_region_match && !left_region_match) 124 return false; 125 126 return left.first < right.first; 127 }); 128 129 for (const auto& [name, info] : images) 130 { 131 QString name_str(QString::fromStdString(name)); 132 cb->addItem(QtUtils::GetIconForRegion(info ? info->region : ConsoleRegion::Count), 133 QStringLiteral("%1 (%2)") 134 .arg(info ? QString(info->description) : qApp->translate("BIOSSettingsWidget", "Unknown")) 135 .arg(name_str), 136 QVariant(name_str)); 137 } 138 } 139 140 void BIOSSettingsWidget::setDropDownValue(QComboBox* cb, const std::optional<std::string>& name, bool per_game) 141 { 142 QSignalBlocker sb(cb); 143 144 if (!name.has_value() || name->empty()) 145 { 146 cb->setCurrentIndex((per_game && name.has_value()) ? 1 : 0); 147 return; 148 } 149 150 QString qname(QString::fromStdString(name.value())); 151 for (int i = 1; i < cb->count(); i++) 152 { 153 if (cb->itemData(i) == qname) 154 { 155 cb->setCurrentIndex(i); 156 return; 157 } 158 } 159 160 cb->addItem(qname, QVariant(qname)); 161 cb->setCurrentIndex(cb->count() - 1); 162 }