From 41315b19f113b359ead37e7d6403caf08fb1e5d3 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 4 Sep 2015 19:08:30 +0200 Subject: [PATCH] DolphinWX: Support banners in Homebrew Channel format HBC uses files named icon.png for icons. This change makes Dolphin support that file name, and also [executable file name].png in case someone wants to have multiple files in one folder. The HBC banner support is mainly intended for DOL and ELF files, but it can also be used to override banners of disc images, something that wasn't possible in the past. There are currently issues with banner scaling not preserving the aspect ratio and looking bad in general. --- Source/Core/DolphinWX/ISOFile.cpp | 67 ++++++++++++++++++++++--------- Source/Core/DolphinWX/ISOFile.h | 7 +++- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/Source/Core/DolphinWX/ISOFile.cpp b/Source/Core/DolphinWX/ISOFile.cpp index 19246a0f0c..5aeca6d1c1 100644 --- a/Source/Core/DolphinWX/ISOFile.cpp +++ b/Source/Core/DolphinWX/ISOFile.cpp @@ -85,7 +85,7 @@ GameListItem::GameListItem(const std::string& _rFileName) std::unique_ptr volume(DiscIO::CreateVolumeFromFilename(_rFileName)); if (volume != nullptr) { - ReadBanner(*volume); + ReadVolumeBanner(*volume); if (!m_pImage.empty()) SaveToCache(); } @@ -112,7 +112,7 @@ GameListItem::GameListItem(const std::string& _rFileName) m_disc_number = pVolume->GetDiscNumber(); m_Revision = pVolume->GetRevision(); - ReadBanner(*pVolume); + ReadVolumeBanner(*pVolume); delete pVolume; @@ -138,24 +138,28 @@ GameListItem::GameListItem(const std::string& _rFileName) m_Platform = DiscIO::IVolume::ELF_DOL; } + 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 own icons. + // 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. + if (ReadPNGBanner(path + "icon.png")) + return; + + // Volume banner. Typical for everything that isn't a DOL or ELF. if (!m_pImage.empty()) { - wxImage Image(m_ImageWidth, m_ImageHeight, &m_pImage[0], true); - double Scale = wxTheApp->GetTopWindow()->GetContentScaleFactor(); - // Note: This uses nearest neighbor, which subjectively looks a lot - // better for GC banners than smooth scaling. - Image.Rescale(DVD_BANNER_WIDTH * Scale, DVD_BANNER_HEIGHT * Scale); -#ifdef __APPLE__ - m_Bitmap = wxBitmap(Image, -1, Scale); -#else - m_Bitmap = wxBitmap(Image, -1); -#endif - } - else - { - // default banner - m_Bitmap.LoadFile(StrToWxStr(File::GetThemeDir(SConfig::GetInstance().theme_name)) + "nobanner.png", wxBITMAP_TYPE_PNG); + wxImage image(m_ImageWidth, m_ImageHeight, &m_pImage[0], true); + m_Bitmap = ScaleBanner(&image); + return; } + + // Fallback in case no banner is available. + ReadPNGBanner(File::GetThemeDir(SConfig::GetInstance().theme_name) + "nobanner.png"); } GameListItem::~GameListItem() @@ -211,7 +215,8 @@ std::string GameListItem::CreateCacheFilename() return fullname; } -void GameListItem::ReadBanner(const DiscIO::IVolume& volume) +// Outputs to m_pImage +void GameListItem::ReadVolumeBanner(const DiscIO::IVolume& volume) { std::vector Buffer = volume.GetBanner(&m_ImageWidth, &m_ImageHeight); u32* pData = Buffer.data(); @@ -225,6 +230,32 @@ void GameListItem::ReadBanner(const DiscIO::IVolume& volume) } } +// Outputs to m_Bitmap +bool GameListItem::ReadPNGBanner(const std::string& path) +{ + if (!File::Exists(path)) + return false; + + wxImage image; + image.LoadFile(StrToWxStr(path), wxBITMAP_TYPE_PNG); + m_Bitmap = ScaleBanner(&image); + return true; +} + +wxBitmap GameListItem::ScaleBanner(wxImage* image) +{ + double scale = wxTheApp->GetTopWindow()->GetContentScaleFactor(); + // Note: This uses nearest neighbor, which subjectively looks a lot + // better for GC banners than smooth scaling. + // TODO: Make scaling less bad for Homebrew Channel banners. + image->Rescale(DVD_BANNER_WIDTH * scale, DVD_BANNER_HEIGHT * scale); +#ifdef __APPLE__ + return wxBitmap(*image, -1, scale); +#else + return wxBitmap(*image, -1); +#endif +} + std::string GameListItem::GetDescription(DiscIO::IVolume::ELanguage language) const { return GetLanguageString(language, m_descriptions); diff --git a/Source/Core/DolphinWX/ISOFile.h b/Source/Core/DolphinWX/ISOFile.h index fad3f22c9e..a96b72ddb0 100644 --- a/Source/Core/DolphinWX/ISOFile.h +++ b/Source/Core/DolphinWX/ISOFile.h @@ -84,5 +84,10 @@ private: std::string CreateCacheFilename(); - void ReadBanner(const DiscIO::IVolume& volume); + // Outputs to m_pImage + void ReadVolumeBanner(const DiscIO::IVolume& volume); + // Outputs to m_Bitmap + bool ReadPNGBanner(const std::string& path); + + static wxBitmap ScaleBanner(wxImage* image); };