96 changes: 66 additions & 30 deletions Source/Core/Core/IOS/ES/Views.cpp
Expand Up @@ -16,6 +16,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand All @@ -40,7 +41,10 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);

const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);

const ES::TicketReader ticket = FindSignedTicket(TitleID);
u32 view_count = ticket.IsValid() ? static_cast<u32>(ticket.GetNumberOfTickets()) : 0;
Expand All @@ -59,7 +63,7 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETVIEWCNT for titleID: {:016x} (View Count = {})", TitleID,
view_count);

Memory::Write_U32(view_count, request.io_vectors[0].address);
memory.Write_U32(view_count, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -68,8 +72,11 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 1))
return IPCReply(ES_EINVAL);

const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
const u32 maxViews = memory.Read_U32(request.in_vectors[1].address);

const ES::TicketReader ticket = FindSignedTicket(TitleID);

Expand All @@ -83,13 +90,13 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
for (u32 view = 0; view < number_of_views; ++view)
{
const std::vector<u8> ticket_view = ticket.GetRawTicketView(view);
Memory::CopyToEmu(request.io_vectors[0].address + view * sizeof(ES::TicketView),
ticket_view.data(), ticket_view.size());
memory.CopyToEmu(request.io_vectors[0].address + view * sizeof(ES::TicketView),
ticket_view.data(), ticket_view.size());
}
}
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_title_context))
{
Memory::Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
memory.Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
WARN_LOG_FMT(IOS_ES, "GetViews: Faking IOS title {:016x} being present", TitleID);
}

Expand Down Expand Up @@ -152,8 +159,11 @@ IPCReply ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address), nullptr, 0));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
memory.GetPointer(request.io_vectors[0].address), nullptr, 0));
}

IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
Expand All @@ -165,9 +175,12 @@ IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
const ReturnCode ret = GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const ReturnCode ret = GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
nullptr, &ticket_size, std::nullopt);
Memory::Write_U32(ticket_size, request.io_vectors[0].address);
memory.Write_U32(ticket_size, request.io_vectors[0].address);
return IPCReply(ret);
}

Expand All @@ -180,12 +193,15 @@ IPCReply ESDevice::GetTicketFromView(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);
}

u32 ticket_size = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 ticket_size = memory.Read_U32(request.in_vectors[1].address);
if (ticket_size != request.io_vectors[0].size)
return IPCReply(ES_EINVAL);

return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address), &ticket_size,
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
memory.GetPointer(request.io_vectors[0].address), &ticket_size,
std::nullopt));
}

Expand All @@ -194,30 +210,36 @@ IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);

const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(TitleID);

if (!tmd.IsValid())
return IPCReply(FS_ENOENT);

const u32 view_size = static_cast<u32>(tmd.GetRawView().size());
Memory::Write_U32(view_size, request.io_vectors[0].address);
memory.Write_U32(view_size, request.io_vectors[0].address);

INFO_LOG_FMT(IOS_ES, "GetTMDViewSize: {} bytes for title {:016x}", view_size, TitleID);
return IPCReply(IPC_SUCCESS);
}

IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TMDHeader::title_id) ||
request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
memory.Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return IPCReply(ES_EINVAL);
}

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);

if (!tmd.IsValid())
Expand All @@ -227,7 +249,7 @@ IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
if (request.io_vectors[0].size < raw_view.size())
return IPCReply(ES_EINVAL);

Memory::CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());
memory.CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());

INFO_LOG_FMT(IOS_ES, "GetTMDView: {} bytes for title {:016x}", raw_view.size(), title_id);
return IPCReply(IPC_SUCCESS);
Expand All @@ -245,13 +267,16 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
if (request.io_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const bool has_tmd = request.in_vectors[0].size != 0;
size_t tmd_view_size = 0;

if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};

// Yes, this returns -1017, not ES_INVALID_TMD.
Expand All @@ -270,7 +295,7 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
tmd_view_size = m_title_context.tmd.GetRawView().size();
}

Memory::Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
memory.Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -283,9 +308,12 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// Check whether the TMD view size is consistent.
if (request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
memory.Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return IPCReply(ES_EINVAL);
}
Expand All @@ -296,7 +324,7 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};

if (!tmd.IsValid())
Expand All @@ -316,7 +344,7 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (tmd_view.size() > request.io_vectors[0].size)
return IPCReply(ES_EINVAL);

Memory::CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
memory.CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -334,6 +362,9 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
if (!has_ticket_vector && request.in_vectors[0].size != 0)
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> view;

// If no ticket was passed in, IOS returns the ticket view for the current title.
Expand All @@ -348,13 +379,13 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
else
{
std::vector<u8> ticket_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(ticket_bytes.data(), request.in_vectors[0].address, ticket_bytes.size());
memory.CopyFromEmu(ticket_bytes.data(), request.in_vectors[0].address, ticket_bytes.size());
const ES::TicketReader ticket{std::move(ticket_bytes)};

view = ticket.GetRawTicketView(0);
}

Memory::CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
memory.CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -366,8 +397,10 @@ IPCReply ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
if (!m_title_context.active)
return IPCReply(ES_EINVAL);

Memory::Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -376,7 +409,10 @@ IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);

const u32 tmd_size = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 tmd_size = memory.Read_U32(request.in_vectors[0].address);
if (tmd_size != request.io_vectors[0].size)
return IPCReply(ES_EINVAL);

Expand All @@ -388,7 +424,7 @@ IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
return IPCReply(ES_EINVAL);

Memory::CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
memory.CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE
73 changes: 51 additions & 22 deletions Source/Core/Core/IOS/FS/FileSystemProxy.cpp
Expand Up @@ -16,6 +16,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -312,7 +313,9 @@ bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
{
return MakeIPCReply([&](Ticks t) {
return Read(request.fd, Memory::GetPointer(request.buffer), request.size, request.buffer, t);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
});
}

Expand Down Expand Up @@ -340,7 +343,9 @@ s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_add
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
{
return MakeIPCReply([&](Ticks t) {
return Write(request.fd, Memory::GetPointer(request.buffer), request.size, request.buffer, t);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
});
}

Expand Down Expand Up @@ -422,8 +427,11 @@ static Result<T> GetParams(const IOCtlRequest& request)
if (request.buffer_in_size < sizeof(T))
return ResultCode::Invalid;

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

T params;
Memory::CopyFromEmu(&params, request.buffer_in, sizeof(params));
memory.CopyFromEmu(&params, request.buffer_in, sizeof(params));
return params;
}

Expand Down Expand Up @@ -498,6 +506,9 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
if (!stats)
return IPCReply(ConvertResult(stats.Error()));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

ISFSNandStats out;
out.cluster_size = stats->cluster_size;
out.free_clusters = stats->free_clusters;
Expand All @@ -506,7 +517,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
out.reserved_clusters = stats->reserved_clusters;
out.free_inodes = stats->free_inodes;
out.used_inodes = stats->used_inodes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -530,28 +541,31 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
return GetFSReply(ConvertResult(ResultCode::Invalid));
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 file_list_address, file_count_address, max_count;
if (request.in_vectors.size() == 2)
{
if (request.in_vectors[1].size != 4 || request.io_vectors[1].size != 4)
return GetFSReply(ConvertResult(ResultCode::Invalid));
max_count = Memory::Read_U32(request.in_vectors[1].address);
max_count = memory.Read_U32(request.in_vectors[1].address);
file_count_address = request.io_vectors[1].address;
file_list_address = request.io_vectors[0].address;
if (request.io_vectors[0].size != 13 * max_count)
return GetFSReply(ConvertResult(ResultCode::Invalid));
Memory::Write_U32(max_count, file_count_address);
memory.Write_U32(max_count, file_count_address);
}
else
{
if (request.io_vectors[0].size != 4)
return GetFSReply(ConvertResult(ResultCode::Invalid));
max_count = Memory::Read_U32(request.io_vectors[0].address);
max_count = memory.Read_U32(request.io_vectors[0].address);
file_count_address = request.io_vectors[0].address;
file_list_address = 0;
}

const std::string directory = Memory::GetString(request.in_vectors[0].address, 64);
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
const Result<std::vector<std::string>> list =
m_ios.GetFS()->ReadDirectory(handle.uid, handle.gid, directory);
LogResult(list, "ReadDirectory({})", directory);
Expand All @@ -560,19 +574,19 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ

if (!file_list_address)
{
Memory::Write_U32(static_cast<u32>(list->size()), file_count_address);
memory.Write_U32(static_cast<u32>(list->size()), file_count_address);
return GetFSReply(IPC_SUCCESS);
}

