diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index f23ca15730..08f030d07a 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -304,7 +304,7 @@ void SConfig::SaveGameListSettings(IniFile& ini) gamelist->Set("ColumnPlatform", m_showSystemColumn); gamelist->Set("ColumnBanner", m_showBannerColumn); - gamelist->Set("ColumnNotes", m_showNotesColumn); + gamelist->Set("ColumnNotes", m_showMakerColumn); gamelist->Set("ColumnID", m_showIDColumn); gamelist->Set("ColumnRegion", m_showRegionColumn); gamelist->Set("ColumnSize", m_showSizeColumn); @@ -557,7 +557,7 @@ void SConfig::LoadGameListSettings(IniFile& ini) // Gamelist columns toggles gamelist->Get("ColumnPlatform", &m_showSystemColumn, true); gamelist->Get("ColumnBanner", &m_showBannerColumn, true); - gamelist->Get("ColumnNotes", &m_showNotesColumn, true); + gamelist->Get("ColumnNotes", &m_showMakerColumn, true); gamelist->Get("ColumnID", &m_showIDColumn, false); gamelist->Get("ColumnRegion", &m_showRegionColumn, true); gamelist->Get("ColumnSize", &m_showSizeColumn, true); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 7a811e164a..8a713946dd 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -84,7 +84,7 @@ struct SConfig : NonCopyable // Game list column toggles bool m_showSystemColumn; bool m_showBannerColumn; - bool m_showNotesColumn; + bool m_showMakerColumn; bool m_showIDColumn; bool m_showRegionColumn; bool m_showSizeColumn; diff --git a/Source/Core/Core/CoreParameter.cpp b/Source/Core/Core/CoreParameter.cpp index 0694b4c07d..bce8101b09 100644 --- a/Source/Core/Core/CoreParameter.cpp +++ b/Source/Core/Core/CoreParameter.cpp @@ -373,6 +373,20 @@ void SCoreStartupParameter::CheckMemcardPath(std::string& memcardPath, std::stri } } +IVolume::ELanguage SCoreStartupParameter::GetCurrentLanguage(bool wii) const +{ + IVolume::ELanguage language; + if (wii) + language = (IVolume::ELanguage)SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG"); + else + language = (IVolume::ELanguage)(SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage + 1); + + // Get rid of invalid values (probably doesn't matter, but might as well do it) + if (language > IVolume::ELanguage::LANGUAGE_UNKNOWN || language < 0) + language = IVolume::ELanguage::LANGUAGE_UNKNOWN; + return language; +} + IniFile SCoreStartupParameter::LoadDefaultGameIni() const { return LoadDefaultGameIni(GetUniqueID(), m_revision); diff --git a/Source/Core/Core/CoreParameter.h b/Source/Core/Core/CoreParameter.h index e5f9cac9b1..381128a1f0 100644 --- a/Source/Core/Core/CoreParameter.h +++ b/Source/Core/Core/CoreParameter.h @@ -7,6 +7,7 @@ #include #include "Common/IniFile.h" +#include "DiscIO/Volume.h" enum Hotkey { @@ -248,6 +249,7 @@ struct SCoreStartupParameter bool AutoSetup(EBootBS2 _BootBS2); const std::string &GetUniqueID() const { return m_strUniqueID; } void CheckMemcardPath(std::string& memcardPath, std::string gameRegion, bool isSlotA); + DiscIO::IVolume::ELanguage GetCurrentLanguage(bool wii) const; IniFile LoadDefaultGameIni() const; IniFile LoadLocalGameIni() const; 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 7d6a25b8cf..0000000000 --- a/Source/Core/DiscIO/BannerLoader.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include -#include - -#include "Common/CommonTypes.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::vector GetNames() = 0; - virtual std::string GetCompany() = 0; - virtual std::vector 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 ce265a016e..0000000000 --- a/Source/Core/DiscIO/BannerLoaderGC.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#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::vector CBannerLoaderGC::GetNames() -{ - std::vector names; - - if (!IsValid()) - { - return names; - } - - u32 name_count = 0; - - // find Banner type - switch (m_BNRType) - { - case CBannerLoaderGC::BANNER_BNR1: - name_count = 1; - break; - - case CBannerLoaderGC::BANNER_BNR2: - name_count = 6; - break; - - default: - break; - } - - auto const banner = reinterpret_cast(m_pBannerFile); - - for (u32 i = 0; i != name_count; ++i) - { - auto& comment = banner->comment[i]; - - if (comment.longTitle[0]) - { - auto& data = comment.longTitle; - names.push_back(GetDecodedString(data)); - } - else - { - auto& data = comment.shortTitle; - names.push_back(GetDecodedString(data)); - } - } - - 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::vector CBannerLoaderGC::GetDescriptions() -{ - std::vector descriptions; - - if (!IsValid()) - { - return descriptions; - } - - u32 desc_count = 0; - - // find Banner type - switch (m_BNRType) - { - case CBannerLoaderGC::BANNER_BNR1: - desc_count = 1; - break; - - // English, German, French, Spanish, Italian, Dutch - case CBannerLoaderGC::BANNER_BNR2: - 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; - descriptions.push_back(GetDecodedString(data)); - } - - return descriptions; -} - -CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType() -{ - u32 bannerSignature = *(u32*)m_pBannerFile; - CBannerLoaderGC::BANNER_TYPE type = CBannerLoaderGC::BANNER_UNKNOWN; - switch (bannerSignature) - { - // "BNR1" - case 0x31524e42: - type = CBannerLoaderGC::BANNER_BNR1; - break; - - // "BNR2" - case 0x32524e42: - type = CBannerLoaderGC::BANNER_BNR2; - break; - } - return type; -} - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoaderGC.h b/Source/Core/DiscIO/BannerLoaderGC.h deleted file mode 100644 index 94e261699c..0000000000 --- a/Source/Core/DiscIO/BannerLoaderGC.h +++ /dev/null @@ -1,86 +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" -#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::vector GetNames() override; - virtual std::string GetCompany() override; - virtual std::vector 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 eaab54a942..0000000000 --- a/Source/Core/DiscIO/BannerLoaderWii.cpp +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#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::vector CBannerLoaderWii::GetNames() -{ - std::vector ret(1); - - if (!GetStringFromComments(NAME_IDX, ret[0])) - ret.clear(); - - return ret; -} - -std::string CBannerLoaderWii::GetCompany() -{ - return ""; -} - -std::vector CBannerLoaderWii::GetDescriptions() -{ - std::vector result(1); - if (!GetStringFromComments(DESC_IDX, result[0])) - result.clear(); - return result; -} - -} // namespace diff --git a/Source/Core/DiscIO/BannerLoaderWii.h b/Source/Core/DiscIO/BannerLoaderWii.h deleted file mode 100644 index 1bbe077509..0000000000 --- a/Source/Core/DiscIO/BannerLoaderWii.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#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::vector GetNames() override; - virtual std::string GetCompany() override; - virtual std::vector 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/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp index 381d1bdbd4..e23a8cb177 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/FileSystemGCWii.cpp @@ -63,7 +63,7 @@ const std::string CFileSystemGCWii::GetFileName(u64 _Address) return ""; } -u64 CFileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) +u64 CFileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize, u64 _OffsetInFile) { if (!m_Initialized) InitFileSystem(); @@ -72,14 +72,16 @@ u64 CFileSystemGCWii::ReadFile(const std::string& _rFullPath, u8* _pBuffer, size if (pFileInfo == nullptr) return 0; - if (pFileInfo->m_FileSize > _MaxBufferSize) + if (_OffsetInFile >= pFileInfo->m_FileSize) return 0; - DEBUG_LOG(DISCIO, "Filename: %s. Offset: %" PRIx64 ". Size: %" PRIx64, _rFullPath.c_str(), - pFileInfo->m_Offset, pFileInfo->m_FileSize); + u64 read_length = std::min(_MaxBufferSize, pFileInfo->m_FileSize - _OffsetInFile); - m_rVolume->Read(pFileInfo->m_Offset, pFileInfo->m_FileSize, _pBuffer, m_Wii); - return pFileInfo->m_FileSize; + DEBUG_LOG(DISCIO, "Reading %" PRIx64 " bytes at %" PRIx64 " from file %s. Offset: %" PRIx64 " Size: %" PRIx64, + read_length, _OffsetInFile, _rFullPath.c_str(), pFileInfo->m_Offset, pFileInfo->m_FileSize); + + m_rVolume->Read(pFileInfo->m_Offset + _OffsetInFile, read_length, _pBuffer, m_Wii); + return read_length; } bool CFileSystemGCWii::ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename) diff --git a/Source/Core/DiscIO/FileSystemGCWii.h b/Source/Core/DiscIO/FileSystemGCWii.h index 24a1c65ab3..03f4bb9eff 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.h +++ b/Source/Core/DiscIO/FileSystemGCWii.h @@ -25,7 +25,7 @@ public: virtual u64 GetFileSize(const std::string& _rFullPath) override; virtual size_t GetFileList(std::vector &_rFilenames) override; virtual const std::string GetFileName(u64 _Address) override; - virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) override; + virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize, u64 _OffsetInFile) override; virtual bool ExportFile(const std::string& _rFullPath, const std::string&_rExportFilename) override; virtual bool ExportApploader(const std::string& _rExportFolder) const override; virtual bool ExportDOL(const std::string& _rExportFolder) const override; diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h index 78f179d6dd..181c25f354 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -45,7 +45,7 @@ public: virtual bool IsValid() const = 0; virtual size_t GetFileList(std::vector &_rFilenames) = 0; virtual u64 GetFileSize(const std::string& _rFullPath) = 0; - virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, size_t _MaxBufferSize) = 0; + virtual u64 ReadFile(const std::string& _rFullPath, u8* _pBuffer, u64 _MaxBufferSize, u64 _OffsetInFile = 0) = 0; virtual bool ExportFile(const std::string& _rFullPath, const std::string& _rExportFilename) = 0; virtual bool ExportApploader(const std::string& _rExportFolder) const = 0; virtual bool ExportDOL(const std::string& _rExportFolder) const = 0; diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index 6efe04a37f..c0fea6ccc4 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -4,18 +4,57 @@ #pragma once +#include #include #include #include #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" +#include "Common/StringUtil.h" namespace DiscIO { class IVolume { public: + // Increment CACHE_REVISION if the enums below are modified (ISOFile.cpp & GameFile.cpp) + enum ECountry + { + COUNTRY_EUROPE = 0, + COUNTRY_JAPAN, + COUNTRY_USA, + COUNTRY_AUSTRALIA, + COUNTRY_FRANCE, + COUNTRY_GERMANY, + COUNTRY_ITALY, + COUNTRY_KOREA, + COUNTRY_NETHERLANDS, + COUNTRY_RUSSIA, + COUNTRY_SPAIN, + COUNTRY_TAIWAN, + COUNTRY_WORLD, + COUNTRY_UNKNOWN, + NUMBER_OF_COUNTRIES + }; + + // Languages 0 - 9 match the official Wii language numbering. + // Languages 1 - 6 match the official GC PAL languages 0 - 5. + enum ELanguage + { + LANGUAGE_JAPANESE = 0, + LANGUAGE_ENGLISH = 1, + LANGUAGE_GERMAN = 2, + LANGUAGE_FRENCH = 3, + LANGUAGE_SPANISH = 4, + LANGUAGE_ITALIAN = 5, + LANGUAGE_DUTCH = 6, + LANGUAGE_SIMPLIFIED_CHINESE = 7, + LANGUAGE_TRADITIONAL_CHINESE = 8, + LANGUAGE_KOREAN = 9, + LANGUAGE_UNKNOWN + }; + IVolume() {} virtual ~IVolume() {} @@ -36,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 std::vector GetNames() const = 0; + 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; @@ -50,31 +91,35 @@ public: virtual bool CheckIntegrity() const { return false; } virtual bool ChangePartition(u64 offset) { return false; } - // Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp) - enum ECountry - { - COUNTRY_EUROPE = 0, - COUNTRY_JAPAN, - COUNTRY_USA, - COUNTRY_AUSTRALIA, - COUNTRY_FRANCE, - COUNTRY_GERMANY, - COUNTRY_ITALY, - COUNTRY_KOREA, - COUNTRY_NETHERLANDS, - COUNTRY_RUSSIA, - COUNTRY_SPAIN, - COUNTRY_TAIWAN, - COUNTRY_WORLD, - COUNTRY_UNKNOWN, - NUMBER_OF_COUNTRIES - }; - virtual ECountry GetCountry() const = 0; virtual u64 GetSize() const = 0; // 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); + } + + static std::map ReadWiiNames(std::vector& data); + + static const size_t NUMBER_OF_LANGUAGES = 10; + static const size_t NAME_STRING_LENGTH = 42; + static const size_t NAME_BYTES_LENGTH = NAME_STRING_LENGTH * sizeof(u16); + static const size_t NAMES_TOTAL_BYTES = NAME_BYTES_LENGTH * NUMBER_OF_LANGUAGES; }; // Generic Switch function for all volumes diff --git a/Source/Core/DiscIO/VolumeCommon.cpp b/Source/Core/DiscIO/VolumeCommon.cpp index 87f0c722a7..d9b5240327 100644 --- a/Source/Core/DiscIO/VolumeCommon.cpp +++ b/Source/Core/DiscIO/VolumeCommon.cpp @@ -2,16 +2,83 @@ // Licensed under GPLv2 // Refer to the license.txt file included. +#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 "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; +} + +std::map IVolume::ReadWiiNames(std::vector& data) +{ + std::map names; + for (size_t i = 0; i < NUMBER_OF_LANGUAGES; ++i) + { + size_t name_start = NAME_BYTES_LENGTH * i; + size_t name_end = name_start + NAME_BYTES_LENGTH; + if (data.size() >= name_end) + { + u16* temp = (u16*)(data.data() + name_start); + std::wstring out_temp(NAME_STRING_LENGTH, '\0'); + std::transform(temp, temp + out_temp.size(), out_temp.begin(), (u16(&)(u16))Common::swap16); + out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end()); + std::string name = UTF16ToUTF8(out_temp); + if (!name.empty()) + names[(IVolume::ELanguage)i] = name; + } + } + return names; +} + +// Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp) IVolume::ECountry CountrySwitch(u8 country_code) { switch (country_code) @@ -98,13 +165,4 @@ u8 GetSysMenuRegion(u16 _TitleVersion) } } -std::string IVolume::GetName() const -{ - auto names = GetNames(); - if (names.empty()) - return ""; - else - return names[0]; -} - } diff --git a/Source/Core/DiscIO/VolumeDirectory.cpp b/Source/Core/DiscIO/VolumeDirectory.cpp index 6f3e4ccb7f..876848b2d3 100644 --- a/Source/Core/DiscIO/VolumeDirectory.cpp +++ b/Source/Core/DiscIO/VolumeDirectory.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "Common/CommonPaths.h" @@ -183,9 +182,22 @@ std::string CVolumeDirectory::GetMakerID() const return "VOID"; } -std::vector CVolumeDirectory::GetNames() const +std::string CVolumeDirectory::GetName() const { - return std::vector(1, (char*)(&m_diskHeader[0x20])); + char name[0x60]; + if (Read(0x20, 0x60, (u8*)name, false)) + return DecodeString(name); + else + return ""; +} + +std::map CVolumeDirectory::GetNames() const +{ + std::map names; + std::string name = GetName(); + if (!name.empty()) + names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name; + return names; } void CVolumeDirectory::SetName(const std::string& name) diff --git a/Source/Core/DiscIO/VolumeDirectory.h b/Source/Core/DiscIO/VolumeDirectory.h index c3e9c881c2..7187e8a017 100644 --- a/Source/Core/DiscIO/VolumeDirectory.h +++ b/Source/Core/DiscIO/VolumeDirectory.h @@ -39,7 +39,9 @@ public: std::string GetMakerID() const override; - std::vector GetNames() const override; + int GetRevision() const override { return 0; } + std::string GetName() const override; + std::map GetNames() const override; void SetName(const std::string&); u32 GetFSTSize() const override; diff --git a/Source/Core/DiscIO/VolumeGC.cpp b/Source/Core/DiscIO/VolumeGC.cpp index 132a630cf0..dd18338f63 100644 --- a/Source/Core/DiscIO/VolumeGC.cpp +++ b/Source/Core/DiscIO/VolumeGC.cpp @@ -3,14 +3,18 @@ // Refer to the license.txt file included. #include +#include #include #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" @@ -92,19 +96,133 @@ int CVolumeGC::GetRevision() const return revision; } -std::vector CVolumeGC::GetNames() const +std::string CVolumeGC::GetName() const { - std::vector names; - - auto const string_decoder = GetStringDecoder(GetCountry()); - - char name[0x60 + 1] = {}; + char name[0x60]; if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name)) - names.push_back(string_decoder(name)); + return DecodeString(name); + else + return ""; +} + +std::map CVolumeGC::GetNames() const +{ + std::map names; + + if (!LoadBannerFile()) + return names; + + 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) @@ -154,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 c2efcd6e9f..3c4abcba31 100644 --- a/Source/Core/DiscIO/VolumeGC.h +++ b/Source/Core/DiscIO/VolumeGC.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -27,7 +28,11 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; - std::vector 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; @@ -37,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.cpp b/Source/Core/DiscIO/VolumeWad.cpp index 1dc746ea4d..7b52e7a82e 100644 --- a/Source/Core/DiscIO/VolumeWad.cpp +++ b/Source/Core/DiscIO/VolumeWad.cpp @@ -2,8 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include #include +#include #include #include @@ -117,42 +117,12 @@ bool CVolumeWAD::IsWadFile() const return true; } -std::vector CVolumeWAD::GetNames() const +std::map CVolumeWAD::GetNames() const { - std::vector names; - - u32 footer_size; - if (!Read(0x1C, 4, (u8*)&footer_size)) - { - return names; - } - - footer_size = Common::swap32(footer_size); - - //Japanese, English, German, French, Spanish, Italian, Dutch, unknown, unknown, Korean - for (int i = 0; i != 10; ++i) - { - static const u32 string_length = 42; - static const u32 bytes_length = string_length * sizeof(u16); - - u16 temp[string_length]; - - if (footer_size < 0xF1 || !Read(0x9C + (i * bytes_length) + m_opening_bnr_offset, bytes_length, (u8*)&temp)) - { - names.push_back(""); - } - else - { - std::wstring out_temp; - out_temp.resize(string_length); - std::transform(temp, temp + out_temp.size(), out_temp.begin(), (u16(&)(u16))Common::swap16); - out_temp.erase(std::find(out_temp.begin(), out_temp.end(), 0x00), out_temp.end()); - - names.push_back(UTF16ToUTF8(out_temp)); - } - } - - return names; + std::vector name_data(NAMES_TOTAL_BYTES); + if (!Read(m_opening_bnr_offset + 0x9C, NAMES_TOTAL_BYTES, name_data.data())) + return std::map(); + return ReadWiiNames(name_data); } u64 CVolumeWAD::GetSize() const diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h index 3205da3a24..229ec6d31b 100644 --- a/Source/Core/DiscIO/VolumeWad.h +++ b/Source/Core/DiscIO/VolumeWad.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -30,9 +31,10 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; - std::vector GetNames() const override; - u32 GetFSTSize() const override { return 0; } - std::string GetApploaderDate() const override { return "0"; } + std::string GetName() const override { return ""; } + std::map GetNames() const override; + 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 4c703fdb3f..7657c0a28d 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,7 @@ #include "Common/Logging/Log.h" #include "DiscIO/Blob.h" #include "DiscIO/FileMonitor.h" +#include "DiscIO/Filesystem.h" #include "DiscIO/Volume.h" #include "DiscIO/VolumeCreator.h" #include "DiscIO/VolumeGC.h" @@ -191,17 +193,21 @@ int CVolumeWiiCrypted::GetRevision() const return revision; } -std::vector CVolumeWiiCrypted::GetNames() const +std::string CVolumeWiiCrypted::GetName() const { - std::vector names; + char name_buffer[0x60]; + if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name_buffer, false)) + return DecodeString(name_buffer); - auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry()); + return ""; +} - char name[0xFF] = {}; - if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name, true)) - names.push_back(string_decoder(name)); - - return names; +std::map CVolumeWiiCrypted::GetNames() const +{ + std::unique_ptr file_system(CreateFileSystem(this)); + std::vector opening_bnr(NAMES_TOTAL_BYTES); + opening_bnr.resize(file_system->ReadFile("opening.bnr", opening_bnr.data(), opening_bnr.size(), 0x5C)); + return ReadWiiNames(opening_bnr); } u32 CVolumeWiiCrypted::GetFSTSize() const diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index 4816bc2ebc..11092c33d1 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -30,7 +31,8 @@ public: std::string GetUniqueID() const override; std::string GetMakerID() const override; int GetRevision() const override; - std::vector GetNames() 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 67b7d7855f..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" @@ -26,25 +25,50 @@ #include "DolphinQt/Utils/Resources.h" #include "DolphinQt/Utils/Utils.h" -static const u32 CACHE_REVISION = 0x006; +static const u32 CACHE_REVISION = 0x007; static const u32 DATASTREAM_REVISION = 15; // Introduced in Qt 5.2 -static QStringList VectorToStringList(std::vector vec, bool trim = false) +static QMap ConvertLocalizedStrings(std::map strings) { - QStringList result; - if (trim) - { - for (const std::string& member : vec) - result.append(QString::fromStdString(member).trimmed()); - } - else - { - for (const std::string& member : vec) - result.append(QString::fromStdString(member)); - } + QMap result; + + for (auto entry : strings) + result.insert(entry.first, QString::fromStdString(entry.second).trimmed()); + return result; } +template +static QMap CastLocalizedStrings(QMap strings) +{ + QMap result; + + auto end = strings.cend(); + for (auto it = strings.cbegin(); it != end; ++it) + result.insert((to)it.key(), it.value()); + + return result; +} + +static QString GetLanguageString(IVolume::ELanguage language, QMap strings) +{ + if (strings.contains(language)) + return strings.value(language); + + // English tends to be a good fallback when the requested language isn't available + if (language != IVolume::ELanguage::LANGUAGE_ENGLISH) + { + if (strings.contains(IVolume::ELanguage::LANGUAGE_ENGLISH)) + return strings.value(IVolume::ELanguage::LANGUAGE_ENGLISH); + } + + // If English isn't available either, just pick something + if (!strings.empty()) + return strings.cbegin().value(); + + return SL(""); +} + GameFile::GameFile(const QString& fileName) : m_file_name(fileName) { @@ -57,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) { @@ -66,7 +90,9 @@ GameFile::GameFile(const QString& fileName) else m_platform = WII_WAD; - m_volume_names = VectorToStringList(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(); @@ -80,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 = VectorToStringList(bannerLoader->GetNames()); - m_company = QString::fromStdString(bannerLoader->GetCompany()); - m_descriptions = VectorToStringList(bannerLoader->GetDescriptions(), true); - - 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) @@ -158,11 +163,13 @@ bool GameFile::LoadFromCache() if (cache_rev != CACHE_REVISION) return false; - int country; + u32 country; + QMap names; + QMap descriptions; stream >> m_folder_name - >> m_volume_names + >> names + >> descriptions >> m_company - >> m_descriptions >> m_unique_id >> m_file_size >> m_volume_size @@ -173,6 +180,8 @@ bool GameFile::LoadFromCache() >> m_is_disc_two >> m_revision; m_country = (DiscIO::IVolume::ECountry)country; + m_names = CastLocalizedStrings(names); + m_descriptions = CastLocalizedStrings(descriptions); file.close(); return true; } @@ -198,13 +207,13 @@ void GameFile::SaveToCache() stream << CACHE_REVISION; stream << m_folder_name - << m_volume_names + << CastLocalizedStrings(m_names) + << CastLocalizedStrings(m_descriptions) << m_company - << m_descriptions << m_unique_id << m_file_size << m_volume_size - << (int)m_country + << (u32)m_country << m_banner << m_compressed << m_platform @@ -233,56 +242,27 @@ QString GameFile::CreateCacheFilename() QString GameFile::GetCompany() const { - if (m_company.isEmpty()) - return QObject::tr("N/A"); - else - return m_company; + return m_company; } -// For all of the following functions that accept an "index" parameter, -// (-1 = Japanese, 0 = English, etc)? - -QString GameFile::GetDescription(int index) const +QString GameFile::GetDescription(IVolume::ELanguage language) const { - if (index < m_descriptions.size()) - return m_descriptions[index]; - - if (!m_descriptions.empty()) - return m_descriptions[0]; - - return SL(""); + return GetLanguageString(language, m_descriptions); } -QString GameFile::GetVolumeName(int index) const +QString GameFile::GetDescription() const { - if (index < m_volume_names.size() && !m_volume_names[index].isEmpty()) - return m_volume_names[index]; - - if (!m_volume_names.isEmpty()) - return m_volume_names[0]; - - return SL(""); + return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC)); } -QString GameFile::GetBannerName(int index) const +QString GameFile::GetName(IVolume::ELanguage language) const { - if (index < m_names.size() && !m_names[index].isEmpty()) - return m_names[index]; - - if (!m_names.isEmpty()) - return m_names[0]; - - return SL(""); + return GetLanguageString(language, m_names); } -QString GameFile::GetName(int index) const +QString GameFile::GetName() const { - // Prefer name from banner, fallback to name from volume, fallback to filename - QString name = GetBannerName(index); - - if (name.isEmpty()) - name = GetVolumeName(index); - + QString name = GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC)); if (name.isEmpty()) { // No usable name, return filename (better than nothing) @@ -290,7 +270,6 @@ QString GameFile::GetName(int index) const SplitPath(m_file_name.toStdString(), nullptr, &nametemp, nullptr); name = QString::fromStdString(nametemp); } - return name; } diff --git a/Source/Core/DolphinQt/GameList/GameFile.h b/Source/Core/DolphinQt/GameList/GameFile.h index bc6e0ea17a..5618c29f02 100644 --- a/Source/Core/DolphinQt/GameList/GameFile.h +++ b/Source/Core/DolphinQt/GameList/GameFile.h @@ -4,9 +4,9 @@ #pragma once +#include #include #include -#include #include @@ -22,11 +22,11 @@ public: bool IsValid() const { return m_valid; } QString GetFileName() { return m_file_name; } QString GetFolderName() { return m_folder_name; } - QString GetBannerName(int index) const; - QString GetVolumeName(int index) const; - QString GetName(int index) const; + QString GetName(DiscIO::IVolume::ELanguage language) const; + QString GetName() const; + QString GetDescription(DiscIO::IVolume::ELanguage language) const; + QString GetDescription() const; QString GetCompany() const; - QString GetDescription(int index = 0) const; int GetRevision() const { return m_revision; } const QString GetUniqueID() const { return m_unique_id; } const QString GetWiiFSPath() const; @@ -52,12 +52,9 @@ private: QString m_file_name; QString m_folder_name; - // TODO: eliminate this and overwrite with names from banner when available? - QStringList m_volume_names; - + QMap m_names; + QMap m_descriptions; QString m_company; - QStringList m_names; - QStringList m_descriptions; QString m_unique_id; diff --git a/Source/Core/DolphinQt/GameList/GameGrid.cpp b/Source/Core/DolphinQt/GameList/GameGrid.cpp index a326c21d21..c4dd2831d8 100644 --- a/Source/Core/DolphinQt/GameList/GameGrid.cpp +++ b/Source/Core/DolphinQt/GameList/GameGrid.cpp @@ -76,7 +76,7 @@ void DGameGrid::AddGame(GameFile* gameItem) QListWidgetItem* i = new QListWidgetItem; i->setIcon(QIcon(gameItem->GetBitmap() .scaled(GRID_BANNER_WIDTH, GRID_BANNER_HEIGHT, Qt::KeepAspectRatio, Qt::SmoothTransformation))); - i->setText(gameItem->GetName(0)); + i->setText(gameItem->GetName()); if (gameItem->IsCompressed()) i->setTextColor(QColor("#00F")); diff --git a/Source/Core/DolphinQt/GameList/GameTree.cpp b/Source/Core/DolphinQt/GameList/GameTree.cpp index e5039751b2..69a1a84294 100644 --- a/Source/Core/DolphinQt/GameList/GameTree.cpp +++ b/Source/Core/DolphinQt/GameList/GameTree.cpp @@ -110,7 +110,7 @@ void DGameTree::AddGame(GameFile* item) QTreeWidgetItem* i = new QTreeWidgetItem; i->setIcon(COL_TYPE, QIcon(Resources::GetPlatformPixmap(item->GetPlatform()))); i->setIcon(COL_BANNER, QIcon(item->GetBitmap())); - i->setText(COL_TITLE, item->GetName(0)); + i->setText(COL_TITLE, item->GetName()); i->setText(COL_DESCRIPTION, item->GetDescription()); i->setIcon(COL_REGION, QIcon(Resources::GetRegionPixmap(item->GetCountry()))); i->setText(COL_SIZE, NiceSizeFormat(item->GetFileSize())); diff --git a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp index 31b957ce89..b2e08b5bee 100644 --- a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp @@ -11,6 +11,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/IPC_HLE/WII_IPC_HLE.h" +#include "DiscIO/Volume.h" #include "DolphinWX/WxUtils.h" #include "DolphinWX/Config/WiiConfigPane.h" @@ -125,7 +126,7 @@ void WiiConfigPane::OnConnectKeyboardCheckBoxChanged(wxCommandEvent& event) void WiiConfigPane::OnSystemLanguageChoiceChanged(wxCommandEvent& event) { - int wii_system_lang = m_system_language_choice->GetSelection(); + IVolume::ELanguage wii_system_lang = (IVolume::ELanguage)m_system_language_choice->GetSelection(); SConfig::GetInstance().m_SYSCONF->SetData("IPL.LNG", wii_system_lang); u8 country_code = GetSADRCountryCode(wii_system_lang); @@ -138,41 +139,33 @@ void WiiConfigPane::OnAspectRatioChoiceChanged(wxCommandEvent& event) SConfig::GetInstance().m_SYSCONF->SetData("IPL.AR", m_aspect_ratio_choice->GetSelection()); } -// Change from IPL.LNG value to IPL.SADR country code -u8 WiiConfigPane::GetSADRCountryCode(int language) +// Change from IPL.LNG value to IPL.SADR country code. +// http://wiibrew.org/wiki/Country_Codes +u8 WiiConfigPane::GetSADRCountryCode(IVolume::ELanguage language) { - //http://wiibrew.org/wiki/Country_Codes - u8 country_code = language; - switch (country_code) + switch (language) { - case 0: //Japanese - country_code = 1; //Japan - break; - case 1: //English - country_code = 49; //USA - break; - case 2: //German - country_code = 78; //Germany - break; - case 3: //French - country_code = 77; //France - break; - case 4: //Spanish - country_code = 105; //Spain - break; - case 5: //Italian - country_code = 83; //Italy - break; - case 6: //Dutch - country_code = 94; //Netherlands - break; - case 7: //Simplified Chinese - case 8: //Traditional Chinese - country_code = 157; //China - break; - case 9: //Korean - country_code = 136; //Korea - break; + case IVolume::LANGUAGE_JAPANESE: + return 1; // Japan + case IVolume::LANGUAGE_ENGLISH: + return 49; // USA + case IVolume::LANGUAGE_GERMAN: + return 78; // Germany + case IVolume::LANGUAGE_FRENCH: + return 77; // France + case IVolume::LANGUAGE_SPANISH: + return 105; // Spain + case IVolume::LANGUAGE_ITALIAN: + return 83; // Italy + case IVolume::LANGUAGE_DUTCH: + return 94; // Netherlands + case IVolume::LANGUAGE_SIMPLIFIED_CHINESE: + case IVolume::LANGUAGE_TRADITIONAL_CHINESE: + return 157; // China + case IVolume::LANGUAGE_KOREAN: + return 136; // Korea } - return country_code; + + PanicAlert("Invalid language"); + return 1; } diff --git a/Source/Core/DolphinWX/Config/WiiConfigPane.h b/Source/Core/DolphinWX/Config/WiiConfigPane.h index 72ea81548a..1fb57887ca 100644 --- a/Source/Core/DolphinWX/Config/WiiConfigPane.h +++ b/Source/Core/DolphinWX/Config/WiiConfigPane.h @@ -7,6 +7,7 @@ #include #include #include "Common/CommonTypes.h" +#include "DiscIO/Volume.h" class wxCheckBox; class wxChoice; @@ -29,7 +30,7 @@ private: void OnSystemLanguageChoiceChanged(wxCommandEvent&); void OnAspectRatioChoiceChanged(wxCommandEvent&); - static u8 GetSADRCountryCode(int language); + static u8 GetSADRCountryCode(IVolume::ELanguage language); wxArrayString m_system_language_strings; wxArrayString m_aspect_ratio_strings; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 77bed66d19..aac0f437a8 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -364,8 +364,8 @@ wxMenuBar* CFrame::CreateMenu() columnsMenu->Check(IDM_SHOW_SYSTEM, SConfig::GetInstance().m_showSystemColumn); columnsMenu->AppendCheckItem(IDM_SHOW_BANNER, _("Banner")); columnsMenu->Check(IDM_SHOW_BANNER, SConfig::GetInstance().m_showBannerColumn); - columnsMenu->AppendCheckItem(IDM_SHOW_NOTES, _("Notes")); - columnsMenu->Check(IDM_SHOW_NOTES, SConfig::GetInstance().m_showNotesColumn); + columnsMenu->AppendCheckItem(IDM_SHOW_MAKER, _("Maker")); + columnsMenu->Check(IDM_SHOW_MAKER, SConfig::GetInstance().m_showMakerColumn); columnsMenu->AppendCheckItem(IDM_SHOW_ID, _("Game ID")); columnsMenu->Check(IDM_SHOW_ID, SConfig::GetInstance().m_showIDColumn); columnsMenu->AppendCheckItem(IDM_SHOW_REGION, _("Region")); @@ -2035,8 +2035,8 @@ void CFrame::OnChangeColumnsVisible(wxCommandEvent& event) case IDM_SHOW_BANNER: SConfig::GetInstance().m_showBannerColumn = !SConfig::GetInstance().m_showBannerColumn; break; - case IDM_SHOW_NOTES: - SConfig::GetInstance().m_showNotesColumn = !SConfig::GetInstance().m_showNotesColumn; + case IDM_SHOW_MAKER: + SConfig::GetInstance().m_showMakerColumn = !SConfig::GetInstance().m_showMakerColumn; break; case IDM_SHOW_ID: SConfig::GetInstance().m_showIDColumn = !SConfig::GetInstance().m_showIDColumn; diff --git a/Source/Core/DolphinWX/GameListCtrl.cpp b/Source/Core/DolphinWX/GameListCtrl.cpp index 66677d0f90..d4b7d85bcf 100644 --- a/Source/Core/DolphinWX/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/GameListCtrl.cpp @@ -99,56 +99,27 @@ static int CompareGameListItems(const GameListItem* iso1, const GameListItem* is sortData = -sortData; } - int indexOne = 0; - int indexOther = 0; - - - // index only matters for WADS and PAL GC games, but invalid indicies for the others - // will return the (only) language in the list - if (iso1->GetPlatform() == GameListItem::WII_WAD) - { - indexOne = SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG"); - } - else // GC - { - indexOne = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; - } - - if (iso2->GetPlatform() == GameListItem::WII_WAD) - { - indexOther = SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG"); - } - else // GC - { - indexOther = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; - } + IVolume::ELanguage languageOne = SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(iso1->GetPlatform() != GameListItem::GAMECUBE_DISC); + IVolume::ELanguage languageOther = SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(iso2->GetPlatform() != GameListItem::GAMECUBE_DISC); switch (sortData) { case CGameListCtrl::COLUMN_TITLE: - if (!strcasecmp(iso1->GetName(indexOne).c_str(),iso2->GetName(indexOther).c_str())) + if (!strcasecmp(iso1->GetName(languageOne).c_str(), iso2->GetName(languageOther).c_str())) { if (iso1->GetUniqueID() != iso2->GetUniqueID()) return t * (iso1->GetUniqueID() > iso2->GetUniqueID() ? 1 : -1); if (iso1->GetRevision() != iso2->GetRevision()) - return t * (iso1->GetRevision() > iso2->GetRevision() ? 1 : -1); + return t * (iso1->GetRevision() > iso2->GetRevision() ? 1 : -1); if (iso1->IsDiscTwo() != iso2->IsDiscTwo()) return t * (iso1->IsDiscTwo() ? 1 : -1); } - return strcasecmp(iso1->GetName(indexOne).c_str(), - iso2->GetName(indexOther).c_str()) * t; - case CGameListCtrl::COLUMN_NOTES: - { - std::string cmp1 = - (iso1->GetPlatform() == GameListItem::GAMECUBE_DISC) ? - iso1->GetCompany() : iso1->GetDescription(indexOne); - std::string cmp2 = - (iso2->GetPlatform() == GameListItem::GAMECUBE_DISC) ? - iso2->GetCompany() : iso2->GetDescription(indexOther); - return strcasecmp(cmp1.c_str(), cmp2.c_str()) * t; - } + return strcasecmp(iso1->GetName(languageOne).c_str(), + iso2->GetName(languageOther).c_str()) * t; + case CGameListCtrl::COLUMN_MAKER: + return strcasecmp(iso1->GetCompany().c_str(), iso2->GetCompany().c_str()) * t; case CGameListCtrl::COLUMN_ID: - return strcasecmp(iso1->GetUniqueID().c_str(), iso2->GetUniqueID().c_str()) * t; + return strcasecmp(iso1->GetUniqueID().c_str(), iso2->GetUniqueID().c_str()) * t; case CGameListCtrl::COLUMN_COUNTRY: if (iso1->GetCountry() > iso2->GetCountry()) return 1 * t; @@ -311,10 +282,7 @@ void CGameListCtrl::Update() InsertColumn(COLUMN_BANNER, _("Banner")); InsertColumn(COLUMN_TITLE, _("Title")); - // Instead of showing the notes + the company, which is unknown with - // Wii titles We show in the same column : company for GC games and - // description for Wii/wad games - InsertColumn(COLUMN_NOTES, _("Notes")); + InsertColumn(COLUMN_MAKER, _("Maker")); InsertColumn(COLUMN_ID, _("ID")); InsertColumn(COLUMN_COUNTRY, ""); InsertColumn(COLUMN_SIZE, _("Size")); @@ -331,7 +299,7 @@ void CGameListCtrl::Update() SetColumnWidth(COLUMN_PLATFORM, SConfig::GetInstance().m_showSystemColumn ? 35 + platform_padding : 0); SetColumnWidth(COLUMN_BANNER, SConfig::GetInstance().m_showBannerColumn ? 96 + platform_padding : 0); SetColumnWidth(COLUMN_TITLE, 175 + platform_padding); - SetColumnWidth(COLUMN_NOTES, SConfig::GetInstance().m_showNotesColumn ? 150 + platform_padding : 0); + SetColumnWidth(COLUMN_MAKER, SConfig::GetInstance().m_showMakerColumn ? 150 + platform_padding : 0); SetColumnWidth(COLUMN_ID, SConfig::GetInstance().m_showIDColumn ? 75 + platform_padding : 0); SetColumnWidth(COLUMN_COUNTRY, SConfig::GetInstance().m_showRegionColumn ? 32 + platform_padding : 0); SetColumnWidth(COLUMN_EMULATION_STATE, SConfig::GetInstance().m_showStateColumn ? 50 + platform_padding : 0); @@ -433,15 +401,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); - int SelectedLanguage = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; - - // Is this sane? - if (rISOFile.GetPlatform() == GameListItem::WII_WAD) - { - SelectedLanguage = SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG"); - } - - std::string name = rISOFile.GetName(SelectedLanguage); + std::string name = rISOFile.GetName(); std::ifstream titlestxt; OpenFStream(titlestxt, File::GetUserPath(D_LOAD_IDX) + "titles.txt", std::ios::in); @@ -470,12 +430,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index) name = title; SetItem(_Index, COLUMN_TITLE, StrToWxStr(name), -1); - - // We show the company string on GameCube only - // On Wii we show the description instead as the company string is empty - std::string const notes = (rISOFile.GetPlatform() == GameListItem::GAMECUBE_DISC) ? - rISOFile.GetCompany() : rISOFile.GetDescription(SelectedLanguage); - SetItem(_Index, COLUMN_NOTES, StrToWxStr(notes), -1); + SetItem(_Index, COLUMN_MAKER, StrToWxStr(rISOFile.GetCompany()), -1); // Emulation state SetItemColumnImage(_Index, COLUMN_EMULATION_STATE, m_EmuStateImageIndex[rISOFile.GetEmuState()]); @@ -699,7 +654,7 @@ void CGameListCtrl::ScanForISOs() void CGameListCtrl::OnColBeginDrag(wxListEvent& event) { - if (event.GetColumn() != COLUMN_TITLE && event.GetColumn() != COLUMN_NOTES) + if (event.GetColumn() != COLUMN_TITLE && event.GetColumn() != COLUMN_MAKER) event.Veto(); } @@ -1348,13 +1303,13 @@ void CGameListCtrl::AutomaticColumnWidth() + GetColumnWidth(COLUMN_SIZE) + GetColumnWidth(COLUMN_EMULATION_STATE)); - // We hide the Notes column if the window is too small + // We hide the Maker column if the window is too small if (resizable > 400) { - if (SConfig::GetInstance().m_showNotesColumn) + if (SConfig::GetInstance().m_showMakerColumn) { SetColumnWidth(COLUMN_TITLE, resizable / 2); - SetColumnWidth(COLUMN_NOTES, resizable / 2); + SetColumnWidth(COLUMN_MAKER, resizable / 2); } else { @@ -1364,7 +1319,7 @@ void CGameListCtrl::AutomaticColumnWidth() else { SetColumnWidth(COLUMN_TITLE, resizable); - SetColumnWidth(COLUMN_NOTES, 0); + SetColumnWidth(COLUMN_MAKER, 0); } } } diff --git a/Source/Core/DolphinWX/GameListCtrl.h b/Source/Core/DolphinWX/GameListCtrl.h index 15f89b2944..b298d1514c 100644 --- a/Source/Core/DolphinWX/GameListCtrl.h +++ b/Source/Core/DolphinWX/GameListCtrl.h @@ -52,7 +52,7 @@ public: COLUMN_PLATFORM, COLUMN_BANNER, COLUMN_TITLE, - COLUMN_NOTES, + COLUMN_MAKER, COLUMN_ID, COLUMN_COUNTRY, COLUMN_SIZE, diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 5f9b2167b7..8c3ff3c691 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -176,7 +176,7 @@ enum // List Column Title Toggles IDM_SHOW_SYSTEM, IDM_SHOW_BANNER, - IDM_SHOW_NOTES, + IDM_SHOW_MAKER, IDM_SHOW_ID, IDM_SHOW_REGION, IDM_SHOW_SIZE, diff --git a/Source/Core/DolphinWX/ISOFile.cpp b/Source/Core/DolphinWX/ISOFile.cpp index db1c141de6..5e3580ab43 100644 --- a/Source/Core/DolphinWX/ISOFile.cpp +++ b/Source/Core/DolphinWX/ISOFile.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -28,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" @@ -37,11 +37,33 @@ #include "DolphinWX/ISOFile.h" #include "DolphinWX/WxUtils.h" -static const u32 CACHE_REVISION = 0x122; +static const u32 CACHE_REVISION = 0x123; #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 +static std::string GetLanguageString(IVolume::ELanguage language, std::map strings) +{ + auto end = strings.end(); + auto it = strings.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 = strings.find(IVolume::ELanguage::LANGUAGE_ENGLISH); + if (it != end) + return it->second; + } + + // If English isn't available either, just pick something + if (!strings.empty()) + return strings.cbegin()->second; + + return ""; +} + GameListItem::GameListItem(const std::string& _rFileName) : m_FileName(_rFileName) , m_emu_state(0) @@ -67,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(); @@ -78,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; @@ -131,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); @@ -165,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); @@ -202,73 +206,43 @@ std::string GameListItem::CreateCacheFilename() std::string GameListItem::GetCompany() const { - if (m_company.empty()) - return "N/A"; - else - return m_company; + return m_company; } -// (-1 = Japanese, 0 = English, etc)? -std::string GameListItem::GetDescription(int _index) const +std::string GameListItem::GetDescription(IVolume::ELanguage language) const { - const u32 index = _index; - - if (index < m_descriptions.size()) - return m_descriptions[index]; - - if (!m_descriptions.empty()) - return m_descriptions[0]; - - return ""; + return GetLanguageString(language, m_descriptions); } -// (-1 = Japanese, 0 = English, etc)? -std::string GameListItem::GetVolumeName(int _index) const +std::string GameListItem::GetDescription() const { - u32 const index = _index; - - if (index < m_volume_names.size() && !m_volume_names[index].empty()) - return m_volume_names[index]; - - if (!m_volume_names.empty()) - return m_volume_names[0]; - - return ""; + return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_Platform != GAMECUBE_DISC)); } -// (-1 = Japanese, 0 = English, etc)? -std::string GameListItem::GetBannerName(int _index) const +std::string GameListItem::GetName(IVolume::ELanguage language) const { - u32 const index = _index; - - if (index < m_banner_names.size() && !m_banner_names[index].empty()) - return m_banner_names[index]; - - if (!m_banner_names.empty()) - return m_banner_names[0]; - - return ""; + return GetLanguageString(language, m_names); } -// (-1 = Japanese, 0 = English, etc)? -std::string GameListItem::GetName(int _index) const +std::string GameListItem::GetName() const { - // Prefer name from banner, fallback to name from volume, fallback to filename - - std::string name = GetBannerName(_index); - - if (name.empty()) - name = GetVolumeName(_index); - + 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::vector GameListItem::GetLanguages() const +{ + std::vector languages; + for (std::pair name : m_names) + languages.push_back(name.first); + return languages; +} + const std::string GameListItem::GetWiiFSPath() const { DiscIO::IVolume *iso = DiscIO::CreateVolumeFromFilename(m_FileName); diff --git a/Source/Core/DolphinWX/ISOFile.h b/Source/Core/DolphinWX/ISOFile.h index d56f3412b8..2f65d7eec4 100644 --- a/Source/Core/DolphinWX/ISOFile.h +++ b/Source/Core/DolphinWX/ISOFile.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "Common/Common.h" @@ -24,11 +25,12 @@ public: bool IsValid() const {return m_Valid;} const std::string& GetFileName() const {return m_FileName;} - std::string GetBannerName(int index) const; - std::string GetVolumeName(int index) const; - std::string GetName(int index) const; + std::string GetName(IVolume::ELanguage language) const; + std::string GetName() const; + std::string GetDescription(IVolume::ELanguage language) const; + std::string GetDescription() const; + std::vector GetLanguages() const; std::string GetCompany() const; - std::string GetDescription(int index = 0) const; int GetRevision() const { return m_Revision; } const std::string& GetUniqueID() const {return m_UniqueID;} const std::string GetWiiFSPath() const; @@ -57,13 +59,9 @@ public: private: std::string m_FileName; - // TODO: eliminate this and overwrite with names from banner when available? - std::vector m_volume_names; - - // Stuff from banner + std::map m_names; + std::map m_descriptions; std::string m_company; - std::vector m_banner_names; - std::vector m_descriptions; std::string m_UniqueID; diff --git a/Source/Core/DolphinWX/ISOProperties.cpp b/Source/Core/DolphinWX/ISOProperties.cpp index b1ec1260a3..7885e09cc4 100644 --- a/Source/Core/DolphinWX/ISOProperties.cpp +++ b/Source/Core/DolphinWX/ISOProperties.cpp @@ -114,9 +114,8 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW { // Load ISO data OpenISO = DiscIO::CreateVolumeFromFilename(fileName); - bool IsWad = OpenISO->IsWadFile(); - // TODO: Is it really necessary to use GetTitleID in case GetUniqueID fails? + // Is it really necessary to use GetTitleID if GetUniqueID fails? game_id = OpenISO->GetUniqueID(); if (game_id.empty()) { @@ -137,7 +136,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW bRefreshList = false; - CreateGUIControls(IsWad); + CreateGUIControls(); LoadGameConfig(); @@ -173,33 +172,15 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW break; case DiscIO::IVolume::COUNTRY_USA: m_Country->SetValue(_("USA")); - if (!IsWad) // For (non wad) NTSC Games, there's no multi lang - { - m_Lang->SetSelection(0); - m_Lang->Disable(); - } - break; case DiscIO::IVolume::COUNTRY_JAPAN: m_Country->SetValue(_("Japan")); - if (!IsWad) // For (non wad) NTSC Games, there's no multi lang - { - m_Lang->Insert(_("Japanese"), 0); - m_Lang->SetSelection(0); - m_Lang->Disable(); - } break; case DiscIO::IVolume::COUNTRY_KOREA: m_Country->SetValue(_("Korea")); break; case DiscIO::IVolume::COUNTRY_TAIWAN: m_Country->SetValue(_("Taiwan")); - if (!IsWad) // For (non wad) NTSC Games, there's no multi lang - { - m_Lang->Insert(_("Taiwan"), 0); - m_Lang->SetSelection(0); - m_Lang->Disable(); - } break; case DiscIO::IVolume::COUNTRY_WORLD: m_Country->SetValue(_("World")); @@ -210,27 +191,14 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW break; } - if (OpenISO->IsWiiDisc()) // Only one language with Wii banners - { - m_Lang->SetSelection(0); - m_Lang->Disable(); - } - wxString temp = "0x" + StrToWxStr(OpenISO->GetMakerID()); m_MakerID->SetValue(temp); m_Revision->SetValue(wxString::Format("%u", OpenISO->GetRevision())); m_Date->SetValue(StrToWxStr(OpenISO->GetApploaderDate())); m_FST->SetValue(wxString::Format("%u", OpenISO->GetFSTSize())); - // Here we set all the info to be shown (be it SJIS or Ascii) + we set the window title - if (!IsWad) - { - ChangeBannerDetails(SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage); - } - else - { - ChangeBannerDetails(SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG")); - } + // Here we set all the info to be shown + we set the window title + ChangeBannerDetails(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(OpenISO->IsWadFile() || OpenISO->IsWiiDisc())); m_Banner->SetBitmap(OpenGameListItem->GetBitmap()); m_Banner->Bind(wxEVT_RIGHT_DOWN, &CISOProperties::RightClickOnBanner, this); @@ -351,7 +319,7 @@ long CISOProperties::GetElementStyle(const char* section, const char* key) return wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER; } -void CISOProperties::CreateGUIControls(bool IsWad) +void CISOProperties::CreateGUIControls() { wxButton* const EditConfig = new wxButton(this, ID_EDITCONFIG, _("Edit Config")); EditConfig->SetToolTip(_("This will let you manually edit the INI config file.")); @@ -534,24 +502,58 @@ void CISOProperties::CreateGUIControls(bool IsWad) m_MD5SumCompute = new wxButton(m_Information, ID_MD5SUMCOMPUTE, _("Compute")); wxStaticText* const m_LangText = new wxStaticText(m_Information, wxID_ANY, _("Show Language:")); - arrayStringFor_Lang.Add(_("English")); - arrayStringFor_Lang.Add(_("German")); - arrayStringFor_Lang.Add(_("French")); - arrayStringFor_Lang.Add(_("Spanish")); - arrayStringFor_Lang.Add(_("Italian")); - arrayStringFor_Lang.Add(_("Dutch")); - int language = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage; - if (IsWad) - { - arrayStringFor_Lang.Insert(_("Japanese"), 0); - arrayStringFor_Lang.Add(_("Simplified Chinese")); - arrayStringFor_Lang.Add(_("Traditional Chinese")); - arrayStringFor_Lang.Add(_("Korean")); - language = SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG"); + IVolume::ELanguage preferred_language = SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(OpenISO->IsWadFile() || OpenISO->IsWiiDisc()); + + std::vector languages = OpenGameListItem->GetLanguages(); + int preferred_language_index = 0; + for (size_t i = 0; i < languages.size(); ++i) + { + if (languages[i] == preferred_language) + preferred_language_index = i; + + switch (languages[i]) + { + case IVolume::LANGUAGE_JAPANESE: + arrayStringFor_Lang.Add(_("Japanese")); + break; + case IVolume::LANGUAGE_ENGLISH: + arrayStringFor_Lang.Add(_("English")); + break; + case IVolume::LANGUAGE_GERMAN: + arrayStringFor_Lang.Add(_("German")); + break; + case IVolume::LANGUAGE_FRENCH: + arrayStringFor_Lang.Add(_("French")); + break; + case IVolume::LANGUAGE_SPANISH: + arrayStringFor_Lang.Add(_("Spanish")); + break; + case IVolume::LANGUAGE_ITALIAN: + arrayStringFor_Lang.Add(_("Italian")); + break; + case IVolume::LANGUAGE_DUTCH: + arrayStringFor_Lang.Add(_("Dutch")); + break; + case IVolume::LANGUAGE_SIMPLIFIED_CHINESE: + arrayStringFor_Lang.Add(_("Simplified Chinese")); + break; + case IVolume::LANGUAGE_TRADITIONAL_CHINESE: + arrayStringFor_Lang.Add(_("Traditional Chinese")); + break; + case IVolume::LANGUAGE_KOREAN: + arrayStringFor_Lang.Add(_("Korean")); + break; + case IVolume::LANGUAGE_UNKNOWN: + default: + arrayStringFor_Lang.Add(_("Unknown")); + break; + } } m_Lang = new wxChoice(m_Information, ID_LANG, wxDefaultPosition, wxDefaultSize, arrayStringFor_Lang); - m_Lang->SetSelection(language); + m_Lang->SetSelection(preferred_language_index); + if (arrayStringFor_Lang.size() <= 1) + m_Lang->Disable(); wxStaticText* const m_ShortText = new wxStaticText(m_Information, wxID_ANY, _("Short Name:")); m_ShortName = new wxTextCtrl(m_Information, ID_SHORTNAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_READONLY); @@ -611,7 +613,7 @@ void CISOProperties::CreateGUIControls(bool IsWad) sInfoPage->Add(sbBannerDetails, 0, wxEXPAND|wxALL, 5); m_Information->SetSizer(sInfoPage); - if (!IsWad) + if (!OpenISO->IsWadFile()) { wxPanel* const m_Filesystem = new wxPanel(m_Notebook, ID_FILESYSTEM); m_Notebook->AddPage(m_Filesystem, _("Filesystem")); @@ -1490,13 +1492,13 @@ void CISOProperties::ActionReplayButtonClicked(wxCommandEvent& event) void CISOProperties::OnChangeBannerLang(wxCommandEvent& event) { - ChangeBannerDetails(event.GetSelection()); + ChangeBannerDetails(OpenGameListItem->GetLanguages()[event.GetSelection()]); } -void CISOProperties::ChangeBannerDetails(int lang) +void CISOProperties::ChangeBannerDetails(IVolume::ELanguage language) { - wxString const shortName = StrToWxStr(OpenGameListItem->GetName(lang)); - wxString const comment = StrToWxStr(OpenGameListItem->GetDescription(lang)); + wxString const shortName = StrToWxStr(OpenGameListItem->GetName(language)); + wxString const comment = StrToWxStr(OpenGameListItem->GetDescription(language)); wxString const maker = StrToWxStr(OpenGameListItem->GetCompany()); // Updates the information shown in the window diff --git a/Source/Core/DolphinWX/ISOProperties.h b/Source/Core/DolphinWX/ISOProperties.h index 36c539bbbc..d37a63fc4b 100644 --- a/Source/Core/DolphinWX/ISOProperties.h +++ b/Source/Core/DolphinWX/ISOProperties.h @@ -197,7 +197,7 @@ private: void LaunchExternalEditor(const std::string& filename); - void CreateGUIControls(bool); + void CreateGUIControls(); void OnClose(wxCloseEvent& event); void OnCloseClick(wxCommandEvent& event); void OnEditConfig(wxCommandEvent& event); @@ -242,7 +242,7 @@ private: void PatchList_Load(); void PatchList_Save(); void ActionReplayList_Save(); - void ChangeBannerDetails(int lang); + void ChangeBannerDetails(IVolume::ELanguage language); long GetElementStyle(const char* section, const char* key); void SetCheckboxValueFromGameini(const char* section, const char* key, wxCheckBox* checkbox); diff --git a/Source/Core/DolphinWX/MainAndroid.cpp b/Source/Core/DolphinWX/MainAndroid.cpp index 1ab7be8c57..0d5f71dc99 100644 --- a/Source/Core/DolphinWX/MainAndroid.cpp +++ b/Source/Core/DolphinWX/MainAndroid.cpp @@ -37,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" @@ -114,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::vector m_volume_names; -std::vector m_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); @@ -130,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; } } @@ -186,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; } @@ -276,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()); } diff --git a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp index febb30e570..75d839fe1b 100644 --- a/Source/Core/DolphinWX/NetPlay/NetWindow.cpp +++ b/Source/Core/DolphinWX/NetPlay/NetWindow.cpp @@ -69,7 +69,7 @@ static wxString FailureReasonStringForHostLabel(int reason) static std::string BuildGameName(const GameListItem& game) { // Lang needs to be consistent - auto const lang = 0; + IVolume::ELanguage const lang = IVolume::LANGUAGE_ENGLISH; std::string name(game.GetName(lang));