IOS HLE: Deduplicate request code in WII_IPC_HLE

This commit is contained in:
Léo Lam
2017-01-15 01:43:00 +01:00
parent d8b9b3825c
commit e2d072250f
2 changed files with 46 additions and 42 deletions

View File

@ -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)

View File

@ -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);