From ec0370d2d1b533516964ae1982ac25f8ae33acb3 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 10 May 2015 19:09:11 +0200 Subject: [PATCH 1/2] Volume: Add prefer_long parameter to GetNames GC games with long names store two variations of the name in opening.bnr. This makes the shorter of those names available. For volumes other than GC discs, prefer_long is ignored. --- Source/Core/DiscIO/Volume.h | 2 +- Source/Core/DiscIO/VolumeDirectory.cpp | 2 +- Source/Core/DiscIO/VolumeDirectory.h | 2 +- Source/Core/DiscIO/VolumeGC.cpp | 150 +++++++++----------- Source/Core/DiscIO/VolumeGC.h | 3 +- Source/Core/DiscIO/VolumeWad.cpp | 2 +- Source/Core/DiscIO/VolumeWad.h | 2 +- Source/Core/DiscIO/VolumeWiiCrypted.cpp | 2 +- Source/Core/DiscIO/VolumeWiiCrypted.h | 2 +- Source/Core/DolphinQt/GameList/GameFile.cpp | 2 +- Source/Core/DolphinWX/ISOFile.cpp | 2 +- Source/Core/DolphinWX/MainAndroid.cpp | 2 +- 12 files changed, 78 insertions(+), 95 deletions(-) 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..67faf56d0e 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt/GameList/GameFile.cpp @@ -87,7 +87,7 @@ GameFile::GameFile(const QString& fileName) { m_platform = volume->GetVolumeType(); - m_names = ConvertLocalizedStrings(volume->GetNames()); + m_names = ConvertLocalizedStrings(volume->GetNames(true)); m_descriptions = ConvertLocalizedStrings(volume->GetDescriptions()); m_company = QString::fromStdString(volume->GetCompany()); 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; From 04de0647326d9521b350c451508491cf6f190c13 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Mon, 11 May 2015 10:51:11 +0200 Subject: [PATCH 2/2] DolphinQt: Use short GC game titles in grid view Short titles fit better than long titles. --- Source/Core/DolphinQt/GameList/GameFile.cpp | 25 ++++++++++++--------- Source/Core/DolphinQt/GameList/GameFile.h | 7 +++--- Source/Core/DolphinQt/GameList/GameGrid.cpp | 2 +- Source/Core/DolphinQt/GameList/GameTree.cpp | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Source/Core/DolphinQt/GameList/GameFile.cpp b/Source/Core/DolphinQt/GameList/GameFile.cpp index 67faf56d0e..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(true)); + 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()));