Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #11787 from AdmiralCurtiss/ios-emulationkernel
IOS: Leverage Kernel/EmulationKernel difference for passing System to most IOS devices.
  • Loading branch information
leoetlino committed Apr 27, 2023
2 parents adbee91 + 15a0860 commit 89154c8
Show file tree
Hide file tree
Showing 59 changed files with 505 additions and 429 deletions.
39 changes: 21 additions & 18 deletions Source/Core/Core/IOS/DI/DI.cpp
Expand Up @@ -41,7 +41,8 @@ namespace IOS::HLE
{
CoreTiming::EventType* DIDevice::s_finish_executing_di_command;

DIDevice::DIDevice(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
DIDevice::DIDevice(EmulationKernel& ios, const std::string& device_name)
: EmulationDevice(ios, device_name)
{
}

Expand Down Expand Up @@ -70,7 +71,7 @@ std::optional<IPCReply> DIDevice::IOCtl(const IOCtlRequest& request)
// asynchronously. The rest are also treated as async to match this. Only one command can be
// executed at a time, so commands are queued until DVDInterface is ready to handle them.

auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto& memory = system.GetMemory();
const u8 command = memory.Read_U8(request.buffer_in);
if (request.request != command)
Expand Down Expand Up @@ -105,12 +106,13 @@ void DIDevice::ProcessQueuedIOCtl()
m_executing_command = {m_commands_to_execute.front()};
m_commands_to_execute.pop_front();

IOCtlRequest request{m_executing_command->m_request_address};
auto& system = GetSystem();
IOCtlRequest request{system, m_executing_command->m_request_address};
auto finished = StartIOCtl(request);
if (finished)
{
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(
IPC_OVERHEAD_TICKS, s_finish_executing_di_command, static_cast<u64>(finished.value()));
system.GetCoreTiming().ScheduleEvent(IPC_OVERHEAD_TICKS, s_finish_executing_di_command,
static_cast<u64>(finished.value()));
return;
}
}
Expand All @@ -124,7 +126,7 @@ std::optional<DIDevice::DIResult> DIDevice::WriteIfFits(const IOCtlRequest& requ
}
else
{
auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto& memory = system.GetMemory();
memory.Write_U32(value, request.buffer_out);
return DIResult::Success;
Expand All @@ -150,7 +152,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::SecurityError;
}

auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto& memory = system.GetMemory();
auto* mmio = memory.GetMMIOMapping();

Expand Down Expand Up @@ -561,7 +563,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartDMATransfer(u32 command_length,
return DIResult::BadArgument;
}

auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto* mmio = system.GetMemory().GetMMIOMapping();
mmio->Write<u32>(ADDRESS_DIMAR, request.buffer_out);
m_last_length = command_length;
Expand All @@ -585,7 +587,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartImmediateTransfer(const IOCtlRe

m_executing_command->m_copy_diimmbuf = write_to_buf;

Core::System::GetInstance().GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS);
auto& system = GetSystem();
system.GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS);
// Reply will be posted when done by FinishIOCtl.
return {};
}
Expand Down Expand Up @@ -649,15 +652,15 @@ void DIDevice::FinishDICommand(DIResult result)
return;
}

auto& system = Core::System::GetInstance();
auto& system = GetSystem();
auto& memory = system.GetMemory();
auto* mmio = memory.GetMMIOMapping();

IOCtlRequest request{m_executing_command->m_request_address};
IOCtlRequest request{system, m_executing_command->m_request_address};
if (m_executing_command->m_copy_diimmbuf)
memory.Write_U32(mmio->Read<u32>(ADDRESS_DIIMMBUF), request.buffer_out);

m_ios.EnqueueIPCReply(request, static_cast<s32>(result));
GetEmulationKernel().EnqueueIPCReply(request, static_cast<s32>(result));

m_executing_command.reset();

Expand All @@ -683,7 +686,7 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
return IPCReply{static_cast<s32>(DIResult::BadArgument)};
}

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

