summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2018-05-20 15:39:07 +0200
committerGitHub <noreply@github.com>2018-05-20 15:39:07 +0200
commit56e91bfdc178ce575a5f252ca03671a9f68ee6d8 (patch)
tree94bd53000fce61c0dd39c7aad891021ca075c864 /Source/Core
parent86c676ab0483dc53b3b08cb327816388d278a600 (diff)
parentcc42b4354d38055629ba3eeac92fa57582a26de0 (diff)
Merge pull request #6429 from JosJuice/png-banners-uicommon
Reimplement custom PNG banners in game list
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DiscIO/Volume.h2
-rw-r--r--Source/Core/DiscIO/VolumeGC.cpp2
-rw-r--r--Source/Core/DiscIO/VolumeGC.h10
-rw-r--r--Source/Core/DiscIO/VolumeWad.cpp2
-rw-r--r--Source/Core/DiscIO/VolumeWad.h2
-rw-r--r--Source/Core/DiscIO/VolumeWii.cpp2
-rw-r--r--Source/Core/DiscIO/VolumeWii.h2
-rw-r--r--Source/Core/DiscIO/WiiSaveBanner.cpp14
-rw-r--r--Source/Core/DiscIO/WiiSaveBanner.h2
-rw-r--r--Source/Core/UICommon/GameFile.cpp74
-rw-r--r--Source/Core/UICommon/GameFile.h18
-rw-r--r--Source/Core/UICommon/GameFileCache.cpp13
12 files changed, 112 insertions, 31 deletions
diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h
index f7172db6cc..f1625a9681 100644
--- a/Source/Core/DiscIO/Volume.h
+++ b/Source/Core/DiscIO/Volume.h
@@ -83,7 +83,7 @@ public:
virtual std::map<Language, std::string> GetShortMakers() const { return {}; }
virtual std::map<Language, std::string> GetLongMakers() const { return {}; }
virtual std::map<Language, std::string> GetDescriptions() const { return {}; }
- virtual std::vector<u32> GetBanner(int* width, int* height) const = 0;
+ virtual std::vector<u32> GetBanner(u32* width, u32* height) const = 0;
std::string GetApploaderDate() const { return GetApploaderDate(GetGamePartition()); }
virtual std::string GetApploaderDate(const Partition& partition) const = 0;
// 0 is the first disc, 1 is the second disc
diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp
index 12c16e10ad..eda59fff08 100644
--- a/Source/Core/DiscIO/VolumeGC.cpp
+++ b/Source/Core/DiscIO/VolumeGC.cpp
@@ -150,7 +150,7 @@ std::map<Language, std::string> VolumeGC::GetDescriptions() const
return m_converted_banner->descriptions;
}
-std::vector<u32> VolumeGC::GetBanner(int* width, int* height) const
+std::vector<u32> VolumeGC::GetBanner(u32* width, u32* height) const
{
*width = m_converted_banner->image_width;
*height = m_converted_banner->image_height;
diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h
index 4f878c3bc9..3977623f23 100644
--- a/Source/Core/DiscIO/VolumeGC.h
+++ b/Source/Core/DiscIO/VolumeGC.h
@@ -42,7 +42,7 @@ public:
std::map<Language, std::string> GetShortMakers() const override;
std::map<Language, std::string> GetLongMakers() const override;
std::map<Language, std::string> GetDescriptions() const override;
- std::vector<u32> GetBanner(int* width, int* height) const override;
+ std::vector<u32> GetBanner(u32* width, u32* height) const override;
std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override;
std::optional<u8> GetDiscNumber(const Partition& partition = PARTITION_NONE) const override;
@@ -54,8 +54,8 @@ public:
u64 GetRawSize() const override;
private:
- static const int GC_BANNER_WIDTH = 96;
- static const int GC_BANNER_HEIGHT = 32;
+ static const u32 GC_BANNER_WIDTH = 96;
+ static const u32 GC_BANNER_HEIGHT = 32;
struct GCBannerInformation
{
@@ -89,8 +89,8 @@ private:
std::map<Language, std::string> descriptions;
std::vector<u32> image_buffer;
- int image_height = 0;
- int image_width = 0;
+ u32 image_height = 0;
+ u32 image_width = 0;
};
ConvertedGCBanner LoadBannerFile() const;
diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp
index 5b601e4fb9..7a1df3e0d5 100644
--- a/Source/Core/DiscIO/VolumeWad.cpp
+++ b/Source/Core/DiscIO/VolumeWad.cpp
@@ -144,7 +144,7 @@ std::map<Language, std::string> VolumeWAD::GetLongNames() const
return ReadWiiNames(names);
}
-std::vector<u32> VolumeWAD::GetBanner(int* width, int* height) const
+std::vector<u32> VolumeWAD::GetBanner(u32* width, u32* height) const
{
*width = 0;
*height = 0;
diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h
index 9fd39db093..cd41593134 100644
--- a/Source/Core/DiscIO/VolumeWad.h
+++ b/Source/Core/DiscIO/VolumeWad.h
@@ -42,7 +42,7 @@ public:
return "";
}
std::map<Language, std::string> GetLongNames() const override;
- std::vector<u32> GetBanner(int* width, int* height) const override;
+ std::vector<u32> GetBanner(u32* width, u32* height) const override;
std::string GetApploaderDate(const Partition& partition = PARTITION_NONE) const override
{
return "";
diff --git a/Source/Core/DiscIO/VolumeWii.cpp b/Source/Core/DiscIO/VolumeWii.cpp
index fc44e29e68..d4558c0c99 100644
--- a/Source/Core/DiscIO/VolumeWii.cpp
+++ b/Source/Core/DiscIO/VolumeWii.cpp
@@ -308,7 +308,7 @@ std::map<Language, std::string> VolumeWii::GetLongNames() const
return ReadWiiNames(names);
}
-std::vector<u32> VolumeWii::GetBanner(int* width, int* height) const
+std::vector<u32> VolumeWii::GetBanner(u32* width, u32* height) const
{
*width = 0;
*height = 0;
diff --git a/Source/Core/DiscIO/VolumeWii.h b/Source/Core/DiscIO/VolumeWii.h
index b854ae5917..a173d17aa7 100644
--- a/Source/Core/DiscIO/VolumeWii.h
+++ b/Source/Core/DiscIO/VolumeWii.h
@@ -45,7 +45,7 @@ public:
std::optional<u16> GetRevision(const Partition& partition) const override;
std::string GetInternalName(const Partition& partition) const override;
std::map<Language, std::string> GetLongNames() const override;
- std::vector<u32> GetBanner(int* width, int* height) const override;
+ std::vector<u32> GetBanner(u32* width, u32* height) const override;
std::string GetApploaderDate(const Partition& partition) const override;
std::optional<u8> GetDiscNumber(const Partition& partition) const override;
diff --git a/Source/Core/DiscIO/WiiSaveBanner.cpp b/Source/Core/DiscIO/WiiSaveBanner.cpp
index 444cb0590d..5bfb87c273 100644
--- a/Source/Core/DiscIO/WiiSaveBanner.cpp
+++ b/Source/Core/DiscIO/WiiSaveBanner.cpp
@@ -16,13 +16,13 @@
namespace DiscIO
{
-constexpr unsigned int BANNER_WIDTH = 192;
-constexpr unsigned int BANNER_HEIGHT = 64;
-constexpr unsigned int BANNER_SIZE = BANNER_WIDTH * BANNER_HEIGHT * 2;
+constexpr u32 BANNER_WIDTH = 192;
+constexpr u32 BANNER_HEIGHT = 64;
+constexpr u32 BANNER_SIZE = BANNER_WIDTH * BANNER_HEIGHT * 2;
-constexpr unsigned int ICON_WIDTH = 48;
-constexpr unsigned int ICON_HEIGHT = 48;
-constexpr unsigned int ICON_SIZE = ICON_WIDTH * ICON_HEIGHT * 2;
+constexpr u32 ICON_WIDTH = 48;
+constexpr u32 ICON_HEIGHT = 48;
+constexpr u32 ICON_SIZE = ICON_WIDTH * ICON_HEIGHT * 2;
WiiSaveBanner::WiiSaveBanner(u64 title_id)
: WiiSaveBanner(Common::GetTitleDataPath(title_id, Common::FROM_CONFIGURED_ROOT) +
@@ -55,7 +55,7 @@ std::string WiiSaveBanner::GetDescription() const
return UTF16BEToUTF8(m_header.description, ArraySize(m_header.description));
}
-std::vector<u32> WiiSaveBanner::GetBanner(int* width, int* height) const
+std::vector<u32> WiiSaveBanner::GetBanner(u32* width, u32* height) const
{
*width = 0;
*height = 0;
diff --git a/Source/Core/DiscIO/WiiSaveBanner.h b/Source/Core/DiscIO/WiiSaveBanner.h
index eb199e5ec4..aa0c47393d 100644
--- a/Source/Core/DiscIO/WiiSaveBanner.h
+++ b/Source/Core/DiscIO/WiiSaveBanner.h
@@ -22,7 +22,7 @@ public:
std::string GetName() const;
std::string GetDescription() const;
- std::vector<u32> GetBanner(int* width, int* height) const;
+ std::vector<u32> GetBanner(u32* width, u32* height) const;
private:
struct Header
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 <memory>
#include <sstream>
#include <string>
+#include <tuple>
#include <utility>
#include <vector>
@@ -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<DiscIO::Language, std::string>& 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<u8> png_data(file.GetSize());
+ if (!file.ReadBytes(png_data.data(), png_data.size()))
+ return false;
+
+ GameBanner& banner = m_pending.custom_banner;
+ std::vector<u8> 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
diff --git a/Source/Core/UICommon/GameFile.h b/Source/Core/UICommon/GameFile.h
index aa33cd7c65..df5845ab83 100644
--- a/Source/Core/UICommon/GameFile.h
+++ b/Source/Core/UICommon/GameFile.h
@@ -31,12 +31,15 @@ namespace UICommon
struct GameBanner
{
std::vector<u32> buffer{};
- int width{};
- int height{};
+ u32 width{};
+ u32 height{};
bool empty() const { return buffer.empty(); }
void DoState(PointerWrap& p);
};
+bool operator==(const GameBanner& lhs, const GameBanner& rhs);
+bool operator!=(const GameBanner& lhs, const GameBanner& rhs);
+
// This class caches the metadata of a DiscIO::Volume (or a DOL/ELF file).
class GameFile final
{
@@ -77,10 +80,12 @@ public:
const std::string& GetApploaderDate() const { return m_apploader_date; }
u64 GetFileSize() const { return m_file_size; }
u64 GetVolumeSize() const { return m_volume_size; }
- const GameBanner& GetBannerImage() const { return m_volume_banner; }
+ const GameBanner& GetBannerImage() const;
void DoState(PointerWrap& p);
- bool BannerChanged();
- void BannerCommit();
+ bool WiiBannerChanged();
+ void WiiBannerCommit();
+ bool CustomBannerChanged();
+ void CustomBannerCommit();
bool CustomNameChanged(const Core::TitleDatabase& title_database);
void CustomNameCommit();
@@ -90,6 +95,7 @@ private:
const std::string&
LookupUsingConfigLanguage(const std::map<DiscIO::Language, std::string>& strings) const;
bool IsElfOrDol() const;
+ bool ReadPNGBanner(const std::string& path);
// IMPORTANT: Nearly all data members must be save/restored in DoState.
// If anything is changed, make sure DoState handles it properly and
@@ -121,6 +127,7 @@ private:
std::string m_apploader_date{};
GameBanner m_volume_banner{};
+ GameBanner m_custom_banner{};
// Overridden name from TitleDatabase
std::string m_custom_name{};
@@ -129,6 +136,7 @@ private:
struct
{
GameBanner volume_banner;
+ GameBanner custom_banner;
std::string custom_name;
} m_pending{};
};
diff --git a/Source/Core/UICommon/GameFileCache.cpp b/Source/Core/UICommon/GameFileCache.cpp
index 9c18b78e81..9dc25740f9 100644
--- a/Source/Core/UICommon/GameFileCache.cpp
+++ b/Source/Core/UICommon/GameFileCache.cpp
@@ -28,7 +28,7 @@
namespace UICommon
{
-static constexpr u32 CACHE_REVISION = 9; // Last changed in PR 6569
+static constexpr u32 CACHE_REVISION = 10; // Last changed in PR 6429
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
bool recursive_scan)
@@ -138,17 +138,20 @@ bool GameFileCache::UpdateAdditionalMetadata(const Core::TitleDatabase& title_da
bool GameFileCache::UpdateAdditionalMetadata(std::shared_ptr<GameFile>* game_file,
const Core::TitleDatabase& title_database)
{
- const bool banner_changed = (*game_file)->BannerChanged();
+ const bool wii_banner_changed = (*game_file)->WiiBannerChanged();
+ const bool custom_banner_changed = (*game_file)->CustomBannerChanged();
const bool custom_title_changed = (*game_file)->CustomNameChanged(title_database);
- if (!banner_changed && !custom_title_changed)
+ if (!wii_banner_changed && !custom_banner_changed && !custom_title_changed)
return false;
// If a cached file needs an update, apply the updates to a copy and delete the original.
// This makes the usage of cached files in other threads safe.
std::shared_ptr<GameFile> copy = std::make_shared<GameFile>(**game_file);
- if (banner_changed)
- copy->BannerCommit();
+ if (wii_banner_changed)
+ copy->WiiBannerCommit();
+ if (custom_banner_changed)
+ copy->CustomBannerCommit();
if (custom_title_changed)
copy->CustomNameCommit();
*game_file = std::move(copy);