From 2fc5047d26f45d5309cdd704ba41c9e724f8966d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 29 Apr 2017 16:11:22 +0200 Subject: [PATCH 1/2] IOS: Convert the IOS kernel HLE code to a class This changes the main IOS code (roughly the equivalent of the kernel) to a class instead of being a set of free functions + tons of static variables. The reason for this change is that keeping tons of static variables like that prevents us from making an IOS instance and reusing IOS code easily. Converting the IOS code to a class also allows us to mostly decouple IOS from the PPC emulation. The more interesting changes are in Core/IOS/IOS. Everything else is mostly just boring stuff required by this change... * Because the devices themselves call back to the main IOS code for various things (getting the current version, replying to a request, and other syscall-like functions), just like processes in IOS call kernel syscalls, we have to pass a reference to the kernel to anything that uses IOS syscalls. * Change DoState to save device names instead of device IDs to simplify AddDevice() and get rid of an ugly static count. * Change ES_Launch's ack to be sent at IOS boot, now that we can do this properly. --- Source/Core/Core/Boot/Boot.cpp | 2 +- Source/Core/Core/Boot/Boot_BS2Emu.cpp | 4 +- Source/Core/Core/Boot/Boot_WiiWAD.cpp | 4 +- Source/Core/Core/CMakeLists.txt | 3 +- Source/Core/Core/Core.cpp | 6 +- Source/Core/Core/Core.vcxproj | 6 +- Source/Core/Core/Core.vcxproj.filters | 10 +- Source/Core/Core/HW/DVD/DVDInterface.cpp | 4 +- Source/Core/Core/HW/HW.cpp | 4 +- Source/Core/Core/HW/ProcessorInterface.cpp | 28 +- Source/Core/Core/HW/SystemTimers.cpp | 4 +- Source/Core/Core/HW/WII_IPC.cpp | 10 +- Source/Core/Core/IOS/DI/DI.cpp | 4 +- Source/Core/Core/IOS/DI/DI.h | 4 +- Source/Core/Core/IOS/Device.cpp | 15 +- Source/Core/Core/IOS/Device.h | 8 +- Source/Core/Core/IOS/DeviceStub.cpp | 4 - Source/Core/Core/IOS/DeviceStub.h | 6 +- Source/Core/Core/IOS/ES/ES.cpp | 29 +- Source/Core/Core/IOS/ES/ES.h | 10 +- Source/Core/Core/IOS/FS/FS.cpp | 2 +- Source/Core/Core/IOS/FS/FS.h | 4 +- Source/Core/Core/IOS/FS/FileIO.cpp | 8 +- Source/Core/Core/IOS/FS/FileIO.h | 4 +- Source/Core/Core/IOS/IOS.cpp | 654 +++++++++++ Source/Core/Core/IOS/IOS.h | 120 ++ Source/Core/Core/IOS/IPC.cpp | 1041 ----------------- Source/Core/Core/IOS/IPC.h | 92 -- Source/Core/Core/IOS/MemoryValues.cpp | 329 ++++++ Source/Core/Core/IOS/MemoryValues.h | 41 + Source/Core/Core/IOS/Network/IP/Top.cpp | 2 +- Source/Core/Core/IOS/Network/IP/Top.h | 2 +- .../Core/Core/IOS/Network/KD/NetKDRequest.cpp | 3 +- .../Core/Core/IOS/Network/KD/NetKDRequest.h | 2 +- Source/Core/Core/IOS/Network/KD/NetKDTime.cpp | 2 +- Source/Core/Core/IOS/Network/KD/NetKDTime.h | 2 +- Source/Core/Core/IOS/Network/NCD/Manage.cpp | 3 +- Source/Core/Core/IOS/Network/NCD/Manage.h | 2 +- Source/Core/Core/IOS/Network/SSL.cpp | 2 +- Source/Core/Core/IOS/Network/SSL.h | 4 +- Source/Core/Core/IOS/Network/Socket.cpp | 5 +- Source/Core/Core/IOS/Network/Socket.h | 4 +- Source/Core/Core/IOS/Network/WD/Command.cpp | 3 +- Source/Core/Core/IOS/Network/WD/Command.h | 2 +- Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp | 8 +- Source/Core/Core/IOS/SDIO/SDIOSlot0.h | 4 +- Source/Core/Core/IOS/STM/STM.cpp | 4 +- Source/Core/Core/IOS/STM/STM.h | 6 +- Source/Core/Core/IOS/USB/Bluetooth/BTBase.h | 4 +- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp | 38 +- Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h | 27 +- Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp | 22 +- Source/Core/Core/IOS/USB/Bluetooth/BTReal.h | 4 +- Source/Core/Core/IOS/USB/Bluetooth/BTStub.h | 7 +- .../Core/IOS/USB/Bluetooth/WiimoteDevice.cpp | 2 +- Source/Core/Core/IOS/USB/Common.cpp | 5 + Source/Core/Core/IOS/USB/Common.h | 12 +- Source/Core/Core/IOS/USB/Host.cpp | 4 +- Source/Core/Core/IOS/USB/Host.h | 4 +- Source/Core/Core/IOS/USB/LibusbDevice.cpp | 14 +- Source/Core/Core/IOS/USB/LibusbDevice.h | 5 +- Source/Core/Core/IOS/USB/OH0/OH0.cpp | 16 +- Source/Core/Core/IOS/USB/OH0/OH0.h | 2 +- Source/Core/Core/IOS/USB/OH0/OH0Device.cpp | 10 +- Source/Core/Core/IOS/USB/OH0/OH0Device.h | 2 +- Source/Core/Core/IOS/USB/USBV0.cpp | 16 +- Source/Core/Core/IOS/USB/USBV0.h | 8 +- Source/Core/Core/IOS/USB/USBV4.cpp | 10 +- Source/Core/Core/IOS/USB/USBV4.h | 8 +- Source/Core/Core/IOS/USB/USBV5.cpp | 16 +- Source/Core/Core/IOS/USB/USBV5.h | 8 +- Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp | 13 +- Source/Core/Core/IOS/USB/USB_HID/HIDv4.h | 4 +- Source/Core/Core/IOS/USB/USB_KBD.cpp | 2 +- Source/Core/Core/IOS/USB/USB_KBD.h | 4 +- Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp | 16 +- Source/Core/Core/IOS/USB/USB_VEN/VEN.h | 4 +- Source/Core/Core/IOS/WFS/WFSI.cpp | 2 +- Source/Core/Core/IOS/WFS/WFSI.h | 4 +- Source/Core/Core/IOS/WFS/WFSSRV.cpp | 2 +- Source/Core/Core/IOS/WFS/WFSSRV.h | 4 +- Source/Core/Core/Movie.cpp | 6 +- Source/Core/Core/State.cpp | 2 +- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 30 +- .../Core/DolphinWX/Config/WiiConfigPane.cpp | 6 +- .../Core/DolphinWX/ControllerConfigDiag.cpp | 12 +- Source/Core/DolphinWX/Frame.cpp | 5 +- Source/Core/DolphinWX/FrameTools.cpp | 25 +- 88 files changed, 1477 insertions(+), 1428 deletions(-) create mode 100644 Source/Core/Core/IOS/IOS.cpp create mode 100644 Source/Core/Core/IOS/IOS.h delete mode 100644 Source/Core/Core/IOS/IPC.cpp delete mode 100644 Source/Core/Core/IOS/IPC.h create mode 100644 Source/Core/Core/IOS/MemoryValues.cpp create mode 100644 Source/Core/Core/IOS/MemoryValues.h diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index fe5aba21de..8f315308c7 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -27,7 +27,7 @@ #include "Core/HW/Memmap.h" #include "Core/HW/VideoInterface.h" #include "Core/Host.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/PatchEngine.h" #include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PPCSymbolDB.h" diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index d6968294a4..a42da732b5 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -23,7 +23,7 @@ #include "Core/HW/Memmap.h" #include "Core/IOS/ES/ES.h" #include "Core/IOS/ES/Formats.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/PatchEngine.h" #include "Core/PowerPC/PowerPC.h" @@ -289,7 +289,7 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id) Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable Memory::Write_U32(0x00000000, 0x000030f0); // Apploader - if (!IOS::HLE::Reload(ios_title_id)) + if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id)) { return false; } diff --git a/Source/Core/Core/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Boot/Boot_WiiWAD.cpp index 0750af9a8f..adb6e5bdad 100644 --- a/Source/Core/Core/Boot/Boot_WiiWAD.cpp +++ b/Source/Core/Core/Boot/Boot_WiiWAD.cpp @@ -16,7 +16,7 @@ #include "Core/Boot/Boot.h" #include "Core/IOS/ES/ES.h" #include "Core/IOS/FS/FileIO.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/PatchEngine.h" #include "DiscIO/NANDContentLoader.h" @@ -88,7 +88,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename) return false; IOS::HLE::Device::ES::LoadWAD(_pFilename); - if (!IOS::HLE::BootstrapPPC(ContentLoader)) + if (!IOS::HLE::GetIOS()->BootstrapPPC(ContentLoader)) return false; return true; diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 82ab438e87..a68a87d731 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -147,7 +147,8 @@ set(SRCS HW/WiiSaveCrypted.cpp IOS/Device.cpp IOS/DeviceStub.cpp - IOS/IPC.cpp + IOS/IOS.cpp + IOS/MemoryValues.cpp IOS/MIOS.cpp IOS/DI/DI.cpp IOS/ES/ES.cpp diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index d886c3bbdd..18622549ba 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -50,7 +50,7 @@ #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/HW/Wiimote.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/Movie.h" #include "Core/NetPlayClient.h" #include "Core/NetPlayProto.h" @@ -952,7 +952,9 @@ void UpdateWantDeterminism(bool initial) bool was_unpaused = Core::PauseAndLock(true); s_wants_determinism = new_want_determinism; - IOS::HLE::UpdateWantDeterminism(new_want_determinism); + const auto ios = IOS::HLE::GetIOS(); + if (ios) + ios->UpdateWantDeterminism(new_want_determinism); Fifo::UpdateWantDeterminism(new_want_determinism); // We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use // of FMA. diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 50f452c4a3..67101bfe4e 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -174,7 +174,8 @@ - + + @@ -431,7 +432,8 @@ - + + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index e61dae56fa..6d0b9c9a4a 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -790,7 +790,10 @@ IOS\Network - + + IOS + + IOS @@ -1504,7 +1507,10 @@ IOS - + + IOS + + IOS diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 49c7926c07..404b855f16 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -28,7 +28,7 @@ #include "Core/HW/StreamADPCM.h" #include "Core/HW/SystemTimers.h" #include "Core/IOS/DI/DI.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/Movie.h" #include "DiscIO/Enums.h" @@ -1136,7 +1136,7 @@ void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type case ReplyType::IOS: { - auto di = IOS::HLE::GetDeviceByName("/dev/di"); + auto di = IOS::HLE::GetIOS()->GetDeviceByName("/dev/di"); if (di) std::static_pointer_cast(di)->FinishIOCtl(interrupt_type); break; diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp index 305755872a..b9017b9f21 100644 --- a/Source/Core/Core/HW/HW.cpp +++ b/Source/Core/Core/HW/HW.cpp @@ -21,7 +21,7 @@ #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/HW/WII_IPC.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/Movie.h" #include "Core/State.h" #include "Core/WiiRoot.h" @@ -102,7 +102,7 @@ void DoState(PointerWrap& p) { IOS::DoState(p); p.DoMarker("IOS"); - IOS::HLE::DoState(p); + IOS::HLE::GetIOS()->DoState(p); p.DoMarker("IOS::HLE"); } diff --git a/Source/Core/Core/HW/ProcessorInterface.cpp b/Source/Core/Core/HW/ProcessorInterface.cpp index 2f5ccc9bb5..b88bf05a49 100644 --- a/Source/Core/Core/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/HW/ProcessorInterface.cpp @@ -11,7 +11,7 @@ #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SystemTimers.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/PowerPC/PowerPC.h" @@ -210,22 +210,24 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate) static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate) { - if (SConfig::GetInstance().bWii) - { - auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook"); - if (stm) - std::static_pointer_cast(stm)->ResetButton(); - } + const auto ios = IOS::HLE::GetIOS(); + if (!ios) + return; + + auto stm = ios->GetDeviceByName("/dev/stm/eventhook"); + if (stm) + std::static_pointer_cast(stm)->ResetButton(); } static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate) { - if (SConfig::GetInstance().bWii) - { - auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook"); - if (stm) - std::static_pointer_cast(stm)->PowerButton(); - } + const auto ios = IOS::HLE::GetIOS(); + if (!ios) + return; + + auto stm = ios->GetDeviceByName("/dev/stm/eventhook"); + if (stm) + std::static_pointer_cast(stm)->PowerButton(); } void ResetButton_Tap() diff --git a/Source/Core/Core/HW/SystemTimers.cpp b/Source/Core/Core/HW/SystemTimers.cpp index 874b6a3efd..935a65efad 100644 --- a/Source/Core/Core/HW/SystemTimers.cpp +++ b/Source/Core/Core/HW/SystemTimers.cpp @@ -57,7 +57,7 @@ IPC_HLE_PERIOD: For the Wii Remote this is the call schedule: #include "Core/HW/DSP.h" #include "Core/HW/EXI/EXI_DeviceIPL.h" #include "Core/HW/VideoInterface.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/PatchEngine.h" #include "Core/PowerPC/PowerPC.h" #include "VideoCommon/Fifo.h" @@ -112,7 +112,7 @@ static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate) { if (SConfig::GetInstance().bWii) { - IOS::HLE::UpdateDevices(); + IOS::HLE::GetIOS()->UpdateDevices(); CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE); } } diff --git a/Source/Core/Core/HW/WII_IPC.cpp b/Source/Core/Core/HW/WII_IPC.cpp index 0a2a8bb5c1..870b251bae 100644 --- a/Source/Core/Core/HW/WII_IPC.cpp +++ b/Source/Core/Core/HW/WII_IPC.cpp @@ -9,7 +9,7 @@ #include "Core/CoreTiming.h" #include "Core/HW/MMIO.h" #include "Core/HW/ProcessorInterface.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" // This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because // of the IOS HLE @@ -153,8 +153,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) MMIO::ComplexWrite([](u32, u32 val) { ctrl.ppc(val); if (ctrl.X1) - HLE::EnqueueRequest(ppc_msg); - HLE::Update(); + HLE::GetIOS()->EnqueueIPCRequest(ppc_msg); + HLE::GetIOS()->UpdateIPC(); CoreTiming::ScheduleEvent(0, updateInterrupts, 0); })); @@ -163,7 +163,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead(), MMIO::ComplexWrite([](u32, u32 val) { ppc_irq_flags &= ~val; - HLE::Update(); + HLE::GetIOS()->UpdateIPC(); CoreTiming::ScheduleEvent(0, updateInterrupts, 0); })); @@ -172,7 +172,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) ppc_irq_masks = val; if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf? Reset(); - HLE::Update(); + HLE::GetIOS()->UpdateIPC(); CoreTiming::ScheduleEvent(0, updateInterrupts, 0); })); diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp index 639038b565..593914bcc2 100644 --- a/Source/Core/Core/IOS/DI/DI.cpp +++ b/Source/Core/Core/IOS/DI/DI.cpp @@ -24,7 +24,7 @@ namespace HLE { namespace Device { -DI::DI(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +DI::DI(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } @@ -76,7 +76,7 @@ void DI::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type) // This command has been executed, so it's removed from the queue u32 command_address = m_commands_to_execute.front(); m_commands_to_execute.pop_front(); - EnqueueReply(IOCtlRequest{command_address}, interrupt_type); + m_ios.EnqueueIPCReply(IOCtlRequest{command_address}, interrupt_type); // DVDInterface is now ready to execute another command, // so we start executing a command from the queue if there is one diff --git a/Source/Core/Core/IOS/DI/DI.h b/Source/Core/Core/IOS/DI/DI.h index 7c866f5494..d2d302da73 100644 --- a/Source/Core/Core/IOS/DI/DI.h +++ b/Source/Core/Core/IOS/DI/DI.h @@ -9,7 +9,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -27,7 +27,7 @@ namespace Device class DI : public Device { public: - DI(u32 device_id, const std::string& device_name); + DI(Kernel& ios, const std::string& device_name); void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/Device.cpp b/Source/Core/Core/IOS/Device.cpp index e407d54777..917da1b8de 100644 --- a/Source/Core/Core/IOS/Device.cpp +++ b/Source/Core/Core/IOS/Device.cpp @@ -10,7 +10,7 @@ #include "Core/HW/Memmap.h" #include "Core/HW/SystemTimers.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -26,8 +26,12 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_) { path = Memory::GetString(Memory::Read_U32(address + 0xc)); flags = static_cast(Memory::Read_U32(address + 0x10)); - uid = GetUIDForPPC(); - gid = GetGIDForPPC(); + const Kernel* ios = GetIOS(); + if (ios) + { + uid = ios->GetUidForPPC(); + gid = ios->GetGidForPPC(); + } } ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_) @@ -129,8 +133,8 @@ void IOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TY namespace Device { -Device::Device(const u32 device_id, const std::string& device_name, const DeviceType type) - : m_name(device_name), m_device_id(device_id), m_device_type(type) +Device::Device(Kernel& ios, const std::string& device_name, const DeviceType type) + : m_ios(ios), m_name(device_name), m_device_type(type) { } @@ -143,7 +147,6 @@ void Device::DoState(PointerWrap& p) void Device::DoStateShared(PointerWrap& p) { p.Do(m_name); - p.Do(m_device_id); p.Do(m_device_type); p.Do(m_is_active); } diff --git a/Source/Core/Core/IOS/Device.h b/Source/Core/Core/IOS/Device.h index c8dd0ccf30..c3ca6812c0 100644 --- a/Source/Core/Core/IOS/Device.h +++ b/Source/Core/Core/IOS/Device.h @@ -11,7 +11,7 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -172,7 +172,7 @@ public: OH0, // OH0 child devices which are created dynamically. }; - Device(u32 device_id, const std::string& device_name, DeviceType type = DeviceType::Static); + Device(Kernel& ios, const std::string& device_name, DeviceType type = DeviceType::Static); virtual ~Device() = default; // Release any resources which might interfere with savestating. @@ -181,7 +181,6 @@ public: void DoStateShared(PointerWrap& p); const std::string& GetDeviceName() const { return m_name; } - u32 GetDeviceID() const { return m_device_id; } // Replies to Open and Close requests are sent by the IPC request handler (HandleCommand), // not by the devices themselves. virtual ReturnCode Open(const OpenRequest& request); @@ -199,9 +198,10 @@ public: static IPCCommandResult GetNoReply(); protected: + Kernel& m_ios; + std::string m_name; // STATE_TO_SAVE - u32 m_device_id; DeviceType m_device_type; bool m_is_active = false; diff --git a/Source/Core/Core/IOS/DeviceStub.cpp b/Source/Core/Core/IOS/DeviceStub.cpp index 2502c84769..ea82d09cbc 100644 --- a/Source/Core/Core/IOS/DeviceStub.cpp +++ b/Source/Core/Core/IOS/DeviceStub.cpp @@ -11,10 +11,6 @@ namespace HLE { namespace Device { -Stub::Stub(u32 device_id, const std::string& device_name) : Device(device_id, device_name) -{ -} - ReturnCode Stub::Open(const OpenRequest& request) { WARN_LOG(IOS, "%s faking Open()", m_name.c_str()); diff --git a/Source/Core/Core/IOS/DeviceStub.h b/Source/Core/Core/IOS/DeviceStub.h index b6b60b0248..b61ed28b4e 100644 --- a/Source/Core/Core/IOS/DeviceStub.h +++ b/Source/Core/Core/IOS/DeviceStub.h @@ -8,7 +8,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -19,8 +19,8 @@ namespace Device class Stub final : public Device { public: - Stub(u32 device_id, const std::string& device_name); - + // Inherit the constructor from the Device class, since we don't need to do anything special. + using Device::Device; ReturnCode Open(const OpenRequest& request) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/ES/ES.cpp b/Source/Core/Core/IOS/ES/ES.cpp index 1ff4064c1a..da2a393c5b 100644 --- a/Source/Core/Core/IOS/ES/ES.cpp +++ b/Source/Core/Core/IOS/ES/ES.cpp @@ -55,7 +55,7 @@ static void FinishAllStaleImports() File::CreateDir(import_dir); } -ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { FinishAllStaleImports(); @@ -155,7 +155,7 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request) return GetDefaultReply(IPC_SUCCESS); } -static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd) +static bool UpdateUIDAndGID(Kernel& kernel, const IOS::ES::TMDReader& tmd) { IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT}; const u64 title_id = tmd.GetTitleId(); @@ -165,8 +165,8 @@ static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd) ERROR_LOG(IOS_ES, "Failed to get UID for title %016" PRIx64, title_id); return false; } - SetUIDForPPC(uid); - SetGIDForPPC(tmd.GetGroupId()); + kernel.SetUidForPPC(uid); + kernel.SetGidForPPC(tmd.GetGroupId()); return true; } @@ -197,7 +197,7 @@ IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request) if (!tmd.IsValid()) return GetDefaultReply(FS_ENOENT); - if (!UpdateUIDAndGID(tmd)) + if (!UpdateUIDAndGID(m_ios, tmd)) { ERROR_LOG(IOS_ES, "SetUID: Failed to get UID for title %016" PRIx64, title_id); return GetDefaultReply(ES_SHORT_READ); @@ -225,7 +225,7 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload) bool ES::LaunchIOS(u64 ios_title_id) { - return Reload(ios_title_id); + return m_ios.BootIOS(ios_title_id); } bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) @@ -266,14 +266,14 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload) // Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles // are installed, we can only do this for PPC titles. - if (!UpdateUIDAndGID(s_title_context.tmd)) + if (!UpdateUIDAndGID(m_ios, s_title_context.tmd)) { s_title_context.Clear(); INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: (none)"); return false; } - return BootstrapPPC(content_loader); + return m_ios.BootstrapPPC(content_loader); } void ES::Context::DoState(PointerWrap& p) @@ -555,11 +555,9 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request) if (!LaunchTitle(TitleID)) return GetDefaultReply(FS_ENOENT); - // Generate a "reply" to the IPC command. ES_LAUNCH is unique because it - // involves restarting IOS; IOS generates two acknowledgements in a row. - // Note: If the launch succeeded, we should not write anything to the command buffer as - // IOS does not even reply unless it failed. - EnqueueCommandAcknowledgement(request.address, 0); + // ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row + // (one from the previous IOS for this IPC request, and one from the new one as it boots). + // Nothing should be written to the command buffer if the launch succeeded for obvious reasons. return GetNoReply(); } @@ -570,13 +568,12 @@ IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request) // Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode. // An alternative way to do this is to check whether the current active IOS is MIOS. - if (GetVersion() == 0x101) + if (m_ios.GetVersion() == 0x101) return GetDefaultReply(ES_EINVAL); if (!LaunchTitle(0x0000000100000100)) return GetDefaultReply(FS_ENOENT); - EnqueueCommandAcknowledgement(request.address, 0); return GetNoReply(); } @@ -633,7 +630,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(); - if (!UpdateUIDAndGID(s_title_context.tmd)) + if (!UpdateUIDAndGID(*GetIOS(), s_title_context.tmd)) { return ES_SHORT_READ; } diff --git a/Source/Core/Core/IOS/ES/ES.h b/Source/Core/Core/IOS/ES/ES.h index e060f51af4..ea3b5de9d4 100644 --- a/Source/Core/Core/IOS/ES/ES.h +++ b/Source/Core/Core/IOS/ES/ES.h @@ -12,7 +12,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" #include "Core/IOS/ES/Formats.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -43,11 +43,11 @@ struct TitleContext class ES final : public Device { public: - ES(u32 device_id, const std::string& device_name); + ES(Kernel& ios, const std::string& device_name); 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); + bool LaunchTitle(u64 title_id, bool skip_reload = false); // Internal implementation of the ES_DECRYPT ioctlv. static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output); @@ -265,8 +265,8 @@ private: ContextArray::iterator FindActiveContext(u32 fd); ContextArray::iterator FindInactiveContext(); - static bool LaunchIOS(u64 ios_title_id); - static bool LaunchPPCTitle(u64 title_id, bool skip_reload); + bool LaunchIOS(u64 ios_title_id); + bool LaunchPPCTitle(u64 title_id, bool skip_reload); static TitleContext& GetTitleContext(); static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id); diff --git a/Source/Core/Core/IOS/FS/FS.cpp b/Source/Core/Core/IOS/FS/FS.cpp index 730ecee28f..c23f450cd0 100644 --- a/Source/Core/Core/IOS/FS/FS.cpp +++ b/Source/Core/Core/IOS/FS/FS.cpp @@ -33,7 +33,7 @@ static bool IsValidWiiPath(const std::string& path) namespace Device { -FS::FS(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +FS::FS(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { const std::string tmp_dir = BuildFilename("/tmp"); File::DeleteDirRecursively(tmp_dir); diff --git a/Source/Core/Core/IOS/FS/FS.h b/Source/Core/Core/IOS/FS/FS.h index cec7983df7..d2dd87d7bb 100644 --- a/Source/Core/Core/IOS/FS/FS.h +++ b/Source/Core/Core/IOS/FS/FS.h @@ -8,7 +8,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -32,7 +32,7 @@ namespace Device class FS : public Device { public: - FS(u32 device_id, const std::string& device_name); + FS(Kernel& ios, const std::string& device_name); void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/FS/FileIO.cpp b/Source/Core/Core/IOS/FS/FileIO.cpp index 4c11d8267c..dd2f17af60 100644 --- a/Source/Core/Core/IOS/FS/FileIO.cpp +++ b/Source/Core/Core/IOS/FS/FileIO.cpp @@ -15,7 +15,7 @@ #include "Common/NandPaths.h" #include "Core/HW/Memmap.h" #include "Core/IOS/FS/FileIO.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -71,14 +71,14 @@ void CreateVirtualFATFilesystem() namespace Device { -FileIO::FileIO(u32 device_id, const std::string& device_name) - : Device(device_id, device_name, DeviceType::FileIO) +FileIO::FileIO(Kernel& ios, const std::string& device_name) + : Device(ios, device_name, DeviceType::FileIO) { } ReturnCode FileIO::Close(u32 fd) { - INFO_LOG(IOS_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id); + INFO_LOG(IOS_FILEIO, "FileIO: Close %s", m_name.c_str()); m_Mode = 0; // Let go of our pointer to the file, it will automatically close if we are the last handle diff --git a/Source/Core/Core/IOS/FS/FileIO.h b/Source/Core/Core/IOS/FS/FileIO.h index f341208d9c..068eab57c2 100644 --- a/Source/Core/Core/IOS/FS/FileIO.h +++ b/Source/Core/Core/IOS/FS/FileIO.h @@ -9,7 +9,7 @@ #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -30,7 +30,7 @@ namespace Device class FileIO : public Device { public: - FileIO(u32 device_id, const std::string& device_name); + FileIO(Kernel& ios, const std::string& device_name); ReturnCode Close(u32 fd) override; ReturnCode Open(const OpenRequest& request) override; diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp new file mode 100644 index 0000000000..d1f7ccd0e7 --- /dev/null +++ b/Source/Core/Core/IOS/IOS.cpp @@ -0,0 +1,654 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/IOS/IOS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/Assert.h" +#include "Common/ChunkFile.h" +#include "Common/CommonTypes.h" +#include "Common/Logging/Log.h" +#include "Core/Boot/Boot_DOL.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/HW/Memmap.h" +#include "Core/HW/WII_IPC.h" +#include "Core/IOS/DI/DI.h" +#include "Core/IOS/Device.h" +#include "Core/IOS/DeviceStub.h" +#include "Core/IOS/ES/ES.h" +#include "Core/IOS/FS/FS.h" +#include "Core/IOS/FS/FileIO.h" +#include "Core/IOS/MIOS.h" +#include "Core/IOS/MemoryValues.h" +#include "Core/IOS/Network/IP/Top.h" +#include "Core/IOS/Network/KD/NetKDRequest.h" +#include "Core/IOS/Network/KD/NetKDTime.h" +#include "Core/IOS/Network/NCD/Manage.h" +#include "Core/IOS/Network/SSL.h" +#include "Core/IOS/Network/Socket.h" +#include "Core/IOS/Network/WD/Command.h" +#include "Core/IOS/SDIO/SDIOSlot0.h" +#include "Core/IOS/STM/STM.h" +#include "Core/IOS/USB/Bluetooth/BTEmu.h" +#include "Core/IOS/USB/Bluetooth/BTReal.h" +#include "Core/IOS/USB/OH0/OH0.h" +#include "Core/IOS/USB/OH0/OH0Device.h" +#include "Core/IOS/USB/USB_HID/HIDv4.h" +#include "Core/IOS/USB/USB_KBD.h" +#include "Core/IOS/USB/USB_VEN/VEN.h" +#include "Core/IOS/WFS/WFSI.h" +#include "Core/IOS/WFS/WFSSRV.h" +#include "Core/PowerPC/PowerPC.h" +#include "DiscIO/NANDContentLoader.h" + +namespace IOS +{ +namespace HLE +{ +static std::unique_ptr s_ios; + +constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; +constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; +static CoreTiming::EventType* s_event_enqueue; +static CoreTiming::EventType* s_event_sdio_notify; + +enum class MemorySetupType +{ + IOSReload, + Full, +}; + +constexpr u32 ADDR_MEM1_SIZE = 0x3100; +constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104; +constexpr u32 ADDR_MEM1_END = 0x3108; +constexpr u32 ADDR_MEM1_ARENA_BEGIN = 0x310c; +constexpr u32 ADDR_MEM1_ARENA_END = 0x3110; +constexpr u32 ADDR_PH1 = 0x3114; +constexpr u32 ADDR_MEM2_SIZE = 0x3118; +constexpr u32 ADDR_MEM2_SIM_SIZE = 0x311c; +constexpr u32 ADDR_MEM2_END = 0x3120; +constexpr u32 ADDR_MEM2_ARENA_BEGIN = 0x3124; +constexpr u32 ADDR_MEM2_ARENA_END = 0x3128; +constexpr u32 ADDR_PH2 = 0x312c; +constexpr u32 ADDR_IPC_BUFFER_BEGIN = 0x3130; +constexpr u32 ADDR_IPC_BUFFER_END = 0x3134; +constexpr u32 ADDR_HOLLYWOOD_REVISION = 0x3138; +constexpr u32 ADDR_PH3 = 0x313c; +constexpr u32 ADDR_IOS_VERSION = 0x3140; +constexpr u32 ADDR_IOS_DATE = 0x3144; +constexpr u32 ADDR_UNKNOWN_BEGIN = 0x3148; +constexpr u32 ADDR_UNKNOWN_END = 0x314c; +constexpr u32 ADDR_PH4 = 0x3150; +constexpr u32 ADDR_PH5 = 0x3154; +constexpr u32 ADDR_RAM_VENDOR = 0x3158; +constexpr u32 ADDR_BOOT_FLAG = 0x315c; +constexpr u32 ADDR_APPLOADER_FLAG = 0x315d; +constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e; +constexpr u32 ADDR_SYSMENU_SYNC = 0x3160; + +// The title ID is a u64 where the first 32 bits are used for the title type. +// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits +// are used for the IOS major version -- which is what we want here. +u32 Kernel::GetVersion() const +{ + return static_cast(m_title_id); +} + +constexpr u32 PLACEHOLDER = 0xDEADBEEF; +static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type) +{ + auto target_imv = std::find_if( + GetMemoryValues().begin(), GetMemoryValues().end(), + [&](const MemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); }); + + if (target_imv == GetMemoryValues().end()) + { + ERROR_LOG(IOS, "Unknown IOS version: %016" PRIx64, ios_title_id); + return false; + } + + if (setup_type == MemorySetupType::IOSReload) + { + Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION); + + // These values are written by the IOS kernel as part of its boot process (for IOS28 and newer). + // + // This works in a slightly different way on a real console: older IOS versions (< IOS28) all + // have the same range (933E0000 - 93400000), thus they don't write it at boot and just inherit + // all values. However, the range has changed since IOS28. To make things work properly + // after a reload, newer IOSes always write the legacy range before loading an IOS kernel; + // the new IOS either updates the range (>= IOS28) or inherits it (< IOS28). + // + // We can skip this convoluted process and just write the correct range directly. + Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE); + Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE); + Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END); + Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN); + Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END); + Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN); + Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END); + Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN); + Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END); + + return true; + } + + Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE); + Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE); + Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END); + Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN); + Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END); + Memory::Write_U32(PLACEHOLDER, ADDR_PH1); + Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE); + Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE); + Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END); + Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN); + Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END); + Memory::Write_U32(PLACEHOLDER, ADDR_PH2); + Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN); + Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END); + Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION); + Memory::Write_U32(PLACEHOLDER, ADDR_PH3); + Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION); + Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE); + Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN); + Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END); + Memory::Write_U32(PLACEHOLDER, ADDR_PH4); + Memory::Write_U32(PLACEHOLDER, ADDR_PH5); + Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR); + Memory::Write_U8(0xDE, ADDR_BOOT_FLAG); + Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG); + Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION); + Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC); + return true; +} + +void Kernel::AddDevice(std::unique_ptr device) +{ + _assert_(device->GetDeviceType() == Device::Device::DeviceType::Static); + m_device_map[device->GetDeviceName()] = std::move(device); +} + +void Kernel::AddStaticDevices() +{ + std::lock_guard lock(m_device_map_mutex); + _assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized"); + + if (!SConfig::GetInstance().m_bt_passthrough_enabled) + AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); + else + AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); + + AddDevice(std::make_unique(*this, "/dev/stm/immediate")); + AddDevice(std::make_unique(*this, "/dev/stm/eventhook")); + AddDevice(std::make_unique(*this, "/dev/fs")); + AddDevice(std::make_unique(*this, "/dev/es")); + AddDevice(std::make_unique(*this, "/dev/di")); + AddDevice(std::make_unique(*this, "/dev/net/kd/request")); + AddDevice(std::make_unique(*this, "/dev/net/kd/time")); + AddDevice(std::make_unique(*this, "/dev/net/ncd/manage")); + AddDevice(std::make_unique(*this, "/dev/net/wd/command")); + AddDevice(std::make_unique(*this, "/dev/net/ip/top")); + AddDevice(std::make_unique(*this, "/dev/net/ssl")); + AddDevice(std::make_unique(*this, "/dev/usb/kbd")); + AddDevice(std::make_unique(*this, "/dev/sdio/slot0")); + AddDevice(std::make_unique(*this, "/dev/sdio/slot1")); + AddDevice(std::make_unique(*this, "/dev/usb/hid")); + AddDevice(std::make_unique(*this, "/dev/usb/oh0")); + AddDevice(std::make_unique(*this, "/dev/usb/oh1")); + AddDevice(std::make_unique(*this, "/dev/usb/ven")); + AddDevice(std::make_unique(*this, "/dev/usb/wfssrv")); + AddDevice(std::make_unique(*this, "/dev/wfsi")); +} + +// IOS used by the latest System Menu (4.3). +constexpr u64 IOS80_TITLE_ID = 0x0000000100000050; +constexpr u64 BC_TITLE_ID = 0x0000000100000100; +constexpr u64 MIOS_TITLE_ID = 0x0000000100000101; + +Kernel::Kernel(u64 title_id) : m_title_id(title_id) +{ + INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id); + + if (!SetupMemory(title_id, MemorySetupType::IOSReload)) + WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values"); + + if (title_id == MIOS_TITLE_ID) + { + MIOS::Load(); + return; + } + + // IOS re-inits IPC and sends a dummy ack during its boot process. + EnqueueIPCAcknowledgement(0); + + AddStaticDevices(); +} + +Kernel::~Kernel() +{ + CoreTiming::RemoveAllEvents(s_event_enqueue); + + // Close all devices that were opened + for (auto& device : m_fdmap) + { + if (!device) + continue; + device->Close(0); + } + + { + std::lock_guard lock(m_device_map_mutex); + m_device_map.clear(); + } +} + +void Kernel::HandleIPCEvent(u64 userdata) +{ + if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) + m_ack_queue.push_back(static_cast(userdata)); + else if (userdata & ENQUEUE_REQUEST_FLAG) + m_request_queue.push_back(static_cast(userdata)); + else + m_reply_queue.push_back(static_cast(userdata)); + + UpdateIPC(); +} + +void Init() +{ + s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", [](u64 userdata, s64) { + if (s_ios) + s_ios->HandleIPCEvent(userdata); + }); + + s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", [](u64, s64) { + if (!s_ios) + return; + + auto device = static_cast(s_ios->GetDeviceByName("/dev/sdio/slot0").get()); + if (device) + device->EventNotify(); + }); + + // Start with IOS80 to simulate part of the Wii boot process. + s_ios = std::make_unique(IOS80_TITLE_ID); + // On a Wii, boot2 launches the system menu IOS, which then launches the system menu + // (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up. + // This means that the constants in the 0x3100 region are always set up by the time + // a game is launched. This is necessary because booting games from the game list skips + // a significant part of a Wii's boot process. + SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full); +} + +void Shutdown() +{ + s_ios.reset(); +} + +Kernel* GetIOS() +{ + return s_ios.get(); +} + +// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS. +// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any +// of the other constants to the memory. +bool Kernel::BootIOS(const u64 ios_title_id) +{ + // A real Wii goes through several steps before getting to MIOS. + // + // * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game. + // * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2. + // * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu. + // + // Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS + // (indirectly via boot2), we can just launch MIOS when BC is launched. + if (ios_title_id == BC_TITLE_ID) + { + NOTICE_LOG(IOS, "BC: Launching MIOS..."); + return BootIOS(MIOS_TITLE_ID); + } + + // Shut down the active IOS first before switching to the new one. + s_ios.reset(); + s_ios = std::make_unique(ios_title_id); + return true; +} + +// Since we don't have actual processes, we keep track of only the PPC's UID/GID. +// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC). +void Kernel::SetUidForPPC(u32 uid) +{ + m_ppc_uid = uid; +} + +u32 Kernel::GetUidForPPC() const +{ + return m_ppc_uid; +} + +void Kernel::SetGidForPPC(u16 gid) +{ + m_ppc_gid = gid; +} + +u16 Kernel::GetGidForPPC() const +{ + return m_ppc_gid; +} + +// 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 Kernel::BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) +{ + if (!content_loader.IsValid()) + return false; + + const auto* content = content_loader.GetContentByIndex(content_loader.GetTMD().GetBootIndex()); + if (!content) + return false; + + const auto dol_loader = std::make_unique(content->m_Data->Get()); + if (!dol_loader->IsValid()) + return false; + + if (!SetupMemory(m_title_id, MemorySetupType::Full)) + return false; + + dol_loader->Load(); + + // NAND titles start with address translation off at 0x3400 (via the PPC bootstub) + // The state of other CPU registers (like the BAT registers) doesn't matter much + // because the realmode code at 0x3400 initializes everything itself anyway. + MSR = 0; + PC = 0x3400; + + return true; +} + +void Kernel::SDIO_EventNotify() +{ + // TODO: Potential race condition: If IsRunning() becomes false after + // it's checked, an event may be scheduled after CoreTiming shuts down. + if (SConfig::GetInstance().bWii && Core::IsRunning()) + CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU); +} + +s32 Kernel::GetFreeDeviceID() +{ + for (u32 i = 0; i < IPC_MAX_FDS; i++) + { + if (m_fdmap[i] == nullptr) + { + return i; + } + } + + return -1; +} + +std::shared_ptr Kernel::GetDeviceByName(const std::string& device_name) +{ + std::lock_guard lock(m_device_map_mutex); + const auto iterator = m_device_map.find(device_name); + return iterator != m_device_map.end() ? iterator->second : nullptr; +} + +void Kernel::DoState(PointerWrap& p) +{ + p.Do(m_request_queue); + p.Do(m_reply_queue); + p.Do(m_last_reply_time); + p.Do(m_title_id); + p.Do(m_ppc_uid); + p.Do(m_ppc_gid); + + if (m_title_id == MIOS_TITLE_ID) + return; + + // We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can + // successfully save or re-create /tmp + for (auto& descriptor : m_fdmap) + { + if (descriptor) + descriptor->PrepareForState(p.GetMode()); + } + + for (const auto& entry : m_device_map) + entry.second->DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + for (u32 i = 0; i < IPC_MAX_FDS; i++) + { + u32 exists = 0; + p.Do(exists); + if (exists) + { + auto device_type = Device::Device::DeviceType::Static; + p.Do(device_type); + switch (device_type) + { + case Device::Device::DeviceType::Static: + { + std::string device_name; + p.Do(device_name); + m_fdmap[i] = GetDeviceByName(device_name); + break; + } + case Device::Device::DeviceType::FileIO: + m_fdmap[i] = std::make_shared(*this, ""); + m_fdmap[i]->DoState(p); + break; + case Device::Device::DeviceType::OH0: + m_fdmap[i] = std::make_shared(*this, ""); + m_fdmap[i]->DoState(p); + break; + } + } + } + } + else + { + for (auto& descriptor : m_fdmap) + { + u32 exists = descriptor ? 1 : 0; + p.Do(exists); + if (exists) + { + auto device_type = descriptor->GetDeviceType(); + p.Do(device_type); + if (device_type == Device::Device::DeviceType::Static) + { + std::string device_name = descriptor->GetDeviceName(); + p.Do(device_name); + } + else + { + descriptor->DoState(p); + } + } + } + } +} + +// Returns the FD for the newly opened device (on success) or an error code. +s32 Kernel::OpenDevice(OpenRequest& request) +{ + const s32 new_fd = GetFreeDeviceID(); + INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd); + if (new_fd < 0 || new_fd >= IPC_MAX_FDS) + { + ERROR_LOG(IOS, "Couldn't get a free fd, too many open files"); + return FS_EFDEXHAUSTED; + } + request.fd = new_fd; + + std::shared_ptr device; + if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) + { + device = std::make_shared(*this, request.path); + } + else if (request.path.find("/dev/") == 0) + { + device = GetDeviceByName(request.path); + } + else if (request.path.find('/') == 0) + { + device = std::make_shared(*this, request.path); + } + + if (!device) + { + ERROR_LOG(IOS, "Unknown device: %s", request.path.c_str()); + return IPC_ENOENT; + } + + const ReturnCode code = device->Open(request); + if (code < IPC_SUCCESS) + return code; + m_fdmap[new_fd] = device; + return new_fd; +} + +IPCCommandResult Kernel::HandleIPCCommand(const Request& request) +{ + if (request.command == IPC_CMD_OPEN) + { + OpenRequest open_request{request.address}; + const s32 new_fd = OpenDevice(open_request); + return Device::Device::GetDefaultReply(new_fd); + } + + const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr; + if (!device) + return Device::Device::GetDefaultReply(IPC_EINVAL); + + switch (request.command) + { + case IPC_CMD_CLOSE: + m_fdmap[request.fd].reset(); + return Device::Device::GetDefaultReply(device->Close(request.fd)); + case IPC_CMD_READ: + return device->Read(ReadWriteRequest{request.address}); + case IPC_CMD_WRITE: + return device->Write(ReadWriteRequest{request.address}); + case IPC_CMD_SEEK: + return device->Seek(SeekRequest{request.address}); + case IPC_CMD_IOCTL: + return device->IOCtl(IOCtlRequest{request.address}); + case IPC_CMD_IOCTLV: + return device->IOCtlV(IOCtlVRequest{request.address}); + default: + _assert_msg_(IOS, false, "Unexpected command: %x", request.command); + return Device::Device::GetDefaultReply(IPC_EINVAL); + } +} + +void Kernel::ExecuteIPCCommand(const u32 address) +{ + Request request{address}; + IPCCommandResult result = HandleIPCCommand(request); + + if (!result.send_reply) + return; + + // Ensure replies happen in order + const s64 ticks_until_last_reply = m_last_reply_time - CoreTiming::GetTicks(); + if (ticks_until_last_reply > 0) + result.reply_delay_ticks += ticks_until_last_reply; + m_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks; + + EnqueueIPCReply(request, result.return_value, static_cast(result.reply_delay_ticks)); +} + +// Happens AS SOON AS IPC gets a new pointer! +void Kernel::EnqueueIPCRequest(u32 address) +{ + CoreTiming::ScheduleEvent(1000, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG); +} + +// Called to send a reply to an IOS syscall +void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, int cycles_in_future, + CoreTiming::FromThread from) +{ + Memory::Write_U32(static_cast(return_value), request.address + 4); + // IOS writes back the command that was responded to in the FD field. + Memory::Write_U32(request.command, request.address + 8); + // IOS also overwrites the command type with the reply type. + Memory::Write_U32(IPC_REPLY, request.address); + CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from); +} + +void Kernel::EnqueueIPCAcknowledgement(u32 address, int cycles_in_future) +{ + CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, + address | ENQUEUE_ACKNOWLEDGEMENT_FLAG); +} + +// This is called every IPC_HLE_PERIOD from SystemTimers.cpp +// Takes care of routing ipc <-> ipc HLE +void Kernel::UpdateIPC() +{ + if (!IsReady()) + return; + + if (m_request_queue.size()) + { + GenerateAck(m_request_queue.front()); + u32 command = m_request_queue.front(); + m_request_queue.pop_front(); + ExecuteIPCCommand(command); + return; + } + + if (m_reply_queue.size()) + { + GenerateReply(m_reply_queue.front()); + DEBUG_LOG(IOS, "<<-- Reply to IPC Request @ 0x%08x", m_reply_queue.front()); + m_reply_queue.pop_front(); + return; + } + + if (m_ack_queue.size()) + { + GenerateAck(m_ack_queue.front()); + WARN_LOG(IOS, "<<-- Double-ack to IPC Request @ 0x%08x", m_ack_queue.front()); + m_ack_queue.pop_front(); + return; + } +} + +void Kernel::UpdateDevices() +{ + // Check if a hardware device must be updated + for (const auto& entry : m_device_map) + { + if (entry.second->IsOpened()) + { + entry.second->Update(); + } + } +} + +void Kernel::UpdateWantDeterminism(const bool new_want_determinism) +{ + WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism); + for (const auto& device : m_device_map) + device.second->UpdateWantDeterminism(new_want_determinism); +} +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h new file mode 100644 index 0000000000..40db6c09b5 --- /dev/null +++ b/Source/Core/Core/IOS/IOS.h @@ -0,0 +1,120 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Core/CoreTiming.h" +#include "Core/HW/SystemTimers.h" + +class PointerWrap; + +namespace DiscIO +{ +class CNANDContentLoader; +} + +namespace IOS +{ +namespace HLE +{ +namespace Device +{ +class Device; +} + +struct Request; +struct OpenRequest; + +struct IPCCommandResult +{ + s32 return_value; + bool send_reply; + u64 reply_delay_ticks; +}; + +enum IPCCommandType : u32 +{ + IPC_CMD_OPEN = 1, + IPC_CMD_CLOSE = 2, + IPC_CMD_READ = 3, + IPC_CMD_WRITE = 4, + IPC_CMD_SEEK = 5, + IPC_CMD_IOCTL = 6, + IPC_CMD_IOCTLV = 7, + // This is used for replies to commands. + IPC_REPLY = 8, +}; + +// HLE for the IOS kernel: IPC, device management, syscalls, and Dolphin-specific, IOS-wide calls. +class Kernel +{ +public: + explicit Kernel(u64 ios_title_id); + ~Kernel(); + + void DoState(PointerWrap& p); + void HandleIPCEvent(u64 userdata); + void UpdateIPC(); + void UpdateDevices(); + void UpdateWantDeterminism(bool new_want_determinism); + + std::shared_ptr GetDeviceByName(const std::string& device_name); + void SDIO_EventNotify(); + + void EnqueueIPCRequest(u32 address); + void EnqueueIPCReply(const Request& request, s32 return_value, int cycles_in_future = 0, + CoreTiming::FromThread from = CoreTiming::FromThread::CPU); + + void SetUidForPPC(u32 uid); + u32 GetUidForPPC() const; + void SetGidForPPC(u16 gid); + u16 GetGidForPPC() const; + + bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader); + bool BootIOS(u64 ios_title_id); + u32 GetVersion() const; + +private: + void ExecuteIPCCommand(u32 address); + IPCCommandResult HandleIPCCommand(const Request& request); + void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0); + + void AddDevice(std::unique_ptr device); + void AddStaticDevices(); + s32 GetFreeDeviceID(); + s32 OpenDevice(OpenRequest& request); + + u64 m_title_id = 0; + static constexpr u8 IPC_MAX_FDS = 0x18; + std::map> m_device_map; + std::mutex m_device_map_mutex; + // TODO: make this fdmap per process. + std::array, IPC_MAX_FDS> m_fdmap; + + u32 m_ppc_uid = 0; + u16 m_ppc_gid = 0; + + using IPCMsgQueue = std::deque; + IPCMsgQueue m_request_queue; // ppc -> arm + IPCMsgQueue m_reply_queue; // arm -> ppc + IPCMsgQueue m_ack_queue; // arm -> ppc + u64 m_last_reply_time = 0; +}; + +// Used for controlling and accessing an IOS instance that is tied to emulation. +void Init(); +void Shutdown(); +Kernel* GetIOS(); + +} // namespace HLE +} // namespace IOS diff --git a/Source/Core/Core/IOS/IPC.cpp b/Source/Core/Core/IOS/IPC.cpp deleted file mode 100644 index 2906f207c2..0000000000 --- a/Source/Core/Core/IOS/IPC.cpp +++ /dev/null @@ -1,1041 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -// This is the main Wii IPC file that handles all incoming IPC requests and directs them -// to the right function. -// -// IPC basics (IOS' usage): -// All IPC request handlers will write a return value to 0x04. -// Open: Device file descriptor or error code -// Close: IPC_SUCCESS -// Read: Bytes read -// Write: Bytes written -// Seek: Seek position -// Ioctl: Depends on the handler -// Ioctlv: Depends on the handler -// Replies may be sent immediately or asynchronously for ioctls and ioctlvs. - -#include "Core/IOS/IPC.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Common/Assert.h" -#include "Common/ChunkFile.h" -#include "Common/CommonTypes.h" -#include "Common/Logging/Log.h" -#include "Core/Boot/Boot_DOL.h" -#include "Core/ConfigManager.h" -#include "Core/Core.h" -#include "Core/CoreTiming.h" -#include "Core/HW/Memmap.h" -#include "Core/HW/WII_IPC.h" -#include "Core/IOS/DI/DI.h" -#include "Core/IOS/Device.h" -#include "Core/IOS/DeviceStub.h" -#include "Core/IOS/ES/ES.h" -#include "Core/IOS/FS/FS.h" -#include "Core/IOS/FS/FileIO.h" -#include "Core/IOS/MIOS.h" -#include "Core/IOS/Network/IP/Top.h" -#include "Core/IOS/Network/KD/NetKDRequest.h" -#include "Core/IOS/Network/KD/NetKDTime.h" -#include "Core/IOS/Network/NCD/Manage.h" -#include "Core/IOS/Network/SSL.h" -#include "Core/IOS/Network/Socket.h" -#include "Core/IOS/Network/WD/Command.h" -#include "Core/IOS/SDIO/SDIOSlot0.h" -#include "Core/IOS/STM/STM.h" -#include "Core/IOS/USB/Bluetooth/BTEmu.h" -#include "Core/IOS/USB/Bluetooth/BTReal.h" -#include "Core/IOS/USB/OH0/OH0.h" -#include "Core/IOS/USB/OH0/OH0Device.h" -#include "Core/IOS/USB/USB_HID/HIDv4.h" -#include "Core/IOS/USB/USB_KBD.h" -#include "Core/IOS/USB/USB_VEN/VEN.h" -#include "Core/IOS/WFS/WFSI.h" -#include "Core/IOS/WFS/WFSSRV.h" -#include "Core/PowerPC/PowerPC.h" -#include "DiscIO/NANDContentLoader.h" - -namespace IOS -{ -namespace HLE -{ -static std::map> s_device_map; -static std::mutex s_device_map_mutex; - -// STATE_TO_SAVE -constexpr u8 IPC_MAX_FDS = 0x18; -static std::shared_ptr s_fdmap[IPC_MAX_FDS]; - -using IPCMsgQueue = std::deque; -static IPCMsgQueue s_request_queue; // ppc -> arm -static IPCMsgQueue s_reply_queue; // arm -> ppc -static IPCMsgQueue s_ack_queue; // arm -> ppc - -static CoreTiming::EventType* s_event_enqueue; -static CoreTiming::EventType* s_event_sdio_notify; - -static u64 s_last_reply_time; - -static u64 s_active_title_id; - -static u32 s_ppc_uid; -static u16 s_ppc_gid; - -static constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; -static constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; - -enum class MemorySetupType -{ - IOSReload, - Full, -}; - -struct IosMemoryValues -{ - u16 ios_number; - u32 ios_version; - u32 ios_date; - u32 mem1_physical_size; - u32 mem1_simulated_size; - u32 mem1_end; - u32 mem1_arena_begin; - u32 mem1_arena_end; - u32 mem2_physical_size; - u32 mem2_simulated_size; - u32 mem2_end; - u32 mem2_arena_begin; - u32 mem2_arena_end; - u32 ipc_buffer_begin; - u32 ipc_buffer_end; - u32 hollywood_revision; - u32 ram_vendor; - u32 unknown_begin; - u32 unknown_end; - u32 sysmenu_sync; -}; - -constexpr u32 ADDR_MEM1_SIZE = 0x3100; -constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104; -constexpr u32 ADDR_MEM1_END = 0x3108; -constexpr u32 ADDR_MEM1_ARENA_BEGIN = 0x310c; -constexpr u32 ADDR_MEM1_ARENA_END = 0x3110; -constexpr u32 ADDR_PH1 = 0x3114; -constexpr u32 ADDR_MEM2_SIZE = 0x3118; -constexpr u32 ADDR_MEM2_SIM_SIZE = 0x311c; -constexpr u32 ADDR_MEM2_END = 0x3120; -constexpr u32 ADDR_MEM2_ARENA_BEGIN = 0x3124; -constexpr u32 ADDR_MEM2_ARENA_END = 0x3128; -constexpr u32 ADDR_PH2 = 0x312c; -constexpr u32 ADDR_IPC_BUFFER_BEGIN = 0x3130; -constexpr u32 ADDR_IPC_BUFFER_END = 0x3134; -constexpr u32 ADDR_HOLLYWOOD_REVISION = 0x3138; -constexpr u32 ADDR_PH3 = 0x313c; -constexpr u32 ADDR_IOS_VERSION = 0x3140; -constexpr u32 ADDR_IOS_DATE = 0x3144; -constexpr u32 ADDR_UNKNOWN_BEGIN = 0x3148; -constexpr u32 ADDR_UNKNOWN_END = 0x314c; -constexpr u32 ADDR_PH4 = 0x3150; -constexpr u32 ADDR_PH5 = 0x3154; -constexpr u32 ADDR_RAM_VENDOR = 0x3158; -constexpr u32 ADDR_BOOT_FLAG = 0x315c; -constexpr u32 ADDR_APPLOADER_FLAG = 0x315d; -constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e; -constexpr u32 ADDR_SYSMENU_SYNC = 0x3160; - -constexpr u32 MEM1_SIZE = 0x01800000; -constexpr u32 MEM1_END = 0x81800000; -constexpr u32 MEM1_ARENA_BEGIN = 0x00000000; -constexpr u32 MEM1_ARENA_END = 0x81800000; -constexpr u32 MEM2_SIZE = 0x4000000; -constexpr u32 MEM2_ARENA_BEGIN = 0x90000800; -constexpr u32 HOLLYWOOD_REVISION = 0x00000011; -constexpr u32 PLACEHOLDER = 0xDEADBEEF; -constexpr u32 RAM_VENDOR = 0x0000FF01; -constexpr u32 RAM_VENDOR_MIOS = 0xCAFEBABE; - -// These values were manually extracted from the relevant IOS binaries. -// The writes are usually contained in a single function that -// mostly writes raw literals to the relevant locations. -// e.g. IOS9, version 1034, content id 0x00000006, function at 0xffff6884 -constexpr std::array ios_memory_values = { - {{ - 9, 0x9040a, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 11, 0xb000a, 0x102506, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 12, 0xc020e, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 13, 0xd0408, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 14, 0xe0408, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 15, 0xf0408, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 17, 0x110408, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 20, 0x14000c, 0x102506, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 21, 0x15040f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 22, 0x16050e, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, - 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, - RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, - }, - { - 28, 0x1c070f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN, - 0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93800000, 0x93820000, 0, - }, - { - 30, 0x1e0a10, 0x40308, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 31, 0x1f0e18, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 33, 0x210e18, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 34, 0x220e18, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 35, 0x230e18, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 36, 0x240e18, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 37, 0x25161f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 38, 0x26101c, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 40, 0x280911, 0x022308, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 41, 0x290e17, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 43, 0x2b0e17, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 45, 0x2d0e17, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 46, 0x2e0e17, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 48, 0x30101c, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 50, 0x321319, 0x101008, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 51, 0x331219, 0x071108, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 52, 0x34161d, 0x101008, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 53, 0x35161f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 55, 0x37161f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 56, 0x38161e, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 57, 0x39171f, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 58, 0x3a1820, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 59, 0x3b1c21, 0x101811, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 60, 0x3c181e, 0x112408, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 61, 0x3d161e, 0x030110, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 62, 0x3e191e, 0x022712, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 70, 0x461a1f, 0x060309, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 80, 0x501b20, 0x030310, MEM1_SIZE, - MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, - MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, - 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, - RAM_VENDOR, 0x93600000, 0x93620000, 0, - }, - { - 257, - 0x707, - 0x82209, - MEM1_SIZE, - MEM1_SIZE, - MEM1_END, - MEM1_ARENA_BEGIN, - MEM1_ARENA_END, - MEM2_SIZE, - MEM2_SIZE, - 0x93600000, - MEM2_ARENA_BEGIN, - 0x935E0000, - 0x935E0000, - 0x93600000, - HOLLYWOOD_REVISION, - RAM_VENDOR_MIOS, - PLACEHOLDER, - PLACEHOLDER, - PLACEHOLDER, - }}}; - -static void EnqueueEvent(u64 userdata, s64 cycles_late = 0) -{ - if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) - { - s_ack_queue.push_back(static_cast(userdata)); - } - else if (userdata & ENQUEUE_REQUEST_FLAG) - { - s_request_queue.push_back(static_cast(userdata)); - } - else - { - s_reply_queue.push_back(static_cast(userdata)); - } - Update(); -} - -static void SDIO_EventNotify_CPUThread(u64 userdata, s64 cycles_late) -{ - auto device = static_cast(GetDeviceByName("/dev/sdio/slot0").get()); - if (device) - device->EventNotify(); -} - -// The title ID is a u64 where the first 32 bits are used for the title type. -// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits -// are used for the IOS major version -- which is what we want here. -u32 GetVersion() -{ - return static_cast(s_active_title_id); -} - -static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type) -{ - auto target_imv = std::find_if( - ios_memory_values.begin(), ios_memory_values.end(), - [&](const IosMemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); }); - - if (target_imv == ios_memory_values.end()) - { - ERROR_LOG(IOS, "Unknown IOS version: %016" PRIx64, ios_title_id); - return false; - } - - if (setup_type == MemorySetupType::IOSReload) - { - Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION); - - // These values are written by the IOS kernel as part of its boot process (for IOS28 and newer). - // - // This works in a slightly different way on a real console: older IOS versions (< IOS28) all - // have the same range (933E0000 - 93400000), thus they don't write it at boot and just inherit - // all values. However, the range has changed since IOS28. To make things work properly - // after a reload, newer IOSes always write the legacy range before loading an IOS kernel; - // the new IOS either updates the range (>= IOS28) or inherits it (< IOS28). - // - // We can skip this convoluted process and just write the correct range directly. - Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE); - Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE); - Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END); - Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN); - Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END); - Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN); - Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END); - Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN); - Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END); - - return true; - } - - Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE); - Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE); - Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END); - Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN); - Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END); - Memory::Write_U32(PLACEHOLDER, ADDR_PH1); - Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE); - Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE); - Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END); - Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN); - Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END); - Memory::Write_U32(PLACEHOLDER, ADDR_PH2); - Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN); - Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END); - Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION); - Memory::Write_U32(PLACEHOLDER, ADDR_PH3); - Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION); - Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE); - Memory::Write_U32(target_imv->unknown_begin, ADDR_UNKNOWN_BEGIN); - Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END); - Memory::Write_U32(PLACEHOLDER, ADDR_PH4); - Memory::Write_U32(PLACEHOLDER, ADDR_PH5); - Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR); - Memory::Write_U8(0xDE, ADDR_BOOT_FLAG); - Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG); - Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION); - Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC); - return true; -} - -static u32 num_devices; - -template -std::shared_ptr AddDevice(const char* device_name) -{ - auto device = std::make_shared(num_devices, device_name); - _assert_(device->GetDeviceType() == Device::Device::DeviceType::Static); - s_device_map[num_devices] = device; - num_devices++; - return device; -} - -static void AddStaticDevices() -{ - std::lock_guard lock(s_device_map_mutex); - _assert_msg_(IOS, s_device_map.empty(), "Reinit called while already initialized"); - - num_devices = 0; - - // Build hardware devices - if (!SConfig::GetInstance().m_bt_passthrough_enabled) - AddDevice("/dev/usb/oh1/57e/305"); - else - AddDevice("/dev/usb/oh1/57e/305"); - - AddDevice("/dev/stm/immediate"); - AddDevice("/dev/stm/eventhook"); - AddDevice("/dev/fs"); - AddDevice("/dev/es"); - AddDevice("/dev/di"); - AddDevice("/dev/net/kd/request"); - AddDevice("/dev/net/kd/time"); - AddDevice("/dev/net/ncd/manage"); - AddDevice("/dev/net/wd/command"); - AddDevice("/dev/net/ip/top"); - AddDevice("/dev/net/ssl"); - AddDevice("/dev/usb/kbd"); - AddDevice("/dev/sdio/slot0"); - AddDevice("/dev/sdio/slot1"); - AddDevice("/dev/usb/hid"); - AddDevice("/dev/usb/oh0"); - AddDevice("/dev/usb/oh1"); - AddDevice("/dev/usb/ven"); - AddDevice("/dev/usb/wfssrv"); - AddDevice("/dev/wfsi"); -} - -// IOS used by the latest System Menu (4.3). -constexpr u64 IOS80_TITLE_ID = 0x0000000100000050; - -void Init() -{ - s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", EnqueueEvent); - s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", SDIO_EventNotify_CPUThread); - - // On a Wii, boot2 launches the system menu IOS, which then launches the system menu - // (which bootstraps the PPC). This means that after a normal boot process, the constants - // in the 0x3100 region will always have been set up. - // This is necessary because booting games from the game list skips a significant part - // of a Wii's boot process. - SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full); -} - -static void Reset() -{ - CoreTiming::RemoveAllEvents(s_event_enqueue); - - // Close all devices that were opened and delete their resources - for (auto& device : s_fdmap) - { - if (!device) - continue; - device->Close(0); - device.reset(); - } - - { - std::lock_guard lock(s_device_map_mutex); - s_device_map.clear(); - } - - s_request_queue.clear(); - s_reply_queue.clear(); - - s_last_reply_time = 0; -} - -void Shutdown() -{ - Reset(); -} - -constexpr u64 BC_TITLE_ID = 0x0000000100000100; -constexpr u64 MIOS_TITLE_ID = 0x0000000100000101; - -// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS. -// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any -// of the other constants to the memory. -bool Reload(const u64 ios_title_id) -{ - // A real Wii goes through several steps before getting to MIOS. - // - // * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game. - // * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2. - // * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu. - // - // Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS - // (indirectly via boot2), we can just launch MIOS when BC is launched. - if (ios_title_id == BC_TITLE_ID) - { - NOTICE_LOG(IOS, "BC: Launching MIOS..."); - return Reload(MIOS_TITLE_ID); - } - - if (!SetupMemory(ios_title_id, MemorySetupType::IOSReload)) - return false; - - s_active_title_id = ios_title_id; - Reset(); - - if (ios_title_id == MIOS_TITLE_ID) - { - // MIOS is a special case. It does not have the same syscalls as regular IOSes - // and writes the magic values at a different time (here) in the boot process. - SetupMemory(ios_title_id, MemorySetupType::Full); - return MIOS::Load(); - } - - AddStaticDevices(); - - return true; -} - -// Since we don't have actual processes, we keep track of only the PPC's UID/GID. -// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC). -void SetUIDForPPC(u32 uid) -{ - s_ppc_uid = uid; -} - -u32 GetUIDForPPC() -{ - return s_ppc_uid; -} - -void SetGIDForPPC(u16 gid) -{ - s_ppc_gid = gid; -} - -u16 GetGIDForPPC() -{ - return s_ppc_gid; -} - -// 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) -{ - if (!content_loader.IsValid()) - return false; - - const auto* content = content_loader.GetContentByIndex(content_loader.GetTMD().GetBootIndex()); - if (!content) - return false; - - const auto dol_loader = std::make_unique(content->m_Data->Get()); - if (!dol_loader->IsValid()) - return false; - - if (!SetupMemory(s_active_title_id, MemorySetupType::Full)) - return false; - - dol_loader->Load(); - - // NAND titles start with address translation off at 0x3400 (via the PPC bootstub) - // The state of other CPU registers (like the BAT registers) doesn't matter much - // because the realmode code at 0x3400 initializes everything itself anyway. - MSR = 0; - PC = 0x3400; - - return true; -} - -void SDIO_EventNotify() -{ - // TODO: Potential race condition: If IsRunning() becomes false after - // it's checked, an event may be scheduled after CoreTiming shuts down. - if (SConfig::GetInstance().bWii && Core::IsRunning()) - CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU); -} - -static int GetFreeDeviceID() -{ - for (u32 i = 0; i < IPC_MAX_FDS; i++) - { - if (s_fdmap[i] == nullptr) - { - return i; - } - } - - return -1; -} - -std::shared_ptr GetDeviceByName(const std::string& device_name) -{ - std::lock_guard lock(s_device_map_mutex); - for (const auto& entry : s_device_map) - { - if (entry.second && entry.second->GetDeviceName() == device_name) - { - return entry.second; - } - } - - return nullptr; -} - -std::shared_ptr AccessDeviceByID(u32 id) -{ - std::lock_guard lock(s_device_map_mutex); - if (s_device_map.find(id) != s_device_map.end()) - { - return s_device_map[id]; - } - - return nullptr; -} - -void DoState(PointerWrap& p) -{ - p.Do(s_request_queue); - p.Do(s_reply_queue); - p.Do(s_last_reply_time); - p.Do(s_active_title_id); - p.Do(s_ppc_uid); - p.Do(s_ppc_gid); - - if (s_active_title_id == MIOS_TITLE_ID) - return; - - // We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can - // successfully save or re-create /tmp - for (auto& descriptor : s_fdmap) - { - if (descriptor) - descriptor->PrepareForState(p.GetMode()); - } - - for (const auto& entry : s_device_map) - entry.second->DoState(p); - - if (p.GetMode() == PointerWrap::MODE_READ) - { - for (u32 i = 0; i < IPC_MAX_FDS; i++) - { - u32 exists = 0; - p.Do(exists); - if (exists) - { - auto device_type = Device::Device::DeviceType::Static; - p.Do(device_type); - switch (device_type) - { - case Device::Device::DeviceType::Static: - { - u32 device_id = 0; - p.Do(device_id); - s_fdmap[i] = AccessDeviceByID(device_id); - break; - } - case Device::Device::DeviceType::FileIO: - s_fdmap[i] = std::make_shared(i, ""); - s_fdmap[i]->DoState(p); - break; - case Device::Device::DeviceType::OH0: - s_fdmap[i] = std::make_shared(i, ""); - s_fdmap[i]->DoState(p); - break; - } - } - } - } - else - { - for (auto& descriptor : s_fdmap) - { - u32 exists = descriptor ? 1 : 0; - p.Do(exists); - if (exists) - { - auto device_type = descriptor->GetDeviceType(); - p.Do(device_type); - if (device_type == Device::Device::DeviceType::Static) - { - u32 hwId = descriptor->GetDeviceID(); - p.Do(hwId); - } - else - { - descriptor->DoState(p); - } - } - } - } -} - -// Returns the FD for the newly opened device (on success) or an error code. -static s32 OpenDevice(OpenRequest& request) -{ - const s32 new_fd = GetFreeDeviceID(); - INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd); - if (new_fd < 0 || new_fd >= IPC_MAX_FDS) - { - ERROR_LOG(IOS, "Couldn't get a free fd, too many open files"); - return FS_EFDEXHAUSTED; - } - request.fd = new_fd; - - std::shared_ptr device; - if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path)) - { - device = std::make_shared(new_fd, request.path); - } - else if (request.path.find("/dev/") == 0) - { - device = GetDeviceByName(request.path); - } - else if (request.path.find('/') == 0) - { - device = std::make_shared(new_fd, request.path); - } - - if (!device) - { - ERROR_LOG(IOS, "Unknown device: %s", request.path.c_str()); - return IPC_ENOENT; - } - - const ReturnCode code = device->Open(request); - if (code < IPC_SUCCESS) - return code; - s_fdmap[new_fd] = device; - return new_fd; -} - -static IPCCommandResult HandleCommand(const Request& request) -{ - if (request.command == IPC_CMD_OPEN) - { - OpenRequest open_request{request.address}; - const s32 new_fd = OpenDevice(open_request); - return Device::Device::GetDefaultReply(new_fd); - } - - const auto device = (request.fd < IPC_MAX_FDS) ? s_fdmap[request.fd] : nullptr; - if (!device) - return Device::Device::GetDefaultReply(IPC_EINVAL); - - switch (request.command) - { - case IPC_CMD_CLOSE: - s_fdmap[request.fd].reset(); - return Device::Device::GetDefaultReply(device->Close(request.fd)); - case IPC_CMD_READ: - return device->Read(ReadWriteRequest{request.address}); - case IPC_CMD_WRITE: - return device->Write(ReadWriteRequest{request.address}); - case IPC_CMD_SEEK: - return device->Seek(SeekRequest{request.address}); - case IPC_CMD_IOCTL: - return device->IOCtl(IOCtlRequest{request.address}); - case IPC_CMD_IOCTLV: - return device->IOCtlV(IOCtlVRequest{request.address}); - default: - _assert_msg_(IOS, false, "Unexpected command: %x", request.command); - return Device::Device::GetDefaultReply(IPC_EINVAL); - } -} - -void ExecuteCommand(const u32 address) -{ - Request request{address}; - IPCCommandResult result = HandleCommand(request); - - // Ensure replies happen in order - const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks(); - if (ticks_until_last_reply > 0) - result.reply_delay_ticks += ticks_until_last_reply; - s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks; - - if (result.send_reply) - EnqueueReply(request, result.return_value, static_cast(result.reply_delay_ticks)); -} - -// Happens AS SOON AS IPC gets a new pointer! -void EnqueueRequest(u32 address) -{ - CoreTiming::ScheduleEvent(1000, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG); -} - -// Called to send a reply to an IOS syscall -void EnqueueReply(const Request& request, const s32 return_value, int cycles_in_future, - CoreTiming::FromThread from) -{ - Memory::Write_U32(static_cast(return_value), request.address + 4); - // IOS writes back the command that was responded to in the FD field. - Memory::Write_U32(request.command, request.address + 8); - // IOS also overwrites the command type with the reply type. - Memory::Write_U32(IPC_REPLY, request.address); - CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from); -} - -void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future) -{ - CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, - address | ENQUEUE_ACKNOWLEDGEMENT_FLAG); -} - -// This is called every IPC_HLE_PERIOD from SystemTimers.cpp -// Takes care of routing ipc <-> ipc HLE -void Update() -{ - if (!IsReady()) - return; - - if (s_request_queue.size()) - { - GenerateAck(s_request_queue.front()); - DEBUG_LOG(IOS, "||-- Acknowledge IPC Request @ 0x%08x", s_request_queue.front()); - u32 command = s_request_queue.front(); - s_request_queue.pop_front(); - ExecuteCommand(command); - return; - } - - if (s_reply_queue.size()) - { - GenerateReply(s_reply_queue.front()); - DEBUG_LOG(IOS, "<<-- Reply to IPC Request @ 0x%08x", s_reply_queue.front()); - s_reply_queue.pop_front(); - return; - } - - if (s_ack_queue.size()) - { - GenerateAck(s_ack_queue.front()); - WARN_LOG(IOS, "<<-- Double-ack to IPC Request @ 0x%08x", s_ack_queue.front()); - s_ack_queue.pop_front(); - return; - } -} - -void UpdateDevices() -{ - // Check if a hardware device must be updated - for (const auto& entry : s_device_map) - { - if (entry.second->IsOpened()) - { - entry.second->Update(); - } - } -} - -void UpdateWantDeterminism(const bool new_want_determinism) -{ - WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism); - for (const auto& device : s_device_map) - device.second->UpdateWantDeterminism(new_want_determinism); -} -} // namespace HLE -} // namespace IOS diff --git a/Source/Core/Core/IOS/IPC.h b/Source/Core/Core/IOS/IPC.h deleted file mode 100644 index 0d9e93ad70..0000000000 --- a/Source/Core/Core/IOS/IPC.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Core/CoreTiming.h" -#include "Core/HW/SystemTimers.h" - -class PointerWrap; - -namespace DiscIO -{ -class CNANDContentLoader; -} - -namespace IOS -{ -namespace HLE -{ -namespace Device -{ -class Device; -} - -struct Request; - -struct IPCCommandResult -{ - s32 return_value; - bool send_reply; - u64 reply_delay_ticks; -}; - -enum IPCCommandType : u32 -{ - IPC_CMD_OPEN = 1, - IPC_CMD_CLOSE = 2, - IPC_CMD_READ = 3, - IPC_CMD_WRITE = 4, - IPC_CMD_SEEK = 5, - IPC_CMD_IOCTL = 6, - IPC_CMD_IOCTLV = 7, - // This is used for replies to commands. - IPC_REPLY = 8, -}; - -// Init events and devices -void Init(); -// Shutdown -void Shutdown(); - -// Reload IOS (to a possibly different version); write the new version to 0x3140 and set up devices. -bool Reload(u64 ios_title_id); -u32 GetVersion(); - -void SetUIDForPPC(u32 uid); -u32 GetUIDForPPC(); -void SetGIDForPPC(u16 gid); -u16 GetGIDForPPC(); - -bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader); - -// Do State -void DoState(PointerWrap& p); - -void SDIO_EventNotify(); - -std::shared_ptr GetDeviceByName(const std::string& device_name); -std::shared_ptr AccessDeviceByID(u32 id); - -// Update -void Update(); - -// Update Devices -void UpdateDevices(); - -void UpdateWantDeterminism(bool new_want_determinism); - -void ExecuteCommand(u32 address); - -void EnqueueRequest(u32 address); -void EnqueueReply(const Request& request, s32 return_value, int cycles_in_future = 0, - CoreTiming::FromThread from = CoreTiming::FromThread::CPU); -void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0); -} // namespace HLE -} // namespace IOS diff --git a/Source/Core/Core/IOS/MemoryValues.cpp b/Source/Core/Core/IOS/MemoryValues.cpp new file mode 100644 index 0000000000..2d0bca4626 --- /dev/null +++ b/Source/Core/Core/IOS/MemoryValues.cpp @@ -0,0 +1,329 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/IOS/MemoryValues.h" +#include "Common/CommonTypes.h" + +namespace IOS +{ +namespace HLE +{ +constexpr u32 MEM1_SIZE = 0x01800000; +constexpr u32 MEM1_END = 0x81800000; +constexpr u32 MEM1_ARENA_BEGIN = 0x00000000; +constexpr u32 MEM1_ARENA_END = 0x81800000; +constexpr u32 MEM2_SIZE = 0x4000000; +constexpr u32 MEM2_ARENA_BEGIN = 0x90000800; +constexpr u32 HOLLYWOOD_REVISION = 0x00000011; +constexpr u32 PLACEHOLDER = 0xDEADBEEF; +constexpr u32 RAM_VENDOR = 0x0000FF01; +constexpr u32 RAM_VENDOR_MIOS = 0xCAFEBABE; + +// These values were manually extracted from the relevant IOS binaries. +// The writes are usually contained in a single function that +// mostly writes raw literals to the relevant locations. +// e.g. IOS9, version 1034, content id 0x00000006, function at 0xffff6884 +constexpr std::array ios_memory_values = { + {{ + 9, 0x9040a, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 11, 0xb000a, 0x102506, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 12, 0xc020e, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 13, 0xd0408, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 14, 0xe0408, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 15, 0xf0408, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 17, 0x110408, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 20, 0x14000c, 0x102506, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 21, 0x15040f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 22, 0x16050e, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN, + 0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION, + RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0, + }, + { + 28, 0x1c070f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN, + 0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93800000, 0x93820000, 0, + }, + { + 30, 0x1e0a10, 0x40308, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 31, 0x1f0e18, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 33, 0x210e18, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 34, 0x220e18, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 35, 0x230e18, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 36, 0x240e18, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 37, 0x25161f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 38, 0x26101c, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 40, 0x280911, 0x022308, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 41, 0x290e17, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 43, 0x2b0e17, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 45, 0x2d0e17, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 46, 0x2e0e17, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 48, 0x30101c, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 50, 0x321319, 0x101008, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 51, 0x331219, 0x071108, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 52, 0x34161d, 0x101008, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 53, 0x35161f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 55, 0x37161f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 56, 0x38161e, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 57, 0x39171f, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 58, 0x3a1820, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 59, 0x3b1c21, 0x101811, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 60, 0x3c181e, 0x112408, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 61, 0x3d161e, 0x030110, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 62, 0x3e191e, 0x022712, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 70, 0x461a1f, 0x060309, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 80, 0x501b20, 0x030310, MEM1_SIZE, + MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END, + MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN, + 0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION, + RAM_VENDOR, 0x93600000, 0x93620000, 0, + }, + { + 257, + 0x707, + 0x82209, + MEM1_SIZE, + MEM1_SIZE, + MEM1_END, + MEM1_ARENA_BEGIN, + MEM1_ARENA_END, + MEM2_SIZE, + MEM2_SIZE, + 0x93600000, + MEM2_ARENA_BEGIN, + 0x935E0000, + 0x935E0000, + 0x93600000, + HOLLYWOOD_REVISION, + RAM_VENDOR_MIOS, + PLACEHOLDER, + PLACEHOLDER, + PLACEHOLDER, + }}}; + +const std::array& GetMemoryValues() +{ + return ios_memory_values; +} +} +} diff --git a/Source/Core/Core/IOS/MemoryValues.h b/Source/Core/Core/IOS/MemoryValues.h new file mode 100644 index 0000000000..f2478a9d8a --- /dev/null +++ b/Source/Core/Core/IOS/MemoryValues.h @@ -0,0 +1,41 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" + +namespace IOS +{ +namespace HLE +{ +struct MemoryValues +{ + u16 ios_number; + u32 ios_version; + u32 ios_date; + u32 mem1_physical_size; + u32 mem1_simulated_size; + u32 mem1_end; + u32 mem1_arena_begin; + u32 mem1_arena_end; + u32 mem2_physical_size; + u32 mem2_simulated_size; + u32 mem2_end; + u32 mem2_arena_begin; + u32 mem2_arena_end; + u32 ipc_buffer_begin; + u32 ipc_buffer_end; + u32 hollywood_revision; + u32 ram_vendor; + u32 unknown_begin; + u32 unknown_end; + u32 sysmenu_sync; +}; + +const std::array& GetMemoryValues(); +} +} diff --git a/Source/Core/Core/IOS/Network/IP/Top.cpp b/Source/Core/Core/IOS/Network/IP/Top.cpp index 30288e229b..91e4d81526 100644 --- a/Source/Core/Core/IOS/Network/IP/Top.cpp +++ b/Source/Core/Core/IOS/Network/IP/Top.cpp @@ -61,7 +61,7 @@ namespace HLE { namespace Device { -NetIPTop::NetIPTop(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +NetIPTop::NetIPTop(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { #ifdef _WIN32 int ret = WSAStartup(MAKEWORD(2, 2), &InitData); diff --git a/Source/Core/Core/IOS/Network/IP/Top.h b/Source/Core/Core/IOS/Network/IP/Top.h index 24b9d4ee5e..7d531d3d3c 100644 --- a/Source/Core/Core/IOS/Network/IP/Top.h +++ b/Source/Core/Core/IOS/Network/IP/Top.h @@ -61,7 +61,7 @@ namespace Device class NetIPTop : public Device { public: - NetIPTop(u32 device_id, const std::string& device_name); + NetIPTop(Kernel& ios, const std::string& device_name); virtual ~NetIPTop(); IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp index 0feb9e1393..48c9e27da0 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp @@ -24,8 +24,7 @@ namespace HLE { namespace Device { -NetKDRequest::NetKDRequest(u32 device_id, const std::string& device_name) - : Device(device_id, device_name) +NetKDRequest::NetKDRequest(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.h b/Source/Core/Core/IOS/Network/KD/NetKDRequest.h index eeb7c48b31..f35c71bf9e 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.h +++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.h @@ -22,7 +22,7 @@ namespace Device class NetKDRequest : public Device { public: - NetKDRequest(u32 device_id, const std::string& device_name); + NetKDRequest(Kernel& ios, const std::string& device_name); ~NetKDRequest() override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp b/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp index a6ce019448..a9f0be3132 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp +++ b/Source/Core/Core/IOS/Network/KD/NetKDTime.cpp @@ -16,7 +16,7 @@ namespace HLE { namespace Device { -NetKDTime::NetKDTime(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +NetKDTime::NetKDTime(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/Network/KD/NetKDTime.h b/Source/Core/Core/IOS/Network/KD/NetKDTime.h index 04cce2d68f..be22e1e3a8 100644 --- a/Source/Core/Core/IOS/Network/KD/NetKDTime.h +++ b/Source/Core/Core/IOS/Network/KD/NetKDTime.h @@ -18,7 +18,7 @@ namespace Device class NetKDTime : public Device { public: - NetKDTime(u32 device_id, const std::string& device_name); + NetKDTime(Kernel& ios, const std::string& device_name); ~NetKDTime() override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/IOS/Network/NCD/Manage.cpp b/Source/Core/Core/IOS/Network/NCD/Manage.cpp index da6ef5978f..410c3bc863 100644 --- a/Source/Core/Core/IOS/Network/NCD/Manage.cpp +++ b/Source/Core/Core/IOS/Network/NCD/Manage.cpp @@ -19,8 +19,7 @@ namespace HLE { namespace Device { -NetNCDManage::NetNCDManage(u32 device_id, const std::string& device_name) - : Device(device_id, device_name) +NetNCDManage::NetNCDManage(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/Network/NCD/Manage.h b/Source/Core/Core/IOS/Network/NCD/Manage.h index fbf5df4ac3..c4ce453697 100644 --- a/Source/Core/Core/IOS/Network/NCD/Manage.h +++ b/Source/Core/Core/IOS/Network/NCD/Manage.h @@ -20,7 +20,7 @@ namespace Device class NetNCDManage : public Device { public: - NetNCDManage(u32 device_id, const std::string& device_name); + NetNCDManage(Kernel& ios, const std::string& device_name); IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp index 21e67b41f8..ca3160bee8 100644 --- a/Source/Core/Core/IOS/Network/SSL.cpp +++ b/Source/Core/Core/IOS/Network/SSL.cpp @@ -37,7 +37,7 @@ static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = { 0, /* No RSA min key size */ }; -NetSSL::NetSSL(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { for (WII_SSL& ssl : _SSL) { diff --git a/Source/Core/Core/IOS/Network/SSL.h b/Source/Core/Core/IOS/Network/SSL.h index 91a41600e0..f1f9f4c611 100644 --- a/Source/Core/Core/IOS/Network/SSL.h +++ b/Source/Core/Core/IOS/Network/SSL.h @@ -19,7 +19,7 @@ // clang-format on #include "Common/CommonTypes.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/Device.h" namespace IOS @@ -90,7 +90,7 @@ namespace Device class NetSSL : public Device { public: - NetSSL(u32 device_id, const std::string& device_name); + NetSSL(Kernel& ios, const std::string& device_name); virtual ~NetSSL(); diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp index caf67861ca..3765e3bd75 100644 --- a/Source/Core/Core/IOS/Network/Socket.cpp +++ b/Source/Core/Core/IOS/Network/Socket.cpp @@ -16,7 +16,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/Network/Socket.h" // No Wii socket support while using NetPlay or TAS #ifdef _WIN32 @@ -579,7 +579,8 @@ void WiiSocket::Update(bool read, bool write, bool except) it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock, forceNonBlock); - EnqueueReply(it->request, ReturnValue); + // TODO: remove the dependency on a running IOS instance. + GetIOS()->EnqueueIPCReply(it->request, ReturnValue); it = pending_sockops.erase(it); } else diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h index acacf48c82..de9d4b4761 100644 --- a/Source/Core/Core/IOS/Network/Socket.h +++ b/Source/Core/Core/IOS/Network/Socket.h @@ -52,7 +52,7 @@ typedef struct pollfd pollfd_t; #include "Common/Logging/Log.h" #include "Common/NonCopyable.h" #include "Core/HW/Memmap.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/Network/IP/Top.h" #include "Core/IOS/Network/SSL.h" @@ -234,7 +234,7 @@ public: { ERROR_LOG(IOS_NET, "DoSock: Error, fd not found (%08x, %08X, %08X)", sock, request.address, type); - EnqueueReply(request, -SO_EBADF); + GetIOS()->EnqueueIPCReply(request, -SO_EBADF); } else { diff --git a/Source/Core/Core/IOS/Network/WD/Command.cpp b/Source/Core/Core/IOS/Network/WD/Command.cpp index 3cbbcf9296..9de91a1291 100644 --- a/Source/Core/Core/IOS/Network/WD/Command.cpp +++ b/Source/Core/Core/IOS/Network/WD/Command.cpp @@ -21,8 +21,7 @@ namespace HLE { namespace Device { -NetWDCommand::NetWDCommand(u32 device_id, const std::string& device_name) - : Device(device_id, device_name) +NetWDCommand::NetWDCommand(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/Network/WD/Command.h b/Source/Core/Core/IOS/Network/WD/Command.h index 3b0decc48a..0c9ac96d68 100644 --- a/Source/Core/Core/IOS/Network/WD/Command.h +++ b/Source/Core/Core/IOS/Network/WD/Command.h @@ -18,7 +18,7 @@ namespace Device class NetWDCommand : public Device { public: - NetWDCommand(u32 device_id, const std::string& device_name); + NetWDCommand(Kernel& ios, const std::string& device_name); IPCCommandResult IOCtlV(const IOCtlVRequest& request) override; diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp index 4987fae39b..3884baefdb 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp @@ -14,7 +14,7 @@ #include "Common/SDCardUtil.h" #include "Core/ConfigManager.h" #include "Core/HW/Memmap.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/SDIO/SDIOSlot0.h" namespace IOS @@ -23,7 +23,7 @@ namespace HLE { namespace Device { -SDIOSlot0::SDIOSlot0(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +SDIOSlot0::SDIOSlot0(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } @@ -49,7 +49,7 @@ void SDIOSlot0::EventNotify() if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) || (!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE)) { - EnqueueReply(m_event->request, m_event->type); + m_ios.EnqueueIPCReply(m_event->request, m_event->type); m_event.reset(); } } @@ -302,7 +302,7 @@ u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _Buffer // release returns 0 // unknown sd int // technically we do it out of order, oh well - EnqueueReply(m_event->request, EVENT_INVALID); + m_ios.EnqueueIPCReply(m_event->request, EVENT_INVALID); m_event.reset(); break; } diff --git a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h index 116625f29b..55bfabf8da 100644 --- a/Source/Core/Core/IOS/SDIO/SDIOSlot0.h +++ b/Source/Core/Core/IOS/SDIO/SDIOSlot0.h @@ -12,7 +12,7 @@ #include "Common/CommonTypes.h" #include "Common/FileUtil.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -26,7 +26,7 @@ namespace Device class SDIOSlot0 : public Device { public: - SDIOSlot0(u32 device_id, const std::string& device_name); + SDIOSlot0(Kernel& ios, const std::string& device_name); void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/STM/STM.cpp b/Source/Core/Core/IOS/STM/STM.cpp index aece7e39fa..b9c02c1f79 100644 --- a/Source/Core/Core/IOS/STM/STM.cpp +++ b/Source/Core/Core/IOS/STM/STM.cpp @@ -39,7 +39,7 @@ IPCCommandResult STMImmediate::IOCtl(const IOCtlRequest& request) break; } Memory::Write_U32(0, s_event_hook_request->buffer_out); - EnqueueReply(*s_event_hook_request, IPC_SUCCESS); + m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS); s_event_hook_request.reset(); break; @@ -109,7 +109,7 @@ void STMEventHook::TriggerEvent(const u32 event) const return; Memory::Write_U32(event, s_event_hook_request->buffer_out); - EnqueueReply(*s_event_hook_request, IPC_SUCCESS); + m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS); s_event_hook_request.reset(); } diff --git a/Source/Core/Core/IOS/STM/STM.h b/Source/Core/Core/IOS/STM/STM.h index 6721e3c28c..e8249ba6b6 100644 --- a/Source/Core/Core/IOS/STM/STM.h +++ b/Source/Core/Core/IOS/STM/STM.h @@ -8,7 +8,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; @@ -46,7 +46,7 @@ namespace Device class STMImmediate final : public Device { public: - STMImmediate(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {} + using Device::Device; IPCCommandResult IOCtl(const IOCtlRequest& request) override; }; @@ -54,7 +54,7 @@ public: class STMEventHook final : public Device { public: - STMEventHook(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {} + using Device::Device; ReturnCode Close(u32 fd) override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTBase.h b/Source/Core/Core/IOS/USB/Bluetooth/BTBase.h index 55eee82b22..6fd3341122 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTBase.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTBase.h @@ -9,7 +9,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" class PointerWrap; class SysConf; @@ -26,7 +26,7 @@ namespace Device class BluetoothBase : public Device { public: - BluetoothBase(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {} + using Device::Device; virtual void UpdateSyncButtonState(bool is_held) {} virtual void TriggerSyncButtonPressedEvent() {} virtual void TriggerSyncButtonHeldEvent() {} diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp index bf6c1c15d6..c0c9379979 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp @@ -23,7 +23,7 @@ #include "Core/HW/Wiimote.h" #include "Core/Host.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTEmu.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" @@ -39,8 +39,8 @@ SQueuedEvent::SQueuedEvent(u32 size, u16 handle) : m_size(size), m_connectionHan namespace Device { -BluetoothEmu::BluetoothEmu(u32 device_id, const std::string& device_name) - : BluetoothBase(device_id, device_name) +BluetoothEmu::BluetoothEmu(Kernel& ios, const std::string& device_name) + : BluetoothBase(ios, device_name) { SysConf sysconf{Core::WantsDeterminism() ? Common::FromWhichRoot::FROM_SESSION_ROOT : Common::FromWhichRoot::FROM_CONFIGURED_ROOT}; @@ -105,14 +105,14 @@ BluetoothEmu::~BluetoothEmu() } template -static void DoStateForMessage(PointerWrap& p, std::unique_ptr& message) +static void DoStateForMessage(Kernel& ios, PointerWrap& p, std::unique_ptr& message) { u32 request_address = (message != nullptr) ? message->ios_request.address : 0; p.Do(request_address); if (request_address != 0) { IOCtlVRequest request{request_address}; - message = std::make_unique(request); + message = std::make_unique(ios, request); } } @@ -129,9 +129,9 @@ void BluetoothEmu::DoState(PointerWrap& p) p.Do(m_is_active); p.Do(m_ControllerBD); - DoStateForMessage(p, m_CtrlSetup); - DoStateForMessage(p, m_HCIEndpoint); - DoStateForMessage(p, m_ACLEndpoint); + DoStateForMessage(m_ios, p, m_CtrlSetup); + DoStateForMessage(m_ios, p, m_HCIEndpoint); + DoStateForMessage(m_ios, p, m_ACLEndpoint); p.Do(m_last_ticks); p.DoArray(m_PacketCount); p.Do(m_ScanEnable); @@ -166,7 +166,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) { case USB::IOCTLV_USBV0_CTRLMSG: // HCI command is received from the stack { - m_CtrlSetup = std::make_unique(request); + m_CtrlSetup = std::make_unique(m_ios, request); // Replies are generated inside ExecuteHCICommandMessage(*m_CtrlSetup); m_CtrlSetup.reset(); @@ -176,7 +176,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) case USB::IOCTLV_USBV0_BLKMSG: { - const USB::V0BulkMessage ctrl{request}; + const USB::V0BulkMessage ctrl{m_ios, request}; switch (ctrl.endpoint) { case ACL_DATA_OUT: // ACL data is received from the stack @@ -195,7 +195,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) } case ACL_DATA_IN: // We are given an ACL buffer to fill { - m_ACLEndpoint = std::make_unique(request); + m_ACLEndpoint = std::make_unique(m_ios, request); DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address); send_reply = false; break; @@ -208,10 +208,10 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request) case USB::IOCTLV_USBV0_INTRMSG: { - const USB::V0IntrMessage ctrl{request}; + const USB::V0IntrMessage ctrl{m_ios, request}; if (ctrl.endpoint == HCI_EVENT) // We are given a HCI buffer to fill { - m_HCIEndpoint = std::make_unique(request); + m_HCIEndpoint = std::make_unique(m_ios, request); DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address); send_reply = false; } @@ -265,7 +265,7 @@ void BluetoothEmu::SendACLPacket(u16 connection_handle, const u8* data, u32 size // Write the packet to the buffer memcpy(reinterpret_cast(header) + sizeof(hci_acldata_hdr_t), data, header->length); - EnqueueReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size); + m_ios.EnqueueIPCReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size); m_ACLEndpoint.reset(); } else @@ -293,7 +293,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event) m_HCIEndpoint->FillBuffer(_event.m_buffer, _event.m_size); // Send a reply to indicate HCI buffer is filled - EnqueueReply(m_HCIEndpoint->ios_request, _event.m_size); + m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, _event.m_size); m_HCIEndpoint.reset(); } else // push new one, pop oldest @@ -309,7 +309,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event) m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size); // Send a reply to indicate HCI buffer is filled - EnqueueReply(m_HCIEndpoint->ios_request, event.m_size); + m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size); m_HCIEndpoint.reset(); m_EventQueue.pop_front(); } @@ -335,7 +335,7 @@ void BluetoothEmu::Update() m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size); // Send a reply to indicate HCI buffer is filled - EnqueueReply(m_HCIEndpoint->ios_request, event.m_size); + m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size); m_HCIEndpoint.reset(); m_EventQueue.pop_front(); } @@ -430,7 +430,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(USB::V0BulkMessage& endpoint) m_queue.pop_front(); - EnqueueReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size); + m_ios.EnqueueIPCReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size); } bool BluetoothEmu::SendEventInquiryComplete() @@ -1141,7 +1141,7 @@ void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_messa } // HCI command is finished, send a reply to command - EnqueueReply(ctrl_message.ios_request, ctrl_message.length); + m_ios.EnqueueIPCReply(ctrl_message.ios_request, ctrl_message.length); } // diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h index efb60cf10d..b39e712710 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTEmu.h @@ -14,7 +14,7 @@ #include "Common/CommonTypes.h" #include "Core/HW/Wiimote.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTBase.h" #include "Core/IOS/USB/Bluetooth/WiimoteDevice.h" #include "Core/IOS/USB/Bluetooth/hci.h" @@ -45,7 +45,7 @@ namespace Device class BluetoothEmu final : public BluetoothBase { public: - BluetoothEmu(u32 device_id, const std::string& device_name); + BluetoothEmu(Kernel& ios, const std::string& device_name); virtual ~BluetoothEmu(); @@ -78,17 +78,8 @@ private: class ACLPool { - struct Packet - { - u8 data[ACL_PKT_SIZE]; - u16 size; - u16 conn_handle; - }; - - std::deque m_queue; - public: - ACLPool() : m_queue() {} + explicit ACLPool(Kernel& ios) : m_ios(ios), m_queue() {} void Store(const u8* data, const u16 size, const u16 conn_handle); void WriteToEndpoint(USB::V0BulkMessage& endpoint); @@ -96,7 +87,17 @@ private: bool IsEmpty() const { return m_queue.empty(); } // For SaveStates void DoState(PointerWrap& p) { p.Do(m_queue); } - } m_acl_pool; + private: + struct Packet + { + u8 data[ACL_PKT_SIZE]; + u16 size; + u16 conn_handle; + }; + + Kernel& m_ios; + std::deque m_queue; + } m_acl_pool{m_ios}; u32 m_PacketCount[MAX_BBMOTES] = {}; u64 m_last_ticks = 0; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp index 25633158c1..a23c236ab8 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp @@ -56,8 +56,8 @@ static bool IsBluetoothDevice(const libusb_interface_descriptor& descriptor) namespace Device { -BluetoothReal::BluetoothReal(u32 device_id, const std::string& device_name) - : BluetoothBase(device_id, device_name) +BluetoothReal::BluetoothReal(Kernel& ios, const std::string& device_name) + : BluetoothBase(ios, device_name) { const int ret = libusb_init(&m_libusb_context); if (ret < 0) @@ -179,7 +179,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request) case USB::IOCTLV_USBV0_CTRLMSG: { std::lock_guard lk(m_transfers_mutex); - auto cmd = std::make_unique(request); + auto cmd = std::make_unique(m_ios, request); const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address)); if (opcode == HCI_CMD_READ_BUFFER_SIZE) { @@ -228,7 +228,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request) case USB::IOCTLV_USBV0_INTRMSG: { std::lock_guard lk(m_transfers_mutex); - auto cmd = std::make_unique(request); + auto cmd = std::make_unique(m_ios, request); if (request.request == USB::IOCTLV_USBV0_INTRMSG) { if (m_sync_button_state == SyncButtonState::Pressed) @@ -310,7 +310,7 @@ void BluetoothReal::DoState(PointerWrap& p) // waiting for the previous request to complete. This is usually not an issue as long as // the Bluetooth state is the same (same Wii remote connections). for (const auto& address_to_discard : addresses_to_discard) - EnqueueReply(Request{address_to_discard}, 0); + m_ios.EnqueueIPCReply(Request{address_to_discard}, 0); // Prevent the callbacks from replying to a request that has already been discarded. m_current_transfers.clear(); @@ -452,7 +452,7 @@ void BluetoothReal::FakeVendorCommandReply(USB::V0IntrMessage& ctrl) hci_event.PacketIndicator = 0x01; hci_event.Opcode = m_fake_vendor_command_reply_opcode; Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event)); - EnqueueReply(ctrl.ios_request, static_cast(sizeof(hci_event))); + m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast(sizeof(hci_event))); } // Due to how the widcomm stack which Nintendo uses is coded, we must never @@ -477,7 +477,7 @@ void BluetoothReal::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl) reply.max_sco_size = SCO_PKT_SIZE; reply.num_sco_pkts = SCO_PKT_NUM; Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply)); - EnqueueReply(ctrl.ios_request, static_cast(sizeof(hci_event) + sizeof(reply))); + m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast(sizeof(hci_event) + sizeof(reply))); } void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, const u8 size) @@ -488,7 +488,7 @@ void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payl hci_event.length = size; Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event)); Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size); - EnqueueReply(ctrl.ios_request, static_cast(sizeof(hci_event) + size)); + m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast(sizeof(hci_event) + size)); } // When the red sync button is pressed, a HCI event is generated: @@ -638,7 +638,8 @@ void BluetoothReal::HandleCtrlTransfer(libusb_transfer* tr) } const auto& command = m_current_transfers.at(tr).command; command->FillBuffer(libusb_control_transfer_get_data(tr), tr->actual_length); - EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU); + m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0, + CoreTiming::FromThread::NON_CPU); m_current_transfers.erase(tr); } @@ -688,7 +689,8 @@ void BluetoothReal::HandleBulkOrIntrTransfer(libusb_transfer* tr) const auto& command = m_current_transfers.at(tr).command; command->FillBuffer(tr->buffer, tr->actual_length); - EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU); + m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0, + CoreTiming::FromThread::NON_CPU); m_current_transfers.erase(tr); } } // namespace Device diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h index 3acc462fc0..8b0fbf91da 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTReal.h @@ -16,7 +16,7 @@ #include "Common/CommonTypes.h" #include "Common/Flag.h" #include "Common/Timer.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTBase.h" #include "Core/IOS/USB/USBV0.h" @@ -48,7 +48,7 @@ namespace Device class BluetoothReal final : public BluetoothBase { public: - BluetoothReal(u32 device_id, const std::string& device_name); + BluetoothReal(Kernel& ios, const std::string& device_name); ~BluetoothReal() override; ReturnCode Open(const OpenRequest& request) override; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/BTStub.h b/Source/Core/Core/IOS/USB/Bluetooth/BTStub.h index 601d0c146f..9a69a556e8 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/BTStub.h +++ b/Source/Core/Core/IOS/USB/Bluetooth/BTStub.h @@ -7,7 +7,7 @@ #include #include "Common/CommonTypes.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTBase.h" class PointerWrap; @@ -21,10 +21,7 @@ namespace Device class BluetoothStub final : public BluetoothBase { public: - BluetoothStub(const u32 device_id, const std::string& device_name) - : BluetoothBase(device_id, device_name) - { - } + using BluetoothBase::BluetoothBase; ReturnCode Open(const OpenRequest& request) override; void DoState(PointerWrap& p) override; }; diff --git a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp index d374ba7451..4e8d935fcb 100644 --- a/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp +++ b/Source/Core/Core/IOS/USB/Bluetooth/WiimoteDevice.cpp @@ -932,7 +932,7 @@ void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _ DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID); const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); + IOS::HLE::GetIOS()->GetDeviceByName("/dev/usb/oh1/57e/305")); if (bt) bt->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size); } diff --git a/Source/Core/Core/IOS/USB/Common.cpp b/Source/Core/Core/IOS/USB/Common.cpp index b8fecd5faf..a9627b0974 100644 --- a/Source/Core/Core/IOS/USB/Common.cpp +++ b/Source/Core/Core/IOS/USB/Common.cpp @@ -33,6 +33,11 @@ void TransferCommand::FillBuffer(const u8* src, const size_t size) const Memory::CopyToEmu(data_address, src, size); } +void TransferCommand::OnTransferComplete(s32 return_value) const +{ + m_ios.EnqueueIPCReply(ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU); +} + void IsoMessage::SetPacketReturnValue(const size_t packet_num, const u16 return_value) const { Memory::Write_U16(return_value, static_cast(packet_sizes_addr + packet_num * sizeof(u16))); diff --git a/Source/Core/Core/IOS/USB/Common.h b/Source/Core/Core/IOS/USB/Common.h index 6c9bb13913..9efb6630a1 100644 --- a/Source/Core/Core/IOS/USB/Common.h +++ b/Source/Core/Core/IOS/USB/Common.h @@ -100,15 +100,19 @@ struct TransferCommand Request ios_request; u32 data_address = 0; - TransferCommand(const Request& ios_request_, u32 data_address_) - : ios_request(ios_request_), data_address(data_address_) + TransferCommand(Kernel& ios, const Request& ios_request_, u32 data_address_) + : ios_request(ios_request_), data_address(data_address_), m_ios(ios) { } virtual ~TransferCommand() = default; - // Called after a transfer has completed and before replying to the transfer request. - virtual void OnTransferComplete() const {} + // Called after a transfer has completed to reply to the IPC request. + // This can be overridden for additional processing before replying. + virtual void OnTransferComplete(s32 return_value) const; std::unique_ptr MakeBuffer(size_t size) const; void FillBuffer(const u8* src, size_t size) const; + +private: + Kernel& m_ios; }; struct CtrlMessage : TransferCommand diff --git a/Source/Core/Core/IOS/USB/Host.cpp b/Source/Core/Core/IOS/USB/Host.cpp index 846bb2c645..e440494460 100644 --- a/Source/Core/Core/IOS/USB/Host.cpp +++ b/Source/Core/Core/IOS/USB/Host.cpp @@ -27,7 +27,7 @@ namespace HLE { namespace Device { -USBHost::USBHost(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { #ifdef __LIBUSB__ const int ret = libusb_init(&m_libusb_context); @@ -150,7 +150,7 @@ bool USBHost::AddNewDevices(std::set& new_devices, DeviceChangeHooks& hooks continue; } - auto usb_device = std::make_unique(device, descriptor); + auto usb_device = std::make_unique(m_ios, device, descriptor); if (!ShouldAddDevice(*usb_device)) { libusb_unref_device(device); diff --git a/Source/Core/Core/IOS/USB/Host.h b/Source/Core/Core/IOS/USB/Host.h index 3bdcb2445b..a595743394 100644 --- a/Source/Core/Core/IOS/USB/Host.h +++ b/Source/Core/Core/IOS/USB/Host.h @@ -17,7 +17,7 @@ #include "Common/CommonTypes.h" #include "Common/Flag.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Common.h" class PointerWrap; @@ -33,7 +33,7 @@ namespace Device class USBHost : public Device { public: - USBHost(u32 device_id, const std::string& device_name); + USBHost(Kernel& ios, const std::string& device_name); virtual ~USBHost(); ReturnCode Open(const OpenRequest& request) override; diff --git a/Source/Core/Core/IOS/USB/LibusbDevice.cpp b/Source/Core/Core/IOS/USB/LibusbDevice.cpp index 69b51e3fba..9b57062336 100644 --- a/Source/Core/Core/IOS/USB/LibusbDevice.cpp +++ b/Source/Core/Core/IOS/USB/LibusbDevice.cpp @@ -15,7 +15,7 @@ #include "Core/CoreTiming.h" #include "Core/HW/Memmap.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/LibusbDevice.h" namespace IOS @@ -24,8 +24,9 @@ namespace HLE { namespace USB { -LibusbDevice::LibusbDevice(libusb_device* device, const libusb_device_descriptor& descriptor) - : m_device(device) +LibusbDevice::LibusbDevice(Kernel& ios, libusb_device* device, + const libusb_device_descriptor& descriptor) + : m_ios(ios), m_device(device) { libusb_ref_device(m_device); m_vid = descriptor.idVendor; @@ -200,14 +201,14 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr cmd) } const int ret = SetAltSetting(static_cast(cmd->value)); if (ret == 0) - EnqueueReply(cmd->ios_request, cmd->length); + m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); return ret; } case USBHDR(DIR_HOST2DEVICE, TYPE_STANDARD, REC_DEVICE, REQUEST_SET_CONFIGURATION): { const int ret = libusb_set_configuration(m_handle, cmd->value); if (ret == 0) - EnqueueReply(cmd->ios_request, cmd->length); + m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length); return ret; } } @@ -355,8 +356,7 @@ void LibusbDevice::TransferEndpoint::HandleTransfer(libusb_transfer* transfer, return_value = IPC_ENOENT; break; } - cmd.OnTransferComplete(); - EnqueueReply(cmd.ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU); + cmd.OnTransferComplete(return_value); m_transfers.erase(transfer); } diff --git a/Source/Core/Core/IOS/USB/LibusbDevice.h b/Source/Core/Core/IOS/USB/LibusbDevice.h index 331aae2593..54b5a19577 100644 --- a/Source/Core/Core/IOS/USB/LibusbDevice.h +++ b/Source/Core/Core/IOS/USB/LibusbDevice.h @@ -43,7 +43,8 @@ private: class LibusbDevice final : public Device { public: - LibusbDevice(libusb_device* device, const libusb_device_descriptor& device_descriptor); + LibusbDevice(Kernel& ios, libusb_device* device, + const libusb_device_descriptor& device_descriptor); ~LibusbDevice(); DeviceDescriptor GetDeviceDescriptor() const override; std::vector GetConfigurations() const override; @@ -61,6 +62,8 @@ public: int SubmitTransfer(std::unique_ptr message) override; private: + Kernel& m_ios; + std::vector> m_config_descriptors; u16 m_vid = 0; u16 m_pid = 0; diff --git a/Source/Core/Core/IOS/USB/OH0/OH0.cpp b/Source/Core/Core/IOS/USB/OH0/OH0.cpp index 3a9ec8d97e..85760299bd 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0.cpp @@ -25,7 +25,7 @@ namespace HLE { namespace Device { -OH0::OH0(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name) +OH0::OH0(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name) { } @@ -36,7 +36,7 @@ OH0::~OH0() ReturnCode OH0::Open(const OpenRequest& request) { - const u32 ios_major_version = GetVersion(); + const u32 ios_major_version = m_ios.GetVersion(); if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59) return IPC_EACCES; return USBHost::Open(request); @@ -240,7 +240,7 @@ void OH0::TriggerHook(std::map& hooks, T value, const ReturnCode return_ const auto hook = hooks.find(value); if (hook == hooks.end()) return; - EnqueueReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY); + m_ios.EnqueueIPCReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY); hooks.erase(hook); } @@ -325,26 +325,26 @@ s32 OH0::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv) if (!ioctlv.HasNumberOfValidVectors(6, 1) || Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size) return IPC_EINVAL; - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); case USB::IOCTLV_USBV0_BLKMSG: case USB::IOCTLV_USBV0_LBLKMSG: if (!ioctlv.HasNumberOfValidVectors(2, 1) || Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size) return IPC_EINVAL; - return device.SubmitTransfer( - std::make_unique(ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG)); + return device.SubmitTransfer(std::make_unique( + m_ios, ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG)); case USB::IOCTLV_USBV0_INTRMSG: if (!ioctlv.HasNumberOfValidVectors(2, 1) || Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size) return IPC_EINVAL; - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); case USB::IOCTLV_USBV0_ISOMSG: if (!ioctlv.HasNumberOfValidVectors(3, 2)) return IPC_EINVAL; - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); default: return IPC_EINVAL; diff --git a/Source/Core/Core/IOS/USB/OH0/OH0.h b/Source/Core/Core/IOS/USB/OH0/OH0.h index df732a8c09..90eb2d6d80 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0.h +++ b/Source/Core/Core/IOS/USB/OH0/OH0.h @@ -38,7 +38,7 @@ namespace Device class OH0 final : public USBHost { public: - OH0(u32 device_id, const std::string& device_name); + OH0(Kernel& ios, const std::string& device_name); ~OH0() override; ReturnCode Open(const OpenRequest& request) override; diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index 03b3e7da2c..390a266e41 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -7,7 +7,7 @@ #include #include "Common/ChunkFile.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/OH0/OH0.h" #include "Core/IOS/USB/OH0/OH0Device.h" @@ -37,7 +37,7 @@ static void GetVidPidFromDevicePath(const std::string& device_path, u16& vid, u1 ss >> pid; } -OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceType::OH0) +OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, DeviceType::OH0) { if (!name.empty()) GetVidPidFromDevicePath(name, m_vid, m_pid); @@ -45,7 +45,7 @@ OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceT void OH0Device::DoState(PointerWrap& p) { - m_oh0 = std::static_pointer_cast(GetDeviceByName("/dev/usb/oh0")); + m_oh0 = std::static_pointer_cast(m_ios.GetDeviceByName("/dev/usb/oh0")); p.Do(m_name); p.Do(m_vid); p.Do(m_pid); @@ -54,14 +54,14 @@ void OH0Device::DoState(PointerWrap& p) ReturnCode OH0Device::Open(const OpenRequest& request) { - const u32 ios_major_version = GetVersion(); + const u32 ios_major_version = m_ios.GetVersion(); if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59) return IPC_ENOENT; if (m_vid == 0 && m_pid == 0) return IPC_ENOENT; - m_oh0 = std::static_pointer_cast(GetDeviceByName("/dev/usb/oh0")); + m_oh0 = std::static_pointer_cast(m_ios.GetDeviceByName("/dev/usb/oh0")); ReturnCode return_code; std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid); diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.h b/Source/Core/Core/IOS/USB/OH0/OH0Device.h index c66ccc4b2f..a7b193ad25 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.h +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.h @@ -22,7 +22,7 @@ class OH0; class OH0Device final : public Device { public: - OH0Device(u32 device_id, const std::string& device_name); + OH0Device(Kernel& ios, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; ReturnCode Close(u32 fd) override; diff --git a/Source/Core/Core/IOS/USB/USBV0.cpp b/Source/Core/Core/IOS/USB/USBV0.cpp index 3f9e276e4f..da195f2463 100644 --- a/Source/Core/Core/IOS/USB/USBV0.cpp +++ b/Source/Core/Core/IOS/USB/USBV0.cpp @@ -17,8 +17,8 @@ namespace HLE { namespace USB { -V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv) - : CtrlMessage(ioctlv, ioctlv.io_vectors[0].address) +V0CtrlMessage::V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : CtrlMessage(ios, ioctlv, ioctlv.io_vectors[0].address) { request_type = Memory::Read_U8(ioctlv.in_vectors[0].address); request = Memory::Read_U8(ioctlv.in_vectors[1].address); @@ -27,8 +27,8 @@ V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv) length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address)); } -V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length) - : BulkMessage(ioctlv, ioctlv.io_vectors[0].address) +V0BulkMessage::V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length) + : BulkMessage(ios, ioctlv, ioctlv.io_vectors[0].address) { endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address); if (long_length) @@ -37,15 +37,15 @@ V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length) length = Memory::Read_U16(ioctlv.in_vectors[1].address); } -V0IntrMessage::V0IntrMessage(const IOCtlVRequest& ioctlv) - : IntrMessage(ioctlv, ioctlv.io_vectors[0].address) +V0IntrMessage::V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : IntrMessage(ios, ioctlv, ioctlv.io_vectors[0].address) { endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address); length = Memory::Read_U16(ioctlv.in_vectors[1].address); } -V0IsoMessage::V0IsoMessage(const IOCtlVRequest& ioctlv) - : IsoMessage(ioctlv, ioctlv.io_vectors[1].address) +V0IsoMessage::V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : IsoMessage(ios, ioctlv, ioctlv.io_vectors[1].address) { endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address); length = Memory::Read_U16(ioctlv.in_vectors[1].address); diff --git a/Source/Core/Core/IOS/USB/USBV0.h b/Source/Core/Core/IOS/USB/USBV0.h index 9af2c1308f..eaa80d9f16 100644 --- a/Source/Core/Core/IOS/USB/USBV0.h +++ b/Source/Core/Core/IOS/USB/USBV0.h @@ -41,22 +41,22 @@ enum V0Requests struct V0CtrlMessage final : CtrlMessage { - explicit V0CtrlMessage(const IOCtlVRequest& ioctlv); + V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; struct V0BulkMessage final : BulkMessage { - explicit V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length = false); + V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length = false); }; struct V0IntrMessage final : IntrMessage { - explicit V0IntrMessage(const IOCtlVRequest& ioctlv); + V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; struct V0IsoMessage final : IsoMessage { - explicit V0IsoMessage(const IOCtlVRequest& ioctlv); + V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; } // namespace USB } // namespace HLE diff --git a/Source/Core/Core/IOS/USB/USBV4.cpp b/Source/Core/Core/IOS/USB/USBV4.cpp index b28142f1e1..c2b9825cd6 100644 --- a/Source/Core/Core/IOS/USB/USBV4.cpp +++ b/Source/Core/Core/IOS/USB/USBV4.cpp @@ -49,7 +49,7 @@ struct HIDRequest }; #pragma pack(pop) -V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1) +V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessage(ios, ioctl, -1) { HIDRequest hid_request; Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request)); @@ -64,7 +64,8 @@ V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1) // Since this is just a standard control request, but with additional requirements // (US for the language and replacing non-ASCII characters with '?'), // we can simply submit it as a usual control request. -V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1) +V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl) + : CtrlMessage(ios, ioctl, -1) { HIDRequest hid_request; Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request)); @@ -76,16 +77,17 @@ V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMess data_address = Common::swap32(hid_request.data_addr); } -void V4GetUSStringMessage::OnTransferComplete() const +void V4GetUSStringMessage::OnTransferComplete(s32 return_value) const { const std::locale& c_locale = std::locale::classic(); std::string message = Memory::GetString(data_address); std::replace_if(message.begin(), message.end(), [&c_locale](char c) { return !std::isprint(c, c_locale); }, '?'); Memory::CopyToEmu(data_address, message.c_str(), message.size()); + TransferCommand::OnTransferComplete(return_value); } -V4IntrMessage::V4IntrMessage(const IOCtlRequest& ioctl) : IntrMessage(ioctl, -1) +V4IntrMessage::V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl) : IntrMessage(ios, ioctl, -1) { HIDRequest hid_request; Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request)); diff --git a/Source/Core/Core/IOS/USB/USBV4.h b/Source/Core/Core/IOS/USB/USBV4.h index 93ccd7ee21..92e23e0a1c 100644 --- a/Source/Core/Core/IOS/USB/USBV4.h +++ b/Source/Core/Core/IOS/USB/USBV4.h @@ -32,18 +32,18 @@ enum V4Requests struct V4CtrlMessage final : CtrlMessage { - explicit V4CtrlMessage(const IOCtlRequest& ioctl); + V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl); }; struct V4GetUSStringMessage final : CtrlMessage { - explicit V4GetUSStringMessage(const IOCtlRequest& ioctl); - void OnTransferComplete() const override; + V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl); + void OnTransferComplete(s32 return_value) const override; }; struct V4IntrMessage final : IntrMessage { - explicit V4IntrMessage(const IOCtlRequest& ioctl); + V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl); }; } // namespace USB } // namespace HLE diff --git a/Source/Core/Core/IOS/USB/USBV5.cpp b/Source/Core/Core/IOS/USB/USBV5.cpp index bf4fd09399..357676fe08 100644 --- a/Source/Core/Core/IOS/USB/USBV5.cpp +++ b/Source/Core/Core/IOS/USB/USBV5.cpp @@ -16,8 +16,8 @@ namespace HLE { namespace USB { -V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv) - : CtrlMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16)) +V5CtrlMessage::V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : CtrlMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16)) { request_type = Memory::Read_U8(ioctlv.in_vectors[0].address + 8); request = Memory::Read_U8(ioctlv.in_vectors[0].address + 9); @@ -26,22 +26,22 @@ V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv) length = Memory::Read_U16(ioctlv.in_vectors[0].address + 14); } -V5BulkMessage::V5BulkMessage(const IOCtlVRequest& ioctlv) - : BulkMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) +V5BulkMessage::V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : BulkMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) { length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12); endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 18); } -V5IntrMessage::V5IntrMessage(const IOCtlVRequest& ioctlv) - : IntrMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) +V5IntrMessage::V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : IntrMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) { length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12); endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 14); } -V5IsoMessage::V5IsoMessage(const IOCtlVRequest& ioctlv) - : IsoMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) +V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv) + : IsoMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8)) { num_packets = Memory::Read_U8(ioctlv.in_vectors[0].address + 16); endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 17); diff --git a/Source/Core/Core/IOS/USB/USBV5.h b/Source/Core/Core/IOS/USB/USBV5.h index 871d0e7856..2db6c22110 100644 --- a/Source/Core/Core/IOS/USB/USBV5.h +++ b/Source/Core/Core/IOS/USB/USBV5.h @@ -36,22 +36,22 @@ enum V5Requests struct V5CtrlMessage final : CtrlMessage { - explicit V5CtrlMessage(const IOCtlVRequest& ioctlv); + V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; struct V5BulkMessage final : BulkMessage { - explicit V5BulkMessage(const IOCtlVRequest& ioctlv); + V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; struct V5IntrMessage final : IntrMessage { - explicit V5IntrMessage(const IOCtlVRequest& ioctlv); + V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv); }; struct V5IsoMessage final : IsoMessage { - explicit V5IsoMessage(const IOCtlVRequest& cmd_buffer); + V5IsoMessage(Kernel& ios, const IOCtlVRequest& cmd_buffer); }; } // namespace USB } // namespace HLE diff --git a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp index e7c87a1c26..897f588809 100644 --- a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp +++ b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.cpp @@ -23,8 +23,7 @@ namespace HLE { namespace Device { -USB_HIDv4::USB_HIDv4(u32 device_id, const std::string& device_name) - : USBHost(device_id, device_name) +USB_HIDv4::USB_HIDv4(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name) { } @@ -102,7 +101,7 @@ IPCCommandResult USB_HIDv4::Shutdown(const IOCtlRequest& request) if (m_devicechange_hook_request != 0) { Memory::Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out); - EnqueueReply(*m_devicechange_hook_request, -1); + m_ios.EnqueueIPCReply(*m_devicechange_hook_request, -1); m_devicechange_hook_request.reset(); } return GetDefaultReply(IPC_SUCCESS); @@ -113,12 +112,12 @@ s32 USB_HIDv4::SubmitTransfer(USB::Device& device, const IOCtlRequest& request) switch (request.request) { case USB::IOCTL_USBV4_CTRLMSG: - return device.SubmitTransfer(std::make_unique(request)); + return device.SubmitTransfer(std::make_unique(m_ios, request)); case USB::IOCTL_USBV4_GET_US_STRING: - return device.SubmitTransfer(std::make_unique(request)); + return device.SubmitTransfer(std::make_unique(m_ios, request)); case USB::IOCTL_USBV4_INTRMSG_IN: case USB::IOCTL_USBV4_INTRMSG_OUT: - return device.SubmitTransfer(std::make_unique(request)); + return device.SubmitTransfer(std::make_unique(m_ios, request)); default: return IPC_EINVAL; } @@ -204,7 +203,7 @@ void USB_HIDv4::TriggerDeviceChangeReply() Memory::Write_U32(0xffffffff, dest + offset); } - EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY); + m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY); m_devicechange_hook_request.reset(); } diff --git a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.h b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.h index 4048f3c339..845bebd394 100644 --- a/Source/Core/Core/IOS/USB/USB_HID/HIDv4.h +++ b/Source/Core/Core/IOS/USB/USB_HID/HIDv4.h @@ -11,7 +11,7 @@ #include #include "Common/CommonTypes.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Host.h" class PointerWrap; @@ -25,7 +25,7 @@ namespace Device class USB_HIDv4 final : public USBHost { public: - USB_HIDv4(u32 device_id, const std::string& device_name); + USB_HIDv4(Kernel& ios, const std::string& device_name); ~USB_HIDv4() override; IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/IOS/USB/USB_KBD.cpp b/Source/Core/Core/IOS/USB/USB_KBD.cpp index bad439ff96..a9f361a1a7 100644 --- a/Source/Core/Core/IOS/USB/USB_KBD.cpp +++ b/Source/Core/Core/IOS/USB/USB_KBD.cpp @@ -39,7 +39,7 @@ USB_KBD::SMessageData::SMessageData(u32 type, u8 modifiers, u8* pressed_keys) // TODO: support in netplay/movies. -USB_KBD::USB_KBD(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/USB/USB_KBD.h b/Source/Core/Core/IOS/USB/USB_KBD.h index 39cab243da..34917338af 100644 --- a/Source/Core/Core/IOS/USB/USB_KBD.h +++ b/Source/Core/Core/IOS/USB/USB_KBD.h @@ -9,7 +9,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -20,7 +20,7 @@ namespace Device class USB_KBD : public Device { public: - USB_KBD(u32 device_id, const std::string& device_name); + USB_KBD(Kernel& ios, const std::string& device_name); ReturnCode Open(const OpenRequest& request) override; IPCCommandResult Write(const ReadWriteRequest& request) override; diff --git a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp index 303915f92a..f9bb7a1583 100644 --- a/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp +++ b/Source/Core/Core/IOS/USB/USB_VEN/VEN.cpp @@ -22,7 +22,7 @@ namespace HLE { namespace Device { -USB_VEN::USB_VEN(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name) +USB_VEN::USB_VEN(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name) { } @@ -33,7 +33,7 @@ USB_VEN::~USB_VEN() ReturnCode USB_VEN::Open(const OpenRequest& request) { - const u32 ios_major_version = GetVersion(); + const u32 ios_major_version = m_ios.GetVersion(); if (ios_major_version != 57 && ios_major_version != 58 && ios_major_version != 59) return IPC_ENOENT; return USBHost::Open(request); @@ -197,7 +197,7 @@ IPCCommandResult USB_VEN::Shutdown(const IOCtlRequest& request) std::lock_guard lk{m_devicechange_hook_address_mutex}; if (m_devicechange_hook_request) { - EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS); + m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS); m_devicechange_hook_request.reset(); } return GetDefaultReply(IPC_SUCCESS); @@ -220,13 +220,13 @@ s32 USB_VEN::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv) switch (ioctlv.request) { case USB::IOCTLV_USBV5_CTRLMSG: - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); case USB::IOCTLV_USBV5_INTRMSG: - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); case USB::IOCTLV_USBV5_BULKMSG: - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); case USB::IOCTLV_USBV5_ISOMSG: - return device.SubmitTransfer(std::make_unique(ioctlv)); + return device.SubmitTransfer(std::make_unique(m_ios, ioctlv)); default: return IPC_EINVAL; } @@ -326,7 +326,7 @@ void USB_VEN::TriggerDeviceChangeReply() &entry, sizeof(entry)); } - EnqueueReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY); + m_ios.EnqueueIPCReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY); m_devicechange_hook_request.reset(); INFO_LOG(IOS_USB, "%d device(s), including interfaces", num_devices); } diff --git a/Source/Core/Core/IOS/USB/USB_VEN/VEN.h b/Source/Core/Core/IOS/USB/USB_VEN/VEN.h index b35ea15384..ed8d71a8d7 100644 --- a/Source/Core/Core/IOS/USB/USB_VEN/VEN.h +++ b/Source/Core/Core/IOS/USB/USB_VEN/VEN.h @@ -14,7 +14,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Host.h" class PointerWrap; @@ -28,7 +28,7 @@ namespace Device class USB_VEN final : public USBHost { public: - USB_VEN(u32 device_id, const std::string& device_name); + USB_VEN(Kernel& ios, const std::string& device_name); ~USB_VEN() override; ReturnCode Open(const OpenRequest& request) override; diff --git a/Source/Core/Core/IOS/WFS/WFSI.cpp b/Source/Core/Core/IOS/WFS/WFSI.cpp index 86e4fb492f..c6d26640f7 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.cpp +++ b/Source/Core/Core/IOS/WFS/WFSI.cpp @@ -80,7 +80,7 @@ void ARCUnpacker::Extract(const WriteCallback& callback) namespace Device { -WFSI::WFSI(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +WFSI::WFSI(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { } diff --git a/Source/Core/Core/IOS/WFS/WFSI.h b/Source/Core/Core/IOS/WFS/WFSI.h index 82dfded277..a6494c4f2c 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.h +++ b/Source/Core/Core/IOS/WFS/WFSI.h @@ -13,7 +13,7 @@ #include "Common/CommonTypes.h" #include "Core/IOS/Device.h" #include "Core/IOS/ES/Formats.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" namespace IOS { @@ -39,7 +39,7 @@ namespace Device class WFSI : public Device { public: - WFSI(u32 device_id, const std::string& device_name); + WFSI(Kernel& ios, const std::string& device_name); IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/IOS/WFS/WFSSRV.cpp b/Source/Core/Core/IOS/WFS/WFSSRV.cpp index 74a67bff2f..54bdd806b7 100644 --- a/Source/Core/Core/IOS/WFS/WFSSRV.cpp +++ b/Source/Core/Core/IOS/WFS/WFSSRV.cpp @@ -27,7 +27,7 @@ std::string NativePath(const std::string& wfs_path) namespace Device { -WFSSRV::WFSSRV(u32 device_id, const std::string& device_name) : Device(device_id, device_name) +WFSSRV::WFSSRV(Kernel& ios, const std::string& device_name) : Device(ios, device_name) { m_device_name = "msc01"; } diff --git a/Source/Core/Core/IOS/WFS/WFSSRV.h b/Source/Core/Core/IOS/WFS/WFSSRV.h index ad540f8de6..097e086f0b 100644 --- a/Source/Core/Core/IOS/WFS/WFSSRV.h +++ b/Source/Core/Core/IOS/WFS/WFSSRV.h @@ -10,7 +10,7 @@ #include "Common/CommonTypes.h" #include "Common/FileUtil.h" #include "Core/IOS/Device.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "DiscIO/Volume.h" namespace IOS @@ -27,7 +27,7 @@ namespace Device class WFSSRV : public Device { public: - WFSSRV(u32 device_id, const std::string& device_name); + WFSSRV(Kernel& ios, const std::string& device_name); IPCCommandResult IOCtl(const IOCtlRequest& request) override; diff --git a/Source/Core/Core/Movie.cpp b/Source/Core/Core/Movie.cpp index a4bada72e2..207a047079 100644 --- a/Source/Core/Core/Movie.cpp +++ b/Source/Core/Core/Movie.cpp @@ -533,8 +533,10 @@ void ChangeWiiPads(bool instantly) if (instantly && (s_controllers >> 4) == controllers) return; - const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); + const auto ios = IOS::HLE::GetIOS(); + const auto bt = ios ? std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")) : + nullptr; for (int i = 0; i < MAX_WIIMOTES; ++i) { g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE; diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index fc2418391e..25b65dc8a7 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 = 82; // Last changed in PR 5333 +static const u32 STATE_VERSION = 83; // Last changed in PR 5340 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list, diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index d9293a0faa..5c24b65a40 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -23,7 +23,7 @@ #include "Core/Core.h" #include "Core/HW/Wiimote.h" #include "Core/Host.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/IOS/USB/Bluetooth/BTEmu.h" #include "Core/IOS/USB/Bluetooth/WiimoteDevice.h" @@ -139,19 +139,18 @@ bool Host_RendererIsFullscreen() void Host_ConnectWiimote(int wm_idx, bool connect) { - if (Core::IsRunning() && SConfig::GetInstance().bWii && - !SConfig::GetInstance().m_bt_passthrough_enabled) - { - Core::QueueHostJob([=] { - bool was_unpaused = Core::PauseAndLock(true); - const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); - if (bt) - bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); - Host_UpdateMainFrame(); - Core::PauseAndLock(false, was_unpaused); - }); - } + Core::QueueHostJob([=] { + const auto ios = IOS::HLE::GetIOS(); + if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) + return; + bool was_unpaused = Core::PauseAndLock(true); + const auto bt = std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); + if (bt) + bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); + Host_UpdateMainFrame(); + Core::PauseAndLock(false, was_unpaused); + }); } void Host_SetWiiMoteConnectionState(int _State) @@ -241,7 +240,8 @@ class PlatformX11 : public Platform { if (s_shutdown_requested.TestAndClear()) { - const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook"); + const auto ios = IOS::HLE::GetIOS(); + const auto stm = ios ? ios->GetDeviceByName("/dev/stm/eventhook") : nullptr; if (!s_tried_graceful_shutdown.IsSet() && stm && std::static_pointer_cast(stm)->HasHookInstalled()) { diff --git a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp index 073dd9814d..d91d4875f3 100644 --- a/Source/Core/DolphinWX/Config/WiiConfigPane.cpp +++ b/Source/Core/DolphinWX/Config/WiiConfigPane.cpp @@ -13,7 +13,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "DolphinWX/Config/AddUSBDeviceDiag.h" #include "DolphinWX/Config/WiiConfigPane.h" #include "DolphinWX/DolphinSlider.h" @@ -279,7 +279,9 @@ void WiiConfigPane::OnPAL60CheckBoxChanged(wxCommandEvent& event) void WiiConfigPane::OnSDCardCheckBoxChanged(wxCommandEvent& event) { SConfig::GetInstance().m_WiiSDCard = m_sd_card_checkbox->IsChecked(); - IOS::HLE::SDIO_EventNotify(); + const auto ios = IOS::HLE::GetIOS(); + if (ios) + ios->SDIO_EventNotify(); } void WiiConfigPane::OnConnectKeyboardCheckBoxChanged(wxCommandEvent& event) diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index e032b5a18e..005b4a5b6b 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -27,7 +27,7 @@ #include "Core/HW/Wiimote.h" #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/HotkeyManager.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTReal.h" #include "Core/NetPlayProto.h" #include "DolphinWX/Config/GCAdapterConfigDiag.h" @@ -543,13 +543,14 @@ void ControllerConfigDiag::OnBluetoothModeChanged(wxCommandEvent& event) void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event) { - if (!Core::IsRunning()) + const auto ios = IOS::HLE::GetIOS(); + if (!ios) { wxMessageBox(_("A sync can only be triggered when a Wii game is running."), _("Sync Wii Remotes"), wxICON_WARNING); return; } - auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"); + auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); if (device != nullptr) std::static_pointer_cast(device) ->TriggerSyncButtonPressedEvent(); @@ -557,13 +558,14 @@ void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event) void ControllerConfigDiag::OnPassthroughResetButton(wxCommandEvent& event) { - if (!Core::IsRunning()) + const auto ios = IOS::HLE::GetIOS(); + if (!ios) { wxMessageBox(_("Saved Wii Remote pairings can only be reset when a Wii game is running."), _("Reset Wii Remote pairings"), wxICON_WARNING); return; } - auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"); + auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); if (device != nullptr) std::static_pointer_cast(device)->TriggerSyncButtonHeldEvent(); } diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 3c47217525..fab9e1ae3f 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -50,7 +50,7 @@ #include "Core/HW/Wiimote.h" #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "Core/HotkeyManager.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTBase.h" #include "Core/Movie.h" #include "Core/State.h" @@ -1278,7 +1278,8 @@ void CFrame::ParseHotkeys() if (SConfig::GetInstance().m_bt_passthrough_enabled) { - auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"); + const auto ios = IOS::HLE::GetIOS(); + auto device = ios ? ios->GetDeviceByName("/dev/usb/oh1/57e/305") : nullptr; if (device != nullptr) std::static_pointer_cast(device)->UpdateSyncButtonState( IsHotkey(HK_TRIGGER_SYNC_BUTTON, true)); diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 9dd9c7a9a2..9822aae148 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -42,7 +42,7 @@ #include "Core/HW/Wiimote.h" #include "Core/Host.h" #include "Core/HotkeyManager.h" -#include "Core/IOS/IPC.h" +#include "Core/IOS/IOS.h" #include "Core/IOS/STM/STM.h" #include "Core/IOS/USB/Bluetooth/BTEmu.h" #include "Core/IOS/USB/Bluetooth/WiimoteDevice.h" @@ -880,7 +880,11 @@ void CFrame::DoStop() bool CFrame::TriggerSTMPowerEvent() { - const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook"); + const auto ios = IOS::HLE::GetIOS(); + if (!ios) + return false; + + const auto stm = ios->GetDeviceByName("/dev/stm/eventhook"); if (!stm || !std::static_pointer_cast(stm)->HasHookInstalled()) return false; @@ -1310,8 +1314,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) !SConfig::GetInstance().m_bt_passthrough_enabled) { bool was_unpaused = Core::PauseAndLock(true); + const auto ios = IOS::HLE::GetIOS(); + if (!ios) + return; + const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); if (bt) bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect); const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected"; @@ -1323,11 +1331,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect) void CFrame::OnConnectWiimote(wxCommandEvent& event) { - if (SConfig::GetInstance().m_bt_passthrough_enabled) + const auto ios = IOS::HLE::GetIOS(); + if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled) return; bool was_unpaused = Core::PauseAndLock(true); const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); + ios->GetDeviceByName("/dev/usb/oh1/57e/305")); const bool is_connected = bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected(); ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected); @@ -1486,8 +1495,10 @@ void CFrame::UpdateGUI() // Tools GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().bEnableCheats); - const auto bt = std::static_pointer_cast( - IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305")); + const auto ios = IOS::HLE::GetIOS(); + const auto bt = ios ? std::static_pointer_cast( + ios->GetDeviceByName("/dev/usb/oh1/57e/305")) : + nullptr; bool ShouldEnableWiimotes = Running && bt && !SConfig::GetInstance().m_bt_passthrough_enabled; GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(ShouldEnableWiimotes); GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(ShouldEnableWiimotes); From 58fe0f12a49dca3ee13bb7f8a2260156059416fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sun, 30 Apr 2017 16:36:33 +0200 Subject: [PATCH 2/2] IOS: Reorder functions in IOS.cpp Puts them in a more logical order. --- Source/Core/Core/IOS/IOS.cpp | 412 +++++++++++++++++------------------ 1 file changed, 206 insertions(+), 206 deletions(-) diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index d1f7ccd0e7..5fce675168 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -64,12 +64,6 @@ constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; static CoreTiming::EventType* s_event_enqueue; static CoreTiming::EventType* s_event_sdio_notify; -enum class MemorySetupType -{ - IOSReload, - Full, -}; - constexpr u32 ADDR_MEM1_SIZE = 0x3100; constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104; constexpr u32 ADDR_MEM1_END = 0x3108; @@ -97,16 +91,14 @@ constexpr u32 ADDR_BOOT_FLAG = 0x315c; constexpr u32 ADDR_APPLOADER_FLAG = 0x315d; constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e; constexpr u32 ADDR_SYSMENU_SYNC = 0x3160; - -// The title ID is a u64 where the first 32 bits are used for the title type. -// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits -// are used for the IOS major version -- which is what we want here. -u32 Kernel::GetVersion() const -{ - return static_cast(m_title_id); -} - constexpr u32 PLACEHOLDER = 0xDEADBEEF; + +enum class MemorySetupType +{ + IOSReload, + Full, +}; + static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type) { auto target_imv = std::find_if( @@ -175,44 +167,6 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type) return true; } -void Kernel::AddDevice(std::unique_ptr device) -{ - _assert_(device->GetDeviceType() == Device::Device::DeviceType::Static); - m_device_map[device->GetDeviceName()] = std::move(device); -} - -void Kernel::AddStaticDevices() -{ - std::lock_guard lock(m_device_map_mutex); - _assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized"); - - if (!SConfig::GetInstance().m_bt_passthrough_enabled) - AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); - else - AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); - - AddDevice(std::make_unique(*this, "/dev/stm/immediate")); - AddDevice(std::make_unique(*this, "/dev/stm/eventhook")); - AddDevice(std::make_unique(*this, "/dev/fs")); - AddDevice(std::make_unique(*this, "/dev/es")); - AddDevice(std::make_unique(*this, "/dev/di")); - AddDevice(std::make_unique(*this, "/dev/net/kd/request")); - AddDevice(std::make_unique(*this, "/dev/net/kd/time")); - AddDevice(std::make_unique(*this, "/dev/net/ncd/manage")); - AddDevice(std::make_unique(*this, "/dev/net/wd/command")); - AddDevice(std::make_unique(*this, "/dev/net/ip/top")); - AddDevice(std::make_unique(*this, "/dev/net/ssl")); - AddDevice(std::make_unique(*this, "/dev/usb/kbd")); - AddDevice(std::make_unique(*this, "/dev/sdio/slot0")); - AddDevice(std::make_unique(*this, "/dev/sdio/slot1")); - AddDevice(std::make_unique(*this, "/dev/usb/hid")); - AddDevice(std::make_unique(*this, "/dev/usb/oh0")); - AddDevice(std::make_unique(*this, "/dev/usb/oh1")); - AddDevice(std::make_unique(*this, "/dev/usb/ven")); - AddDevice(std::make_unique(*this, "/dev/usb/wfssrv")); - AddDevice(std::make_unique(*this, "/dev/wfsi")); -} - // IOS used by the latest System Menu (4.3). constexpr u64 IOS80_TITLE_ID = 0x0000000100000050; constexpr u64 BC_TITLE_ID = 0x0000000100000100; @@ -255,77 +209,12 @@ Kernel::~Kernel() } } -void Kernel::HandleIPCEvent(u64 userdata) +// The title ID is a u64 where the first 32 bits are used for the title type. +// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits +// are used for the IOS major version -- which is what we want here. +u32 Kernel::GetVersion() const { - if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) - m_ack_queue.push_back(static_cast(userdata)); - else if (userdata & ENQUEUE_REQUEST_FLAG) - m_request_queue.push_back(static_cast(userdata)); - else - m_reply_queue.push_back(static_cast(userdata)); - - UpdateIPC(); -} - -void Init() -{ - s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", [](u64 userdata, s64) { - if (s_ios) - s_ios->HandleIPCEvent(userdata); - }); - - s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", [](u64, s64) { - if (!s_ios) - return; - - auto device = static_cast(s_ios->GetDeviceByName("/dev/sdio/slot0").get()); - if (device) - device->EventNotify(); - }); - - // Start with IOS80 to simulate part of the Wii boot process. - s_ios = std::make_unique(IOS80_TITLE_ID); - // On a Wii, boot2 launches the system menu IOS, which then launches the system menu - // (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up. - // This means that the constants in the 0x3100 region are always set up by the time - // a game is launched. This is necessary because booting games from the game list skips - // a significant part of a Wii's boot process. - SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full); -} - -void Shutdown() -{ - s_ios.reset(); -} - -Kernel* GetIOS() -{ - return s_ios.get(); -} - -// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS. -// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any -// of the other constants to the memory. -bool Kernel::BootIOS(const u64 ios_title_id) -{ - // A real Wii goes through several steps before getting to MIOS. - // - // * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game. - // * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2. - // * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu. - // - // Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS - // (indirectly via boot2), we can just launch MIOS when BC is launched. - if (ios_title_id == BC_TITLE_ID) - { - NOTICE_LOG(IOS, "BC: Launching MIOS..."); - return BootIOS(MIOS_TITLE_ID); - } - - // Shut down the active IOS first before switching to the new one. - s_ios.reset(); - s_ios = std::make_unique(ios_title_id); - return true; + return static_cast(m_title_id); } // Since we don't have actual processes, we keep track of only the PPC's UID/GID. @@ -379,12 +268,67 @@ bool Kernel::BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader) return true; } -void Kernel::SDIO_EventNotify() +// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS. +// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any +// of the other constants to the memory. Warning: this resets the kernel instance. +bool Kernel::BootIOS(const u64 ios_title_id) { - // TODO: Potential race condition: If IsRunning() becomes false after - // it's checked, an event may be scheduled after CoreTiming shuts down. - if (SConfig::GetInstance().bWii && Core::IsRunning()) - CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU); + // A real Wii goes through several steps before getting to MIOS. + // + // * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game. + // * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2. + // * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu. + // + // Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS + // (indirectly via boot2), we can just launch MIOS when BC is launched. + if (ios_title_id == BC_TITLE_ID) + { + NOTICE_LOG(IOS, "BC: Launching MIOS..."); + return BootIOS(MIOS_TITLE_ID); + } + + // Shut down the active IOS first before switching to the new one. + s_ios.reset(); + s_ios = std::make_unique(ios_title_id); + return true; +} + +void Kernel::AddDevice(std::unique_ptr device) +{ + _assert_(device->GetDeviceType() == Device::Device::DeviceType::Static); + m_device_map[device->GetDeviceName()] = std::move(device); +} + +void Kernel::AddStaticDevices() +{ + std::lock_guard lock(m_device_map_mutex); + _assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized"); + + if (!SConfig::GetInstance().m_bt_passthrough_enabled) + AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); + else + AddDevice(std::make_unique(*this, "/dev/usb/oh1/57e/305")); + + AddDevice(std::make_unique(*this, "/dev/stm/immediate")); + AddDevice(std::make_unique(*this, "/dev/stm/eventhook")); + AddDevice(std::make_unique(*this, "/dev/fs")); + AddDevice(std::make_unique(*this, "/dev/es")); + AddDevice(std::make_unique(*this, "/dev/di")); + AddDevice(std::make_unique(*this, "/dev/net/kd/request")); + AddDevice(std::make_unique(*this, "/dev/net/kd/time")); + AddDevice(std::make_unique(*this, "/dev/net/ncd/manage")); + AddDevice(std::make_unique(*this, "/dev/net/wd/command")); + AddDevice(std::make_unique(*this, "/dev/net/ip/top")); + AddDevice(std::make_unique(*this, "/dev/net/ssl")); + AddDevice(std::make_unique(*this, "/dev/usb/kbd")); + AddDevice(std::make_unique(*this, "/dev/sdio/slot0")); + AddDevice(std::make_unique(*this, "/dev/sdio/slot1")); + AddDevice(std::make_unique(*this, "/dev/usb/hid")); + AddDevice(std::make_unique(*this, "/dev/usb/oh0")); + AddDevice(std::make_unique(*this, "/dev/usb/oh1")); + AddDevice(std::make_unique(*this, "/dev/usb/ven")); + AddDevice(std::make_unique(*this, "/dev/usb/wfssrv")); + AddDevice(std::make_unique(*this, "/dev/wfsi")); } s32 Kernel::GetFreeDeviceID() @@ -407,84 +351,6 @@ std::shared_ptr Kernel::GetDeviceByName(const std::string& devic return iterator != m_device_map.end() ? iterator->second : nullptr; } -void Kernel::DoState(PointerWrap& p) -{ - p.Do(m_request_queue); - p.Do(m_reply_queue); - p.Do(m_last_reply_time); - p.Do(m_title_id); - p.Do(m_ppc_uid); - p.Do(m_ppc_gid); - - if (m_title_id == MIOS_TITLE_ID) - return; - - // We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can - // successfully save or re-create /tmp - for (auto& descriptor : m_fdmap) - { - if (descriptor) - descriptor->PrepareForState(p.GetMode()); - } - - for (const auto& entry : m_device_map) - entry.second->DoState(p); - - if (p.GetMode() == PointerWrap::MODE_READ) - { - for (u32 i = 0; i < IPC_MAX_FDS; i++) - { - u32 exists = 0; - p.Do(exists); - if (exists) - { - auto device_type = Device::Device::DeviceType::Static; - p.Do(device_type); - switch (device_type) - { - case Device::Device::DeviceType::Static: - { - std::string device_name; - p.Do(device_name); - m_fdmap[i] = GetDeviceByName(device_name); - break; - } - case Device::Device::DeviceType::FileIO: - m_fdmap[i] = std::make_shared(*this, ""); - m_fdmap[i]->DoState(p); - break; - case Device::Device::DeviceType::OH0: - m_fdmap[i] = std::make_shared(*this, ""); - m_fdmap[i]->DoState(p); - break; - } - } - } - } - else - { - for (auto& descriptor : m_fdmap) - { - u32 exists = descriptor ? 1 : 0; - p.Do(exists); - if (exists) - { - auto device_type = descriptor->GetDeviceType(); - p.Do(device_type); - if (device_type == Device::Device::DeviceType::Static) - { - std::string device_name = descriptor->GetDeviceName(); - p.Do(device_name); - } - else - { - descriptor->DoState(p); - } - } - } - } -} - // Returns the FD for the newly opened device (on success) or an error code. s32 Kernel::OpenDevice(OpenRequest& request) { @@ -599,6 +465,18 @@ void Kernel::EnqueueIPCAcknowledgement(u32 address, int cycles_in_future) address | ENQUEUE_ACKNOWLEDGEMENT_FLAG); } +void Kernel::HandleIPCEvent(u64 userdata) +{ + if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG) + m_ack_queue.push_back(static_cast(userdata)); + else if (userdata & ENQUEUE_REQUEST_FLAG) + m_request_queue.push_back(static_cast(userdata)); + else + m_reply_queue.push_back(static_cast(userdata)); + + UpdateIPC(); +} + // This is called every IPC_HLE_PERIOD from SystemTimers.cpp // Takes care of routing ipc <-> ipc HLE void Kernel::UpdateIPC() @@ -650,5 +528,127 @@ void Kernel::UpdateWantDeterminism(const bool new_want_determinism) for (const auto& device : m_device_map) device.second->UpdateWantDeterminism(new_want_determinism); } + +void Kernel::SDIO_EventNotify() +{ + // TODO: Potential race condition: If IsRunning() becomes false after + // it's checked, an event may be scheduled after CoreTiming shuts down. + if (SConfig::GetInstance().bWii && Core::IsRunning()) + CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU); +} + +void Kernel::DoState(PointerWrap& p) +{ + p.Do(m_request_queue); + p.Do(m_reply_queue); + p.Do(m_last_reply_time); + p.Do(m_title_id); + p.Do(m_ppc_uid); + p.Do(m_ppc_gid); + + if (m_title_id == MIOS_TITLE_ID) + return; + + // We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can + // successfully save or re-create /tmp + for (auto& descriptor : m_fdmap) + { + if (descriptor) + descriptor->PrepareForState(p.GetMode()); + } + + for (const auto& entry : m_device_map) + entry.second->DoState(p); + + if (p.GetMode() == PointerWrap::MODE_READ) + { + for (u32 i = 0; i < IPC_MAX_FDS; i++) + { + u32 exists = 0; + p.Do(exists); + if (exists) + { + auto device_type = Device::Device::DeviceType::Static; + p.Do(device_type); + switch (device_type) + { + case Device::Device::DeviceType::Static: + { + std::string device_name; + p.Do(device_name); + m_fdmap[i] = GetDeviceByName(device_name); + break; + } + case Device::Device::DeviceType::FileIO: + m_fdmap[i] = std::make_shared(*this, ""); + m_fdmap[i]->DoState(p); + break; + case Device::Device::DeviceType::OH0: + m_fdmap[i] = std::make_shared(*this, ""); + m_fdmap[i]->DoState(p); + break; + } + } + } + } + else + { + for (auto& descriptor : m_fdmap) + { + u32 exists = descriptor ? 1 : 0; + p.Do(exists); + if (exists) + { + auto device_type = descriptor->GetDeviceType(); + p.Do(device_type); + if (device_type == Device::Device::DeviceType::Static) + { + std::string device_name = descriptor->GetDeviceName(); + p.Do(device_name); + } + else + { + descriptor->DoState(p); + } + } + } + } +} + +void Init() +{ + s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", [](u64 userdata, s64) { + if (s_ios) + s_ios->HandleIPCEvent(userdata); + }); + + s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", [](u64, s64) { + if (!s_ios) + return; + + auto device = static_cast(s_ios->GetDeviceByName("/dev/sdio/slot0").get()); + if (device) + device->EventNotify(); + }); + + // Start with IOS80 to simulate part of the Wii boot process. + s_ios = std::make_unique(IOS80_TITLE_ID); + // On a Wii, boot2 launches the system menu IOS, which then launches the system menu + // (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up. + // This means that the constants in the 0x3100 region are always set up by the time + // a game is launched. This is necessary because booting games from the game list skips + // a significant part of a Wii's boot process. + SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full); +} + +void Shutdown() +{ + s_ios.reset(); +} + +Kernel* GetIOS() +{ + return s_ios.get(); +} } // namespace HLE } // namespace IOS