From deb9964333065ade4fc5461edbb078d31c39ba21 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Tue, 18 Jan 2022 23:48:39 +0100 Subject: [PATCH] Core: Unify handling of raw memory card path. --- Source/Core/Core/Config/MainSettings.cpp | 47 ++++++++++++++++++ Source/Core/Core/Config/MainSettings.h | 4 ++ .../Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp | 16 ++---- .../Core/HW/GCMemcard/GCMemcardDirectory.cpp | 5 +- .../Core/HW/GCMemcard/GCMemcardDirectory.h | 4 +- .../Core/Core/HW/GCMemcard/GCMemcardRaw.cpp | 49 ------------------- Source/Core/Core/HW/GCMemcard/GCMemcardRaw.h | 2 - Source/Core/Core/Movie.cpp | 12 +++-- Source/Core/Core/NetPlayServer.cpp | 19 +++---- 9 files changed, 76 insertions(+), 82 deletions(-) diff --git a/Source/Core/Core/Config/MainSettings.cpp b/Source/Core/Core/Config/MainSettings.cpp index 9ec9555021..d7d146e3e2 100644 --- a/Source/Core/Core/Config/MainSettings.cpp +++ b/Source/Core/Core/Config/MainSettings.cpp @@ -20,6 +20,7 @@ #include "Core/Config/DefaultLocale.h" #include "Core/HW/EXI/EXI.h" #include "Core/HW/EXI/EXI_Device.h" +#include "Core/HW/GCMemcard/GCMemcard.h" #include "Core/HW/HSP/HSP_Device.h" #include "Core/HW/Memmap.h" #include "Core/HW/SI/SI_Device.h" @@ -571,4 +572,50 @@ std::string GetBootROMPath(const std::string& region_directory) return File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + region_directory + DIR_SEP GC_IPL; return path; } + +std::string GetMemcardPath(ExpansionInterface::Slot slot, DiscIO::Region region, u16 size_mb) +{ + return GetMemcardPath(Config::Get(GetInfoForMemcardPath(slot)), slot, region, size_mb); +} + +std::string GetMemcardPath(std::string configured_filename, ExpansionInterface::Slot slot, + DiscIO::Region region, u16 size_mb) +{ + const std::string region_dir = Config::GetDirectoryForRegion(Config::ToGameCubeRegion(region)); + const std::string blocks_string = size_mb < Memcard::MBIT_SIZE_MEMORY_CARD_2043 ? + fmt::format(".{}", Memcard::MbitToFreeBlocks(size_mb)) : + ""; + + if (configured_filename.empty()) + { + // Use default memcard path if there is no user defined one. + const bool is_slot_a = slot == ExpansionInterface::Slot::A; + return fmt::format("{}{}.{}{}.raw", File::GetUserPath(D_GCUSER_IDX), + is_slot_a ? GC_MEMCARDA : GC_MEMCARDB, region_dir, blocks_string); + } + + // Custom path is expected to be stored in the form of + // "/path/to/file.{region_code}.raw" + // with an arbitrary but supported region code. + // Try to extract and replace that region code. + // If there's no region code just insert one before the extension. + + std::string dir; + std::string name; + std::string ext; + UnifyPathSeparators(configured_filename); + SplitPath(configured_filename, &dir, &name, &ext); + + constexpr std::string_view us_region = "." USA_DIR; + constexpr std::string_view jp_region = "." JAP_DIR; + constexpr std::string_view eu_region = "." EUR_DIR; + if (StringEndsWith(name, us_region)) + name = name.substr(0, name.size() - us_region.size()); + else if (StringEndsWith(name, jp_region)) + name = name.substr(0, name.size() - jp_region.size()); + else if (StringEndsWith(name, eu_region)) + name = name.substr(0, name.size() - eu_region.size()); + + return fmt::format("{}{}.{}{}{}", dir, name, region_dir, blocks_string, ext); +} } // namespace Config diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index 413f595dd4..e1b538f2b6 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -338,4 +338,8 @@ DiscIO::Region ToGameCubeRegion(DiscIO::Region region); // The region argument must be valid for GameCube (i.e. must not be NTSC-K) const char* GetDirectoryForRegion(DiscIO::Region region); std::string GetBootROMPath(const std::string& region_directory); +std::string GetMemcardPath(ExpansionInterface::Slot slot, DiscIO::Region region, + u16 size_mb = 0x80); +std::string GetMemcardPath(std::string configured_filename, ExpansionInterface::Slot slot, + DiscIO::Region region, u16 size_mb = 0x80); } // namespace Config diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp index 2baf002ca1..83263ed04d 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceMemoryCard.cpp @@ -188,7 +188,7 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data) if (!file_info.Exists()) { if (migrate) // first use of memcard folder, migrate automatically - MigrateFromMemcardFile(dir_path + DIR_SEP, m_card_slot); + MigrateFromMemcardFile(dir_path + DIR_SEP, m_card_slot, SConfig::GetInstance().m_region); else File::CreateFullPath(dir_path + DIR_SEP); } @@ -198,7 +198,7 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data) { PanicAlertFmtT("{0} was not a directory, moved to *.original", dir_path); if (migrate) - MigrateFromMemcardFile(dir_path + DIR_SEP, m_card_slot); + MigrateFromMemcardFile(dir_path + DIR_SEP, m_card_slot, SConfig::GetInstance().m_region); else File::CreateFullPath(dir_path + DIR_SEP); } @@ -218,22 +218,16 @@ void CEXIMemoryCard::SetupGciFolder(const Memcard::HeaderData& header_data) void CEXIMemoryCard::SetupRawMemcard(u16 size_mb) { - std::string filename = Config::Get(Config::GetInfoForMemcardPath(m_card_slot)); + std::string filename; if (Movie::IsPlayingInput() && Movie::IsConfigSaved() && Movie::IsUsingMemcard(m_card_slot) && Movie::IsStartingFromClearSave()) { filename = File::GetUserPath(D_GCUSER_IDX) + fmt::format("Movie{}.raw", s_card_short_names[m_card_slot]); } - - const std::string region_dir = - Config::GetDirectoryForRegion(Config::ToGameCubeRegion(SConfig::GetInstance().m_region)); - MemoryCard::CheckPath(filename, region_dir, m_card_slot); - - if (size_mb < Memcard::MBIT_SIZE_MEMORY_CARD_2043) + else { - filename.insert(filename.find_last_of('.'), - fmt::format(".{}", Memcard::MbitToFreeBlocks(size_mb))); + filename = Config::GetMemcardPath(m_card_slot, SConfig::GetInstance().m_region, size_mb); } m_memory_card = std::make_unique(filename, m_card_slot, size_mb); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp index b65d7f0d03..f5a46046c0 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.cpp @@ -705,10 +705,11 @@ void GCMemcardDirectory::DoState(PointerWrap& p) } } -void MigrateFromMemcardFile(const std::string& directory_name, ExpansionInterface::Slot card_slot) +void MigrateFromMemcardFile(const std::string& directory_name, ExpansionInterface::Slot card_slot, + DiscIO::Region region) { File::CreateFullPath(directory_name); - std::string ini_memcard = Config::Get(Config::GetInfoForMemcardPath(card_slot)); + const std::string ini_memcard = Config::GetMemcardPath(card_slot, region); if (File::Exists(ini_memcard)) { auto [error_code, memcard] = Memcard::GCMemcard::Open(ini_memcard.c_str()); diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.h b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.h index fa9ae44110..5b02700a61 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardDirectory.h @@ -12,10 +12,12 @@ #include "Core/HW/GCMemcard/GCIFile.h" #include "Core/HW/GCMemcard/GCMemcard.h" #include "Core/HW/GCMemcard/GCMemcardBase.h" +#include "DiscIO/Enums.h" // Uncomment this to write the system data of the memorycard from directory to disc //#define _WRITE_MC_HEADER 1 -void MigrateFromMemcardFile(const std::string& directory_name, ExpansionInterface::Slot card_slot); +void MigrateFromMemcardFile(const std::string& directory_name, ExpansionInterface::Slot card_slot, + DiscIO::Region region); class GCMemcardDirectory : public MemoryCardBase { diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.cpp b/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.cpp index 923f88bc69..23bca41df1 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.cpp +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.cpp @@ -90,55 +90,6 @@ MemoryCard::~MemoryCard() } } -void MemoryCard::CheckPath(std::string& memcardPath, const std::string& gameRegion, - ExpansionInterface::Slot card_slot) -{ - bool is_slot_a = card_slot == ExpansionInterface::Slot::A; - std::string ext("." + gameRegion + ".raw"); - if (memcardPath.empty()) - { - // Use default memcard path if there is no user defined name - std::string defaultFilename = is_slot_a ? GC_MEMCARDA : GC_MEMCARDB; - memcardPath = File::GetUserPath(D_GCUSER_IDX) + defaultFilename + ext; - } - else - { - std::string filename = memcardPath; - std::string region = filename.substr(filename.size() - 7, 3); - bool hasregion = false; - hasregion |= region.compare(USA_DIR) == 0; - hasregion |= region.compare(JAP_DIR) == 0; - hasregion |= region.compare(EUR_DIR) == 0; - if (!hasregion) - { - // filename doesn't have region in the extension - if (File::Exists(filename)) - { - // If the old file exists we are polite and ask if we should copy it - std::string oldFilename = filename; - filename.replace(filename.size() - 4, 4, ext); - if (PanicYesNoFmtT("Memory Card filename in Slot {0} is incorrect\n" - "Region not specified\n\n" - "Slot {1} path was changed to\n" - "{2}\n" - "Would you like to copy the old file to this new location?\n", - is_slot_a ? 'A' : 'B', is_slot_a ? 'A' : 'B', filename)) - { - if (!File::Copy(oldFilename, filename)) - PanicAlertFmtT("Copy failed"); - } - } - memcardPath = filename; // Always correct the path! - } - else if (region.compare(gameRegion) != 0) - { - // filename has region, but it's not == gameRegion - // Just set the correct filename, the EXI Device will create it if it doesn't exist - memcardPath = filename.replace(filename.size() - ext.size(), ext.size(), ext); - } - } -} - void MemoryCard::FlushThread() { if (!Config::Get(Config::SESSION_SAVE_DATA_WRITABLE)) diff --git a/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.h b/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.h index b8486c13a3..c6c85313e8 100644 --- a/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.h +++ b/Source/Core/Core/HW/GCMemcard/GCMemcardRaw.h @@ -20,8 +20,6 @@ public: MemoryCard(const std::string& filename, ExpansionInterface::Slot card_slot, u16 size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_2043); ~MemoryCard(); - static void CheckPath(std::string& memcardPath, const std::string& gameRegion, - ExpansionInterface::Slot slot); void FlushThread(); void MakeDirty(); diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index 938a17f2eb..f988fc7e65 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -1479,6 +1479,9 @@ void GetSettings() } else { + const auto raw_memcard_exists = [](ExpansionInterface::Slot card_slot) { + return File::Exists(Config::GetMemcardPath(card_slot, SConfig::GetInstance().m_region)); + }; const auto gci_folder_has_saves = [](ExpansionInterface::Slot card_slot) { const auto [path, migrate] = ExpansionInterface::CEXIMemoryCard::GetGCIFolderPath( card_slot, ExpansionInterface::AllowMovieFolder::No); @@ -1486,11 +1489,10 @@ void GetSettings() return number_of_saves > 0; }; - s_bClearSave = - !(slot_a_has_raw_memcard && File::Exists(Config::Get(Config::MAIN_MEMCARD_A_PATH))) && - !(slot_b_has_raw_memcard && File::Exists(Config::Get(Config::MAIN_MEMCARD_B_PATH))) && - !(slot_a_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::A)) && - !(slot_b_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::B)); + s_bClearSave = !(slot_a_has_raw_memcard && raw_memcard_exists(ExpansionInterface::Slot::A)) && + !(slot_b_has_raw_memcard && raw_memcard_exists(ExpansionInterface::Slot::B)) && + !(slot_a_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::A)) && + !(slot_b_has_gci_folder && gci_folder_has_saves(ExpansionInterface::Slot::B)); } s_memcards |= (slot_a_has_raw_memcard || slot_a_has_gci_folder) << 0; s_memcards |= (slot_b_has_raw_memcard || slot_b_has_gci_folder) << 1; diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp index cc1d9e6280..0ed2290b0d 100644 --- a/Source/Core/Core/NetPlayServer.cpp +++ b/Source/Core/Core/NetPlayServer.cpp @@ -1665,8 +1665,8 @@ bool NetPlayServer::SyncSaveData() if (save_count == 0) return true; - const std::string region = - Config::GetDirectoryForRegion(Config::ToGameCubeRegion(game->GetRegion())); + const auto game_region = game->GetRegion(); + const std::string region = Config::GetDirectoryForRegion(Config::ToGameCubeRegion(game_region)); for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS) { @@ -1674,17 +1674,12 @@ bool NetPlayServer::SyncSaveData() if (m_settings.m_EXIDevice[slot] == ExpansionInterface::EXIDeviceType::MemoryCard) { - std::string path = Config::Get(Config::GetInfoForMemcardPath(slot)); - - MemoryCard::CheckPath(path, region, slot); - const int size_override = m_settings.m_MemcardSizeOverride; - if (size_override >= 0 && size_override <= 4) - { - path.insert(path.find_last_of('.'), - fmt::format(".{}", Memcard::MbitToFreeBlocks(Memcard::MBIT_SIZE_MEMORY_CARD_59 - << size_override))); - } + const u16 card_size_mbits = + size_override >= 0 && size_override <= 4 ? + static_cast(Memcard::MBIT_SIZE_MEMORY_CARD_59 << size_override) : + Memcard::MBIT_SIZE_MEMORY_CARD_2043; + const std::string path = Config::GetMemcardPath(slot, game_region, card_size_mbits); sf::Packet pac; pac << MessageID::SyncSaveData;