From b5104a79f1d39d2d7d160f2bd984f604a5ae2797 Mon Sep 17 00:00:00 2001 From: Rukai Date: Mon, 29 Feb 2016 19:52:15 +1100 Subject: [PATCH] GCVolume: supports reading all opening.bnr information DQT2: Game properties dialog contains info tab giving information about the selected iso. --- Source/Android/jni/MainAndroid.cpp | 28 ++- Source/Core/Common/ColorUtil.cpp | 4 +- Source/Core/Common/ColorUtil.h | 4 +- Source/Core/DiscIO/Volume.h | 23 +- Source/Core/DiscIO/VolumeDirectory.cpp | 14 +- Source/Core/DiscIO/VolumeDirectory.h | 5 +- Source/Core/DiscIO/VolumeGC.cpp | 181 ++++++++-------- Source/Core/DiscIO/VolumeGC.h | 52 ++--- Source/Core/DiscIO/VolumeWad.cpp | 5 +- Source/Core/DiscIO/VolumeWad.h | 5 +- Source/Core/DiscIO/VolumeWiiCrypted.cpp | 2 +- Source/Core/DiscIO/VolumeWiiCrypted.h | 2 +- Source/Core/DolphinQt2/CMakeLists.txt | 3 + .../DolphinQt2/Config/FilesystemWidget.cpp | 9 + .../Core/DolphinQt2/Config/FilesystemWidget.h | 19 ++ Source/Core/DolphinQt2/Config/InfoWidget.cpp | 196 ++++++++++++++++++ Source/Core/DolphinQt2/Config/InfoWidget.h | 44 ++++ .../DolphinQt2/Config/PropertiesDialog.cpp | 30 +++ .../Core/DolphinQt2/Config/PropertiesDialog.h | 16 ++ Source/Core/DolphinQt2/DolphinQt2.vcxproj | 9 + .../DolphinQt2/DolphinQt2.vcxproj.filters | 15 ++ Source/Core/DolphinQt2/GameList/GameFile.cpp | 123 ++++++++++- Source/Core/DolphinQt2/GameList/GameFile.h | 37 +++- Source/Core/DolphinQt2/GameList/GameList.cpp | 21 +- Source/Core/DolphinQt2/GameList/GameList.h | 1 + .../DolphinQt2/GameList/GameListModel.cpp | 8 +- .../Core/DolphinQt2/GameList/GameListModel.h | 2 +- .../DolphinQt2/GameList/TableDelegate.cpp | 17 +- Source/Core/DolphinWX/ISOFile.cpp | 20 +- 29 files changed, 693 insertions(+), 202 deletions(-) create mode 100644 Source/Core/DolphinQt2/Config/FilesystemWidget.cpp create mode 100644 Source/Core/DolphinQt2/Config/FilesystemWidget.h create mode 100644 Source/Core/DolphinQt2/Config/InfoWidget.cpp create mode 100644 Source/Core/DolphinQt2/Config/InfoWidget.h create mode 100644 Source/Core/DolphinQt2/Config/PropertiesDialog.cpp create mode 100644 Source/Core/DolphinQt2/Config/PropertiesDialog.h diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 796a2b5409..4dab66a701 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -269,11 +269,15 @@ static std::string GetTitle(std::string filename) if (pVolume != nullptr) { - std::map titles = pVolume->GetNames(true); + std::map titles = pVolume->GetLongNames(); + if (titles.empty()) + titles = pVolume->GetShortNames(); /* - bool is_wii_title = pVolume->GetVolumeType() != DiscIO::IVolume::GAMECUBE_DISC; - DiscIO::IVolume::ELanguage language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title); + bool is_wii_title = pVolume->GetVolumeType() != + DiscIO::IVolume::GAMECUBE_DISC; + DiscIO::IVolume::ELanguage language = + SConfig::GetInstance().GetCurrentLanguage(is_wii_title); auto it = titles.find(language); if (it != end) @@ -281,7 +285,8 @@ static std::string GetTitle(std::string filename) auto end = titles.end(); - // English tends to be a good fallback when the requested language isn't available + // English tends to be a good fallback when the requested language isn't + // available // if (language != DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH) { auto it = titles.find(DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH); if (it != end) @@ -313,8 +318,10 @@ static std::string GetDescription(std::string filename) std::map descriptions = volume->GetDescriptions(); /* - bool is_wii_title = pVolume->GetVolumeType() != DiscIO::IVolume::GAMECUBE_DISC; - DiscIO::IVolume::ELanguage language = SConfig::GetInstance().GetCurrentLanguage(is_wii_title); + bool is_wii_title = pVolume->GetVolumeType() != + DiscIO::IVolume::GAMECUBE_DISC; + DiscIO::IVolume::ELanguage language = + SConfig::GetInstance().GetCurrentLanguage(is_wii_title); auto it = descriptions.find(language); if (it != end) @@ -322,7 +329,8 @@ static std::string GetDescription(std::string filename) auto end = descriptions.end(); - // English tends to be a good fallback when the requested language isn't available + // English tends to be a good fallback when the requested language isn't + // available // if (language != DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH) { auto it = descriptions.find(DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH); if (it != end) @@ -745,7 +753,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang if (surf == nullptr) __android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null."); - // If GLInterface isn't a thing yet then we don't need to let it know that the surface has changed + // If GLInterface isn't a thing yet then we don't need to let it know that the + // surface has changed if (GLInterface) { GLInterface->UpdateHandle(surf); @@ -764,7 +773,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr surf = nullptr; } - // If GLInterface isn't a thing yet then we don't need to let it know that the surface has changed + // If GLInterface isn't a thing yet then we don't need to let it know that the + // surface has changed if (GLInterface) { GLInterface->UpdateHandle(nullptr); diff --git a/Source/Core/Common/ColorUtil.cpp b/Source/Core/Common/ColorUtil.cpp index a4f01da453..fafdcf227f 100644 --- a/Source/Core/Common/ColorUtil.cpp +++ b/Source/Core/Common/ColorUtil.cpp @@ -40,7 +40,7 @@ static u32 Decode5A3(u16 val) return (a << 24) | (r << 16) | (g << 8) | b; } -void decode5A3image(u32* dst, u16* src, int width, int height) +void decode5A3image(u32* dst, const u16* src, int width, int height) { for (int y = 0; y < height; y += 4) { @@ -58,7 +58,7 @@ void decode5A3image(u32* dst, u16* src, int width, int height) } } -void decodeCI8image(u32* dst, u8* src, u16* pal, int width, int height) +void decodeCI8image(u32* dst, const u8* src, u16* pal, int width, int height) { for (int y = 0; y < height; y += 4) { diff --git a/Source/Core/Common/ColorUtil.h b/Source/Core/Common/ColorUtil.h index bc2b100dc7..8b17919ec3 100644 --- a/Source/Core/Common/ColorUtil.h +++ b/Source/Core/Common/ColorUtil.h @@ -8,7 +8,7 @@ namespace ColorUtil { -void decode5A3image(u32* dst, u16* src, int width, int height); -void decodeCI8image(u32* dst, u8* src, u16* pal, int width, int height); +void decode5A3image(u32* dst, const u16* src, int width, int height); +void decodeCI8image(u32* dst, const u8* src, u16* pal, int width, int height); } // namespace diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index 190376a19d..1ea9d3650f 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -19,7 +19,8 @@ namespace DiscIO class IVolume { public: - // Increment CACHE_REVISION if the enums below are modified (ISOFile.cpp & GameFile.cpp) + // Increment CACHE_REVISION if the enums below are modified (ISOFile.cpp & + // GameFile.cpp) enum EPlatform { GAMECUBE_DISC = 0, @@ -85,12 +86,26 @@ public: virtual std::string GetMakerID() const = 0; virtual u16 GetRevision() const = 0; virtual std::string GetInternalName() const = 0; - virtual std::map GetNames(bool prefer_long) const = 0; + virtual std::map GetShortNames() const + { + return std::map(); + } + virtual std::map GetLongNames() const + { + return std::map(); + } + virtual std::map GetShortMakers() const + { + return std::map(); + } + virtual std::map GetLongMakers() const + { + return std::map(); + } 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 = 0; virtual u64 GetFSTSize() const = 0; virtual std::string GetApploaderDate() const = 0; @@ -116,7 +131,7 @@ protected: // strnlen to trim NULLs std::string string(data, strnlen(data, sizeof(data))); - // There don't seem to be any GC discs with the country set to Taiwan... + // There doesn't seem to be any GC discs with the country set to Taiwan... // But maybe they would use Shift_JIS if they existed? Not sure bool use_shift_jis = (COUNTRY_JAPAN == GetCountry() || COUNTRY_TAIWAN == GetCountry()); diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 8fe2e65cf0..5662fa57c2 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -63,10 +63,14 @@ bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt if (!decrypt && (_Offset + _Length >= 0x400) && m_is_wii) { // Fully supporting this would require re-encrypting every file that's read. - // Only supporting the areas that IOS allows software to read could be more feasible. - // Currently, only the header (up to 0x400) is supported, though we're cheating a bit - // with it by reading the header inside the current partition instead. Supporting the - // header is enough for booting games, but not for running things like the Disc Channel. + // Only supporting the areas that IOS allows software to read could be more + // feasible. + // Currently, only the header (up to 0x400) is supported, though we're + // cheating a bit + // with it by reading the header inside the current partition instead. + // Supporting the + // header is enough for booting games, but not for running things like the + // Disc Channel. return false; } @@ -183,7 +187,7 @@ std::string CVolumeDirectory::GetInternalName() const return ""; } -std::map CVolumeDirectory::GetNames(bool prefer_long) const +std::map CVolumeDirectory::GetLongNames() const { std::string name = GetInternalName(); if (name.empty()) diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index 496f1119cb..2a6fb87808 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -19,7 +19,8 @@ struct FSTEntry; } // -// --- this volume type is used for reading files directly from the hard drive --- +// --- this volume type is used for reading files directly from the hard drive +// --- // namespace DiscIO @@ -43,7 +44,7 @@ public: u16 GetRevision() const override { return 0; } std::string GetInternalName() const override; - std::map GetNames(bool prefer_long) const override; + std::map GetLongNames() const override; std::vector GetBanner(int* width, int* height) const override; void SetName(const std::string&); diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 2930c6cd33..4c364b941b 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -100,48 +100,46 @@ std::string CVolumeGC::GetInternalName() const char name[0x60]; if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name)) return DecodeString(name); - else - return ""; + + return ""; } -std::map CVolumeGC::GetNames(bool prefer_long) const +std::map CVolumeGC::GetShortNames() const { - return ReadMultiLanguageStrings(false, prefer_long); + LoadBannerFile(); + return m_short_names; +} + +std::map CVolumeGC::GetLongNames() const +{ + LoadBannerFile(); + return m_long_names; +} + +std::map CVolumeGC::GetShortMakers() const +{ + LoadBannerFile(); + return m_short_makers; +} + +std::map CVolumeGC::GetLongMakers() const +{ + LoadBannerFile(); + return m_long_makers; } std::map CVolumeGC::GetDescriptions() const { - return ReadMultiLanguageStrings(true); -} - -std::string CVolumeGC::GetCompany() const -{ - if (!LoadBannerFile()) - return ""; - - std::string company = DecodeString(m_banner_file.comment[0].longMaker); - - if (company.empty()) - company = DecodeString(m_banner_file.comment[0].shortMaker); - - return company; + LoadBannerFile(); + return m_descriptions; } std::vector CVolumeGC::GetBanner(int* width, int* height) const { - if (!LoadBannerFile()) - { - *width = 0; - *height = 0; - return std::vector(); - } - - std::vector image_buffer(GC_BANNER_WIDTH * GC_BANNER_HEIGHT); - ColorUtil::decode5A3image(image_buffer.data(), m_banner_file.image, GC_BANNER_WIDTH, - GC_BANNER_HEIGHT); - *width = GC_BANNER_WIDTH; - *height = GC_BANNER_HEIGHT; - return image_buffer; + LoadBannerFile(); + *width = m_image_width; + *height = m_image_height; + return m_image_buffer; } u64 CVolumeGC::GetFSTSize() const @@ -201,102 +199,93 @@ 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 +void CVolumeGC::LoadBannerFile() const { - // 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; + if (m_banner_loaded) + return; + GCBanner banner_file; std::unique_ptr file_system(CreateFileSystem(this)); size_t file_size = (size_t)file_system->GetFileSize("opening.bnr"); - if (file_size == BNR1_SIZE || file_size == BNR2_SIZE) - { - file_system->ReadFile("opening.bnr", reinterpret_cast(&m_banner_file), file_size); - if (file_size == BNR1_SIZE && m_banner_file.id == 0x31524e42) // "BNR1" - { - m_banner_file_type = BANNER_BNR1; - } - else if (file_size == BNR2_SIZE && m_banner_file.id == 0x32524e42) // "BNR2" - { - m_banner_file_type = BANNER_BNR2; - } - else - { - m_banner_file_type = BANNER_INVALID; - WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", m_banner_file.id, file_size); - } + constexpr int BNR1_MAGIC = 0x31524e42; + constexpr int BNR2_MAGIC = 0x32524e42; + if (file_size != BNR1_SIZE && file_size != BNR2_SIZE) + { + WARN_LOG(DISCIO, "Invalid opening.bnr. Size: %0zx", file_size); + return; + } + + file_system->ReadFile("opening.bnr", reinterpret_cast(&banner_file), file_size); + + bool is_bnr1; + if (banner_file.id == BNR1_MAGIC && file_size == BNR1_SIZE) + { + is_bnr1 = true; + } + else if (banner_file.id == BNR2_MAGIC && file_size == BNR2_SIZE) + { + is_bnr1 = false; } else { - m_banner_file_type = BANNER_INVALID; - WARN_LOG(DISCIO, "Invalid opening.bnr. Size: %0zx", file_size); + WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size); + return; } - return m_banner_file_type != BANNER_INVALID; + ExtractBannerInformation(banner_file, is_bnr1); + m_banner_loaded = true; } -std::map -CVolumeGC::ReadMultiLanguageStrings(bool description, bool prefer_long) const +void CVolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const { - std::map strings; - - if (!LoadBannerFile()) - return strings; - u32 number_of_languages = 0; ELanguage start_language = LANGUAGE_UNKNOWN; bool is_japanese = GetCountry() == ECountry::COUNTRY_JAPAN; - switch (m_banner_file_type) + if (is_bnr1) // NTSC { - case BANNER_BNR1: // NTSC number_of_languages = 1; start_language = is_japanese ? ELanguage::LANGUAGE_JAPANESE : ELanguage::LANGUAGE_ENGLISH; - break; - - case BANNER_BNR2: // PAL + } + else // PAL + { number_of_languages = 6; start_language = ELanguage::LANGUAGE_ENGLISH; - break; - - // Shouldn't happen - case BANNER_INVALID: - case BANNER_NOT_LOADED: - break; } + m_image_width = GC_BANNER_WIDTH; + m_image_height = GC_BANNER_HEIGHT; + m_image_buffer = std::vector(m_image_width * m_image_height); + ColorUtil::decode5A3image(m_image_buffer.data(), banner_file.image, m_image_width, + m_image_height); + for (u32 i = 0; i < number_of_languages; ++i) { - const GCBannerComment& comment = m_banner_file.comment[i]; - std::string string; + const GCBannerInformation& info = banner_file.information[i]; + ELanguage language = static_cast(start_language + i); - if (description) - { - string = DecodeString(comment.comment); - } - else // Title - { - if (prefer_long) - string = DecodeString(comment.longTitle); + std::string description = DecodeString(info.description); + if (!description.empty()) + m_descriptions[language] = description; - if (string.empty()) - string = DecodeString(comment.shortTitle); - } + std::string short_name = DecodeString(info.short_name); + if (!short_name.empty()) + m_short_names[language] = short_name; - if (!string.empty()) - strings[(ELanguage)(start_language + i)] = string; + std::string long_name = DecodeString(info.long_name); + if (!long_name.empty()) + m_long_names[language] = long_name; + + std::string short_maker = DecodeString(info.short_maker); + if (!short_maker.empty()) + m_short_makers[language] = short_maker; + + std::string long_maker = DecodeString(info.long_maker); + if (!long_maker.empty()) + m_long_makers[language] = long_maker; } - - return strings; } } // namespace diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index 0842736d08..4cef2a0e29 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -27,9 +27,11 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; std::string GetInternalName() const override; - std::map GetNames(bool prefer_long) const override; + std::map GetShortNames() const override; + std::map GetLongNames() const override; + std::map GetShortMakers() const override; + std::map GetLongMakers() const override; std::map GetDescriptions() const override; - std::string GetCompany() const override; std::vector GetBanner(int* width, int* height) const override; u64 GetFSTSize() const override; std::string GetApploaderDate() const override; @@ -42,21 +44,18 @@ public: u64 GetRawSize() const override; 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; - // Banner Comment - struct GCBannerComment + struct GCBannerInformation { - char shortTitle[32]; // Short game title shown in IPL menu - char shortMaker[32]; // Short developer, publisher names shown in IPL menu - char longTitle[64]; // Long game title shown in IPL game start screen - char longMaker[64]; // Long developer, publisher names shown in IPL game start screen - char comment[128]; // Game description shown in IPL game start screen in two lines. + char short_name[32]; // Short game title shown in IPL menu + char short_maker[32]; // Short developer, publisher names shown in IPL menu + char long_name[64]; // Long game title shown in IPL game start screen + char long_maker[64]; // Long developer, publisher names shown in IPL game + // start screen + char description[128]; // Game description shown in IPL game start screen in + // two lines. }; struct GCBanner @@ -64,22 +63,27 @@ private: u32 id; // "BNR1" for NTSC, "BNR2" for PAL u32 padding[7]; u16 image[GC_BANNER_WIDTH * GC_BANNER_HEIGHT]; // RGB5A3 96x32 image - GCBannerComment comment[6]; // Comments in six languages (only one for BNR1 type) + GCBannerInformation information[6]; // information comes in six languages + // (only one for BNR1 type) }; - static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerComment) * 5; + void LoadBannerFile() const; + void ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const; + + static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerInformation) * 5; static const size_t BNR2_SIZE = sizeof(GCBanner); - enum BannerFileType - { - BANNER_NOT_LOADED, - BANNER_INVALID, - BANNER_BNR1, - BANNER_BNR2 - }; + mutable std::map m_short_names; - mutable BannerFileType m_banner_file_type = BANNER_NOT_LOADED; - mutable GCBanner m_banner_file; + mutable std::map m_long_names; + mutable std::map m_short_makers; + mutable std::map m_long_makers; + mutable std::map m_descriptions; + + mutable bool m_banner_loaded = false; + mutable std::vector m_image_buffer; + mutable int m_image_height = 0; + mutable int m_image_width = 0; std::unique_ptr m_pReader; }; diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp index c86c490ed4..fe9da2db50 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -89,7 +89,8 @@ std::string CVolumeWAD::GetUniqueID() const std::string CVolumeWAD::GetMakerID() const { char temp[2] = {1}; - // Some weird channels use 0x0000 in place of the MakerID, so we need a check there + // Some weird channels use 0x0000 in place of the MakerID, so we need a check + // there if (!Read(0x198 + m_tmd_offset, 2, (u8*)temp) || temp[0] == 0 || temp[1] == 0) return "00"; @@ -119,7 +120,7 @@ IVolume::EPlatform CVolumeWAD::GetVolumeType() const return WII_WAD; } -std::map CVolumeWAD::GetNames(bool prefer_long) const +std::map CVolumeWAD::GetLongNames() 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 1b522a5a83..4e5c8016ee 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -14,7 +14,8 @@ #include "DiscIO/Volume.h" // --- this volume type is used for Wad files --- -// Some of this code might look redundant with the CNANDContentLoader class, however, +// Some of this code might look redundant with the CNANDContentLoader class, +// however, // We do not do any decryption here, we do raw read, so things are -Faster- namespace DiscIO @@ -30,7 +31,7 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; std::string GetInternalName() const override { return ""; } - std::map GetNames(bool prefer_long) const override; + std::map GetLongNames() const override; std::vector GetBanner(int* width, int* height) const override; u64 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 fb0b14ec43..cbc56a72f4 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -238,7 +238,7 @@ std::string CVolumeWiiCrypted::GetInternalName() const return ""; } -std::map CVolumeWiiCrypted::GetNames(bool prefer_long) const +std::map CVolumeWiiCrypted::GetLongNames() 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 34bc46b029..c2f089839e 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -31,7 +31,7 @@ public: std::string GetMakerID() const override; u16 GetRevision() const override; std::string GetInternalName() const override; - std::map GetNames(bool prefer_long) const override; + std::map GetLongNames() const override; std::vector GetBanner(int* width, int* height) const override; u64 GetFSTSize() const override; std::string GetApploaderDate() const override; diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index 97e483340b..b03d17bdf1 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -13,7 +13,10 @@ set(SRCS Resources.cpp Settings.cpp ToolBar.cpp + Config/FilesystemWidget.cpp + Config/InfoWidget.cpp Config/PathDialog.cpp + Config/PropertiesDialog.cpp Config/SettingsWindow.cpp GameList/GameFile.cpp GameList/GameList.cpp diff --git a/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp b/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp new file mode 100644 index 0000000000..935d0617a2 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/FilesystemWidget.cpp @@ -0,0 +1,9 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Config/FilesystemWidget.h" + +FilesystemWidget::FilesystemWidget(const GameFile& game) : m_game(game) +{ +} diff --git a/Source/Core/DolphinQt2/Config/FilesystemWidget.h b/Source/Core/DolphinQt2/Config/FilesystemWidget.h new file mode 100644 index 0000000000..8cb58fa236 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/FilesystemWidget.h @@ -0,0 +1,19 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "DolphinQt2/GameList/GameFile.h" + +class FilesystemWidget final : public QWidget +{ + Q_OBJECT +public: + explicit FilesystemWidget(const GameFile& game); + +private: + GameFile m_game; +}; diff --git a/Source/Core/DolphinQt2/Config/InfoWidget.cpp b/Source/Core/DolphinQt2/Config/InfoWidget.cpp new file mode 100644 index 0000000000..0fbba477a5 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/InfoWidget.cpp @@ -0,0 +1,196 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DolphinQt2/Config/InfoWidget.h" + +InfoWidget::InfoWidget(const GameFile& game) : m_game(game) +{ + QVBoxLayout* layout = new QVBoxLayout(); + layout->addWidget(CreateISODetails()); + layout->addWidget(CreateBannerDetails()); + setLayout(layout); +} + +QGroupBox* InfoWidget::CreateISODetails() +{ + QGroupBox* group = new QGroupBox(tr("ISO Details")); + QFormLayout* layout = new QFormLayout; + + QLineEdit* file_path = CreateValueDisplay(m_game.GetFilePath()); + QLineEdit* internal_name = CreateValueDisplay(m_game.GetInternalName()); + QLineEdit* game_id = CreateValueDisplay(m_game.GetUniqueID()); + QLineEdit* country = CreateValueDisplay(m_game.GetCountry()); + QLineEdit* maker = CreateValueDisplay(m_game.GetMaker()); + QLineEdit* maker_id = CreateValueDisplay(QStringLiteral("0x") + m_game.GetMakerID()); + QLineEdit* disc_number = CreateValueDisplay(QString::number(m_game.GetDiscNumber())); + QLineEdit* revision = CreateValueDisplay(QString::number(m_game.GetRevision())); + QLineEdit* apploader_date = CreateValueDisplay(m_game.GetApploaderDate()); + QLineEdit* iso_size = CreateValueDisplay(FormatSize(m_game.GetFileSize())); + QWidget* checksum = CreateChecksumComputer(); + + layout->addRow(tr("File Path:"), file_path); + layout->addRow(tr("Internal Name:"), internal_name); + layout->addRow(tr("Game ID:"), game_id); + layout->addRow(tr("Country:"), country); + layout->addRow(tr("Maker:"), maker); + layout->addRow(tr("Maker ID:"), maker_id); + layout->addRow(tr("Disc Number:"), disc_number); + layout->addRow(tr("Revision:"), revision); + layout->addRow(tr("Apploader Date:"), apploader_date); + layout->addRow(tr("ISO Size:"), iso_size); + layout->addRow(tr("MD5 Checksum:"), checksum); + + group->setLayout(layout); + return group; +} + +QGroupBox* InfoWidget::CreateBannerDetails() +{ + QGroupBox* group = new QGroupBox(tr("%1 Banner Details").arg(m_game.GetPlatform())); + QFormLayout* layout = new QFormLayout; + + m_long_name = CreateValueDisplay(); + m_short_name = CreateValueDisplay(); + m_short_maker = CreateValueDisplay(); + m_long_maker = CreateValueDisplay(); + m_description = new QTextEdit(); + m_description->setReadOnly(true); + QWidget* banner = CreateBannerGraphic(); + CreateLanguageSelector(); + + layout->addRow(tr("Show Language:"), m_language_selector); + if (m_game.GetPlatformID() == DiscIO::IVolume::GAMECUBE_DISC) + { + layout->addRow(tr("Short Name:"), m_short_name); + layout->addRow(tr("Short Maker:"), m_short_maker); + layout->addRow(tr("Long Name:"), m_long_name); + layout->addRow(tr("Long Maker:"), m_long_maker); + layout->addRow(tr("Description:"), m_description); + } + else if (m_game.GetPlatformID() == DiscIO::IVolume::WII_DISC) + { + layout->addRow(tr("Name:"), m_long_name); + } + layout->addRow(tr("Banner:"), banner); + + group->setLayout(layout); + return group; +} + +QWidget* InfoWidget::CreateBannerGraphic() +{ + QWidget* widget = new QWidget(); + QHBoxLayout* layout = new QHBoxLayout(); + + QLabel* banner = new QLabel(); + banner->setPixmap(m_game.GetBanner()); + QPushButton* save = new QPushButton(tr("Save as...")); + connect(save, &QPushButton::clicked, this, &InfoWidget::SaveBanner); + + layout->addWidget(banner); + layout->addWidget(save); + widget->setLayout(layout); + return widget; +} + +void InfoWidget::SaveBanner() +{ + QString path = QFileDialog::getSaveFileName(this, tr("Select a File"), QDir::currentPath(), + tr("PNG image file (*.png);; All Files (*)")); + m_game.GetBanner().save(path, "PNG"); +} + +QLineEdit* InfoWidget::CreateValueDisplay(const QString& value) +{ + QLineEdit* value_display = new QLineEdit(value); + value_display->setReadOnly(true); + value_display->setCursorPosition(0); + return value_display; +} + +void InfoWidget::CreateLanguageSelector() +{ + m_language_selector = new QComboBox(); + QList languages = m_game.GetAvailableLanguages(); + for (int i = 0; i < languages.count(); i++) + { + DiscIO::IVolume::ELanguage language = languages.at(i); + m_language_selector->addItem(m_game.GetLanguage(language), language); + } + if (m_language_selector->count() == 1) + m_language_selector->setDisabled(true); + connect(m_language_selector, SIGNAL(currentIndexChanged(int)), this, SLOT(ChangeLanguage())); + ChangeLanguage(); +} + +void InfoWidget::ChangeLanguage() +{ + DiscIO::IVolume::ELanguage language = + static_cast(m_language_selector->currentData().toInt()); + m_short_name->setText(m_game.GetShortName(language)); + m_short_maker->setText(m_game.GetShortMaker(language)); + m_long_name->setText(m_game.GetLongName(language)); + m_long_maker->setText(m_game.GetLongMaker(language)); + m_description->setText(m_game.GetDescription(language)); +} + +QWidget* InfoWidget::CreateChecksumComputer() +{ + QWidget* widget = new QWidget(); + QHBoxLayout* layout = new QHBoxLayout(); + layout->setContentsMargins(0, 0, 0, 0); + + m_checksum_result = new QLineEdit(); + QPushButton* calculate = new QPushButton(tr("Compute")); + connect(calculate, &QPushButton::clicked, this, &InfoWidget::ComputeChecksum); + layout->addWidget(m_checksum_result); + layout->addWidget(calculate); + + widget->setLayout(layout); + return widget; +} + +void InfoWidget::ComputeChecksum() +{ + QCryptographicHash hash(QCryptographicHash::Md5); + hash.reset(); + std::unique_ptr file( + DiscIO::CreateBlobReader(m_game.GetFilePath().toStdString())); + std::vector file_data(8 * 1080 * 1080); // read 1MB at a time + u64 game_size = file->GetDataSize(); + u64 read_offset = 0; + + // a maximum of 1000 is used instead of game_size because otherwise 8GB games overflow the int + // typed maximum parameter + QProgressDialog* progress = + new QProgressDialog(tr("Computing MD5 Checksum"), tr("Cancel"), 0, 1000, this); + progress->setWindowTitle(tr("Computing MD5 Checksum")); + progress->setMinimumDuration(500); + progress->setWindowModality(Qt::WindowModal); + while (read_offset < game_size) + { + progress->setValue(static_cast(read_offset) / static_cast(game_size) * 1000); + if (progress->wasCanceled()) + return; + + u64 read_size = std::min(file_data.size(), game_size - read_offset); + file->Read(read_offset, read_size, file_data.data()); + hash.addData(reinterpret_cast(file_data.data()), read_size); + read_offset += read_size; + } + m_checksum_result->setText(QString::fromUtf8(hash.result().toHex())); + Q_ASSERT(read_offset == game_size); + progress->setValue(1000); +} diff --git a/Source/Core/DolphinQt2/Config/InfoWidget.h b/Source/Core/DolphinQt2/Config/InfoWidget.h new file mode 100644 index 0000000000..38c73b4a1c --- /dev/null +++ b/Source/Core/DolphinQt2/Config/InfoWidget.h @@ -0,0 +1,44 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "DolphinQt2/GameList/GameFile.h" + +class QComboBox; +class QGroupBox; +class QTextEdit; +class QLineEdit; + +class InfoWidget final : public QWidget +{ + Q_OBJECT +public: + explicit InfoWidget(const GameFile& game); + +private slots: + void ComputeChecksum(); + void ChangeLanguage(); + void SaveBanner(); + +private: + QGroupBox* CreateBannerDetails(); + QGroupBox* CreateISODetails(); + QLineEdit* CreateValueDisplay() { return CreateValueDisplay(QStringLiteral("")); }; + QLineEdit* CreateValueDisplay(const QString& value); + QWidget* CreateChecksumComputer(); + void CreateLanguageSelector(); + QWidget* CreateBannerGraphic(); + + GameFile m_game; + QLineEdit* m_checksum_result; + QComboBox* m_language_selector; + QLineEdit* m_long_name; + QLineEdit* m_short_name; + QLineEdit* m_short_maker; + QLineEdit* m_long_maker; + QTextEdit* m_description; +}; diff --git a/Source/Core/DolphinQt2/Config/PropertiesDialog.cpp b/Source/Core/DolphinQt2/Config/PropertiesDialog.cpp new file mode 100644 index 0000000000..6d00e21b9b --- /dev/null +++ b/Source/Core/DolphinQt2/Config/PropertiesDialog.cpp @@ -0,0 +1,30 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include + +#include "DolphinQt2/Config/FilesystemWidget.h" +#include "DolphinQt2/Config/InfoWidget.h" +#include "DolphinQt2/Config/PropertiesDialog.h" + +PropertiesDialog::PropertiesDialog(QWidget* parent, const GameFile& game) : QDialog(parent) +{ + setWindowTitle(QStringLiteral("%1: %2").arg(game.GetUniqueID()).arg(game.GetLongName())); + QVBoxLayout* layout = new QVBoxLayout(); + + QTabWidget* tab_widget = new QTabWidget(this); + InfoWidget* info = new InfoWidget(game); + FilesystemWidget* filesystem = new FilesystemWidget(game); + tab_widget->addTab(info, tr("Info")); + tab_widget->addTab(filesystem, tr("Filesystem")); + layout->addWidget(tab_widget); + + QDialogButtonBox* ok_box = new QDialogButtonBox(QDialogButtonBox::Ok); + connect(ok_box, &QDialogButtonBox::accepted, this, &PropertiesDialog::accept); + layout->addWidget(ok_box); + + setLayout(layout); +} diff --git a/Source/Core/DolphinQt2/Config/PropertiesDialog.h b/Source/Core/DolphinQt2/Config/PropertiesDialog.h new file mode 100644 index 0000000000..f640f4e536 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/PropertiesDialog.h @@ -0,0 +1,16 @@ +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "DolphinQt2/GameList/GameFile.h" + +class PropertiesDialog final : public QDialog +{ + Q_OBJECT +public: + explicit PropertiesDialog(QWidget* parent, const GameFile& game); +}; diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 0494619944..1c69275b5b 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -78,7 +78,10 @@ + + + @@ -96,22 +99,28 @@ + + + + + + diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters b/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters index 5d141f9f6d..77def9d722 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj.filters @@ -75,6 +75,18 @@ Generated Files + + + Generated Files + + + Generated Files + + + + + Generated Files + @@ -104,6 +116,9 @@ + + + diff --git a/Source/Core/DolphinQt2/GameList/GameFile.cpp b/Source/Core/DolphinQt2/GameList/GameFile.cpp index 8efb267e24..3f7b9c3016 100644 --- a/Source/Core/DolphinQt2/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt2/GameList/GameFile.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include #include @@ -20,6 +18,11 @@ static const int CACHE_VERSION = 13; // Last changed in PR #3261 static const int DATASTREAM_VERSION = QDataStream::Qt_5_5; +QList GameFile::GetAvailableLanguages() const +{ + return m_long_names.keys(); +} + static QMap ConvertLanguageMap(const std::map& map) { @@ -137,22 +140,22 @@ bool GameFile::TryLoadVolume() return false; m_unique_id = QString::fromStdString(volume->GetUniqueID()); - m_maker_id = QString::fromStdString(volume->GetMakerID()); + std::string maker_id = volume->GetMakerID(); + m_maker = QString::fromStdString(DiscIO::GetCompanyFromID(maker_id)); + m_maker_id = QString::fromStdString(maker_id); m_revision = volume->GetRevision(); m_internal_name = QString::fromStdString(volume->GetInternalName()); - m_short_names = ConvertLanguageMap(volume->GetNames(false)); - m_long_names = ConvertLanguageMap(volume->GetNames(true)); + m_short_names = ConvertLanguageMap(volume->GetShortNames()); + m_long_names = ConvertLanguageMap(volume->GetLongNames()); + m_short_makers = ConvertLanguageMap(volume->GetShortMakers()); + m_long_makers = ConvertLanguageMap(volume->GetLongMakers()); m_descriptions = ConvertLanguageMap(volume->GetDescriptions()); - m_company = QString::fromStdString(volume->GetCompany()); m_disc_number = volume->GetDiscNumber(); m_platform = volume->GetVolumeType(); m_country = volume->GetCountry(); m_blob_type = volume->GetBlobType(); m_raw_size = volume->GetRawSize(); - - if (m_company.isEmpty() && m_unique_id.size() >= 6) - m_company = - QString::fromStdString(DiscIO::GetCompanyFromID(m_unique_id.mid(4, 2).toStdString())); + m_apploader_date = QString::fromStdString(volume->GetApploaderDate()); ReadBanner(*volume); @@ -176,12 +179,13 @@ bool GameFile::TryLoadElfDol() return true; } + void GameFile::SaveCache() { // TODO } -QString GameFile::GetLanguageString(const QMap& m) const +QString GameFile::GetBannerString(const QMap& m) const { // Try the settings language, then English, then just pick one. if (m.isEmpty()) @@ -200,3 +204,100 @@ QString GameFile::GetLanguageString(const QMap 1024.0 && i.hasNext()) + { + unit = i.next(); + num /= 1024.0; + } + return QStringLiteral("%1 %2").arg(QString::number(num, 'f', 1)).arg(unit); +} diff --git a/Source/Core/DolphinQt2/GameList/GameFile.h b/Source/Core/DolphinQt2/GameList/GameFile.h index c1daed88db..b76ac077df 100644 --- a/Source/Core/DolphinQt2/GameList/GameFile.h +++ b/Source/Core/DolphinQt2/GameList/GameFile.h @@ -19,34 +19,43 @@ public: bool IsValid() const { return m_valid; } // These will be properly initialized before we try to load the file. - QString GetPath() const { return m_path; } + QString GetFilePath() const { return m_path; } QString GetFileName() const { return m_file_name; } - QString GetExtension() const { return m_extension; } - QString GetFolder() const { return m_folder; } + QString GetFileExtension() const { return m_extension; } + QString GetFileFolder() const { return m_folder; } qint64 GetFileSize() const { return m_size; } // The rest will not. QString GetUniqueID() const { return m_unique_id; } QString GetMakerID() const { return m_maker_id; } + QString GetMaker() const { return m_maker; } u16 GetRevision() const { return m_revision; } QString GetInternalName() const { return m_internal_name; } - QString GetCompany() const { return m_company; } u8 GetDiscNumber() const { return m_disc_number; } u64 GetRawSize() const { return m_raw_size; } QPixmap GetBanner() const { return m_banner; } QString GetIssues() const { return m_issues; } int GetRating() const { return m_rating; } - DiscIO::IVolume::EPlatform GetPlatform() const { return m_platform; } - DiscIO::IVolume::ECountry GetCountry() const { return m_country; } + QString GetApploaderDate() const { return m_apploader_date; } + DiscIO::IVolume::EPlatform GetPlatformID() const { return m_platform; } + QString GetPlatform() const; + DiscIO::IVolume::ECountry GetCountryID() const { return m_country; } + QString GetCountry() const; DiscIO::BlobType GetBlobType() const { return m_blob_type; } - QString GetShortName() const { return GetLanguageString(m_short_names); } + // Banner details + QString GetLanguage(DiscIO::IVolume::ELanguage lang) const; + QList GetAvailableLanguages() const; + QString GetShortName() const { return GetBannerString(m_short_names); } + QString GetShortMaker() const { return GetBannerString(m_short_makers); } + QString GetLongName() const { return GetBannerString(m_long_names); } + QString GetLongMaker() const { return GetBannerString(m_long_makers); } + QString GetDescription() const { return GetBannerString(m_descriptions); } QString GetShortName(DiscIO::IVolume::ELanguage lang) const { return m_short_names[lang]; } - QString GetLongName() const { return GetLanguageString(m_long_names); } + QString GetShortMaker(DiscIO::IVolume::ELanguage lang) const { return m_short_makers[lang]; } QString GetLongName(DiscIO::IVolume::ELanguage lang) const { return m_long_names[lang]; } - QString GetDescription() const { return GetLanguageString(m_descriptions); } + QString GetLongMaker(DiscIO::IVolume::ELanguage lang) const { return m_long_makers[lang]; } QString GetDescription(DiscIO::IVolume::ELanguage lang) const { return m_descriptions[lang]; } private: - DiscIO::IVolume::ELanguage GetDefaultLanguage() const; - QString GetLanguageString(const QMap& m) const; + QString GetBannerString(const QMap& m) const; QString GetCacheFileName() const; void ReadBanner(const DiscIO::IVolume& volume); @@ -67,11 +76,14 @@ private: qint64 m_size = 0; QString m_unique_id; + QString m_maker; QString m_maker_id; u16 m_revision = 0; QString m_internal_name; QMap m_short_names; QMap m_long_names; + QMap m_short_makers; + QMap m_long_makers; QMap m_descriptions; QString m_company; u8 m_disc_number = 0; @@ -82,4 +94,7 @@ private: QPixmap m_banner; QString m_issues; int m_rating = 0; + QString m_apploader_date; }; + +QString FormatSize(qint64 size); diff --git a/Source/Core/DolphinQt2/GameList/GameList.cpp b/Source/Core/DolphinQt2/GameList/GameList.cpp index 8c407b846c..5559187c2e 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.cpp +++ b/Source/Core/DolphinQt2/GameList/GameList.cpp @@ -8,6 +8,7 @@ #include #include +#include "DolphinQt2/Config/PropertiesDialog.h" #include "DolphinQt2/GameList/GameList.h" #include "DolphinQt2/GameList/ListProxyModel.h" #include "DolphinQt2/GameList/TableDelegate.h" @@ -103,12 +104,26 @@ void GameList::MakeListView() void GameList::ShowContextMenu(const QPoint&) { QMenu* menu = new QMenu(this); - menu->addAction(tr("Properties")); - menu->addAction(tr("Open Wiki Page"), this, SLOT(OpenWiki())); - menu->addAction(tr("Set as Default ISO"), this, SLOT(SetDefaultISO())); + DiscIO::IVolume::EPlatform platform = GameFile(GetSelectedGame()).GetPlatformID(); + if (platform == DiscIO::IVolume::GAMECUBE_DISC || platform == DiscIO::IVolume::WII_DISC) + { + menu->addAction(tr("Properties"), this, SLOT(OpenProperties())); + menu->addAction(tr("Open Wiki Page"), this, SLOT(OpenWiki())); + menu->addAction(tr("Set as Default ISO"), this, SLOT(SetDefaultISO())); + } + else + { + return; + } menu->exec(QCursor::pos()); } +void GameList::OpenProperties() +{ + PropertiesDialog* properties = new PropertiesDialog(this, GameFile(GetSelectedGame())); + properties->show(); +} + void GameList::OpenWiki() { QString game_id = GameFile(GetSelectedGame()).GetUniqueID(); diff --git a/Source/Core/DolphinQt2/GameList/GameList.h b/Source/Core/DolphinQt2/GameList/GameList.h index 2ba457b950..45f8b2d979 100644 --- a/Source/Core/DolphinQt2/GameList/GameList.h +++ b/Source/Core/DolphinQt2/GameList/GameList.h @@ -29,6 +29,7 @@ public slots: void SetViewColumn(int col, bool view) { m_table->setColumnHidden(col, !view); } private slots: void ShowContextMenu(const QPoint&); + void OpenProperties(); void OpenWiki(); void SetDefaultISO(); diff --git a/Source/Core/DolphinQt2/GameList/GameListModel.cpp b/Source/Core/DolphinQt2/GameList/GameListModel.cpp index dac4881432..5d28daf350 100644 --- a/Source/Core/DolphinQt2/GameList/GameListModel.cpp +++ b/Source/Core/DolphinQt2/GameList/GameListModel.cpp @@ -34,11 +34,11 @@ QVariant GameListModel::data(const QModelIndex& index, int role) const case COL_DESCRIPTION: return game->GetDescription(); case COL_MAKER: - return game->GetCompany(); + return game->GetMaker(); case COL_SIZE: return game->GetFileSize(); case COL_COUNTRY: - return game->GetCountry(); + return game->GetCountryID(); case COL_RATING: return game->GetRating(); } @@ -85,7 +85,7 @@ int GameListModel::columnCount(const QModelIndex& parent) const void GameListModel::UpdateGame(QSharedPointer game) { - QString path = game->GetPath(); + QString path = game->GetFilePath(); int entry = FindGame(path); if (entry < 0) @@ -111,7 +111,7 @@ int GameListModel::FindGame(const QString& path) const { for (int i = 0; i < m_games.size(); i++) { - if (m_games[i]->GetPath() == path) + if (m_games[i]->GetFilePath() == path) return i; } return -1; diff --git a/Source/Core/DolphinQt2/GameList/GameListModel.h b/Source/Core/DolphinQt2/GameList/GameListModel.h index 4637d7e0f2..7e9474672d 100644 --- a/Source/Core/DolphinQt2/GameList/GameListModel.h +++ b/Source/Core/DolphinQt2/GameList/GameListModel.h @@ -25,7 +25,7 @@ public: int columnCount(const QModelIndex& parent) const override; // Path of the Game at the specified index. - QString GetPath(int index) const { return m_games[index]->GetPath(); } + QString GetPath(int index) const { return m_games[index]->GetFilePath(); } enum { COL_PLATFORM = 0, diff --git a/Source/Core/DolphinQt2/GameList/TableDelegate.cpp b/Source/Core/DolphinQt2/GameList/TableDelegate.cpp index c6df5bfc72..f0f2fcaadf 100644 --- a/Source/Core/DolphinQt2/GameList/TableDelegate.cpp +++ b/Source/Core/DolphinQt2/GameList/TableDelegate.cpp @@ -4,28 +4,13 @@ #include +#include "DolphinQt2/GameList/GameFile.h" #include "DolphinQt2/GameList/GameListModel.h" #include "DolphinQt2/GameList/TableDelegate.h" #include "DolphinQt2/Resources.h" static QSize NORMAL_BANNER_SIZE(96, 32); -// Convert an integer size to a friendly string representation. -static QString FormatSize(qint64 size) -{ - QStringList units{QStringLiteral("KB"), QStringLiteral("MB"), QStringLiteral("GB"), - QStringLiteral("TB")}; - QStringListIterator i(units); - QString unit = QStringLiteral("B"); - double num = (double)size; - while (num > 1024.0 && i.hasNext()) - { - unit = i.next(); - num /= 1024.0; - } - return QStringLiteral("%1 %2").arg(QString::number(num, 'f', 1)).arg(unit); -} - TableDelegate::TableDelegate(QWidget* parent) : QStyledItemDelegate(parent) { } diff --git a/Source/Core/DolphinWX/ISOFile.cpp b/Source/Core/DolphinWX/ISOFile.cpp index e61fb9875f..95b9a02e2a 100644 --- a/Source/Core/DolphinWX/ISOFile.cpp +++ b/Source/Core/DolphinWX/ISOFile.cpp @@ -47,7 +47,8 @@ static std::string GetLanguageString(DiscIO::IVolume::ELanguage language, if (it != end) return it->second; - // English tends to be a good fallback when the requested language isn't available + // English tends to be a good fallback when the requested language isn't + // available if (language != DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH) { it = strings.find(DiscIO::IVolume::ELanguage::LANGUAGE_ENGLISH); @@ -92,9 +93,13 @@ GameListItem::GameListItem(const std::string& _rFileName, { m_Platform = volume->GetVolumeType(); - m_names = volume->GetNames(true); m_descriptions = volume->GetDescriptions(); - m_company = volume->GetCompany(); + m_names = volume->GetLongNames(); + if (m_names.empty()) + m_names = volume->GetShortNames(); + m_company = GetLanguageString(DiscIO::IVolume::LANGUAGE_ENGLISH, volume->GetLongMakers()); + if (m_company.empty()) + m_company = GetLanguageString(DiscIO::IVolume::LANGUAGE_ENGLISH, volume->GetShortMakers()); m_Country = volume->GetCountry(); m_blob_type = volume->GetBlobType(); @@ -145,13 +150,16 @@ GameListItem::GameListItem(const std::string& _rFileName, std::string path, name; SplitPath(m_FileName, &path, &name, nullptr); - // A bit like the Homebrew Channel icon, except there can be multiple files in a folder with their + // A bit like the Homebrew Channel icon, except there can be multiple files in + // a folder with their // own icons. - // Useful for those who don't want to have a Homebrew Channel-style folder structure. + // Useful for those who don't want to have a Homebrew Channel-style folder + // structure. if (ReadPNGBanner(path + name + ".png")) return; - // Homebrew Channel icon. Typical for DOLs and ELFs, but can be also used with volumes. + // Homebrew Channel icon. Typical for DOLs and ELFs, but can be also used with + // volumes. if (ReadPNGBanner(path + "icon.png")) return;