diff --git a/Source/Core/DiscIO/BannerLoader.cpp b/Source/Core/DiscIO/BannerLoader.cpp deleted file mode 100644 index b5353b5a0f..0000000000 --- a/Source/Core/DiscIO/BannerLoader.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include - -#include "DiscIO/BannerLoader.h" -#include "DiscIO/BannerLoaderGC.h" -#include "DiscIO/BannerLoaderWii.h" -#include "DiscIO/Filesystem.h" - -namespace DiscIO -{ - -class IBannerLoader; -class IVolume; - -IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume) -{ - if (pVolume->IsWiiDisc() || pVolume->IsWadFile()) - return new CBannerLoaderWii(pVolume); - if (_rFileSystem.IsValid()) - return new CBannerLoaderGC(_rFileSystem, pVolume); - - return nullptr; -} - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoader.h b/Source/Core/DiscIO/BannerLoader.h deleted file mode 100644 index 31a09f56d0..0000000000 --- a/Source/Core/DiscIO/BannerLoader.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "DiscIO/Volume.h" - -namespace DiscIO -{ - -class IFileSystem; -class IVolume; - -class IBannerLoader -{ -public: - IBannerLoader() - : m_IsValid(false) - , m_pBannerFile(nullptr) - {} - - virtual ~IBannerLoader() - {} - - virtual std::vector GetBanner(int* pWidth, int* pHeight) = 0; - - virtual std::map GetNames() = 0; - virtual std::string GetCompany() = 0; - virtual std::map GetDescriptions() = 0; - - bool IsValid() - { - return m_IsValid; - } - -protected: - bool m_IsValid; - u8* m_pBannerFile; -}; - -IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume); - -} // namespace DiscIO diff --git a/Source/Core/DiscIO/BannerLoaderGC.cpp b/Source/Core/DiscIO/BannerLoaderGC.cpp deleted file mode 100644 index a5da3c4512..0000000000 --- a/Source/Core/DiscIO/BannerLoaderGC.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include -#include -#include -#include - -#include "Common/ColorUtil.h" -#include "Common/CommonTypes.h" -#include "Common/MsgHandler.h" -#include "Common/Logging/Log.h" -#include "DiscIO/BannerLoaderGC.h" -#include "DiscIO/Filesystem.h" -#include "DiscIO/Volume.h" - -namespace DiscIO -{ -CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume) - : m_country(volume->GetCountry()) -{ - // load the opening.bnr - size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); - if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE) - { - m_pBannerFile = new u8[FileSize]; - if (m_pBannerFile) - { - _rFileSystem.ReadFile("opening.bnr", m_pBannerFile, FileSize); - m_BNRType = getBannerType(); - if (m_BNRType == BANNER_UNKNOWN) - PanicAlertT("Invalid opening.bnr found in gcm:\n%s\n You may need to redump this game.", - _rFileSystem.GetVolume()->GetName().c_str()); - else m_IsValid = true; - } - } - else WARN_LOG(DISCIO, "Invalid opening.bnr size: %0lx", - (unsigned long)FileSize); -} - - -CBannerLoaderGC::~CBannerLoaderGC() -{ - if (m_pBannerFile) - { - delete [] m_pBannerFile; - m_pBannerFile = nullptr; - } -} - -std::vector CBannerLoaderGC::GetBanner(int* pWidth, int* pHeight) -{ - std::vector Buffer; - Buffer.resize(DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT); - auto const pBanner = (DVDBanner*)m_pBannerFile; - ColorUtil::decode5A3image(&Buffer[0], pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); - *pWidth = DVD_BANNER_WIDTH; - *pHeight = DVD_BANNER_HEIGHT; - return Buffer; -} - - -std::map CBannerLoaderGC::GetNames() -{ - std::map names; - - if (!IsValid()) - { - return names; - } - - u32 name_count = 0; - IVolume::ELanguage language; - bool is_japanese = m_country == IVolume::ECountry::COUNTRY_JAPAN; - - // find Banner type - switch (m_BNRType) - { - case CBannerLoaderGC::BANNER_BNR1: - name_count = 1; - language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - // English, German, French, Spanish, Italian, Dutch - case CBannerLoaderGC::BANNER_BNR2: - name_count = 6; - language = IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - default: - break; - } - - auto const banner = reinterpret_cast(m_pBannerFile); - - for (u32 i = 0; i < name_count; ++i) - { - auto& comment = banner->comment[i]; - std::string name = GetDecodedString(comment.longTitle); - - if (name.empty()) - name = GetDecodedString(comment.shortTitle); - - if (!name.empty()) - names[(IVolume::ELanguage)(language + i)] = name; - } - - return names; -} - - -std::string CBannerLoaderGC::GetCompany() -{ - std::string company; - - if (IsValid()) - { - auto const pBanner = (DVDBanner*)m_pBannerFile; - auto& data = pBanner->comment[0].shortMaker; - company = GetDecodedString(data); - } - - return company; -} - - -std::map CBannerLoaderGC::GetDescriptions() -{ - std::map descriptions; - - if (!IsValid()) - { - return descriptions; - } - - u32 desc_count = 0; - IVolume::ELanguage language; - bool is_japanese = m_country == IVolume::ECountry::COUNTRY_JAPAN; - - // find Banner type - switch (m_BNRType) - { - case CBannerLoaderGC::BANNER_BNR1: - desc_count = 1; - language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH; - break; - - // English, German, French, Spanish, Italian, Dutch - case CBannerLoaderGC::BANNER_BNR2: - language = IVolume::ELanguage::LANGUAGE_ENGLISH; - desc_count = 6; - break; - - default: - break; - } - - auto banner = reinterpret_cast(m_pBannerFile); - - for (u32 i = 0; i < desc_count; ++i) - { - auto& data = banner->comment[i].comment; - std::string description = GetDecodedString(data); - - if (!description.empty()) - descriptions[(IVolume::ELanguage)(language + i)] = description; - } - - return descriptions; -} - -CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType() -{ - u32 bannerSignature = *(u32*)m_pBannerFile; - switch (bannerSignature) - { - case 0x31524e42: // "BNR1" - return CBannerLoaderGC::BANNER_BNR1; - case 0x32524e42: // "BNR2" - return CBannerLoaderGC::BANNER_BNR2; - default: - return CBannerLoaderGC::BANNER_UNKNOWN; - } -} - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoaderGC.h b/Source/Core/DiscIO/BannerLoaderGC.h deleted file mode 100644 index b381e10f92..0000000000 --- a/Source/Core/DiscIO/BannerLoaderGC.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include - -#include "Common/CommonTypes.h" - -#include "DiscIO/BannerLoader.h" -#include "DiscIO/Volume.h" -#include "DiscIO/VolumeGC.h" - -namespace DiscIO -{ - -class IFileSystem; - -class CBannerLoaderGC - : public IBannerLoader -{ -public: - CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume); - virtual ~CBannerLoaderGC(); - - virtual std::vector GetBanner(int* pWidth, int* pHeight) override; - - virtual std::map GetNames() override; - virtual std::string GetCompany() override; - virtual std::map GetDescriptions() override; - -private: - enum - { - DVD_BANNER_WIDTH = 96, - DVD_BANNER_HEIGHT = 32 - }; - - enum BANNER_TYPE - { - BANNER_UNKNOWN, - BANNER_BNR1, - BANNER_BNR2, - }; - - // Banner Comment - struct DVDBannerComment - { - 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. - }; - - // "opening.bnr" file format for EU console - struct DVDBanner - { - u32 id; // 'BNR2' - u32 padding[7]; - u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image - DVDBannerComment comment[6]; // Comments in six languages (only 1 for BNR1 type) - }; - - static const u32 BNR1_SIZE = sizeof(DVDBanner) - sizeof(DVDBannerComment) * 5; - static const u32 BNR2_SIZE = sizeof(DVDBanner); - - template - std::string GetDecodedString(const char (&data)[N]) - { - auto const string_decoder = CVolumeGC::GetStringDecoder(m_country); - - // strnlen to trim NULLs - return string_decoder(std::string(data, strnlen(data, sizeof(data)))); - } - - BANNER_TYPE m_BNRType; - BANNER_TYPE getBannerType(); - - DiscIO::IVolume::ECountry const m_country; -}; - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoaderWii.cpp b/Source/Core/DiscIO/BannerLoaderWii.cpp deleted file mode 100644 index 1de9120c10..0000000000 --- a/Source/Core/DiscIO/BannerLoaderWii.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include -#include -#include -#include -#include -#include - -#include "Common/ColorUtil.h" -#include "Common/CommonFuncs.h" -#include "Common/CommonTypes.h" -#include "Common/FileUtil.h" -#include "Common/StringUtil.h" - -#include "DiscIO/BannerLoaderWii.h" -#include "DiscIO/Volume.h" - -namespace DiscIO -{ - -CBannerLoaderWii::CBannerLoaderWii(DiscIO::IVolume *pVolume) -{ - u64 TitleID = 0; - pVolume->GetTitleID((u8*)&TitleID); - TitleID = Common::swap64(TitleID); - - std::string Filename = StringFromFormat("%stitle/%08x/%08x/data/banner.bin", - File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(TitleID>>32), (u32)TitleID); - - if (!File::Exists(Filename)) - { - m_IsValid = false; - return; - } - - // load the banner.bin - size_t FileSize = (size_t) File::GetSize(Filename); - - if (FileSize > 0) - { - m_pBannerFile = new u8[FileSize]; - File::IOFile pFile(Filename, "rb"); - if (pFile) - { - pFile.ReadBytes(m_pBannerFile, FileSize); - m_IsValid = true; - } - } -} - -CBannerLoaderWii::~CBannerLoaderWii() -{ - if (m_pBannerFile) - { - delete [] m_pBannerFile; - m_pBannerFile = nullptr; - } -} - -std::vector CBannerLoaderWii::GetBanner(int* pWidth, int* pHeight) -{ - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - std::vector Buffer; - Buffer.resize(192 * 64); - ColorUtil::decode5A3image(&Buffer[0], (u16*)pBanner->m_BannerTexture, 192, 64); - *pWidth = 192; - *pHeight = 64; - return Buffer; -} - -bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result) -{ - if (IsValid()) - { - auto const banner = reinterpret_cast(m_pBannerFile); - auto const src_ptr = banner->m_Comment[index]; - - // Trim at first nullptr - auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr; - - std::wstring src; - src.resize(length); - std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16); - result = UTF16ToUTF8(src); - - return true; - } - - return false; -} - -std::map CBannerLoaderWii::GetNames() -{ - std::map result; - - std::string name; - if (GetStringFromComments(NAME_IDX, name)) - result[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name; - - return result; -} - -std::string CBannerLoaderWii::GetCompany() -{ - return ""; -} - -std::map CBannerLoaderWii::GetDescriptions() -{ - std::map result; - - std::string name; - if (GetStringFromComments(DESC_IDX, name)) - result[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name; - - return result; -} - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoaderWii.h b/Source/Core/DiscIO/BannerLoaderWii.h deleted file mode 100644 index 29d3b0f470..0000000000 --- a/Source/Core/DiscIO/BannerLoaderWii.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "DiscIO/BannerLoader.h" - -namespace DiscIO -{ - -class IVolume; - -class CBannerLoaderWii - : public IBannerLoader -{ -public: - CBannerLoaderWii(DiscIO::IVolume *pVolume); - - virtual ~CBannerLoaderWii(); - - virtual std::vector GetBanner(int* pWidth, int* pHeight) override; - - virtual std::map GetNames() override; - virtual std::string GetCompany() override; - virtual std::map GetDescriptions() override; - -private: - enum - { - TEXTURE_SIZE = 192 * 64 * 2, - ICON_SIZE = 48 * 48 * 2, - COMMENT_SIZE = 32 - }; - - enum CommentIndex - { - NAME_IDX, - DESC_IDX - }; - - struct SWiiBanner - { - u32 ID; - - u32 m_Flag; - u16 m_Speed; - u8 m_Unknown[22]; - - // Not null terminated! - u16 m_Comment[2][COMMENT_SIZE]; - u8 m_BannerTexture[TEXTURE_SIZE]; - u8 m_IconTexture[8][ICON_SIZE]; - }; - - bool GetStringFromComments(const CommentIndex index, std::string& s); -}; - -} // namespace diff --git a/Source/Core/DiscIO/CMakeLists.txt b/Source/Core/DiscIO/CMakeLists.txt index 7cc2859053..e9f20ffe8d 100644 --- a/Source/Core/DiscIO/CMakeLists.txt +++ b/Source/Core/DiscIO/CMakeLists.txt @@ -1,7 +1,4 @@ -set(SRCS BannerLoader.cpp - BannerLoaderGC.cpp - BannerLoaderWii.cpp - Blob.cpp +set(SRCS Blob.cpp CISOBlob.cpp WbfsBlob.cpp CompressedBlob.cpp diff --git a/Source/Core/DiscIO/DiscIO.vcxproj b/Source/Core/DiscIO/DiscIO.vcxproj index 5ef6853456..b0a9ef63fd 100644 --- a/Source/Core/DiscIO/DiscIO.vcxproj +++ b/Source/Core/DiscIO/DiscIO.vcxproj @@ -35,9 +35,6 @@ - - - @@ -58,9 +55,6 @@ - - - diff --git a/Source/Core/DiscIO/DiscIO.vcxproj.filters b/Source/Core/DiscIO/DiscIO.vcxproj.filters index 1f5f383831..3d27813cba 100644 --- a/Source/Core/DiscIO/DiscIO.vcxproj.filters +++ b/Source/Core/DiscIO/DiscIO.vcxproj.filters @@ -24,15 +24,6 @@ DiscScrubber - - FileHandler - - - FileHandler - - - FileHandler - FileSystem @@ -89,15 +80,6 @@ DiscScrubber - - FileHandler - - - FileHandler - - - FileHandler - FileSystem diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index 50e09c34d1..ff7e6a8b63 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -11,6 +11,7 @@ #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" +#include "Common/StringUtil.h" namespace DiscIO { @@ -74,10 +75,12 @@ public: } virtual std::string GetUniqueID() const = 0; virtual std::string GetMakerID() const = 0; - virtual int GetRevision() const { return 0; } - // TODO: eliminate? - virtual std::string GetName() const; + virtual int GetRevision() const = 0; + virtual std::string GetName() const = 0; virtual std::map GetNames() 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; virtual u32 GetFSTSize() const = 0; virtual std::string GetApploaderDate() const = 0; @@ -93,6 +96,23 @@ public: // Size on disc (compressed size) virtual u64 GetRawSize() const = 0; + +protected: + template + std::string DecodeString(const char(&data)[N]) const + { + // 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... + // But maybe they would use Shift_JIS if they existed? Not sure + bool use_shift_jis = (COUNTRY_JAPAN == GetCountry() || COUNTRY_TAIWAN == GetCountry()); + + if (use_shift_jis) + return SHIFTJISToUTF8(string); + else + return CP1252ToUTF8(string); + } }; // Generic Switch function for all volumes diff --git a/Source/Core/DiscIO/VolumeCommon.cpp b/Source/Core/DiscIO/VolumeCommon.cpp index 1728e78732..e2c3117170 100644 --- a/Source/Core/DiscIO/VolumeCommon.cpp +++ b/Source/Core/DiscIO/VolumeCommon.cpp @@ -4,15 +4,59 @@ #include #include +#include #include +#include "Common/ColorUtil.h" +#include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" +#include "Common/FileUtil.h" +#include "Common/StringUtil.h" #include "Common/Logging/Log.h" #include "DiscIO/Volume.h" -// Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp) namespace DiscIO { + +static const unsigned int WII_BANNER_WIDTH = 192; +static const unsigned int WII_BANNER_HEIGHT = 64; +static const unsigned int WII_BANNER_SIZE = WII_BANNER_WIDTH * WII_BANNER_HEIGHT * 2; +static const unsigned int WII_BANNER_OFFSET = 0xA0; + +std::vector IVolume::GetBanner(int* width, int* height) const +{ + *width = 0; + *height = 0; + + u64 TitleID = 0; + GetTitleID((u8*)&TitleID); + TitleID = Common::swap64(TitleID); + + std::string file_name = StringFromFormat("%stitle/%08x/%08x/data/banner.bin", + File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(TitleID >> 32), (u32)TitleID); + if (!File::Exists(file_name)) + return std::vector(); + + if (File::GetSize(file_name) < WII_BANNER_OFFSET + WII_BANNER_SIZE) + return std::vector(); + + File::IOFile file(file_name, "rb"); + if (!file.Seek(WII_BANNER_OFFSET, SEEK_SET)) + return std::vector(); + + std::vector banner_file(WII_BANNER_SIZE); + if (!file.ReadBytes(banner_file.data(), banner_file.size())) + return std::vector(); + + std::vector image_buffer(WII_BANNER_WIDTH * WII_BANNER_HEIGHT); + ColorUtil::decode5A3image(image_buffer.data(), (u16*)banner_file.data(), WII_BANNER_WIDTH, WII_BANNER_HEIGHT); + + *width = WII_BANNER_WIDTH; + *height = WII_BANNER_HEIGHT; + return image_buffer; +} + +// Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp) IVolume::ECountry CountrySwitch(u8 country_code) { switch (country_code) @@ -99,13 +143,4 @@ u8 GetSysMenuRegion(u16 _TitleVersion) } } -std::string IVolume::GetName() const -{ - auto names = GetNames(); - if (names.empty()) - return ""; - else - return names.cbegin()->second; -} - } diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 9db6e58e46..876848b2d3 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -182,10 +182,21 @@ std::string CVolumeDirectory::GetMakerID() const return "VOID"; } +std::string CVolumeDirectory::GetName() const +{ + char name[0x60]; + if (Read(0x20, 0x60, (u8*)name, false)) + return DecodeString(name); + else + return ""; +} + std::map CVolumeDirectory::GetNames() const { std::map names; - names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = (char*)(&m_diskHeader[0x20]); + std::string name = GetName(); + if (!name.empty()) + names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name; return names; } diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index d283e9051b..7187e8a017 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -39,6 +39,8 @@ public: std::string GetMakerID() const override; + int GetRevision() const override { return 0; } + std::string GetName() const override; std::map GetNames() const override; void SetName(const std::string&); diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 272408011e..dd18338f63 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -8,10 +8,13 @@ #include #include +#include "Common/ColorUtil.h" #include "Common/CommonTypes.h" #include "Common/StringUtil.h" +#include "Common/Logging/Log.h" #include "DiscIO/Blob.h" #include "DiscIO/FileMonitor.h" +#include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" #include "DiscIO/VolumeGC.h" @@ -93,19 +96,133 @@ int CVolumeGC::GetRevision() const return revision; } +std::string CVolumeGC::GetName() const +{ + char name[0x60]; + if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name)) + return DecodeString(name); + else + return ""; +} + std::map CVolumeGC::GetNames() const { std::map names; - auto const string_decoder = GetStringDecoder(GetCountry()); + if (!LoadBannerFile()) + return names; - char name[0x60 + 1] = {}; - if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name)) - names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = string_decoder(name); + 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; } +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; +} + +std::string CVolumeGC::GetCompany() const +{ + if (!LoadBannerFile()) + return ""; + + auto const pBanner = (GCBanner*)m_banner_file.data(); + std::string company = DecodeString(pBanner->comment[0].longMaker); + + if (company.empty()) + company = DecodeString(pBanner->comment[0].shortMaker); + + return company; +} + +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); + auto const pBanner = (GCBanner*)m_banner_file.data(); + ColorUtil::decode5A3image(image_buffer.data(), pBanner->image, GC_BANNER_WIDTH, GC_BANNER_HEIGHT); + *width = GC_BANNER_WIDTH; + *height = GC_BANNER_HEIGHT; + return image_buffer; +} + u32 CVolumeGC::GetFSTSize() const { if (m_pReader == nullptr) @@ -155,10 +272,46 @@ bool CVolumeGC::IsDiscTwo() const return (disc_two_check == 1); } -CVolumeGC::StringDecoder CVolumeGC::GetStringDecoder(ECountry country) +bool CVolumeGC::LoadBannerFile() const { - return (COUNTRY_JAPAN == country || COUNTRY_TAIWAN == country) ? - SHIFTJISToUTF8 : CP1252ToUTF8; + // 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, + // if none of these methods are called, the file is never loaded. + + if (m_banner_file_type != BANNER_NOT_LOADED) + return m_banner_file_type != BANNER_INVALID; + + 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) + { + m_banner_file.resize(file_size); + file_system->ReadFile("opening.bnr", m_banner_file.data(), m_banner_file.size()); + + u32 bannerSignature = *(u32*)m_banner_file.data(); + switch (bannerSignature) + { + case 0x31524e42: // "BNR1" + m_banner_file_type = BANNER_BNR1; + break; + case 0x32524e42: // "BNR2" + m_banner_file_type = BANNER_BNR2; + break; + default: + m_banner_file_type = BANNER_INVALID; + WARN_LOG(DISCIO, "Invalid opening.bnr type"); + break; + } + } + else + { + m_banner_file_type = BANNER_INVALID; + WARN_LOG(DISCIO, "Invalid opening.bnr size: %0lx", (unsigned long)file_size); + } + + return m_banner_file_type != BANNER_INVALID; } } // namespace diff --git a/Source/Core/DiscIO/VolumeGC.h b/Source/Core/DiscIO/VolumeGC.h index e9757df948..3c4abcba31 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -28,7 +28,11 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; - std::map GetNames() const override; + virtual std::string GetName() const override; + std::map GetNames() const override; + std::map GetDescriptions() const override; + std::string GetCompany() const override; + std::vector GetBanner(int* width, int* height) const override; u32 GetFSTSize() const override; std::string GetApploaderDate() const override; @@ -38,11 +42,44 @@ public: u64 GetSize() const override; u64 GetRawSize() const override; - typedef std::string(*StringDecoder)(const std::string&); - - static StringDecoder GetStringDecoder(ECountry country); - private: + bool LoadBannerFile() const; + + static const int GC_BANNER_WIDTH = 96; + static const int GC_BANNER_HEIGHT = 32; + + // Banner Comment + struct GCBannerComment + { + 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. + }; + + struct GCBanner + { + 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) + }; + + static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerComment) * 5; + static const size_t BNR2_SIZE = sizeof(GCBanner); + + enum BannerFileType + { + BANNER_NOT_LOADED, + BANNER_INVALID, + BANNER_BNR1, + BANNER_BNR2 + }; + + mutable BannerFileType m_banner_file_type = BANNER_NOT_LOADED; + mutable std::vector m_banner_file; + std::unique_ptr m_pReader; }; diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index 33dc213aee..229ec6d31b 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -31,9 +31,10 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; + std::string GetName() const override { return ""; } std::map GetNames() const override; - u32 GetFSTSize() const override { return 0; } - std::string GetApploaderDate() const override { return "0"; } + u32 GetFSTSize() const override { return 0; } + std::string GetApploaderDate() const override { return ""; } bool IsWadFile() const override; diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index 935d18b8f8..baf96f2e5d 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -192,16 +192,20 @@ int CVolumeWiiCrypted::GetRevision() const return revision; } +std::string CVolumeWiiCrypted::GetName() const +{ + char name_buffer[0x60]; + if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name_buffer, false)) + return DecodeString(name_buffer); + + return ""; +} + std::map CVolumeWiiCrypted::GetNames() const { + // TODO: Read opening.bnr std::map names; - - auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry()); - - char name[0xFF] = {}; - if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name, true)) - names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = string_decoder(name); - + names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = GetName(); return names; } diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index f4712fd230..11092c33d1 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -31,6 +31,7 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; + std::string GetName() const override; std::map GetNames() const override; u32 GetFSTSize() const override; std::string GetApploaderDate() const override; diff --git a/Source/Core/DolphinQt/GameList/GameFile.cpp b/Source/Core/DolphinQt/GameList/GameFile.cpp index 9b36e86069..e97117d033 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.cpp +++ b/Source/Core/DolphinQt/GameList/GameFile.cpp @@ -18,7 +18,6 @@ #include "Core/ConfigManager.h" -#include "DiscIO/BannerLoader.h" #include "DiscIO/CompressedBlob.h" #include "DiscIO/Filesystem.h" @@ -82,7 +81,7 @@ GameFile::GameFile(const QString& fileName) } else { - DiscIO::IVolume* volume = DiscIO::CreateVolumeFromFilename(fileName.toStdString()); + std::unique_ptr volume(DiscIO::CreateVolumeFromFilename(fileName.toStdString())); if (volume != nullptr) { @@ -91,7 +90,9 @@ GameFile::GameFile(const QString& fileName) else m_platform = WII_WAD; - m_volume_names = ConvertLocalizedStrings(volume->GetNames()); + m_names = ConvertLocalizedStrings(volume->GetNames()); + m_descriptions = ConvertLocalizedStrings(volume->GetDescriptions()); + m_company = QString::fromStdString(volume->GetCompany()); m_country = volume->GetCountry(); m_file_size = volume->GetRawSize(); @@ -105,43 +106,22 @@ GameFile::GameFile(const QString& fileName) QFileInfo info(m_file_name); m_folder_name = info.absoluteDir().dirName(); - // check if we can get some info from the banner file too - DiscIO::IFileSystem* fileSystem = DiscIO::CreateFileSystem(volume); - - if (fileSystem != nullptr || m_platform == WII_WAD) + int width, height; + std::vector buffer = volume->GetBanner(&width, &height); + QImage banner(width, height, QImage::Format_RGB888); + for (int i = 0; i < width * height; i++) { - std::unique_ptr bannerLoader(DiscIO::CreateBannerLoader(*fileSystem, volume)); - - if (bannerLoader != nullptr) - { - if (bannerLoader->IsValid()) - { - if (m_platform != WII_WAD) - m_names = ConvertLocalizedStrings(bannerLoader->GetNames()); - m_company = QString::fromStdString(bannerLoader->GetCompany()); - m_descriptions = ConvertLocalizedStrings(bannerLoader->GetDescriptions()); - - int width, height; - std::vector buffer = bannerLoader->GetBanner(&width, &height); - QImage banner(width, height, QImage::Format_RGB888); - for (int i = 0; i < width * height; i++) - { - int x = i % width, y = i / width; - banner.setPixel(x, y, qRgb((buffer[i] & 0xFF0000) >> 16, - (buffer[i] & 0x00FF00) >> 8, - (buffer[i] & 0x0000FF) >> 0)); - } - - if (!banner.isNull()) - { - hasBanner = true; - m_banner = QPixmap::fromImage(banner); - } - } - } - delete fileSystem; + int x = i % width, y = i / width; + banner.setPixel(x, y, qRgb((buffer[i] & 0xFF0000) >> 16, + (buffer[i] & 0x00FF00) >> 8, + (buffer[i] & 0x0000FF) >> 0)); + } + + if (!banner.isNull()) + { + hasBanner = true; + m_banner = QPixmap::fromImage(banner); } - delete volume; m_valid = true; if (hasBanner) @@ -184,14 +164,12 @@ bool GameFile::LoadFromCache() return false; u32 country; - QMap volume_names; QMap names; QMap descriptions; stream >> m_folder_name - >> volume_names >> names - >> m_company >> descriptions + >> m_company >> m_unique_id >> m_file_size >> m_volume_size @@ -202,7 +180,6 @@ bool GameFile::LoadFromCache() >> m_is_disc_two >> m_revision; m_country = (DiscIO::IVolume::ECountry)country; - m_volume_names = CastLocalizedStrings(volume_names); m_names = CastLocalizedStrings(names); m_descriptions = CastLocalizedStrings(descriptions); file.close(); @@ -230,10 +207,9 @@ void GameFile::SaveToCache() stream << CACHE_REVISION; stream << m_folder_name - << CastLocalizedStrings(m_volume_names) << CastLocalizedStrings(m_names) - << m_company << CastLocalizedStrings(m_descriptions) + << m_company << m_unique_id << m_file_size << m_volume_size @@ -279,24 +255,14 @@ QString GameFile::GetDescription() const return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC)); } -QString GameFile::GetVolumeName(IVolume::ELanguage language) const -{ - return GetLanguageString(language, m_volume_names); -} - -QString GameFile::GetBannerName(IVolume::ELanguage language) const +QString GameFile::GetName(IVolume::ELanguage language) const { return GetLanguageString(language, m_names); } -QString GameFile::GetName(IVolume::ELanguage language) const +QString GameFile::GetName() const { - // Prefer name from banner, fallback to name from volume, fallback to filename - QString name = GetBannerName(language); - - if (name.isEmpty()) - name = GetVolumeName(language); - + QString name = GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC)); if (name.isEmpty()) { // No usable name, return filename (better than nothing) @@ -304,15 +270,9 @@ QString GameFile::GetName(IVolume::ELanguage language) const SplitPath(m_file_name.toStdString(), nullptr, &nametemp, nullptr); name = QString::fromStdString(nametemp); } - return name; } -QString GameFile::GetName() const -{ - return GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC)); -} - const QString GameFile::GetWiiFSPath() const { std::unique_ptr volume(DiscIO::CreateVolumeFromFilename(m_file_name.toStdString())); diff --git a/Source/Core/DolphinQt/GameList/GameFile.h b/Source/Core/DolphinQt/GameList/GameFile.h index e6732d3c49..5618c29f02 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.h +++ b/Source/Core/DolphinQt/GameList/GameFile.h @@ -22,13 +22,11 @@ public: bool IsValid() const { return m_valid; } QString GetFileName() { return m_file_name; } QString GetFolderName() { return m_folder_name; } - QString GetBannerName(DiscIO::IVolume::ELanguage language) const; - QString GetVolumeName(DiscIO::IVolume::ELanguage language) const; QString GetName(DiscIO::IVolume::ELanguage language) const; QString GetName() const; - QString GetCompany() const; QString GetDescription(DiscIO::IVolume::ELanguage language) const; QString GetDescription() const; + QString GetCompany() const; int GetRevision() const { return m_revision; } const QString GetUniqueID() const { return m_unique_id; } const QString GetWiiFSPath() const; @@ -54,12 +52,9 @@ private: QString m_file_name; QString m_folder_name; - // TODO: eliminate this and overwrite with names from banner when available? - QMap m_volume_names; - - QString m_company; QMap m_names; QMap m_descriptions; + QString m_company; QString m_unique_id; diff --git a/Source/Core/DolphinWX/ISOFile.cpp b/Source/Core/DolphinWX/ISOFile.cpp index 5190849435..5e3580ab43 100644 --- a/Source/Core/DolphinWX/ISOFile.cpp +++ b/Source/Core/DolphinWX/ISOFile.cpp @@ -29,7 +29,6 @@ #include "Core/CoreParameter.h" #include "Core/Boot/Boot.h" -#include "DiscIO/BannerLoader.h" #include "DiscIO/CompressedBlob.h" #include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" @@ -90,7 +89,9 @@ GameListItem::GameListItem(const std::string& _rFileName) else m_Platform = WII_WAD; - m_volume_names = pVolume->GetNames(); + m_names = pVolume->GetNames(); + m_descriptions = pVolume->GetDescriptions(); + m_company = pVolume->GetCompany(); m_Country = pVolume->GetCountry(); m_FileSize = pVolume->GetRawSize(); @@ -101,34 +102,15 @@ GameListItem::GameListItem(const std::string& _rFileName) m_IsDiscTwo = pVolume->IsDiscTwo(); m_Revision = pVolume->GetRevision(); - // check if we can get some info from the banner file too - DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); + std::vector Buffer = pVolume->GetBanner(&m_ImageWidth, &m_ImageHeight); + u32* pData = Buffer.data(); + m_pImage.resize(m_ImageWidth * m_ImageHeight * 3); - if (pFileSystem != nullptr || m_Platform == WII_WAD) + for (int i = 0; i < m_ImageWidth * m_ImageHeight; i++) { - std::unique_ptr pBannerLoader(DiscIO::CreateBannerLoader(*pFileSystem, pVolume)); - - if (pBannerLoader != nullptr && pBannerLoader->IsValid()) - { - if (m_Platform != WII_WAD) - m_banner_names = pBannerLoader->GetNames(); - m_company = pBannerLoader->GetCompany(); - m_descriptions = pBannerLoader->GetDescriptions(); - - std::vector Buffer = pBannerLoader->GetBanner(&m_ImageWidth, &m_ImageHeight); - u32* pData = &Buffer[0]; - // resize vector to image size - m_pImage.resize(m_ImageWidth * m_ImageHeight * 3); - - for (int i = 0; i < m_ImageWidth * m_ImageHeight; i++) - { - m_pImage[i * 3 + 0] = (pData[i] & 0xFF0000) >> 16; - m_pImage[i * 3 + 1] = (pData[i] & 0x00FF00) >> 8; - m_pImage[i * 3 + 2] = (pData[i] & 0x0000FF) >> 0; - } - } - - delete pFileSystem; + m_pImage[i * 3 + 0] = (pData[i] & 0xFF0000) >> 16; + m_pImage[i * 3 + 1] = (pData[i] & 0x00FF00) >> 8; + m_pImage[i * 3 + 2] = (pData[i] & 0x0000FF) >> 0; } delete pVolume; @@ -154,7 +136,7 @@ GameListItem::GameListItem(const std::string& _rFileName) 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 smooths caling. + // 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); @@ -188,10 +170,9 @@ void GameListItem::SaveToCache() void GameListItem::DoState(PointerWrap &p) { - p.Do(m_volume_names); - p.Do(m_company); - p.Do(m_banner_names); + p.Do(m_names); p.Do(m_descriptions); + p.Do(m_company); p.Do(m_UniqueID); p.Do(m_FileSize); p.Do(m_VolumeSize); @@ -238,48 +219,27 @@ std::string GameListItem::GetDescription() const return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_Platform != GAMECUBE_DISC)); } -std::string GameListItem::GetVolumeName(IVolume::ELanguage language) const -{ - return GetLanguageString(language, m_volume_names); -} - -std::string GameListItem::GetBannerName(IVolume::ELanguage language) const -{ - return GetLanguageString(language, m_banner_names); -} - std::string GameListItem::GetName(IVolume::ELanguage language) const { - // Prefer name from banner, fallback to name from volume, fallback to filename - - std::string name = GetBannerName(language); - - if (name.empty()) - name = GetVolumeName(language); + return GetLanguageString(language, m_names); +} +std::string GameListItem::GetName() const +{ + std::string name = GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_Platform != GAMECUBE_DISC)); if (name.empty()) { // No usable name, return filename (better than nothing) SplitPath(GetFileName(), nullptr, &name, nullptr); } - return name; } -std::string GameListItem::GetName() const -{ - return GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_Platform != GAMECUBE_DISC)); -} - std::vector GameListItem::GetLanguages() const { - std::map language_strings = m_banner_names; - if (m_volume_names.size() > m_banner_names.size()) - language_strings = m_volume_names; - std::vector languages; - for (std::pair language_string : language_strings) - languages.emplace_back(language_string.first); + for (std::pair name : m_names) + languages.push_back(name.first); return languages; } diff --git a/Source/Core/DolphinWX/ISOFile.h b/Source/Core/DolphinWX/ISOFile.h index 9370028a48..2f65d7eec4 100644 --- a/Source/Core/DolphinWX/ISOFile.h +++ b/Source/Core/DolphinWX/ISOFile.h @@ -25,14 +25,12 @@ public: bool IsValid() const {return m_Valid;} const std::string& GetFileName() const {return m_FileName;} - std::string GetBannerName(IVolume::ELanguage language) const; - std::string GetVolumeName(IVolume::ELanguage language) const; std::string GetName(IVolume::ELanguage language) const; std::string GetName() const; - std::string GetCompany() const; std::string GetDescription(IVolume::ELanguage language) const; std::string GetDescription() const; std::vector GetLanguages() const; + std::string GetCompany() const; int GetRevision() const { return m_Revision; } const std::string& GetUniqueID() const {return m_UniqueID;} const std::string GetWiiFSPath() const; @@ -61,13 +59,9 @@ public: private: std::string m_FileName; - // TODO: eliminate this and overwrite with names from banner when available? - std::map m_volume_names; - - // Stuff from banner - std::string m_company; - std::map m_banner_names; + std::map m_names; std::map m_descriptions; + std::string m_company; std::string m_UniqueID; diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index 9ac5f7735b..0d5f71dc99 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -38,9 +37,6 @@ #include "Core/HW/Wiimote.h" #include "Core/PowerPC/PowerPC.h" -// Banner loading -#include "DiscIO/BannerLoader.h" -#include "DiscIO/Filesystem.h" #include "DiscIO/VolumeCreator.h" #include "UICommon/UICommon.h" @@ -115,8 +111,8 @@ static bool MsgAlert(const char* caption, const char* text, bool /*yes_no*/, int #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 -std::map m_volume_names; std::map m_names; +bool m_is_wii_title; static inline u32 Average32(u32 a, u32 b) { return ((a >> 1) & 0x7f7f7f7f) + ((b >> 1) & 0x7f7f7f7f); @@ -131,54 +127,39 @@ static inline u32 GetPixel(u32 *buffer, unsigned int x, unsigned int y) { static bool LoadBanner(std::string filename, u32 *Banner) { - DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(filename); + std::unique_ptr pVolume(DiscIO::CreateVolumeFromFilename(filename)); if (pVolume != nullptr) { - bool bIsWad = false; - if (DiscIO::IsVolumeWadFile(pVolume)) - bIsWad = true; + m_names = pVolume->GetNames(); + m_is_wii_title = pVolume->IsWiiDisc() || pVolume->IsWadFile(); - m_volume_names = pVolume->GetNames(); - - // check if we can get some info from the banner file too - DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); - - if (pFileSystem != nullptr || bIsWad) + int Width, Height; + std::vector BannerVec = pVolume->GetBanner(&Width, &Height); + // This code (along with above inlines) is moved from + // elsewhere. Someone who knows anything about Android + // please get rid of it and use proper high-resolution + // images. + if (Height == 64 && Width == 192) { - DiscIO::IBannerLoader* pBannerLoader = DiscIO::CreateBannerLoader(*pFileSystem, pVolume); - - if (pBannerLoader != nullptr) - if (pBannerLoader->IsValid()) + u32* Buffer = &BannerVec[0]; + for (int y = 0; y < 32; y++) + { + for (int x = 0; x < 96; x++) { - m_names = pBannerLoader->GetNames(); - int Width, Height; - std::vector BannerVec = pBannerLoader->GetBanner(&Width, &Height); - // This code (along with above inlines) is moved from - // elsewhere. Someone who knows anything about Android - // please get rid of it and use proper high-resolution - // images. - if (Height == 64) - { - u32* Buffer = &BannerVec[0]; - for (int y = 0; y < 32; y++) - { - for (int x = 0; x < 96; x++) - { - // simplified plus-shaped "gaussian" - u32 surround = Average32( - Average32(GetPixel(Buffer, x*2 - 1, y*2), GetPixel(Buffer, x*2 + 1, y*2)), - Average32(GetPixel(Buffer, x*2, y*2 - 1), GetPixel(Buffer, x*2, y*2 + 1))); - Banner[y * 96 + x] = Average32(GetPixel(Buffer, x*2, y*2), surround); - } - } - } - else - { - memcpy(Banner, &BannerVec[0], 96 * 32 * 4); - } - return true; + // simplified plus-shaped "gaussian" + u32 surround = Average32( + Average32(GetPixel(Buffer, x*2 - 1, y*2), GetPixel(Buffer, x*2 + 1, y*2)), + Average32(GetPixel(Buffer, x*2, y*2 - 1), GetPixel(Buffer, x*2, y*2 + 1))); + Banner[y * 96 + x] = Average32(GetPixel(Buffer, x*2, y*2), surround); } + } + return true; + } + else if (Height == 32 && Width == 96) + { + memcpy(Banner, &BannerVec[0], 96 * 32 * 4); + return true; } } @@ -187,15 +168,28 @@ static bool LoadBanner(std::string filename, u32 *Banner) static std::string GetName(std::string filename) { - if (!m_names.empty()) - return m_names[0]; + DiscIO::IVolume::ELanguage language = SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_is_wii_title); + + auto end = m_names.end(); + auto it = m_names.find(language); + if (it != end) + return it->second; + + // English tends to be a good fallback when the requested language isn't available + if (language != IVolume::ELanguage::LANGUAGE_ENGLISH) + { + it = m_names.find(IVolume::ELanguage::LANGUAGE_ENGLISH); + if (it != end) + return it->second; + } + + // If English isn't available either, just pick something + if (!m_names.empty()) + return m_names.cbegin()->second; - if (!m_volume_names.empty()) - return m_volume_names[0]; // No usable name, return filename (better than nothing) std::string name; SplitPath(filename, nullptr, &name, nullptr); - return name; } @@ -277,7 +271,6 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle( std::string file = GetJString(env, jFile); std::string name = GetName(file); m_names.clear(); - m_volume_names.clear(); return env->NewStringUTF(name.c_str()); }