for (size_t i = 0; i < list->size() && i < max_count; ++i)
{
Memory::Memset(file_list_address, 0, 13);
Memory::CopyToEmu(file_list_address, (*list)[i].data(), (*list)[i].size());
Memory::Write_U8(0, file_list_address + 12);
memory.Memset(file_list_address, 0, 13);
memory.CopyToEmu(file_list_address, (*list)[i].data(), (*list)[i].size());
memory.Write_U8(0, file_list_address + 12);
file_list_address += static_cast<u32>((*list)[i].size()) + 1;
}
// Write the actual number of entries in the buffer.
Memory::Write_U32(std::min(max_count, static_cast<u32>(list->size())), file_count_address);
memory.Write_U32(std::min(max_count, static_cast<u32>(list->size())), file_count_address);
return GetFSReply(IPC_SUCCESS);
}

Expand All @@ -593,7 +607,10 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
return GetFSReply(ConvertResult(ResultCode::Invalid));

const std::string path = Memory::GetString(request.buffer_in, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const std::string path = memory.GetString(request.buffer_in, 64);
const auto ticks = EstimateFileLookupTicks(path, FileLookupMode::Split);
const Result<Metadata> metadata = m_ios.GetFS()->GetMetadata(handle.uid, handle.gid, path);
LogResult(metadata, "GetMetadata({})", path);
Expand All @@ -608,7 +625,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
out.gid = metadata->gid;
out.attribute = metadata->attribute;
out.modes = metadata->modes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetFSReply(IPC_SUCCESS, ticks);
}

Expand All @@ -627,7 +644,10 @@ IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
if (request.buffer_in_size < 64)
return GetFSReply(ConvertResult(ResultCode::Invalid));

const std::string path = Memory::GetString(request.buffer_in, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const std::string path = memory.GetString(request.buffer_in, 64);
return MakeIPCReply(
[&](Ticks ticks) { return ConvertResult(DeleteFile(handle.uid, handle.gid, path, ticks)); });
}
Expand All @@ -648,8 +668,11 @@ IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
if (request.buffer_in_size < 64 * 2)
return GetFSReply(ConvertResult(ResultCode::Invalid));

const std::string old_path = Memory::GetString(request.buffer_in, 64);
const std::string new_path = Memory::GetString(request.buffer_in + 64, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const std::string old_path = memory.GetString(request.buffer_in, 64);
const std::string new_path = memory.GetString(request.buffer_in + 64, 64);
return MakeIPCReply([&](Ticks ticks) {
return ConvertResult(RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
});
Expand Down Expand Up @@ -699,10 +722,13 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
if (!status)
return ConvertResult(status.Error());

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

ISFSFileStats out;
out.size = status->size;
out.seek_position = status->offset;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return IPC_SUCCESS;
});
}
Expand All @@ -727,14 +753,17 @@ IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
return GetFSReply(ConvertResult(ResultCode::Invalid));
}

const std::string directory = Memory::GetString(request.in_vectors[0].address, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
const Result<DirectoryStats> stats = m_ios.GetFS()->GetDirectoryStats(directory);
LogResult(stats, "GetDirectoryStats({})", directory);
if (!stats)
return GetFSReply(ConvertResult(stats.Error()));

Memory::Write_U32(stats->used_clusters, request.io_vectors[0].address);
Memory::Write_U32(stats->used_inodes, request.io_vectors[1].address);
memory.Write_U32(stats->used_clusters, request.io_vectors[0].address);
memory.Write_U32(stats->used_inodes, request.io_vectors[1].address);
return GetFSReply(IPC_SUCCESS);
}

Expand Down
173 changes: 94 additions & 79 deletions Source/Core/Core/IOS/IOS.cpp
Expand Up @@ -104,6 +104,9 @@ constexpr u32 PLACEHOLDER = 0xDEADBEEF;

static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

auto target_imv = std::find_if(
GetMemoryValues().begin(), GetMemoryValues().end(),
[&](const MemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); });
Expand All @@ -116,7 +119,7 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)

if (setup_type == MemorySetupType::IOSReload)
{
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
memory.Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);

// These values are written by the IOS kernel as part of its boot process (for IOS28 and newer).
//
Expand All @@ -127,15 +130,15 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
// the new IOS either updates the range (>= IOS28) or inherits it (< IOS28).
//
// We can skip this convoluted process and just write the correct range directly.
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
memory.Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);

RAMOverrideForIOSMemoryValues(setup_type);

Expand All @@ -146,40 +149,40 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
// and system information (see below).
constexpr u32 LOW_MEM1_REGION_START = 0;
constexpr u32 LOW_MEM1_REGION_SIZE = 0x3fff;
Memory::Memset(LOW_MEM1_REGION_START, 0, LOW_MEM1_REGION_SIZE);

Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH1);
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH2);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
Memory::Write_U32(PLACEHOLDER, ADDR_PH3);
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
Memory::Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH4);
Memory::Write_U32(PLACEHOLDER, ADDR_PH5);
Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
Memory::Write_U8(0xDE, ADDR_BOOT_FLAG);
Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG);
Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);

Memory::Write_U32(target_imv->mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
Memory::Write_U32(target_imv->mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
memory.Memset(LOW_MEM1_REGION_START, 0, LOW_MEM1_REGION_SIZE);

memory.Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
memory.Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
memory.Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
memory.Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
memory.Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH1);
memory.Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
memory.Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH2);
memory.Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
memory.Write_U32(PLACEHOLDER, ADDR_PH3);
memory.Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
memory.Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
memory.Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH4);
memory.Write_U32(PLACEHOLDER, ADDR_PH5);
memory.Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
memory.Write_U8(0xDE, ADDR_BOOT_FLAG);
memory.Write_U8(0xAD, ADDR_APPLOADER_FLAG);
memory.Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
memory.Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);

memory.Write_U32(target_imv->mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
memory.Write_U32(target_imv->mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
memory.Write_U32(target_imv->mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
memory.Write_U32(target_imv->mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);

RAMOverrideForIOSMemoryValues(setup_type);

Expand All @@ -193,14 +196,18 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
static void ResetAndPausePPC()
{
// This should be cleared when the PPC is released so that the write is not observable.
Memory::Write_U32(0x48000000, 0x00000000); // b 0x0
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0x48000000, 0x00000000); // b 0x0
PowerPC::Reset();
PC = 0;
}

static void ReleasePPC()
{
Memory::Write_U32(0, 0);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0, 0);
// HLE the bootstub that jumps to 0x3400.
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
// The state of other CPU registers (like the BAT registers) doesn't matter much
Expand All @@ -210,7 +217,9 @@ static void ReleasePPC()

static void ReleasePPCAncast()
{
Memory::Write_U32(0, 0);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0, 0);
// On a real console the Espresso verifies and decrypts the Ancast image,
// then jumps to the decrypted ancast body.
// The Ancast loader already did this, so just jump to the decrypted body.
Expand All @@ -223,19 +232,22 @@ void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type)
if (!Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE))
return;

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// Some unstated constants that can be inferred.
const u32 ipc_buffer_size =
Memory::Read_U32(ADDR_IPC_BUFFER_END) - Memory::Read_U32(ADDR_IPC_BUFFER_BEGIN);
memory.Read_U32(ADDR_IPC_BUFFER_END) - memory.Read_U32(ADDR_IPC_BUFFER_BEGIN);
const u32 ios_reserved_size =
Memory::Read_U32(ADDR_IOS_RESERVED_END) - Memory::Read_U32(ADDR_IOS_RESERVED_BEGIN);
memory.Read_U32(ADDR_IOS_RESERVED_END) - memory.Read_U32(ADDR_IOS_RESERVED_BEGIN);

