Use Slot in GameCubePane

This commit is contained in:
Pokechu22 2022-01-11 12:25:17 -08:00
parent 9109258b85
commit 19ef936e27
2 changed files with 123 additions and 126 deletions

View File

@ -19,6 +19,7 @@
#include <array>
#include <utility>
#include "Common/Assert.h"
#include "Common/CommonPaths.h"
#include "Common/Config/Config.h"
#include "Common/FileUtil.h"
@ -89,12 +90,12 @@ void GameCubePane::CreateWidgets()
QGridLayout* device_layout = new QGridLayout(device_box);
device_box->setLayout(device_layout);
for (int i = 0; i < SLOT_COUNT; i++)
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
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);
m_slot_combos[slot] = new QComboBox(device_box);
m_slot_combos[slot]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
m_slot_buttons[slot] = new QPushButton(tr("..."), device_box);
m_slot_buttons[slot]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}
// Add slot devices
@ -104,8 +105,8 @@ void GameCubePane::CreateWidgets()
{
const QString name = tr(fmt::format("{:n}", device).c_str());
const int value = static_cast<int>(device);
m_slot_combos[0]->addItem(name, value);
m_slot_combos[1]->addItem(name, value);
m_slot_combos[ExpansionInterface::Slot::A]->addItem(name, value);
m_slot_combos[ExpansionInterface::Slot::B]->addItem(name, value);
}
// Add SP1 devices
@ -119,18 +120,19 @@ void GameCubePane::CreateWidgets()
#endif
})
{
m_slot_combos[2]->addItem(tr(fmt::format("{:n}", device).c_str()), static_cast<int>(device));
m_slot_combos[ExpansionInterface::Slot::SP1]->addItem(tr(fmt::format("{:n}", device).c_str()),
static_cast<int>(device));
}
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(m_slot_combos[ExpansionInterface::Slot::A], 0, 1);
device_layout->addWidget(m_slot_buttons[ExpansionInterface::Slot::A], 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(m_slot_combos[ExpansionInterface::Slot::B], 1, 1);
device_layout->addWidget(m_slot_buttons[ExpansionInterface::Slot::B], 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);
device_layout->addWidget(m_slot_combos[ExpansionInterface::Slot::SP1], 2, 1);
device_layout->addWidget(m_slot_buttons[ExpansionInterface::Slot::SP1], 2, 2);
#ifdef HAS_LIBMGBA
// GBA Settings
@ -191,13 +193,13 @@ void GameCubePane::ConnectWidgets()
&GameCubePane::SaveSettings);
// Device Settings
for (int i = 0; i < SLOT_COUNT; i++)
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
connect(m_slot_combos[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
[this, i] { UpdateButton(i); });
connect(m_slot_combos[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
connect(m_slot_combos[slot], qOverload<int>(&QComboBox::currentIndexChanged), this,
[this, slot] { UpdateButton(slot); });
connect(m_slot_combos[slot], qOverload<int>(&QComboBox::currentIndexChanged), this,
&GameCubePane::SaveSettings);
connect(m_slot_buttons[i], &QPushButton::clicked, [this, i] { OnConfigPressed(i); });
connect(m_slot_buttons[slot], &QPushButton::clicked, [this, slot] { OnConfigPressed(slot); });
}
#ifdef HAS_LIBMGBA
@ -239,7 +241,7 @@ void GameCubePane::OnEmulationStateChanged()
#endif
}
void GameCubePane::UpdateButton(int slot)
void GameCubePane::UpdateButton(ExpansionInterface::Slot slot)
{
const auto device =
static_cast<ExpansionInterface::EXIDeviceType>(m_slot_combos[slot]->currentData().toInt());
@ -247,13 +249,13 @@ void GameCubePane::UpdateButton(int slot)
switch (slot)
{
case SLOT_A_INDEX:
case SLOT_B_INDEX:
case ExpansionInterface::Slot::A:
case ExpansionInterface::Slot::B:
has_config = (device == ExpansionInterface::EXIDeviceType::MemoryCard ||
device == ExpansionInterface::EXIDeviceType::AGP ||
device == ExpansionInterface::EXIDeviceType::Microphone);
break;
case SLOT_SP1_INDEX:
case ExpansionInterface::Slot::SP1:
has_config = (device == ExpansionInterface::EXIDeviceType::Ethernet ||
device == ExpansionInterface::EXIDeviceType::EthernetXLink);
break;
@ -262,25 +264,22 @@ void GameCubePane::UpdateButton(int slot)
m_slot_buttons[slot]->setEnabled(has_config);
}
void GameCubePane::OnConfigPressed(int slot)
void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot)
{
QString filter;
bool memcard = false;
const ExpansionInterface::EXIDeviceType device =
static_cast<ExpansionInterface::EXIDeviceType>(m_slot_combos[slot]->currentData().toInt());
switch (device)
{
case ExpansionInterface::EXIDeviceType::MemoryCard:
filter = tr("GameCube Memory Cards (*.raw *.gcp)");
memcard = true;
break;
BrowseMemcard(slot);
return;
case ExpansionInterface::EXIDeviceType::AGP:
filter = tr("Game Boy Advance Carts (*.gba)");
break;
BrowseAGPRom(slot);
return;
case ExpansionInterface::EXIDeviceType::Microphone:
MappingWindow(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, slot).exec();
// TODO: convert MappingWindow to use Slot?
MappingWindow(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, static_cast<int>(slot)).exec();
return;
case ExpansionInterface::EXIDeviceType::Ethernet:
{
@ -296,10 +295,15 @@ void GameCubePane::OnConfigPressed(int slot)
PanicAlertFmt("Unknown settings pressed for {}", device);
return;
}
}
void GameCubePane::BrowseMemcard(ExpansionInterface::Slot slot)
{
ASSERT(ExpansionInterface::IsMemcardSlot(slot));
QString filename = DolphinFileDialog::getSaveFileName(
this, tr("Choose a file to open"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)),
filter, 0, QFileDialog::DontConfirmOverwrite);
tr("GameCube Memory Cards (*.raw *.gcp)"), 0, QFileDialog::DontConfirmOverwrite);
if (filename.isEmpty())
return;
@ -307,91 +311,85 @@ void GameCubePane::OnConfigPressed(int slot)
QString path_abs = QFileInfo(filename).absoluteFilePath();
// Memcard validity checks
if (memcard)
if (File::Exists(filename.toStdString()))
{
if (File::Exists(filename.toStdString()))
{
auto [error_code, mc] = Memcard::GCMemcard::Open(filename.toStdString());
auto [error_code, mc] = Memcard::GCMemcard::Open(filename.toStdString());
if (error_code.HasCriticalErrors() || !mc || !mc->IsValid())
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;
}
}
for (ExpansionInterface::Slot other_slot : ExpansionInterface::MEMCARD_SLOTS)
{
if (other_slot == slot)
continue;
bool other_slot_memcard = m_slot_combos[other_slot]->currentData().toInt() ==
static_cast<int>(ExpansionInterface::EXIDeviceType::MemoryCard);
if (other_slot_memcard)
{
QString path_other =
QFileInfo(QString::fromStdString(Config::Get(Config::GetInfoForMemcardPath(other_slot))))
.absoluteFilePath();
if (path_abs == path_other)
{
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() ==
static_cast<int>(ExpansionInterface::EXIDeviceType::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."));
tr("The same file can't be used in multiple slots; it is already used by %1.")
.arg(QString::fromStdString(fmt::to_string(other_slot))));
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 ? Config::Get(Config::MAIN_AGP_CART_A_PATH) :
Config::Get(Config::MAIN_AGP_CART_B_PATH)))
.absoluteFilePath();
}
QString path_old =
QFileInfo(QString::fromStdString(Config::Get(Config::GetInfoForMemcardPath(slot))))
.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)
{
Config::SetBase(Config::MAIN_AGP_CART_A_PATH, path_abs.toStdString());
}
else
{
Config::SetBase(Config::MAIN_AGP_CART_B_PATH, path_abs.toStdString());
}
}
Config::SetBase(Config::GetInfoForMemcardPath(slot), path_abs.toStdString());
if (Core::IsRunning() && path_abs != path_old)
{
ExpansionInterface::ChangeDevice(
// SlotB is on channel 1, slotA and SP1 are on 0
slot,
// SP1 is device 2, slots are device 0
0,
// The device enum to change to
memcard ? ExpansionInterface::EXIDeviceType::MemoryCard :
ExpansionInterface::EXIDeviceType::AGP);
// ChangeDevice unplugs the device for 1 second, which means that games should notice that
// the path has changed and thus the memory card contents have changed
ExpansionInterface::ChangeDevice(slot, ExpansionInterface::EXIDeviceType::MemoryCard);
}
}
void GameCubePane::BrowseAGPRom(ExpansionInterface::Slot slot)
{
ASSERT(ExpansionInterface::IsMemcardSlot(slot));
QString filename = DolphinFileDialog::getSaveFileName(
this, tr("Choose a file to open"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)),
tr("Game Boy Advance Carts (*.gba)"), 0, QFileDialog::DontConfirmOverwrite);
if (filename.isEmpty())
return;
QString path_abs = QFileInfo(filename).absoluteFilePath();
QString path_old =
QFileInfo(QString::fromStdString(Config::Get(Config::GetInfoForAGPCartPath(slot))))
.absoluteFilePath();
Config::SetBase(Config::GetInfoForAGPCartPath(slot), path_abs.toStdString());
if (Core::IsRunning() && path_abs != path_old)
{
// ChangeDevice unplugs the device for 1 second. For an actual AGP, you can remove the
// cartridge without unplugging it, and it's not clear if the AGP software actually notices
// that it's been unplugged or the cartridge has changed, but this was done for memcards so
// we might as well do it for the AGP too.
ExpansionInterface::ChangeDevice(slot, ExpansionInterface::EXIDeviceType::AGP);
}
}
@ -460,13 +458,14 @@ void GameCubePane::LoadSettings()
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++)
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
QSignalBlocker blocker(m_slot_combos[i]);
QSignalBlocker blocker(m_slot_combos[slot]);
const ExpansionInterface::EXIDeviceType exi_device =
Config::Get(Config::GetInfoForEXIDevice(static_cast<ExpansionInterface::Slot>(i)));
m_slot_combos[i]->setCurrentIndex(m_slot_combos[i]->findData(static_cast<int>(exi_device)));
UpdateButton(i);
Config::Get(Config::GetInfoForEXIDevice(slot));
m_slot_combos[slot]->setCurrentIndex(
m_slot_combos[slot]->findData(static_cast<int>(exi_device)));
UpdateButton(slot);
}
#ifdef HAS_LIBMGBA
@ -489,26 +488,19 @@ void GameCubePane::SaveSettings()
Config::SetBaseOrCurrent(Config::MAIN_GC_LANGUAGE, m_language_combo->currentData().toInt());
// Device Settings
for (int i = 0; i < SLOT_COUNT; i++)
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
{
const auto dev =
static_cast<ExpansionInterface::EXIDeviceType>(m_slot_combos[i]->currentData().toInt());
static_cast<ExpansionInterface::EXIDeviceType>(m_slot_combos[slot]->currentData().toInt());
const ExpansionInterface::EXIDeviceType current_exi_device =
Config::Get(Config::GetInfoForEXIDevice(static_cast<ExpansionInterface::Slot>(i)));
Config::Get(Config::GetInfoForEXIDevice(slot));
if (Core::IsRunning() && current_exi_device != dev)
{
ExpansionInterface::ChangeDevice(
// SlotB is on channel 1, slotA and SP1 are on 0
(i == 1) ? 1 : 0,
// SP1 is device 2, slots are device 0
(i == 2) ? 2 : 0,
// The device enum to change to
dev);
ExpansionInterface::ChangeDevice(slot, dev);
}
Config::SetBaseOrCurrent(Config::GetInfoForEXIDevice(static_cast<ExpansionInterface::Slot>(i)),
dev);
Config::SetBaseOrCurrent(Config::GetInfoForEXIDevice(slot), dev);
}
#ifdef HAS_LIBMGBA

View File

@ -9,6 +9,9 @@
#include <QWidget>
#include "Common/EnumMap.h"
#include "Core/HW/EXI/EXI.h"
class QCheckBox;
class QComboBox;
class QLineEdit;
@ -31,9 +34,11 @@ private:
void OnEmulationStateChanged();
void UpdateButton(int slot);
void OnConfigPressed(int slot);
void UpdateButton(ExpansionInterface::Slot slot);
void OnConfigPressed(ExpansionInterface::Slot slot);
void BrowseMemcard(ExpansionInterface::Slot slot);
void BrowseAGPRom(ExpansionInterface::Slot slot);
void BrowseGBABios();
void BrowseGBARom(size_t index);
void SaveRomPathChanged();
@ -42,8 +47,8 @@ private:
QCheckBox* m_skip_main_menu;
QComboBox* m_language_combo;
QPushButton* m_slot_buttons[3];
QComboBox* m_slot_combos[3];
Common::EnumMap<QPushButton*, ExpansionInterface::MAX_SLOT> m_slot_buttons;
Common::EnumMap<QComboBox*, ExpansionInterface::MAX_SLOT> m_slot_combos;
QCheckBox* m_gba_threads;
QCheckBox* m_gba_save_rom_path;