diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 2cb7ec62b4..d12114c14c 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -251,8 +251,10 @@ bool ES::LaunchIOS(u64 ios_title_id) bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) { - const DiscIO::NANDContentLoader& content_loader = AccessContentDevice(title_id); - if (!content_loader.IsValid()) + const IOS::ES::TMDReader tmd = FindInstalledTMD(title_id); + const IOS::ES::TicketReader ticket = FindSignedTicket(title_id); + + if (!tmd.IsValid() || !ticket.IsValid()) { if (title_id == Titles::SYSTEM_MENU) { @@ -268,22 +270,18 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) return false; } - if (!content_loader.GetTMD().IsValid() || !content_loader.GetTicket().IsValid()) - return false; - // Before launching a title, IOS first reads the TMD and reloads into the specified IOS version, // even when that version is already running. After it has reloaded, ES_Launch will be called // again with the reload skipped, and the PPC will be bootstrapped then. if (!skip_reload) { s_title_to_launch = title_id; - const u64 required_ios = content_loader.GetTMD().GetIOSId(); + const u64 required_ios = tmd.GetIOSId(); return LaunchTitle(required_ios); } - m_title_context.Update(content_loader.GetTMD(), content_loader.GetTicket()); - INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: %016" PRIx64, - m_title_context.tmd.GetTitleId()); + m_title_context.Update(tmd, ticket); + INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: %016" PRIx64, tmd.GetTitleId()); // Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles // are installed, we can only do this for PPC titles. @@ -294,7 +292,11 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) return false; } - return m_ios.BootstrapPPC(content_loader); + IOS::ES::Content content; + if (!tmd.GetContent(tmd.GetBootIndex(), &content)) + return false; + + return m_ios.BootstrapPPC(GetContentPath(tmd.GetTitleId(), content)); } void ES::Context::DoState(PointerWrap& p) @@ -310,7 +312,20 @@ void ES::Context::DoState(PointerWrap& p) void ES::DoState(PointerWrap& p) { Device::DoState(p); - p.Do(m_content_table); + + for (auto& entry : m_content_table) + { + p.Do(entry.m_opened); + p.Do(entry.m_title_id); + p.Do(entry.m_content); + p.Do(entry.m_position); + p.Do(entry.m_uid); + if (entry.m_opened) + entry.m_opened = entry.m_file.Open(GetContentPath(entry.m_title_id, entry.m_content), "rb"); + else + entry.m_file.Close(); + } + m_title_context.DoState(p); for (auto& context : m_contexts) @@ -573,11 +588,6 @@ IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request) return GetNoReply(); } -const DiscIO::NANDContentLoader& ES::AccessContentDevice(u64 title_id) -{ - return DiscIO::NANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT); -} - // This is technically an ioctlv in IOS's ES, but it is an internal API which cannot be // used from the PowerPC (for unpatched and up-to-date IOSes anyway). // So we block access to it from the IPC interface. diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 9695fd43c8..433a9bad0f 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -10,6 +10,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/File.h" #include "Core/IOS/Device.h" #include "Core/IOS/ES/Formats.h" #include "Core/IOS/IOS.h" @@ -343,13 +344,11 @@ private: const IOS::ES::SharedContentMap& map = IOS::ES::SharedContentMap{ Common::FROM_SESSION_ROOT}) const; - // TODO: remove these - const DiscIO::NANDContentLoader& AccessContentDevice(u64 title_id); - // TODO: reuse the FS code. struct OpenedContent { bool m_opened = false; + File::IOFile m_file; u64 m_title_id = 0; IOS::ES::Content m_content; u32 m_position = 0; diff --git a/Source/Core/Core/IOS/ES/TitleContents.cpp b/Source/Core/Core/IOS/ES/TitleContents.cpp index 46b6477c0e..28c93b0215 100644 --- a/Source/Core/Core/IOS/ES/TitleContents.cpp +++ b/Source/Core/Core/IOS/ES/TitleContents.cpp @@ -23,14 +23,10 @@ namespace Device s32 ES::OpenContent(const IOS::ES::TMDReader& tmd, u16 content_index, u32 uid) { const u64 title_id = tmd.GetTitleId(); - const DiscIO::NANDContentLoader& loader = AccessContentDevice(title_id); - if (!loader.IsValid()) - return FS_ENOENT; - - const DiscIO::NANDContent* content = loader.GetContentByIndex(content_index); - if (!content) - return FS_ENOENT; + IOS::ES::Content content; + if (!tmd.GetContent(content_index, &content)) + return ES_EINVAL; for (size_t i = 0; i < m_content_table.size(); ++i) { @@ -38,9 +34,12 @@ s32 ES::OpenContent(const IOS::ES::TMDReader& tmd, u16 content_index, u32 uid) if (entry.m_opened) continue; + if (!entry.m_file.Open(GetContentPath(title_id, content), "rb")) + return FS_ENOENT; + entry.m_opened = true; entry.m_position = 0; - entry.m_content = content->m_metadata; + entry.m_content = content; entry.m_title_id = title_id; entry.m_uid = uid; INFO_LOG(IOS_ES, "OpenContent: title ID %016" PRIx64 ", UID 0x%x, CFD %zu", title_id, uid, i); @@ -102,20 +101,14 @@ s32 ES::ReadContent(u32 cfd, u8* buffer, u32 size, u32 uid) // XXX: make this reuse the FS code... ES just does a simple "IOS_Read" call here // instead of all this duplicated filesystem logic. - if (entry.m_position + size > entry.m_content.size) - size = static_cast(entry.m_content.size) - entry.m_position; + if (entry.m_position + size > entry.m_file.GetSize()) + size = static_cast(entry.m_file.GetSize()) - entry.m_position; - const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id); - // ContentLoader should never be invalid; rContent has been created by it. - if (ContentLoader.IsValid() && ContentLoader.GetTicket().IsValid()) + entry.m_file.Seek(entry.m_position, SEEK_SET); + if (!entry.m_file.ReadBytes(buffer, size)) { - const DiscIO::NANDContent* pContent = ContentLoader.GetContentByIndex(entry.m_content.index); - pContent->m_Data->Open(); - if (!pContent->m_Data->GetRange(entry.m_position, size, buffer)) - { - ERROR_LOG(IOS_ES, "ES: failed to read %u bytes from %u!", size, entry.m_position); - return ES_SHORT_READ; - } + ERROR_LOG(IOS_ES, "ES: failed to read %u bytes from %u!", size, entry.m_position); + return ES_SHORT_READ; } entry.m_position += size; @@ -145,15 +138,6 @@ ReturnCode ES::CloseContent(u32 cfd, u32 uid) if (!entry.m_opened) return IPC_EINVAL; - // XXX: again, this should be a simple IOS_Close. - const DiscIO::NANDContentLoader& ContentLoader = AccessContentDevice(entry.m_title_id); - // ContentLoader should never be invalid; we shouldn't be here if ES_OPENCONTENT failed before. - if (ContentLoader.IsValid()) - { - const DiscIO::NANDContent* content = ContentLoader.GetContentByIndex(entry.m_content.index); - content->m_Data->Close(); - } - entry = {}; INFO_LOG(IOS_ES, "CloseContent: CFD %u", cfd); return IPC_SUCCESS; diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 3d372c7688..073323d347 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -54,7 +54,6 @@ #include "Core/IOS/WFS/WFSSRV.h" #include "Core/PowerPC/PowerPC.h" #include "Core/WiiRoot.h" -#include "DiscIO/NANDContentLoader.h" namespace IOS { @@ -275,23 +274,17 @@ u16 Kernel::GetGidForPPC() const // This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC. // Unlike 0x42, IOS will set up some constants in memory before booting the PPC. -bool Kernel::BootstrapPPC(const DiscIO::NANDContentLoader& content_loader) +bool Kernel::BootstrapPPC(const std::string& boot_content_path) { - if (!content_loader.IsValid()) - return false; + const DolReader dol{boot_content_path}; - const auto* content = content_loader.GetContentByIndex(content_loader.GetTMD().GetBootIndex()); - if (!content) - return false; - - const auto dol_loader = std::make_unique(content->m_Data->Get()); - if (!dol_loader->IsValid()) + if (!dol.IsValid()) return false; if (!SetupMemory(m_title_id, MemorySetupType::Full)) return false; - if (!dol_loader->LoadIntoMemory()) + if (!dol.LoadIntoMemory()) return false; // NAND titles start with address translation off at 0x3400 (via the PPC bootstub) diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h index aaf6b18671..73f17cbe7a 100644 --- a/Source/Core/Core/IOS/IOS.h +++ b/Source/Core/Core/IOS/IOS.h @@ -19,11 +19,6 @@ class PointerWrap; -namespace DiscIO -{ -class NANDContentLoader; -} - namespace IOS { namespace HLE @@ -113,7 +108,7 @@ public: void SetGidForPPC(u16 gid); u16 GetGidForPPC() const; - bool BootstrapPPC(const DiscIO::NANDContentLoader& content_loader); + bool BootstrapPPC(const std::string& boot_content_path); bool BootIOS(u64 ios_title_id); u32 GetVersion() const;