const u32 mem1_physical_size = Memory::GetRamSizeReal();
const u32 mem1_simulated_size = Memory::GetRamSizeReal();
const u32 mem1_physical_size = memory.GetRamSizeReal();
const u32 mem1_simulated_size = memory.GetRamSizeReal();
const u32 mem1_end = Memory::MEM1_BASE_ADDR + mem1_simulated_size;
const u32 mem1_arena_begin = 0;
const u32 mem1_arena_end = mem1_end;
const u32 mem2_physical_size = Memory::GetExRamSizeReal();
const u32 mem2_simulated_size = Memory::GetExRamSizeReal();
const u32 mem2_physical_size = memory.GetExRamSizeReal();
const u32 mem2_simulated_size = memory.GetExRamSizeReal();
const u32 mem2_end = Memory::MEM2_BASE_ADDR + mem2_simulated_size - ios_reserved_size;
const u32 mem2_arena_begin = Memory::MEM2_BASE_ADDR + 0x800U;
const u32 mem2_arena_end = mem2_end - ipc_buffer_size;
Expand All @@ -247,31 +259,33 @@ void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type)
if (setup_type == MemorySetupType::Full)
{
// Overwriting these after the game's apploader sets them would be bad
Memory::Write_U32(mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(mem1_end, ADDR_MEM1_END);
Memory::Write_U32(mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
Memory::Write_U32(mem1_arena_end, ADDR_MEM1_ARENA_END);

Memory::Write_U32(mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
Memory::Write_U32(mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
Memory::Write_U32(mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
Memory::Write_U32(mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
}
Memory::Write_U32(mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(mem2_end, ADDR_MEM2_END);
Memory::Write_U32(mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(mem1_physical_size, ADDR_MEM1_SIZE);
memory.Write_U32(mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
memory.Write_U32(mem1_end, ADDR_MEM1_END);
memory.Write_U32(mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
memory.Write_U32(mem1_arena_end, ADDR_MEM1_ARENA_END);

memory.Write_U32(mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
memory.Write_U32(mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
memory.Write_U32(mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
memory.Write_U32(mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
}
memory.Write_U32(mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(mem2_end, ADDR_MEM2_END);
memory.Write_U32(mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(ios_reserved_end, ADDR_IOS_RESERVED_END);
}

void WriteReturnValue(s32 value, u32 address)
{
Memory::Write_U32(static_cast<u32>(value), address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(value), address);
}

Kernel::Kernel(IOSC::ConsoleType console_type) : m_iosc(console_type)
Expand Down Expand Up @@ -751,13 +765,14 @@ void Kernel::EnqueueIPCRequest(u32 address)
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, s64 cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(return_value), request.address + 4);
// IOS writes back the command that was responded to in the FD field.
Memory::Write_U32(request.command, request.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, request.address);
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(cycles_in_future, s_event_enqueue,
request.address, from);
memory.Write_U32(IPC_REPLY, request.address);
system.GetCoreTiming().ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
}

void Kernel::HandleIPCEvent(u64 userdata)
Expand Down
15 changes: 10 additions & 5 deletions Source/Core/Core/IOS/MIOS.cpp
Expand Up @@ -24,6 +24,7 @@
#include "Core/Host.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

namespace IOS::HLE::MIOS
{
Expand All @@ -32,7 +33,9 @@ static void ReinitHardware()
SConfig::GetInstance().bWii = false;

// IOS clears mem2 and overwrites it with pseudo-random data (for security).
std::memset(Memory::m_pEXRAM, 0, Memory::GetExRamSizeReal());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::memset(memory.GetEXRAM(), 0, memory.GetExRamSizeReal());
// MIOS appears to only reset the DI and the PPC.
// HACK However, resetting DI will reset the DTK config, which is set by the system menu
// (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually
Expand All @@ -52,8 +55,10 @@ constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;

bool Load()
{
Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
Memory::Write_U32(0x09142001, 0x3180);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
memory.Write_U32(0x09142001, 0x3180);

ReinitHardware();
NOTICE_LOG_FMT(IOS, "Reinitialised hardware.");
Expand All @@ -79,11 +84,11 @@ bool Load()

// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
// 0xdeadbeef there, then waits for it to be cleared by IOS before continuing.
while (Memory::Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
PowerPC::SingleStep();
PowerPC::SetMode(core_mode);

Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
NOTICE_LOG_FMT(IOS, "IPL ready.");
SConfig::GetInstance().m_is_mios = true;
DVDInterface::UpdateRunningGameMetadata();
Expand Down
282 changes: 171 additions & 111 deletions Source/Core/Core/IOS/Network/IP/Top.cpp

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp
Expand Up @@ -23,6 +23,7 @@
#include "Core/IOS/Network/KD/VFF/VFFUtil.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -232,12 +233,14 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index,

IPCReply NetKDRequestDevice::HandleNWC24DownloadNowEx(const IOCtlRequest& request)
{
const u32 flags = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 flags = memory.Read_U32(request.buffer_in);
// Nintendo converts the entry ID between a u32 and u16
// several times, presumably for alignment purposes.
// We'll skip past buffer_in+4 and keep the entry index as a u16.
const u16 entry_index = Memory::Read_U16(request.buffer_in + 6);
const u32 subtask_bitmask = Memory::Read_U32(request.buffer_in + 8);
const u16 entry_index = memory.Read_U16(request.buffer_in + 6);
const u32 subtask_bitmask = memory.Read_U32(request.buffer_in + 8);

INFO_LOG_FMT(IOS_WC24,
"NET_KD_REQ: IOCTL_NWC24_DOWNLOAD_NOW_EX - NI - flags: {}, index: {}, bitmask: {}",
Expand Down Expand Up @@ -315,6 +318,8 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28,
};

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
s32 return_value = 0;
switch (request.request)
{
Expand All @@ -335,7 +340,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)

case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket
WriteReturnValue(0, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4);
memory.Write_U32(0, request.buffer_out + 4);
return_value = 0;
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI");
break;
Expand All @@ -356,7 +361,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_NWC24_REQUEST_REGISTER_USER_ID:
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID");
WriteReturnValue(0, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4);
memory.Write_U32(0, request.buffer_out + 4);
break;

case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes)
Expand Down Expand Up @@ -409,8 +414,8 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
{
WriteReturnValue(NWC24::WC24_ERR_ID_REGISTERED, request.buffer_out);
}
Memory::Write_U64(config.Id(), request.buffer_out + 4);
Memory::Write_U32(u32(config.CreationStage()), request.buffer_out + 0xC);
memory.Write_U64(config.Id(), request.buffer_out + 4);
memory.Write_U32(u32(config.CreationStage()), request.buffer_out + 0xC);
break;

case IOCTL_NWC24_GET_SCHEDULER_STAT:
Expand All @@ -435,7 +440,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
}

INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN");
[[maybe_unused]] const u32 event = Memory::Read_U32(request.buffer_in);
[[maybe_unused]] const u32 event = memory.Read_U32(request.buffer_in);
// TODO: Advertise shutdown event
// TODO: Shutdown USB keyboard LEDs if event == 3
// TODO: IOCTLV_NCD_SETCONFIG
Expand Down
18 changes: 11 additions & 7 deletions Source/Core/Core/IOS/Network/KD/NetKDTime.cpp
Expand Up @@ -8,6 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand All @@ -34,36 +35,39 @@ std::optional<IPCReply> NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
// TODO Writes stuff to /shared2/nwc24/misc.bin
u32 update_misc = 0;

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

switch (request.request)
{
case IOCTL_NW24_GET_UNIVERSAL_TIME:
{
const u64 adjusted_utc = GetAdjustedUTC();
Memory::Write_U64(adjusted_utc, request.buffer_out + 4);
memory.Write_U64(adjusted_utc, request.buffer_out + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_GET_UNIVERSAL_TIME = {}, time = {}", result, adjusted_utc);
}
break;

case IOCTL_NW24_SET_UNIVERSAL_TIME:
{
const u64 adjusted_utc = Memory::Read_U64(request.buffer_in);
const u64 adjusted_utc = memory.Read_U64(request.buffer_in);
SetAdjustedUTC(adjusted_utc);
update_misc = Memory::Read_U32(request.buffer_in + 8);
update_misc = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_SET_UNIVERSAL_TIME ({}, {}) = {}", adjusted_utc, update_misc,
result);
}
break;

case IOCTL_NW24_SET_RTC_COUNTER:
rtc = Memory::Read_U32(request.buffer_in);
update_misc = Memory::Read_U32(request.buffer_in + 4);
rtc = memory.Read_U32(request.buffer_in);
update_misc = memory.Read_U32(request.buffer_in + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_SET_RTC_COUNTER ({}, {}) = {}", rtc, update_misc, result);
break;

case IOCTL_NW24_GET_TIME_DIFF:
{
const u64 time_diff = GetAdjustedUTC() - rtc;
Memory::Write_U64(time_diff, request.buffer_out + 4);
memory.Write_U64(time_diff, request.buffer_out + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_GET_TIME_DIFF = {}, time_diff = {}", result, time_diff);
}
break;
Expand All @@ -79,7 +83,7 @@ std::optional<IPCReply> NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
}

// write return values
Memory::Write_U32(common_result, request.buffer_out);
memory.Write_U32(common_result, request.buffer_out);
return IPCReply(result);
}

Expand Down
16 changes: 10 additions & 6 deletions Source/Core/Core/IOS/Network/NCD/Manage.cpp
Expand Up @@ -11,6 +11,7 @@

#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/MACUtils.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand All @@ -32,6 +33,9 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
u32 common_result = 0;
u32 common_vector = 0;

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

switch (request.request)
{
case IOCTLV_NCD_LOCKWIRELESSDRIVER:
Expand All @@ -52,7 +56,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
// We will just write the value of the file descriptor.
// The value will be positive so this will work fine.
m_ipc_fd = request.fd;
Memory::Write_U32(request.fd, request.io_vectors[0].address + 4);
memory.Write_U32(request.fd, request.io_vectors[0].address + 4);
}
break;

Expand All @@ -67,7 +71,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
if (request.io_vectors[0].size < sizeof(u32))
return IPCReply(IPC_EINVAL);

const u32 request_handle = Memory::Read_U32(request.in_vectors[0].address);
const u32 request_handle = memory.Read_U32(request.in_vectors[0].address);
if (m_ipc_fd == request_handle)
{
m_ipc_fd = 0;
Expand Down Expand Up @@ -107,15 +111,15 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTLV_NCD_GETLINKSTATUS:
INFO_LOG_FMT(IOS_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS");
// Always connected
Memory::Write_U32(Net::ConnectionSettings::LINK_WIRED, request.io_vectors.at(0).address + 4);
memory.Write_U32(Net::ConnectionSettings::LINK_WIRED, request.io_vectors.at(0).address + 4);
break;

case IOCTLV_NCD_GETWIRELESSMACADDRESS:
{
INFO_LOG_FMT(IOS_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS");

const Common::MACAddress address = IOS::Net::GetMACAddress();
Memory::CopyToEmu(request.io_vectors.at(1).address, address.data(), address.size());
memory.CopyToEmu(request.io_vectors.at(1).address, address.data(), address.size());
break;
}

Expand All @@ -124,10 +128,10 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
break;
}

Memory::Write_U32(common_result, request.io_vectors.at(common_vector).address);
memory.Write_U32(common_result, request.io_vectors.at(common_vector).address);
if (common_vector == 1)
{
Memory::Write_U32(common_result, request.io_vectors.at(common_vector).address + 4);
memory.Write_U32(common_result, request.io_vectors.at(common_vector).address + 4);
}
return IPCReply(return_value);
}
Expand Down
9 changes: 7 additions & 2 deletions Source/Core/Core/IOS/Network/NCD/WiiNetConfig.cpp
Expand Up @@ -12,6 +12,7 @@
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE::Net
{
Expand Down Expand Up @@ -53,11 +54,15 @@ void WiiNetConfig::ResetConfig(FS::FileSystem* fs)

void WiiNetConfig::WriteToMem(const u32 address) const
{
Memory::CopyToEmu(address, &m_data, sizeof(m_data));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(address, &m_data, sizeof(m_data));
}

void WiiNetConfig::ReadFromMem(const u32 address)
{
Memory::CopyFromEmu(&m_data, address, sizeof(m_data));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(&m_data, address, sizeof(m_data));
}
} // namespace IOS::HLE::Net
38 changes: 21 additions & 17 deletions Source/Core/Core/IOS/Network/SSL.cpp
Expand Up @@ -20,6 +20,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -225,12 +226,15 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
if (Core::WantsDeterminism())
return IPCReply(IPC_EACCES);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

switch (request.request)
{
case IOCTLV_NET_SSL_NEW:
{
int verifyOption = Memory::Read_U32(BufferOut);
std::string hostname = Memory::GetString(BufferOut2, BufferOutSize2);
int verifyOption = memory.Read_U32(BufferOut);
std::string hostname = memory.GetString(BufferOut2, BufferOutSize2);

int freeSSL = GetSSLFreeID();
if (freeSSL)
Expand Down Expand Up @@ -290,7 +294,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SHUTDOWN:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
Expand Down Expand Up @@ -335,17 +339,17 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);

int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
int ret =
mbedtls_x509_crt_parse_der(&ssl->cacert, Memory::GetPointer(BufferOut2), BufferOutSize2);
mbedtls_x509_crt_parse_der(&ssl->cacert, memory.GetPointer(BufferOut2), BufferOutSize2);

if (Config::Get(Config::MAIN_NETWORK_SSL_DUMP_ROOT_CA))
{
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + ssl->hostname + "_rootca.der";
File::IOFile(filename, "wb").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2);
File::IOFile(filename, "wb").WriteBytes(memory.GetPointer(BufferOut2), BufferOutSize2);
}

if (ret)
Expand Down Expand Up @@ -376,7 +380,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);

int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
Expand Down Expand Up @@ -423,7 +427,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);

int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
Expand All @@ -442,7 +446,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SETBUILTINROOTCA:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
Expand Down Expand Up @@ -480,12 +484,12 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_CONNECT:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
mbedtls_ssl_setup(&ssl->ctx, &ssl->config);
ssl->sockfd = Memory::Read_U32(BufferOut2);
ssl->sockfd = memory.Read_U32(BufferOut2);
WiiSockMan& sm = WiiSockMan::GetInstance();
ssl->hostfd = sm.GetHostSocket(ssl->sockfd);
INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", ssl->sockfd);
Expand All @@ -507,7 +511,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_DOHANDSHAKE:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
Expand All @@ -522,7 +526,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_WRITE:
{
const int sslID = Memory::Read_U32(BufferOut) - 1;
const int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
Expand All @@ -540,13 +544,13 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
"BufferOut2: ({:08x}, {}), BufferOut3: ({:08x}, {})",
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
INFO_LOG_FMT(IOS_SSL, "{}", Memory::GetString(BufferOut2));
INFO_LOG_FMT(IOS_SSL, "{}", memory.GetString(BufferOut2));
break;
}
case IOCTLV_NET_SSL_READ:
{
int ret = 0;
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
Expand All @@ -569,7 +573,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SETROOTCADEFAULT:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WriteReturnValue(SSL_OK, BufferIn);
Expand Down Expand Up @@ -597,7 +601,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);

int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WriteReturnValue(SSL_OK, BufferIn);
Expand Down
53 changes: 30 additions & 23 deletions Source/Core/Core/IOS/Network/Socket.cpp
Expand Up @@ -26,6 +26,7 @@
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

#ifdef _WIN32
#define ERRORCODE(name) WSA##name
Expand Down Expand Up @@ -244,6 +245,9 @@ s32 WiiSocket::FCntl(u32 cmd, u32 arg)

void WiiSocket::Update(bool read, bool write, bool except)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

auto it = pending_sockops.begin();
while (it != pending_sockops.end())
{
Expand All @@ -257,15 +261,15 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
case IOCTL_SO_FCNTL:
{
u32 cmd = Memory::Read_U32(ioctl.buffer_in + 4);
u32 arg = Memory::Read_U32(ioctl.buffer_in + 8);
u32 cmd = memory.Read_U32(ioctl.buffer_in + 4);
u32 arg = memory.Read_U32(ioctl.buffer_in + 8);
ReturnValue = FCntl(cmd, arg);
break;
}
case IOCTL_SO_BIND:
{
sockaddr_in local_name;
const u8* addr = Memory::GetPointer(ioctl.buffer_in + 8);
const u8* addr = memory.GetPointer(ioctl.buffer_in + 8);
WiiSockMan::ToNativeAddrIn(addr, &local_name);

int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
Expand All @@ -278,7 +282,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
case IOCTL_SO_CONNECT:
{
sockaddr_in local_name;
const u8* addr = Memory::GetPointer(ioctl.buffer_in + 8);
const u8* addr = memory.GetPointer(ioctl.buffer_in + 8);
WiiSockMan::ToNativeAddrIn(addr, &local_name);

int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
Expand All @@ -295,7 +299,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (ioctl.buffer_out_size > 0)
{
sockaddr_in local_name;
u8* addr = Memory::GetPointer(ioctl.buffer_out);
u8* addr = memory.GetPointer(ioctl.buffer_out);
WiiSockMan::ToNativeAddrIn(addr, &local_name);

socklen_t addrlen = sizeof(sockaddr_in);
Expand Down Expand Up @@ -375,7 +379,7 @@ void WiiSocket::Update(bool read, bool write, bool except)

if (it->is_ssl)
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
switch (it->ssl_type)
Expand Down Expand Up @@ -479,11 +483,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
WII_SSL* ssl = &NetSSLDevice::_SSL[sslID];
const int ret =
mbedtls_ssl_write(&ssl->ctx, Memory::GetPointer(BufferOut2), BufferOutSize2);
mbedtls_ssl_write(&ssl->ctx, memory.GetPointer(BufferOut2), BufferOutSize2);

if (ret >= 0)
{
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(Memory::GetPointer(BufferOut2),
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(memory.GetPointer(BufferOut2),
ret, ssl->hostfd);
// Return bytes written or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
Expand Down Expand Up @@ -513,11 +517,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
WII_SSL* ssl = &NetSSLDevice::_SSL[sslID];
const int ret =
mbedtls_ssl_read(&ssl->ctx, Memory::GetPointer(BufferIn2), BufferInSize2);
mbedtls_ssl_read(&ssl->ctx, memory.GetPointer(BufferIn2), BufferInSize2);

if (ret >= 0)
{
PowerPC::debug_interface.NetworkLogger()->LogSSLRead(Memory::GetPointer(BufferIn2),
PowerPC::debug_interface.NetworkLogger()->LogSSLRead(memory.GetPointer(BufferIn2),
ret, ssl->hostfd);
// Return bytes read or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
Expand Down Expand Up @@ -568,11 +572,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
break;
}

u32 flags = Memory::Read_U32(BufferIn2 + 0x04);
u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08);
u32 flags = memory.Read_U32(BufferIn2 + 0x04);
u32 has_destaddr = memory.Read_U32(BufferIn2 + 0x08);

// Not a string, Windows requires a const char* for sendto
const char* data = (const char*)Memory::GetPointer(BufferIn);
const char* data = (const char*)memory.GetPointer(BufferIn);

// Act as non blocking when SO_MSG_NONBLOCK is specified
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
Expand All @@ -582,7 +586,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
sockaddr_in local_name = {0};
if (has_destaddr)
{
const u8* addr = Memory::GetPointer(BufferIn2 + 0x0C);
const u8* addr = memory.GetPointer(BufferIn2 + 0x0C);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
}

Expand Down Expand Up @@ -615,17 +619,17 @@ void WiiSocket::Update(bool read, bool write, bool except)
break;
}

u32 flags = Memory::Read_U32(BufferIn + 0x04);
u32 flags = memory.Read_U32(BufferIn + 0x04);
// Not a string, Windows requires a char* for recvfrom
char* data = (char*)Memory::GetPointer(BufferOut);
char* data = (char*)memory.GetPointer(BufferOut);
int data_len = BufferOutSize;

sockaddr_in local_name;
memset(&local_name, 0, sizeof(sockaddr_in));

if (BufferOutSize2 != 0)
{
const u8* addr = Memory::GetPointer(BufferOut2);
const u8* addr = memory.GetPointer(BufferOut2);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
}

Expand Down Expand Up @@ -662,7 +666,7 @@ void WiiSocket::Update(bool read, bool write, bool except)

if (BufferOutSize2 != 0)
{
u8* addr = Memory::GetPointer(BufferOut2);
u8* addr = memory.GetPointer(BufferOut2);
WiiSockMan::ToWiiAddrIn(local_name, addr, addrlen);
}
break;
Expand Down Expand Up @@ -1008,10 +1012,13 @@ void WiiSockMan::UpdatePollCommands()
pcmd.timeout = std::max<s64>(0, pcmd.timeout - elapsed);
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

pending_polls.erase(
std::remove_if(
pending_polls.begin(), pending_polls.end(),
[this](PollCommand& pcmd) {
[&memory, this](PollCommand& pcmd) {
const auto request = Request(pcmd.request_addr);
auto& pfds = pcmd.wii_fds;
int ret = 0;
Expand All @@ -1030,7 +1037,7 @@ void WiiSockMan::UpdatePollCommands()
std::iota(original_order.begin(), original_order.end(), 0);
// Select indices with valid fds
auto mid = std::partition(original_order.begin(), original_order.end(), [&](auto i) {
return GetHostSocket(Memory::Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
});
const auto n_valid = std::distance(original_order.begin(), mid);

Expand All @@ -1057,9 +1064,9 @@ void WiiSockMan::UpdatePollCommands()
const int revents = ConvertEvents(pfds[i].revents, ConvertDirection::NativeToWii);

// No need to change fd or events as they are input only.
// Memory::Write_U32(ufds[i].fd, request.buffer_out + 0xc*i); //fd
// Memory::Write_U32(events, request.buffer_out + 0xc*i + 4); //events
Memory::Write_U32(revents, pcmd.buffer_out + 0xc * i + 8); // revents
// memory.Write_U32(ufds[i].fd, request.buffer_out + 0xc*i); //fd
// memory.Write_U32(events, request.buffer_out + 0xc*i + 4); //events
memory.Write_U32(revents, pcmd.buffer_out + 0xc * i + 8); // revents
DEBUG_LOG_FMT(IOS_NET,
"IOCTL_SO_POLL socket {} wevents {:08X} events {:08X} revents {:08X}",
i, revents, pfds[i].events, pfds[i].revents);
Expand Down
20 changes: 15 additions & 5 deletions Source/Core/Core/IOS/Network/WD/Command.cpp
Expand Up @@ -14,6 +14,7 @@
#include "Core/DolphinAnalytics.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/MACUtils.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -233,7 +234,9 @@ IPCReply NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));

const u32 state = Memory::Read_U32(vector->address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 state = memory.Read_U32(vector->address);
INFO_LOG_FMT(IOS_NET, "WD_SetLinkState called (state={}, mode={})", state, m_mode);

if (state == 0)
Expand Down Expand Up @@ -279,8 +282,11 @@ IPCReply NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

Common::MACAddress mac;
Memory::CopyFromEmu(mac.data(), vector->address, mac.size());
memory.CopyFromEmu(mac.data(), vector->address, mac.size());

INFO_LOG_FMT(IOS_NET, "WD_Disassociate: MAC {}", Common::MacAddressToString(mac));

Expand Down Expand Up @@ -309,7 +315,9 @@ IPCReply NetWDCommandDevice::GetInfo(const IOCtlVRequest& request) const
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));

Memory::CopyToEmu(vector->address, &m_info, sizeof(m_info));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(vector->address, &m_info, sizeof(m_info));
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -332,9 +340,11 @@ std::optional<IPCReply> NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
{
// Gives parameters detailing type of scan and what to match
// XXX - unused
// ScanInfo *scan = (ScanInfo *)Memory::GetPointer(request.in_vectors.at(0).m_Address);
// ScanInfo *scan = (ScanInfo *)memory.GetPointer(request.in_vectors.at(0).m_Address);

u16* results = (u16*)Memory::GetPointer(request.io_vectors.at(0).address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u16* results = (u16*)memory.GetPointer(request.io_vectors.at(0).address);
// first u16 indicates number of BSSInfo following
results[0] = Common::swap16(1);

Expand Down
105 changes: 67 additions & 38 deletions Source/Core/Core/IOS/SDIO/SDIOSlot0.cpp
Expand Up @@ -21,6 +21,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -128,7 +129,9 @@ std::optional<IPCReply> SDIOSlot0Device::Close(u32 fd)

std::optional<IPCReply> SDIOSlot0Device::IOCtl(const IOCtlRequest& request)
{
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Memset(request.buffer_out, 0, request.buffer_out_size);

switch (request.request)
{
Expand Down Expand Up @@ -187,15 +190,18 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
u32 pad0;
} req;

req.command = Memory::Read_U32(buffer_in + 0);
req.type = Memory::Read_U32(buffer_in + 4);
req.resp = Memory::Read_U32(buffer_in + 8);
req.arg = Memory::Read_U32(buffer_in + 12);
req.blocks = Memory::Read_U32(buffer_in + 16);
req.bsize = Memory::Read_U32(buffer_in + 20);
req.addr = Memory::Read_U32(buffer_in + 24);
req.isDMA = Memory::Read_U32(buffer_in + 28);
req.pad0 = Memory::Read_U32(buffer_in + 32);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

req.command = memory.Read_U32(buffer_in + 0);
req.type = memory.Read_U32(buffer_in + 4);
req.resp = memory.Read_U32(buffer_in + 8);
req.arg = memory.Read_U32(buffer_in + 12);
req.blocks = memory.Read_U32(buffer_in + 16);
req.bsize = memory.Read_U32(buffer_in + 20);
req.addr = memory.Read_U32(buffer_in + 24);
req.isDMA = memory.Read_U32(buffer_in + 28);
req.pad0 = memory.Read_U32(buffer_in + 32);

// Note: req.addr is the virtual address of _rwBuffer

Expand All @@ -206,19 +212,19 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
case GO_IDLE_STATE:
INFO_LOG_FMT(IOS_SD, "GO_IDLE_STATE");
// Response is R1 (idle state)
Memory::Write_U32(0x00, buffer_out);
memory.Write_U32(0x00, buffer_out);
break;

case SEND_RELATIVE_ADDR:
// Technically RCA should be generated when asked and at power on...w/e :p
Memory::Write_U32(0x9f62, buffer_out);
memory.Write_U32(0x9f62, buffer_out);
break;

case SELECT_CARD:
// This covers both select and deselect
// Differentiate by checking if rca is set in req.arg
// If it is, it's a select and return 0x700
Memory::Write_U32((req.arg >> 16) ? 0x700 : 0x900, buffer_out);
memory.Write_U32((req.arg >> 16) ? 0x700 : 0x900, buffer_out);
break;

case SEND_IF_COND:
Expand All @@ -227,45 +233,45 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
// voltage and the check pattern that were set in the command argument.
// This command is used to differentiate between protocol v1 and v2.
InitSDHC();
Memory::Write_U32(req.arg, buffer_out);
memory.Write_U32(req.arg, buffer_out);
break;

case SEND_CSD:
{
const std::array<u32, 4> csd = m_protocol == SDProtocol::V1 ? GetCSDv1() : GetCSDv2();
Memory::CopyToEmuSwapped(buffer_out, csd.data(), csd.size() * sizeof(u32));
memory.CopyToEmuSwapped(buffer_out, csd.data(), csd.size() * sizeof(u32));
}
break;

case ALL_SEND_CID:
case SEND_CID:
INFO_LOG_FMT(IOS_SD, "(ALL_)SEND_CID");
Memory::Write_U32(0x80114d1c, buffer_out);
Memory::Write_U32(0x80080000, buffer_out + 4);
Memory::Write_U32(0x8007b520, buffer_out + 8);
Memory::Write_U32(0x80080000, buffer_out + 12);
memory.Write_U32(0x80114d1c, buffer_out);
memory.Write_U32(0x80080000, buffer_out + 4);
memory.Write_U32(0x8007b520, buffer_out + 8);
memory.Write_U32(0x80080000, buffer_out + 12);
break;

case SET_BLOCKLEN:
m_block_length = req.arg;
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;

case APP_CMD_NEXT:
// Next cmd is going to be ACMD_*
Memory::Write_U32(0x920, buffer_out);
memory.Write_U32(0x920, buffer_out);
break;

case ACMD_SETBUSWIDTH:
// 0 = 1bit, 2 = 4bit
m_bus_width = (req.arg & 3);
Memory::Write_U32(0x920, buffer_out);
memory.Write_U32(0x920, buffer_out);
break;

case ACMD_SENDOPCOND:
// Sends host capacity support information (HCS) and asks the accessed card to send
// its operating condition register (OCR) content
Memory::Write_U32(GetOCRegister(), buffer_out);
memory.Write_U32(GetOCRegister(), buffer_out);
break;

case READ_MULTIPLE_BLOCK:
Expand All @@ -283,7 +289,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
if (!m_card.Seek(address, File::SeekOrigin::Begin))
ERROR_LOG_FMT(IOS_SD, "Seek failed");

if (m_card.ReadBytes(Memory::GetPointer(req.addr), size))
if (m_card.ReadBytes(memory.GetPointer(req.addr), size))
{
DEBUG_LOG_FMT(IOS_SD, "Outbuffer size {} got {}", rw_buffer_size, size);
}
Expand All @@ -295,7 +301,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
}
}
}
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;

case WRITE_MULTIPLE_BLOCK:
Expand All @@ -313,15 +319,15 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
if (!m_card.Seek(address, File::SeekOrigin::Begin))
ERROR_LOG_FMT(IOS_SD, "Seek failed");

if (!m_card.WriteBytes(Memory::GetPointer(req.addr), size))
if (!m_card.WriteBytes(memory.GetPointer(req.addr), size))
{
ERROR_LOG_FMT(IOS_SD, "Write Failed - error: {}, eof: {}", std::ferror(m_card.GetHandle()),
std::feof(m_card.GetHandle()));
ret = RET_FAIL;
}
}
}
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;

case EVENT_REGISTER: // async
Expand Down Expand Up @@ -354,8 +360,11 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b

IPCReply SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
const u32 val = Memory::Read_U32(request.buffer_in + 16);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 reg = memory.Read_U32(request.buffer_in);
const u32 val = memory.Read_U32(request.buffer_in + 16);

INFO_LOG_FMT(IOS_SD, "IOCTL_WRITEHCR {:#010x} - {:#010x}", reg, val);

Expand Down Expand Up @@ -386,7 +395,10 @@ IPCReply SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)

IPCReply SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 reg = memory.Read_U32(request.buffer_in);

if (reg >= m_registers.size())
{
Expand All @@ -398,16 +410,19 @@ IPCReply SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
INFO_LOG_FMT(IOS_SD, "IOCTL_READHCR {:#010x} - {:#010x}", reg, val);

// Just reading the register
Memory::Write_U32(val, request.buffer_out);
memory.Write_U32(val, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}

IPCReply SDIOSlot0Device::ResetCard(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_RESETCARD");

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(m_status, request.buffer_out);
memory.Write_U32(m_status, request.buffer_out);

return IPCReply(IPC_SUCCESS);
}
Expand All @@ -416,9 +431,12 @@ IPCReply SDIOSlot0Device::SetClk(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SETCLK");

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// 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.
const u32 clock = Memory::Read_U32(request.buffer_in);
const u32 clock = memory.Read_U32(request.buffer_in);
if (clock != 1)
INFO_LOG_FMT(IOS_SD, "Setting to {}, interesting", clock);

Expand All @@ -427,7 +445,10 @@ IPCReply SDIOSlot0Device::SetClk(const IOCtlRequest& request)

std::optional<IPCReply> SDIOSlot0Device::SendCommand(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SENDCMD {:x} IPC:{:08x}", Memory::Read_U32(request.buffer_in),
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

INFO_LOG_FMT(IOS_SD, "IOCTL_SENDCMD {:x} IPC:{:08x}", memory.Read_U32(request.buffer_in),
request.address);

const s32 return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
Expand Down Expand Up @@ -476,23 +497,31 @@ IPCReply SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
(status & CARD_INSERTED) ? "inserted" : "not present",
(status & CARD_INITIALIZED) ? " and initialized" : "");

Memory::Write_U32(status, request.buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(status, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}

IPCReply SDIOSlot0Device::GetOCRegister(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 ocr = GetOCRegister();
INFO_LOG_FMT(IOS_SD, "IOCTL_GETOCR. Replying with ocr {:x}", ocr);
Memory::Write_U32(ocr, request.buffer_out);
memory.Write_U32(ocr, request.buffer_out);

return IPCReply(IPC_SUCCESS);
}

IPCReply SDIOSlot0Device::SendCommand(const IOCtlVRequest& request)
{
DEBUG_LOG_FMT(IOS_SD, "IOCTLV_SENDCMD {:#010x}", Memory::Read_U32(request.in_vectors[0].address));
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

DEBUG_LOG_FMT(IOS_SD, "IOCTLV_SENDCMD {:#010x}", memory.Read_U32(request.in_vectors[0].address));
memory.Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);

const s32 return_value =
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,
Expand Down
12 changes: 9 additions & 3 deletions Source/Core/Core/IOS/STM/STM.cpp
Expand Up @@ -10,13 +10,17 @@
#include "Common/Logging/Log.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace IOS::HLE
{
static std::unique_ptr<IOCtlRequest> s_event_hook_request;

std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

s32 return_value = IPC_SUCCESS;
switch (request.request)
{
Expand All @@ -32,7 +36,7 @@ std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
return_value = IPC_ENOENT;
break;
}
Memory::Write_U32(0, s_event_hook_request->buffer_out);
memory.Write_U32(0, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
break;
Expand All @@ -45,7 +49,7 @@ std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes)
INFO_LOG_FMT(IOS_STM, "{} - IOCtl:", GetDeviceName());
INFO_LOG_FMT(IOS_STM, " IOCTL_STM_VIDIMMING");
// Memory::Write_U32(1, buffer_out);
// memory.Write_U32(1, buffer_out);
// return_value = 1;
break;

Expand Down Expand Up @@ -101,7 +105,9 @@ void STMEventHookDevice::TriggerEvent(const u32 event) const
if (!m_is_active || !s_event_hook_request)
return;

Memory::Write_U32(event, s_event_hook_request->buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(event, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
}
Expand Down
24 changes: 18 additions & 6 deletions Source/Core/Core/IOS/USB/Bluetooth/BTEmu.cpp
Expand Up @@ -164,15 +164,18 @@ std::optional<IPCReply> BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
{
case ACL_DATA_OUT: // ACL data is received from the stack
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// This is the ACL datapath from CPU to Wii Remote
const auto* acl_header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.data_address));
reinterpret_cast<hci_acldata_hdr_t*>(memory.GetPointer(ctrl.data_address));

DEBUG_ASSERT(HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
DEBUG_ASSERT(HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);

SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
Memory::GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
memory.GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
acl_header->length);
break;
}
Expand Down Expand Up @@ -244,8 +247,11 @@ void BluetoothEmuDevice::SendACLPacket(const bdaddr_t& source, const u8* data, u
DEBUG_LOG_FMT(IOS_WIIMOTE, "ACL endpoint valid, sending packet to {:08x}",
m_acl_endpoint->ios_request.address);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

hci_acldata_hdr_t* header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_acl_endpoint->data_address));
reinterpret_cast<hci_acldata_hdr_t*>(memory.GetPointer(m_acl_endpoint->data_address));
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;

Expand Down Expand Up @@ -421,7 +427,10 @@ void BluetoothEmuDevice::ACLPool::WriteToEndpoint(const USB::V0BulkMessage& endp
DEBUG_LOG_FMT(IOS_WIIMOTE, "ACL packet being written from queue to {:08x}",
endpoint.ios_request.address);

hci_acldata_hdr_t* header = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.data_address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

hci_acldata_hdr_t* header = (hci_acldata_hdr_t*)memory.GetPointer(endpoint.data_address);
header->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;

Expand Down Expand Up @@ -957,10 +966,13 @@ bool BluetoothEmuDevice::SendEventConPacketTypeChange(u16 connection_handle, u16
// This is called from the USB::IOCTLV_USBV0_CTRLMSG Ioctlv
void BluetoothEmuDevice::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message)
{
const u8* input = Memory::GetPointer(ctrl_message.data_address + 3);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u8* input = memory.GetPointer(ctrl_message.data_address + 3);

SCommandMessage msg;
std::memcpy(&msg, Memory::GetPointer(ctrl_message.data_address), sizeof(msg));
std::memcpy(&msg, memory.GetPointer(ctrl_message.data_address), sizeof(msg));

const u16 ocf = HCI_OCF(msg.Opcode);
const u16 ogf = HCI_OGF(msg.Opcode);
Expand Down
35 changes: 24 additions & 11 deletions Source/Core/Core/IOS/USB/Bluetooth/BTReal.cpp
Expand Up @@ -28,6 +28,7 @@
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"
#include "VideoCommon/OnScreenDisplay.h"

namespace IOS::HLE
Expand Down Expand Up @@ -213,9 +214,12 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
// HCI commands to the Bluetooth adapter
case USB::IOCTLV_USBV0_CTRLMSG:
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::lock_guard lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
const u16 opcode = Common::swap16(memory.Read_U16(cmd->data_address));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
m_fake_read_buffer_size_reply.Set();
Expand All @@ -231,7 +235,7 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
{
// Delete link key(s) from our own link key storage when the game tells the adapter to
hci_delete_stored_link_key_cp delete_cmd;
Memory::CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
memory.CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
if (delete_cmd.delete_all)
m_link_keys.clear();
else
Expand All @@ -240,7 +244,7 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
auto buffer = std::make_unique<u8[]>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
cmd->length);
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
memory.CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.get(), nullptr, this, 0);
Expand Down Expand Up @@ -490,13 +494,16 @@ bool BluetoothRealDevice::SendHCIStoreLinkKeyCommand()

void BluetoothRealDevice::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = m_fake_vendor_command_reply_opcode;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
}

Expand All @@ -507,33 +514,39 @@ void BluetoothRealDevice::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
// (including Wiimote disconnects and "event mismatch" warning messages).
void BluetoothRealDevice::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = HCI_CMD_READ_BUFFER_SIZE;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));

hci_read_buffer_size_rp reply;
reply.status = 0x00;
reply.max_acl_size = ACL_PKT_SIZE;
reply.num_acl_pkts = ACL_PKT_NUM;
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
memory.CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
}

void BluetoothRealDevice::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload,
const u8 size)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

hci_event_hdr_t hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.event = HCI_EVENT_VENDOR;
hci_event.length = size;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
}

Expand Down
13 changes: 10 additions & 3 deletions Source/Core/Core/IOS/USB/Common.cpp
Expand Up @@ -11,21 +11,26 @@
#include "Common/CommonTypes.h"
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace IOS::HLE::USB
{
std::unique_ptr<u8[]> TransferCommand::MakeBuffer(const size_t size) const
{
ASSERT_MSG(IOS_USB, data_address != 0, "Invalid data_address");
auto buffer = std::make_unique<u8[]>(size);
Memory::CopyFromEmu(buffer.get(), data_address, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(buffer.get(), data_address, size);
return buffer;
}

void TransferCommand::FillBuffer(const u8* src, const size_t size) const
{
ASSERT_MSG(IOS_USB, size == 0 || data_address != 0, "Invalid data_address");
Memory::CopyToEmu(data_address, src, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(data_address, src, size);
}

void TransferCommand::OnTransferComplete(s32 return_value) const
Expand All @@ -35,7 +40,9 @@ void TransferCommand::OnTransferComplete(s32 return_value) const

void IsoMessage::SetPacketReturnValue(const size_t packet_num, const u16 return_value) const
{
Memory::Write_U16(return_value, static_cast<u32>(packet_sizes_addr + packet_num * sizeof(u16)));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U16(return_value, static_cast<u32>(packet_sizes_addr + packet_num * sizeof(u16)));
}

Device::~Device() = default;
Expand Down
7 changes: 6 additions & 1 deletion Source/Core/Core/IOS/USB/LibusbDevice.cpp
Expand Up @@ -21,6 +21,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/System.h"

namespace IOS::HLE::USB
{
Expand Down Expand Up @@ -247,7 +248,11 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
auto buffer = std::make_unique<u8[]>(size);
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
cmd->length);
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);

libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CtrlTransferCallback, this, 0);
Expand Down
49 changes: 34 additions & 15 deletions Source/Core/Core/IOS/USB/OH0/OH0.cpp
Expand Up @@ -18,6 +18,7 @@
#include "Core/IOS/USB/Common.h"
#include "Core/IOS/USB/USBV0.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand Down Expand Up @@ -92,9 +93,12 @@ IPCReply OH0::CancelInsertionHook(const IOCtlRequest& request)
if (!request.buffer_in || request.buffer_in_size != 4)
return IPCReply(IPC_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// IOS assigns random IDs, but ours are simply the VID + PID (see RegisterInsertionHookWithID)
TriggerHook(m_insertion_hooks,
{Memory::Read_U16(request.buffer_in), Memory::Read_U16(request.buffer_in + 2)},
{memory.Read_U16(request.buffer_in), memory.Read_U16(request.buffer_in + 2)},
USB_ECANCELED);
return IPCReply(IPC_SUCCESS);
}
Expand All @@ -104,11 +108,14 @@ IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const
if (!request.HasNumberOfValidVectors(2, 2))
return IPCReply(IPC_EINVAL);

const u8 max_entries_count = Memory::Read_U8(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u8 max_entries_count = memory.Read_U8(request.in_vectors[0].address);
if (request.io_vectors[1].size != max_entries_count * sizeof(DeviceEntry))
return IPCReply(IPC_EINVAL);

const u8 interface_class = Memory::Read_U8(request.in_vectors[1].address);
const u8 interface_class = memory.Read_U8(request.in_vectors[1].address);
u8 entries_count = 0;
std::lock_guard lk(m_devices_mutex);
for (const auto& device : m_devices)
Expand All @@ -122,9 +129,9 @@ IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const
entry.unknown = 0;
entry.vid = Common::swap16(device.second->GetVid());
entry.pid = Common::swap16(device.second->GetPid());
Memory::CopyToEmu(request.io_vectors[1].address + 8 * entries_count++, &entry, 8);
memory.CopyToEmu(request.io_vectors[1].address + 8 * entries_count++, &entry, 8);
}
Memory::Write_U8(entries_count, request.io_vectors[0].address);
memory.Write_U8(entries_count, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

Expand All @@ -133,8 +140,11 @@ IPCReply OH0::GetRhDesca(const IOCtlRequest& request) const
if (!request.buffer_out || request.buffer_out_size != 4)
return IPCReply(IPC_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// Based on a hardware test, this ioctl seems to return a constant value
Memory::Write_U32(0x02000302, request.buffer_out);
memory.Write_U32(0x02000302, request.buffer_out);
request.Dump(GetDeviceName(), Common::Log::LogType::IOS_USB, Common::Log::LogLevel::LWARNING);
return IPCReply(IPC_SUCCESS);
}
Expand Down Expand Up @@ -174,8 +184,11 @@ std::optional<IPCReply> OH0::RegisterInsertionHook(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 0))
return IPCReply(IPC_EINVAL);

const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u16 vid = memory.Read_U16(request.in_vectors[0].address);
const u16 pid = memory.Read_U16(request.in_vectors[1].address);
if (HasDeviceWithVidPid(vid, pid))
return IPCReply(IPC_SUCCESS);

Expand All @@ -190,16 +203,19 @@ std::optional<IPCReply> OH0::RegisterInsertionHookWithID(const IOCtlVRequest& re
if (!request.HasNumberOfValidVectors(3, 1))
return IPCReply(IPC_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::lock_guard lock{m_hooks_mutex};
const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
const bool trigger_only_for_new_device = Memory::Read_U8(request.in_vectors[2].address) == 1;
const u16 vid = memory.Read_U16(request.in_vectors[0].address);
const u16 pid = memory.Read_U16(request.in_vectors[1].address);
const bool trigger_only_for_new_device = memory.Read_U8(request.in_vectors[2].address) == 1;
if (!trigger_only_for_new_device && HasDeviceWithVidPid(vid, pid))
return IPCReply(IPC_SUCCESS);
// TODO: figure out whether IOS allows more than one hook.
m_insertion_hooks.insert({{vid, pid}, request.address});
// The output vector is overwritten with an ID to use with ioctl 31 for cancelling the hook.
Memory::Write_U32(vid << 16 | pid, request.io_vectors[0].address);
memory.Write_U32(vid << 16 | pid, request.io_vectors[0].address);
return std::nullopt;
}

Expand Down Expand Up @@ -316,25 +332,28 @@ std::optional<IPCReply> OH0::DeviceIOCtlV(const u64 device_id, const IOCtlVReque

s32 OH0::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

switch (ioctlv.request)
{
case USB::IOCTLV_USBV0_CTRLMSG:
if (!ioctlv.HasNumberOfValidVectors(6, 1) ||
Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size)
Common::swap16(memory.Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0CtrlMessage>(m_ios, ioctlv));

case USB::IOCTLV_USBV0_BLKMSG:
case USB::IOCTLV_USBV0_LBLKMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
memory.Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0BulkMessage>(
m_ios, ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG));

case USB::IOCTLV_USBV0_INTRMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
memory.Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(m_ios, ioctlv));

Expand Down
37 changes: 23 additions & 14 deletions Source/Core/Core/IOS/USB/USBV0.cpp
Expand Up @@ -9,44 +9,53 @@
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"

namespace IOS::HLE::USB
{
V0CtrlMessage::V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address);
request = Memory::Read_U8(ioctlv.in_vectors[1].address);
value = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[2].address));
index = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[3].address));
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request_type = memory.Read_U8(ioctlv.in_vectors[0].address);
request = memory.Read_U8(ioctlv.in_vectors[1].address);
value = Common::swap16(memory.Read_U16(ioctlv.in_vectors[2].address));
index = Common::swap16(memory.Read_U16(ioctlv.in_vectors[3].address));
length = Common::swap16(memory.Read_U16(ioctlv.in_vectors[4].address));
}

V0BulkMessage::V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length)
: BulkMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
if (long_length)
length = Memory::Read_U32(ioctlv.in_vectors[1].address);
length = memory.Read_U32(ioctlv.in_vectors[1].address);
else
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
}

V0IntrMessage::V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
}

V0IsoMessage::V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, ioctlv.io_vectors[1].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
num_packets = Memory::Read_U8(ioctlv.in_vectors[2].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
num_packets = memory.Read_U8(ioctlv.in_vectors[2].address);
packet_sizes_addr = ioctlv.io_vectors[0].address;
for (size_t i = 0; i < num_packets; ++i)
packet_sizes.push_back(Memory::Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16))));
packet_sizes.push_back(memory.Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16))));
}
} // namespace IOS::HLE::USB
23 changes: 18 additions & 5 deletions Source/Core/Core/IOS/USB/USBV4.cpp
Expand Up @@ -12,6 +12,7 @@
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"

namespace IOS::HLE::USB
{
Expand Down Expand Up @@ -47,8 +48,11 @@ struct HIDRequest

V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
request_type = hid_request.control.bmRequestType;
request = hid_request.control.bmRequest;
value = Common::swap16(hid_request.control.wValue);
Expand All @@ -63,8 +67,11 @@ V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessa
V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl)
: CtrlMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
request_type = 0x80;
request = REQUEST_GET_DESCRIPTOR;
value = (0x03 << 8) | hid_request.string.bIndex;
Expand All @@ -75,16 +82,22 @@ V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioct

void V4GetUSStringMessage::OnTransferComplete(s32 return_value) const
{
std::string message = Memory::GetString(data_address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::string message = memory.GetString(data_address);
std::replace_if(message.begin(), message.end(), std::not_fn(IsPrintableCharacter), '?');
Memory::CopyToEmu(data_address, message.c_str(), message.size());
memory.CopyToEmu(data_address, message.c_str(), message.size());
TransferCommand::OnTransferComplete(return_value);
}

V4IntrMessage::V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl) : IntrMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
length = Common::swap32(hid_request.interrupt.length);
endpoint = static_cast<u8>(Common::swap32(hid_request.interrupt.endpoint));
data_address = Common::swap32(hid_request.data_addr);
Expand Down
49 changes: 34 additions & 15 deletions Source/Core/Core/IOS/USB/USBV5.cpp
Expand Up @@ -13,6 +13,7 @@
#include "Common/Swap.h"
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace IOS::HLE
{
Expand All @@ -21,37 +22,45 @@ namespace USB
V5CtrlMessage::V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address + 8);
request = Memory::Read_U8(ioctlv.in_vectors[0].address + 9);
value = Memory::Read_U16(ioctlv.in_vectors[0].address + 10);
index = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request_type = memory.Read_U8(ioctlv.in_vectors[0].address + 8);
request = memory.Read_U8(ioctlv.in_vectors[0].address + 9);
value = memory.Read_U16(ioctlv.in_vectors[0].address + 10);
index = memory.Read_U16(ioctlv.in_vectors[0].address + 12);
length = static_cast<u16>(ioctlv.GetVector(1)->size);
}

V5BulkMessage::V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: BulkMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
length = ioctlv.GetVector(1)->size;
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 18);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 18);
}

