diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2016-03-26 05:00:08 +0100 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2016-03-26 05:00:08 +0100 |
| commit | bd200bd19516a095205a125a599e70daf7102d25 (patch) | |
| tree | 0363dcc1a89daa60df3c9d371cee5cf09f10b1e8 /Source/Core/DiscIO/NANDContentLoader.cpp | |
| parent | 2fd08843475aaa023a7a1b8c56c7bf141b042e6c (diff) | |
| parent | 0aeac6622253ff5bc0aab3f5f48d75f0b788adb8 (diff) | |
Merge pull request #3736 from BhaaLseN/issue-9135
Rewrite NAND Content handling in ES to fix Issue 9135
Diffstat (limited to 'Source/Core/DiscIO/NANDContentLoader.cpp')
| -rw-r--r-- | Source/Core/DiscIO/NANDContentLoader.cpp | 160 |
1 files changed, 109 insertions, 51 deletions
diff --git a/Source/Core/DiscIO/NANDContentLoader.cpp b/Source/Core/DiscIO/NANDContentLoader.cpp index e2bfe425c7..b7f5deb9c1 100644 --- a/Source/Core/DiscIO/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/NANDContentLoader.cpp @@ -38,26 +38,26 @@ CSharedContent::CSharedContent() void CSharedContent::UpdateLocation() { m_Elements.clear(); - m_lastID = 0; - m_contentMap = StringFromFormat("%s/shared1/content.map", File::GetUserPath(D_WIIROOT_IDX).c_str()); + m_LastID = 0; + m_ContentMap = StringFromFormat("%s/shared1/content.map", File::GetUserPath(D_WIIROOT_IDX).c_str()); - File::IOFile pFile(m_contentMap, "rb"); + File::IOFile pFile(m_ContentMap, "rb"); SElement Element; while (pFile.ReadArray(&Element, 1)) { m_Elements.push_back(Element); - m_lastID++; + m_LastID++; } } CSharedContent::~CSharedContent() {} -std::string CSharedContent::GetFilenameFromSHA1(const u8* _pHash) +std::string CSharedContent::GetFilenameFromSHA1(const u8* hash) { for (auto& Element : m_Elements) { - if (memcmp(_pHash, Element.SHA1Hash, 20) == 0) + if (memcmp(hash, Element.SHA1Hash, 20) == 0) { return StringFromFormat("%s/shared1/%c%c%c%c%c%c%c%c.app", File::GetUserPath(D_WIIROOT_IDX).c_str(), Element.FileName[0], Element.FileName[1], Element.FileName[2], Element.FileName[3], @@ -67,39 +67,94 @@ std::string CSharedContent::GetFilenameFromSHA1(const u8* _pHash) return "unk"; } -std::string CSharedContent::AddSharedContent(const u8* _pHash) +std::string CSharedContent::AddSharedContent(const u8* hash) { - std::string filename = GetFilenameFromSHA1(_pHash); + std::string filename = GetFilenameFromSHA1(hash); if (strcasecmp(filename.c_str(), "unk") == 0) { - std::string id = StringFromFormat("%08x", m_lastID); + std::string id = StringFromFormat("%08x", m_LastID); SElement Element; memcpy(Element.FileName, id.c_str(), 8); - memcpy(Element.SHA1Hash, _pHash, 20); + memcpy(Element.SHA1Hash, hash, 20); m_Elements.push_back(Element); - File::CreateFullPath(m_contentMap); + File::CreateFullPath(m_ContentMap); - File::IOFile pFile(m_contentMap, "ab"); + File::IOFile pFile(m_ContentMap, "ab"); pFile.WriteArray(&Element, 1); filename = StringFromFormat("%s/shared1/%s.app", File::GetUserPath(D_WIIROOT_IDX).c_str(), id.c_str()); - m_lastID++; + m_LastID++; } return filename; } +void CNANDContentDataFile::EnsureOpen() +{ + if (!m_file) + m_file = std::make_unique<File::IOFile>(m_filename, "rb"); + else if (!m_file->IsOpen()) + m_file->Open(m_filename, "rb"); +} +void CNANDContentDataFile::Open() +{ + EnsureOpen(); +} +const std::vector<u8> CNANDContentDataFile::Get() +{ + std::vector<u8> result; + EnsureOpen(); + if (!m_file->IsGood()) + return result; + + u64 size = m_file->GetSize(); + if (size == 0) + return result; + + result.resize(size); + m_file->ReadBytes(result.data(), result.size()); + + return result; +} + +bool CNANDContentDataFile::GetRange(u32 start, u32 size, u8* buffer) +{ + EnsureOpen(); + if (!m_file->IsGood()) + return false; + + if (!m_file->Seek(start, SEEK_SET)) + return false; -CNANDContentLoader::CNANDContentLoader(const std::string& name) + return m_file->ReadBytes(buffer, static_cast<size_t>(size)); +} +void CNANDContentDataFile::Close() +{ + if (m_file && m_file->IsOpen()) + m_file->Close(); +} + + +bool CNANDContentDataBuffer::GetRange(u32 start, u32 size, u8* buffer) +{ + if (start + size > m_buffer.size()) + return false; + + std::copy(&m_buffer[start], &m_buffer[start + size], buffer); + return true; +} + + +CNANDContentLoader::CNANDContentLoader(const std::string& content_name) : m_Valid(false) - , m_isWAD(false) + , m_IsWAD(false) , m_TitleID(-1) , m_IosVersion(0x09) , m_BootIndex(-1) { - m_Valid = Initialize(name); + m_Valid = Initialize(content_name); } CNANDContentLoader::~CNANDContentLoader() @@ -132,9 +187,9 @@ bool CNANDContentLoader::Initialize(const std::string& name) if (wad.IsValid()) { - m_isWAD = true; - m_ticket = wad.GetTicket(); - decrypted_title_key = GetKeyFromTicket(m_ticket); + m_IsWAD = true; + m_Ticket = wad.GetTicket(); + decrypted_title_key = GetKeyFromTicket(m_Ticket); tmd = wad.GetTMD(); data_app = wad.GetDataApp(); } @@ -162,7 +217,7 @@ bool CNANDContentLoader::Initialize(const std::string& name) std::copy(&tmd[0x180], &tmd[0x180 + TMD_VIEW_SIZE], m_TMDView); m_TitleVersion = Common::swap16(&tmd[0x01DC]); - m_numEntries = Common::swap16(&tmd[0x01DE]); + m_NumEntries = Common::swap16(&tmd[0x01DE]); m_BootIndex = Common::swap16(&tmd[0x01E0]); m_TitleID = Common::swap64(&tmd[0x018C]); m_IosVersion = Common::swap16(&tmd[0x018A]); @@ -177,12 +232,12 @@ bool CNANDContentLoader::Initialize(const std::string& name) void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& tmd, const std::vector<u8>& decrypted_title_key, const std::vector<u8>& data_app) { - m_Content.resize(m_numEntries); + m_Content.resize(m_NumEntries); std::array<u8, 16> iv; u32 data_app_offset = 0; - for (u32 i = 0; i < m_numEntries; i++) + for (u32 i = 0; i < m_NumEntries; i++) { const u32 entry_offset = 0x24 * i; @@ -200,27 +255,30 @@ void CNANDContentLoader::InitializeContentEntries(const std::vector<u8>& tmd, co const auto hash_end = std::next(hash_begin, ArraySize(content.m_SHA1Hash)); std::copy(hash_begin, hash_end, content.m_SHA1Hash); - if (m_isWAD) + if (m_IsWAD) { u32 rounded_size = ROUND_UP(content.m_Size, 0x40); iv.fill(0); std::copy(&tmd[entry_offset + 0x01E8], &tmd[entry_offset + 0x01E8 + 2], iv.begin()); - content.m_data = AESDecode(decrypted_title_key.data(), iv.data(), &data_app[data_app_offset], rounded_size); + content.m_Data = std::make_unique<CNANDContentDataBuffer>(AESDecode(decrypted_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 - content.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(content.m_SHA1Hash); + filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(content.m_SHA1Hash); else - content.m_Filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), content.m_ContentID); + 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(content.m_Filename)) - content.m_Size = static_cast<u32>(File::GetSize(content.m_Filename)); + if (File::Exists(filename)) + content.m_Size = static_cast<u32>(File::GetSize(filename)); } } @@ -292,7 +350,7 @@ void CNANDContentLoader::RemoveTitle() const if (IsValid()) { // remove TMD? - for (u32 i = 0; i < m_numEntries; i++) + for (u32 i = 0; i < m_NumEntries; i++) { if (!(m_Content[i].m_Type & 0x8000)) // skip shared apps { @@ -313,14 +371,14 @@ cUIDsys::cUIDsys() void cUIDsys::UpdateLocation() { m_Elements.clear(); - m_lastUID = 0x00001000; - m_uidSys = File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/sys/uid.sys"; + m_LastUID = 0x00001000; + m_UidSys = File::GetUserPath(D_SESSION_WIIROOT_IDX) + "/sys/uid.sys"; - File::IOFile pFile(m_uidSys, "rb"); + File::IOFile pFile(m_UidSys, "rb"); SElement Element; while (pFile.ReadArray(&Element, 1)) { - *(u32*)&(Element.UID) = Common::swap32(m_lastUID++); + *(u32*)&(Element.UID) = Common::swap32(m_LastUID++); m_Elements.push_back(Element); } pFile.Close(); @@ -328,23 +386,23 @@ void cUIDsys::UpdateLocation() if (m_Elements.empty()) { *(u64*)&(Element.titleID) = Common::swap64(TITLEID_SYSMENU); - *(u32*)&(Element.UID) = Common::swap32(m_lastUID++); + *(u32*)&(Element.UID) = Common::swap32(m_LastUID++); - File::CreateFullPath(m_uidSys); - pFile.Open(m_uidSys, "wb"); + 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()); + ERROR_LOG(DISCIO, "Failed to write to %s", m_UidSys.c_str()); } } cUIDsys::~cUIDsys() {} -u32 cUIDsys::GetUIDFromTitle(u64 _Title) +u32 cUIDsys::GetUIDFromTitle(u64 title_id) { for (auto& Element : m_Elements) { - if (Common::swap64(_Title) == *(u64*)&(Element.titleID)) + if (Common::swap64(title_id) == *(u64*)&(Element.titleID)) { return Common::swap32(Element.UID); } @@ -352,33 +410,33 @@ u32 cUIDsys::GetUIDFromTitle(u64 _Title) return 0; } -void cUIDsys::AddTitle(u64 _TitleID) +void cUIDsys::AddTitle(u64 title_id) { - if (GetUIDFromTitle(_TitleID)) + if (GetUIDFromTitle(title_id)) { - INFO_LOG(DISCIO, "Title %08x%08x, already exists in uid.sys", (u32)(_TitleID >> 32), (u32)_TitleID); + 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(_TitleID); - *(u32*)&(Element.UID) = Common::swap32(m_lastUID++); + *(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"); + 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>& _TitleIDs, bool _owned) +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))) - _TitleIDs.push_back(Common::swap64(Element.titleID)); + 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)); } } @@ -429,7 +487,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename) return 0; } - app_file.WriteBytes(content.m_data.data(), content.m_Size); + app_file.WriteBytes(content.m_Data->Get().data(), content.m_Size); } else { |
