IOS: Leverage Kernel/EmulationKernel difference for passing System to most IOS devices.

This commit is contained in:
Admiral H. Curtiss
2023-04-23 19:38:11 +02:00
parent ba150a6824
commit 15a0860f15
59 changed files with 505 additions and 429 deletions

View File

@ -319,7 +319,8 @@ Kernel::Kernel(u64 title_id) : m_title_id(title_id)
{
}
EmulationKernel::EmulationKernel(u64 title_id) : Kernel(title_id)
EmulationKernel::EmulationKernel(Core::System& system, u64 title_id)
: Kernel(title_id), m_system(system)
{
INFO_LOG_FMT(IOS, "Starting IOS {:016x}", title_id);
@ -364,7 +365,7 @@ std::shared_ptr<ESDevice> Kernel::GetES()
return std::static_pointer_cast<ESDevice>(m_device_map.at("/dev/es"));
}
std::shared_ptr<WiiSockMan> Kernel::GetSocketManager()
std::shared_ptr<WiiSockMan> EmulationKernel::GetSocketManager()
{
return m_socket_manager;
}
@ -462,11 +463,11 @@ private:
std::vector<u8> m_bytes;
};
static void FinishIOSBoot(u64 ios_title_id)
static void FinishIOSBoot(Core::System& system, u64 ios_title_id)
{
// Shut down the active IOS first before switching to the new one.
s_ios.reset();
s_ios = std::make_unique<EmulationKernel>(ios_title_id);
s_ios = std::make_unique<EmulationKernel>(system, ios_title_id);
}
static constexpr SystemTimers::TimeBaseTick GetIOSBootTicks(u32 version)
@ -515,7 +516,7 @@ bool Kernel::BootIOS(Core::System& system, const u64 ios_title_id, HangPPC hang_
}
else
{
FinishIOSBoot(ios_title_id);
FinishIOSBoot(system, ios_title_id);
}
return true;
@ -546,7 +547,7 @@ void Kernel::AddCoreDevices()
AddDevice(std::make_unique<ESDevice>(*this, "/dev/es"));
}
void Kernel::AddStaticDevices()
void EmulationKernel::AddStaticDevices()
{
std::lock_guard lock(m_device_map_mutex);
@ -623,7 +624,7 @@ void Kernel::AddStaticDevices()
}
}
s32 Kernel::GetFreeDeviceID()
s32 EmulationKernel::GetFreeDeviceID()
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
@ -649,7 +650,7 @@ std::shared_ptr<Device> EmulationKernel::GetDeviceByName(std::string_view device
}
// Returns the FD for the newly opened device (on success) or an error code.
std::optional<IPCReply> Kernel::OpenDevice(OpenRequest& request)
std::optional<IPCReply> EmulationKernel::OpenDevice(OpenRequest& request)
{
const s32 new_fd = GetFreeDeviceID();
INFO_LOG_FMT(IOS, "Opening {} (mode {}, fd {})", request.path, static_cast<u32>(request.flags),
@ -691,14 +692,14 @@ std::optional<IPCReply> Kernel::OpenDevice(OpenRequest& request)
return result;
}
std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
std::optional<IPCReply> EmulationKernel::HandleIPCCommand(const Request& request)
{
if (request.command < IPC_CMD_OPEN || request.command > IPC_CMD_IOCTLV)
return IPCReply{IPC_EINVAL, 978_tbticks};
if (request.command == IPC_CMD_OPEN)
{
OpenRequest open_request{request.address};
OpenRequest open_request{GetSystem(), request.address};
return OpenDevice(open_request);
}
@ -716,19 +717,19 @@ std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
ret = device->Close(request.fd);
break;
case IPC_CMD_READ:
ret = device->Read(ReadWriteRequest{request.address});
ret = device->Read(ReadWriteRequest{GetSystem(), request.address});
break;
case IPC_CMD_WRITE:
ret = device->Write(ReadWriteRequest{request.address});
ret = device->Write(ReadWriteRequest{GetSystem(), request.address});
break;
case IPC_CMD_SEEK:
ret = device->Seek(SeekRequest{request.address});
ret = device->Seek(SeekRequest{GetSystem(), request.address});
break;
case IPC_CMD_IOCTL:
ret = device->IOCtl(IOCtlRequest{request.address});
ret = device->IOCtl(IOCtlRequest{GetSystem(), request.address});
break;
case IPC_CMD_IOCTLV:
ret = device->IOCtlV(IOCtlVRequest{request.address});
ret = device->IOCtlV(IOCtlVRequest{GetSystem(), request.address});
break;
default:
ASSERT_MSG(IOS, false, "Unexpected command: {:#x}", static_cast<u32>(request.command));
@ -747,17 +748,16 @@ std::optional<IPCReply> Kernel::HandleIPCCommand(const Request& request)
return ret;
}
void Kernel::ExecuteIPCCommand(const u32 address)
void EmulationKernel::ExecuteIPCCommand(const u32 address)
{
Request request{address};
Request request{GetSystem(), address};
std::optional<IPCReply> result = HandleIPCCommand(request);
if (!result)
return;
// Ensure replies happen in order
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& core_timing = GetSystem().GetCoreTiming();
const s64 ticks_until_last_reply = m_last_reply_time - core_timing.GetTicks();
if (ticks_until_last_reply > 0)
result->reply_delay_ticks += ticks_until_last_reply;
@ -767,20 +767,20 @@ void Kernel::ExecuteIPCCommand(const u32 address)
}
// Happens AS SOON AS IPC gets a new pointer!
void Kernel::EnqueueIPCRequest(u32 address)
void EmulationKernel::EnqueueIPCRequest(u32 address)
{
// Based on hardware tests, IOS takes between 5µs and 10µs to acknowledge an IPC request.
// Console 1: 456 TB ticks before ACK
// Console 2: 658 TB ticks before ACK
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(500_tbticks, s_event_enqueue,
address | ENQUEUE_REQUEST_FLAG);
GetSystem().GetCoreTiming().ScheduleEvent(500_tbticks, 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, s64 cycles_in_future,
CoreTiming::FromThread from)
void EmulationKernel::EnqueueIPCReply(const Request& request, const s32 return_value,
s64 cycles_in_future, CoreTiming::FromThread from)
{
auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(return_value), request.address + 4);
// IOS writes back the command that was responded to in the FD field.
@ -790,7 +790,7 @@ void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, s64
system.GetCoreTiming().ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
}
void Kernel::HandleIPCEvent(u64 userdata)
void EmulationKernel::HandleIPCEvent(u64 userdata)
{
if (userdata & ENQUEUE_REQUEST_FLAG)
m_request_queue.push_back(static_cast<u32>(userdata));
@ -800,7 +800,7 @@ void Kernel::HandleIPCEvent(u64 userdata)
UpdateIPC();
}
void Kernel::UpdateIPC()
void EmulationKernel::UpdateIPC()
{
if (m_ipc_paused || !IsReady())
return;
@ -824,7 +824,7 @@ void Kernel::UpdateIPC()
}
}
void Kernel::UpdateDevices()
void EmulationKernel::UpdateDevices()
{
// Check if a hardware device must be updated
for (const auto& entry : m_device_map)
@ -836,7 +836,7 @@ void Kernel::UpdateDevices()
}
}
void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
void EmulationKernel::UpdateWantDeterminism(const bool new_want_determinism)
{
if (m_socket_manager)
m_socket_manager->UpdateWantDeterminism(new_want_determinism);
@ -844,7 +844,7 @@ void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
device.second->UpdateWantDeterminism(new_want_determinism);
}
void Kernel::DoState(PointerWrap& p)
void EmulationKernel::DoState(PointerWrap& p)
{
p.Do(m_request_queue);
p.Do(m_reply_queue);
@ -954,15 +954,15 @@ void Init()
s_event_finish_ppc_bootstrap =
core_timing.RegisterEvent("IOSFinishPPCBootstrap", FinishPPCBootstrap);
s_event_finish_ios_boot =
core_timing.RegisterEvent("IOSFinishIOSBoot", [](Core::System& system_, u64 ios_title_id,
s64) { FinishIOSBoot(ios_title_id); });
s_event_finish_ios_boot = core_timing.RegisterEvent(
"IOSFinishIOSBoot",
[](Core::System& system_, u64 ios_title_id, s64) { FinishIOSBoot(system_, ios_title_id); });
DIDevice::s_finish_executing_di_command =
core_timing.RegisterEvent("FinishDICommand", DIDevice::FinishDICommandCallback);
// Start with IOS80 to simulate part of the Wii boot process.
s_ios = std::make_unique<EmulationKernel>(Titles::SYSTEM_MENU_IOS);
s_ios = std::make_unique<EmulationKernel>(system, Titles::SYSTEM_MENU_IOS);
// 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