From 4d776ffa8ff1dcefb3618297e8971eb59122c869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 17:26:08 +0100 Subject: [PATCH 1/5] IOS/ES: Keep track of the active title properly This changes ES to keep track of the active title properly, just like IOS: * It is NOT changed on resource manager open/close. * It is reset on IOS reload. * It is changed by ES_DIVerify and ES_Launch. IOS stores the active title in a structure like this: struct ESTitleContext { Ticket* ticket; TMD* tmd; u32 active; }; With this commit, we also do keep the Ticket and TMD around. This makes some of the DI ioctlvs (which return data about the current active title) trivial to implement in the future. This fixes the System Menu not being able to see update partitions and also allows us to change Dolphin's active game info in the future. --- Source/Core/Core/Boot/Boot.cpp | 2 - Source/Core/Core/Boot/Boot_BS2Emu.cpp | 18 ++-- Source/Core/Core/IOS/DI/DI.cpp | 2 +- Source/Core/Core/IOS/ES/ES.cpp | 135 +++++++++++++++--------- Source/Core/Core/IOS/ES/ES.h | 18 +++- Source/Core/Core/IOS/ES/Formats.cpp | 5 + Source/Core/Core/IOS/ES/Formats.h | 1 + Source/Core/Core/IOS/IPC.cpp | 8 +- Source/Core/Core/IOS/IPC.h | 3 +- Source/Core/Core/State.cpp | 2 +- Source/Core/DiscIO/Volume.h | 1 + Source/Core/DiscIO/VolumeWiiCrypted.cpp | 7 ++ Source/Core/DiscIO/VolumeWiiCrypted.h | 1 + 13 files changed, 128 insertions(+), 75 deletions(-) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 46176ecf5c..6e0ffebba6 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -278,8 +278,6 @@ bool CBoot::BootUp() PanicAlertT("Warning - starting ISO in wrong console mode!"); } - IOS::HLE::ES_DIVerify(pVolume.GetTMD()); - _StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::Platform::WII_DISC; // HLE BS2 or not diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index 605579f597..26b44593ad 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -311,6 +311,11 @@ bool CBoot::EmulatedBS2_Wii() if (DVDInterface::GetVolume().GetVolumeType() != DiscIO::Platform::WII_DISC) return false; + const IOS::ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD(); + + if (!SetupWiiMemory(tmd.GetIOSId())) + return false; + // This is some kind of consistency check that is compared to the 0x00 // values as the game boots. This location keeps the 4 byte ID for as long // as the game is running. The 6 byte ID at 0x00 is overwritten sometime @@ -346,11 +351,6 @@ bool CBoot::EmulatedBS2_Wii() PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer - IOS::ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD(); - - if (!SetupWiiMemory(tmd.GetIOSId())) - return false; - // Execute the apploader const u32 apploader_offset = 0x2440; // 0x1c40; @@ -383,11 +383,7 @@ bool CBoot::EmulatedBS2_Wii() PowerPC::ppcState.gpr[3] = 0x81300000; RunFunction(iAppLoaderInit); - // Let the apploader load the exe to memory. At this point I get an unknown IPC command - // (command zero) when I load Wii Sports or other games a second time. I don't notice - // any side effects however. It's a little disconcerting however that Start after Stop - // behaves differently than the first Start after starting Dolphin. It means something - // was not reset correctly. + // Let the apploader load the exe to memory DEBUG_LOG(BOOT, "Run iAppLoaderMain"); do { @@ -413,6 +409,8 @@ bool CBoot::EmulatedBS2_Wii() // Load patches and run startup patches PatchEngine::LoadPatches(); + IOS::HLE::ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); + // return PC = PowerPC::ppcState.gpr[3]; return true; diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp index bd91eb11d5..59c0de4b52 100644 --- a/Source/Core/Core/IOS/DI/DI.cpp +++ b/Source/Core/Core/IOS/DI/DI.cpp @@ -109,7 +109,7 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request) const ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD(); const std::vector raw_tmd = tmd.GetRawTMD(); Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size()); - ES_DIVerify(tmd); + ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); return_value = 1; break; diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 79a69e2317..d2b30b6da7 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -39,6 +39,7 @@ namespace HLE namespace Device { std::string ES::m_ContentFile; +ES::TitleContext ES::m_title_context; constexpr u8 s_key_sd[0x10] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; @@ -65,11 +66,58 @@ constexpr const u8* s_key_table[11] = { ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { + m_title_context.Clear(); + + m_TitleIDs.clear(); + DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; + uid_sys.GetTitleIDs(m_TitleIDs); + + // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented + // m_TitleIDsOwned.clear(); + // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true); +} + +void ES::TitleContext::Clear() +{ + ticket.SetBytes({}); + tmd.SetBytes({}); + active = false; +} + +void ES::TitleContext::DoState(PointerWrap& p) +{ + ticket.DoState(p); + tmd.DoState(p); + p.Do(active); +} + +void ES::TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader) +{ + if (!content_loader.IsValid()) + return; + Update(content_loader.GetTMD(), content_loader.GetTicket()); +} + +void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_) +{ + if (!tmd_.IsValid() || !ticket_.IsValid()) + { + ERROR_LOG(IOS_ES, "TMD or ticket is not valid -- refusing to update title context"); + return; + } + + ticket = ticket_; + tmd = tmd_; + active = true; } void ES::LoadWAD(const std::string& _rContentFile) { m_ContentFile = _rContentFile; + // XXX: Ideally, this should be done during a launch, but because we support launching WADs + // without installing them (which is a bit of a hack), we have to do this manually here. + const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); + m_title_context.Update(content_loader); } void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output) @@ -82,6 +130,8 @@ void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, bool ES::LaunchTitle(u64 title_id, bool skip_reload) const { + m_title_context.Clear(); + NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id); // ES_Launch should probably reset the whole state, which at least means closing all open files. @@ -120,47 +170,18 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const return LaunchTitle(required_ios); } + m_title_context.Update(content_loader); SetDefaultContentFile(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT)); return BootstrapPPC(content_loader); } -void ES::OpenInternal() -{ - auto& contentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); - - // check for cd ... - if (contentLoader.IsValid()) - { - m_TitleID = contentLoader.GetTMD().GetTitleId(); - - m_TitleIDs.clear(); - DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; - uid_sys.GetTitleIDs(m_TitleIDs); - // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented - // m_TitleIDsOwned.clear(); - // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true); - } - else if (DVDInterface::VolumeIsValid()) - { - // blindly grab the titleID from the disc - it's unencrypted at: - // offset 0x0F8001DC and 0x0F80044C - DVDInterface::GetVolume().GetTitleID(&m_TitleID); - } - else - { - m_TitleID = ((u64)0x00010000 << 32) | 0xF00DBEEF; - } - - INFO_LOG(IOS_ES, "Set default title to %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID); -} - void ES::DoState(PointerWrap& p) { Device::DoState(p); p.Do(m_ContentFile); - OpenInternal(); p.Do(m_AccessIdentID); p.Do(m_TitleIDs); + m_title_context.DoState(p); m_addtitle_tmd.DoState(p); p.Do(m_addtitle_content_id); @@ -197,8 +218,6 @@ void ES::DoState(PointerWrap& p) ReturnCode ES::Open(const OpenRequest& request) { - OpenInternal(); - if (m_is_active) INFO_LOG(IOS_ES, "Device was re-opened."); return Device::Open(request); @@ -206,9 +225,8 @@ ReturnCode ES::Open(const OpenRequest& request) void ES::Close() { + // XXX: does IOS really clear the content access map here? m_ContentAccessMap.clear(); - m_TitleIDs.clear(); - m_TitleID = -1; m_AccessIdentID = 0; INFO_LOG(IOS_ES, "ES: Close"); @@ -628,7 +646,10 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); u32 Index = Memory::Read_U32(request.in_vectors[0].address); - s32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index); + if (!m_title_context.active) + return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); + + s32 CFD = OpenTitleContent(m_AccessIdentID++, m_title_context.tmd.GetTitleId(), Index); INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); return GetDefaultReply(CFD); @@ -771,8 +792,13 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(0, 1)) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - Memory::Write_U64(m_TitleID, request.io_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", (u32)(m_TitleID >> 32), (u32)m_TitleID); + if (!m_title_context.active) + return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); + + const u64 title_id = m_title_context.tmd.GetTitleId(); + Memory::Write_U64(title_id, request.io_vectors[0].address); + INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", static_cast(title_id >> 32), + static_cast(title_id)); return GetDefaultReply(IPC_SUCCESS); } @@ -1327,8 +1353,12 @@ IPCCommandResult ES::Sign(const IOCtlVRequest& request) u32 data_size = request.in_vectors[0].size; u8* sig_out = Memory::GetPointer(request.io_vectors[0].address); + if (!m_title_context.active) + return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); + const EcWii& ec = EcWii::GetInstance(); - MakeAPSigAndCert(sig_out, ap_cert_out, m_TitleID, data, data_size, ec.GetNGPriv(), ec.GetNGID()); + MakeAPSigAndCert(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size, + ec.GetNGPriv(), ec.GetNGID()); return GetDefaultReply(IPC_SUCCESS); } @@ -1373,28 +1403,27 @@ const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) const // 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()) + if (m_title_context.active && m_title_context.tmd.GetTitleId() == title_id && + !m_ContentFile.empty()) return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT); } -u32 ES::ES_DIVerify(const IOS::ES::TMDReader& tmd) +s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket) { - if (!tmd.IsValid()) - return -1; + m_title_context.Clear(); - u64 title_id = 0xDEADBEEFDEADBEEFull; - u64 tmd_title_id = tmd.GetTitleId(); + if (!tmd.IsValid() || !ticket.IsValid()) + return ES_PARAMETER_SIZE_OR_ALIGNMENT; - DVDInterface::GetVolume().GetTitleID(&title_id); - if (title_id != tmd_title_id) - return -1; + if (tmd.GetTitleId() != ticket.GetTitleId()) + return ES_PARAMETER_SIZE_OR_ALIGNMENT; - std::string tmd_path = Common::GetTMDFileName(tmd_title_id, Common::FROM_SESSION_ROOT); + std::string tmd_path = Common::GetTMDFileName(tmd.GetTitleId(), Common::FROM_SESSION_ROOT); File::CreateFullPath(tmd_path); - File::CreateFullPath(Common::GetTitleDataPath(tmd_title_id, Common::FROM_SESSION_ROOT)); + File::CreateFullPath(Common::GetTitleDataPath(tmd.GetTitleId(), Common::FROM_SESSION_ROOT)); if (!File::Exists(tmd_path)) { @@ -1404,11 +1433,13 @@ u32 ES::ES_DIVerify(const IOS::ES::TMDReader& tmd) ERROR_LOG(IOS_ES, "DIVerify failed to write disc TMD to NAND."); } DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; - uid_sys.AddTitle(tmd_title_id); + uid_sys.AddTitle(tmd.GetTitleId()); // 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; + + m_title_context.Update(tmd, ticket); + return IPC_SUCCESS; } } // namespace Device } // namespace HLE diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 6521eaa360..120effcd8c 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -40,15 +40,13 @@ public: // Internal implementation of the ES_DECRYPT ioctlv. void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); - void OpenInternal(); - void DoState(PointerWrap& p) override; ReturnCode Open(const OpenRequest& request) override; void Close() override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; - static u32 ES_DIVerify(const IOS::ES::TMDReader& tmd); + static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); // This should only be cleared on power reset static std::string m_ContentFile; @@ -211,9 +209,21 @@ private: ContentAccessMap m_ContentAccessMap; std::vector m_TitleIDs; - u64 m_TitleID = -1; u32 m_AccessIdentID = 0; + // Shared across all ES instances. + static struct TitleContext + { + void Clear(); + void DoState(PointerWrap& p); + void Update(const DiscIO::CNANDContentLoader& content_loader); + void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); + + IOS::ES::TicketReader ticket; + IOS::ES::TMDReader tmd; + bool active = false; + } m_title_context; + // For title installation (ioctls IOCTL_ES_ADDTITLE*). IOS::ES::TMDReader m_addtitle_tmd; u32 m_addtitle_content_id = 0xFFFFFFFF; diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp index 7e94798305..9efc47c846 100644 --- a/Source/Core/Core/IOS/ES/Formats.cpp +++ b/Source/Core/Core/IOS/ES/Formats.cpp @@ -212,6 +212,11 @@ bool TicketReader::IsValid() const return true; } +void TicketReader::DoState(PointerWrap& p) +{ + p.Do(m_bytes); +} + u32 TicketReader::GetNumberOfTickets() const { return static_cast(m_bytes.size() / (GetOffset() + sizeof(Ticket))); diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h index 268506bec3..1dea544cc8 100644 --- a/Source/Core/Core/IOS/ES/Formats.h +++ b/Source/Core/Core/IOS/ES/Formats.h @@ -160,6 +160,7 @@ public: void SetBytes(std::vector&& bytes); bool IsValid() const; + void DoState(PointerWrap& p); const std::vector& GetRawTicket() const; u32 GetNumberOfTickets() const; diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index 1ebedf5d3d..a8295db851 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -752,13 +752,13 @@ bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) void SetDefaultContentFile(const std::string& file_name) { std::lock_guard lock(s_device_map_mutex); - for (const auto& es : s_es_handles) - es->LoadWAD(file_name); + s_es_handles[0]->LoadWAD(file_name); } -void ES_DIVerify(const ES::TMDReader& tmd) +// XXX: also pass certificate chains? +void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket) { - Device::ES::ES_DIVerify(tmd); + Device::ES::DIVerify(tmd, ticket); } void SDIO_EventNotify() diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h index 39acad15fa..ae2c7470d9 100644 --- a/Source/Core/Core/IOS/IPC.h +++ b/Source/Core/Core/IOS/IPC.h @@ -24,6 +24,7 @@ namespace IOS namespace ES { class TMDReader; +class TicketReader; } namespace HLE @@ -75,7 +76,7 @@ void DoState(PointerWrap& p); // Set default content file void SetDefaultContentFile(const std::string& file_name); -void ES_DIVerify(const ES::TMDReader& tmd); +void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket); void SDIO_EventNotify(); diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index f8ae519dc3..209afb1865 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 78; // Last changed in PR 49XX +static const u32 STATE_VERSION = 79; // Last changed in PR 4981 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list, diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index 1190565004..f3f530e5e4 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -37,6 +37,7 @@ public: } virtual bool GetTitleID(u64*) const { return false; } + virtual IOS::ES::TicketReader GetTicket() const { return {}; } virtual IOS::ES::TMDReader GetTMD() const { return {}; } virtual u64 PartitionOffsetToRawOffset(u64 offset) const { return offset; } virtual std::string GetGameID() const = 0; diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.cpp b/Source/Core/DiscIO/VolumeWiiCrypted.cpp index ef291fa237..71e50252db 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.cpp +++ b/Source/Core/DiscIO/VolumeWiiCrypted.cpp @@ -114,6 +114,13 @@ bool CVolumeWiiCrypted::GetTitleID(u64* buffer) const return true; } +IOS::ES::TicketReader CVolumeWiiCrypted::GetTicket() const +{ + std::vector buffer(0x2a4); + Read(m_VolumeOffset, buffer.size(), buffer.data(), false); + return IOS::ES::TicketReader{std::move(buffer)}; +} + IOS::ES::TMDReader CVolumeWiiCrypted::GetTMD() const { u32 tmd_size; diff --git a/Source/Core/DiscIO/VolumeWiiCrypted.h b/Source/Core/DiscIO/VolumeWiiCrypted.h index dfeb74ad66..d7e7c4bddb 100644 --- a/Source/Core/DiscIO/VolumeWiiCrypted.h +++ b/Source/Core/DiscIO/VolumeWiiCrypted.h @@ -33,6 +33,7 @@ public: ~CVolumeWiiCrypted(); bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const override; bool GetTitleID(u64* buffer) const override; + IOS::ES::TicketReader GetTicket() const override; IOS::ES::TMDReader GetTMD() const override; u64 PartitionOffsetToRawOffset(u64 offset) const override; std::string GetGameID() const override; From 9c18eea812b5fe299d0d80d1d3a639c60b63d5b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 17:48:15 +0100 Subject: [PATCH 2/5] IOS/ES: Mark members shared between instances as static Some members are shared between ES instances, and they are just global variables in IOS. This is more efficient than getting the installed titles or setting the current active title tons of times for no reason. --- Source/Core/Core/IOS/ES/ES.cpp | 125 ++++++++++++++++++++------------- Source/Core/Core/IOS/ES/ES.h | 35 +++------ Source/Core/Core/IOS/IPC.cpp | 14 +--- Source/Core/Core/IOS/IPC.h | 2 - 4 files changed, 89 insertions(+), 87 deletions(-) diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index d2b30b6da7..abd458cc22 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -38,8 +38,25 @@ namespace HLE { namespace Device { -std::string ES::m_ContentFile; -ES::TitleContext ES::m_title_context; +struct TitleContext +{ + void Clear(); + void DoState(PointerWrap& p); + void Update(const DiscIO::CNANDContentLoader& content_loader); + void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); + + IOS::ES::TicketReader ticket; + IOS::ES::TMDReader tmd; + bool active = false; +}; + +// Shared across all ES instances. +static std::string s_content_file; +static std::vector s_title_ids; +static TitleContext s_title_context; + +// Title to launch after IOS has been reset and reloaded (similar to /sys/launch.sys). +static u64 s_title_to_launch; constexpr u8 s_key_sd[0x10] = {0xab, 0x01, 0xb9, 0xd8, 0xe1, 0x62, 0x2b, 0x08, 0xaf, 0xba, 0xd8, 0x4d, 0xbf, 0xc2, 0xa5, 0x5d}; @@ -66,39 +83,51 @@ constexpr const u8* s_key_table[11] = { ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) { - m_title_context.Clear(); - - m_TitleIDs.clear(); - DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; - uid_sys.GetTitleIDs(m_TitleIDs); - - // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented - // m_TitleIDsOwned.clear(); - // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(m_TitleIDsOwned, true); } -void ES::TitleContext::Clear() +void ES::Init() +{ + s_content_file = ""; + s_title_context = TitleContext{}; + + s_title_ids.clear(); + DiscIO::cUIDsys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; + uid_sys.GetTitleIDs(s_title_ids); + + // uncomment if ES_GetOwnedTitlesCount / ES_GetOwnedTitles is implemented + // s_title_idsOwned.clear(); + // DiscIO::cUIDsys::AccessInstance().GetTitleIDs(s_title_idsOwned, true); + + if (s_title_to_launch != 0) + { + NOTICE_LOG(IOS, "Re-launching title after IOS reload."); + LaunchTitle(s_title_to_launch, true); + s_title_to_launch = 0; + } +} + +void TitleContext::Clear() { ticket.SetBytes({}); tmd.SetBytes({}); active = false; } -void ES::TitleContext::DoState(PointerWrap& p) +void TitleContext::DoState(PointerWrap& p) { ticket.DoState(p); tmd.DoState(p); p.Do(active); } -void ES::TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader) +void TitleContext::Update(const DiscIO::CNANDContentLoader& content_loader) { if (!content_loader.IsValid()) return; Update(content_loader.GetTMD(), content_loader.GetTicket()); } -void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_) +void TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_) { if (!tmd_.IsValid() || !ticket_.IsValid()) { @@ -113,11 +142,11 @@ void ES::TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::Tic void ES::LoadWAD(const std::string& _rContentFile) { - m_ContentFile = _rContentFile; + s_content_file = _rContentFile; // XXX: Ideally, this should be done during a launch, but because we support launching WADs // without installing them (which is a bit of a hack), we have to do this manually here. - const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); - m_title_context.Update(content_loader); + const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(s_content_file); + s_title_context.Update(content_loader); } void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output) @@ -128,9 +157,9 @@ void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, size, new_iv, input, output); } -bool ES::LaunchTitle(u64 title_id, bool skip_reload) const +bool ES::LaunchTitle(u64 title_id, bool skip_reload) { - m_title_context.Clear(); + s_title_context.Clear(); NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id); @@ -144,12 +173,12 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload) const return LaunchPPCTitle(title_id, skip_reload); } -bool ES::LaunchIOS(u64 ios_title_id) const +bool ES::LaunchIOS(u64 ios_title_id) { return Reload(ios_title_id); } -bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const +bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) { const DiscIO::CNANDContentLoader& content_loader = AccessContentDevice(title_id); if (!content_loader.IsValid()) @@ -165,23 +194,22 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) const // again with the reload skipped, and the PPC will be bootstrapped then. if (!skip_reload) { - SetTitleToLaunch(title_id); + s_title_to_launch = title_id; const u64 required_ios = content_loader.GetTMD().GetIOSId(); return LaunchTitle(required_ios); } - m_title_context.Update(content_loader); - SetDefaultContentFile(Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT)); + s_title_context.Update(content_loader); return BootstrapPPC(content_loader); } void ES::DoState(PointerWrap& p) { Device::DoState(p); - p.Do(m_ContentFile); + p.Do(s_content_file); p.Do(m_AccessIdentID); - p.Do(m_TitleIDs); - m_title_context.DoState(p); + p.Do(s_title_ids); + s_title_context.DoState(p); m_addtitle_tmd.DoState(p); p.Do(m_addtitle_content_id); @@ -646,10 +674,10 @@ IPCCommandResult ES::OpenContent(const IOCtlVRequest& request) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); u32 Index = Memory::Read_U32(request.in_vectors[0].address); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - s32 CFD = OpenTitleContent(m_AccessIdentID++, m_title_context.tmd.GetTitleId(), Index); + s32 CFD = OpenTitleContent(m_AccessIdentID++, s_title_context.tmd.GetTitleId(), Index); INFO_LOG(IOS_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); return GetDefaultReply(CFD); @@ -792,10 +820,10 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(0, 1)) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - const u64 title_id = m_title_context.tmd.GetTitleId(); + const u64 title_id = s_title_context.tmd.GetTitleId(); Memory::Write_U64(title_id, request.io_vectors[0].address); INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLEID: %08x/%08x", static_cast(title_id >> 32), static_cast(title_id)); @@ -818,9 +846,9 @@ IPCCommandResult ES::GetTitleCount(const IOCtlVRequest& request) if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); - Memory::Write_U32((u32)m_TitleIDs.size(), request.io_vectors[0].address); + Memory::Write_U32((u32)s_title_ids.size(), request.io_vectors[0].address); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", m_TitleIDs.size()); + INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLECNT: Number of Titles %zu", s_title_ids.size()); return GetDefaultReply(IPC_SUCCESS); } @@ -832,11 +860,11 @@ IPCCommandResult ES::GetTitles(const IOCtlVRequest& request) u32 MaxCount = Memory::Read_U32(request.in_vectors[0].address); u32 Count = 0; - for (int i = 0; i < (int)m_TitleIDs.size(); i++) + for (int i = 0; i < (int)s_title_ids.size(); i++) { - Memory::Write_U64(m_TitleIDs[i], request.io_vectors[0].address + i * 8); - INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(m_TitleIDs[i] >> 32), - (u32)m_TitleIDs[i]); + Memory::Write_U64(s_title_ids[i], request.io_vectors[0].address + i * 8); + INFO_LOG(IOS_ES, "IOCTL_ES_GETTITLES: %08x/%08x", (u32)(s_title_ids[i] >> 32), + (u32)s_title_ids[i]); Count++; if (Count >= MaxCount) break; @@ -1353,11 +1381,11 @@ IPCCommandResult ES::Sign(const IOCtlVRequest& request) u32 data_size = request.in_vectors[0].size; u8* sig_out = Memory::GetPointer(request.io_vectors[0].address); - if (!m_title_context.active) + if (!s_title_context.active) return GetDefaultReply(ES_PARAMETER_SIZE_OR_ALIGNMENT); const EcWii& ec = EcWii::GetInstance(); - MakeAPSigAndCert(sig_out, ap_cert_out, m_title_context.tmd.GetTitleId(), data, data_size, + MakeAPSigAndCert(sig_out, ap_cert_out, s_title_context.tmd.GetTitleId(), data, data_size, ec.GetNGPriv(), ec.GetNGID()); return GetDefaultReply(IPC_SUCCESS); @@ -1395,24 +1423,27 @@ IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) const +const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) { - // for WADs, the passed title id and the stored title id match; along with m_ContentFile being set + // for WADs, the passed title id and the stored title id match; along with s_content_file 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_title_context.active && m_title_context.tmd.GetTitleId() == title_id && - !m_ContentFile.empty()) - return DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile); + if (s_title_context.active && s_title_context.tmd.GetTitleId() == title_id && + !s_content_file.empty()) + { + return DiscIO::CNANDContentManager::Access().GetNANDLoader(s_content_file); + } return DiscIO::CNANDContentManager::Access().GetNANDLoader(title_id, Common::FROM_SESSION_ROOT); } s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket) { - m_title_context.Clear(); + s_title_context.Clear(); if (!tmd.IsValid() || !ticket.IsValid()) return ES_PARAMETER_SIZE_OR_ALIGNMENT; @@ -1438,7 +1469,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic // clear the cache to avoid content access mismatches. DiscIO::CNANDContentManager::Access().ClearCache(); - m_title_context.Update(tmd, ticket); + s_title_context.Update(tmd, ticket); return IPC_SUCCESS; } } // namespace Device diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index 120effcd8c..8adb54e8e9 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -34,11 +34,15 @@ class ES : public Device public: ES(u32 device_id, const std::string& device_name); - void LoadWAD(const std::string& _rContentFile); - bool LaunchTitle(u64 title_id, bool skip_reload = false) const; + // Called after an IOS reload. + static void Init(); + + static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); + static void LoadWAD(const std::string& _rContentFile); + static bool LaunchTitle(u64 title_id, bool skip_reload = false); // Internal implementation of the ES_DECRYPT ioctlv. - void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); + static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); void DoState(PointerWrap& p) override; @@ -46,11 +50,6 @@ public: void Close() override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; - static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket); - - // This should only be cleared on power reset - static std::string m_ContentFile; - private: enum { @@ -198,32 +197,18 @@ private: IPCCommandResult DIGetTicketView(const IOCtlVRequest& request); IPCCommandResult GetOwnedTitleCount(const IOCtlVRequest& request); - bool LaunchIOS(u64 ios_title_id) const; - bool LaunchPPCTitle(u64 title_id, bool skip_reload) const; + static bool LaunchIOS(u64 ios_title_id); + static bool LaunchPPCTitle(u64 title_id, bool skip_reload); - const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id) const; + static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id); u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index); using ContentAccessMap = std::map; ContentAccessMap m_ContentAccessMap; - std::vector m_TitleIDs; u32 m_AccessIdentID = 0; - // Shared across all ES instances. - static struct TitleContext - { - void Clear(); - void DoState(PointerWrap& p); - void Update(const DiscIO::CNANDContentLoader& content_loader); - void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); - - IOS::ES::TicketReader ticket; - IOS::ES::TMDReader tmd; - bool active = false; - } m_title_context; - // For title installation (ioctls IOCTL_ES_ADDTITLE*). IOS::ES::TMDReader m_addtitle_tmd; u32 m_addtitle_content_id = 0xFFFFFFFF; diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index a8295db851..8dff5a90a6 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -95,7 +95,6 @@ static CoreTiming::EventType* s_event_sdio_notify; static u64 s_last_reply_time; static u64 s_active_title_id; -static u64 s_title_to_launch; static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; @@ -586,7 +585,6 @@ static void AddStaticDevices() { std::lock_guard lock(s_device_map_mutex); _assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized"); - Device::ES::m_ContentFile = ""; num_devices = 0; @@ -706,20 +704,10 @@ bool Reload(const u64 ios_title_id) AddStaticDevices(); - if (s_title_to_launch != 0) - { - NOTICE_LOG(IOS, "Re-launching title after IOS reload."); - s_es_handles[0]->LaunchTitle(s_title_to_launch, true); - s_title_to_launch = 0; - } + Device::ES::Init(); return true; } -void SetTitleToLaunch(const u64 title_id) -{ - s_title_to_launch = title_id; -} - // 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 BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h index ae2c7470d9..901699c545 100644 --- a/Source/Core/Core/IOS/IPC.h +++ b/Source/Core/Core/IOS/IPC.h @@ -68,8 +68,6 @@ bool Reload(u64 ios_title_id); u32 GetVersion(); bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader); -// This sets a title to launch after IOS has been reset and reloaded (similar to /sys/launch.sys). -void SetTitleToLaunch(u64 title_id); // Do State void DoState(PointerWrap& p); From c191fe5348481aac0bce5fac6d6ca292ff76919c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 19:23:12 +0100 Subject: [PATCH 3/5] IOS/ES: Update running game info on title change This allows Dolphin to stay up-to-date about what title is currently running, which fixes savestates, screenshots, etc. after an ES_Launch. Same limitation as with MIOS: currently, GameINIs are not reloaded, because it's a pain with the current config system. It'll happen when the new config system is done, and this commit makes it much easier to do! --- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 3 -- Source/Core/Core/IOS/ES/ES.cpp | 58 +++++++++++++++++++++++---- Source/Core/Core/IOS/ES/Formats.cpp | 5 +++ Source/Core/Core/IOS/ES/Formats.h | 1 + 4 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index 26b44593ad..fa60ba4ab4 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -406,9 +406,6 @@ bool CBoot::EmulatedBS2_Wii() DEBUG_LOG(BOOT, "Run iAppLoaderClose"); RunFunction(iAppLoaderClose); - // Load patches and run startup patches - PatchEngine::LoadPatches(); - IOS::HLE::ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); // return diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index abd458cc22..28a46422de 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -20,17 +20,22 @@ #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/NandPaths.h" +#include "Core/Boot/Boot.h" #include "Core/Boot/Boot_DOL.h" #include "Core/ConfigManager.h" +#include "Core/HLE/HLE.h" #include "Core/HW/DVDInterface.h" #include "Core/HW/Memmap.h" #include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/Formats.h" +#include "Core/PatchEngine.h" +#include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PowerPC.h" #include "Core/WiiRoot.h" #include "Core/ec_wii.h" #include "DiscIO/NANDContentLoader.h" #include "DiscIO/Volume.h" +#include "VideoCommon/HiresTextures.h" namespace IOS { @@ -44,10 +49,12 @@ struct TitleContext void DoState(PointerWrap& p); void Update(const DiscIO::CNANDContentLoader& content_loader); void Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketReader& ticket_); + void UpdateRunningGame() const; IOS::ES::TicketReader ticket; IOS::ES::TMDReader tmd; bool active = false; + bool first_change = true; }; // Shared across all ES instances. @@ -138,6 +145,46 @@ void TitleContext::Update(const IOS::ES::TMDReader& tmd_, const IOS::ES::TicketR ticket = ticket_; tmd = tmd_; active = true; + + // Interesting title changes (channel or disc game launch) always happen after an IOS reload. + if (first_change) + { + UpdateRunningGame(); + first_change = false; + } +} + +void TitleContext::UpdateRunningGame() const +{ + // This one does not always make sense for Wii titles, so let's reset it back to a sane value. + SConfig::GetInstance().m_strName = ""; + if (IOS::ES::IsTitleType(tmd.GetTitleId(), IOS::ES::TitleType::Game) || + IOS::ES::IsTitleType(tmd.GetTitleId(), IOS::ES::TitleType::GameWithChannel)) + { + const u32 title_identifier = Common::swap32(static_cast(tmd.GetTitleId())); + const u16 group_id = Common::swap16(tmd.GetGroupId()); + + char ascii_game_id[6]; + std::memcpy(ascii_game_id, &title_identifier, sizeof(title_identifier)); + std::memcpy(ascii_game_id + sizeof(title_identifier), &group_id, sizeof(group_id)); + + SConfig::GetInstance().m_strGameID = ascii_game_id; + } + else + { + SConfig::GetInstance().m_strGameID = StringFromFormat("%016" PRIX64, tmd.GetTitleId()); + } + + SConfig::GetInstance().m_title_id = tmd.GetTitleId(); + + // TODO: have a callback mechanism for title changes? + g_symbolDB.Clear(); + CBoot::LoadMapFromFilename(); + ::HLE::Clear(); + ::HLE::PatchFunctions(); + PatchEngine::Shutdown(); + PatchEngine::LoadPatches(); + HiresTexture::Update(); } void ES::LoadWAD(const std::string& _rContentFile) @@ -1425,13 +1472,10 @@ IPCCommandResult ES::GetOwnedTitleCount(const IOCtlVRequest& request) const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) { - // for WADs, the passed title id and the stored title id match; along with s_content_file 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. + // for WADs, the passed title id and the stored title id match; along with s_content_file + // 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 (s_title_context.active && s_title_context.tmd.GetTitleId() == title_id && !s_content_file.empty()) { diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp index 9efc47c846..96a81004e5 100644 --- a/Source/Core/Core/IOS/ES/Formats.cpp +++ b/Source/Core/Core/IOS/ES/Formats.cpp @@ -126,6 +126,11 @@ u16 TMDReader::GetTitleVersion() const return Common::swap16(m_bytes.data() + offsetof(TMDHeader, title_version)); } +u16 TMDReader::GetGroupId() const +{ + return Common::swap16(m_bytes.data() + offsetof(TMDHeader, group_id)); +} + u16 TMDReader::GetNumContents() const { return Common::swap16(m_bytes.data() + offsetof(TMDHeader, num_contents)); diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h index 1dea544cc8..de31b78d0b 100644 --- a/Source/Core/Core/IOS/ES/Formats.h +++ b/Source/Core/Core/IOS/ES/Formats.h @@ -137,6 +137,7 @@ public: DiscIO::Region GetRegion() const; u64 GetTitleId() const; u16 GetTitleVersion() const; + u16 GetGroupId() const; u16 GetNumContents() const; bool GetContent(u16 index, Content* content) const; From 5a74343d06c96a643200a63ee6c87736c1036468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 26 Feb 2017 20:47:05 +0100 Subject: [PATCH 4/5] IOS/ES: Add logging for title context changes --- Source/Core/Core/IOS/ES/ES.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 28a46422de..9cf977f439 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -185,6 +185,8 @@ void TitleContext::UpdateRunningGame() const PatchEngine::Shutdown(); PatchEngine::LoadPatches(); HiresTexture::Update(); + + NOTICE_LOG(IOS_ES, "Active title: %016" PRIx64, tmd.GetTitleId()); } void ES::LoadWAD(const std::string& _rContentFile) @@ -194,6 +196,7 @@ void ES::LoadWAD(const std::string& _rContentFile) // without installing them (which is a bit of a hack), we have to do this manually here. const auto& content_loader = DiscIO::CNANDContentManager::Access().GetNANDLoader(s_content_file); s_title_context.Update(content_loader); + INFO_LOG(IOS_ES, "LoadWAD: Title context changed: %016" PRIx64, s_title_context.tmd.GetTitleId()); } void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output) @@ -207,6 +210,7 @@ void ES::DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, bool ES::LaunchTitle(u64 title_id, bool skip_reload) { s_title_context.Clear(); + INFO_LOG(IOS_ES, "ES_Launch: Title context changed: (none)"); NOTICE_LOG(IOS_ES, "Launching title %016" PRIx64 "...", title_id); @@ -247,6 +251,8 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) } s_title_context.Update(content_loader); + INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: %016" PRIx64, + s_title_context.tmd.GetTitleId()); return BootstrapPPC(content_loader); } @@ -1488,6 +1494,7 @@ const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket) { s_title_context.Clear(); + INFO_LOG(IOS_ES, "ES_DIVerify: Title context changed: (none)"); if (!tmd.IsValid() || !ticket.IsValid()) return ES_PARAMETER_SIZE_OR_ALIGNMENT; @@ -1514,6 +1521,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic DiscIO::CNANDContentManager::Access().ClearCache(); s_title_context.Update(tmd, ticket); + INFO_LOG(IOS_ES, "ES_DIVerify: Title context changed: %016" PRIx64, tmd.GetTitleId()); return IPC_SUCCESS; } } // namespace Device From d97ae1054f3dddb840b93334a7cec69a7ba8f196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 27 Feb 2017 21:51:07 +0100 Subject: [PATCH 5/5] Remove useless ES wrappers from the main IOS file This removes wrappers for ES_DIVerify and ES::LoadWAD. They are not really useful as we can simply call the ES function directly, and it is actually somewhat confusing because both functions are static and are not tied to a particular ES instance. --- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 3 ++- Source/Core/Core/Boot/Boot_WiiWAD.cpp | 3 ++- Source/Core/Core/IOS/DI/DI.cpp | 6 +++--- Source/Core/Core/IOS/ES/ES.cpp | 2 ++ Source/Core/Core/IOS/IPC.cpp | 12 ------------ Source/Core/Core/IOS/IPC.h | 10 ---------- 6 files changed, 9 insertions(+), 27 deletions(-) diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index fa60ba4ab4..e320d93e71 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -21,6 +21,7 @@ #include "Core/HW/DVDInterface.h" #include "Core/HW/EXI/EXI_DeviceIPL.h" #include "Core/HW/Memmap.h" +#include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/Formats.h" #include "Core/IOS/IPC.h" #include "Core/PatchEngine.h" @@ -406,7 +407,7 @@ bool CBoot::EmulatedBS2_Wii() DEBUG_LOG(BOOT, "Run iAppLoaderClose"); RunFunction(iAppLoaderClose); - IOS::HLE::ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); + IOS::HLE::Device::ES::DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); // return PC = PowerPC::ppcState.gpr[3]; diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp index 612ddc8fe8..eff9775006 100644 --- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp @@ -11,6 +11,7 @@ #include "Common/NandPaths.h" #include "Core/Boot/Boot.h" +#include "Core/IOS/ES/ES.h" #include "Core/IOS/FS/FileIO.h" #include "Core/IOS/IPC.h" #include "Core/PatchEngine.h" @@ -87,7 +88,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename) if (!SetupWiiMemory(ContentLoader.GetTMD().GetIOSId())) return false; - IOS::HLE::SetDefaultContentFile(_pFilename); + IOS::HLE::Device::ES::LoadWAD(_pFilename); if (!IOS::HLE::BootstrapPPC(ContentLoader)) return false; diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp index 59c0de4b52..4dc743b81c 100644 --- a/Source/Core/Core/IOS/DI/DI.cpp +++ b/Source/Core/Core/IOS/DI/DI.cpp @@ -14,8 +14,8 @@ #include "Core/HW/DVDInterface.h" #include "Core/HW/Memmap.h" #include "Core/IOS/DI/DI.h" +#include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/Formats.h" -#include "Core/IOS/IPC.h" #include "DiscIO/Volume.h" namespace IOS @@ -106,10 +106,10 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request) INFO_LOG(IOS_DI, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset); // Read TMD to the buffer - const ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD(); + const IOS::ES::TMDReader tmd = DVDInterface::GetVolume().GetTMD(); const std::vector raw_tmd = tmd.GetRawTMD(); Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size()); - ES_DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); + ES::DIVerify(tmd, DVDInterface::GetVolume().GetTicket()); return_value = 1; break; diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 9cf977f439..e2cb1ce188 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -1491,6 +1491,8 @@ const DiscIO::CNANDContentLoader& ES::AccessContentDevice(u64 title_id) return DiscIO::CNANDContentManager::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 IOSes anyway). s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket) { s_title_context.Clear(); diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp index 8dff5a90a6..e8bb80f1aa 100644 --- a/Source/Core/Core/IOS/IPC.cpp +++ b/Source/Core/Core/IOS/IPC.cpp @@ -737,18 +737,6 @@ bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) return true; } -void SetDefaultContentFile(const std::string& file_name) -{ - std::lock_guard lock(s_device_map_mutex); - s_es_handles[0]->LoadWAD(file_name); -} - -// XXX: also pass certificate chains? -void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket) -{ - Device::ES::DIVerify(tmd, ticket); -} - void SDIO_EventNotify() { // TODO: Potential race condition: If IsRunning() becomes false after diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h index 901699c545..9bf4f9a24a 100644 --- a/Source/Core/Core/IOS/IPC.h +++ b/Source/Core/Core/IOS/IPC.h @@ -21,12 +21,6 @@ class CNANDContentLoader; namespace IOS { -namespace ES -{ -class TMDReader; -class TicketReader; -} - namespace HLE { namespace Device @@ -72,10 +66,6 @@ bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader); // Do State void DoState(PointerWrap& p); -// Set default content file -void SetDefaultContentFile(const std::string& file_name); -void ES_DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket); - void SDIO_EventNotify(); std::shared_ptr GetDeviceByName(const std::string& device_name);