IOS HLE: Deduplicate request code in WII_IPC_HLE
This commit is contained in:
parent
d8b9b3825c
commit
e2d072250f
|
@ -180,7 +180,7 @@ void Reset(bool hard)
|
|||
{
|
||||
if (!device)
|
||||
continue;
|
||||
device->Close(0, true);
|
||||
device->Close();
|
||||
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.
|
||||
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();
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (device_name.find("/dev/es") == 0)
|
||||
if (request.path == "/dev/es")
|
||||
{
|
||||
device = GetUnusedESDevice();
|
||||
if (!device)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Memory::Write_U32(new_fd, address + 4);
|
||||
device->Open(address, open_mode);
|
||||
const s32 open_return_code = Memory::Read_U32(address + 4);
|
||||
if (open_return_code < 0)
|
||||
return open_return_code;
|
||||
const IOSReturnCode code = device->Open(request);
|
||||
if (code < IPC_SUCCESS)
|
||||
return code;
|
||||
s_fdmap[new_fd] = device;
|
||||
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 (command == IPC_CMD_OPEN)
|
||||
if (request.command == IPC_CMD_OPEN)
|
||||
{
|
||||
const s32 new_fd = OpenDevice(address);
|
||||
Memory::Write_U32(new_fd, address + 4);
|
||||
IOSOpenRequest open_request{request.address};
|
||||
const s32 new_fd = OpenDevice(open_request);
|
||||
open_request.SetReturnValue(new_fd);
|
||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||
}
|
||||
|
||||
const s32 fd = Memory::Read_U32(address + 8);
|
||||
const auto device = (fd >= 0 && fd < IPC_MAX_FDS) ? s_fdmap[fd] : nullptr;
|
||||
const auto device = (request.fd < IPC_MAX_FDS) ? s_fdmap[request.fd] : nullptr;
|
||||
if (!device)
|
||||
{
|
||||
Memory::Write_U32(IPC_EINVAL, address + 4);
|
||||
request.SetReturnValue(IPC_EINVAL);
|
||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||
}
|
||||
|
||||
switch (command)
|
||||
switch (request.command)
|
||||
{
|
||||
case IPC_CMD_CLOSE:
|
||||
s_fdmap[fd].reset();
|
||||
// A close on a valid device returns IPC_SUCCESS.
|
||||
Memory::Write_U32(IPC_SUCCESS, address + 4);
|
||||
return device->Close(address);
|
||||
s_fdmap[request.fd].reset();
|
||||
device->Close();
|
||||
request.SetReturnValue(IPC_SUCCESS);
|
||||
return IWII_IPC_HLE_Device::GetDefaultReply();
|
||||
case IPC_CMD_READ:
|
||||
return device->Read(address);
|
||||
return device->Read(IOSReadWriteRequest{request.address});
|
||||
case IPC_CMD_WRITE:
|
||||
return device->Write(address);
|
||||
return device->Write(IOSReadWriteRequest{request.address});
|
||||
case IPC_CMD_SEEK:
|
||||
return device->Seek(address);
|
||||
return device->Seek(IOSSeekRequest{request.address});
|
||||
case IPC_CMD_IOCTL:
|
||||
return device->IOCtl(address);
|
||||
return device->IOCtl(IOSIOCtlRequest{request.address});
|
||||
case IPC_CMD_IOCTLV:
|
||||
return device->IOCtlV(address);
|
||||
return device->IOCtlV(IOSIOCtlVRequest{request.address});
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteCommand(const u32 address)
|
||||
{
|
||||
IPCCommandResult result = HandleCommand(address);
|
||||
IOSRequest request{address};
|
||||
IPCCommandResult result = HandleCommand(request);
|
||||
|
||||
// Ensure replies happen in order
|
||||
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;
|
||||
|
||||
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!
|
||||
|
@ -453,13 +449,18 @@ void EnqueueRequest(u32 address)
|
|||
}
|
||||
|
||||
// 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.
|
||||
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.
|
||||
Memory::Write_U32(IPC_REPLY, address);
|
||||
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, address, from);
|
||||
Memory::Write_U32(IPC_REPLY, request.address);
|
||||
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)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
|
||||
struct IOSRequest;
|
||||
class IWII_IPC_HLE_Device;
|
||||
class PointerWrap;
|
||||
|
||||
|
@ -69,7 +70,9 @@ void UpdateDevices();
|
|||
void ExecuteCommand(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);
|
||||
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue