mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Use ESFormats for TMDs
We already have a TMDReader, so let's actually use it. And move ESFormats to IOS::ES, since it's definitely part of IOS. This adds a DiscIO dependency on Core which will be fixed in a follow-up PR.
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@ -146,7 +147,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);
|
||||
}
|
||||
@ -159,7 +159,7 @@ 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;
|
||||
}
|
||||
@ -176,13 +176,12 @@ bool CNANDContentLoader::Initialize(const std::string& name)
|
||||
|
||||
WiiWAD wad(name);
|
||||
std::vector<u8> data_app;
|
||||
std::vector<u8> tmd;
|
||||
|
||||
if (wad.IsValid())
|
||||
{
|
||||
m_IsWAD = true;
|
||||
m_ticket = wad.GetTicket();
|
||||
tmd = wad.GetTMD();
|
||||
m_tmd = wad.GetTMD();
|
||||
data_app = wad.GetDataApp();
|
||||
}
|
||||
else
|
||||
@ -201,94 +200,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::vector<u8> bytes(File::GetSize(tmd_filename));
|
||||
tmd_file.ReadBytes(bytes.data(), bytes.size());
|
||||
m_tmd.SetBytes(std::move(bytes));
|
||||
|
||||
m_ticket = FindSignedTicket(m_tmd.GetTitleId());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (m_Country == 2) // SYSMENU
|
||||
m_Country = GetSysMenuRegion(m_TitleVersion);
|
||||
|
||||
if (!m_IsWAD)
|
||||
m_ticket = FindSignedTicket(m_TitleID);
|
||||
|
||||
InitializeContentEntries(tmd, data_app);
|
||||
InitializeContentEntries(data_app);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& tmd,
|
||||
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;
|
||||
}
|
||||
|
||||
const std::vector<IOS::ES::Content> contents = m_tmd.GetContents();
|
||||
m_Content.resize(contents.size());
|
||||
|
||||
std::array<u8, 16> iv;
|
||||
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);
|
||||
// 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;
|
||||
|
||||
iv.fill(0);
|
||||
std::copy(&tmd[entry_offset + 0x01E8], &tmd[entry_offset + 0x01E8 + 2], iv.begin());
|
||||
|
||||
content.m_Data = std::make_unique<CNANDContentDataBuffer>(ES::AESDecode(
|
||||
m_ticket.GetTitleKey().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>(IOS::ES::AESDecode(
|
||||
title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size));
|
||||
data_app_offset += rounded_size;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
m_Content[i].m_Data = std::make_unique<CNANDContentDataFile>(filename);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
content.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()
|
||||
{
|
||||
}
|
||||
@ -327,18 +296,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'
|
||||
@ -425,7 +394,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
|
||||
|
||||
@ -440,20 +409,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))
|
||||
{
|
||||
@ -465,7 +431,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
|
||||
{
|
||||
@ -488,7 +454,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
||||
return title_id;
|
||||
}
|
||||
|
||||
bool AddTicket(const ES::TicketReader& signed_ticket)
|
||||
bool AddTicket(const IOS::ES::TicketReader& signed_ticket)
|
||||
{
|
||||
if (!signed_ticket.IsValid())
|
||||
{
|
||||
@ -508,21 +474,21 @@ bool AddTicket(const ES::TicketReader& signed_ticket)
|
||||
return ticket_file.WriteBytes(raw_ticket.data(), raw_ticket.size());
|
||||
}
|
||||
|
||||
ES::TicketReader 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 ES::TicketReader{};
|
||||
return IOS::ES::TicketReader{};
|
||||
}
|
||||
|
||||
std::vector<u8> signed_ticket(ticket_file.GetSize());
|
||||
if (!ticket_file.ReadBytes(signed_ticket.data(), signed_ticket.size()))
|
||||
{
|
||||
return ES::TicketReader{};
|
||||
return IOS::ES::TicketReader{};
|
||||
}
|
||||
|
||||
return ES::TicketReader{std::move(signed_ticket)};
|
||||
return IOS::ES::TicketReader{std::move(signed_ticket)};
|
||||
}
|
||||
} // namespace end
|
||||
|
@ -23,8 +23,8 @@ namespace DiscIO
|
||||
{
|
||||
enum class Region;
|
||||
|
||||
bool AddTicket(const ES::TicketReader& signed_ticket);
|
||||
ES::TicketReader FindSignedTicket(u64 title_id);
|
||||
bool AddTicket(const IOS::ES::TicketReader& signed_ticket);
|
||||
IOS::ES::TicketReader FindSignedTicket(u64 title_id);
|
||||
|
||||
class CNANDContentData
|
||||
{
|
||||
@ -66,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;
|
||||
};
|
||||
|
||||
@ -85,42 +79,19 @@ public:
|
||||
|
||||
bool IsValid() const { return m_Valid; }
|
||||
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 ES::TicketReader& 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,
|
||||
};
|
||||
|
||||
private:
|
||||
bool Initialize(const std::string& name);
|
||||
void InitializeContentEntries(const std::vector<u8>& tmd, 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];
|
||||
ES::TicketReader m_ticket;
|
||||
u8 m_Country;
|
||||
IOS::ES::TMDReader m_tmd;
|
||||
IOS::ES::TicketReader m_ticket;
|
||||
|
||||
std::vector<SNANDContent> m_Content;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -90,7 +90,7 @@ bool WiiWAD::ParseWAD(IBlobReader& reader)
|
||||
offset += Common::AlignUp(certificate_chain_size, 0x40);
|
||||
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);
|
||||
|
@ -23,8 +23,8 @@ public:
|
||||
|
||||
bool IsValid() const { return m_valid; }
|
||||
const std::vector<u8>& GetCertificateChain() const { return m_certificate_chain; }
|
||||
const ES::TicketReader& 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:
|
||||
@ -33,8 +33,8 @@ private:
|
||||
bool m_valid;
|
||||
|
||||
std::vector<u8> m_certificate_chain;
|
||||
ES::TicketReader 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;
|
||||
};
|
||||
|
Reference in New Issue
Block a user