summaryrefslogtreecommitdiff
path: root/Source/Core/DiscIO
diff options
context:
space:
mode:
authorMatthew Parlane <parlane@gmail.com>2017-02-27 16:15:05 +1300
committerGitHub <noreply@github.com>2017-02-27 16:15:05 +1300
commit48aeb5bf4be58eafd9a9fd36de983aaccfc25365 (patch)
treef7fb394acdc67efce888648ecf6d66d71e277964 /Source/Core/DiscIO
parentd1b343ab5aebf9398c5b3d78382678df50728d0c (diff)
parent44a3db21e4b7fe20ee2ed6253990f5981b3f12f9 (diff)
Merge pull request #4896 from leoetlino/esformats
Use ESFormats for tickets, TMDs and views
Diffstat (limited to 'Source/Core/DiscIO')
-rw-r--r--Source/Core/DiscIO/NANDContentLoader.cpp232
-rw-r--r--Source/Core/DiscIO/NANDContentLoader.h57
-rw-r--r--Source/Core/DiscIO/Volume.h3
-rw-r--r--Source/Core/DiscIO/VolumeWad.cpp43
-rw-r--r--Source/Core/DiscIO/VolumeWad.h4
-rw-r--r--Source/Core/DiscIO/VolumeWiiCrypted.cpp4
-rw-r--r--Source/Core/DiscIO/VolumeWiiCrypted.h3
-rw-r--r--Source/Core/DiscIO/WiiWad.cpp4
-rw-r--r--Source/Core/DiscIO/WiiWad.h9
9 files changed, 116 insertions, 243 deletions
diff --git a/Source/Core/DiscIO/NANDContentLoader.cpp b/Source/Core/DiscIO/NANDContentLoader.cpp
index fc1f600aa1..1204550fab 100644
--- a/Source/Core/DiscIO/NANDContentLoader.cpp
+++ b/Source/Core/DiscIO/NANDContentLoader.cpp
@@ -4,12 +4,12 @@
#include <algorithm>
#include <array>
+#include <cinttypes>
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <functional>
#include <map>
-#include <mbedtls/aes.h>
#include <string>
#include <utility>
#include <vector>
@@ -17,6 +17,7 @@
#include "Common/Align.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
+#include "Common/Crypto/AES.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
@@ -29,50 +30,6 @@
namespace DiscIO
{
-namespace
-{
-// Strips the signature part of a ticket, which has variable size based on
-// signature type. Returns a new vector which has only the ticket structure
-// itself.
-std::vector<u8> SignedTicketToTicket(const std::vector<u8>& signed_ticket)
-{
- u32 signature_type = Common::swap32(signed_ticket.data());
- u32 entry_offset;
- if (signature_type == 0x10000) // RSA4096
- {
- entry_offset = 576;
- }
- else if (signature_type == 0x10001) // RSA2048
- {
- entry_offset = 320;
- }
- else if (signature_type == 0x10002) // ECDSA
- {
- entry_offset = 128;
- }
- else
- {
- ERROR_LOG(DISCIO, "Invalid ticket signature type: %08x", signature_type);
- return std::vector<u8>();
- }
-
- std::vector<u8> ticket(signed_ticket.size() - entry_offset);
- std::copy(signed_ticket.begin() + entry_offset, signed_ticket.end(), ticket.begin());
- return ticket;
-}
-
-std::vector<u8> AESDecode(const u8* key, u8* iv, const u8* src, u32 size)
-{
- mbedtls_aes_context aes_ctx;
- std::vector<u8> buffer(size);
-
- mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
- mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, size, iv, src, buffer.data());
-
- return buffer;
-}
-}
-
CNANDContentData::~CNANDContentData() = default;
CSharedContent::CSharedContent(Common::FromWhichRoot root) : m_root(root)
@@ -191,7 +148,6 @@ bool CNANDContentDataBuffer::GetRange(u32 start, u32 size, u8* buffer)
}
CNANDContentLoader::CNANDContentLoader(const std::string& content_name)
- : m_Valid(false), m_IsWAD(false), m_TitleID(-1), m_IosVersion(0x09), m_BootIndex(-1)
{
m_Valid = Initialize(content_name);
}
@@ -200,11 +156,16 @@ CNANDContentLoader::~CNANDContentLoader()
{
}
+bool CNANDContentLoader::IsValid() const
+{
+ return m_Valid && m_tmd.IsValid();
+}
+
const SNANDContent* CNANDContentLoader::GetContentByIndex(int index) const
{
for (auto& Content : m_Content)
{
- if (Content.m_Index == index)
+ if (Content.m_metadata.index == index)
{
return &Content;
}
@@ -221,15 +182,12 @@ bool CNANDContentLoader::Initialize(const std::string& name)
WiiWAD wad(name);
std::vector<u8> data_app;
- std::vector<u8> tmd;
- std::vector<u8> decrypted_title_key;
if (wad.IsValid())
{
m_IsWAD = true;
- m_Ticket = wad.GetTicket();
- decrypted_title_key = GetKeyFromTicket(m_Ticket);
- tmd = wad.GetTMD();
+ m_ticket = wad.GetTicket();
+ m_tmd = wad.GetTMD();
data_app = wad.GetDataApp();
}
else
@@ -248,92 +206,64 @@ bool CNANDContentLoader::Initialize(const std::string& name)
return false;
}
- tmd.resize(static_cast<size_t>(File::GetSize(tmd_filename)));
- tmd_file.ReadBytes(tmd.data(), tmd.size());
- }
-
- std::copy(&tmd[0], &tmd[TMD_HEADER_SIZE], m_TMDHeader);
- std::copy(&tmd[0x180], &tmd[0x180 + TMD_VIEW_SIZE], m_TMDView);
-
- m_TitleVersion = Common::swap16(&tmd[0x01DC]);
- m_NumEntries = Common::swap16(&tmd[0x01DE]);
- m_BootIndex = Common::swap16(&tmd[0x01E0]);
- m_TitleID = Common::swap64(&tmd[0x018C]);
- m_IosVersion = Common::swap16(&tmd[0x018A]);
- m_Country = static_cast<u8>(m_TitleID & 0xFF);
+ std::vector<u8> bytes(File::GetSize(tmd_filename));
+ tmd_file.ReadBytes(bytes.data(), bytes.size());
+ m_tmd.SetBytes(std::move(bytes));
- if (m_Country == 2) // SYSMENU
- m_Country = GetSysMenuRegion(m_TitleVersion);
+ m_ticket = FindSignedTicket(m_tmd.GetTitleId());
+ }
- InitializeContentEntries(tmd, decrypted_title_key, data_app);
+ InitializeContentEntries(data_app);
return true;
}
-void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& tmd,
- const std::vector<u8>& decrypted_title_key,
- const std::vector<u8>& data_app)
+void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& data_app)
{
- m_Content.resize(m_NumEntries);
+ if (!m_ticket.IsValid())
+ {
+ ERROR_LOG(IOS_ES, "No valid ticket for title %016" PRIx64, m_tmd.GetTitleId());
+ return;
+ }
- std::array<u8, 16> iv;
- u32 data_app_offset = 0;
+ const std::vector<IOS::ES::Content> contents = m_tmd.GetContents();
+ m_Content.resize(contents.size());
+ u32 data_app_offset = 0;
+ const std::vector<u8> title_key = m_ticket.GetTitleKey();
CSharedContent shared_content{Common::FromWhichRoot::FROM_SESSION_ROOT};
- for (u32 i = 0; i < m_NumEntries; i++)
+ for (size_t i = 0; i < contents.size(); ++i)
{
- const u32 entry_offset = 0x24 * i;
-
- SNANDContent& content = m_Content[i];
- content.m_ContentID = Common::swap32(&tmd[entry_offset + 0x01E4]);
- content.m_Index = Common::swap16(&tmd[entry_offset + 0x01E8]);
- content.m_Type = Common::swap16(&tmd[entry_offset + 0x01EA]);
- content.m_Size = static_cast<u32>(Common::swap64(&tmd[entry_offset + 0x01EC]));
-
- const auto header_begin = std::next(tmd.begin(), entry_offset + 0x01E4);
- const auto header_end = std::next(header_begin, ArraySize(content.m_Header));
- std::copy(header_begin, header_end, content.m_Header);
-
- const auto hash_begin = std::next(tmd.begin(), entry_offset + 0x01F4);
- const auto hash_end = std::next(hash_begin, ArraySize(content.m_SHA1Hash));
- std::copy(hash_begin, hash_end, content.m_SHA1Hash);
+ const auto& content = contents.at(i);
if (m_IsWAD)
{
- u32 rounded_size = Common::AlignUp(content.m_Size, 0x40);
-
- iv.fill(0);
- std::copy(&tmd[entry_offset + 0x01E8], &tmd[entry_offset + 0x01E8 + 2], iv.begin());
+ // The content index is used as IV (2 bytes); the remaining 14 bytes are zeroes.
+ std::array<u8, 16> iv{};
+ iv[0] = static_cast<u8>(content.index >> 8) & 0xFF;
+ iv[1] = static_cast<u8>(content.index) & 0xFF;
- content.m_Data = std::make_unique<CNANDContentDataBuffer>(AESDecode(
- decrypted_title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size));
+ u32 rounded_size = Common::AlignUp(static_cast<u32>(content.size), 0x40);
+ m_Content[i].m_Data = std::make_unique<CNANDContentDataBuffer>(Common::AES::Decrypt(
+ title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size));
data_app_offset += rounded_size;
- continue;
}
-
- std::string filename;
- if (content.m_Type & 0x8000) // shared app
- filename = shared_content.GetFilenameFromSHA1(content.m_SHA1Hash);
else
- filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_ContentID);
+ {
+ std::string filename;
+ if (content.type & 0x8000) // shared app
+ filename = shared_content.GetFilenameFromSHA1(content.sha1.data());
+ else
+ filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.id);
- content.m_Data = std::make_unique<CNANDContentDataFile>(filename);
+ m_Content[i].m_Data = std::make_unique<CNANDContentDataFile>(filename);
+ }
- // Be graceful about incorrect TMDs.
- if (File::Exists(filename))
- content.m_Size = static_cast<u32>(File::GetSize(filename));
+ m_Content[i].m_metadata = std::move(content);
}
}
-DiscIO::Region CNANDContentLoader::GetRegion() const
-{
- if (!IsValid())
- return DiscIO::Region::UNKNOWN_REGION;
-
- return RegionSwitchWii(m_Country);
-}
-
CNANDContentManager::~CNANDContentManager()
{
}
@@ -372,18 +302,18 @@ void CNANDContentManager::ClearCache()
void CNANDContentLoader::RemoveTitle() const
{
- INFO_LOG(DISCIO, "RemoveTitle %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID);
+ const u64 title_id = m_tmd.GetTitleId();
+ INFO_LOG(DISCIO, "RemoveTitle %08x/%08x", (u32)(title_id >> 32), (u32)title_id);
if (IsValid())
{
// remove TMD?
- for (u32 i = 0; i < m_NumEntries; i++)
+ for (const auto& content : m_Content)
{
- if (!(m_Content[i].m_Type & 0x8000)) // skip shared apps
+ if (!(content.m_metadata.type & 0x8000)) // skip shared apps
{
- std::string filename =
- StringFromFormat("%s/%08x.app", m_Path.c_str(), m_Content[i].m_ContentID);
- INFO_LOG(DISCIO, "Delete %s", filename.c_str());
- File::Delete(filename);
+ std::string path = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_metadata.id);
+ INFO_LOG(DISCIO, "Delete %s", path.c_str());
+ File::Delete(path);
}
}
CNANDContentManager::Access().ClearCache(); // deletes 'this'
@@ -470,7 +400,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
if (content_loader.IsValid() == false)
return 0;
- u64 title_id = content_loader.GetTitleID();
+ const u64 title_id = content_loader.GetTMD().GetTitleId();
// copy WAD's TMD header and contents to content directory
@@ -485,20 +415,17 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
return 0;
}
- tmd_file.WriteBytes(content_loader.GetTMDHeader(), CNANDContentLoader::TMD_HEADER_SIZE);
+ const auto& raw_tmd = content_loader.GetTMD().GetRawTMD();
+ tmd_file.WriteBytes(raw_tmd.data(), raw_tmd.size());
CSharedContent shared_content{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
- for (u32 i = 0; i < content_loader.GetContentSize(); i++)
+ for (const auto& content : content_loader.GetContent())
{
- const SNANDContent& content = content_loader.GetContent()[i];
-
- tmd_file.WriteBytes(content.m_Header, CNANDContentLoader::CONTENT_HEADER_SIZE);
-
std::string app_filename;
- if (content.m_Type & 0x8000) // shared
- app_filename = shared_content.AddSharedContent(content.m_SHA1Hash);
+ if (content.m_metadata.type & 0x8000) // shared
+ app_filename = shared_content.AddSharedContent(content.m_metadata.sha1.data());
else
- app_filename = StringFromFormat("%s%08x.app", content_path.c_str(), content.m_ContentID);
+ app_filename = StringFromFormat("%s%08x.app", content_path.c_str(), content.m_metadata.id);
if (!File::Exists(app_filename))
{
@@ -510,7 +437,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
return 0;
}
- app_file.WriteBytes(content.m_Data->Get().data(), content.m_Size);
+ app_file.WriteBytes(content.m_Data->Get().data(), content.m_metadata.size);
}
else
{
@@ -533,14 +460,14 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
return title_id;
}
-bool AddTicket(const std::vector<u8>& signed_ticket)
+bool AddTicket(const IOS::ES::TicketReader& signed_ticket)
{
- std::vector<u8> ticket = SignedTicketToTicket(signed_ticket);
- if (ticket.empty())
+ if (!signed_ticket.IsValid())
{
return false;
}
- u64 title_id = Common::swap64(ticket.data() + 0x9c);
+
+ u64 title_id = signed_ticket.GetTitleId();
std::string ticket_filename = Common::GetTicketFileName(title_id, Common::FROM_CONFIGURED_ROOT);
File::CreateFullPath(ticket_filename);
@@ -549,46 +476,25 @@ bool AddTicket(const std::vector<u8>& signed_ticket)
if (!ticket_file)
return false;
- return ticket_file.WriteBytes(signed_ticket.data(), signed_ticket.size());
+ const std::vector<u8>& raw_ticket = signed_ticket.GetRawTicket();
+ return ticket_file.WriteBytes(raw_ticket.data(), raw_ticket.size());
}
-std::vector<u8> FindSignedTicket(u64 title_id)
+IOS::ES::TicketReader FindSignedTicket(u64 title_id)
{
std::string ticket_filename = Common::GetTicketFileName(title_id, Common::FROM_CONFIGURED_ROOT);
File::IOFile ticket_file(ticket_filename, "rb");
if (!ticket_file)
{
- return std::vector<u8>();
+ return IOS::ES::TicketReader{};
}
std::vector<u8> signed_ticket(ticket_file.GetSize());
if (!ticket_file.ReadBytes(signed_ticket.data(), signed_ticket.size()))
{
- return std::vector<u8>();
- }
-
- return signed_ticket;
-}
-
-std::vector<u8> FindTicket(u64 title_id)
-{
- std::vector<u8> signed_ticket = FindSignedTicket(title_id);
- if (signed_ticket.empty())
- {
- return std::vector<u8>();
+ return IOS::ES::TicketReader{};
}
- return SignedTicketToTicket(signed_ticket);
+ return IOS::ES::TicketReader{std::move(signed_ticket)};
}
-
-std::vector<u8> GetKeyFromTicket(const std::vector<u8>& signed_ticket)
-{
- const u8 common_key[16] = {0xeb, 0xe4, 0x2a, 0x22, 0x5e, 0x85, 0x93, 0xe4,
- 0x48, 0xd9, 0xc5, 0x45, 0x73, 0x81, 0xaa, 0xf7};
- u8 iv[16] = {};
-
- std::copy(&signed_ticket[0x01DC], &signed_ticket[0x01DC + 8], iv);
- return AESDecode(common_key, iv, &signed_ticket[0x01BF], 16);
-}
-
} // namespace end
diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h
index 632ac0ef3e..ca9b8fe78d 100644
--- a/Source/Core/DiscIO/NANDContentLoader.h
+++ b/Source/Core/DiscIO/NANDContentLoader.h
@@ -12,6 +12,7 @@
#include "Common/CommonTypes.h"
#include "Common/NandPaths.h"
+#include "Core/IOS/ES/Formats.h"
namespace File
{
@@ -22,10 +23,8 @@ namespace DiscIO
{
enum class Region;
-bool AddTicket(const std::vector<u8>& signed_ticket);
-std::vector<u8> FindSignedTicket(u64 title_id);
-std::vector<u8> FindTicket(u64 title_id);
-std::vector<u8> GetKeyFromTicket(const std::vector<u8>& ticket);
+bool AddTicket(const IOS::ES::TicketReader& signed_ticket);
+IOS::ES::TicketReader FindSignedTicket(u64 title_id);
class CNANDContentData
{
@@ -67,13 +66,7 @@ private:
struct SNANDContent
{
- u32 m_ContentID;
- u16 m_Index;
- u16 m_Type;
- u32 m_Size;
- u8 m_SHA1Hash[20];
- u8 m_Header[36]; // all of the above
-
+ IOS::ES::Content m_metadata;
std::unique_ptr<CNANDContentData> m_Data;
};
@@ -84,47 +77,21 @@ public:
explicit CNANDContentLoader(const std::string& content_name);
~CNANDContentLoader();
- bool IsValid() const { return m_Valid; }
+ bool IsValid() const;
void RemoveTitle() const;
- u64 GetTitleID() const { return m_TitleID; }
- u16 GetIosVersion() const { return m_IosVersion; }
- u32 GetBootIndex() const { return m_BootIndex; }
- size_t GetContentSize() const { return m_Content.size(); }
const SNANDContent* GetContentByIndex(int index) const;
- const u8* GetTMDView() const { return m_TMDView; }
- const u8* GetTMDHeader() const { return m_TMDHeader; }
- const std::vector<u8>& GetTicket() const { return m_Ticket; }
+ const IOS::ES::TMDReader& GetTMD() const { return m_tmd; }
+ const IOS::ES::TicketReader& GetTicket() const { return m_ticket; }
const std::vector<SNANDContent>& GetContent() const { return m_Content; }
- u16 GetTitleVersion() const { return m_TitleVersion; }
- u16 GetNumEntries() const { return m_NumEntries; }
- DiscIO::Region GetRegion() const;
- u8 GetCountryChar() const { return m_Country; }
- enum
- {
- TMD_VIEW_SIZE = 0x58,
- TMD_HEADER_SIZE = 0x1E4,
- CONTENT_HEADER_SIZE = 0x24,
- TICKET_SIZE = 0x2A4
- };
-
private:
bool Initialize(const std::string& name);
- void InitializeContentEntries(const std::vector<u8>& tmd,
- const std::vector<u8>& decrypted_title_key,
- const std::vector<u8>& data_app);
+ void InitializeContentEntries(const std::vector<u8>& data_app);
- bool m_Valid;
- bool m_IsWAD;
+ bool m_Valid = false;
+ bool m_IsWAD = false;
std::string m_Path;
- u64 m_TitleID;
- u16 m_IosVersion;
- u32 m_BootIndex;
- u16 m_NumEntries;
- u16 m_TitleVersion;
- u8 m_TMDView[TMD_VIEW_SIZE];
- u8 m_TMDHeader[TMD_HEADER_SIZE];
- std::vector<u8> m_Ticket;
- u8 m_Country;
+ IOS::ES::TMDReader m_tmd;
+ IOS::ES::TicketReader m_ticket;
std::vector<SNANDContent> m_Content;
};
diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h
index 966bbe2ae1..1190565004 100644
--- a/Source/Core/DiscIO/Volume.h
+++ b/Source/Core/DiscIO/Volume.h
@@ -12,6 +12,7 @@
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/StringUtil.h"
+#include "Core/IOS/ES/Formats.h"
#include "DiscIO/Enums.h"
namespace DiscIO
@@ -36,7 +37,7 @@ public:
}
virtual bool GetTitleID(u64*) const { return false; }
- virtual std::vector<u8> GetTMD() const { return {}; }
+ virtual IOS::ES::TMDReader GetTMD() const { return {}; }
virtual u64 PartitionOffsetToRawOffset(u64 offset) const { return offset; }
virtual std::string GetGameID() const = 0;
virtual std::string GetMakerID() const = 0;
diff --git a/Source/Core/DiscIO/VolumeWad.cpp b/Source/Core/DiscIO/VolumeWad.cpp
index 29f543586d..01080c7b52 100644
--- a/Source/Core/DiscIO/VolumeWad.cpp
+++ b/Source/Core/DiscIO/VolumeWad.cpp
@@ -36,6 +36,16 @@ CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) : m_reader(std::move
Common::AlignUp(m_tick_size, 0x40);
m_opening_bnr_offset =
m_tmd_offset + Common::AlignUp(m_tmd_size, 0x40) + Common::AlignUp(m_data_size, 0x40);
+
+ if (m_tmd_size > 1024 * 1024 * 4)
+ {
+ ERROR_LOG(DISCIO, "TMD is too large: %u bytes", m_tmd_size);
+ return;
+ }
+
+ std::vector<u8> tmd_buffer(m_tmd_size);
+ Read(m_tmd_offset, m_tmd_size, tmd_buffer.data(), false);
+ m_tmd.SetBytes(std::move(tmd_buffer));
}
CVolumeWAD::~CVolumeWAD()
@@ -55,40 +65,26 @@ bool CVolumeWAD::Read(u64 offset, u64 length, u8* buffer, bool decrypt) const
Region CVolumeWAD::GetRegion() const
{
- u8 country_code;
- if (!Read(m_tmd_offset + 0x0193, 1, &country_code))
+ if (!m_tmd.IsValid())
return Region::UNKNOWN_REGION;
-
- return RegionSwitchWii(country_code);
+ return m_tmd.GetRegion();
}
Country CVolumeWAD::GetCountry() const
{
- // read the last digit of the titleID in the ticket
- u8 country_code;
- if (!Read(m_tmd_offset + 0x0193, 1, &country_code))
+ if (!m_tmd.IsValid())
return Country::COUNTRY_UNKNOWN;
+ u8 country_code = static_cast<u8>(m_tmd.GetTitleId() & 0xff);
if (country_code == 2) // SYSMENU
- {
- u16 title_version = 0;
- Read(m_tmd_offset + 0x01dc, 2, (u8*)&title_version);
- country_code = GetSysMenuRegion(Common::swap16(title_version));
- }
+ country_code = GetSysMenuRegion(m_tmd.GetTitleVersion());
return CountrySwitch(country_code);
}
-std::vector<u8> CVolumeWAD::GetTMD() const
+IOS::ES::TMDReader CVolumeWAD::GetTMD() const
{
- if (m_tmd_size > 1024 * 1024 * 4)
- {
- ERROR_LOG(DISCIO, "TMD is too large: %u bytes", m_tmd_size);
- return {};
- }
- std::vector<u8> buffer(m_tmd_size);
- Read(m_tmd_offset, m_tmd_size, buffer.data(), false);
- return buffer;
+ return m_tmd;
}
std::string CVolumeWAD::GetGameID() const
@@ -125,11 +121,10 @@ bool CVolumeWAD::GetTitleID(u64* buffer) const
u16 CVolumeWAD::GetRevision() const
{
- u16 revision;
- if (!m_reader->Read(m_tmd_offset + 0x1dc, 2, (u8*)&revision))
+ if (!m_tmd.IsValid())
return 0;
- return Common::swap16(revision);
+ return m_tmd.GetTitleVersion();
}
Platform CVolumeWAD::GetVolumeType() const
diff --git a/Source/Core/DiscIO/VolumeWad.h b/Source/Core/DiscIO/VolumeWad.h
index c93315f72b..f84af08796 100644
--- a/Source/Core/DiscIO/VolumeWad.h
+++ b/Source/Core/DiscIO/VolumeWad.h
@@ -10,6 +10,7 @@
#include <vector>
#include "Common/CommonTypes.h"
+#include "Core/IOS/ES/Formats.h"
#include "DiscIO/Volume.h"
// --- this volume type is used for Wad files ---
@@ -32,7 +33,7 @@ public:
~CVolumeWAD();
bool Read(u64 offset, u64 length, u8* buffer, bool decrypt = false) const override;
bool GetTitleID(u64* buffer) const override;
- std::vector<u8> GetTMD() const override;
+ IOS::ES::TMDReader GetTMD() const override;
std::string GetGameID() const override;
std::string GetMakerID() const override;
u16 GetRevision() const override;
@@ -51,6 +52,7 @@ public:
private:
std::unique_ptr<IBlobReader> m_reader;
+ IOS::ES::TMDReader m_tmd;
u32 m_offset = 0;
u32 m_tmd_offset = 0;
u32 m_opening_bnr_offset = 0;
diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp
index ae174604cc..ef291fa237 100644
--- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp
+++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp
@@ -114,7 +114,7 @@ bool CVolumeWiiCrypted::GetTitleID(u64* buffer) const
return true;
}
-std::vector<u8> CVolumeWiiCrypted::GetTMD() const
+IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const
{
u32 tmd_size;
u32 tmd_address;
@@ -137,7 +137,7 @@ std::vector<u8> CVolumeWiiCrypted::GetTMD() const
std::vector<u8> buffer(tmd_size);
Read(m_VolumeOffset + tmd_address, tmd_size, buffer.data(), false);
- return buffer;
+ return IOS::ES::TMDReader{std::move(buffer)};
}
u64 CVolumeWiiCrypted::PartitionOffsetToRawOffset(u64 offset) const
diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h
index 7d8943ea8a..dfeb74ad66 100644
--- a/Source/Core/DiscIO/VolumeWiiCrypted.h
+++ b/Source/Core/DiscIO/VolumeWiiCrypted.h
@@ -11,6 +11,7 @@
#include <vector>
#include "Common/CommonTypes.h"
+#include "Core/IOS/ES/Formats.h"
#include "DiscIO/Volume.h"
// --- this volume type is used for encrypted Wii images ---
@@ -32,7 +33,7 @@ public:
~CVolumeWiiCrypted();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const override;
bool GetTitleID(u64* buffer) const override;
- std::vector<u8> GetTMD() const override;
+ IOS::ES::TMDReader GetTMD() const override;
u64 PartitionOffsetToRawOffset(u64 offset) const override;
std::string GetGameID() const override;
std::string GetMakerID() const override;
diff --git a/Source/Core/DiscIO/WiiWad.cpp b/Source/Core/DiscIO/WiiWad.cpp
index 9e85669204..2576dac41f 100644
--- a/Source/Core/DiscIO/WiiWad.cpp
+++ b/Source/Core/DiscIO/WiiWad.cpp
@@ -88,9 +88,9 @@ bool WiiWAD::ParseWAD(IBlobReader& reader)
u32 offset = 0x40;
m_certificate_chain = CreateWADEntry(reader, certificate_chain_size, offset);
offset += Common::AlignUp(certificate_chain_size, 0x40);
- m_ticket = CreateWADEntry(reader, ticket_size, offset);
+ m_ticket.SetBytes(CreateWADEntry(reader, ticket_size, offset));
offset += Common::AlignUp(ticket_size, 0x40);
- m_tmd = CreateWADEntry(reader, tmd_size, offset);
+ m_tmd.SetBytes(CreateWADEntry(reader, tmd_size, offset));
offset += Common::AlignUp(tmd_size, 0x40);
m_data_app = CreateWADEntry(reader, data_app_size, offset);
offset += Common::AlignUp(data_app_size, 0x40);
diff --git a/Source/Core/DiscIO/WiiWad.h b/Source/Core/DiscIO/WiiWad.h
index 21f8b746bd..46480fdaa6 100644
--- a/Source/Core/DiscIO/WiiWad.h
+++ b/Source/Core/DiscIO/WiiWad.h
@@ -8,6 +8,7 @@
#include <vector>
#include "Common/CommonTypes.h"
+#include "Core/IOS/ES/Formats.h"
namespace DiscIO
{
@@ -22,8 +23,8 @@ public:
bool IsValid() const { return m_valid; }
const std::vector<u8>& GetCertificateChain() const { return m_certificate_chain; }
- const std::vector<u8>& GetTicket() const { return m_ticket; }
- const std::vector<u8>& GetTMD() const { return m_tmd; }
+ const IOS::ES::TicketReader& GetTicket() const { return m_ticket; }
+ const IOS::ES::TMDReader& GetTMD() const { return m_tmd; }
const std::vector<u8>& GetDataApp() const { return m_data_app; }
const std::vector<u8>& GetFooter() const { return m_footer; }
private:
@@ -32,8 +33,8 @@ private:
bool m_valid;
std::vector<u8> m_certificate_chain;
- std::vector<u8> m_ticket;
- std::vector<u8> m_tmd;
+ IOS::ES::TicketReader m_ticket;
+ IOS::ES::TMDReader m_tmd;
std::vector<u8> m_data_app;
std::vector<u8> m_footer;
};