mirror of
				https://github.com/dolphin-emu/dolphin.git
				synced 2025-10-25 09:29:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			556 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			556 lines
		
	
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2018 Dolphin Emulator Project
 | |
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| 
 | |
| #include "DolphinQt/Settings/GameCubePane.h"
 | |
| 
 | |
| #include <QCheckBox>
 | |
| #include <QComboBox>
 | |
| #include <QFileDialog>
 | |
| #include <QFileInfo>
 | |
| #include <QFormLayout>
 | |
| #include <QGridLayout>
 | |
| #include <QGroupBox>
 | |
| #include <QInputDialog>
 | |
| #include <QLabel>
 | |
| #include <QLineEdit>
 | |
| #include <QPushButton>
 | |
| #include <QVBoxLayout>
 | |
| 
 | |
| #include <utility>
 | |
| 
 | |
| #include "Common/CommonPaths.h"
 | |
| #include "Common/Config/Config.h"
 | |
| #include "Common/FileUtil.h"
 | |
| #include "Common/MsgHandler.h"
 | |
| 
 | |
| #include "Core/Config/MainSettings.h"
 | |
| #include "Core/ConfigManager.h"
 | |
| #include "Core/Core.h"
 | |
| #include "Core/HW/EXI/EXI.h"
 | |
| #include "Core/HW/GCMemcard/GCMemcard.h"
 | |
| #include "Core/NetPlayServer.h"
 | |
| 
 | |
| #include "DolphinQt/Config/Mapping/MappingWindow.h"
 | |
| #include "DolphinQt/GCMemcardManager.h"
 | |
| #include "DolphinQt/QtUtils/DolphinFileDialog.h"
 | |
| #include "DolphinQt/QtUtils/ModalMessageBox.h"
 | |
| #include "DolphinQt/Settings.h"
 | |
| #include "DolphinQt/Settings/BroadbandAdapterSettingsDialog.h"
 | |
| 
 | |
| enum
 | |
| {
 | |
|   SLOT_A_INDEX,
 | |
|   SLOT_B_INDEX,
 | |
|   SLOT_SP1_INDEX,
 | |
|   SLOT_COUNT
 | |
| };
 | |
| 
 | |
| GameCubePane::GameCubePane()
 | |
| {
 | |
|   CreateWidgets();
 | |
|   LoadSettings();
 | |
|   ConnectWidgets();
 | |
| }
 | |
| 
 | |
| void GameCubePane::CreateWidgets()
 | |
