diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index 807eea9018..6da7028e55 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -46,10 +46,6 @@ static const SPatch OSPatches[] = // Name doesn't matter, installed in CBoot::BootUp() { "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, - // ES_LAUNCH - { "__OSBootDol", HLE_Misc::OSBootDol, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, - { "OSGetResetCode", HLE_Misc::OSGetResetCode, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, - // Debug/OS Support { "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index 887762c0f0..01648f8d88 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -54,206 +54,6 @@ void HBReload() Host_Message(WM_USER_STOP); } -void ExecuteDOL(u8* dolFile, u32 fileSize) -{ - // Clear memory before loading the dol - for (u32 i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4) - { - // TODO: Should not write over the "save region" - Memory::Write_U32(0x00000000, i); - } - CDolLoader dolLoader(dolFile, fileSize); - dolLoader.Load(); - - // Scan for common HLE functions - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) - { - g_symbolDB.Clear(); - PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); - SignatureDB db; - if (db.Load(File::GetSysDirectory() + TOTALDB)) - { - db.Apply(&g_symbolDB); - HLE::PatchFunctions(); - db.Clear(); - } - } - - PowerPC::ppcState.iCache.Reset(); - TextureCache::RequestInvalidateTextureCache(); - - CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer(); - size_t size = s_Usb->m_WiiMotes.size(); - bool* wiiMoteConnected = new bool[size]; - for (unsigned int i = 0; i < size; i++) - wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected(); - - WII_IPC_HLE_Interface::Reset(true); - WII_IPC_HLE_Interface::Init(); - s_Usb = GetUsbPointer(); - for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++) - { - if (wiiMoteConnected[i]) - { - s_Usb->m_WiiMotes[i].Activate(false); - s_Usb->m_WiiMotes[i].Activate(true); - } - else - { - s_Usb->m_WiiMotes[i].Activate(false); - } - } - - delete[] wiiMoteConnected; - - if (argsPtr) - { - u32 args_base = Memory::Read_U32(0x800000f4); - u32 ptr_to_num_args = 0xc; - u32 num_args = 1; - u32 hi_ptr = args_base + ptr_to_num_args + 4; - u32 new_args_ptr = args_base + ptr_to_num_args + 8; - - Memory::Write_U32(ptr_to_num_args, args_base + 8); - Memory::Write_U32(num_args, args_base + ptr_to_num_args); - Memory::Write_U32(0x14, hi_ptr); - - for (unsigned int i = 0; i < args.length(); i++) - Memory::WriteUnchecked_U8(args[i], new_args_ptr+i); - } - - NPC = dolLoader.GetEntryPoint() | 0x80000000; -} - -void LoadDOLFromDisc(std::string dol) -{ - DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename); - DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); - - if (dol.length() > 1 && dol.compare(0, 1, "/") == 0) - dol = dol.substr(1); - - u32 fileSize = (u32) pFileSystem->GetFileSize(dol); - u8* dolFile = new u8[fileSize]; - if (fileSize > 0) - { - pFileSystem->ReadFile(dol, dolFile, fileSize); - ExecuteDOL(dolFile, fileSize); - } - delete[] dolFile; -} - -void LoadBootDOLFromDisc() -{ - DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename); - DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); - u32 fileSize = pFileSystem->GetBootDOLSize(); - u8* dolFile = new u8[fileSize]; - if (fileSize > 0) - { - pFileSystem->GetBootDOL(dolFile, fileSize); - ExecuteDOL(dolFile, fileSize); - } - delete[] dolFile; -} - -u32 GetDolFileSize(std::string dol) -{ - DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename); - DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); - - std::string dolFile; - - if (dol.length() > 1 && dol.compare(0, 1, "/") == 0) - dolFile = dol.substr(1); - else - dolFile = dol; - - return (u32)pFileSystem->GetFileSize(dolFile); -} - -u16 GetIOSVersion() -{ - return Memory::Read_U16(0x00003140); -} - -void OSGetResetCode() -{ - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii) - { - u32 resetCode = Memory::Read_U32(0xCC003024); - - if ((resetCode & 0x1fffffff) != 0) - { - GPR(3) = resetCode | 0x80000000; - } - else - { - GPR(3) = 0; - } - - NPC = LR; - } - else - { - HLE::UnPatch("OSGetResetCode"); - NPC = PC; - } -} - -void OSBootDol() -{ - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && GetIOSVersion() >= 30) - { - if ((GPR(4) >> 28) == 0x8) - { - u32 resetCode = GPR(30); - - // Reset game - Memory::Write_U32(resetCode, 0xCC003024); - LoadBootDOLFromDisc(); - return; - } - else if ((GPR(4) >> 28) == 0xA) - { - // Boot from disc partition - PanicAlert("Boot Partition: %08x", GPR(26)); - } - else if ((GPR(4) >> 28) == 0xC) - { - std::string dol; - - // Boot DOL from disc - u32 ptr = GPR(28); - Memory::GetString(dol, ptr); - - if (GetDolFileSize(dol) == 0) - { - ptr = GPR(30); - Memory::GetString(dol, ptr); - if (GetDolFileSize(dol) == 0) - { - // Cannot locate the dol file, exit. - HLE::UnPatch("__OSBootDol"); - NPC = PC; - return; - } - } - - argsPtr = Memory::Read_U32(GPR(5)); - Memory::GetString(args, argsPtr); - LoadDOLFromDisc(dol); - return; - } - else - { - PanicAlert("Unknown boot type: %08x", GPR(4)); - } - } - HLE::UnPatch("__OSBootDol"); - NPC = PC; -} - void HLEGeckoCodehandler() { // Work around the codehandler not properly invalidating the icache, but diff --git a/Source/Core/Core/HLE/HLE_Misc.h b/Source/Core/Core/HLE/HLE_Misc.h index 3a75edb118..7647bd90d0 100644 --- a/Source/Core/Core/HLE/HLE_Misc.h +++ b/Source/Core/Core/HLE/HLE_Misc.h @@ -9,7 +9,5 @@ namespace HLE_Misc void HLEPanicAlert(); void UnimplementedFunction(); void HBReload(); - void OSBootDol(); - void OSGetResetCode(); void HLEGeckoCodehandler(); } diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp index b52ae01c0b..7e2e586e87 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE.cpp @@ -76,21 +76,28 @@ 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 int event_enqueue; static u64 last_reply_time; -static void EnqueueReplyCallback(u64 userdata, int) +static const u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; +static const u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; +static void EnqueueEventCallback(u64 userdata, int) { - reply_queue.push_back((u32)userdata); - Update(); -} - -static void EnqueueRequestCallback(u64 userdata, int) -{ - request_queue.push_back((u32)userdata); + if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) + { + ack_queue.push_back((u32)userdata); + } + else if (userdata & ENQUEUE_REQUEST_FLAG) + { + request_queue.push_back((u32)userdata); + } + else + { + reply_queue.push_back((u32)userdata); + } Update(); } @@ -136,14 +143,12 @@ void Init() g_DeviceMap[i] = new CWII_IPC_HLE_Device_stub(i, "/dev/usb/oh1"); i++; g_DeviceMap[i] = new IWII_IPC_HLE_Device(i, "_Unimplemented_Device_"); i++; - event_enqueue_reply = CoreTiming::RegisterEvent("IPCReply", EnqueueReplyCallback); - event_enqueue_request = CoreTiming::RegisterEvent("IPCRequest", EnqueueRequestCallback); + event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEventCallback); } void Reset(bool _bHard) { - CoreTiming::RemoveAllEvents(event_enqueue_reply); - CoreTiming::RemoveAllEvents(event_enqueue_request); + CoreTiming::RemoveAllEvents(event_enqueue); for (IWII_IPC_HLE_Device*& dev : g_FdMap) { @@ -559,7 +564,7 @@ void ExecuteCommand(u32 _Address) // Happens AS SOON AS IPC gets a new pointer! void EnqueueRequest(u32 address) { - CoreTiming::ScheduleEvent(1000, event_enqueue_request, address); + CoreTiming::ScheduleEvent(1000, event_enqueue, address | ENQUEUE_REQUEST_FLAG); } // Called when IOS module has some reply @@ -568,12 +573,18 @@ void EnqueueRequest(u32 address) // Please search for examples of this being called elsewhere. void EnqueueReply(u32 address, int cycles_in_future) { - CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue_reply, address); + CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, address); } 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, address); +} + +void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future) +{ + CoreTiming::ScheduleEvent(cycles_in_future, event_enqueue, + address | ENQUEUE_ACKNOWLEDGEMENT_FLAG); } // This is called every IPC_HLE_PERIOD from SystemTimers.cpp @@ -600,6 +611,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;