const u8 command = memory.Read_U8(request.in_vectors[0].address);
Expand Down Expand Up @@ -742,17 +745,17 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
case DIIoctl::DVDLowGetNoDiscOpenPartitionParams:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscOpenPartitionParams - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_DI);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowNoDiscOpenPartition:
ERROR_LOG_FMT(IOS_DI, "DVDLowNoDiscOpenPartition - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_DI);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowGetNoDiscBufferSizes:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscBufferSizes - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_DI);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowOpenPartitionWithTmdAndTicket:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicket - not implemented");
Expand All @@ -764,7 +767,7 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
break;
default:
ERROR_LOG_FMT(IOS_DI, "Unknown ioctlv {:#04x}", request.request);
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_DI);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
}
return IPCReply{static_cast<s32>(return_value)};
}
Expand Down Expand Up @@ -804,7 +807,7 @@ void DIDevice::ResetDIRegisters()
{
// Clear transfer complete and error interrupts (normally r/z, but here we just directly write
// zero)
auto& di = Core::System::GetInstance().GetDVDInterface();
auto& di = GetSystem().GetDVDInterface();
di.ClearInterrupt(DVD::DIInterruptType::TCINT);
di.ClearInterrupt(DVD::DIInterruptType::DEINT);
// Enable transfer complete and error interrupts, and disable cover interrupt
Expand Down
4 changes: 2 additions & 2 deletions Source/Core/Core/IOS/DI/DI.h
Expand Up @@ -35,10 +35,10 @@ void Init();

namespace IOS::HLE
{
class DIDevice : public Device
class DIDevice : public EmulationDevice
{
public:
DIDevice(Kernel& ios, const std::string& device_name);
DIDevice(EmulationKernel& ios, const std::string& device_name);

static void InterruptFromDVDInterface(DVD::DIInterruptType interrupt_type);
static DiscIO::Partition GetCurrentPartition();
Expand Down
41 changes: 17 additions & 24 deletions Source/Core/Core/IOS/Device.cpp
Expand Up @@ -16,17 +16,15 @@

namespace IOS::HLE
{
Request::Request(const u32 address_) : address(address_)
Request::Request(Core::System& system, const u32 address_) : address(address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
command = static_cast<IPCCommandType>(memory.Read_U32(address));
fd = memory.Read_U32(address + 8);
}

OpenRequest::OpenRequest(const u32 address_) : Request(address_)
OpenRequest::OpenRequest(Core::System& system, const u32 address_) : Request(system, address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
path = memory.GetString(memory.Read_U32(address + 0xc));
flags = static_cast<OpenMode>(memory.Read_U32(address + 0x10));
Expand All @@ -38,25 +36,23 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_)
}
}

ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_)
ReadWriteRequest::ReadWriteRequest(Core::System& system, const u32 address_)
: Request(system, address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
buffer = memory.Read_U32(address + 0xc);
size = memory.Read_U32(address + 0x10);
}

SeekRequest::SeekRequest(const u32 address_) : Request(address_)
SeekRequest::SeekRequest(Core::System& system, const u32 address_) : Request(system, address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
offset = memory.Read_U32(address + 0xc);
mode = static_cast<SeekMode>(memory.Read_U32(address + 0x10));
}

IOCtlRequest::IOCtlRequest(const u32 address_) : Request(address_)
IOCtlRequest::IOCtlRequest(Core::System& system, const u32 address_) : Request(system, address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request = memory.Read_U32(address + 0x0c);
buffer_in = memory.Read_U32(address + 0x10);
Expand All @@ -65,9 +61,8 @@ IOCtlRequest::IOCtlRequest(const u32 address_) : Request(address_)
buffer_out_size = memory.Read_U32(address + 0x1c);
}

IOCtlVRequest::IOCtlVRequest(const u32 address_) : Request(address_)
IOCtlVRequest::IOCtlVRequest(Core::System& system, const u32 address_) : Request(system, address_)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request = memory.Read_U32(address + 0x0c);
const u32 in_number = memory.Read_U32(address + 0x10);
Expand Down Expand Up @@ -114,10 +109,9 @@ void IOCtlRequest::Log(std::string_view device_name, Common::Log::LogType type,
device_name, fd, request, buffer_in_size, buffer_out_size);
}

void IOCtlRequest::Dump(const std::string& description, Common::Log::LogType type,
Common::Log::LogLevel level) const
void IOCtlRequest::Dump(Core::System& system, const std::string& description,
Common::Log::LogType type, Common::Log::LogLevel level) const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

Log("===== " + description, type, level);
Expand All @@ -127,16 +121,15 @@ void IOCtlRequest::Dump(const std::string& description, Common::Log::LogType typ
HexDump(memory.GetPointer(buffer_out), buffer_out_size));
}

void IOCtlRequest::DumpUnknown(const std::string& description, Common::Log::LogType type,
Common::Log::LogLevel level) const
void IOCtlRequest::DumpUnknown(Core::System& system, const std::string& description,
Common::Log::LogType type, Common::Log::LogLevel level) const
{
Dump("Unknown IOCtl - " + description, type, level);
Dump(system, "Unknown IOCtl - " + description, type, level);
}

void IOCtlVRequest::Dump(std::string_view description, Common::Log::LogType type,
Common::Log::LogLevel level) const
void IOCtlVRequest::Dump(Core::System& system, std::string_view description,
Common::Log::LogType type, Common::Log::LogLevel level) const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

