diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index fc86827f51..294cf94c01 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -85,7 +85,7 @@ public: virtual std::string GetMakerID() const = 0; virtual u16 GetRevision() const = 0; virtual std::string GetInternalName() const = 0; - virtual std::map GetNames() const = 0; + virtual std::map GetNames(bool prefer_long) const = 0; virtual std::map GetDescriptions() const { return std::map(); } virtual std::string GetCompany() const { return std::string(); } virtual std::vector GetBanner(int* width, int* height) const; diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 77f4523417..ee22db75ab 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -191,7 +191,7 @@ std::string CVolumeDirectory::GetInternalName() const return ""; } -std::map CVolumeDirectory::GetNames() const +std::map CVolumeDirectory::GetNames(bool prefer_long) const { std::map names; std::string name = GetInternalName(); diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index ac9d965e3b..8053d209d2 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -41,7 +41,7 @@ public: u16 GetRevision() const override { return 0; } std::string GetInternalName() const override; - std::map GetNames() const override; + std::map GetNames(bool prefer_long) const override; void SetName(const std::string&); u32 GetFSTSize() const override; diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 07682e7a65..6160c65b24 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -105,91 +105,14 @@ std::string CVolumeGC::GetInternalName() const return ""; } -std::map CVolumeGC::GetNames() const +std::map CVolumeGC::GetNames(bool prefer_long) const { - std::map names; - - if (!LoadBannerFile()) - return names; - - u32 name_count = 0; - IVolume::ELanguage language; - bool is_japanese = GetCountry() == IVolume::ECountry::COUNTRY_JAPAN; - - switch (m_banner_file_type) - { - case BANNER_BNR1: - name_count = 1; - language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - case BANNER_BNR2: - name_count = 6; - language = IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - case BANNER_INVALID: - case BANNER_NOT_LOADED: - break; - } - - auto const banner = reinterpret_cast(m_banner_file.data()); - - for (u32 i = 0; i < name_count; ++i) - { - auto& comment = banner->comment[i]; - std::string name = DecodeString(comment.longTitle); - - if (name.empty()) - name = DecodeString(comment.shortTitle); - - if (!name.empty()) - names[(IVolume::ELanguage)(language + i)] = name; - } - - return names; + return ReadMultiLanguageStrings(false, prefer_long); } std::map CVolumeGC::GetDescriptions() const { - std::map descriptions; - - if (!LoadBannerFile()) - return descriptions; - - u32 desc_count = 0; - IVolume::ELanguage language; - bool is_japanese = GetCountry() == IVolume::ECountry::COUNTRY_JAPAN; - - switch (m_banner_file_type) - { - case BANNER_BNR1: - desc_count = 1; - language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - case BANNER_BNR2: - language = IVolume::ELanguage::LANGUAGE_ENGLISH; - desc_count = 6; - break; - - case BANNER_INVALID: - case BANNER_NOT_LOADED: - break; - } - - auto banner = reinterpret_cast(m_banner_file.data()); - - for (u32 i = 0; i < desc_count; ++i) - { - auto& data = banner->comment[i].comment; - std::string description = DecodeString(data); - - if (!description.empty()) - descriptions[(IVolume::ELanguage)(language + i)] = description; - } - - return descriptions; + return ReadMultiLanguageStrings(true); } std::string CVolumeGC::GetCompany() const @@ -277,14 +200,17 @@ IVolume::EPlatform CVolumeGC::GetVolumeType() const return GAMECUBE_DISC; } +// Returns true if the loaded banner file is valid, +// regardless of whether it was loaded by the current call bool CVolumeGC::LoadBannerFile() const { - // The methods GetNames, GetDescriptions, GetCompany and GetBanner - // all need to access the opening.bnr file. These four methods are - // typically called after each other, so we store the file in RAM - // to avoid reading it from the disc several times. However, + // The methods ReadMultiLanguageStrings, GetCompany and GetBanner + // need to access the opening.bnr file. These methods are + // usually called one after another. The file is cached in + // RAM to avoid reading it from the disc several times, but // if none of these methods are called, the file is never loaded. + // If opening.bnr has been loaded already, return immediately if (m_banner_file_type != BANNER_NOT_LOADED) return m_banner_file_type != BANNER_INVALID; @@ -319,4 +245,60 @@ bool CVolumeGC::LoadBannerFile() const return m_banner_file_type != BANNER_INVALID; } +std::map CVolumeGC::ReadMultiLanguageStrings(bool description, bool prefer_long) const +{ + std::map strings; + + if (!LoadBannerFile()) + return strings; + + u32 number_of_languages = 0; + ELanguage start_language; + bool is_japanese = GetCountry() == ECountry::COUNTRY_JAPAN; + + switch (m_banner_file_type) + { + case BANNER_BNR1: // NTSC + number_of_languages = 1; + start_language = is_japanese ? ELanguage::LANGUAGE_JAPANESE : ELanguage::LANGUAGE_ENGLISH; + break; + + case BANNER_BNR2: // PAL + number_of_languages = 6; + start_language = ELanguage::LANGUAGE_ENGLISH; + break; + + // Shouldn't happen + case BANNER_INVALID: + case BANNER_NOT_LOADED: + break; + } + + auto const banner = reinterpret_cast(m_banner_file.data()); + + for (u32 i = 0; i < number_of_languages; ++i) + { + GCBannerComment comment = banner->comment[i]; + std::string string; + + if (description) + { + string = DecodeString(comment.comment); + } + else // Title + { + if (prefer_long) + string = DecodeString(comment.longTitle); + + if (string.empty()) + string = DecodeString(comment.shortTitle); + } + + if (!string.empty()) + strings[(ELanguage)(start_language + i)] = string; + } + + return strings; +} + } // namespace diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index 9d93441579..35599cacf6 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -29,7 +29,7 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; virtual std::string GetInternalName() const override; - std::map GetNames() const override; + std::map GetNames(bool prefer_long) const override; std::map GetDescriptions() const override; std::string GetCompany() const override; std::vector GetBanner(int* width, int* height) const override; @@ -44,6 +44,7 @@ public: private: bool LoadBannerFile() const; + std::map ReadMultiLanguageStrings(bool description, bool prefer_long = true) const; static const int GC_BANNER_WIDTH = 96; static const int GC_BANNER_HEIGHT = 32; diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp index de1a2fd542..9821e93862 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -117,7 +117,7 @@ IVolume::EPlatform CVolumeWAD::GetVolumeType() const return WII_WAD; } -std::map CVolumeWAD::GetNames() const +std::map CVolumeWAD::GetNames(bool prefer_long) const { std::vector name_data(NAMES_TOTAL_BYTES); if (!Read(m_opening_bnr_offset + 0x9C, NAMES_TOTAL_BYTES, name_data.data())) diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index e52951e33e..16168aefad 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -32,7 +32,7 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; std::string GetInternalName() const override { return ""; } - std::map GetNames() const override; + std::map GetNames(bool prefer_long) const override; u32 GetFSTSize() const override { return 0; } std::string GetApploaderDate() const override { return ""; } diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index fe337253df..ec5564f954 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -202,7 +202,7 @@ std::string CVolumeWiiCrypted::GetInternalName() const return ""; } -std::map CVolumeWiiCrypted::GetNames() const +std::map CVolumeWiiCrypted::GetNames(bool prefer_long) const { std::unique_ptr file_system(CreateFileSystem(this)); std::vector opening_bnr(NAMES_TOTAL_BYTES); diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index 634614a690..6fd687db3d 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -32,7 +32,7 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; std::string GetInternalName() const override; - std::map GetNames() const override; + std::map GetNames(bool prefer_long) const override; u32 GetFSTSize() const override; std::string GetApploaderDate() const override; u8 GetDiscNumber() const override; diff --git a/Source/Core/DolphinQt/GameList/GameFile.cpp b/Source/Core/DolphinQt/GameList/GameFile.cpp index 50e407d2a6..85efd8f4e9 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt/GameList/GameFile.cpp @@ -25,7 +25,7 @@ #include "DolphinQt/Utils/Resources.h" #include "DolphinQt/Utils/Utils.h" -static const u32 CACHE_REVISION = 0x009; +static const u32 CACHE_REVISION = 0x00A; static const u32 DATASTREAM_REVISION = 15; // Introduced in Qt 5.2 static QMap ConvertLocalizedStrings(std::map strings) @@ -87,7 +87,8 @@ GameFile::GameFile(const QString& fileName) { m_platform = volume->GetVolumeType(); - m_names = ConvertLocalizedStrings(volume->GetNames()); + m_short_names = ConvertLocalizedStrings(volume->GetNames(false)); + m_long_names = ConvertLocalizedStrings(volume->GetNames(true)); m_descriptions = ConvertLocalizedStrings(volume->GetDescriptions()); m_company = QString::fromStdString(volume->GetCompany()); @@ -165,10 +166,12 @@ bool GameFile::LoadFromCache() u32 country; u32 platform; - QMap names; + QMap short_names; + QMap long_names; QMap descriptions; stream >> m_folder_name - >> names + >> short_names + >> long_names >> descriptions >> m_company >> m_unique_id @@ -182,7 +185,8 @@ bool GameFile::LoadFromCache() >> m_revision; m_country = (DiscIO::IVolume::ECountry)country; m_platform = (DiscIO::IVolume::EPlatform)platform; - m_names = CastLocalizedStrings(names); + m_short_names = CastLocalizedStrings(short_names); + m_long_names = CastLocalizedStrings(long_names); m_descriptions = CastLocalizedStrings(descriptions); file.close(); return true; @@ -209,7 +213,8 @@ void GameFile::SaveToCache() stream << CACHE_REVISION; stream << m_folder_name - << CastLocalizedStrings(m_names) + << CastLocalizedStrings(m_short_names) + << CastLocalizedStrings(m_long_names) << CastLocalizedStrings(m_descriptions) << m_company << m_unique_id @@ -258,15 +263,15 @@ QString GameFile::GetDescription() const return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(wii)); } -QString GameFile::GetName(DiscIO::IVolume::ELanguage language) const +QString GameFile::GetName(bool prefer_long, DiscIO::IVolume::ELanguage language) const { - return GetLanguageString(language, m_names); + return GetLanguageString(language, prefer_long ? m_long_names : m_short_names); } -QString GameFile::GetName() const +QString GameFile::GetName(bool prefer_long) const { bool wii = m_platform != DiscIO::IVolume::GAMECUBE_DISC; - QString name = GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(wii)); + QString name = GetName(prefer_long, SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(wii)); if (name.isEmpty()) { // No usable name, return filename (better than nothing) diff --git a/Source/Core/DolphinQt/GameList/GameFile.h b/Source/Core/DolphinQt/GameList/GameFile.h index 4f906fb611..30ea33d50d 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.h +++ b/Source/Core/DolphinQt/GameList/GameFile.h @@ -22,8 +22,8 @@ public: bool IsValid() const { return m_valid; } QString GetFileName() { return m_file_name; } QString GetFolderName() { return m_folder_name; } - QString GetName(DiscIO::IVolume::ELanguage language) const; - QString GetName() const; + QString GetName(bool prefer_long, DiscIO::IVolume::ELanguage language) const; + QString GetName(bool prefer_long) const; QString GetDescription(DiscIO::IVolume::ELanguage language) const; QString GetDescription() const; QString GetCompany() const; @@ -45,7 +45,8 @@ private: QString m_file_name; QString m_folder_name; - QMap m_names; + QMap m_short_names; + QMap m_long_names; QMap m_descriptions; QString m_company; diff --git a/Source/Core/DolphinQt/GameList/GameGrid.cpp b/Source/Core/DolphinQt/GameList/GameGrid.cpp index 2e6d76f3d5..ebce076ccb 100644 --- a/Source/Core/DolphinQt/GameList/GameGrid.cpp +++ b/Source/Core/DolphinQt/GameList/GameGrid.cpp @@ -76,7 +76,7 @@ void DGameGrid::AddGame(GameFile* gameItem) QListWidgetItem* i = new QListWidgetItem; i->setIcon(QIcon(gameItem->GetBitmap() .scaled(GRID_BANNER_WIDTH, GRID_BANNER_HEIGHT, Qt::KeepAspectRatio, Qt::SmoothTransformation))); - i->setText(gameItem->GetName()); + i->setText(gameItem->GetName(false)); if (gameItem->IsCompressed()) i->setTextColor(QColor("#00F")); diff --git a/Source/Core/DolphinQt/GameList/GameTree.cpp b/Source/Core/DolphinQt/GameList/GameTree.cpp index 0d84a3152d..b218d6072f 100644 --- a/Source/Core/DolphinQt/GameList/GameTree.cpp +++ b/Source/Core/DolphinQt/GameList/GameTree.cpp @@ -110,7 +110,7 @@ void DGameTree::AddGame(GameFile* item) QTreeWidgetItem* i = new QTreeWidgetItem; i->setIcon(COL_TYPE, QIcon(Resources::GetPlatformPixmap(item->GetPlatform()))); i->setIcon(COL_BANNER, QIcon(item->GetBitmap())); - i->setText(COL_TITLE, item->GetName()); + i->setText(COL_TITLE, item->GetName(true)); i->setText(COL_DESCRIPTION, item->GetDescription()); i->setIcon(COL_REGION, QIcon(Resources::GetRegionPixmap(item->GetCountry()))); i->setText(COL_SIZE, NiceSizeFormat(item->GetFileSize())); diff --git a/Source/Core/DolphinWX/ISOFile.cpp b/Source/Core/DolphinWX/ISOFile.cpp index a1f9187f64..d36ce1fde4 100644 --- a/Source/Core/DolphinWX/ISOFile.cpp +++ b/Source/Core/DolphinWX/ISOFile.cpp @@ -84,7 +84,7 @@ GameListItem::GameListItem(const std::string& _rFileName) { m_Platform = pVolume->GetVolumeType(); - m_names = pVolume->GetNames(); + m_names = pVolume->GetNames(true); m_descriptions = pVolume->GetDescriptions(); m_company = pVolume->GetCompany(); diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index 4706a63ccf..1389abdcee 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -222,7 +222,7 @@ static std::string GetTitle(std::string filename) std::unique_ptr pVolume(DiscIO::CreateVolumeFromFilename(filename)); if (pVolume != nullptr) { - std::map titles = pVolume->GetNames(); + std::map titles = pVolume->GetNames(true); /* bool is_wii_title = pVolume->GetVolumeType() != DiscIO::IVolume::GAMECUBE_DISC;