diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp index 00bca2eb97..2d27231426 100644 --- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp @@ -101,15 +101,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename) WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename); - std::unique_ptr pDolLoader; - if (pContent->m_data.empty()) - { - pDolLoader = std::make_unique(pContent->m_Filename); - } - else - { - pDolLoader = std::make_unique(pContent->m_data); - } + std::unique_ptr pDolLoader = std::make_unique(pContent->m_Data->Get()); if (!pDolLoader->IsValid()) return false; diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp index eba6971550..da601455c4 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -64,7 +64,6 @@ std::string CWII_IPC_HLE_Device_es::m_ContentFile; CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) - , m_pContentLoader(nullptr) , m_TitleID(-1) , m_AccessIdentID(0x6000000) { @@ -99,12 +98,12 @@ void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile) void CWII_IPC_HLE_Device_es::OpenInternal() { - m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); + auto& contentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); // check for cd ... - if (m_pContentLoader->IsValid()) + if (contentLoader.IsValid()) { - m_TitleID = m_pContentLoader->GetTitleID(); + m_TitleID = contentLoader.GetTitleID(); m_TitleIDs.clear(); DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDs); @@ -164,7 +163,7 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p) SContentAccess& Access = pair.second; Position = Access.m_Position; TitleID = Access.m_TitleID; - Index = Access.m_pContent->m_Index; + Index = Access.m_Index; p.Do(CFD); p.Do(Position); p.Do(TitleID); @@ -186,14 +185,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce) { - // Leave deletion of the CNANDContentLoader objects to CNANDContentManager, don't do it here! - m_NANDContent.clear(); - for (auto& pair : m_ContentAccessMap) - { - delete pair.second.m_pFile; - } m_ContentAccessMap.clear(); - m_pContentLoader = nullptr; m_TitleIDs.clear(); m_TitleID = -1; m_AccessIdentID = 0x6000000; @@ -202,6 +194,8 @@ IPCCommandResult CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce if (!_bForce) Memory::Write_U32(0, _CommandAddress + 4); m_Active = false; + // clear the NAND content cache to make sure nothing remains open. + DiscIO::CNANDContentManager::Access().ClearCache(); return GetDefaultReply(); } @@ -224,22 +218,11 @@ u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) SContentAccess Access; Access.m_Position = 0; - Access.m_pContent = pContent; + Access.m_Index = pContent->m_Index; + Access.m_Size = pContent->m_Size; Access.m_TitleID = TitleID; - Access.m_pFile = nullptr; - if (pContent->m_data.empty()) - { - std::string Filename = pContent->m_Filename; - INFO_LOG(WII_IPC_ES, "ES: load %s", Filename.c_str()); - - Access.m_pFile = new File::IOFile(Filename, "rb"); - if (!Access.m_pFile->IsGood()) - { - WARN_LOG(WII_IPC_ES, "ES: couldn't load %s", Filename.c_str()); - return 0xffffffff; - } - } + pContent->m_Data->Open(); m_ContentAccessMap[CFD] = Access; return CFD; @@ -323,21 +306,21 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - const DiscIO::CNANDContentLoader& rNANDCOntent = AccessContentDevice(TitleID); - if (rNANDCOntent.IsValid()) // Not sure if dolphin will ever fail this check + const DiscIO::CNANDContentLoader& rNANDContent = AccessContentDevice(TitleID); + if (rNANDContent.IsValid()) // Not sure if dolphin will ever fail this check { - for (u16 i = 0; i < rNANDCOntent.GetNumEntries(); i++) + for (u16 i = 0; i < rNANDContent.GetNumEntries(); i++) { - Memory::Write_U32(rNANDCOntent.GetContentByIndex(i)->m_ContentID, Buffer.PayloadBuffer[0].m_Address + i*4); - INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i, rNANDCOntent.GetContentByIndex(i)->m_ContentID); + Memory::Write_U32(rNANDContent.GetContentByIndex(i)->m_ContentID, Buffer.PayloadBuffer[0].m_Address + i*4); + INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Index %d: %08x", i, rNANDContent.GetContentByIndex(i)->m_ContentID); } Memory::Write_U32(0, _CommandAddress + 0x4); } else { - Memory::Write_U32((u32)rNANDCOntent.GetContentSize(), _CommandAddress + 0x4); + Memory::Write_U32((u32)rNANDContent.GetContentSize(), _CommandAddress + 0x4); INFO_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECONTENTS: Unable to open content %zu", - rNANDCOntent.GetContentSize()); + rNANDContent.GetContentSize()); } return GetDefaultReply(); @@ -395,32 +378,22 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u8* pDest = Memory::GetPointer(Addr); - if (rContent.m_Position + Size > rContent.m_pContent->m_Size) + if (rContent.m_Position + Size > rContent.m_Size) { - Size = rContent.m_pContent->m_Size-rContent.m_Position; + Size = rContent.m_Size - rContent.m_Position; } if (Size > 0) { if (pDest) { - if (rContent.m_pContent->m_data.empty()) + const DiscIO::CNANDContentLoader& ContentLoader = AccessContentDevice(rContent.m_TitleID); + // ContentLoader should never be invalid; rContent has been created by it. + if (ContentLoader.IsValid()) { - auto& pFile = rContent.m_pFile; - if (!pFile->Seek(rContent.m_Position, SEEK_SET)) - { - ERROR_LOG(WII_IPC_ES, "ES: couldn't seek!"); - } - WARN_LOG(WII_IPC_ES, "2 %p", pFile->GetHandle()); - if (!pFile->ReadBytes(pDest, Size)) - { - ERROR_LOG(WII_IPC_ES, "ES: short read; returning uninitialized data!"); - } - } - else - { - const u8* src = &rContent.m_pContent->m_data[rContent.m_Position]; - memcpy(pDest, src, Size); + const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(rContent.m_Index); + if (!pContent->m_Data->GetRange(rContent.m_Position, Size, pDest)) + ERROR_LOG(WII_IPC_ES, "ES: failed to read %u bytes from %u!", Size, rContent.m_Position); } rContent.m_Position += Size; @@ -431,7 +404,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) } } - INFO_LOG(WII_IPC_ES, "IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", CFD, Addr, Size, rContent.m_Position, rContent.m_pContent->m_Index); + INFO_LOG(WII_IPC_ES, "IOCTL_ES_READCONTENT: CFD %x, Address 0x%x, Size %i -> stream pos %i (Index %i)", CFD, Addr, Size, rContent.m_Position, rContent.m_Index); Memory::Write_U32(Size, _CommandAddress + 0x4); return GetDefaultReply(); @@ -454,7 +427,14 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) return GetDefaultReply(); } - delete itr->second.m_pFile; + const DiscIO::CNANDContentLoader& ContentLoader = AccessContentDevice(itr->second.m_TitleID); + // ContentLoader should never be invalid; we shouldn't be here if ES_OPENCONTENT failed before. + if (ContentLoader.IsValid()) + { + const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(itr->second.m_Index); + pContent->m_Data->Close(); + } + m_ContentAccessMap.erase(itr); Memory::Write_U32(0, _CommandAddress + 0x4); @@ -490,7 +470,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) break; case 2: // END - rContent.m_Position = rContent.m_pContent->m_Size + Addr; + rContent.m_Position = rContent.m_Size + Addr; break; } @@ -906,6 +886,11 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16); u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24); + // ES_LAUNCH should probably reset thw whole state, which at least means closing all open files. + // leaving them open through ES_LAUNCH may cause hangs and other funky behavior + // (supposedly when trying to re-open those files). + DiscIO::CNANDContentManager::Access().ClearCache(); + std::string tContentFile; if ((u32)(TitleID>>32) != 0x00000001 || TitleID == TITLEID_SYSMENU) { @@ -917,15 +902,7 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) if (pContent) { tContentFile = Common::GetTitleContentPath(TitleID, Common::FROM_SESSION_ROOT); - std::unique_ptr pDolLoader; - if (pContent->m_data.empty()) - { - pDolLoader = std::make_unique(pContent->m_Filename); - } - else - { - pDolLoader = std::make_unique(pContent->m_data); - } + std::unique_ptr pDolLoader = std::make_unique(pContent->m_Data->Get()); if (pDolLoader->IsValid()) { @@ -1077,31 +1054,17 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) return GetDefaultReply(); } -// TODO: This cache is redundant with the one in CNANDContentManager.h -const DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID) +const DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 title_id) { - if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) - return *m_pContentLoader; + // for WADs, the passed title id and the stored title id match; along with m_ContentFile being set to the + // actual WAD file name. We cannot simply get a NAND Loader for the title id in those cases, since the WAD + // need not be installed in the NAND, but it could be opened directly from a WAD file anywhere on disk. + if (m_TitleID == title_id && !m_ContentFile.empty()) + return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); - CTitleToContentMap::iterator itr = m_NANDContent.find(_TitleID); - if (itr != m_NANDContent.end()) - return *itr->second; - - m_NANDContent[_TitleID] = &DiscIO::CNANDContentManager::Access().GetNANDLoader(_TitleID, Common::FROM_SESSION_ROOT); - - _dbg_assert_msg_(WII_IPC_ES, ((u32)(_TitleID >> 32) == 0x00010000) || m_NANDContent[_TitleID]->IsValid(), "NandContent not valid for TitleID %08x/%08x", (u32)(_TitleID >> 32), (u32)_TitleID); - return *m_NANDContent[_TitleID]; + return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT); } -bool CWII_IPC_HLE_Device_es::IsValid(u64 _TitleID) const -{ - if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) - return true; - - return false; -} - - u32 CWII_IPC_HLE_Device_es::ES_DIVerify(const std::vector& tmd) { u64 title_id = 0xDEADBEEFDEADBEEFull; @@ -1168,6 +1131,8 @@ u32 CWII_IPC_HLE_Device_es::ES_DIVerify(const std::vector& tmd) ERROR_LOG(WII_IPC_ES, "DIVerify failed to write disc TMD to NAND."); } DiscIO::cUIDsys::AccessInstance().AddTitle(tmd_title_id); + // DI_VERIFY writes to title.tmd, which is read and cached inside the NAND Content Manager. + // clear the cache to avoid content access mismatches. DiscIO::CNANDContentManager::Access().ClearCache(); return 0; } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.h index bf9c06a918..a0d0d72065 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_es.h @@ -125,30 +125,22 @@ private: { u32 m_Position; u64 m_TitleID; - const DiscIO::SNANDContent* m_pContent; - // This is a (raw) pointer to work around a MSVC bug. - File::IOFile* m_pFile; + u16 m_Index; + u32 m_Size; }; typedef std::map CContentAccessMap; CContentAccessMap m_ContentAccessMap; - typedef std::map CTitleToContentMap; - CTitleToContentMap m_NANDContent; - - const DiscIO::CNANDContentLoader* m_pContentLoader; - std::vector m_TitleIDs; u64 m_TitleID; u32 m_AccessIdentID; static u8 *keyTable[11]; - const DiscIO::CNANDContentLoader& AccessContentDevice(u64 _TitleID); + const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id); u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index); - bool IsValid(u64 _TitleID) const; - struct ecc_cert_t { u32 sig_type ; 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(m_filename, "rb"); + else if (!m_file->IsOpen()) + m_file->Open(m_filename, "rb"); +} +void CNANDContentDataFile::Open() +{ + EnsureOpen(); +} +const std::vector CNANDContentDataFile::Get() +{ + std::vector result; + EnsureOpen(); + if (!m_file->IsGood()) + return result; -CNANDContentLoader::CNANDContentLoader(const std::string& name) + 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; + + return m_file->ReadBytes(buffer, static_cast(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& tmd, const std::vector& decrypted_title_key, const std::vector& data_app) { - m_Content.resize(m_numEntries); + m_Content.resize(m_NumEntries); std::array 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& 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(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(filename); // Be graceful about incorrect TMDs. - if (File::Exists(content.m_Filename)) - content.m_Size = static_cast(File::GetSize(content.m_Filename)); + if (File::Exists(filename)) + content.m_Size = static_cast(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& _TitleIDs, bool _owned) +void cUIDsys::GetTitleIDs(std::vector& 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 { diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h index d6c03a773b..85b6de5117 100644 --- a/Source/Core/DiscIO/NANDContentLoader.h +++ b/Source/Core/DiscIO/NANDContentLoader.h @@ -17,6 +17,41 @@ namespace DiscIO { bool AddTicket(u64 title_id, const std::vector& ticket); +class CNANDContentData +{ +public: + virtual void Open() { }; + virtual const std::vector Get() = 0; + virtual bool GetRange(u32 start, u32 size, u8* buffer) = 0; + virtual void Close() { }; +}; + +class CNANDContentDataFile final : public CNANDContentData +{ +public: + CNANDContentDataFile(const std::string& filename) : m_filename(filename) { }; + + void Open() override; + const std::vector Get() override; + bool GetRange(u32 start, u32 size, u8* buffer) override; + void Close() override; +private: + void EnsureOpen(); + + const std::string m_filename; + std::unique_ptr m_file; +}; +class CNANDContentDataBuffer final : public CNANDContentData +{ +public: + CNANDContentDataBuffer(const std::vector& buffer) : m_buffer(buffer) { }; + + const std::vector Get() override { return m_buffer; }; + bool GetRange(u32 start, u32 size, u8* buffer) override; +private: + const std::vector m_buffer; +}; + struct SNANDContent { u32 m_ContentID; @@ -26,34 +61,33 @@ struct SNANDContent u8 m_SHA1Hash[20]; u8 m_Header[36]; //all of the above - std::string m_Filename; - std::vector m_data; + std::unique_ptr m_Data; }; // Instances of this class must be created by CNANDContentManager class CNANDContentLoader final { public: - CNANDContentLoader(const std::string& _rName); + CNANDContentLoader(const std::string& content_name); virtual ~CNANDContentLoader(); bool IsValid() const { return m_Valid; } void RemoveTitle() const; - u64 GetTitleID() const { return m_TitleID; } + u64 GetTitleID() const { return m_TitleID; } u16 GetIosVersion() const { return m_IosVersion; } - u32 GetBootIndex() const { return m_BootIndex; } + 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& GetTicket() const { return m_ticket; } + const std::vector& GetTicket() const { return m_Ticket; } const std::vector& GetContent() const { return m_Content; } - u16 GetTitleVersion() const {return m_TitleVersion;} - u16 GetNumEntries() const {return m_numEntries;} + u16 GetTitleVersion() const { return m_TitleVersion; } + u16 GetNumEntries() const { return m_NumEntries; } DiscIO::IVolume::ECountry GetCountry() const; - u8 GetCountryChar() const {return m_Country; } + u8 GetCountryChar() const { return m_Country; } enum { @@ -71,16 +105,16 @@ private: static std::vector GetKeyFromTicket(const std::vector& ticket); bool m_Valid; - bool m_isWAD; + bool m_IsWAD; std::string m_Path; u64 m_TitleID; u16 m_IosVersion; u32 m_BootIndex; - u16 m_numEntries; + u16 m_NumEntries; u16 m_TitleVersion; u8 m_TMDView[TMD_VIEW_SIZE]; u8 m_TMDHeader[TMD_HEADER_SIZE]; - std::vector m_ticket; + std::vector m_Ticket; u8 m_Country; std::vector m_Content; @@ -96,7 +130,7 @@ public: const CNANDContentLoader& GetNANDLoader(const std::string& content_path); const CNANDContentLoader& GetNANDLoader(u64 title_id, Common::FromWhichRoot from); - bool RemoveTitle(u64 titl_id, Common::FromWhichRoot from); + bool RemoveTitle(u64 title_id, Common::FromWhichRoot from); void ClearCache(); private: @@ -114,8 +148,8 @@ class CSharedContent public: static CSharedContent& AccessInstance() { static CSharedContent instance; return instance; } - std::string GetFilenameFromSHA1(const u8* _pHash); - std::string AddSharedContent(const u8* _pHash); + std::string GetFilenameFromSHA1(const u8* hash); + std::string AddSharedContent(const u8* hash); void UpdateLocation(); private: @@ -133,8 +167,8 @@ private: }; #pragma pack(pop) - u32 m_lastID; - std::string m_contentMap; + u32 m_LastID; + std::string m_ContentMap; std::vector m_Elements; }; @@ -143,9 +177,9 @@ class cUIDsys public: static cUIDsys& AccessInstance() { static cUIDsys instance; return instance; } - u32 GetUIDFromTitle(u64 _Title); - void AddTitle(u64 _Title); - void GetTitleIDs(std::vector& _TitleIDs, bool _owned = false); + u32 GetUIDFromTitle(u64 title_id); + void AddTitle(u64 title_id); + void GetTitleIDs(std::vector& title_ids, bool owned = false); void UpdateLocation(); private: @@ -163,8 +197,8 @@ private: }; #pragma pack(pop) - u32 m_lastUID; - std::string m_uidSys; + u32 m_LastUID; + std::string m_UidSys; std::vector m_Elements; };