GENERIC_LOG_FMT(type, level, "===== {} (fd {}) - IOCtlV {:#x} ({} in, {} io)", description, fd,
Expand All @@ -154,10 +147,10 @@ void IOCtlVRequest::Dump(std::string_view description, Common::Log::LogType type
GENERIC_LOG_FMT(type, level, "io[{}] (size={:#x})", i++, vector.size);
}

void IOCtlVRequest::DumpUnknown(const std::string& description, Common::Log::LogType type,
Common::Log::LogLevel level) const
void IOCtlVRequest::DumpUnknown(Core::System& system, const std::string& description,
Common::Log::LogType type, Common::Log::LogLevel level) const
{
Dump("Unknown IOCtlV - " + description, type, level);
Dump(system, "Unknown IOCtlV - " + description, type, level);
}

Device::Device(Kernel& ios, const std::string& device_name, const DeviceType type)
Expand Down
45 changes: 35 additions & 10 deletions Source/Core/Core/IOS/Device.h
Expand Up @@ -13,6 +13,11 @@
#include "Common/Logging/Log.h"
#include "Core/IOS/IOS.h"

namespace Core
{
class System;
}

namespace IOS::HLE
{
enum ReturnCode : s32
Expand Down Expand Up @@ -77,7 +82,7 @@ struct Request
u32 address = 0;
IPCCommandType command = IPC_CMD_OPEN;
u32 fd = 0;
explicit Request(u32 address);
Request(Core::System& system, u32 address);
virtual ~Request() = default;
};

Expand All @@ -97,14 +102,14 @@ struct OpenRequest final : Request
// but they are set after they reach IOS and are dispatched to the appropriate module.
u32 uid = 0;
u16 gid = 0;
explicit OpenRequest(u32 address);
OpenRequest(Core::System& system, u32 address);
};

struct ReadWriteRequest final : Request
{
u32 buffer = 0;
u32 size = 0;
explicit ReadWriteRequest(u32 address);
ReadWriteRequest(Core::System& system, u32 address);
};

enum SeekMode : s32
Expand All @@ -118,7 +123,7 @@ struct SeekRequest final : Request
{
u32 offset = 0;
SeekMode mode = IOS_SEEK_SET;
explicit SeekRequest(u32 address);
SeekRequest(Core::System& system, u32 address);
};

struct IOCtlRequest final : Request
Expand All @@ -129,12 +134,13 @@ struct IOCtlRequest final : Request
// Contrary to the name, the output buffer can also be used for input.
u32 buffer_out = 0;
u32 buffer_out_size = 0;
explicit IOCtlRequest(u32 address);
IOCtlRequest(Core::System& system, u32 address);
void Log(std::string_view description, Common::Log::LogType type = Common::Log::LogType::IOS,
Common::Log::LogLevel level = Common::Log::LogLevel::LINFO) const;
void Dump(const std::string& description, Common::Log::LogType type = Common::Log::LogType::IOS,
void Dump(Core::System& system, const std::string& description,
Common::Log::LogType type = Common::Log::LogType::IOS,
Common::Log::LogLevel level = Common::Log::LogLevel::LINFO) const;
void DumpUnknown(const std::string& description,
void DumpUnknown(Core::System& system, const std::string& description,
Common::Log::LogType type = Common::Log::LogType::IOS,
Common::Log::LogLevel level = Common::Log::LogLevel::LERROR) const;
};
Expand All @@ -159,11 +165,12 @@ struct IOCtlVRequest final : Request
/// Returns the specified vector or nullptr if the index is out of bounds.
const IOVector* GetVector(size_t index) const;

explicit IOCtlVRequest(u32 address);
IOCtlVRequest(Core::System& system, u32 address);
bool HasNumberOfValidVectors(size_t in_count, size_t io_count) const;
void Dump(std::string_view description, Common::Log::LogType type = Common::Log::LogType::IOS,
void Dump(Core::System& system, std::string_view description,
Common::Log::LogType type = Common::Log::LogType::IOS,
Common::Log::LogLevel level = Common::Log::LogLevel::LINFO) const;
void DumpUnknown(const std::string& description,
void DumpUnknown(Core::System& system, const std::string& description,
Common::Log::LogType type = Common::Log::LogType::IOS,
Common::Log::LogLevel level = Common::Log::LogLevel::LERROR) const;
};
Expand Down Expand Up @@ -214,4 +221,22 @@ class Device
private:
std::optional<IPCReply> Unsupported(const Request& request);
};

// Helper class for Devices that we know are only ever instantiated under an EmulationKernel.
// Deriving a Device from this allows it to access EmulationKernel-only features without runtime
// overhead, since it will know that the m_ios instance is an EmulationKernel.
class EmulationDevice : public Device
{
public:
EmulationDevice(EmulationKernel& ios, const std::string& device_name,
DeviceType type = DeviceType::Static)
: Device(ios, device_name, type)
{
}

protected:
EmulationKernel& GetEmulationKernel() const { return static_cast<EmulationKernel&>(m_ios); }

Core::System& GetSystem() const { return GetEmulationKernel().GetSystem(); }
};
} // namespace IOS::HLE

0 comments on commit 89154c8

Please sign in to comment.