summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorcomex <comexk@gmail.com>2015-05-05 16:20:04 -0400
committercomex <comexk@gmail.com>2015-05-05 16:20:04 -0400
commit6414cdabb2ae7762f2d98427b9ff024af07bb959 (patch)
tree5362ae99777fc494d6c2b059b0bd63a6bb296b97 /Source
parent430e8b7adeb5b3adb12ef50ce7961562463b0fa0 (diff)
parentdf8e768b77b551832ace0d552ec10c1b062c55f3 (diff)
Merge pull request #2286 from JosJuice/wii-opening-bnr
Read opening.bnr to get names from Wii discs
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/ConfigManager.cpp4
-rw-r--r--Source/Core/Core/ConfigManager.h2
-rw-r--r--Source/Core/Core/CoreParameter.cpp14
-rw-r--r--Source/Core/Core/CoreParameter.h2
-rw-r--r--Source/Core/DiscIO/BannerLoader.cpp28
-rw-r--r--Source/Core/DiscIO/BannerLoader.h47
-rw-r--r--Source/Core/DiscIO/BannerLoaderGC.cpp183
-rw-r--r--Source/Core/DiscIO/BannerLoaderGC.h86
-rw-r--r--Source/Core/DiscIO/BannerLoaderWii.cpp117
-rw-r--r--Source/Core/DiscIO/BannerLoaderWii.h63
-rw-r--r--Source/Core/DiscIO/CMakeLists.txt5
-rw-r--r--Source/Core/DiscIO/DiscIO.vcxproj6
-rw-r--r--Source/Core/DiscIO/DiscIO.vcxproj.filters18
-rw-r--r--Source/Core/DiscIO/FileSystemGCWii.cpp14
-rw-r--r--Source/Core/DiscIO/FileSystemGCWii.h2
-rw-r--r--Source/Core/DiscIO/Filesystem.h2
-rw-r--r--Source/Core/DiscIO/Volume.h93
-rw-r--r--Source/Core/DiscIO/VolumeCommon.cpp78
-rw-r--r--Source/Core/DiscIO/VolumeDirectory.cpp18
-rw-r--r--Source/Core/DiscIO/VolumeDirectory.h4
-rw-r--r--Source/Core/DiscIO/VolumeGC.cpp172
-rw-r--r--Source/Core/DiscIO/VolumeGC.h46
-rw-r--r--Source/Core/DiscIO/VolumeWad.cpp42
-rw-r--r--Source/Core/DiscIO/VolumeWad.h8
-rw-r--r--Source/Core/DiscIO/VolumeWiiCrypted.cpp22
-rw-r--r--Source/Core/DiscIO/VolumeWiiCrypted.h4
-rw-r--r--Source/Core/DolphinQt/GameList/GameFile.cpp167
-rw-r--r--Source/Core/DolphinQt/GameList/GameFile.h17
-rw-r--r--Source/Core/DolphinQt/GameList/GameGrid.cpp2
-rw-r--r--Source/Core/DolphinQt/GameList/GameTree.cpp2
-rw-r--r--Source/Core/DolphinWX/Config/WiiConfigPane.cpp63
-rw-r--r--Source/Core/DolphinWX/Config/WiiConfigPane.h3
-rw-r--r--Source/Core/DolphinWX/FrameTools.cpp8
-rw-r--r--Source/Core/DolphinWX/GameListCtrl.cpp81
-rw-r--r--Source/Core/DolphinWX/GameListCtrl.h2
-rw-r--r--Source/Core/DolphinWX/Globals.h2
-rw-r--r--Source/Core/DolphinWX/ISOFile.cpp134
-rw-r--r--Source/Core/DolphinWX/ISOFile.h18
-rw-r--r--Source/Core/DolphinWX/ISOProperties.cpp114
-rw-r--r--Source/Core/DolphinWX/ISOProperties.h4
-rw-r--r--Source/Core/DolphinWX/MainAndroid.cpp98
-rw-r--r--Source/Core/DolphinWX/NetPlay/NetWindow.cpp2
42 files changed, 723 insertions, 1074 deletions
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<u8>("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 <string>
#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 <cstddef>
-
-#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 <string>
-#include <vector>
-
-#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<u32> GetBanner(int* pWidth, int* pHeight) = 0;
-
- virtual std::vector<std::string> GetNames() = 0;
- virtual std::string GetCompany() = 0;
- virtual std::vector<std::string> 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 <cstddef>
-#include <string>
-#include <vector>
-
-#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<u32> CBannerLoaderGC::GetBanner(int* pWidth, int* pHeight)
-{
- std::vector<u32> 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<std::string> CBannerLoaderGC::GetNames()
-{
- std::vector<std::string> 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<const DVDBanner*>(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<std::string> CBannerLoaderGC::GetDescriptions()
-{
- std::vector<std::string> 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<const DVDBanner*>(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 <cstring>
-#include <string>
-#include <vector>
-
-#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<u32> GetBanner(int* pWidth, int* pHeight) override;
-
- virtual std::vector<std::string> GetNames() override;
- virtual std::string GetCompany() override;
- virtual std::vector<std::string> 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 <u32 N>
- 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 <algorithm>
-#include <cstddef>
-#include <cstdio>
-#include <string>
-#include <vector>
-
-#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<u32> CBannerLoaderWii::GetBanner(int* pWidth, int* pHeight)
-{
- SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
- std::vector<u32> 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<const SWiiBanner*>(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<std::string> CBannerLoaderWii::GetNames()
-{
- std::vector<std::string> ret(1);
-
- if (!GetStringFromComments(NAME_IDX, ret[0]))
- ret.clear();
-
- return ret;
-}
-
-std::string CBannerLoaderWii::GetCompany()
-{
- return "";
-}
-
-std::vector<std::string> CBannerLoaderWii::GetDescriptions()
-{
- std::vector<std::string> 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 <string>
-#include <vector>
-
-#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<u32> GetBanner(int* pWidth, int* pHeight) override;
-
- virtual std::vector<std::string> GetNames() override;
- virtual std::string GetCompany() override;
- virtual std::vector<std::string> 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 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemGroup>
- <ClCompile Include="BannerLoader.cpp" />
- <ClCompile Include="BannerLoaderGC.cpp" />
- <ClCompile Include="BannerLoaderWii.cpp" />
<ClCompile Include="Blob.cpp" />
<ClCompile Include="CISOBlob.cpp" />
<ClCompile Include="CompressedBlob.cpp" />
@@ -58,9 +55,6 @@
<ClCompile Include="WiiWad.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="BannerLoader.h" />
- <ClInclude Include="BannerLoaderGC.h" />
- <ClInclude Include="BannerLoaderWii.h" />
<ClInclude Include="Blob.h" />
<ClInclude Include="CISOBlob.h" />
<ClInclude Include="CompressedBlob.h" />
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 @@
<ClCompile Include="DiscScrubber.cpp">
<Filter>DiscScrubber</Filter>
</ClCompile>
- <ClCompile Include="BannerLoader.cpp">
- <Filter>FileHandler</Filter>
- </ClCompile>
- <ClCompile Include="BannerLoaderGC.cpp">
- <Filter>FileHandler</Filter>
- </ClCompile>
- <ClCompile Include="BannerLoaderWii.cpp">
- <Filter>FileHandler</Filter>
- </ClCompile>
<ClCompile Include="Filesystem.cpp">
<Filter>FileSystem</Filter>
</ClCompile>
@@ -89,15 +80,6 @@
<ClInclude Include="DiscScrubber.h">
<Filter>DiscScrubber</Filter>
</ClInclude>
- <ClInclude Include="BannerLoaderWii.h">
- <Filter>FileHandler</Filter>
- </ClInclude>
- <ClInclude Include="BannerLoader.h">
- <Filter>FileHandler</Filter>
- </ClInclude>
- <ClInclude Include="BannerLoaderGC.h">
- <Filter>FileHandler</Filter>
- </ClInclude>
<ClInclude Include="Filesystem.h">
<Filter>FileSystem</Filter>
</ClInclude>
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<const SFileInfo *> &_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<const SFileInfo *> &_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 <map>
#include <memory>
#include <string>
#include <vector>
#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<std::string> GetNames() const = 0;
+ virtual int GetRevision() const = 0;
+ virtual std::string GetName() const = 0;
+ virtual std::map<ELanguage, std::string> GetNames() const = 0;
+ virtual std::map<ELanguage, std::string> GetDescriptions() const { return std::map<ELanguage, std::string>(); }
+ virtual std::string GetCompany() const { return std::string(); }
+ virtual std::vector<u32> 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 <u32 N>
+ 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<IVolume::ELanguage, std::string> ReadWiiNames(std::vector<u8>& 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 <algorithm>
+#include <map>
#include <string>
+#include <utility>
#include <vector>
+#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<u32> 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<u32>();
+
+ if (File::GetSize(file_name) < WII_BANNER_OFFSET + WII_BANNER_SIZE)
+ return std::vector<u32>();
+
+ File::IOFile file(file_name, "rb");
+ if (!file.Seek(WII_BANNER_OFFSET, SEEK_SET))
+ return std::vector<u32>();
+
+ std::vector<u8> banner_file(WII_BANNER_SIZE);
+ if (!file.ReadBytes(banner_file.data(), banner_file.size()))
+ return std::vector<u32>();
+
+ std::vector<u32> 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::ELanguage, std::string> IVolume::ReadWiiNames(std::vector<u8>& data)
+{
+ std::map<IVolume::ELanguage, std::string> 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 <map>
#include <memory>
#include <string>
-#include <utility>
#include <vector>
#include "Common/CommonPaths.h"
@@ -183,9 +182,22 @@ std::string CVolumeDirectory::GetMakerID() const
return "VOID";
}
-std::vector<std::string> CVolumeDirectory::GetNames() const
+std::string CVolumeDirectory::GetName() const
{
- return std::vector<std::string>(1, (char*)(&m_diskHeader[0x20]));
+ char name[0x60];
+ if (Read(0x20, 0x60, (u8*)name, false))
+ return DecodeString(name);
+ else
+ return "";
+}
+
+std::map<IVolume::ELanguage, std::string> CVolumeDirectory::GetNames() const
+{
+ std::map<IVolume::ELanguage, std::string> 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<std::string> GetNames() const override;
+ int GetRevision() const override { return 0; }
+ std::string GetName() const override;
+ std::map<IVolume::ELanguage, std::string> 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 <cstddef>
+#include <map>
#include <memory>
#include <string>
#include <vector>
+#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<std::string> CVolumeGC::GetNames() const
+std::string CVolumeGC::GetName() const
{
- std::vector<std::string> names;
+ char name[0x60];
+ if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name))
+ return DecodeString(name);
+ else
+ return "";
+}
- auto const string_decoder = GetStringDecoder(GetCountry());
+std::map<IVolume::ELanguage, std::string> CVolumeGC::GetNames() const
+{
+ std::map<IVolume::ELanguage, std::string> names;
- char name[0x60 + 1] = {};
- if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name))
- names.push_back(string_decoder(name));
+ 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<const GCBanner*>(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<IVolume::ELanguage, std::string> CVolumeGC::GetDescriptions() const
+{
+ std::map<IVolume::ELanguage, std::string> 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<const GCBanner*>(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<u32> CVolumeGC::GetBanner(int* width, int* height) const
+{
+ if (!LoadBannerFile())
+ {
+ *width = 0;
+ *height = 0;
+ return std::vector<u32>();
+ }
+
+ std::vector<u32> 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<IFileSystem> 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 <map>
#include <memory>
#include <string>
#include <vector>
@@ -27,7 +28,11 @@ public:
std::string GetUniqueID() const override;
std::string GetMakerID() const override;
int GetRevision() const override;
- std::vector<std::string> GetNames() const override;
+ virtual std::string GetName() const override;
+ std::map<ELanguage, std::string> GetNames() const override;
+ std::map<ELanguage, std::string> GetDescriptions() const override;
+ std::string GetCompany() const override;
+ std::vector<u32> 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&);
+private:
+ bool LoadBannerFile() const;
- static StringDecoder GetStringDecoder(ECountry country);
+ 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<u8> m_banner_file;
-private:
std::unique_ptr<IBlobReader> 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 <algorithm>
#include <cstddef>
+#include <map>
#include <string>
#include <vector>
@@ -117,42 +117,12 @@ bool CVolumeWAD::IsWadFile() const
return true;
}
-std::vector<std::string> CVolumeWAD::GetNames() const
+std::map<IVolume::ELanguage, std::string> CVolumeWAD::GetNames() const
{
- std::vector<std::string> 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<u8> name_data(NAMES_TOTAL_BYTES);
+ if (!Read(m_opening_bnr_offset + 0x9C, NAMES_TOTAL_BYTES, name_data.data()))
+ return std::map<IVolume::ELanguage, std::string>();
+ 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 <map>
#include <memory>
#include <string>
#include <vector>
@@ -30,9 +31,10 @@ public:
std::string GetUniqueID() const override;
std::string GetMakerID() const override;
int GetRevision() const override;
- std::vector<std::string> GetNames() const override;
- u32 GetFSTSize() const override { return 0; }
- std::string GetApploaderDate() const override { return "0"; }
+ std::string GetName() const override { return ""; }
+ std::map<IVolume::ELanguage, std::string> 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 <cstddef>
#include <cstring>
+#include <map>
#include <string>
#include <vector>
#include <polarssl/aes.h>
@@ -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<std::string> CVolumeWiiCrypted::GetNames() const
+std::string CVolumeWiiCrypted::GetName() const
{
- std::vector<std::string> 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());
-
- char name[0xFF] = {};
- if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name, true))
- names.push_back(string_decoder(name));
+ return "";
+}
- return names;
+std::map<IVolume::ELanguage, std::string> CVolumeWiiCrypted::GetNames() const
+{
+ std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this));
+ std::vector<u8> 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 <map>
#include <memory>
#include <string>
#include <vector>
@@ -30,7 +31,8 @@ public:
std::string GetUniqueID() const override;
std::string GetMakerID() const override;
int GetRevision() const override;
- std::vector<std::string> GetNames() const override;
+ std::string GetName() const override;
+ std::map<IVolume::ELanguage, std::string> 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,23 +25,48 @@
#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<std::string> vec, bool trim = false)
+static QMap<IVolume::ELanguage, QString> ConvertLocalizedStrings(std::map<IVolume::ELanguage, std::string> strings)
{
- QStringList result;
- if (trim)
- {
- for (const std::string& member : vec)
- result.append(QString::fromStdString(member).trimmed());
- }
- else
+ QMap<IVolume::ELanguage, QString> result;
+
+ for (auto entry : strings)
+ result.insert(entry.first, QString::fromStdString(entry.second).trimmed());
+
+ return result;
+}
+
+template<class to, class from>
+static QMap<to, QString> CastLocalizedStrings(QMap<from, QString> strings)
+{
+ QMap<to, QString> 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<IVolume::ELanguage, QString> 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)
{
- for (const std::string& member : vec)
- result.append(QString::fromStdString(member));
+ if (strings.contains(IVolume::ELanguage::LANGUAGE_ENGLISH))
+ return strings.value(IVolume::ELanguage::LANGUAGE_ENGLISH);
}
- return result;
+
+ // If English isn't available either, just pick something
+ if (!strings.empty())
+ return strings.cbegin().value();
+
+ return SL("");
}
GameFile::GameFile(const QString& fileName)
@@ -57,7 +81,7 @@ GameFile::GameFile(const QString& fileName)
}
else
{
- DiscIO::IVolume* volume = DiscIO::CreateVolumeFromFilename(fileName.toStdString());
+ std::unique_ptr<DiscIO::IVolume> 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);
+ int width, height;
+ std::vector<u32> buffer = volume->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 (fileSystem != nullptr || m_platform == WII_WAD)
+ if (!banner.isNull())
{
- std::unique_ptr<DiscIO::IBannerLoader> 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<u32> 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;
+ 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<u8, QString> names;
+ QMap<u8, QString> 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<IVolume::ELanguage>(names);
+ m_descriptions = CastLocalizedStrings<IVolume::ELanguage>(descriptions);
file.close();
return true;
}
@@ -198,13 +207,13 @@ void GameFile::SaveToCache()
stream << CACHE_REVISION;
stream << m_folder_name
- << m_volume_names
+ << CastLocalizedStrings<u8>(m_names)
+ << CastLocalizedStrings<u8>(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 <QMap>
#include <QPixmap>
#include <QString>
-#include <QStringList>
#include <string>
@@ -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<DiscIO::IVolume::ELanguage, QString> m_names;
+ QMap<DiscIO::IVolume::ELanguage, QString> 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 <wx/arrstr.h>
#include <wx/panel.h>
#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<u8>("IPL.LNG");
- }
- else // GC
- {
- indexOne = SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage;
- }
-
- if (iso2->GetPlatform() == GameListItem::WII_WAD)
- {
- indexOther = SConfig::GetInstance().m_SYSCONF->GetData<u8>("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<u8>("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 <cstring>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <wx/app.h>
#include <wx/bitmap.h>
@@ -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<IVolume::ELanguage, std::string> 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<u32> 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<DiscIO::IBannerLoader> 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<u32> 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<IVolume::ELanguage> GameListItem::GetLanguages() const
+{
+ std::vector<IVolume::ELanguage> languages;
+ for (std::pair<IVolume::ELanguage, std::string> 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 <string>
+#include <utility>
#include <vector>
#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<IVolume::ELanguage> 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<std::string> m_volume_names;
-
- // Stuff from banner
+ std::map<IVolume::ELanguage, std::string> m_names;
+ std::map<IVolume::ELanguage, std::string> m_descriptions;
std::string m_company;
- std::vector<std::string> m_banner_names;
- std::vector<std::string> 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<u8>("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)
+
+ IVolume::ELanguage preferred_language = SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(OpenISO->IsWadFile() || OpenISO->IsWiiDisc());
+
+ std::vector<IVolume::ELanguage> languages = OpenGameListItem->GetLanguages();
+ int preferred_language_index = 0;
+ for (size_t i = 0; i < languages.size(); ++i)
{
- arrayStringFor_Lang.Insert(_("Japanese"), 0);
- arrayStringFor_Lang.Add(_("Simplified Chinese"));
- arrayStringFor_Lang.Add(_("Traditional Chinese"));
- arrayStringFor_Lang.Add(_("Korean"));
+ if (languages[i] == preferred_language)
+ preferred_language_index = i;
- language = SConfig::GetInstance().m_SYSCONF->GetData<u8>("IPL.LNG");
+ 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<std::string> m_volume_names;
-std::vector<std::string> m_names;
+std::map<DiscIO::IVolume::ELanguage, std::string> 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<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(filename));
if (pVolume != nullptr)
{
- bool bIsWad = false;
- if (DiscIO::IsVolumeWadFile(pVolume))
- bIsWad = true;
-
- 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)
+ m_names = pVolume->GetNames();
+ m_is_wii_title = pVolume->IsWiiDisc() || pVolume->IsWadFile();
+
+ int Width, Height;
+ std::vector<u32> 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<u32> 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)
{
+ 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[0];
+ 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));