diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index b52ae01c0b..d6ccf7254e 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -76,14 +76,22 @@ IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT]; typedef std::deque ipc_msg_queue; static ipc_msg_queue request_queue; // ppc -> arm static ipc_msg_queue reply_queue; // arm -> ppc +static ipc_msg_queue ack_queue; // arm -> ppc static int event_enqueue_reply; static int event_enqueue_request; static u64 last_reply_time; +static const u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x100000000ULL; static void EnqueueReplyCallback(u64 userdata, int) { + if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) + { + ack_queue.push_back((u32)userdata); + Update(); + return; + } reply_queue.push_back((u32)userdata); Update(); } @@ -576,6 +584,12 @@ void EnqueueReply_Threadsafe(u32 address, int cycles_in_future) CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue_reply, address); } +void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future) +{ + CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue_reply, + address | ENQUEUE_ACKNOWLEDGEMENT_FLAG); +} + // This is called every IPC_HLE_PERIOD from SystemTimers.cpp // Takes care of routing ipc <-> ipc HLE void Update() @@ -600,6 +614,14 @@ void Update() reply_queue.pop_front(); return; } + + if (ack_queue.size()) + { + WII_IPCInterface::GenerateAck(ack_queue.front()); + WARN_LOG(WII_IPC_HLE, "<<-- Double-ack to IPC Request @ 0x%08x", ack_queue.front()); + ack_queue.pop_front(); + return; + } } void UpdateDevices() diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h index fbb8cfb464..224dfec4bd 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.h @@ -65,5 +65,6 @@ void ExecuteCommand(u32 _Address); void EnqueueRequest(u32 address); void EnqueueReply(u32 address, int cycles_in_future = 0); void EnqueueReply_Threadsafe(u32 address, int cycles_in_future = 0); +void EnqueueCommandAcknowledgement(u32 _Address, int cycles_in_future = 0); } // end of namespace WII_IPC_HLE_Interface 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 633364d68a..610f0dc6de 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 @@ -394,8 +394,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) } SContentAccess& rContent = itr->second; - _dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != nullptr); - u8* pDest = Memory::GetPointer(Addr); if (rContent.m_Position + Size > rContent.m_pContent->m_Size) @@ -905,7 +903,7 @@ bool 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); - + std::string tContentFile; if ((u32)(TitleID>>32) != 0x00000001 || TitleID == TITLEID_SYSMENU) { const DiscIO::INANDContentLoader& ContentLoader = AccessContentDevice(TitleID); @@ -915,7 +913,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(bootInd); if (pContent) { - LoadWAD(Common::GetTitleContentPath(TitleID)); + tContentFile = Common::GetTitleContentPath(TitleID); std::unique_ptr pDolLoader; if (pContent->m_pData) { @@ -954,8 +952,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) for (unsigned int i = 0; i < size; i++) wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected(); - std::string tContentFile(m_ContentFile); - WII_IPC_HLE_Interface::Reset(true); WII_IPC_HLE_Interface::Init(); s_Usb = GetUsbPointer(); @@ -997,9 +993,9 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) // IOS also seems to write back the command that was responded to in the FD field. Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8); - // Generate a reply to the IPC command - WII_IPC_HLE_Interface::EnqueueReply(_CommandAddress, 0); - + // Generate a "reply" to the IPC command. ES_LAUNCH is unique because it + // involves restarting IOS; IOS generates two acknowledgements in a row. + WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(_CommandAddress, 0); return false; } break;