diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 29810239b..ee062af60 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -1182,12 +1182,6 @@ void Achievements::GameChanged(CDImage* image) bool Achievements::IdentifyGame(CDImage* image) { - if (s_state.game_path == (image ? std::string_view(image->GetPath()) : std::string_view())) - { - WARNING_LOG("Game path is unchanged."); - return false; - } - std::optional game_hash; if (image) { diff --git a/src/core/game_list.cpp b/src/core/game_list.cpp index 111a16ca5..b99c69aa8 100644 --- a/src/core/game_list.cpp +++ b/src/core/game_list.cpp @@ -358,10 +358,7 @@ bool GameList::GetDiscListEntry(const std::string& path, Entry* entry) if (cdi->HasSubImages()) { entry->type = EntryType::Playlist; - - std::string image_title(cdi->GetMetadata("title")); - if (!image_title.empty()) - entry->title = std::move(image_title); + entry->title = Path::GetFileTitle(FileSystem::GetDisplayNameFromPath(path)); // get the size of all the subimages const u32 subimage_count = cdi->GetSubImageCount(); diff --git a/src/core/system.cpp b/src/core/system.cpp index b742afc34..f67c01387 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -200,7 +200,7 @@ static bool SwitchDiscFromSet(s32 direction, bool show_osd_message); static void UpdateControllers(); static void ResetControllers(); -static void UpdatePerGameMemoryCards(); +static void ReloadMemoryCardsFromGameChange(); static std::unique_ptr GetMemoryCardForSlot(u32 slot, MemoryCardType type); static void UpdateMultitaps(); @@ -498,7 +498,10 @@ bool System::ProcessStartup(Error* error) #ifdef __linux__ // Running DuckStation out of /usr/lib is not supported and makes no sense. - if (std::memcmp(EmuFolders::AppRoot.data(), "/usr/""lib", 8) == 0) + if (std::memcmp(EmuFolders::AppRoot.data(), + "/usr/" + "lib", + 8) == 0) return false; #endif @@ -2984,8 +2987,7 @@ bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bo } // ensure the correct card is loaded - if (g_settings.HasAnyPerGameMemoryCards()) - UpdatePerGameMemoryCards(); + ReloadMemoryCardsFromGameChange(); ClearMemorySaveStates(false, false); @@ -3812,17 +3814,12 @@ std::unique_ptr System::GetMemoryCardForSlot(u32 slot, MemoryCardTyp else { const std::string_view game_title = (s_state.running_game_custom_title || !s_state.running_game_entry) ? - s_state.running_game_title : + std::string_view(s_state.running_game_title) : s_state.running_game_entry->GetSaveTitle(); std::string card_path; - // Playlist - use title if different. - if (HasMediaSubImages() && s_state.running_game_entry && s_state.running_game_title != game_title) - { - card_path = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(s_state.running_game_title), slot); - } // Multi-disc game - use disc set name. - else if (s_state.running_game_entry && s_state.running_game_entry->disc_set) + if (s_state.running_game_entry && s_state.running_game_entry->disc_set) { card_path = g_settings.GetGameMemoryCardPath( Path::SanitizeFileName(s_state.running_game_entry->disc_set->GetSaveTitle()), slot); @@ -3912,8 +3909,14 @@ void System::UpdateMemoryCardTypes() } } -void System::UpdatePerGameMemoryCards() +void System::ReloadMemoryCardsFromGameChange() { + if (!g_settings.HasAnyPerGameMemoryCards()) + return; + + Host::AddIconOSDMessage("ReloadMemoryCardsFromGameChange", ICON_PF_MEMORY_CARD, + TRANSLATE_STR("System", "Game changed, reloading memory cards."), Host::OSD_INFO_DURATION); + for (u32 i = 0; i < NUM_CONTROLLER_AND_CARD_PORTS; i++) { const MemoryCardType type = g_settings.memory_card_types[i]; @@ -4097,13 +4100,7 @@ bool System::InsertMedia(const char* path) s_state.running_game_title, s_state.running_game_serial), Host::OSD_INFO_DURATION); - if (g_settings.HasAnyPerGameMemoryCards()) - { - Host::AddIconOSDMessage("ReloadMemoryCardsFromGameChange", ICON_PF_MEMORY_CARD, - TRANSLATE_STR("System", "Game changed, reloading memory cards."), Host::OSD_INFO_DURATION); - UpdatePerGameMemoryCards(); - } - + ReloadMemoryCardsFromGameChange(); return true; } @@ -4115,9 +4112,6 @@ void System::RemoveMedia() void System::UpdateRunningGame(const std::string& path, CDImage* image, bool booting) { - if (!booting && s_state.running_game_path == path) - return; - const std::string prev_serial = std::move(s_state.running_game_serial); s_state.running_game_path.clear(); @@ -4195,16 +4189,6 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo if (s_state.running_game_title.empty() && !CDImage::IsDeviceName(path.c_str())) s_state.running_game_title = Path::GetFileTitle(FileSystem::GetDisplayNameFromPath(path)); } - - if (image->HasSubImages()) - { - std::string image_title = image->GetMetadata("title"); - if (!image_title.empty()) - { - s_state.running_game_title = std::move(image_title); - s_state.running_game_custom_title = false; - } - } } else { @@ -4296,29 +4280,13 @@ u32 System::GetMediaSubImageIndex() return cdi ? cdi->GetCurrentSubImage() : 0; } -u32 System::GetMediaSubImageIndexForTitle(std::string_view title) -{ - const CDImage* cdi = CDROM::GetMedia(); - if (!cdi) - return 0; - - const u32 count = cdi->GetSubImageCount(); - for (u32 i = 0; i < count; i++) - { - if (title == cdi->GetSubImageMetadata(i, "title")) - return i; - } - - return std::numeric_limits::max(); -} - std::string System::GetMediaSubImageTitle(u32 index) { const CDImage* cdi = CDROM::GetMedia(); if (!cdi) return {}; - return cdi->GetSubImageMetadata(index, "title"); + return cdi->GetSubImageTitle(index); } bool System::SwitchMediaSubImage(u32 index) @@ -4338,9 +4306,10 @@ bool System::SwitchMediaSubImage(u32 index) { const DiscRegion region = GameList::GetCustomRegionForPath(image->GetPath()).value_or(GetRegionForImage(image.get())); - subimage_title = image->GetSubImageMetadata(index, "title"); - title = image->GetMetadata("title"); + subimage_title = image->GetSubImageTitle(index); + title = FileSystem::GetDisplayNameFromPath(image->GetPath()); UpdateRunningGame(image->GetPath(), image.get(), false); + ReloadMemoryCardsFromGameChange(); okay = CDROM::InsertMedia(image, region, s_state.running_game_serial, s_state.running_game_title, &error); } if (!okay) @@ -5781,22 +5750,24 @@ std::string System::GetGameMemoryCardPath(std::string_view serial, std::string_v case MemoryCardType::PerGameTitle: { + const std::string custom_title = GameList::GetCustomTitleForPath(path); const GameDatabase::Entry* entry = GameDatabase::GetEntryForSerial(serial); - if (entry) - { - ret = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(entry->GetSaveTitle()), slot); + const std::string_view game_title = + (!custom_title.empty() || !entry) ? std::string_view(custom_title) : entry->GetSaveTitle(); - // Use disc set name if there isn't a per-disc card present. + // Multi-disc game - use disc set name. + if (entry && entry->disc_set) + ret = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(entry->disc_set->GetSaveTitle()), slot); + + // But prefer a disc-specific card if one already exists. + std::string disc_card_path = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(game_title), slot); + if (disc_card_path != ret) + { const bool global_use_playlist_title = Host::GetBaseBoolSettingValue(section, "UsePlaylistTitle", true); const bool use_playlist_title = ini ? ini->GetBoolValue(section, "UsePlaylistTitle", global_use_playlist_title) : global_use_playlist_title; - if (entry->disc_set && use_playlist_title && !FileSystem::FileExists(ret.c_str())) - ret = g_settings.GetGameMemoryCardPath(Path::SanitizeFileName(entry->disc_set->GetSaveTitle()), slot); - } - else - { - ret = g_settings.GetGameMemoryCardPath( - Path::SanitizeFileName(Path::GetFileTitle(FileSystem::GetDisplayNameFromPath(path))), slot); + if (ret.empty() || !use_playlist_title || FileSystem::FileExists(disc_card_path.c_str())) + ret = std::move(disc_card_path); } } break; diff --git a/src/core/system.h b/src/core/system.h index 7dcbb5738..1b22986d0 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -323,9 +323,6 @@ u32 GetMediaSubImageCount(); /// Returns the current image from the media/disc playlist. u32 GetMediaSubImageIndex(); -/// Returns the index of the specified path in the playlist, or UINT32_MAX if it does not exist. -u32 GetMediaSubImageIndexForTitle(std::string_view title); - /// Returns the path to the specified playlist index. std::string GetMediaSubImageTitle(u32 index); diff --git a/src/duckstation-qt/mainwindow.cpp b/src/duckstation-qt/mainwindow.cpp index d5cb28525..e588eed65 100644 --- a/src/duckstation-qt/mainwindow.cpp +++ b/src/duckstation-qt/mainwindow.cpp @@ -1287,6 +1287,7 @@ void MainWindow::onChangeDiscMenuAboutToShow() if (!s_system_valid) return; + // NOTE: This is terrible and a race condition. But nobody should be using m3u files anyway. if (System::HasMediaSubImages()) { const u32 count = System::GetMediaSubImageCount(); diff --git a/src/util/cd_image.cpp b/src/util/cd_image.cpp index 93648ab9a..caa50ca61 100644 --- a/src/util/cd_image.cpp +++ b/src/util/cd_image.cpp @@ -304,18 +304,6 @@ bool CDImage::HasSubchannelData() const return false; } -std::string CDImage::GetMetadata(std::string_view type) const -{ - std::string result; - if (type == "title") - { - const std::string display_name(FileSystem::GetDisplayNameFromPath(m_filename)); - result = Path::StripExtension(display_name); - } - - return result; -} - bool CDImage::HasSubImages() const { return false; @@ -336,7 +324,7 @@ bool CDImage::SwitchSubImage(u32 index, Error* error) return false; } -std::string CDImage::GetSubImageMetadata(u32 index, std::string_view type) const +std::string CDImage::GetSubImageTitle(u32 index) const { return {}; } diff --git a/src/util/cd_image.h b/src/util/cd_image.h index 2cc792b5b..e8e10a0f9 100644 --- a/src/util/cd_image.h +++ b/src/util/cd_image.h @@ -290,9 +290,6 @@ public: // Reads a single sector from an index. virtual bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) = 0; - // Retrieve image metadata. - virtual std::string GetMetadata(std::string_view type) const; - // Returns true if this image type has sub-images (e.g. m3u). virtual bool HasSubImages() const; @@ -306,7 +303,7 @@ public: virtual bool SwitchSubImage(u32 index, Error* error); // Retrieve sub-image metadata. - virtual std::string GetSubImageMetadata(u32 index, std::string_view type) const; + virtual std::string GetSubImageTitle(u32 index) const; // Returns true if the source supports precaching, which may be more optimal than an in-memory copy. virtual PrecacheResult Precache(ProgressCallback* progress = ProgressCallback::NullProgressCallback); diff --git a/src/util/cd_image_m3u.cpp b/src/util/cd_image_m3u.cpp index 60d67c995..fdbd1a51e 100644 --- a/src/util/cd_image_m3u.cpp +++ b/src/util/cd_image_m3u.cpp @@ -33,7 +33,7 @@ public: bool HasSubImages() const override; u32 GetSubImageCount() const override; u32 GetCurrentSubImage() const override; - std::string GetSubImageMetadata(u32 index, std::string_view type) const override; + std::string GetSubImageTitle(u32 index) const override; bool SwitchSubImage(u32 index, Error* error) override; protected: @@ -159,17 +159,13 @@ bool CDImageM3u::SwitchSubImage(u32 index, Error* error) return true; } -std::string CDImageM3u::GetSubImageMetadata(u32 index, std::string_view type) const +std::string CDImageM3u::GetSubImageTitle(u32 index) const { - if (index >= m_entries.size()) - return {}; - - if (type == "title") - return m_entries[index].title; - else if (type == "file_title") - return std::string(Path::GetFileTitle(m_entries[index].filename)); + std::string ret; + if (index < m_entries.size()) + ret = m_entries[index].title; - return CDImage::GetSubImageMetadata(index, type); + return ret; } bool CDImageM3u::ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) diff --git a/src/util/cd_image_pbp.cpp b/src/util/cd_image_pbp.cpp index e79198e9a..20ccb6464 100644 --- a/src/util/cd_image_pbp.cpp +++ b/src/util/cd_image_pbp.cpp @@ -139,8 +139,7 @@ public: u32 GetSubImageCount() const override; u32 GetCurrentSubImage() const override; bool SwitchSubImage(u32 index, Error* error) override; - std::string GetMetadata(std::string_view type) const override; - std::string GetSubImageMetadata(u32 index, std::string_view type) const override; + std::string GetSubImageTitle(u32 index) const override; protected: bool ReadSectorFromIndex(void* buffer, const Index& index, LBA lba_in_index) override; @@ -336,7 +335,8 @@ bool CDImagePBP::LoadSFOTable(Error* error) } else { - Error::SetStringFmt(error, "Unhandled SFO data type 0x{:04X} found in SFO table for entry {}", m_sfo_index_table[i].data_type, i); + Error::SetStringFmt(error, "Unhandled SFO data type 0x{:04X} found in SFO table for entry {}", + m_sfo_index_table[i].data_type, i); return false; } } @@ -871,18 +871,6 @@ bool CDImagePBP::HasSubImages() const return m_disc_offsets.size() > 1; } -std::string CDImagePBP::GetMetadata(std::string_view type) const -{ - if (type == "title") - { - const std::string* title = LookupStringSFOTableEntry("TITLE", m_sfo_table); - if (title && !title->empty()) - return *title; - } - - return CDImage::GetMetadata(type); -} - u32 CDImagePBP::GetSubImageCount() const { return static_cast(m_disc_offsets.size()); @@ -909,16 +897,15 @@ bool CDImagePBP::SwitchSubImage(u32 index, Error* error) return true; } -std::string CDImagePBP::GetSubImageMetadata(u32 index, std::string_view type) const +std::string CDImagePBP::GetSubImageTitle(u32 index) const { - if (type == "title") - { - const std::string* title = LookupStringSFOTableEntry("TITLE", m_sfo_table); - if (title && !title->empty()) - return fmt::format("{} (Disc {})", *title, index + 1); - } + std::string ret; + + const std::string* title = LookupStringSFOTableEntry("TITLE", m_sfo_table); + if (title && !title->empty()) + ret = fmt::format("{} (Disc {})", *title, index + 1); - return CDImage::GetSubImageMetadata(index, type); + return ret; } s64 CDImagePBP::GetSizeOnDisk() const diff --git a/src/util/cd_image_ppf.cpp b/src/util/cd_image_ppf.cpp index c895ce882..bccac200a 100644 --- a/src/util/cd_image_ppf.cpp +++ b/src/util/cd_image_ppf.cpp @@ -35,8 +35,7 @@ public: bool HasSubchannelData() const override; s64 GetSizeOnDisk() const override; - std::string GetMetadata(std::string_view type) const override; - std::string GetSubImageMetadata(u32 index, std::string_view type) const override; + std::string GetSubImageTitle(u32 index) const override; PrecacheResult Precache(ProgressCallback* progress = ProgressCallback::NullProgressCallback) override; @@ -420,19 +419,10 @@ bool CDImagePPF::HasSubchannelData() const return m_parent_image->HasSubchannelData(); } -std::string CDImagePPF::GetMetadata(std::string_view type) const -{ - return m_parent_image->GetMetadata(type); -} - -std::string CDImagePPF::GetSubImageMetadata(u32 index, std::string_view type) const +std::string CDImagePPF::GetSubImageTitle(u32 index) const { // We only support a single sub-image for patched games. - std::string ret; - if (index == 0) - ret = m_parent_image->GetSubImageMetadata(index, type); - - return ret; + return (index == 0) ? m_parent_image->GetSubImageTitle(index) : std::string(); } CDImage::PrecacheResult CDImagePPF::Precache(ProgressCallback* progress /*= ProgressCallback::NullProgressCallback*/)