From f8e57a9de364cbef81d47707ca728ccc24c65d57 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Fri, 4 Sep 2020 15:58:43 -0700 Subject: [PATCH] Partially implement configuring the SD card path This doesn't work (changes aren't saved to disk), and I don't fully understand why... --- Source/Core/Core/Config/MainSettings.cpp | 15 ++++ Source/Core/Core/Config/MainSettings.h | 4 + Source/Core/Core/HW/EXI/EXI_Device.cpp | 2 +- Source/Core/Core/HW/EXI/EXI_DeviceSD.cpp | 18 ++++- Source/Core/Core/HW/EXI/EXI_DeviceSD.h | 2 +- .../Core/DolphinQt/Settings/GameCubePane.cpp | 73 ++++++++++++++++++- Source/Core/DolphinQt/Settings/GameCubePane.h | 1 + Source/Core/DolphinQt/Settings/PathPane.cpp | 1 + Source/Core/DolphinQt/Settings/WiiPane.cpp | 17 ++++- 9 files changed, 125 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index defebcd426..d4f06da99a 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -111,6 +111,21 @@ const Info& GetInfoForGCIPathOverride(ExpansionInterface::Slot slot const Info MAIN_MEMORY_CARD_SIZE{{System::Main, "Core", "MemoryCardSize"}, -1}; +const Info MAIN_SLOT_A_SD_CARD_PATH{{System::Main, "Core", "SlotASDCardPath"}, ""}; +const Info MAIN_SLOT_B_SD_CARD_PATH{{System::Main, "Core", "SlotBSDCardPath"}, ""}; +const Info MAIN_SP2_SD_CARD_PATH{{System::Main, "Core", "SP2SDCardPath"}, ""}; +const Info& GetInfoForSDCardPath(ExpansionInterface::Slot slot) +{ + ASSERT(slot != ExpansionInterface::Slot::SP1); + static constexpr Common::EnumMap*, ExpansionInterface::MAX_SLOT> infos{ + &MAIN_SLOT_A_SD_CARD_PATH, + &MAIN_SLOT_B_SD_CARD_PATH, + nullptr, + &MAIN_SP2_SD_CARD_PATH, + }; + return *infos[slot]; +} + const Info MAIN_SLOT_A{ {System::Main, "Core", "SlotA"}, ExpansionInterface::EXIDeviceType::MemoryCardFolder}; const Info MAIN_SLOT_B{{System::Main, "Core", "SlotB"}, diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index a1d334bc18..6459eb19d5 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -87,6 +87,10 @@ extern const Info MAIN_GCI_FOLDER_A_PATH_OVERRIDE; extern const Info MAIN_GCI_FOLDER_B_PATH_OVERRIDE; const Info& GetInfoForGCIPathOverride(ExpansionInterface::Slot slot); extern const Info MAIN_MEMORY_CARD_SIZE; +extern const Info MAIN_SLOT_A_SD_CARD_PATH; +extern const Info MAIN_SLOT_B_SD_CARD_PATH; +extern const Info MAIN_SP2_SD_CARD_PATH; +const Info& GetInfoForSDCardPath(ExpansionInterface::Slot slot); extern const Info MAIN_SLOT_A; extern const Info MAIN_SLOT_B; extern const Info MAIN_SERIAL_PORT_1; diff --git a/Source/Core/Core/HW/EXI/EXI_Device.cpp b/Source/Core/Core/HW/EXI/EXI_Device.cpp index 21b5a49313..6b90bff9bc 100644 --- a/Source/Core/Core/HW/EXI/EXI_Device.cpp +++ b/Source/Core/Core/HW/EXI/EXI_Device.cpp @@ -164,7 +164,7 @@ std::unique_ptr EXIDevice_Create(Core::System& system, const EXIDevi break; case EXIDeviceType::SD: - result = std::make_unique(system); + result = std::make_unique(system, channel_num); break; case EXIDeviceType::AMBaseboard: diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSD.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceSD.cpp index 383cfde7b7..7fb66eaa26 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSD.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSD.cpp @@ -9,16 +9,30 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" +#include "Common/Config/Config.h" #include "Common/FileUtil.h" #include "Common/Hash.h" #include "Common/IOFile.h" #include "Common/Logging/Log.h" +#include "Core/Config/MainSettings.h" + namespace ExpansionInterface { -CEXISD::CEXISD(Core::System& system) : IEXIDevice(system) +CEXISD::CEXISD(Core::System& system, int channel_num) : IEXIDevice(system) { - const std::string filename = File::GetUserPath(D_GCUSER_IDX) + "sdcard.bin"; + ASSERT_MSG(EXPANSIONINTERFACE, 0 <= channel_num && channel_num <= 2, + "Trying to create invalid SD card index {}.", channel_num); + + // TODO: I don't like using channel_num here; Slot would be better + std::string filename; + if (channel_num == 0) + filename = Config::Get(Config::MAIN_SLOT_A_SD_CARD_PATH); + else if (channel_num == 1) + filename = Config::Get(Config::MAIN_SLOT_B_SD_CARD_PATH); + else + filename = Config::Get(Config::MAIN_SP2_SD_CARD_PATH); + m_card.Open(filename, "r+b"); if (!m_card) { diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSD.h b/Source/Core/Core/HW/EXI/EXI_DeviceSD.h index 61dd8a16f8..9e3626fac7 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSD.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSD.h @@ -21,7 +21,7 @@ namespace ExpansionInterface class CEXISD final : public IEXIDevice { public: - explicit CEXISD(Core::System& system); + explicit CEXISD(Core::System& system, int channel_num); void ImmWrite(u32 data, u32 size) override; u32 ImmRead(u32 size) override; diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 199ac51e73..3e617b5052 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -342,7 +342,8 @@ void GameCubePane::UpdateButton(ExpansionInterface::Slot slot) has_config = (device == ExpansionInterface::EXIDeviceType::MemoryCard || device == ExpansionInterface::EXIDeviceType::MemoryCardFolder || device == ExpansionInterface::EXIDeviceType::AGP || - device == ExpansionInterface::EXIDeviceType::Microphone); + device == ExpansionInterface::EXIDeviceType::Microphone || + device == ExpansionInterface::EXIDeviceType::SD); const bool hide_memory_card = device != ExpansionInterface::EXIDeviceType::MemoryCard || Config::IsDefaultMemcardPathConfigured(slot); const bool hide_gci_path = device != ExpansionInterface::EXIDeviceType::MemoryCardFolder || @@ -372,7 +373,7 @@ void GameCubePane::UpdateButton(ExpansionInterface::Slot slot) device == ExpansionInterface::EXIDeviceType::ModemTapServer); break; case ExpansionInterface::Slot::SP2: - has_config = false; // TODO + has_config = (device == ExpansionInterface::EXIDeviceType::SD); break; } @@ -395,6 +396,9 @@ void GameCubePane::OnConfigPressed(ExpansionInterface::Slot slot) case ExpansionInterface::EXIDeviceType::AGP: BrowseAGPRom(slot); return; + case ExpansionInterface::EXIDeviceType::SD: + BrowseSDCard(slot); + return; case ExpansionInterface::EXIDeviceType::Microphone: { // TODO: convert MappingWindow to use Slot? @@ -690,6 +694,71 @@ void GameCubePane::SetAGPRom(ExpansionInterface::Slot slot, const QString& filen LoadSettings(); } +void GameCubePane::BrowseSDCard(ExpansionInterface::Slot slot) +{ + ASSERT(slot != ExpansionInterface::Slot::SP1); + + QString filename = DolphinFileDialog::getSaveFileName( + this, tr("Choose a file to open"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)), + tr("SD Card Image (*.raw)"), 0, QFileDialog::DontConfirmOverwrite); + + if (filename.isEmpty()) + return; + + QString path_abs = QFileInfo(filename).absoluteFilePath(); + + for (ExpansionInterface::Slot other_slot : ExpansionInterface::SLOTS) + { + if (other_slot == slot || other_slot == ExpansionInterface::Slot::SP1) + continue; + + bool other_slot_sd = m_slot_combos[other_slot]->currentData().toInt() == + static_cast(ExpansionInterface::EXIDeviceType::SD); + if (other_slot_sd) + { + QString path_other = + QFileInfo(QString::fromStdString(Config::Get(Config::GetInfoForSDCardPath(other_slot)))) + .absoluteFilePath(); + + if (path_abs == path_other) + { + ModalMessageBox::critical( + this, tr("Error"), + 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_wii = + QFileInfo(QString::fromStdString(Config::Get(Config::MAIN_WII_SD_CARD_IMAGE_PATH))) + .absoluteFilePath(); + if (path_abs == path_wii) + { + ModalMessageBox::critical(this, tr("Error"), + tr("The same file can't be used in multiple slots; it is already " + "used by the Wii SD slot.")); + return; + } + + QString path_old = + QFileInfo(QString::fromStdString(Config::Get(Config::GetInfoForSDCardPath(slot)))) + .absoluteFilePath(); + + Config::SetBase(Config::GetInfoForSDCardPath(slot), path_abs.toStdString()); + + auto& system = Core::System::GetInstance(); + if (Core::IsRunning(system) && path_abs != path_old) + { + // ChangeDevice unplugs the device for 1 second, which means that games should notice that + // the path has changed and thus the sd card contents have changed + // (not sure if anything actually checks for this) + Core::System::GetInstance().GetExpansionInterface().ChangeDevice( + slot, ExpansionInterface::EXIDeviceType::SD); + } +} + void GameCubePane::BrowseGBABios() { QString file = QDir::toNativeSeparators(DolphinFileDialog::getOpenFileName( diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.h b/Source/Core/DolphinQt/Settings/GameCubePane.h index 35862e2f57..a52b83d100 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.h +++ b/Source/Core/DolphinQt/Settings/GameCubePane.h @@ -47,6 +47,7 @@ private: bool SetGCIFolder(ExpansionInterface::Slot slot, const QString& path); void BrowseAGPRom(ExpansionInterface::Slot slot); void SetAGPRom(ExpansionInterface::Slot slot, const QString& filename); + void BrowseSDCard(ExpansionInterface::Slot slot); void BrowseGBABios(); void BrowseGBARom(size_t index); void SaveRomPathChanged(); diff --git a/Source/Core/DolphinQt/Settings/PathPane.cpp b/Source/Core/DolphinQt/Settings/PathPane.cpp index 8d91e31d50..ea199a1799 100644 --- a/Source/Core/DolphinQt/Settings/PathPane.cpp +++ b/Source/Core/DolphinQt/Settings/PathPane.cpp @@ -19,6 +19,7 @@ #include "Core/Config/UISettings.h" #include "DolphinQt/QtUtils/DolphinFileDialog.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/Settings.h" diff --git a/Source/Core/DolphinQt/Settings/WiiPane.cpp b/Source/Core/DolphinQt/Settings/WiiPane.cpp index d7ae90b815..ffdfba85ef 100644 --- a/Source/Core/DolphinQt/Settings/WiiPane.cpp +++ b/Source/Core/DolphinQt/Settings/WiiPane.cpp @@ -513,8 +513,21 @@ void WiiPane::BrowseSDRaw() void WiiPane::SetSDRaw(const QString& path) { - Config::SetBase(Config::MAIN_WII_SD_CARD_IMAGE_PATH, path.toStdString()); - SignalBlocking(m_sd_raw_edit)->setText(path); + const auto str = path.toStdString(); + if (str == Config::Get(Config::MAIN_SLOT_A_SD_CARD_PATH) || + str == Config::Get(Config::MAIN_SLOT_B_SD_CARD_PATH) || + str == Config::Get(Config::MAIN_SP2_SD_CARD_PATH)) + { + ModalMessageBox::critical(this, tr("Error"), + tr("The same file can't be used in multiple slots.")); + SignalBlocking(m_sd_raw_edit) + ->setText(QString::fromStdString(Config::Get(Config::MAIN_WII_SD_CARD_IMAGE_PATH))); + } + else + { + Config::SetBase(Config::MAIN_WII_SD_CARD_IMAGE_PATH, str); + SignalBlocking(m_sd_raw_edit)->setText(path); + } } void WiiPane::BrowseSDSyncFolder()