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 667945bbfa..2d228d7982 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 @@ -264,6 +264,18 @@ IPCCommandResult CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) switch (Buffer.Parameter) { + case IOCTL_ES_ADDTICKET: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 3, + "IOCTL_ES_ADDTICKET wrong number of inputs"); + + INFO_LOG(WII_IPC_ES, "IOCTL_ES_ADDTICKET"); + std::vector ticket(Buffer.InBuffer[0].m_Size); + Memory::CopyFromEmu(ticket.data(), Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size); + DiscIO::AddTicket(ticket); + break; + } + case IOCTL_ES_GETDEVICEID: { _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, diff --git a/Source/Core/DiscIO/NANDContentLoader.cpp b/Source/Core/DiscIO/NANDContentLoader.cpp index 2c5e0e87e7..b3e0ab741f 100644 --- a/Source/Core/DiscIO/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/NANDContentLoader.cpp @@ -512,7 +512,7 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename) } // Extract and copy WAD's ticket to ticket directory - if (!AddTicket(title_id, content_loader.GetTicket())) + if (!AddTicket(content_loader.GetTicket())) { PanicAlertT("WAD installation failed: error creating ticket"); return 0; @@ -525,8 +525,35 @@ u64 CNANDContentManager::Install_WiiWAD(const std::string& filename) return title_id; } -bool AddTicket(u64 title_id, const std::vector& ticket) +bool AddTicket(const std::vector& ticket) { + // Find the "entry point" of the ticket by skipping the appropriate number of + // bytes, depending on the signature type. We need to parse some of the + // ticket because in some cases (ES_AddTicket) it is the only thing that + // indicated to us what title id the ticket is for. + u32 signature_type = Common::FromBigEndian(*reinterpret_cast(ticket.data())); + u32 entry_offset; + if (signature_type == 0x10000) // RSA4096 + { + entry_offset = 576; + } + else if (signature_type == 0x10001) // RSA2048 + { + entry_offset = 320; + } + else if (signature_type == 0x10002) // ECDSA + { + entry_offset = 128; + } + else + { + ERROR_LOG(DISCIO, "Invalid ticket signature type: %08x", signature_type); + return false; + } + + const u8* ticket_data = ticket.data() + entry_offset; + u64 title_id = Common::FromBigEndian(*reinterpret_cast(ticket_data + 0x9c)); + std::string ticket_filename = Common::GetTicketFileName(title_id, Common::FROM_CONFIGURED_ROOT); File::CreateFullPath(ticket_filename); diff --git a/Source/Core/DiscIO/NANDContentLoader.h b/Source/Core/DiscIO/NANDContentLoader.h index f8d3bb6711..589e75ee4f 100644 --- a/Source/Core/DiscIO/NANDContentLoader.h +++ b/Source/Core/DiscIO/NANDContentLoader.h @@ -22,7 +22,7 @@ namespace DiscIO { enum class Region; -bool AddTicket(u64 title_id, const std::vector& ticket); +bool AddTicket(const std::vector& ticket); class CNANDContentData {