IOS/ES: Move shared content map, uid.sys code
These are all specific to ES and belong there. The SharedContentMap and UIDSys classes were also modernised.
This commit is contained in:
parent
0b6170cc33
commit
7b17163a7a
|
@ -494,7 +494,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
|
||||||
if (!tmd_file.WriteBytes(tmd_bytes.data(), tmd_bytes.size()))
|
if (!tmd_file.WriteBytes(tmd_bytes.data(), tmd_bytes.size()))
|
||||||
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
|
ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND.");
|
||||||
}
|
}
|
||||||
DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
||||||
uid_sys.AddTitle(tmd.GetTitleId());
|
uid_sys.AddTitle(tmd.GetTitleId());
|
||||||
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
|
// DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager.
|
||||||
// clear the cache to avoid content access mismatches.
|
// clear the cache to avoid content access mismatches.
|
||||||
|
|
|
@ -13,9 +13,12 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Common/Assert.h"
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Crypto/AES.h"
|
#include "Common/Crypto/AES.h"
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
#include "Core/ec_wii.h"
|
#include "Core/ec_wii.h"
|
||||||
|
@ -345,5 +348,132 @@ s32 TicketReader::Unpersonalise()
|
||||||
std::copy(key.cbegin(), key.cend(), ticket_begin + offsetof(Ticket, title_key));
|
std::copy(key.cbegin(), key.cend(), ticket_begin + offsetof(Ticket, title_key));
|
||||||
return IOSC_OK;
|
return IOSC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SharedContentMap::Entry
|
||||||
|
{
|
||||||
|
// ID string
|
||||||
|
std::array<u8, 8> id;
|
||||||
|
// Binary SHA1 hash
|
||||||
|
std::array<u8, 20> sha1;
|
||||||
|
};
|
||||||
|
|
||||||
|
SharedContentMap::SharedContentMap(Common::FromWhichRoot root) : m_root(root)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Entry) == 28, "SharedContentMap::Entry has the wrong size");
|
||||||
|
|
||||||
|
m_file_path = Common::RootUserPath(root) + "/shared1/content.map";
|
||||||
|
|
||||||
|
File::IOFile file(m_file_path, "rb");
|
||||||
|
Entry entry;
|
||||||
|
while (file.ReadArray(&entry, 1))
|
||||||
|
{
|
||||||
|
m_entries.push_back(entry);
|
||||||
|
m_last_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedContentMap::~SharedContentMap() = default;
|
||||||
|
|
||||||
|
std::string SharedContentMap::GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const
|
||||||
|
{
|
||||||
|
const auto it = std::find_if(m_entries.begin(), m_entries.end(),
|
||||||
|
[&sha1](const auto& entry) { return entry.sha1 == sha1; });
|
||||||
|
if (it == m_entries.end())
|
||||||
|
return "unk";
|
||||||
|
|
||||||
|
const std::string id_string(it->id.begin(), it->id.end());
|
||||||
|
return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
|
||||||
|
{
|
||||||
|
std::string filename = GetFilenameFromSHA1(sha1);
|
||||||
|
if (filename != "unk")
|
||||||
|
return filename;
|
||||||
|
|
||||||
|
const std::string id = StringFromFormat("%08x", m_last_id);
|
||||||
|
Entry entry;
|
||||||
|
std::copy(id.cbegin(), id.cend(), entry.id.begin());
|
||||||
|
entry.sha1 = sha1;
|
||||||
|
m_entries.push_back(entry);
|
||||||
|
|
||||||
|
File::CreateFullPath(m_file_path);
|
||||||
|
|
||||||
|
File::IOFile file(m_file_path, "ab");
|
||||||
|
file.WriteArray(&entry, 1);
|
||||||
|
|
||||||
|
filename = Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id.c_str());
|
||||||
|
m_last_id++;
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::pair<u32, u64> ReadUidSysEntry(File::IOFile& file)
|
||||||
|
{
|
||||||
|
u64 title_id = 0;
|
||||||
|
if (!file.ReadBytes(&title_id, sizeof(title_id)))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
u32 uid = 0;
|
||||||
|
if (!file.ReadBytes(&uid, sizeof(uid)))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return {Common::swap32(uid), Common::swap64(title_id)};
|
||||||
|
}
|
||||||
|
|
||||||
|
UIDSys::UIDSys(Common::FromWhichRoot root)
|
||||||
|
{
|
||||||
|
m_file_path = Common::RootUserPath(root) + "/sys/uid.sys";
|
||||||
|
|
||||||
|
File::IOFile file(m_file_path, "rb");
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const std::pair<u32, u64> entry = ReadUidSysEntry(file);
|
||||||
|
if (!entry.first && !entry.second)
|
||||||
|
break;
|
||||||
|
|
||||||
|
m_entries.insert(std::move(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_entries.empty())
|
||||||
|
{
|
||||||
|
AddTitle(TITLEID_SYSMENU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 UIDSys::GetUIDFromTitle(u64 title_id)
|
||||||
|
{
|
||||||
|
const auto it = std::find_if(m_entries.begin(), m_entries.end(),
|
||||||
|
[title_id](const auto& entry) { return entry.second == title_id; });
|
||||||
|
return (it == m_entries.end()) ? 0 : it->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 UIDSys::GetNextUID() const
|
||||||
|
{
|
||||||
|
if (m_entries.empty())
|
||||||
|
return 0x00001000;
|
||||||
|
return m_entries.rbegin()->first + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UIDSys::AddTitle(u64 title_id)
|
||||||
|
{
|
||||||
|
if (GetUIDFromTitle(title_id))
|
||||||
|
{
|
||||||
|
INFO_LOG(IOS_ES, "Title %016" PRIx64 " already exists in uid.sys", title_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 uid = GetNextUID();
|
||||||
|
m_entries.insert({uid, title_id});
|
||||||
|
|
||||||
|
// Byte swap before writing.
|
||||||
|
title_id = Common::swap64(title_id);
|
||||||
|
uid = Common::swap32(uid);
|
||||||
|
|
||||||
|
File::CreateFullPath(m_file_path);
|
||||||
|
File::IOFile file(m_file_path, "ab");
|
||||||
|
|
||||||
|
if (!file.WriteBytes(&title_id, sizeof(title_id)) || !file.WriteBytes(&uid, sizeof(uid)))
|
||||||
|
ERROR_LOG(IOS_ES, "Failed to write to /sys/uid.sys");
|
||||||
|
}
|
||||||
} // namespace ES
|
} // namespace ES
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/NandPaths.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
|
|
||||||
namespace IOS
|
namespace IOS
|
||||||
|
@ -194,5 +195,36 @@ public:
|
||||||
private:
|
private:
|
||||||
std::vector<u8> m_bytes;
|
std::vector<u8> m_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SharedContentMap final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SharedContentMap(Common::FromWhichRoot root);
|
||||||
|
~SharedContentMap();
|
||||||
|
|
||||||
|
std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
|
||||||
|
std::string AddSharedContent(const std::array<u8, 20>& sha1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Entry;
|
||||||
|
Common::FromWhichRoot m_root;
|
||||||
|
u32 m_last_id = 0;
|
||||||
|
std::string m_file_path;
|
||||||
|
std::vector<Entry> m_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UIDSys final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit UIDSys(Common::FromWhichRoot root);
|
||||||
|
|
||||||
|
u32 GetUIDFromTitle(u64 title_id);
|
||||||
|
void AddTitle(u64 title_id);
|
||||||
|
u32 GetNextUID() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_file_path;
|
||||||
|
std::map<u32, u64> m_entries;
|
||||||
|
};
|
||||||
} // namespace ES
|
} // namespace ES
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Core/IOS/ES/Formats.h"
|
#include "Core/IOS/ES/Formats.h"
|
||||||
#include "Core/IOS/ES/NandUtils.h"
|
#include "Core/IOS/ES/NandUtils.h"
|
||||||
#include "DiscIO/NANDContentLoader.h"
|
|
||||||
|
|
||||||
namespace IOS
|
namespace IOS
|
||||||
{
|
{
|
||||||
|
@ -142,7 +141,7 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
|
||||||
if (!tmd.IsValid())
|
if (!tmd.IsValid())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const DiscIO::CSharedContent shared{Common::FROM_SESSION_ROOT};
|
const IOS::ES::SharedContentMap shared{Common::FROM_SESSION_ROOT};
|
||||||
const std::vector<Content> contents = tmd.GetContents();
|
const std::vector<Content> contents = tmd.GetContents();
|
||||||
|
|
||||||
std::vector<Content> stored_contents;
|
std::vector<Content> stored_contents;
|
||||||
|
@ -151,7 +150,7 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
|
||||||
[&tmd, &shared](const auto& content) {
|
[&tmd, &shared](const auto& content) {
|
||||||
if (content.IsShared())
|
if (content.IsShared())
|
||||||
{
|
{
|
||||||
const std::string path = shared.GetFilenameFromSHA1(content.sha1.data());
|
const std::string path = shared.GetFilenameFromSHA1(content.sha1);
|
||||||
return path != "unk" && File::Exists(path);
|
return path != "unk" && File::Exists(path);
|
||||||
}
|
}
|
||||||
return File::Exists(
|
return File::Exists(
|
||||||
|
|
|
@ -102,7 +102,7 @@ IPCCommandResult ES::AddTMD(const IOCtlVRequest& request)
|
||||||
if (!m_addtitle_tmd.IsValid())
|
if (!m_addtitle_tmd.IsValid())
|
||||||
return GetDefaultReply(ES_INVALID_TMD);
|
return GetDefaultReply(ES_INVALID_TMD);
|
||||||
|
|
||||||
DiscIO::cUIDsys uid_sys{Common::FROM_CONFIGURED_ROOT};
|
IOS::ES::UIDSys uid_sys{Common::FROM_CONFIGURED_ROOT};
|
||||||
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
|
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
|
||||||
|
|
||||||
return GetDefaultReply(IPC_SUCCESS);
|
return GetDefaultReply(IPC_SUCCESS);
|
||||||
|
@ -124,7 +124,7 @@ IPCCommandResult ES::AddTitleStart(const IOCtlVRequest& request)
|
||||||
return GetDefaultReply(ES_INVALID_TMD);
|
return GetDefaultReply(ES_INVALID_TMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
DiscIO::cUIDsys uid_sys{Common::FROM_CONFIGURED_ROOT};
|
IOS::ES::UIDSys uid_sys{Common::FROM_CONFIGURED_ROOT};
|
||||||
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
|
uid_sys.AddTitle(m_addtitle_tmd.GetTitleId());
|
||||||
|
|
||||||
// TODO: check and use the other vectors.
|
// TODO: check and use the other vectors.
|
||||||
|
@ -281,8 +281,8 @@ IPCCommandResult ES::AddTitleFinish(const IOCtlVRequest& request)
|
||||||
std::string content_path;
|
std::string content_path;
|
||||||
if (content_info.IsShared())
|
if (content_info.IsShared())
|
||||||
{
|
{
|
||||||
DiscIO::CSharedContent shared_content{Common::FROM_SESSION_ROOT};
|
IOS::ES::SharedContentMap shared_content{Common::FROM_SESSION_ROOT};
|
||||||
content_path = shared_content.AddSharedContent(content_info.sha1.data());
|
content_path = shared_content.AddSharedContent(content_info.sha1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "Common/NandPaths.h"
|
#include "Common/NandPaths.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/Swap.h"
|
#include "Common/Swap.h"
|
||||||
|
// TODO: kill this dependency.
|
||||||
|
#include "Core/IOS/ES/Formats.h"
|
||||||
|
|
||||||
#include "DiscIO/WiiWad.h"
|
#include "DiscIO/WiiWad.h"
|
||||||
|
|
||||||
|
@ -32,61 +34,6 @@ namespace DiscIO
|
||||||
{
|
{
|
||||||
CNANDContentData::~CNANDContentData() = default;
|
CNANDContentData::~CNANDContentData() = default;
|
||||||
|
|
||||||
CSharedContent::CSharedContent(Common::FromWhichRoot root) : m_root(root)
|
|
||||||
{
|
|
||||||
m_Elements.clear();
|
|
||||||
m_LastID = 0;
|
|
||||||
m_ContentMap = Common::RootUserPath(root) + "/shared1/content.map";
|
|
||||||
|
|
||||||
File::IOFile pFile(m_ContentMap, "rb");
|
|
||||||
SElement Element;
|
|
||||||
while (pFile.ReadArray(&Element, 1))
|
|
||||||
{
|
|
||||||
m_Elements.push_back(Element);
|
|
||||||
m_LastID++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSharedContent::GetFilenameFromSHA1(const u8* hash) const
|
|
||||||
{
|
|
||||||
for (const auto& Element : m_Elements)
|
|
||||||
{
|
|
||||||
if (memcmp(hash, Element.SHA1Hash, 20) == 0)
|
|
||||||
{
|
|
||||||
return StringFromFormat(
|
|
||||||
"%s/shared1/%c%c%c%c%c%c%c%c.app", Common::RootUserPath(m_root).c_str(),
|
|
||||||
Element.FileName[0], Element.FileName[1], Element.FileName[2], Element.FileName[3],
|
|
||||||
Element.FileName[4], Element.FileName[5], Element.FileName[6], Element.FileName[7]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "unk";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CSharedContent::AddSharedContent(const u8* hash)
|
|
||||||
{
|
|
||||||
std::string filename = GetFilenameFromSHA1(hash);
|
|
||||||
|
|
||||||
if (strcasecmp(filename.c_str(), "unk") == 0)
|
|
||||||
{
|
|
||||||
std::string id = StringFromFormat("%08x", m_LastID);
|
|
||||||
SElement Element;
|
|
||||||
memcpy(Element.FileName, id.c_str(), 8);
|
|
||||||
memcpy(Element.SHA1Hash, hash, 20);
|
|
||||||
m_Elements.push_back(Element);
|
|
||||||
|
|
||||||
File::CreateFullPath(m_ContentMap);
|
|
||||||
|
|
||||||
File::IOFile pFile(m_ContentMap, "ab");
|
|
||||||
pFile.WriteArray(&Element, 1);
|
|
||||||
|
|
||||||
filename =
|
|
||||||
StringFromFormat("%s/shared1/%s.app", Common::RootUserPath(m_root).c_str(), id.c_str());
|
|
||||||
m_LastID++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
CNANDContentDataFile::CNANDContentDataFile(const std::string& filename) : m_filename{filename}
|
CNANDContentDataFile::CNANDContentDataFile(const std::string& filename) : m_filename{filename}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -238,7 +185,7 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& data_ap
|
||||||
|
|
||||||
u32 data_app_offset = 0;
|
u32 data_app_offset = 0;
|
||||||
const std::vector<u8> title_key = m_ticket.GetTitleKey();
|
const std::vector<u8> title_key = m_ticket.GetTitleKey();
|
||||||
CSharedContent shared_content{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
IOS::ES::SharedContentMap shared_content{Common::FromWhichRoot::FROM_SESSION_ROOT};
|
||||||
|
|
||||||
for (size_t i = 0; i < contents.size(); ++i)
|
for (size_t i = 0; i < contents.size(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -261,7 +208,7 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& data_ap
|
||||||
{
|
{
|
||||||
std::string filename;
|
std::string filename;
|
||||||
if (content.IsShared())
|
if (content.IsShared())
|
||||||
filename = shared_content.GetFilenameFromSHA1(content.sha1.data());
|
filename = shared_content.GetFilenameFromSHA1(content.sha1);
|
||||||
else
|
else
|
||||||
filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.id);
|
filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.id);
|
||||||
|
|
||||||
|
@ -328,78 +275,6 @@ void CNANDContentLoader::RemoveTitle() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cUIDsys::cUIDsys(Common::FromWhichRoot root)
|
|
||||||
{
|
|
||||||
m_Elements.clear();
|
|
||||||
m_LastUID = 0x00001000;
|
|
||||||
m_UidSys = Common::RootUserPath(root) + "/sys/uid.sys";
|
|
||||||
|
|
||||||
File::IOFile pFile(m_UidSys, "rb");
|
|
||||||
SElement Element;
|
|
||||||
while (pFile.ReadArray(&Element, 1))
|
|
||||||
{
|
|
||||||
*(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
|
|
||||||
m_Elements.push_back(Element);
|
|
||||||
}
|
|
||||||
pFile.Close();
|
|
||||||
|
|
||||||
if (m_Elements.empty())
|
|
||||||
{
|
|
||||||
*(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU);
|
|
||||||
*(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
|
|
||||||
|
|
||||||
File::CreateFullPath(m_UidSys);
|
|
||||||
pFile.Open(m_UidSys, "wb");
|
|
||||||
if (!pFile.WriteArray(&Element, 1))
|
|
||||||
ERROR_LOG(DISCIO, "Failed to write to %s", m_UidSys.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 cUIDsys::GetUIDFromTitle(u64 title_id)
|
|
||||||
{
|
|
||||||
for (auto& Element : m_Elements)
|
|
||||||
{
|
|
||||||
if (Common::swap64(title_id) == *(u64*)&(Element.titleID))
|
|
||||||
{
|
|
||||||
return Common::swap32(Element.UID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cUIDsys::AddTitle(u64 title_id)
|
|
||||||
{
|
|
||||||
if (GetUIDFromTitle(title_id))
|
|
||||||
{
|
|
||||||
INFO_LOG(DISCIO, "Title %08x%08x, already exists in uid.sys", (u32)(title_id >> 32),
|
|
||||||
(u32)title_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SElement Element;
|
|
||||||
*(u64*)&(Element.titleID) = Common::swap64(title_id);
|
|
||||||
*(u32*)&(Element.UID) = Common::swap32(m_LastUID++);
|
|
||||||
m_Elements.push_back(Element);
|
|
||||||
|
|
||||||
File::CreateFullPath(m_UidSys);
|
|
||||||
File::IOFile pFile(m_UidSys, "ab");
|
|
||||||
|
|
||||||
if (!pFile.WriteArray(&Element, 1))
|
|
||||||
ERROR_LOG(DISCIO, "fwrite failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void cUIDsys::GetTitleIDs(std::vector<u64>& title_ids, bool owned)
|
|
||||||
{
|
|
||||||
for (auto& Element : m_Elements)
|
|
||||||
{
|
|
||||||
if ((owned &&
|
|
||||||
Common::CheckTitleTIK(Common::swap64(Element.titleID), Common::FROM_SESSION_ROOT)) ||
|
|
||||||
(!owned &&
|
|
||||||
Common::CheckTitleTMD(Common::swap64(Element.titleID), Common::FROM_SESSION_ROOT)))
|
|
||||||
title_ids.push_back(Common::swap64(Element.titleID));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
||||||
{
|
{
|
||||||
if (filename.find(".wad") == std::string::npos)
|
if (filename.find(".wad") == std::string::npos)
|
||||||
|
@ -426,12 +301,12 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
||||||
const auto& raw_tmd = content_loader.GetTMD().GetRawTMD();
|
const auto& raw_tmd = content_loader.GetTMD().GetRawTMD();
|
||||||
tmd_file.WriteBytes(raw_tmd.data(), raw_tmd.size());
|
tmd_file.WriteBytes(raw_tmd.data(), raw_tmd.size());
|
||||||
|
|
||||||
CSharedContent shared_content{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
IOS::ES::SharedContentMap shared_content{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
||||||
for (const auto& content : content_loader.GetContent())
|
for (const auto& content : content_loader.GetContent())
|
||||||
{
|
{
|
||||||
std::string app_filename;
|
std::string app_filename;
|
||||||
if (content.m_metadata.IsShared())
|
if (content.m_metadata.IsShared())
|
||||||
app_filename = shared_content.AddSharedContent(content.m_metadata.sha1.data());
|
app_filename = shared_content.AddSharedContent(content.m_metadata.sha1);
|
||||||
else
|
else
|
||||||
app_filename = StringFromFormat("%s%08x.app", content_path.c_str(), content.m_metadata.id);
|
app_filename = StringFromFormat("%s%08x.app", content_path.c_str(), content.m_metadata.id);
|
||||||
|
|
||||||
|
@ -460,7 +335,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cUIDsys uid_sys{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
|
||||||
uid_sys.AddTitle(title_id);
|
uid_sys.AddTitle(title_id);
|
||||||
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
|
|
|
@ -123,50 +123,4 @@ private:
|
||||||
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<CNANDContentLoader>> m_map;
|
std::unordered_map<std::string, std::unique_ptr<CNANDContentLoader>> m_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CSharedContent final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit CSharedContent(Common::FromWhichRoot root);
|
|
||||||
|
|
||||||
std::string GetFilenameFromSHA1(const u8* hash) const;
|
|
||||||
std::string AddSharedContent(const u8* hash);
|
|
||||||
|
|
||||||
private:
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct SElement
|
|
||||||
{
|
|
||||||
u8 FileName[8];
|
|
||||||
u8 SHA1Hash[20];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
Common::FromWhichRoot m_root;
|
|
||||||
u32 m_LastID;
|
|
||||||
std::string m_ContentMap;
|
|
||||||
std::vector<SElement> m_Elements;
|
|
||||||
};
|
|
||||||
|
|
||||||
class cUIDsys final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit cUIDsys(Common::FromWhichRoot root);
|
|
||||||
|
|
||||||
u32 GetUIDFromTitle(u64 title_id);
|
|
||||||
void AddTitle(u64 title_id);
|
|
||||||
void GetTitleIDs(std::vector<u64>& title_ids, bool owned = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct SElement
|
|
||||||
{
|
|
||||||
u8 titleID[8];
|
|
||||||
u8 UID[4];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
u32 m_LastUID;
|
|
||||||
std::string m_UidSys;
|
|
||||||
std::vector<SElement> m_Elements;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue