IPCHLE: Fix ES_LAUNCH so it works for disk titles.

Among other things, this makes the Disk Channel fully functional.
This commit is contained in:
magumagu 2014-05-28 18:46:34 -07:00
parent 7416b9cdb4
commit f9b72d0891
3 changed files with 28 additions and 9 deletions

View File

@ -76,14 +76,22 @@ IWII_IPC_HLE_Device* es_handles[ES_MAX_COUNT];
typedef std::deque<u32> ipc_msg_queue; typedef std::deque<u32> ipc_msg_queue;
static ipc_msg_queue request_queue; // ppc -> arm static ipc_msg_queue request_queue; // ppc -> arm
static ipc_msg_queue reply_queue; // arm -> ppc 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_reply;
static int event_enqueue_request; static int event_enqueue_request;
static u64 last_reply_time; static u64 last_reply_time;
static const u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x100000000ULL;
static void EnqueueReplyCallback(u64 userdata, int) 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); reply_queue.push_back((u32)userdata);
Update(); Update();
} }
@ -576,6 +584,12 @@ void EnqueueReply_Threadsafe(u32 address, int cycles_in_future)
CoreTiming::ScheduleEvent_Threadsafe(cycles_in_future, event_enqueue_reply, address); 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 // This is called every IPC_HLE_PERIOD from SystemTimers.cpp
// Takes care of routing ipc <-> ipc HLE // Takes care of routing ipc <-> ipc HLE
void Update() void Update()
@ -600,6 +614,14 @@ void Update()
reply_queue.pop_front(); reply_queue.pop_front();
return; 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() void UpdateDevices()

View File

@ -65,5 +65,6 @@ void ExecuteCommand(u32 _Address);
void EnqueueRequest(u32 address); void EnqueueRequest(u32 address);
void EnqueueReply(u32 address, int cycles_in_future = 0); void EnqueueReply(u32 address, int cycles_in_future = 0);
void EnqueueReply_Threadsafe(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 } // end of namespace WII_IPC_HLE_Interface

View File

@ -394,8 +394,6 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
} }
SContentAccess& rContent = itr->second; SContentAccess& rContent = itr->second;
_dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != nullptr);
u8* pDest = Memory::GetPointer(Addr); u8* pDest = Memory::GetPointer(Addr);
if (rContent.m_Position + Size > rContent.m_pContent->m_Size) 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); u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16);
u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24); u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24);
std::string tContentFile;
if ((u32)(TitleID>>32) != 0x00000001 || TitleID == TITLEID_SYSMENU) if ((u32)(TitleID>>32) != 0x00000001 || TitleID == TITLEID_SYSMENU)
{ {
const DiscIO::INANDContentLoader& ContentLoader = AccessContentDevice(TitleID); 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); const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(bootInd);
if (pContent) if (pContent)
{ {
LoadWAD(Common::GetTitleContentPath(TitleID)); tContentFile = Common::GetTitleContentPath(TitleID);
std::unique_ptr<CDolLoader> pDolLoader; std::unique_ptr<CDolLoader> pDolLoader;
if (pContent->m_pData) 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++) for (unsigned int i = 0; i < size; i++)
wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected(); wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected();
std::string tContentFile(m_ContentFile);
WII_IPC_HLE_Interface::Reset(true); WII_IPC_HLE_Interface::Reset(true);
WII_IPC_HLE_Interface::Init(); WII_IPC_HLE_Interface::Init();
s_Usb = GetUsbPointer(); 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. // IOS also seems to write back the command that was responded to in the FD field.
Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8); Memory::Write_U32(IPC_CMD_IOCTLV, _CommandAddress + 8);
// Generate a reply to the IPC command // Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
WII_IPC_HLE_Interface::EnqueueReply(_CommandAddress, 0); // involves restarting IOS; IOS generates two acknowledgements in a row.
WII_IPC_HLE_Interface::EnqueueCommandAcknowledgement(_CommandAddress, 0);
return false; return false;
} }
break; break;