mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
IOS HLE: Deduplicate request code in WII_IPC_HLE
This commit is contained in:
@ -180,7 +180,7 @@ void Reset(bool hard)
|
|||||||
{
|
{
|
||||||
if (!device)
|
if (!device)
|
||||||
continue;
|
continue;
|
||||||
device->Close(0, true);
|
device->Close();
|
||||||
device.reset();
|
device.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,12 +348,10 @@ static std::shared_ptr<IWII_IPC_HLE_Device> GetUnusedESDevice()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the FD for the newly opened device (on success) or an error code.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
static s32 OpenDevice(const u32 address)
|
static s32 OpenDevice(const IOSOpenRequest& request)
|
||||||
{
|
{
|
||||||
const std::string device_name = Memory::GetString(Memory::Read_U32(address + 0xC));
|
|
||||||
const u32 open_mode = Memory::Read_U32(address + 0x10);
|
|
||||||
const s32 new_fd = GetFreeDeviceID();
|
const s32 new_fd = GetFreeDeviceID();
|
||||||
INFO_LOG(WII_IPC_HLE, "Opening %s (mode %d, fd %d)", device_name.c_str(), open_mode, new_fd);
|
INFO_LOG(WII_IPC_HLE, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd);
|
||||||
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
|
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_HLE, "Couldn't get a free fd, too many open files");
|
ERROR_LOG(WII_IPC_HLE, "Couldn't get a free fd, too many open files");
|
||||||
@ -361,80 +359,78 @@ static s32 OpenDevice(const u32 address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<IWII_IPC_HLE_Device> device;
|
std::shared_ptr<IWII_IPC_HLE_Device> device;
|
||||||
if (device_name.find("/dev/es") == 0)
|
if (request.path == "/dev/es")
|
||||||
{
|
{
|
||||||
device = GetUnusedESDevice();
|
device = GetUnusedESDevice();
|
||||||
if (!device)
|
if (!device)
|
||||||
return IPC_EESEXHAUSTED;
|
return IPC_EESEXHAUSTED;
|
||||||
}
|
}
|
||||||
else if (device_name.find("/dev/") == 0)
|
else if (request.path.find("/dev/") == 0)
|
||||||
{
|
{
|
||||||
device = GetDeviceByName(device_name);
|
device = GetDeviceByName(request.path);
|
||||||
}
|
}
|
||||||
else if (device_name.find('/') == 0)
|
else if (request.path.find('/') == 0)
|
||||||
{
|
{
|
||||||
device = std::make_shared<CWII_IPC_HLE_Device_FileIO>(new_fd, device_name);
|
device = std::make_shared<CWII_IPC_HLE_Device_FileIO>(new_fd, request.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device)
|
if (!device)
|
||||||
{
|
{
|
||||||
ERROR_LOG(WII_IPC_HLE, "Unknown device: %s", device_name.c_str());
|
ERROR_LOG(WII_IPC_HLE, "Unknown device: %s", request.path.c_str());
|
||||||
return IPC_ENOENT;
|
return IPC_ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory::Write_U32(new_fd, address + 4);
|
const IOSReturnCode code = device->Open(request);
|
||||||
device->Open(address, open_mode);
|
if (code < IPC_SUCCESS)
|
||||||
const s32 open_return_code = Memory::Read_U32(address + 4);
|
return code;
|
||||||
if (open_return_code < 0)
|
|
||||||
return open_return_code;
|
|
||||||
s_fdmap[new_fd] = device;
|
s_fdmap[new_fd] = device;
|
||||||
return new_fd;
|
return new_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IPCCommandResult HandleCommand(const u32 address)
|
static IPCCommandResult HandleCommand(const IOSRequest& request)
|
||||||
{
|
{
|
||||||
const auto command = static_cast<IPCCommandType>(Memory::Read_U32(address));
|
if (request.command == IPC_CMD_OPEN)
|
||||||
if (command == IPC_CMD_OPEN)
|
|
||||||
{
|
{
|
||||||
const s32 new_fd = OpenDevice(address);
|
IOSOpenRequest open_request{request.address};
|
||||||
Memory::Write_U32(new_fd, address + 4);
|
const s32 new_fd = OpenDevice(open_request);
|
||||||
|
open_request.SetReturnValue(new_fd);
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
const s32 fd = Memory::Read_U32(address + 8);
|
const auto device = (request.fd < IPC_MAX_FDS) ? s_fdmap[request.fd] : nullptr;
|
||||||
const auto device = (fd >= 0 && fd < IPC_MAX_FDS) ? s_fdmap[fd] : nullptr;
|
|
||||||
if (!device)
|
if (!device)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(IPC_EINVAL, address + 4);
|
request.SetReturnValue(IPC_EINVAL);
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (command)
|
switch (request.command)
|
||||||
{
|
{
|
||||||
case IPC_CMD_CLOSE:
|
case IPC_CMD_CLOSE:
|
||||||
s_fdmap[fd].reset();
|
s_fdmap[request.fd].reset();
|
||||||
// A close on a valid device returns IPC_SUCCESS.
|
device->Close();
|
||||||
Memory::Write_U32(IPC_SUCCESS, address + 4);
|
request.SetReturnValue(IPC_SUCCESS);
|
||||||
return device->Close(address);
|
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||||
case IPC_CMD_READ:
|
case IPC_CMD_READ:
|
||||||
return device->Read(address);
|
return device->Read(IOSReadWriteRequest{request.address});
|
||||||
case IPC_CMD_WRITE:
|
case IPC_CMD_WRITE:
|
||||||
return device->Write(address);
|
return device->Write(IOSReadWriteRequest{request.address});
|
||||||
case IPC_CMD_SEEK:
|
case IPC_CMD_SEEK:
|
||||||
return device->Seek(address);
|
return device->Seek(IOSSeekRequest{request.address});
|
||||||
case IPC_CMD_IOCTL:
|
case IPC_CMD_IOCTL:
|
||||||
return device->IOCtl(address);
|
return device->IOCtl(IOSIOCtlRequest{request.address});
|
||||||
case IPC_CMD_IOCTLV:
|
case IPC_CMD_IOCTLV:
|
||||||
return device->IOCtlV(address);
|
return device->IOCtlV(IOSIOCtlVRequest{request.address});
|
||||||
default:
|
default:
|
||||||
_assert_msg_(WII_IPC_HLE, false, "Unexpected command: %x", command);
|
_assert_msg_(WII_IPC_HLE, false, "Unexpected command: %x", request.command);
|
||||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteCommand(const u32 address)
|
void ExecuteCommand(const u32 address)
|
||||||
{
|
{
|
||||||
IPCCommandResult result = HandleCommand(address);
|
IOSRequest request{address};
|
||||||
|
IPCCommandResult result = HandleCommand(request);
|
||||||
|
|
||||||
// Ensure replies happen in order
|
// Ensure replies happen in order
|
||||||
const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks();
|
const s64 ticks_until_last_reply = s_last_reply_time - CoreTiming::GetTicks();
|
||||||
@ -443,7 +439,7 @@ void ExecuteCommand(const u32 address)
|
|||||||
s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
|
s_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
|
||||||
|
|
||||||
if (result.send_reply)
|
if (result.send_reply)
|
||||||
EnqueueReply(address, static_cast<int>(result.reply_delay_ticks));
|
EnqueueReply(request, static_cast<int>(result.reply_delay_ticks));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Happens AS SOON AS IPC gets a new pointer!
|
// Happens AS SOON AS IPC gets a new pointer!
|
||||||
@ -453,13 +449,18 @@ void EnqueueRequest(u32 address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called to send a reply to an IOS syscall
|
// Called to send a reply to an IOS syscall
|
||||||
void EnqueueReply(u32 address, int cycles_in_future, CoreTiming::FromThread from)
|
void EnqueueReply(const IOSRequest& request, int cycles_in_future, CoreTiming::FromThread from)
|
||||||
{
|
{
|
||||||
// IOS writes back the command that was responded to in the FD field.
|
// IOS writes back the command that was responded to in the FD field.
|
||||||
Memory::Write_U32(Memory::Read_U32(address), address + 8);
|
Memory::Write_U32(request.command, request.address + 8);
|
||||||
// IOS also overwrites the command type with the reply type.
|
// IOS also overwrites the command type with the reply type.
|
||||||
Memory::Write_U32(IPC_REPLY, address);
|
Memory::Write_U32(IPC_REPLY, request.address);
|
||||||
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, address, from);
|
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnqueueReply(u32 command_address, int cycles_in_future, CoreTiming::FromThread from)
|
||||||
|
{
|
||||||
|
EnqueueReply(IOSRequest{command_address}, cycles_in_future, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/SystemTimers.h"
|
#include "Core/HW/SystemTimers.h"
|
||||||
|
|
||||||
|
struct IOSRequest;
|
||||||
class IWII_IPC_HLE_Device;
|
class IWII_IPC_HLE_Device;
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
|
||||||
@ -69,7 +70,9 @@ void UpdateDevices();
|
|||||||
void ExecuteCommand(u32 address);
|
void ExecuteCommand(u32 address);
|
||||||
|
|
||||||
void EnqueueRequest(u32 address);
|
void EnqueueRequest(u32 address);
|
||||||
void EnqueueReply(u32 address, int cycles_in_future = 0,
|
void EnqueueReply(const IOSRequest& request, int cycles_in_future = 0,
|
||||||
|
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
||||||
|
void EnqueueReply(u32 command_address, int cycles_in_future = 0,
|
||||||
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
|
||||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
|
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user