diff --git a/Source/Core/Core/HW/HW.cpp b/Source/Core/Core/HW/HW.cpp index b9017b9f21..253883d9b1 100644 --- a/Source/Core/Core/HW/HW.cpp +++ b/Source/Core/Core/HW/HW.cpp @@ -24,7 +24,6 @@ #include "Core/IOS/IOS.h" #include "Core/Movie.h" #include "Core/State.h" -#include "Core/WiiRoot.h" namespace HW { @@ -50,7 +49,6 @@ void Init() if (SConfig::GetInstance().bWii) { - Core::InitializeWiiRoot(Core::WantsDeterminism()); IOS::Init(); IOS::HLE::Init(); // Depends on Memory } @@ -61,8 +59,6 @@ void Shutdown() // IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS). IOS::HLE::Shutdown(); // Depends on Memory IOS::Shutdown(); - if (SConfig::GetInstance().bWii) - Core::ShutdownWiiRoot(); SystemTimers::Shutdown(); CPU::Shutdown(); diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp index 8720882bac..eaf2fa605b 100644 --- a/Source/Core/Core/IOS/IOS.cpp +++ b/Source/Core/Core/IOS/IOS.cpp @@ -51,13 +51,14 @@ #include "Core/IOS/WFS/WFSI.h" #include "Core/IOS/WFS/WFSSRV.h" #include "Core/PowerPC/PowerPC.h" +#include "Core/WiiRoot.h" #include "DiscIO/NANDContentLoader.h" namespace IOS { namespace HLE { -static std::unique_ptr s_ios; +static std::unique_ptr s_ios; constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL; constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL; @@ -172,29 +173,17 @@ 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) +Kernel::Kernel() { - 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(); + // Until the Wii root and NAND path stuff is entirely managed by IOS and made non-static, + // using more than one IOS instance at a time is not supported. + _assert_(GetIOS() == nullptr); + Core::InitializeWiiRoot(false); + AddCoreDevices(); } Kernel::~Kernel() { - CoreTiming::RemoveAllEvents(s_event_enqueue); - // Close all devices that were opened for (auto& device : m_fdmap) { @@ -207,6 +196,36 @@ Kernel::~Kernel() std::lock_guard lock(m_device_map_mutex); m_device_map.clear(); } + + Core::ShutdownWiiRoot(); +} + +EmulationKernel::EmulationKernel(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"); + + Core::InitializeWiiRoot(Core::WantsDeterminism()); + + if (title_id == MIOS_TITLE_ID) + { + MIOS::Load(); + return; + } + + // IOS re-inits IPC and sends a dummy ack during its boot process. + EnqueueIPCAcknowledgement(0); + + AddCoreDevices(); + AddStaticDevices(); +} + +EmulationKernel::~EmulationKernel() +{ + CoreTiming::RemoveAllEvents(s_event_enqueue); } // The title ID is a u64 where the first 32 bits are used for the title type. @@ -217,6 +236,16 @@ u32 Kernel::GetVersion() const return static_cast(m_title_id); } +std::shared_ptr Kernel::GetFS() +{ + return std::static_pointer_cast(m_device_map.at("/dev/fs")); +} + +std::shared_ptr Kernel::GetES() +{ + return std::static_pointer_cast(m_device_map.at("/dev/es")); +} + // 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) @@ -289,7 +318,7 @@ bool Kernel::BootIOS(const u64 ios_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); + s_ios = std::make_unique(ios_title_id); return true; } @@ -299,10 +328,16 @@ void Kernel::AddDevice(std::unique_ptr device) m_device_map[device->GetDeviceName()] = std::move(device); } +void Kernel::AddCoreDevices() +{ + std::lock_guard lock(m_device_map_mutex); + AddDevice(std::make_unique(*this, "/dev/fs")); + AddDevice(std::make_unique(*this, "/dev/es")); +} + 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")); @@ -311,8 +346,6 @@ void Kernel::AddStaticDevices() 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")); @@ -351,6 +384,11 @@ std::shared_ptr Kernel::GetDeviceByName(const std::string& devic return iterator != m_device_map.end() ? iterator->second : nullptr; } +std::shared_ptr EmulationKernel::GetDeviceByName(const std::string& device_name) +{ + return Kernel::GetDeviceByName(device_name); +} + // Returns the FD for the newly opened device (on success) or an error code. s32 Kernel::OpenDevice(OpenRequest& request) { @@ -639,7 +677,7 @@ void Init() }); // Start with IOS80 to simulate part of the Wii boot process. - s_ios = std::make_unique(IOS80_TITLE_ID); + 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 @@ -653,7 +691,7 @@ void Shutdown() s_ios.reset(); } -Kernel* GetIOS() +EmulationKernel* GetIOS() { return s_ios.get(); } diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h index ffc469c882..b9d540b7ba 100644 --- a/Source/Core/Core/IOS/IOS.h +++ b/Source/Core/Core/IOS/IOS.h @@ -31,6 +31,8 @@ namespace HLE namespace Device { class Device; +class ES; +class FS; } struct Request; @@ -84,8 +86,8 @@ enum ProcessId : u32 class Kernel { public: - explicit Kernel(u64 ios_title_id); - ~Kernel(); + Kernel(); + virtual ~Kernel(); void DoState(PointerWrap& p); void HandleIPCEvent(u64 userdata); @@ -93,7 +95,11 @@ public: void UpdateDevices(); void UpdateWantDeterminism(bool new_want_determinism); - std::shared_ptr GetDeviceByName(const std::string& device_name); + // These are *always* part of the IOS kernel and always available. + // They are also the only available resource managers even before loading any module. + std::shared_ptr GetFS(); + std::shared_ptr GetES(); + void SDIO_EventNotify(); void EnqueueIPCRequest(u32 address); @@ -111,13 +117,15 @@ public: IOSC& GetIOSC(); -private: +protected: 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 AddCoreDevices(); void AddStaticDevices(); + std::shared_ptr GetDeviceByName(const std::string& device_name); s32 GetFreeDeviceID(); s32 OpenDevice(OpenRequest& request); @@ -140,10 +148,22 @@ private: IOSC m_iosc; }; +// HLE for an IOS tied to emulation: base kernel which may have additional modules loaded. +class EmulationKernel : public Kernel +{ +public: + explicit EmulationKernel(u64 ios_title_id); + ~EmulationKernel(); + + // Get a resource manager by name. + // This only works for devices which are part of the device map. + std::shared_ptr GetDeviceByName(const std::string& device_name); +}; + // Used for controlling and accessing an IOS instance that is tied to emulation. void Init(); void Shutdown(); -Kernel* GetIOS(); +EmulationKernel* GetIOS(); } // namespace HLE } // namespace IOS diff --git a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp index 390a266e41..e72de9cdfe 100644 --- a/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp +++ b/Source/Core/Core/IOS/USB/OH0/OH0Device.cpp @@ -45,7 +45,7 @@ OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, D void OH0Device::DoState(PointerWrap& p) { - m_oh0 = std::static_pointer_cast(m_ios.GetDeviceByName("/dev/usb/oh0")); + m_oh0 = std::static_pointer_cast(GetIOS()->GetDeviceByName("/dev/usb/oh0")); p.Do(m_name); p.Do(m_vid); p.Do(m_pid); @@ -61,7 +61,7 @@ ReturnCode OH0Device::Open(const OpenRequest& request) if (m_vid == 0 && m_pid == 0) return IPC_ENOENT; - m_oh0 = std::static_pointer_cast(m_ios.GetDeviceByName("/dev/usb/oh0")); + m_oh0 = std::static_pointer_cast(GetIOS()->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/WFS/WFSI.cpp b/Source/Core/Core/IOS/WFS/WFSI.cpp index c6d26640f7..a5464151b6 100644 --- a/Source/Core/Core/IOS/WFS/WFSI.cpp +++ b/Source/Core/Core/IOS/WFS/WFSI.cpp @@ -109,7 +109,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size); m_tmd.SetBytes(std::move(tmd_bytes)); - ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId()); + IOS::ES::TicketReader ticket = DiscIO::FindSignedTicket(m_tmd.GetTitleId()); if (!ticket.IsValid()) { return_error_code = -11028; @@ -134,7 +134,7 @@ IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request) // Initializes the IV from the index of the content in the TMD contents. u32 content_id = Memory::Read_U32(request.buffer_in + 8); - ES::Content content_info; + IOS::ES::Content content_info; if (!m_tmd.FindContentById(content_id, &content_info)) { WARN_LOG(IOS, "%s: Content id %08x not found", ioctl_name, content_id);