Merge pull request #4661 from leoetlino/ios-request

IOS HLE: Deduplicate the request parsing code
This commit is contained in:
Matthew Parlane
2017-01-18 08:38:37 +13:00
committed by GitHub
43 changed files with 1348 additions and 1965 deletions
+39 -46
View File
@@ -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,73 @@ 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);
return IWII_IPC_HLE_Device::GetDefaultReply();
IOSOpenRequest open_request{request.address};
const s32 new_fd = OpenDevice(open_request);
return IWII_IPC_HLE_Device::GetDefaultReply(new_fd);
}
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);
return IWII_IPC_HLE_Device::GetDefaultReply();
}
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_EINVAL);
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();
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_SUCCESS);
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);
return IWII_IPC_HLE_Device::GetDefaultReply();
_assert_msg_(WII_IPC_HLE, false, "Unexpected command: %x", request.command);
return IWII_IPC_HLE_Device::GetDefaultReply(IPC_EINVAL);
}
}
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 +434,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, result.return_value, static_cast<int>(result.reply_delay_ticks));
}
// Happens AS SOON AS IPC gets a new pointer!
@@ -453,13 +444,15 @@ 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, const s32 return_value, int cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
// 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 EnqueueCommandAcknowledgement(u32 address, int cycles_in_future)
+3 -1
View File
@@ -12,11 +12,13 @@
#include "Core/CoreTiming.h"
#include "Core/HW/SystemTimers.h"
struct IOSRequest;
class IWII_IPC_HLE_Device;
class PointerWrap;
struct IPCCommandResult
{
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
@@ -69,7 +71,7 @@ void UpdateDevices();
void ExecuteCommand(u32 address);
void EnqueueRequest(u32 address);
void EnqueueReply(u32 address, int cycles_in_future = 0,
void EnqueueReply(const IOSRequest& request, s32 return_value, int cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
+117 -125
View File
@@ -2,48 +2,119 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include <algorithm>
#include <map>
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device.h"
SIOCtlVBuffer::SIOCtlVBuffer(const u32 address) : m_Address(address)
IOSRequest::IOSRequest(const u32 address_) : address(address_)
{
// These are the Ioctlv parameters in the IOS communication. The BufferVector
// is a memory address offset at where the in and out buffer addresses are
// stored.
Parameter = Memory::Read_U32(m_Address + 0x0C); // command 3, arg0
NumberInBuffer = Memory::Read_U32(m_Address + 0x10); // 4, arg1
NumberPayloadBuffer = Memory::Read_U32(m_Address + 0x14); // 5, arg2
BufferVector = Memory::Read_U32(m_Address + 0x18); // 6, arg3
command = static_cast<IPCCommandType>(Memory::Read_U32(address));
fd = Memory::Read_U32(address + 8);
}
// The start of the out buffer
u32 BufferVectorOffset = BufferVector;
IOSOpenRequest::IOSOpenRequest(const u32 address_) : IOSRequest(address_)
{
path = Memory::GetString(Memory::Read_U32(address + 0xc));
flags = static_cast<IOSOpenMode>(Memory::Read_U32(address + 0x10));
}
// Write the address and size for all in messages
for (u32 i = 0; i < NumberInBuffer; i++)
IOSReadWriteRequest::IOSReadWriteRequest(const u32 address_) : IOSRequest(address_)
{
buffer = Memory::Read_U32(address + 0xc);
size = Memory::Read_U32(address + 0x10);
}
IOSSeekRequest::IOSSeekRequest(const u32 address_) : IOSRequest(address_)
{
offset = Memory::Read_U32(address + 0xc);
mode = static_cast<SeekMode>(Memory::Read_U32(address + 0x10));
}
IOSIOCtlRequest::IOSIOCtlRequest(const u32 address_) : IOSRequest(address_)
{
request = Memory::Read_U32(address + 0x0c);
buffer_in = Memory::Read_U32(address + 0x10);
buffer_in_size = Memory::Read_U32(address + 0x14);
buffer_out = Memory::Read_U32(address + 0x18);
buffer_out_size = Memory::Read_U32(address + 0x1c);
}
IOSIOCtlVRequest::IOSIOCtlVRequest(const u32 address_) : IOSRequest(address_)
{
request = Memory::Read_U32(address + 0x0c);
const u32 in_number = Memory::Read_U32(address + 0x10);
const u32 out_number = Memory::Read_U32(address + 0x14);
const u32 vectors_base = Memory::Read_U32(address + 0x18); // address to vectors
u32 offset = 0;
for (size_t i = 0; i < (in_number + out_number); ++i)
{
SBuffer Buffer;
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
InBuffer.push_back(Buffer);
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer in%i: 0x%08x, 0x%x", i, Buffer.m_Address, Buffer.m_Size);
IOVector vector;
vector.address = Memory::Read_U32(vectors_base + offset);
vector.size = Memory::Read_U32(vectors_base + offset + 4);
offset += 8;
if (i < in_number)
in_vectors.emplace_back(vector);
else
io_vectors.emplace_back(vector);
}
}
// Write the address and size for all out or in-out messages
for (u32 i = 0; i < NumberPayloadBuffer; i++)
{
SBuffer Buffer;
Buffer.m_Address = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
Buffer.m_Size = Memory::Read_U32(BufferVectorOffset);
BufferVectorOffset += 4;
PayloadBuffer.push_back(Buffer);
DEBUG_LOG(WII_IPC_HLE, "SIOCtlVBuffer io%i: 0x%08x, 0x%x", i, Buffer.m_Address, Buffer.m_Size);
}
bool IOSIOCtlVRequest::HasInputVectorWithAddress(const u32 vector_address) const
{
return std::any_of(in_vectors.begin(), in_vectors.end(),
[&](const auto& in_vector) { return in_vector.address == vector_address; });
}
void IOSIOCtlRequest::Log(const std::string& device_name, LogTypes::LOG_TYPE type,
LogTypes::LOG_LEVELS verbosity) const
{
GENERIC_LOG(type, verbosity, "%s (fd %u) - IOCtl 0x%x (in_size=0x%x, out_size=0x%x)",
device_name.c_str(), fd, request, buffer_in_size, buffer_out_size);
}
void IOSIOCtlRequest::Dump(const std::string& description, LogTypes::LOG_TYPE type,
LogTypes::LOG_LEVELS level) const
{
Log("===== " + description, type, level);
GENERIC_LOG(type, level, "In buffer\n%s",
HexDump(Memory::GetPointer(buffer_in), buffer_in_size).c_str());
GENERIC_LOG(type, level, "Out buffer\n%s",
HexDump(Memory::GetPointer(buffer_out), buffer_out_size).c_str());
}
void IOSIOCtlRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type,
LogTypes::LOG_LEVELS level) const
{
Dump("Unknown IOCtl - " + description, type, level);
}
void IOSIOCtlVRequest::Dump(const std::string& description, LogTypes::LOG_TYPE type,
LogTypes::LOG_LEVELS level) const
{
GENERIC_LOG(type, level, "===== %s (fd %u) - IOCtlV 0x%x (%zu in, %zu io)", description.c_str(),
fd, request, in_vectors.size(), io_vectors.size());
size_t i = 0;
for (const auto& vector : in_vectors)
GENERIC_LOG(type, level, "in[%zu] (size=0x%x):\n%s", i++, vector.size,
HexDump(Memory::GetPointer(vector.address), vector.size).c_str());
i = 0;
for (const auto& vector : io_vectors)
GENERIC_LOG(type, level, "io[%zu] (size=0x%x)", i++, vector.size);
}
void IOSIOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type,
LogTypes::LOG_LEVELS level) const
{
Dump("Unknown IOCtlV - " + description, type, level);
}
IWII_IPC_HLE_Device::IWII_IPC_HLE_Device(const u32 device_id, const std::string& device_name,
@@ -66,116 +137,37 @@ void IWII_IPC_HLE_Device::DoStateShared(PointerWrap& p)
p.Do(m_is_active);
}
IPCCommandResult IWII_IPC_HLE_Device::Open(u32 command_address, u32 mode)
IOSReturnCode IWII_IPC_HLE_Device::Open(const IOSOpenRequest& request)
{
m_is_active = true;
return GetDefaultReply();
return IPC_SUCCESS;
}
IPCCommandResult IWII_IPC_HLE_Device::Close(u32 command_address, bool force)
void IWII_IPC_HLE_Device::Close()
{
m_is_active = false;
return GetDefaultReply();
}
IPCCommandResult IWII_IPC_HLE_Device::Seek(u32 command_address)
IPCCommandResult IWII_IPC_HLE_Device::Unsupported(const IOSRequest& request)
{
WARN_LOG(WII_IPC_HLE, "%s does not support Seek()", m_name.c_str());
Memory::Write_U32(IPC_EINVAL, command_address);
return GetDefaultReply();
}
IPCCommandResult IWII_IPC_HLE_Device::Read(u32 command_address)
{
WARN_LOG(WII_IPC_HLE, "%s does not support Read()", m_name.c_str());
Memory::Write_U32(IPC_EINVAL, command_address);
return GetDefaultReply();
}
IPCCommandResult IWII_IPC_HLE_Device::Write(u32 command_address)
{
WARN_LOG(WII_IPC_HLE, "%s does not support Write()", m_name.c_str());
Memory::Write_U32(IPC_EINVAL, command_address);
return GetDefaultReply();
}
IPCCommandResult IWII_IPC_HLE_Device::IOCtl(u32 command_address)
{
WARN_LOG(WII_IPC_HLE, "%s does not support IOCtl()", m_name.c_str());
Memory::Write_U32(IPC_EINVAL, command_address);
return GetDefaultReply();
}
IPCCommandResult IWII_IPC_HLE_Device::IOCtlV(u32 command_address)
{
WARN_LOG(WII_IPC_HLE, "%s does not support IOCtlV()", m_name.c_str());
Memory::Write_U32(IPC_EINVAL, command_address);
return GetDefaultReply();
static std::map<IPCCommandType, std::string> names = {{{IPC_CMD_READ, "Read"},
{IPC_CMD_WRITE, "Write"},
{IPC_CMD_SEEK, "Seek"},
{IPC_CMD_IOCTL, "IOCtl"},
{IPC_CMD_IOCTLV, "IOCtlV"}}};
WARN_LOG(WII_IPC_HLE, "%s does not support %s()", m_name.c_str(), names[request.command].c_str());
return GetDefaultReply(IPC_EINVAL);
}
// Returns an IPCCommandResult for a reply that takes 250 us (arbitrarily chosen value)
IPCCommandResult IWII_IPC_HLE_Device::GetDefaultReply()
IPCCommandResult IWII_IPC_HLE_Device::GetDefaultReply(const s32 return_value)
{
return {true, SystemTimers::GetTicksPerSecond() / 4000};
return {return_value, true, SystemTimers::GetTicksPerSecond() / 4000};
}
// Returns an IPCCommandResult with no reply. Useful for async commands that will generate a reply
// later
// later. This takes no return value because it won't be used.
IPCCommandResult IWII_IPC_HLE_Device::GetNoReply()
{
return {false, 0};
}
// Write out the IPC struct from command_address to num_commands numbers
// of 4 byte commands.
void IWII_IPC_HLE_Device::DumpCommands(u32 command_address, size_t num_commands,
LogTypes::LOG_TYPE log_type, LogTypes::LOG_LEVELS verbosity)
{
GENERIC_LOG(log_type, verbosity, "CommandDump of %s", GetDeviceName().c_str());
for (u32 i = 0; i < num_commands; i++)
{
GENERIC_LOG(log_type, verbosity, " Command%02i: 0x%08x", i,
Memory::Read_U32(command_address + i * 4));
}
}
void IWII_IPC_HLE_Device::DumpAsync(u32 buffer_vector, u32 number_in_buffer, u32 number_io_buffer,
LogTypes::LOG_TYPE log_type, LogTypes::LOG_LEVELS verbosity)
{
GENERIC_LOG(log_type, verbosity, "======= DumpAsync ======");
u32 BufferOffset = buffer_vector;
for (u32 i = 0; i < number_in_buffer; i++)
{
u32 InBuffer = Memory::Read_U32(BufferOffset);
BufferOffset += 4;
u32 InBufferSize = Memory::Read_U32(BufferOffset);
BufferOffset += 4;
GENERIC_LOG(log_type, LogTypes::LINFO, "%s - IOCtlV InBuffer[%i]:", GetDeviceName().c_str(), i);
std::string Temp;
for (u32 j = 0; j < InBufferSize; j++)
{
Temp += StringFromFormat("%02x ", Memory::Read_U8(InBuffer + j));
}
GENERIC_LOG(log_type, LogTypes::LDEBUG, " Buffer: %s", Temp.c_str());
}
for (u32 i = 0; i < number_io_buffer; i++)
{
u32 OutBuffer = Memory::Read_U32(BufferOffset);
BufferOffset += 4;
u32 OutBufferSize = Memory::Read_U32(BufferOffset);
BufferOffset += 4;
GENERIC_LOG(log_type, LogTypes::LINFO, "%s - IOCtlV OutBuffer[%i]:", GetDeviceName().c_str(),
i);
GENERIC_LOG(log_type, LogTypes::LINFO, " OutBuffer: 0x%08x (0x%x):", OutBuffer,
OutBufferSize);
if (verbosity >= LogTypes::LOG_LEVELS::LINFO)
DumpCommands(OutBuffer, OutBufferSize, log_type, verbosity);
}
return {IPC_SUCCESS, false, 0};
}
+89 -31
View File
@@ -11,7 +11,6 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/IPC_HLE/WII_IPC_HLE.h"
enum IOSReturnCode : s32
@@ -41,22 +40,88 @@ enum IOSReturnCode : s32
IPC_EESEXHAUSTED = -1016, // Max of 2 ES handles exceeded
};
// A struct for IOS ioctlv calls
struct SIOCtlVBuffer
struct IOSRequest
{
explicit SIOCtlVBuffer(u32 address);
u32 address = 0;
IPCCommandType command = IPC_CMD_OPEN;
u32 fd = 0;
explicit IOSRequest(u32 address);
virtual ~IOSRequest() = default;
};
const u32 m_Address;
u32 Parameter;
u32 NumberInBuffer;
u32 NumberPayloadBuffer;
u32 BufferVector;
struct SBuffer
enum IOSOpenMode : s32
{
IOS_OPEN_READ = 1,
IOS_OPEN_WRITE = 2,
IOS_OPEN_RW = (IOS_OPEN_READ | IOS_OPEN_WRITE)
};
struct IOSOpenRequest final : IOSRequest
{
std::string path;
IOSOpenMode flags = IOS_OPEN_READ;
explicit IOSOpenRequest(u32 address);
};
struct IOSReadWriteRequest final : IOSRequest
{
u32 buffer = 0;
u32 size = 0;
explicit IOSReadWriteRequest(u32 address);
};
struct IOSSeekRequest final : IOSRequest
{
enum SeekMode
{
u32 m_Address, m_Size;
IOS_SEEK_SET = 0,
IOS_SEEK_CUR = 1,
IOS_SEEK_END = 2,
};
std::vector<SBuffer> InBuffer;
std::vector<SBuffer> PayloadBuffer;
u32 offset = 0;
SeekMode mode = IOS_SEEK_SET;
explicit IOSSeekRequest(u32 address);
};
struct IOSIOCtlRequest final : IOSRequest
{
u32 request = 0;
u32 buffer_in = 0;
u32 buffer_in_size = 0;
// Contrary to the name, the output buffer can also be used for input.
u32 buffer_out = 0;
u32 buffer_out_size = 0;
explicit IOSIOCtlRequest(u32 address);
void Log(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
void Dump(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
void DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS level = LogTypes::LERROR) const;
};
struct IOSIOCtlVRequest final : IOSRequest
{
struct IOVector
{
u32 address = 0;
u32 size = 0;
};
u32 request = 0;
// In vectors are *mostly* used for input buffers. Sometimes they are also used as
// output buffers (notably in the network code).
// IO vectors are *mostly* used for output buffers. However, as indicated in the name,
// they're also used as input buffers.
// So both of them are technically IO vectors. But we're keeping them separated because
// merging them into a single std::vector would make using the first out vector more complicated.
std::vector<IOVector> in_vectors;
std::vector<IOVector> io_vectors;
explicit IOSIOCtlVRequest(u32 address);
bool HasInputVectorWithAddress(u32 vector_address) const;
void Dump(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS level = LogTypes::LINFO) const;
void DumpUnknown(const std::string& description, LogTypes::LOG_TYPE type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS level = LogTypes::LERROR) const;
};
class IWII_IPC_HLE_Device
@@ -79,18 +144,18 @@ public:
const std::string& GetDeviceName() const { return m_name; }
u32 GetDeviceID() const { return m_device_id; }
virtual IPCCommandResult Open(u32 command_address, u32 mode);
virtual IPCCommandResult Close(u32 command_address, bool force = false);
virtual IPCCommandResult Seek(u32 command_address);
virtual IPCCommandResult Read(u32 command_address);
virtual IPCCommandResult Write(u32 command_address);
virtual IPCCommandResult IOCtl(u32 command_address);
virtual IPCCommandResult IOCtlV(u32 command_address);
// Replies to Open and Close requests are sent by WII_IPC_HLE, not by the devices themselves.
virtual IOSReturnCode Open(const IOSOpenRequest& request);
virtual void Close();
virtual IPCCommandResult Seek(const IOSSeekRequest& seek) { return Unsupported(seek); }
virtual IPCCommandResult Read(const IOSReadWriteRequest& read) { return Unsupported(read); }
virtual IPCCommandResult Write(const IOSReadWriteRequest& write) { return Unsupported(write); }
virtual IPCCommandResult IOCtl(const IOSIOCtlRequest& ioctl) { return Unsupported(ioctl); }
virtual IPCCommandResult IOCtlV(const IOSIOCtlVRequest& ioctlv) { return Unsupported(ioctlv); }
virtual void Update() {}
virtual DeviceType GetDeviceType() const { return m_device_type; }
virtual bool IsOpened() const { return m_is_active; }
static IPCCommandResult GetDefaultReply();
static IPCCommandResult GetDefaultReply(s32 return_value);
static IPCCommandResult GetNoReply();
protected:
@@ -100,13 +165,6 @@ protected:
DeviceType m_device_type;
bool m_is_active = false;
// Write out the IPC struct from command_address to number_of_commands numbers
// of 4 byte commands.
void DumpCommands(u32 command_address, size_t number_of_commands = 8,
LogTypes::LOG_TYPE log_type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS verbosity = LogTypes::LDEBUG);
void DumpAsync(u32 buffer_vector, u32 number_in_buffer, u32 number_io_buffer,
LogTypes::LOG_TYPE log_type = LogTypes::WII_IPC_HLE,
LogTypes::LOG_LEVELS verbosity = LogTypes::LDEBUG);
private:
IPCCommandResult Unsupported(const IOSRequest& request);
};
@@ -32,7 +32,7 @@ void CWII_IPC_HLE_Device_di::DoState(PointerWrap& p)
p.Do(m_commands_to_execute);
}
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(const IOSIOCtlRequest& request)
{
// DI IOCtls are handled in a special way by Dolphin
// compared to other WII_IPC_HLE functions.
@@ -42,40 +42,25 @@ IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
// are queued until DVDInterface is ready to handle them.
bool ready_to_execute = m_commands_to_execute.empty();
m_commands_to_execute.push_back(_CommandAddress);
m_commands_to_execute.push_back(request.address);
if (ready_to_execute)
StartIOCtl(_CommandAddress);
StartIOCtl(request);
// DVDInterface handles the timing and we handle the reply,
// so WII_IPC_HLE shouldn't handle anything.
return GetNoReply();
}
void CWII_IPC_HLE_Device_di::StartIOCtl(u32 command_address)
void CWII_IPC_HLE_Device_di::StartIOCtl(const IOSIOCtlRequest& request)
{
u32 BufferIn = Memory::Read_U32(command_address + 0x10);
u32 BufferInSize = Memory::Read_U32(command_address + 0x14);
u32 BufferOut = Memory::Read_U32(command_address + 0x18);
u32 BufferOutSize = Memory::Read_U32(command_address + 0x1C);
u32 command_0 = Memory::Read_U32(BufferIn);
u32 command_1 = Memory::Read_U32(BufferIn + 4);
u32 command_2 = Memory::Read_U32(BufferIn + 8);
DEBUG_LOG(WII_IPC_DVD, "IOCtl Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)",
command_0, BufferIn, BufferInSize, BufferOut, BufferOutSize);
// TATSUNOKO VS CAPCOM: Gets here with BufferOut == 0!!!
if (BufferOut != 0)
{
// Set out buffer to zeroes as a safety precaution
// to avoid answering nonsense values
Memory::Memset(BufferOut, 0, BufferOutSize);
}
const u32 command_0 = Memory::Read_U32(request.buffer_in);
const u32 command_1 = Memory::Read_U32(request.buffer_in + 4);
const u32 command_2 = Memory::Read_U32(request.buffer_in + 8);
// DVDInterface's ExecuteCommand handles most of the work.
// The IOCtl callback is used to generate a reply afterwards.
DVDInterface::ExecuteCommand(command_0, command_1, command_2, BufferOut, BufferOutSize, true);
DVDInterface::ExecuteCommand(command_0, command_1, command_2, request.buffer_out,
request.buffer_out_size, true);
}
void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
@@ -89,58 +74,46 @@ void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt
// This command has been executed, so it's removed from the queue
u32 command_address = m_commands_to_execute.front();
m_commands_to_execute.pop_front();
// The DI interrupt type is used as a return value
Memory::Write_U32(interrupt_type, command_address + 4);
WII_IPC_HLE_Interface::EnqueueReply(command_address);
WII_IPC_HLE_Interface::EnqueueReply(IOSIOCtlRequest{command_address}, interrupt_type);
// DVDInterface is now ready to execute another command,
// so we start executing a command from the queue if there is one
if (!m_commands_to_execute.empty())
StartIOCtl(m_commands_to_execute.front());
{
IOSIOCtlRequest next_request{m_commands_to_execute.front()};
StartIOCtl(next_request);
}
}
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(const IOSIOCtlVRequest& request)
{
SIOCtlVBuffer CommandBuffer(_CommandAddress);
// Prepare the out buffer(s) with zeros as a safety precaution
// to avoid returning bad values
for (const auto& buffer : CommandBuffer.PayloadBuffer)
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
u32 ReturnValue = 0;
switch (CommandBuffer.Parameter)
for (const auto& vector : request.io_vectors)
Memory::Memset(vector.address, 0, vector.size);
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case DVDInterface::DVDLowOpenPartition:
{
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0,
_dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[1].address == 0,
"DVDLowOpenPartition with ticket");
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0,
_dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[2].address == 0,
"DVDLowOpenPartition with cert chain");
u64 const partition_offset =
((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2);
u64 const partition_offset = ((u64)Memory::Read_U32(request.in_vectors[0].address + 4) << 2);
DVDInterface::ChangePartition(partition_offset);
INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset);
// Read TMD to the buffer
std::vector<u8> tmd_buffer = DVDInterface::GetVolume().GetTMD();
Memory::CopyToEmu(CommandBuffer.PayloadBuffer[0].m_Address, tmd_buffer.data(),
tmd_buffer.size());
Memory::CopyToEmu(request.io_vectors[0].address, tmd_buffer.data(), tmd_buffer.size());
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
ReturnValue = 1;
}
break;
default:
ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter);
_dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter);
return_value = 1;
break;
}
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetDefaultReply();
default:
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_DVD);
}
return GetDefaultReply(return_value);
}
@@ -27,13 +27,13 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
private:
void StartIOCtl(u32 command_address);
void StartIOCtl(const IOSIOCtlRequest& request);
std::deque<u32> m_commands_to_execute;
};
@@ -2,6 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cinttypes>
#include <cstdio>
#include <map>
#include <memory>
@@ -70,11 +71,7 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 device_id,
{
}
CWII_IPC_HLE_Device_FileIO::~CWII_IPC_HLE_Device_FileIO()
{
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bForce)
void CWII_IPC_HLE_Device_FileIO::Close()
{
INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id);
m_Mode = 0;
@@ -84,12 +81,11 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress, bool _bF
m_file.reset();
m_is_active = false;
return GetDefaultReply();
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Open(u32 command_address, u32 mode)
IOSReturnCode CWII_IPC_HLE_Device_FileIO::Open(const IOSOpenRequest& request)
{
m_Mode = mode;
m_Mode = request.flags;
static const char* const Modes[] = {"Unk Mode", "Read only", "Write only", "Read and Write"};
@@ -97,21 +93,18 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Open(u32 command_address, u32 mode)
// The file must exist before we can open it
// It should be created by ISFS_CreateFile, not here
if (File::Exists(m_filepath) && !File::IsDirectory(m_filepath))
if (!File::Exists(m_filepath) || File::IsDirectory(m_filepath))
{
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_name.c_str(), Modes[mode], mode);
OpenFile();
}
else
{
WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[mode],
WARN_LOG(WII_IPC_FILEIO, "FileIO: Open (%s) failed - File doesn't exist %s", Modes[m_Mode],
m_filepath.c_str());
if (command_address)
Memory::Write_U32(FS_ENOENT, command_address + 4);
return FS_ENOENT;
}
INFO_LOG(WII_IPC_FILEIO, "FileIO: Open %s (%s == %08X)", m_name.c_str(), Modes[m_Mode], m_Mode);
OpenFile();
m_is_active = true;
return GetDefaultReply();
return IPC_SUCCESS;
}
// This isn't theadsafe, but it's only called from the CPU thread.
@@ -158,98 +151,90 @@ void CWII_IPC_HLE_Device_FileIO::OpenFile()
}
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Seek(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Seek(const IOSSeekRequest& request)
{
u32 ReturnValue = FS_EINVAL;
const s32 SeekPosition = Memory::Read_U32(_CommandAddress + 0xC);
const s32 Mode = Memory::Read_U32(_CommandAddress + 0x10);
u32 return_value = FS_EINVAL;
if (m_file->IsOpen())
{
ReturnValue = FS_EINVAL;
const s32 fileSize = (s32)m_file->GetSize();
const u32 file_size = static_cast<u32>(m_file->GetSize());
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Seek Pos: 0x%08x, Mode: %i (%s, Length=0x%08x)",
SeekPosition, Mode, m_name.c_str(), fileSize);
request.offset, request.mode, m_name.c_str(), file_size);
switch (Mode)
switch (request.mode)
{
case WII_SEEK_SET:
case IOSSeekRequest::IOS_SEEK_SET:
{
if ((SeekPosition >= 0) && (SeekPosition <= fileSize))
if (request.offset <= file_size)
{
m_SeekPos = SeekPosition;
ReturnValue = m_SeekPos;
m_SeekPos = request.offset;
return_value = m_SeekPos;
}
break;
}
case WII_SEEK_CUR:
case IOSSeekRequest::IOS_SEEK_CUR:
{
s32 wantedPos = SeekPosition + m_SeekPos;
if (wantedPos >= 0 && wantedPos <= fileSize)
const u32 wanted_pos = request.offset + m_SeekPos;
if (wanted_pos <= file_size)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
m_SeekPos = wanted_pos;
return_value = m_SeekPos;
}
break;
}
case WII_SEEK_END:
case IOSSeekRequest::IOS_SEEK_END:
{
s32 wantedPos = SeekPosition + fileSize;
if (wantedPos >= 0 && wantedPos <= fileSize)
const u32 wanted_pos = request.offset + file_size;
if (wanted_pos <= file_size)
{
m_SeekPos = wantedPos;
ReturnValue = m_SeekPos;
m_SeekPos = wanted_pos;
return_value = m_SeekPos;
}
break;
}
default:
{
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", Mode);
ReturnValue = FS_EINVAL;
PanicAlert("CWII_IPC_HLE_Device_FileIO Unsupported seek mode %i", request.mode);
return_value = FS_EINVAL;
break;
}
}
}
else
{
ReturnValue = FS_ENOENT;
return_value = FS_ENOENT;
}
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(const IOSReadWriteRequest& request)
{
u32 ReturnValue = FS_EACCESS;
const u32 Address = Memory::Read_U32(_CommandAddress + 0xC); // Read to this memory address
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
s32 return_value = FS_EACCESS;
if (m_file->IsOpen())
{
if (m_Mode == ISFS_OPEN_WRITE)
if (m_Mode == IOS_OPEN_WRITE)
{
WARN_LOG(WII_IPC_FILEIO,
"FileIO: Attempted to read 0x%x bytes to 0x%08x on a write-only file %s", Size,
Address, m_name.c_str());
"FileIO: Attempted to read 0x%x bytes to 0x%08x on a write-only file %s",
request.size, request.buffer, m_name.c_str());
}
else
{
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", Size, Address,
m_name.c_str());
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Read 0x%x bytes to 0x%08x from %s", request.size,
request.buffer, m_name.c_str());
m_file->Seek(m_SeekPos, SEEK_SET); // File might be opened twice, need to seek before we read
ReturnValue = (u32)fread(Memory::GetPointer(Address), 1, Size, m_file->GetHandle());
if (ReturnValue != Size && ferror(m_file->GetHandle()))
return_value = static_cast<u32>(
fread(Memory::GetPointer(request.buffer), 1, request.size, m_file->GetHandle()));
if (static_cast<u32>(return_value) != request.size && ferror(m_file->GetHandle()))
{
ReturnValue = FS_EACCESS;
return_value = FS_EACCESS;
}
else
{
m_SeekPos += Size;
m_SeekPos += request.size;
}
}
}
@@ -257,39 +242,34 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Read(u32 _CommandAddress)
{
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
"not be opened or does not exist",
m_name.c_str(), Address, Size);
ReturnValue = FS_ENOENT;
m_name.c_str(), request.buffer, request.size);
return_value = FS_ENOENT;
}
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(const IOSReadWriteRequest& request)
{
u32 ReturnValue = FS_EACCESS;
const u32 Address =
Memory::Read_U32(_CommandAddress + 0xC); // Write data from this memory address
const u32 Size = Memory::Read_U32(_CommandAddress + 0x10);
s32 return_value = FS_EACCESS;
if (m_file->IsOpen())
{
if (m_Mode == ISFS_OPEN_READ)
if (m_Mode == IOS_OPEN_READ)
{
WARN_LOG(WII_IPC_FILEIO,
"FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s", Size,
Address, m_name.c_str());
"FileIO: Attempted to write 0x%x bytes from 0x%08x to a read-only file %s",
request.size, request.buffer, m_name.c_str());
}
else
{
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", Size, Address,
m_name.c_str());
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: Write 0x%04x bytes from 0x%08x to %s", request.size,
request.buffer, m_name.c_str());
m_file->Seek(m_SeekPos,
SEEK_SET); // File might be opened twice, need to seek before we write
if (m_file->WriteBytes(Memory::GetPointer(Address), Size))
if (m_file->WriteBytes(Memory::GetPointer(request.buffer), request.size))
{
ReturnValue = Size;
m_SeekPos += Size;
return_value = request.size;
m_SeekPos += request.size;
}
}
}
@@ -297,55 +277,41 @@ IPCCommandResult CWII_IPC_HLE_Device_FileIO::Write(u32 _CommandAddress)
{
ERROR_LOG(WII_IPC_FILEIO, "FileIO: Failed to read from %s (Addr=0x%08x Size=0x%x) - file could "
"not be opened or does not exist",
m_name.c_str(), Address, Size);
ReturnValue = FS_ENOENT;
m_name.c_str(), request.buffer, request.size);
return_value = FS_ENOENT;
}
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
IPCCommandResult CWII_IPC_HLE_Device_FileIO::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_FileIO::IOCtl(const IOSIOCtlRequest& request)
{
DEBUG_LOG(WII_IPC_FILEIO, "FileIO: IOCtl (Device=%s)", m_name.c_str());
#if defined(_DEBUG) || defined(DEBUGFAST)
DumpCommands(_CommandAddress);
#endif
const u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
u32 ReturnValue = 0;
s32 return_value = IPC_SUCCESS;
switch (Parameter)
switch (request.request)
{
case ISFS_IOCTL_GETFILESTATS:
{
if (m_file->IsOpen())
{
u32 m_FileLength = (u32)m_file->GetSize();
const u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
DEBUG_LOG(WII_IPC_FILEIO, " File: %s, Length: %i, Pos: %i", m_name.c_str(), m_FileLength,
m_SeekPos);
Memory::Write_U32(m_FileLength, BufferOut);
Memory::Write_U32(m_SeekPos, BufferOut + 4);
DEBUG_LOG(WII_IPC_FILEIO, "File: %s, Length: %" PRIu64 ", Pos: %i", m_name.c_str(),
m_file->GetSize(), m_SeekPos);
Memory::Write_U32(static_cast<u32>(m_file->GetSize()), request.buffer_out);
Memory::Write_U32(m_SeekPos, request.buffer_out + 4);
}
else
{
ReturnValue = FS_ENOENT;
return_value = FS_ENOENT;
}
}
break;
default:
{
PanicAlert("CWII_IPC_HLE_Device_FileIO: Parameter %i", Parameter);
}
break;
request.Log(GetDeviceName(), LogTypes::WII_IPC_FILEIO, LogTypes::LERROR);
}
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
void CWII_IPC_HLE_Device_FileIO::PrepareForState(PointerWrap::Mode mode)
@@ -26,34 +26,18 @@ class CWII_IPC_HLE_Device_FileIO : public IWII_IPC_HLE_Device
public:
CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_FileIO();
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Seek(u32 _CommandAddress) override;
IPCCommandResult Read(u32 _CommandAddress) override;
IPCCommandResult Write(u32 _CommandAddress) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
void Close() override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
IPCCommandResult Seek(const IOSSeekRequest& request) override;
IPCCommandResult Read(const IOSReadWriteRequest& request) override;
IPCCommandResult Write(const IOSReadWriteRequest& request) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
void PrepareForState(PointerWrap::Mode mode) override;
void DoState(PointerWrap& p) override;
void OpenFile();
private:
enum
{
ISFS_OPEN_READ = 1,
ISFS_OPEN_WRITE = 2,
ISFS_OPEN_RW = (ISFS_OPEN_READ | ISFS_OPEN_WRITE)
};
enum
{
WII_SEEK_SET = 0,
WII_SEEK_CUR = 1,
WII_SEEK_END = 2,
};
enum
{
ISFS_FUNCNULL = 0,
File diff suppressed because it is too large Load Diff
@@ -27,8 +27,6 @@ class CWII_IPC_HLE_Device_es : public IWII_IPC_HLE_Device
public:
CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_es();
void LoadWAD(const std::string& _rContentFile);
// Internal implementation of the ES_DECRYPT ioctlv.
@@ -38,10 +36,9 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
void Close() override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
static u32 ES_DIVerify(const std::vector<u8>& tmd);
@@ -116,7 +113,7 @@ private:
ES_INVALID_TMD = -106, // or access denied
ES_READ_LESS_DATA_THAN_EXPECTED = -1009,
ES_WRITE_FAILURE = -1010,
ES_PARAMTER_SIZE_OR_ALIGNMENT = -1017,
ES_PARAMETER_SIZE_OR_ALIGNMENT = -1017,
ES_HASH_DOESNT_MATCH = -1022,
ES_MEM_ALLOC_FAILED = -1024,
ES_INCORRECT_ACCESS_RIGHT = -1026,
@@ -32,18 +32,14 @@ CWII_IPC_HLE_Device_fs::CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string&
{
}
CWII_IPC_HLE_Device_fs::~CWII_IPC_HLE_Device_fs()
{
}
// ~1/1000th of a second is too short and causes hangs in Wii Party
// Play it safe at 1/500th
IPCCommandResult CWII_IPC_HLE_Device_fs::GetFSReply() const
IPCCommandResult CWII_IPC_HLE_Device_fs::GetFSReply(const s32 return_value) const
{
return {true, SystemTimers::GetTicksPerSecond() / 500};
return {return_value, true, SystemTimers::GetTicksPerSecond() / 500};
}
IPCCommandResult CWII_IPC_HLE_Device_fs::Open(u32 _CommandAddress, u32 _Mode)
IOSReturnCode CWII_IPC_HLE_Device_fs::Open(const IOSOpenRequest& request)
{
// clear tmp folder
{
@@ -53,7 +49,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::Open(u32 _CommandAddress, u32 _Mode)
}
m_is_active = true;
return GetFSReply();
return IPC_SUCCESS;
}
// Get total filesize of contents of a directory (recursive)
@@ -71,27 +67,20 @@ static u64 ComputeTotalFileSize(const File::FSTEntry& parentEntry)
return sizeOfFiles;
}
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(const IOSIOCtlVRequest& request)
{
u32 ReturnValue = IPC_SUCCESS;
SIOCtlVBuffer CommandBuffer(_CommandAddress);
// Prepare the out buffer(s) with zeros as a safety precaution
// to avoid returning bad values
for (const auto& buffer : CommandBuffer.PayloadBuffer)
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
switch (CommandBuffer.Parameter)
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case IOCTLV_READ_DIR:
{
const std::string relative_path =
Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
if (!IsValidWiiPath(relative_path))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relative_path.c_str());
ReturnValue = FS_EINVAL;
return_value = FS_EINVAL;
break;
}
@@ -103,7 +92,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
if (!File::Exists(DirName))
{
WARN_LOG(WII_IPC_FILEIO, "FS: Search not found: %s", DirName.c_str());
ReturnValue = FS_ENOENT;
return_value = FS_ENOENT;
break;
}
else if (!File::IsDirectory(DirName))
@@ -112,19 +101,19 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
// Games don't usually seem to care WHICH error they get, as long as it's <
// Well the system menu CARES!
WARN_LOG(WII_IPC_FILEIO, "\tNot a directory - return FS_EINVAL");
ReturnValue = FS_EINVAL;
return_value = FS_EINVAL;
break;
}
File::FSTEntry entry = File::ScanDirectoryTree(DirName, false);
// it is one
if ((CommandBuffer.InBuffer.size() == 1) && (CommandBuffer.PayloadBuffer.size() == 1))
if ((request.in_vectors.size() == 1) && (request.io_vectors.size() == 1))
{
size_t numFile = entry.children.size();
INFO_LOG(WII_IPC_FILEIO, "\t%zu files found", numFile);
Memory::Write_U32((u32)numFile, CommandBuffer.PayloadBuffer[0].m_Address);
Memory::Write_U32((u32)numFile, request.io_vectors[0].address);
}
else
{
@@ -140,13 +129,12 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
return one.virtualName < two.virtualName;
});
u32 MaxEntries = Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address);
u32 MaxEntries = Memory::Read_U32(request.in_vectors[0].address);
memset(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), 0,
CommandBuffer.PayloadBuffer[0].m_Size);
memset(Memory::GetPointer(request.io_vectors[0].address), 0, request.io_vectors[0].size);
size_t numFiles = 0;
char* pFilename = (char*)Memory::GetPointer((u32)(CommandBuffer.PayloadBuffer[0].m_Address));
char* pFilename = (char*)Memory::GetPointer((u32)(request.io_vectors[0].address));
for (size_t i = 0; i < entry.children.size() && i < MaxEntries; i++)
{
@@ -160,29 +148,29 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
INFO_LOG(WII_IPC_FILEIO, "\tFound: %s", FileName.c_str());
}
Memory::Write_U32((u32)numFiles, CommandBuffer.PayloadBuffer[1].m_Address);
Memory::Write_U32((u32)numFiles, request.io_vectors[1].address);
}
ReturnValue = IPC_SUCCESS;
return_value = IPC_SUCCESS;
}
break;
case IOCTLV_GETUSAGE:
{
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer.size() == 2);
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[0].m_Size == 4);
_dbg_assert_(WII_IPC_FILEIO, CommandBuffer.PayloadBuffer[1].m_Size == 4);
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors.size() == 2);
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors[0].size == 4);
_dbg_assert_(WII_IPC_FILEIO, request.io_vectors[1].size == 4);
// this command sucks because it asks of the number of used
// fsBlocks and inodes
// It should be correct, but don't count on it...
std::string relativepath =
Memory::GetString(CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size);
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
if (!IsValidWiiPath(relativepath))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", relativepath.c_str());
ReturnValue = FS_EINVAL;
return_value = FS_EINVAL;
break;
}
@@ -214,7 +202,7 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
fsBlocks = (u32)(totalSize / (16 * 1024)); // one bock is 16kb
}
ReturnValue = IPC_SUCCESS;
return_value = IPC_SUCCESS;
INFO_LOG(WII_IPC_FILEIO, "FS: fsBlock: %i, iNodes: %i", fsBlocks, iNodes);
}
@@ -222,54 +210,37 @@ IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtlV(u32 _CommandAddress)
{
fsBlocks = 0;
iNodes = 0;
ReturnValue = IPC_SUCCESS;
return_value = IPC_SUCCESS;
WARN_LOG(WII_IPC_FILEIO, "FS: fsBlock failed, cannot find directory: %s", path.c_str());
}
Memory::Write_U32(fsBlocks, CommandBuffer.PayloadBuffer[0].m_Address);
Memory::Write_U32(iNodes, CommandBuffer.PayloadBuffer[1].m_Address);
Memory::Write_U32(fsBlocks, request.io_vectors[0].address);
Memory::Write_U32(iNodes, request.io_vectors[1].address);
}
break;
default:
PanicAlert("CWII_IPC_HLE_Device_fs::IOCtlV: %i", CommandBuffer.Parameter);
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_FILEIO);
break;
}
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetFSReply();
return GetFSReply(return_value);
}
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_fs::IOCtl(const IOSIOCtlRequest& request)
{
// u32 DeviceID = Memory::Read_U32(_CommandAddress + 8);
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
/* Prepare the out buffer(s) with zeroes as a safety precaution
to avoid returning bad values. */
// LOG(WII_IPC_FILEIO, "Cleared %u bytes of the out buffer", _BufferOutSize);
Memory::Memset(BufferOut, 0, BufferOutSize);
u32 ReturnValue = ExecuteCommand(Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize);
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetFSReply();
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
const s32 return_value = ExecuteCommand(request);
return GetFSReply(return_value);
}
s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _BufferInSize,
u32 _BufferOut, u32 _BufferOutSize)
s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(const IOSIOCtlRequest& request)
{
switch (_Parameter)
switch (request.request)
{
case IOCTL_GET_STATS:
{
if (_BufferOutSize < 0x1c)
if (request.buffer_out_size < 0x1c)
return -1017;
WARN_LOG(WII_IPC_FILEIO, "FS: GET STATS - returning static values for now");
@@ -285,7 +256,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
fs.Free_INodes = 0x146B;
fs.Used_Inodes = 0x0394;
std::memcpy(Memory::GetPointer(_BufferOut), &fs, sizeof(NANDStat));
std::memcpy(Memory::GetPointer(request.buffer_out), &fs, sizeof(NANDStat));
return IPC_SUCCESS;
}
@@ -293,8 +264,8 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_CREATE_DIR:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
u32 Addr = _BufferIn;
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
u32 Addr = request.buffer_in;
u32 OwnerID = Memory::Read_U32(Addr);
Addr += 4;
@@ -325,7 +296,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_SET_ATTR:
{
u32 Addr = _BufferIn;
u32 Addr = request.buffer_in;
u32 OwnerID = Memory::Read_U32(Addr);
Addr += 4;
@@ -362,14 +333,14 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_GET_ATTR:
{
_dbg_assert_msg_(WII_IPC_FILEIO, _BufferOutSize == 76,
_dbg_assert_msg_(WII_IPC_FILEIO, request.buffer_out_size == 76,
" GET_ATTR needs an 76 bytes large output buffer but it is %i bytes large",
_BufferOutSize);
request.buffer_out_size);
u32 OwnerID = 0;
u16 GroupID = 0x3031; // this is also known as makercd, 01 (0x3031) for nintendo and 08
// (0x3038) for MH3 etc
const std::string wii_path = Memory::GetString(_BufferIn, 64);
const std::string wii_path = Memory::GetString(request.buffer_in, 64);
if (!IsValidWiiPath(wii_path))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
@@ -400,14 +371,14 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
}
// write answer to buffer
if (_BufferOutSize == 76)
if (request.buffer_out_size == 76)
{
u32 Addr = _BufferOut;
u32 Addr = request.buffer_out;
Memory::Write_U32(OwnerID, Addr);
Addr += 4;
Memory::Write_U16(GroupID, Addr);
Addr += 2;
memcpy(Memory::GetPointer(Addr), Memory::GetPointer(_BufferIn), 64);
memcpy(Memory::GetPointer(Addr), Memory::GetPointer(request.buffer_in), 64);
Addr += 64;
Memory::Write_U8(OwnerPerm, Addr);
Addr += 1;
@@ -425,10 +396,10 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_DELETE_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
int Offset = 0;
const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64);
const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
if (!IsValidWiiPath(wii_path))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
@@ -455,10 +426,10 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_RENAME_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
int Offset = 0;
const std::string wii_path = Memory::GetString(_BufferIn + Offset, 64);
const std::string wii_path = Memory::GetString(request.buffer_in + Offset, 64);
if (!IsValidWiiPath(wii_path))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path.c_str());
@@ -467,7 +438,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
std::string Filename = HLE_IPC_BuildFilename(wii_path);
Offset += 64;
const std::string wii_path_rename = Memory::GetString(_BufferIn + Offset, 64);
const std::string wii_path_rename = Memory::GetString(request.buffer_in + Offset, 64);
if (!IsValidWiiPath(wii_path_rename))
{
WARN_LOG(WII_IPC_FILEIO, "Not a valid path: %s", wii_path_rename.c_str());
@@ -503,9 +474,9 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
case IOCTL_CREATE_FILE:
{
_dbg_assert_(WII_IPC_FILEIO, _BufferOutSize == 0);
_dbg_assert_(WII_IPC_FILEIO, request.buffer_out_size == 0);
u32 Addr = _BufferIn;
u32 Addr = request.buffer_in;
u32 OwnerID = Memory::Read_U32(Addr);
Addr += 4;
u16 GroupID = Memory::Read_U16(Addr);
@@ -563,9 +534,7 @@ s32 CWII_IPC_HLE_Device_fs::ExecuteCommand(u32 _Parameter, u32 _BufferIn, u32 _B
}
break;
default:
ERROR_LOG(WII_IPC_FILEIO, "CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter);
PanicAlert("CWII_IPC_HLE_Device_fs::IOCtl: ni 0x%x", _Parameter);
break;
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_FILEIO);
}
return FS_EINVAL;
@@ -27,14 +27,12 @@ class CWII_IPC_HLE_Device_fs : public IWII_IPC_HLE_Device
{
public:
CWII_IPC_HLE_Device_fs(u32 _DeviceID, const std::string& _rDeviceName);
virtual ~CWII_IPC_HLE_Device_fs();
void DoState(PointerWrap& p) override;
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
private:
enum
@@ -51,7 +49,6 @@ private:
IOCTL_SHUTDOWN = 0x0D
};
IPCCommandResult GetFSReply() const;
s32 ExecuteCommand(u32 Parameter, u32 _BufferIn, u32 _BufferInSize, u32 _BufferOut,
u32 _BufferOutSize);
IPCCommandResult GetFSReply(s32 return_value) const;
s32 ExecuteCommand(const IOSIOCtlRequest& request);
};
@@ -37,12 +37,9 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
std::lock_guard<std::mutex> lk(hid->m_device_list_reply_mutex);
if (hid->deviceCommandAddress != 0)
{
hid->FillOutDevices(Memory::Read_U32(hid->deviceCommandAddress + 0x18),
Memory::Read_U32(hid->deviceCommandAddress + 0x1C));
// Return value
Memory::Write_U32(0, hid->deviceCommandAddress + 4);
WII_IPC_HLE_Interface::EnqueueReply(hid->deviceCommandAddress, 0,
IOSIOCtlRequest request{hid->deviceCommandAddress};
hid->FillOutDevices(request);
WII_IPC_HLE_Interface::EnqueueReply(request, IPC_SUCCESS, 0,
CoreTiming::FromThread::NON_CPU);
hid->deviceCommandAddress = 0;
}
@@ -56,16 +53,15 @@ void CWII_IPC_HLE_Device_hid::checkUsbUpdates(CWII_IPC_HLE_Device_hid* hid)
void CWII_IPC_HLE_Device_hid::handleUsbUpdates(struct libusb_transfer* transfer)
{
int ret = IPC_EINVAL;
s32 ret = IPC_EINVAL;
u32 replyAddress = (u32)(size_t)transfer->user_data;
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
{
ret = transfer->length;
}
// Return value
Memory::Write_U32(ret, replyAddress + 4);
WII_IPC_HLE_Interface::EnqueueReply(replyAddress, 0, CoreTiming::FromThread::NON_CPU);
IOSIOCtlRequest request{replyAddress};
WII_IPC_HLE_Interface::EnqueueReply(request, ret, 0, CoreTiming::FromThread::NON_CPU);
}
CWII_IPC_HLE_Device_hid::CWII_IPC_HLE_Device_hid(u32 _DeviceID, const std::string& _rDeviceName)
@@ -105,53 +101,36 @@ CWII_IPC_HLE_Device_hid::~CWII_IPC_HLE_Device_hid()
libusb_exit(nullptr);
}
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(const IOSIOCtlRequest& request)
{
if (Core::g_want_determinism)
{
Memory::Write_U32(-1, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(IPC_EACCES);
}
u32 Parameter = Memory::Read_U32(_CommandAddress + 0xC);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
u32 ReturnValue = 0;
switch (Parameter)
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case IOCTL_HID_GET_ATTACHED:
{
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Get Attached) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
deviceCommandAddress = _CommandAddress;
deviceCommandAddress = request.address;
return GetNoReply();
}
case IOCTL_HID_OPEN:
{
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Open) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
BufferInSize, BufferOut, BufferOutSize);
// hid version, apparently
ReturnValue = 0x40001;
return_value = 0x40001;
break;
}
case IOCTL_HID_SET_SUSPEND:
{
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Set Suspend) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
// not actually implemented in IOS
ReturnValue = 0;
return_value = IPC_SUCCESS;
break;
}
case IOCTL_HID_CANCEL_INTERRUPT:
{
DEBUG_LOG(WII_IPC_HID,
"HID::IOCtl(Cancel Interrupt) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)", BufferIn,
BufferInSize, BufferOut, BufferOutSize);
ReturnValue = 0;
return_value = IPC_SUCCESS;
break;
}
case IOCTL_HID_CONTROL:
@@ -161,15 +140,15 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
-4 Can't find device specified
*/
u32 dev_num = Memory::Read_U32(BufferIn + 0x10);
u8 bmRequestType = Memory::Read_U8(BufferIn + 0x14);
u8 bRequest = Memory::Read_U8(BufferIn + 0x15);
u16 wValue = Memory::Read_U16(BufferIn + 0x16);
u16 wIndex = Memory::Read_U16(BufferIn + 0x18);
u16 wLength = Memory::Read_U16(BufferIn + 0x1A);
u32 data = Memory::Read_U32(BufferIn + 0x1C);
u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
u8 bmRequestType = Memory::Read_U8(request.buffer_in + 0x14);
u8 bRequest = Memory::Read_U8(request.buffer_in + 0x15);
u16 wValue = Memory::Read_U16(request.buffer_in + 0x16);
u16 wIndex = Memory::Read_U16(request.buffer_in + 0x18);
u16 wLength = Memory::Read_U16(request.buffer_in + 0x1A);
u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
ReturnValue = IPC_EINVAL;
return_value = IPC_EINVAL;
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
@@ -185,12 +164,14 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
libusb_fill_control_setup(buffer, bmRequestType, bRequest, wValue, wIndex, wLength);
Memory::CopyFromEmu(buffer + LIBUSB_CONTROL_SETUP_SIZE, data, wLength);
libusb_fill_control_transfer(transfer, dev_handle, buffer, handleUsbUpdates,
(void*)(size_t)_CommandAddress, /* no timeout */ 0);
(void*)(size_t)request.address, /* no timeout */ 0);
libusb_submit_transfer(transfer);
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i), BufferOut:
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Control)(%02X, %02X) (BufferIn: (%08x, %i),
// request.buffer_out:
// (%08x, %i)",
// bmRequestType, bRequest, BufferIn, BufferInSize, BufferOut, BufferOutSize);
// bmRequestType, bRequest, BufferIn, request.buffer_in_size, request.buffer_out,
// request.buffer_out_size);
// It's the async way!
return GetNoReply();
@@ -198,13 +179,13 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
case IOCTL_HID_INTERRUPT_OUT:
case IOCTL_HID_INTERRUPT_IN:
{
u32 dev_num = Memory::Read_U32(BufferIn + 0x10);
u32 endpoint = Memory::Read_U32(BufferIn + 0x14);
u32 length = Memory::Read_U32(BufferIn + 0x18);
u32 dev_num = Memory::Read_U32(request.buffer_in + 0x10);
u32 endpoint = Memory::Read_U32(request.buffer_in + 0x14);
u32 length = Memory::Read_U32(request.buffer_in + 0x18);
u32 data = Memory::Read_U32(BufferIn + 0x1C);
u32 data = Memory::Read_U32(request.buffer_in + 0x1C);
ReturnValue = IPC_EINVAL;
return_value = IPC_EINVAL;
libusb_device_handle* dev_handle = GetDeviceByDevNum(dev_num);
@@ -217,14 +198,9 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
struct libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_interrupt_transfer(transfer, dev_handle, endpoint, Memory::GetPointer(data), length,
handleUsbUpdates, (void*)(size_t)_CommandAddress, 0);
handleUsbUpdates, (void*)(size_t)request.address, 0);
libusb_submit_transfer(transfer);
// DEBUG_LOG(WII_IPC_HID, "HID::IOCtl(Interrupt %s)(%d,%d,%X) (BufferIn: (%08x, %i), BufferOut:
// (%08x, %i)",
// Parameter == IOCTL_HID_INTERRUPT_IN ? "In" : "Out", endpoint, length, data,
// BufferIn, BufferInSize, BufferOut, BufferOutSize);
// It's the async way!
return GetNoReply();
}
@@ -233,28 +209,21 @@ IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtl(u32 _CommandAddress)
std::lock_guard<std::mutex> lk(m_device_list_reply_mutex);
if (deviceCommandAddress != 0)
{
Memory::Write_U32(0xFFFFFFFF, Memory::Read_U32(deviceCommandAddress + 0x18));
// Return value
Memory::Write_U32(-1, deviceCommandAddress + 4);
WII_IPC_HLE_Interface::EnqueueReply(deviceCommandAddress);
IOSIOCtlRequest pending_request{deviceCommandAddress};
Memory::Write_U32(0xFFFFFFFF, pending_request.buffer_out);
WII_IPC_HLE_Interface::EnqueueReply(pending_request, -1);
deviceCommandAddress = 0;
}
INFO_LOG(WII_IPC_HID, "HID::IOCtl(Shutdown) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
request.buffer_in, request.buffer_in_size, request.buffer_out,
request.buffer_out_size);
break;
}
default:
{
INFO_LOG(WII_IPC_HID, "HID::IOCtl(0x%x) (BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
Parameter, BufferIn, BufferInSize, BufferOut, BufferOutSize);
break;
}
request.Log(GetDeviceName(), LogTypes::WII_IPC_HID);
}
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
@@ -283,26 +252,11 @@ bool CWII_IPC_HLE_Device_hid::ClaimDevice(libusb_device_handle* dev)
return true;
}
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_hid::IOCtlV(const IOSIOCtlVRequest& request)
{
Dolphin_Debugger::PrintCallstack(LogTypes::WII_IPC_HID, LogTypes::LWARNING);
u32 ReturnValue = 0;
SIOCtlVBuffer CommandBuffer(_CommandAddress);
INFO_LOG(WII_IPC_HID, "%s - IOCtlV:", GetDeviceName().c_str());
INFO_LOG(WII_IPC_HID, " Parameter: 0x%x", CommandBuffer.Parameter);
INFO_LOG(WII_IPC_HID, " NumberIn: 0x%08x", CommandBuffer.NumberInBuffer);
INFO_LOG(WII_IPC_HID, " NumberOut: 0x%08x", CommandBuffer.NumberPayloadBuffer);
INFO_LOG(WII_IPC_HID, " BufferVector: 0x%08x", CommandBuffer.BufferVector);
INFO_LOG(WII_IPC_HID, " PayloadAddr: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Address);
INFO_LOG(WII_IPC_HID, " PayloadSize: 0x%08x", CommandBuffer.PayloadBuffer[0].m_Size);
#if defined(_DEBUG) || defined(DEBUGFAST)
DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
CommandBuffer.NumberPayloadBuffer);
#endif
Memory::Write_U32(ReturnValue, _CommandAddress + 4);
return GetDefaultReply();
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_HID);
return GetDefaultReply(IPC_SUCCESS);
}
void CWII_IPC_HLE_Device_hid::ConvertDeviceToWii(WiiHIDDeviceDescriptor* dest,
@@ -344,10 +298,10 @@ void CWII_IPC_HLE_Device_hid::ConvertEndpointToWii(WiiHIDEndpointDescriptor* des
dest->wMaxPacketSize = Common::swap16(dest->wMaxPacketSize);
}
void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize)
void CWII_IPC_HLE_Device_hid::FillOutDevices(const IOSIOCtlRequest& request)
{
static u16 check = 1;
int OffsetBuffer = BufferOut;
int OffsetBuffer = request.buffer_out;
int OffsetStart = 0;
// int OffsetDevice = 0;
int d, c, ic, i, e; /* config, interface container, interface, endpoint */
@@ -38,8 +38,8 @@ public:
virtual ~CWII_IPC_HLE_Device_hid();
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
private:
enum
@@ -115,7 +115,7 @@ private:
};
u32 deviceCommandAddress;
void FillOutDevices(u32 BufferOut, u32 BufferOutSize);
void FillOutDevices(const IOSIOCtlRequest& request);
int GetAvailableDevNum(u16 idVendor, u16 idProduct, u8 bus, u8 port, u16 check);
bool ClaimDevice(libusb_device_handle* dev);
File diff suppressed because it is too large Load Diff
@@ -30,7 +30,7 @@ public:
virtual ~CWII_IPC_HLE_Device_net_kd_request();
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
private:
enum
@@ -86,35 +86,31 @@ public:
}
virtual ~CWII_IPC_HLE_Device_net_kd_time() {}
IPCCommandResult IOCtl(u32 _CommandAddress) override
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override
{
u32 Parameter = Memory::Read_U32(_CommandAddress + 0x0C);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 result = 0;
s32 result = 0;
u32 common_result = 0;
// TODO Writes stuff to /shared2/nwc24/misc.bin
// u32 update_misc = 0;
switch (Parameter)
switch (request.request)
{
case IOCTL_NW24_GET_UNIVERSAL_TIME:
Memory::Write_U64(GetAdjustedUTC(), BufferOut + 4);
Memory::Write_U64(GetAdjustedUTC(), request.buffer_out + 4);
break;
case IOCTL_NW24_SET_UNIVERSAL_TIME:
SetAdjustedUTC(Memory::Read_U64(BufferIn));
// update_misc = Memory::Read_U32(BufferIn + 8);
SetAdjustedUTC(Memory::Read_U64(request.buffer_in));
// update_misc = Memory::Read_U32(request.buffer_in + 8);
break;
case IOCTL_NW24_SET_RTC_COUNTER:
rtc = Memory::Read_U32(BufferIn);
// update_misc = Memory::Read_U32(BufferIn + 4);
rtc = Memory::Read_U32(request.buffer_in);
// update_misc = Memory::Read_U32(request.buffer_in + 4);
break;
case IOCTL_NW24_GET_TIME_DIFF:
Memory::Write_U64(GetAdjustedUTC() - rtc, BufferOut + 4);
Memory::Write_U64(GetAdjustedUTC() - rtc, request.buffer_out + 4);
break;
case IOCTL_NW24_UNIMPLEMENTED:
@@ -122,14 +118,13 @@ public:
break;
default:
ERROR_LOG(WII_IPC_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), Parameter);
ERROR_LOG(WII_IPC_NET, "%s - unknown IOCtl: %x", GetDeviceName().c_str(), request.request);
break;
}
// write return values
Memory::Write_U32(common_result, BufferOut);
Memory::Write_U32(result, _CommandAddress + 4);
return GetDefaultReply();
Memory::Write_U32(common_result, request.buffer_out);
return GetDefaultReply(result);
}
private:
@@ -207,8 +202,8 @@ public:
virtual ~CWII_IPC_HLE_Device_net_ip_top();
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void Update() override;
@@ -227,7 +222,7 @@ public:
virtual ~CWII_IPC_HLE_Device_net_ncd_manage();
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
private:
enum
@@ -253,7 +248,7 @@ public:
virtual ~CWII_IPC_HLE_Device_net_wd_command();
IPCCommandResult IOCtlV(u32 CommandAddress) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
private:
enum
@@ -75,72 +75,58 @@ int CWII_IPC_HLE_Device_net_ssl::GetSSLFreeID() const
return 0;
}
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtl(const IOSIOCtlRequest& request)
{
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
u32 Command = Memory::Read_U32(_CommandAddress + 0x0C);
INFO_LOG(WII_IPC_SSL, "%s unknown %i "
"(BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
GetDeviceName().c_str(), Command, BufferIn, BufferInSize, BufferOut, BufferOutSize);
Memory::Write_U32(0, _CommandAddress + 0x4);
return GetDefaultReply();
request.Log(GetDeviceName(), LogTypes::WII_IPC_SSL, LogTypes::LINFO);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(const IOSIOCtlVRequest& request)
{
SIOCtlVBuffer CommandBuffer(_CommandAddress);
u32 _BufferIn = 0, _BufferIn2 = 0, _BufferIn3 = 0;
u32 BufferIn = 0, BufferIn2 = 0, BufferIn3 = 0;
u32 BufferInSize = 0, BufferInSize2 = 0, BufferInSize3 = 0;
u32 BufferOut = 0, BufferOut2 = 0, BufferOut3 = 0;
u32 BufferOutSize = 0, BufferOutSize2 = 0, BufferOutSize3 = 0;
if (CommandBuffer.InBuffer.size() > 0)
if (request.in_vectors.size() > 0)
{
_BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
BufferIn = request.in_vectors.at(0).address;
BufferInSize = request.in_vectors.at(0).size;
}
if (CommandBuffer.InBuffer.size() > 1)
if (request.in_vectors.size() > 1)
{
_BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
BufferIn2 = request.in_vectors.at(1).address;
BufferInSize2 = request.in_vectors.at(1).size;
}
if (CommandBuffer.InBuffer.size() > 2)
if (request.in_vectors.size() > 2)
{
_BufferIn3 = CommandBuffer.InBuffer.at(2).m_Address;
BufferInSize3 = CommandBuffer.InBuffer.at(2).m_Size;
BufferIn3 = request.in_vectors.at(2).address;
BufferInSize3 = request.in_vectors.at(2).size;
}
if (CommandBuffer.PayloadBuffer.size() > 0)
if (request.io_vectors.size() > 0)
{
BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
BufferOut = request.io_vectors.at(0).address;
BufferOutSize = request.io_vectors.at(0).size;
}
if (CommandBuffer.PayloadBuffer.size() > 1)
if (request.io_vectors.size() > 1)
{
BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
BufferOut2 = request.io_vectors.at(1).address;
BufferOutSize2 = request.io_vectors.at(1).size;
}
if (CommandBuffer.PayloadBuffer.size() > 2)
if (request.io_vectors.size() > 2)
{
BufferOut3 = CommandBuffer.PayloadBuffer.at(2).m_Address;
BufferOutSize3 = CommandBuffer.PayloadBuffer.at(2).m_Size;
BufferOut3 = request.io_vectors.at(2).address;
BufferOutSize3 = request.io_vectors.at(2).size;
}
// I don't trust SSL to be deterministic, and this is never going to sync
// as such (as opposed to forwarding IPC results or whatever), so -
if (Core::g_want_determinism)
{
Memory::Write_U32(-1, _CommandAddress + 0x4);
return GetDefaultReply();
}
return GetDefaultReply(IPC_EACCES);
switch (CommandBuffer.Parameter)
switch (request.request)
{
case IOCTLV_NET_SSL_NEW:
{
@@ -187,20 +173,20 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
mbedtls_ssl_set_hostname(&ssl->ctx, ssl->hostname.c_str());
ssl->active = true;
Memory::Write_U32(freeSSL, _BufferIn);
Memory::Write_U32(freeSSL, BufferIn);
}
else
{
_SSL_NEW_ERROR:
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_NEW (%d, %s) "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
verifyOption, hostname.c_str(), _BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
verifyOption, hostname.c_str(), BufferIn, BufferInSize, BufferIn2, BufferInSize2,
BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
BufferOut3, BufferOutSize3);
break;
}
@@ -226,18 +212,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
ssl->active = false;
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SHUTDOWN "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
break;
}
case IOCTLV_NET_SSL_SETROOTCA:
@@ -246,8 +232,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
if (SSLID_VALID(sslID))
@@ -264,19 +250,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (ret)
{
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
}
else
{
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCA = %d", ret);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
break;
}
@@ -286,8 +272,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
if (SSLID_VALID(sslID))
@@ -302,19 +288,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
{
mbedtls_x509_crt_free(&ssl->clicert);
mbedtls_pk_free(&ssl->pk);
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
}
else
{
mbedtls_ssl_conf_own_cert(&ssl->config, &ssl->clicert, &ssl->pk);
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT = (%d, %d)", ret, pk_ret);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
}
break;
@@ -325,8 +311,8 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
if (SSLID_VALID(sslID))
@@ -336,11 +322,11 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
mbedtls_pk_free(&ssl->pk);
mbedtls_ssl_conf_own_cert(&ssl->config, nullptr, nullptr);
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINCLIENTCERT invalid sslID = %d", sslID);
}
break;
@@ -357,25 +343,25 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (ret)
{
mbedtls_x509_crt_free(&ssl->clicert);
Memory::Write_U32(SSL_ERR_FAILED, _BufferIn);
Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
}
else
{
mbedtls_ssl_conf_ca_chain(&ssl->config, &ssl->cacert, nullptr);
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA = %d", ret);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETBUILTINROOTCA "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
break;
}
case IOCTLV_NET_SSL_CONNECT:
@@ -388,18 +374,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
ssl->sockfd = Memory::Read_U32(BufferOut2);
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT socket = %d", ssl->sockfd);
mbedtls_ssl_set_bio(&ssl->ctx, &ssl->sockfd, mbedtls_net_send, mbedtls_net_recv, nullptr);
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_CONNECT "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
break;
}
case IOCTLV_NET_SSL_DOHANDSHAKE:
@@ -408,12 +394,12 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (SSLID_VALID(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_DOHANDSHAKE);
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE);
return GetNoReply();
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
break;
}
@@ -423,19 +409,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (SSLID_VALID(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_WRITE);
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE);
return GetNoReply();
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_WRITE "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
INFO_LOG(WII_IPC_SSL, "%s", Memory::GetString(BufferOut2).c_str());
break;
}
@@ -446,19 +432,19 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
if (SSLID_VALID(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(_SSL[sslID].sockfd, _CommandAddress, IOCTLV_NET_SSL_READ);
sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ);
return GetNoReply();
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_READ(%d)"
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
ret, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
ret, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
break;
}
@@ -467,18 +453,18 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
int sslID = Memory::Read_U32(BufferOut) - 1;
if (SSLID_VALID(sslID))
{
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_SETROOTCADEFAULT "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
break;
}
case IOCTLV_NET_SSL_SETCLIENTCERTDEFAULT:
@@ -487,33 +473,24 @@ IPCCommandResult CWII_IPC_HLE_Device_net_ssl::IOCtlV(u32 _CommandAddress)
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
_BufferIn, BufferInSize, _BufferIn2, BufferInSize2, _BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3, BufferOut,
BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
if (SSLID_VALID(sslID))
{
Memory::Write_U32(SSL_OK, _BufferIn);
Memory::Write_U32(SSL_OK, BufferIn);
}
else
{
Memory::Write_U32(SSL_ERR_ID, _BufferIn);
Memory::Write_U32(SSL_ERR_ID, BufferIn);
}
break;
}
default:
ERROR_LOG(WII_IPC_SSL, "%i "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferIn3: (%08x, %i), BufferOut: (%08x, %i), "
"BufferOut2: (%08x, %i), BufferOut3: (%08x, %i)",
CommandBuffer.Parameter, _BufferIn, BufferInSize, _BufferIn2, BufferInSize2,
_BufferIn3, BufferInSize3, BufferOut, BufferOutSize, BufferOut2, BufferOutSize2,
BufferOut3, BufferOutSize3);
break;
request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_SSL);
}
// SSL return codes are written to BufferIn
Memory::Write_U32(0, _CommandAddress + 4);
return GetDefaultReply();
return GetDefaultReply(IPC_SUCCESS);
}
@@ -87,8 +87,8 @@ public:
virtual ~CWII_IPC_HLE_Device_net_ssl();
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
int GetSSLFreeID() const;
@@ -38,15 +38,15 @@ void CWII_IPC_HLE_Device_sdio_slot0::DoState(PointerWrap& p)
void CWII_IPC_HLE_Device_sdio_slot0::EventNotify()
{
if (!m_event)
return;
// Accessing SConfig variables like this isn't really threadsafe,
// but this is how it's done all over the place...
if ((SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_INSERT) ||
(!SConfig::GetInstance().m_WiiSDCard && m_event.type == EVENT_REMOVE))
if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) ||
(!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE))
{
Memory::Write_U32(m_event.type, m_event.addr + 4);
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
m_event.addr = 0;
m_event.type = EVENT_NONE;
WII_IPC_HLE_Interface::EnqueueReply(m_event->request, m_event->type);
m_event.reset();
}
}
@@ -70,50 +70,35 @@ void CWII_IPC_HLE_Device_sdio_slot0::OpenInternal()
}
}
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Open(u32 _CommandAddress, u32 _Mode)
IOSReturnCode CWII_IPC_HLE_Device_sdio_slot0::Open(const IOSOpenRequest& request)
{
INFO_LOG(WII_IPC_SD, "Open");
OpenInternal();
m_registers.fill(0);
m_is_active = true;
return GetDefaultReply();
return IPC_SUCCESS;
}
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::Close(u32 _CommandAddress, bool _bForce)
void CWII_IPC_HLE_Device_sdio_slot0::Close()
{
INFO_LOG(WII_IPC_SD, "Close");
m_Card.Close();
m_BlockLength = 0;
m_BusWidth = 0;
m_is_active = false;
return GetDefaultReply();
}
// The front SD slot
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(const IOSIOCtlRequest& request)
{
u32 Cmd = Memory::Read_U32(_CommandAddress + 0xC);
u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10);
u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14);
u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18);
u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C);
// As a safety precaution we fill the out buffer with zeros to avoid
// returning nonsense values
Memory::Memset(BufferOut, 0, BufferOutSize);
u32 ReturnValue = 0;
switch (Cmd)
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case IOCTL_WRITEHCR:
{
u32 reg = Memory::Read_U32(BufferIn);
u32 val = Memory::Read_U32(BufferIn + 16);
u32 reg = Memory::Read_U32(request.buffer_in);
u32 val = Memory::Read_U32(request.buffer_in + 16);
INFO_LOG(WII_IPC_SD, "IOCTL_WRITEHCR 0x%08x - 0x%08x", reg, val);
@@ -143,7 +128,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
case IOCTL_READHCR:
{
u32 reg = Memory::Read_U32(BufferIn);
u32 reg = Memory::Read_U32(request.buffer_in);
if (reg >= m_registers.size())
{
@@ -155,7 +140,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
INFO_LOG(WII_IPC_SD, "IOCTL_READHCR 0x%08x - 0x%08x", reg, val);
// Just reading the register
Memory::Write_U32(val, BufferOut);
Memory::Write_U32(val, request.buffer_out);
}
break;
@@ -164,7 +149,7 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
if (m_Card)
m_Status |= CARD_INITIALIZED;
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(0x9f620000, BufferOut);
Memory::Write_U32(0x9f620000, request.buffer_out);
break;
case IOCTL_SETCLK:
@@ -172,15 +157,17 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
INFO_LOG(WII_IPC_SD, "IOCTL_SETCLK");
// libogc only sets it to 1 and makes sure the return isn't negative...
// one half of the sdclk divisor: a power of two or zero.
u32 clock = Memory::Read_U32(BufferIn);
u32 clock = Memory::Read_U32(request.buffer_in);
if (clock != 1)
INFO_LOG(WII_IPC_SD, "Setting to %i, interesting", clock);
}
break;
case IOCTL_SENDCMD:
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(BufferIn), _CommandAddress);
ReturnValue = ExecuteCommand(BufferIn, BufferInSize, 0, 0, BufferOut, BufferOutSize);
INFO_LOG(WII_IPC_SD, "IOCTL_SENDCMD %x IPC:%08x", Memory::Read_U32(request.buffer_in),
request.address);
return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
request.buffer_out, request.buffer_out_size);
break;
case IOCTL_GETSTATUS:
@@ -191,89 +178,51 @@ IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtl(u32 _CommandAddress)
INFO_LOG(WII_IPC_SD, "IOCTL_GETSTATUS. Replying that SD card is %s%s",
(m_Status & CARD_INSERTED) ? "inserted" : "not present",
(m_Status & CARD_INITIALIZED) ? " and initialized" : "");
Memory::Write_U32(m_Status, BufferOut);
Memory::Write_U32(m_Status, request.buffer_out);
break;
case IOCTL_GETOCR:
INFO_LOG(WII_IPC_SD, "IOCTL_GETOCR");
Memory::Write_U32(0x80ff8000, BufferOut);
Memory::Write_U32(0x80ff8000, request.buffer_out);
break;
default:
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", Cmd);
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtl command (0x%08x)", request.request);
break;
}
// INFO_LOG(WII_IPC_SD, "InBuffer");
// DumpCommands(BufferIn, BufferInSize / 4, LogTypes::WII_IPC_SD);
// INFO_LOG(WII_IPC_SD, "OutBuffer");
// DumpCommands(BufferOut, BufferOutSize/4, LogTypes::WII_IPC_SD);
if (ReturnValue == RET_EVENT_REGISTER)
if (return_value == RET_EVENT_REGISTER)
{
// async
m_event.addr = _CommandAddress;
Memory::Write_U32(0, _CommandAddress + 0x4);
// Check if the condition is already true
EventNotify();
return GetNoReply();
}
else if (ReturnValue == RET_EVENT_UNREGISTER)
{
// release returns 0
// unknown sd int
// technically we do it out of order, oh well
Memory::Write_U32(EVENT_INVALID, m_event.addr + 4);
WII_IPC_HLE_Interface::EnqueueReply(m_event.addr);
m_event.addr = 0;
m_event.type = EVENT_NONE;
Memory::Write_U32(0, _CommandAddress + 0x4);
return GetDefaultReply();
}
else
{
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
}
return GetDefaultReply(return_value);
}
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(u32 _CommandAddress)
IPCCommandResult CWII_IPC_HLE_Device_sdio_slot0::IOCtlV(const IOSIOCtlVRequest& request)
{
// PPC sending commands
SIOCtlVBuffer CommandBuffer(_CommandAddress);
// Prepare the out buffer(s) with zeros as a safety precaution
// to avoid returning bad values
for (const auto& buffer : CommandBuffer.PayloadBuffer)
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
u32 ReturnValue = 0;
switch (CommandBuffer.Parameter)
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
case IOCTLV_SENDCMD:
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x",
Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address));
ReturnValue = ExecuteCommand(
CommandBuffer.InBuffer[0].m_Address, CommandBuffer.InBuffer[0].m_Size,
CommandBuffer.InBuffer[1].m_Address, CommandBuffer.InBuffer[1].m_Size,
CommandBuffer.PayloadBuffer[0].m_Address, CommandBuffer.PayloadBuffer[0].m_Size);
DEBUG_LOG(WII_IPC_SD, "IOCTLV_SENDCMD 0x%08x", Memory::Read_U32(request.in_vectors[0].address));
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
return_value =
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
request.in_vectors[1].address, request.in_vectors[1].size,
request.io_vectors[0].address, request.io_vectors[0].size);
break;
default:
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", CommandBuffer.Parameter);
break;
ERROR_LOG(WII_IPC_SD, "Unknown SD IOCtlV command 0x%08x", request.request);
}
// DumpAsync(CommandBuffer.BufferVector, CommandBuffer.NumberInBuffer,
// CommandBuffer.NumberPayloadBuffer, LogTypes::WII_IPC_SD);
Memory::Write_U32(ReturnValue, _CommandAddress + 0x4);
return GetDefaultReply();
return GetDefaultReply(return_value);
}
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 _rwBuffer,
u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(const IOSRequest& request, u32 _BufferIn,
u32 _BufferInSize, u32 _rwBuffer,
u32 _rwBufferSize, u32 _BufferOut,
u32 _BufferOutSize)
{
@@ -429,15 +378,23 @@ u32 CWII_IPC_HLE_Device_sdio_slot0::ExecuteCommand(u32 _BufferIn, u32 _BufferInS
case EVENT_REGISTER: // async
INFO_LOG(WII_IPC_SD, "Register event %x", req.arg);
m_event.type = (EventType)req.arg;
m_event = std::make_unique<Event>(static_cast<EventType>(req.arg), request);
ret = RET_EVENT_REGISTER;
break;
case EVENT_UNREGISTER: // synchronous
// Used to cancel an event that was already registered.
case EVENT_UNREGISTER:
{
INFO_LOG(WII_IPC_SD, "Unregister event %x", req.arg);
m_event.type = (EventType)req.arg;
ret = RET_EVENT_UNREGISTER;
if (!m_event)
return IPC_EINVAL;
// release returns 0
// unknown sd int
// technically we do it out of order, oh well
WII_IPC_HLE_Interface::EnqueueReply(m_event->request, EVENT_INVALID);
m_event.reset();
break;
}
default:
ERROR_LOG(WII_IPC_SD, "Unknown SD command 0x%08x", req.command);
@@ -23,11 +23,10 @@ public:
void DoState(PointerWrap& p) override;
IPCCommandResult Open(u32 _CommandAddress, u32 _Mode) override;
IPCCommandResult Close(u32 _CommandAddress, bool _bForce) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override;
IOSReturnCode Open(const IOSOpenRequest& request) override;
void Close() override;
IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void EventNotify();
@@ -63,7 +62,6 @@ private:
RET_OK,
RET_FAIL,
RET_EVENT_REGISTER, // internal state only - not actually returned
RET_EVENT_UNREGISTER
};
// Status
@@ -100,9 +98,8 @@ private:
enum EventType
{
EVENT_NONE = 0,
EVENT_INSERT,
EVENT_REMOVE,
EVENT_INSERT = 1,
EVENT_REMOVE = 2,
// from unregister, i think it is just meant to be invalid
EVENT_INVALID = 0xc210000
};
@@ -110,9 +107,11 @@ private:
// TODO do we need more than one?
struct Event
{
EventType type = EVENT_NONE;
u32 addr = 0;
} m_event;
Event(EventType type_, IOSRequest request_) : type(type_), request(request_) {}
EventType type;
IOSRequest request;
};
std::unique_ptr<Event> m_event;
u32 m_Status = CARD_NOT_EXIST;
u32 m_BlockLength = 0;
@@ -122,7 +121,7 @@ private:
File::IOFile m_Card;
u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 BufferIn2, u32 BufferInSize2,
u32 _BufferOut, u32 BufferOutSize);
u32 ExecuteCommand(const IOSRequest& request, u32 BufferIn, u32 BufferInSize, u32 BufferIn2,
u32 BufferInSize2, u32 _BufferOut, u32 BufferOutSize);
void OpenInternal();
};

Some files were not shown because too many files have changed in this diff Show More