| {
 | |
|   QVBoxLayout* layout = new QVBoxLayout(this);
 | |
| 
 | |
|   // IPL Settings
 | |
|   QGroupBox* ipl_box = new QGroupBox(tr("IPL Settings"), this);
 | |
|   QVBoxLayout* ipl_box_layout = new QVBoxLayout(ipl_box);
 | |
|   ipl_box->setLayout(ipl_box_layout);
 | |
| 
 | |
|   m_skip_main_menu = new QCheckBox(tr("Skip Main Menu"), ipl_box);
 | |
|   ipl_box_layout->addWidget(m_skip_main_menu);
 | |
| 
 | |
|   QFormLayout* ipl_language_layout = new QFormLayout;
 | |
|   ipl_language_layout->setFormAlignment(Qt::AlignLeft | Qt::AlignTop);
 | |
|   ipl_language_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
 | |
|   ipl_box_layout->addLayout(ipl_language_layout);
 | |
| 
 | |
|   m_language_combo = new QComboBox(ipl_box);
 | |
|   m_language_combo->setCurrentIndex(-1);
 | |
|   ipl_language_layout->addRow(tr("System Language:"), m_language_combo);
 | |
| 
 | |
|   // Add languages
 | |
|   for (const auto& entry : {std::make_pair(tr("English"), 0), std::make_pair(tr("German"), 1),
 | |
|                             std::make_pair(tr("French"), 2), std::make_pair(tr("Spanish"), 3),
 | |
|                             std::make_pair(tr("Italian"), 4), std::make_pair(tr("Dutch"), 5)})
 | |
|   {
 | |
|     m_language_combo->addItem(entry.first, entry.second);
 | |
|   }
 | |
| 
 | |
|   // Device Settings
 | |
|   QGroupBox* device_box = new QGroupBox(tr("Device Settings"), this);
 | |
|   QGridLayout* device_layout = new QGridLayout(device_box);
 | |
|   device_box->setLayout(device_layout);
 | |
| 
 | |
|   for (int i = 0; i < SLOT_COUNT; i++)
 | |
|   {
 | |
|     m_slot_combos[i] = new QComboBox(device_box);
 | |
|     m_slot_combos[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
 | |
|     m_slot_buttons[i] = new QPushButton(tr("..."), device_box);
 | |
|     m_slot_buttons[i]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 | |
|   }
 | |
| 
 | |
|   // Add slot devices
 | |
|   for (const auto& entry :
 | |
|        {std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
 | |
|         std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
 | |
|         std::make_pair(tr("Memory Card"), ExpansionInterface::EXIDEVICE_MEMORYCARD),
 | |
|         std::make_pair(tr("GCI Folder"), ExpansionInterface::EXIDEVICE_MEMORYCARDFOLDER),
 | |
|         std::make_pair(tr("USB Gecko"), ExpansionInterface::EXIDEVICE_GECKO),
 | |
|         std::make_pair(tr("Advance Game Port"), ExpansionInterface::EXIDEVICE_AGP),
 | |
|         std::make_pair(tr("Microphone"), ExpansionInterface::EXIDEVICE_MIC)})
 | |
|   {
 | |
|     m_slot_combos[0]->addItem(entry.first, entry.second);
 | |
|     m_slot_combos[1]->addItem(entry.first, entry.second);
 | |
|   }
 | |
| 
 | |
|   // Add SP1 devices
 | |
|   std::vector<std::pair<QString, ExpansionInterface::TEXIDevices>> sp1Entries{
 | |
|       std::make_pair(tr("<Nothing>"), ExpansionInterface::EXIDEVICE_NONE),
 | |
|       std::make_pair(tr("Dummy"), ExpansionInterface::EXIDEVICE_DUMMY),
 | |
|       std::make_pair(tr("Broadband Adapter (TAP)"), ExpansionInterface::EXIDEVICE_ETH),
 | |
|       std::make_pair(tr("Broadband Adapter (XLink Kai)"), ExpansionInterface::EXIDEVICE_ETHXLINK)};
 | |
| #if defined(__APPLE__)
 | |
|   sp1Entries.emplace_back(std::make_pair(tr("Broadband Adapter (tapserver)"),
 | |
|                                          ExpansionInterface::EXIDEVICE_ETHTAPSERVER));
 | |
| #endif
 | |
|   for (const auto& entry : sp1Entries)
 | |
|   {
 | |
|     m_slot_combos[2]->addItem(entry.first, entry.second);
 | |
|   }
 | |
| 
 | |
|   device_layout->addWidget(new QLabel(tr("Slot A:")), 0, 0);
 | |
|   device_layout->addWidget(m_slot_combos[0], 0, 1);
 | |
|   device_layout->addWidget(m_slot_buttons[0], 0, 2);
 | |
|   device_layout->addWidget(new QLabel(tr("Slot B:")), 1, 0);
 | |
|   device_layout->addWidget(m_slot_combos[1], 1, 1);
 | |
|   device_layout->addWidget(m_slot_buttons[1], 1, 2);
 | |
|   device_layout->addWidget(new QLabel(tr("SP1:")), 2, 0);
 | |
|   device_layout->addWidget(m_slot_combos[2], 2, 1);
 | |
|   device_layout->addWidget(m_slot_buttons[2], 2, 2);
 | |
| 
 | |
| #ifdef HAS_LIBMGBA
 | |
|   // GBA Settings
 | |
|   auto* gba_box = new QGroupBox(tr("GBA Settings"), this);
 | |
|   auto* gba_layout = new QGridLayout(gba_box);
 | |
|   gba_box->setLayout(gba_layout);
 | |
|   int gba_row = 0;
 | |
| 
 | |
|   m_gba_threads = new QCheckBox(tr("Run GBA Cores in Dedicated Threads"));
 | |
|   gba_layout->addWidget(m_gba_threads, gba_row, 0, 1, -1);
 | |
|   gba_row++;
 | |
| 
 | |
|   m_gba_bios_edit = new QLineEdit();
 | |
|   m_gba_browse_bios = new QPushButton(QStringLiteral("..."));
 | |
|   gba_layout->addWidget(new QLabel(tr("BIOS:")), gba_row, 0);
 | |
|   gba_layout->addWidget(m_gba_bios_edit, gba_row, 1);
 | |
|   gba_layout->addWidget(m_gba_browse_bios, gba_row, 2);
 | |
|   gba_row++;
 | |
| 
 | |
|   for (size_t i = 0; i < m_gba_rom_edits.size(); ++i)
 | |
|   {
 | |
|     m_gba_rom_edits[i] = new QLineEdit();
 | |
|     m_gba_browse_roms[i] = new QPushButton(QStringLiteral("..."));
 | |
|     gba_layout->addWidget(new QLabel(tr("Port %1 ROM:").arg(i + 1)), gba_row, 0);
 | |
|     gba_layout->addWidget(m_gba_rom_edits[i], gba_row, 1);
 | |
|     gba_layout->addWidget(m_gba_browse_roms[i], gba_row, 2);
 | |
|     gba_row++;
 | |
|   }
 | |
| 
 | |
|   m_gba_save_rom_path = new QCheckBox(tr("Save in Same Directory as the ROM"));
 | |
|   gba_layout->addWidget(m_gba_save_rom_path, gba_row, 0, 1, -1);
 | |
|   gba_row++;
 | |
| 
 | |
|   m_gba_saves_edit = new QLineEdit();
 | |
|   m_gba_browse_saves = new QPushButton(QStringLiteral("..."));
 | |
|   gba_layout->addWidget(new QLabel(tr("Saves:")), gba_row, 0);
 | |
|   gba_layout->addWidget(m_gba_saves_edit, gba_row, 1);
 | |
|   gba_layout->addWidget(m_gba_browse_saves, gba_row, 2);
 | |
|   gba_row++;
 | |
| #endif
 | |
| 
 | |
|   layout->addWidget(ipl_box);
 | |
|   layout->addWidget(device_box);
 | |
| #ifdef HAS_LIBMGBA
 | |
|   layout->addWidget(gba_box);
 | |
| #endif
 | |
| 
 | |
|   layout->addStretch();
 | |
| 
 | |
|   setLayout(layout);
 | |
| }
 | |
| 
 | |
| void GameCubePane::ConnectWidgets()
 | |
| {
 | |
|   // IPL Settings
 | |
|   connect(m_skip_main_menu, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings);
 | |
|   connect(m_language_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
 | |
|           &GameCubePane::SaveSettings);
 | |
| 
 | |
|   // Device Settings
 | |
|   for (int i = 0; i < SLOT_COUNT; i++)
 | |
|   {
 | |
|     connect(m_slot_combos[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
 | |
|             [this, i] { UpdateButton(i); });
 | |
|     connect(m_slot_combos[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
 | |
|             &GameCubePane::SaveSettings);
 | |
|     connect(m_slot_buttons[i], &QPushButton::clicked, [this, i] { OnConfigPressed(i); });
 | |
|   }
 | |
| 
 | |
| #ifdef HAS_LIBMGBA
 | |
|   // GBA Settings
 | |
|   connect(m_gba_threads, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings);
 | |
|   connect(m_gba_bios_edit, &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings);
 | |
|   connect(m_gba_browse_bios, &QPushButton::clicked, this, &GameCubePane::BrowseGBABios);
 | |
|   connect(m_gba_save_rom_path, &QCheckBox::stateChanged, this, &GameCubePane::SaveRomPathChanged);
 | |
|   connect(m_gba_saves_edit, &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings);
 | |
|   connect(m_gba_browse_saves, &QPushButton::clicked, this, &GameCubePane::BrowseGBASaves);
 | |
|   for (size_t i = 0; i < m_gba_browse_roms.size(); ++i)
 | |
|   {
 | |
|     connect(m_gba_rom_edits[i], &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings);
 | |
|     connect(m_gba_browse_roms[i], &QPushButton::clicked, this, [this, i] { BrowseGBARom(i); });
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   // Emulation State
 | |
|   connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
 | |
|           &GameCubePane::OnEmulationStateChanged);
 | |
|   OnEmulationStateChanged();
 | |
| }
 | |
| 
 | |
| void GameCubePane::OnEmulationStateChanged()
 | |
| {
 | |
| #ifdef HAS_LIBMGBA
 | |
|   bool gba_enabled = !NetPlay::IsNetPlayRunning();
 | |
|   m_gba_threads->setEnabled(gba_enabled);
 | |
|   m_gba_bios_edit->setEnabled(gba_enabled);
 | |
|   m_gba_browse_bios->setEnabled(gba_enabled);
 | |
|   m_gba_save_rom_path->setEnabled(gba_enabled);
 | |
|   m_gba_saves_edit->setEnabled(gba_enabled);
 | |
|   m_gba_browse_saves->setEnabled(gba_enabled);
 | |
|   for (size_t i = 0; i < m_gba_browse_roms.size(); ++i)
 | |
|   {
 | |
|     m_gba_rom_edits[i]->setEnabled(gba_enabled);
 | |
|     m_gba_browse_roms[i]->setEnabled(gba_enabled);
 | |
|   }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void GameCubePane::UpdateButton(int slot)
 | |
| {
 | |
|   const auto value = m_slot_combos[slot]->currentData().toInt();
 | |
|   bool has_config = false;
 | |
| 
 | |
|   switch (slot)
 | |
|   {
 | |
|   case SLOT_A_INDEX:
 | |
|   case SLOT_B_INDEX:
 | |
|     has_config =
 | |
|         (value == ExpansionInterface::EXIDEVICE_MEMORYCARD ||
 | |
|          value == ExpansionInterface::EXIDEVICE_AGP || value == ExpansionInterface::EXIDEVICE_MIC);
 | |
|     break;
 | |
|   case SLOT_SP1_INDEX:
 | |
|     has_config = (value == ExpansionInterface::EXIDEVICE_ETH ||
 | |
|                   value == ExpansionInterface::EXIDEVICE_ETHXLINK);
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   m_slot_buttons[slot]->setEnabled(has_config);
 | |
| }
 | |
| 
 | |
| void GameCubePane::OnConfigPressed(int slot)
 | |
| {
 | |
|   QString filter;
 | |
|   bool memcard = false;
 | |
| 
 | |
|   switch (m_slot_combos[slot]->currentData().toInt())
 | |
|   {
 | |
|   case ExpansionInterface::EXIDEVICE_MEMORYCARD:
 | |
|     filter = tr("GameCube Memory Cards (*.raw *.gcp)");
 | |
|     memcard = true;
 | |
|     break;
 | |
|   case ExpansionInterface::EXIDEVICE_AGP:
 | |
|     filter = tr("Game Boy Advance Carts (*.gba)");
 | |
|     break;
 | |
|   case ExpansionInterface::EXIDEVICE_MIC:
 | |
|     MappingWindow(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, slot).exec();
 | |
|     return;
 | |
|   case ExpansionInterface::EXIDEVICE_ETH:
 | |
|   {
 | |
|     BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::Ethernet).exec();
 | |
|     return;
 | |
|   }
 | |
|   case ExpansionInterface::EXIDEVICE_ETHXLINK:
 | |
|   {
 | |
|     BroadbandAdapterSettingsDialog(this, BroadbandAdapterSettingsDialog::Type::XLinkKai).exec();
 | |
|     return;
 | |
|   }
 | |
|   default:
 | |
|     qFatal("unknown settings pressed");
 | |
|   }
 | |
| 
 | |
|   QString filename = DolphinFileDialog::getSaveFileName(
 | |
|       this, tr("Choose a file to open"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)),
 | |
|       filter, 0, QFileDialog::DontConfirmOverwrite);
 | |
| 
 | |
|   if (filename.isEmpty())
 | |
|     return;
 | |
| 
 | |
|   QString path_abs = QFileInfo(filename).absoluteFilePath();
 | |
| 
 | |
|   // Memcard validity checks
 | |
|   if (memcard)
 | |
|   {
 | |
|     if (File::Exists(filename.toStdString()))
 | |
|     {
 | |
|       auto [error_code, mc] = Memcard::GCMemcard::Open(filename.toStdString());
 | |
| 
 | |
|       if (error_code.HasCriticalErrors() || !mc || !mc->IsValid())
 | |
|       {
 | |
|         ModalMessageBox::critical(
 | |
|             this, tr("Error"),
 | |
|             tr("The file\n%1\nis either corrupted or not a GameCube memory card file.\n%2")
 | |
|                 .arg(filename)
 | |
|                 .arg(GCMemcardManager::GetErrorMessagesForErrorCode(error_code)));
 | |
|         return;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     bool other_slot_memcard =
 | |
|         m_slot_combos[slot == SLOT_A_INDEX ? SLOT_B_INDEX : SLOT_A_INDEX]->currentData().toInt() ==
 | |
|         ExpansionInterface::EXIDEVICE_MEMORYCARD;
 | |
|     if (other_slot_memcard)
 | |
|     {
 | |
|       QString path_b =
 | |
|           QFileInfo(QString::fromStdString(slot == 0 ? Config::Get(Config::MAIN_MEMCARD_B_PATH) :
 | |
|                                                        Config::Get(Config::MAIN_MEMCARD_A_PATH)))
 | |
|               .absoluteFilePath();
 | |
| 
 | |
|       if (path_abs == path_b)
 | |
|       {
 | |
|         ModalMessageBox::critical(this, tr("Error"),
 | |
|                                   tr("The same file can't be used in both slots."));
 | |
|         return;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   QString path_old;
 | |
|   if (memcard)
 | |
|   {
 | |
|     path_old =
 | |
|         QFileInfo(QString::fromStdString(slot == 0 ? Config::Get(Config::MAIN_MEMCARD_A_PATH) :
 | |
|                                                      Config::Get(Config::MAIN_MEMCARD_B_PATH)))
 | |
|             .absoluteFilePath();
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     path_old = QFileInfo(QString::fromStdString(slot == 0 ? SConfig::GetInstance().m_strGbaCartA :
 | |
|                                                             SConfig::GetInstance().m_strGbaCartB))
 | |
|                    .absoluteFilePath();
 | |
|   }
 | |
| 
 | |
|   if (memcard)
 | |
|   {
 | |
|     if (slot == SLOT_A_INDEX)
 | |
|     {
 | |
|       Config::SetBase(Config::MAIN_MEMCARD_A_PATH, path_abs.toStdString());
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       Config::SetBase(Config::MAIN_MEMCARD_B_PATH, path_abs.toStdString());
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (slot == SLOT_A_INDEX)
 | |
|     {
 | |
|       SConfig::GetInstance().m_strGbaCartA = path_abs.toStdString();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       SConfig::GetInstance().m_strGbaCartB = path_abs.toStdString();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (Core::IsRunning() && path_abs != path_old)
 | |
|   {
 | |
|     ExpansionInterface::ChangeDevice(
 | |
|         // SlotB is on channel 1, slotA and SP1 are on 0
 | |
|         slot,
 | |
|         // The device enum to change to
 | |
|         memcard ? ExpansionInterface::EXIDEVICE_MEMORYCARD : ExpansionInterface::EXIDEVICE_AGP,
 | |
|         // SP1 is device 2, slots are device 0
 | |
|         0);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void GameCubePane::BrowseGBABios()
 | |
| {
 | |
|   QString file = QDir::toNativeSeparators(DolphinFileDialog::getOpenFileName(
 | |
|       this, tr("Select GBA BIOS"), QString::fromStdString(File::GetUserPath(F_GBABIOS_IDX)),
 | |
|       tr("All Files (*)")));
 | |
|   if (!file.isEmpty())
 | |
|   {
 | |
|     m_gba_bios_edit->setText(file);
 | |
|     SaveSettings();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void GameCubePane::BrowseGBARom(size_t index)
 | |
| {
 | |
|   QString file = QString::fromStdString(GetOpenGBARom({}));
 | |
|   if (!file.isEmpty())
 | |
|   {
 | |
|     m_gba_rom_edits[index]->setText(file);
 | |
|     SaveSettings();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void GameCubePane::SaveRomPathChanged()
 | |
| {
 | |
|   m_gba_saves_edit->setEnabled(!m_gba_save_rom_path->isChecked());
 | |
|   m_gba_browse_saves->setEnabled(!m_gba_save_rom_path->isChecked());
 | |
|   SaveSettings();
 | |
| }
 | |
| 
 | |
| void GameCubePane::BrowseGBASaves()
 | |
| {
 | |
|   QString dir = QDir::toNativeSeparators(DolphinFileDialog::getExistingDirectory(
 | |
|       this, tr("Select GBA Saves Path"),
 | |
|       QString::fromStdString(File::GetUserPath(D_GBASAVES_IDX))));
 | |
|   if (!dir.isEmpty())
 | |
|   {
 | |
|     m_gba_saves_edit->setText(dir);
 | |
|     SaveSettings();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void GameCubePane::LoadSettings()
 | |
| {
 | |
|   const SConfig& params = SConfig::GetInstance();
 | |
| 
 | |
|   // IPL Settings
 | |
|   m_skip_main_menu->setChecked(params.bHLE_BS2);
 | |
|   m_language_combo->setCurrentIndex(m_language_combo->findData(params.SelectedLanguage));
 | |
| 
 | |
|   bool have_menu = false;
 | |
| 
 | |
|   for (const std::string dir : {USA_DIR, JAP_DIR, EUR_DIR})
 | |
|   {
 | |
|     const auto path = DIR_SEP + dir + DIR_SEP GC_IPL;
 | |
|     if (File::Exists(File::GetUserPath(D_GCUSER_IDX) + path) ||
 | |
|         File::Exists(File::GetSysDirectory() + GC_SYS_DIR + path))
 | |
|     {
 | |
|       have_menu = true;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   m_skip_main_menu->setEnabled(have_menu);
 | |
|   m_skip_main_menu->setToolTip(have_menu ? QString{} : tr("Put IPL ROMs in User/GC/<region>."));
 | |
| 
 | |
|   // Device Settings
 | |
|   for (int i = 0; i < SLOT_COUNT; i++)
 | |
|   {
 | |
|     QSignalBlocker blocker(m_slot_combos[i]);
 | |
|     m_slot_combos[i]->setCurrentIndex(
 | |
|         m_slot_combos[i]->findData(SConfig::GetInstance().m_EXIDevice[i]));
 | |
|     UpdateButton(i);
 | |
|   }
 | |
| 
 | |
| #ifdef HAS_LIBMGBA
 | |
|   // GBA Settings
 | |
|   m_gba_threads->setChecked(Config::Get(Config::MAIN_GBA_THREADS));
 | |
|   m_gba_bios_edit->setText(QString::fromStdString(File::GetUserPath(F_GBABIOS_IDX)));
 | |
|   m_gba_save_rom_path->setChecked(Config::Get(Config::MAIN_GBA_SAVES_IN_ROM_PATH));
 | |
|   m_gba_saves_edit->setText(QString::fromStdString(File::GetUserPath(D_GBASAVES_IDX)));
 | |
|   for (size_t i = 0; i < m_gba_rom_edits.size(); ++i)
 | |
|     m_gba_rom_edits[i]->setText(QString::fromStdString(Config::Get(Config::MAIN_GBA_ROM_PATHS[i])));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void GameCubePane::SaveSettings()
 | |
| {
 | |
|   Config::ConfigChangeCallbackGuard config_guard;
 | |
| 
 | |
|   SConfig& params = SConfig::GetInstance();
 | |
| 
 | |
|   // IPL Settings
 | |
|   params.bHLE_BS2 = m_skip_main_menu->isChecked();
 | |
|   Config::SetBaseOrCurrent(Config::MAIN_SKIP_IPL, m_skip_main_menu->isChecked());
 | |
|   params.SelectedLanguage = m_language_combo->currentData().toInt();
 | |
|   Config::SetBaseOrCurrent(Config::MAIN_GC_LANGUAGE, m_language_combo->currentData().toInt());
 | |
| 
 | |
|   // Device Settings
 | |
|   for (int i = 0; i < SLOT_COUNT; i++)
 | |
|   {
 | |
|     const auto dev = ExpansionInterface::TEXIDevices(m_slot_combos[i]->currentData().toInt());
 | |
| 
 | |
|     if (Core::IsRunning() && SConfig::GetInstance().m_EXIDevice[i] != dev)
 | |
|     {
 | |
|       ExpansionInterface::ChangeDevice(
 | |
|           // SlotB is on channel 1, slotA and SP1 are on 0
 | |
|           (i == 1) ? 1 : 0,
 | |
|           // The device enum to change to
 | |
|           dev,
 | |
|           // SP1 is device 2, slots are device 0
 | |
|           (i == 2) ? 2 : 0);
 | |
|     }
 | |
| 
 | |
|     SConfig::GetInstance().m_EXIDevice[i] = dev;
 | |
|     switch (i)
 | |
|     {
 | |
|     case SLOT_A_INDEX:
 | |
|       Config::SetBaseOrCurrent(Config::MAIN_SLOT_A, dev);
 | |
|       break;
 | |
|     case SLOT_B_INDEX:
 | |
|       Config::SetBaseOrCurrent(Config::MAIN_SLOT_B, dev);
 | |
|       break;
 | |
|     case SLOT_SP1_INDEX:
 | |
|       Config::SetBaseOrCurrent(Config::MAIN_SERIAL_PORT_1, dev);
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| #ifdef HAS_LIBMGBA
 | |
|   // GBA Settings
 | |
|   if (!NetPlay::IsNetPlayRunning())
 | |
|   {
 | |
|     Config::SetBaseOrCurrent(Config::MAIN_GBA_THREADS, m_gba_threads->isChecked());
 | |
|     Config::SetBaseOrCurrent(Config::MAIN_GBA_BIOS_PATH, m_gba_bios_edit->text().toStdString());
 | |
|     Config::SetBaseOrCurrent(Config::MAIN_GBA_SAVES_IN_ROM_PATH, m_gba_save_rom_path->isChecked());
 | |
|     Config::SetBaseOrCurrent(Config::MAIN_GBA_SAVES_PATH, m_gba_saves_edit->text().toStdString());
 | |
|     File::SetUserPath(F_GBABIOS_IDX, Config::Get(Config::MAIN_GBA_BIOS_PATH));
 | |
|     File::SetUserPath(D_GBASAVES_IDX, Config::Get(Config::MAIN_GBA_SAVES_PATH));
 | |
|     for (size_t i = 0; i < m_gba_rom_edits.size(); ++i)
 | |
|     {
 | |
|       Config::SetBaseOrCurrent(Config::MAIN_GBA_ROM_PATHS[i],
 | |
|                                m_gba_rom_edits[i]->text().toStdString());
 | |
|     }
 | |
| 
 | |
|     auto server = Settings::Instance().GetNetPlayServer();
 | |
|     if (server)
 | |
|       server->SetGBAConfig(server->GetGBAConfig(), true);
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   LoadSettings();
 | |
| }
 | |
| 
 | |
| std::string GameCubePane::GetOpenGBARom(std::string_view title)
 | |
| {
 | |
|   QString caption = tr("Select GBA ROM");
 | |
|   if (!title.empty())
 | |
|     caption += QStringLiteral(": %1").arg(QString::fromStdString(std::string(title)));
 | |
|   return QDir::toNativeSeparators(
 | |
|              DolphinFileDialog::getOpenFileName(
 | |
|                  nullptr, caption, QString(),
 | |
|                  tr("Game Boy Advance ROMs (*.gba *.gbc *.gb *.7z *.zip *.agb *.mb *.rom *.bin);;"
 | |
|                     "All Files (*)")))
 | |
|       .toStdString();
 | |
| }
 |