From cc42b4354d38055629ba3eeac92fa57582a26de0 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 10 Mar 2018 22:41:49 +0100 Subject: Reimplement custom PNG banners in game list Fixes https://bugs.dolphin-emu.org/issues/10938 and makes PNG banners available in DolphinQt2 for the first time. --- Source/Core/UICommon/GameFile.cpp | 74 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) (limited to 'Source/Core/UICommon/GameFile.cpp') diff --git a/Source/Core/UICommon/GameFile.cpp b/Source/Core/UICommon/GameFile.cpp index cbd7077987..90f87bb016 100644 --- a/Source/Core/UICommon/GameFile.cpp +++ b/Source/Core/UICommon/GameFile.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -21,9 +22,11 @@ #include "Common/CommonTypes.h" #include "Common/FileUtil.h" #include "Common/Hash.h" +#include "Common/Image.h" #include "Common/IniFile.h" #include "Common/NandPaths.h" #include "Common/StringUtil.h" +#include "Common/Swap.h" #include "Core/Boot/Boot.h" #include "Core/ConfigManager.h" @@ -39,6 +42,16 @@ namespace UICommon { static const std::string EMPTY_STRING; +bool operator==(const GameBanner& lhs, const GameBanner& rhs) +{ + return std::tie(lhs.buffer, lhs.width, lhs.height) == std::tie(rhs.buffer, rhs.width, rhs.height); +} + +bool operator!=(const GameBanner& lhs, const GameBanner& rhs) +{ + return !operator==(lhs, rhs); +} + const std::string& GameFile::Lookup(DiscIO::Language language, const std::map& strings) { @@ -177,6 +190,7 @@ void GameFile::DoState(PointerWrap& p) p.Do(m_apploader_date); m_volume_banner.DoState(p); + m_custom_banner.DoState(p); p.Do(m_custom_name); } @@ -190,7 +204,7 @@ bool GameFile::IsElfOrDol() const return name_end == ".elf" || name_end == ".dol"; } -bool GameFile::BannerChanged() +bool GameFile::WiiBannerChanged() { // Wii banners can only be read if there is a save file. // In case the cache was created without a save file existing, @@ -210,11 +224,62 @@ bool GameFile::BannerChanged() return !m_pending.volume_banner.buffer.empty(); } -void GameFile::BannerCommit() +void GameFile::WiiBannerCommit() { m_volume_banner = std::move(m_pending.volume_banner); } +bool GameFile::ReadPNGBanner(const std::string& path) +{ + File::IOFile file(path, "rb"); + if (!file) + return false; + + std::vector png_data(file.GetSize()); + if (!file.ReadBytes(png_data.data(), png_data.size())) + return false; + + GameBanner& banner = m_pending.custom_banner; + std::vector data_out; + if (!Common::LoadPNG(png_data, &data_out, &banner.width, &banner.height)) + return false; + + // Make an ARGB copy of the RGBA data + banner.buffer.resize(data_out.size() / sizeof(u32)); + for (size_t i = 0; i < banner.buffer.size(); i++) + { + const size_t j = i * sizeof(u32); + banner.buffer[i] = (Common::swap32(data_out.data() + j) >> 8) + (data_out[j] << 24); + } + + return true; +} + +bool GameFile::CustomBannerChanged() +{ + std::string path, name; + SplitPath(m_file_path, &path, &name, nullptr); + + // This icon naming format is intended as an alternative to Homebrew Channel icons + // for those who don't want to have a Homebrew Channel style folder structure. + if (!ReadPNGBanner(path + name + ".png")) + { + // Homebrew Channel icon naming. Typical for DOLs and ELFs, but we also support it for volumes. + if (!ReadPNGBanner(path + "icon.png")) + { + // If no custom icon is found, go back to the non-custom one. + m_pending.custom_banner = {}; + } + } + + return m_pending.custom_banner != m_custom_banner; +} + +void GameFile::CustomBannerCommit() +{ + m_custom_banner = std::move(m_pending.custom_banner); +} + const std::string& GameFile::GetName(bool long_name) const { if (!m_custom_name.empty()) @@ -287,4 +352,9 @@ std::string GameFile::GetWiiFSPath() const return Common::GetTitleDataPath(m_title_id, Common::FROM_CONFIGURED_ROOT); } +const GameBanner& GameFile::GetBannerImage() const +{ + return m_custom_banner.empty() ? m_volume_banner : m_custom_banner; +} + } // namespace UICommon -- cgit v1.2.3