V5IntrMessage::V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
length = ioctlv.GetVector(1)->size;
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 14);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 14);
}

V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, ioctlv.GetVector(2)->address)
{
num_packets = Memory::Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 17);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
num_packets = memory.Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 17);
packet_sizes_addr = ioctlv.GetVector(1)->address;
u32 total_packet_size = 0;
for (size_t i = 0; i < num_packets; ++i)
{
const u32 packet_size = Memory::Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16)));
const u32 packet_size = memory.Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16)));
packet_sizes.push_back(packet_size);
total_packet_size += packet_size;
}
Expand Down Expand Up @@ -99,8 +108,10 @@ void USBV5ResourceManager::DoState(PointerWrap& p)

USBV5ResourceManager::USBV5Device* USBV5ResourceManager::GetUSBV5Device(u32 in_buffer)
{
const u8 index = Memory::Read_U8(in_buffer + offsetof(DeviceID, index));
const u16 number = Memory::Read_U16(in_buffer + offsetof(DeviceID, number));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 index = memory.Read_U8(in_buffer + offsetof(DeviceID, index));
const u16 number = memory.Read_U16(in_buffer + offsetof(DeviceID, number));

if (index >= m_usbv5_devices.size())
return nullptr;
Expand Down Expand Up @@ -135,7 +146,9 @@ IPCReply USBV5ResourceManager::SetAlternateSetting(USBV5Device& device, const IO
if (!host_device->AttachAndChangeInterface(device.interface_number))
return IPCReply(-1);

const u8 alt_setting = Memory::Read_U8(request.buffer_in + 2 * sizeof(s32));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 alt_setting = memory.Read_U8(request.buffer_in + 2 * sizeof(s32));

const bool success = host_device->SetAltSetting(alt_setting) == 0;
return IPCReply(success ? IPC_SUCCESS : IPC_EINVAL);
Expand All @@ -160,8 +173,11 @@ IPCReply USBV5ResourceManager::Shutdown(const IOCtlRequest& request)

IPCReply USBV5ResourceManager::SuspendResume(USBV5Device& device, const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const auto host_device = GetDeviceById(device.host_id);
const s32 resumed = Memory::Read_U32(request.buffer_in + 8);
const s32 resumed = memory.Read_U32(request.buffer_in + 8);

// Note: this is unimplemented because there's no easy way to do this in a
// platform-independant way (libusb does not support power management).
Expand Down Expand Up @@ -232,6 +248,9 @@ void USBV5ResourceManager::TriggerDeviceChangeReply()
return;
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::lock_guard lock{m_usbv5_devices_mutex};
u8 num_devices = 0;
for (auto it = m_usbv5_devices.crbegin(); it != m_usbv5_devices.crend(); ++it)
Expand Down Expand Up @@ -264,8 +283,8 @@ void USBV5ResourceManager::TriggerDeviceChangeReply()
entry.interface_number = usbv5_device.interface_number;
entry.num_altsettings = device->GetNumberOfAltSettings(entry.interface_number);

Memory::CopyToEmu(m_devicechange_hook_request->buffer_out + sizeof(entry) * num_devices, &entry,
sizeof(entry));
memory.CopyToEmu(m_devicechange_hook_request->buffer_out + sizeof(entry) * num_devices, &entry,
sizeof(entry));
++num_devices;
}

Expand Down