Merge pull request #5340 from leoetlino/ios-reorg

IOS: Convert the IOS kernel HLE code to a class
This commit is contained in:
Léo Lam 2017-04-30 18:03:33 +02:00 committed by GitHub
commit 8e2028e8da
88 changed files with 1477 additions and 1428 deletions

View File

@ -27,7 +27,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/VideoInterface.h"
#include "Core/Host.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCSymbolDB.h"

View File

@ -23,7 +23,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
@ -289,7 +289,7 @@ bool CBoot::SetupWiiMemory(u64 ios_title_id)
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
if (!IOS::HLE::Reload(ios_title_id))
if (!IOS::HLE::GetIOS()->BootIOS(ios_title_id))
{
return false;
}

View File

@ -16,7 +16,7 @@
#include "Core/Boot/Boot.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "DiscIO/NANDContentLoader.h"
@ -88,7 +88,7 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
return false;
IOS::HLE::Device::ES::LoadWAD(_pFilename);
if (!IOS::HLE::BootstrapPPC(ContentLoader))
if (!IOS::HLE::GetIOS()->BootstrapPPC(ContentLoader))
return false;
return true;

View File

@ -147,7 +147,8 @@ set(SRCS
HW/WiiSaveCrypted.cpp
IOS/Device.cpp
IOS/DeviceStub.cpp
IOS/IPC.cpp
IOS/IOS.cpp
IOS/MemoryValues.cpp
IOS/MIOS.cpp
IOS/DI/DI.cpp
IOS/ES/ES.cpp

View File

@ -50,7 +50,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/NetPlayClient.h"
#include "Core/NetPlayProto.h"
@ -952,7 +952,9 @@ void UpdateWantDeterminism(bool initial)
bool was_unpaused = Core::PauseAndLock(true);
s_wants_determinism = new_want_determinism;
IOS::HLE::UpdateWantDeterminism(new_want_determinism);
const auto ios = IOS::HLE::GetIOS();
if (ios)
ios->UpdateWantDeterminism(new_want_determinism);
Fifo::UpdateWantDeterminism(new_want_determinism);
// We need to clear the cache because some parts of the JIT depend on want_determinism, e.g. use
// of FMA.

View File

@ -174,7 +174,8 @@
<ClCompile Include="HW\WiiSaveCrypted.cpp" />
<ClCompile Include="IOS\Device.cpp" />
<ClCompile Include="IOS\DeviceStub.cpp" />
<ClCompile Include="IOS\IPC.cpp" />
<ClCompile Include="IOS\IOS.cpp" />
<ClCompile Include="IOS\MemoryValues.cpp" />
<ClCompile Include="IOS\MIOS.cpp" />
<ClCompile Include="IOS\DI\DI.cpp" />
<ClCompile Include="IOS\ES\ES.cpp" />
@ -431,7 +432,8 @@
<ClInclude Include="HW\WII_IPC.h" />
<ClInclude Include="IOS\Device.h" />
<ClInclude Include="IOS\DeviceStub.h" />
<ClInclude Include="IOS\IPC.h" />
<ClInclude Include="IOS\IOS.h" />
<ClInclude Include="IOS\MemoryValues.h" />
<ClInclude Include="IOS\MIOS.h" />
<ClInclude Include="IOS\DI\DI.h" />
<ClInclude Include="IOS\ES\ES.h" />

View File

@ -790,7 +790,10 @@
<ClCompile Include="IOS\Network\ICMPLin.cpp">
<Filter>IOS\Network</Filter>
</ClCompile>
<ClCompile Include="IOS\IPC.cpp">
<ClCompile Include="IOS\IOS.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MemoryValues.cpp">
<Filter>IOS</Filter>
</ClCompile>
<ClCompile Include="IOS\MIOS.cpp">
@ -1504,7 +1507,10 @@
<ClInclude Include="IOS\Device.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\IPC.h">
<ClInclude Include="IOS\IOS.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MemoryValues.h">
<Filter>IOS</Filter>
</ClInclude>
<ClInclude Include="IOS\MIOS.h">

View File

@ -28,7 +28,7 @@
#include "Core/HW/StreamADPCM.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "DiscIO/Enums.h"
@ -1136,7 +1136,7 @@ void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type
case ReplyType::IOS:
{
auto di = IOS::HLE::GetDeviceByName("/dev/di");
auto di = IOS::HLE::GetIOS()->GetDeviceByName("/dev/di");
if (di)
std::static_pointer_cast<IOS::HLE::Device::DI>(di)->FinishIOCtl(interrupt_type);
break;

View File

@ -21,7 +21,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/Movie.h"
#include "Core/State.h"
#include "Core/WiiRoot.h"
@ -102,7 +102,7 @@ void DoState(PointerWrap& p)
{
IOS::DoState(p);
p.DoMarker("IOS");
IOS::HLE::DoState(p);
IOS::HLE::GetIOS()->DoState(p);
p.DoMarker("IOS::HLE");
}

View File

@ -11,7 +11,7 @@
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/PowerPC/PowerPC.h"
@ -210,22 +210,24 @@ static void ToggleResetButtonCallback(u64 userdata, s64 cyclesLate)
static void IOSNotifyResetButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->ResetButton();
}
static void IOSNotifyPowerButtonCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (stm)
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->PowerButton();
}
void ResetButton_Tap()

View File

@ -57,7 +57,7 @@ IPC_HLE_PERIOD: For the Wii Remote this is the call schedule:
#include "Core/HW/DSP.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/VideoInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/PowerPC.h"
#include "VideoCommon/Fifo.h"
@ -112,7 +112,7 @@ static void IPC_HLE_UpdateCallback(u64 userdata, s64 cyclesLate)
{
if (SConfig::GetInstance().bWii)
{
IOS::HLE::UpdateDevices();
IOS::HLE::GetIOS()->UpdateDevices();
CoreTiming::ScheduleEvent(s_ipc_hle_period - cyclesLate, et_IPC_HLE);
}
}

View File

@ -9,7 +9,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
// This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because
// of the IOS HLE
@ -153,8 +153,8 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ctrl.ppc(val);
if (ctrl.X1)
HLE::EnqueueRequest(ppc_msg);
HLE::Update();
HLE::GetIOS()->EnqueueIPCRequest(ppc_msg);
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@ -163,7 +163,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](u32, u32 val) {
ppc_irq_flags &= ~val;
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));
@ -172,7 +172,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
ppc_irq_masks = val;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset();
HLE::Update();
HLE::GetIOS()->UpdateIPC();
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
}));

View File

@ -24,7 +24,7 @@ namespace HLE
{
namespace Device
{
DI::DI(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
DI::DI(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
@ -76,7 +76,7 @@ void DI::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
// This command has been executed, so it's removed from the queue
u32 command_address = m_commands_to_execute.front();
m_commands_to_execute.pop_front();
EnqueueReply(IOCtlRequest{command_address}, interrupt_type);
m_ios.EnqueueIPCReply(IOCtlRequest{command_address}, interrupt_type);
// DVDInterface is now ready to execute another command,
// so we start executing a command from the queue if there is one

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -27,7 +27,7 @@ namespace Device
class DI : public Device
{
public:
DI(u32 device_id, const std::string& device_name);
DI(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -10,7 +10,7 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -26,8 +26,12 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_)
{
path = Memory::GetString(Memory::Read_U32(address + 0xc));
flags = static_cast<OpenMode>(Memory::Read_U32(address + 0x10));
uid = GetUIDForPPC();
gid = GetGIDForPPC();
const Kernel* ios = GetIOS();
if (ios)
{
uid = ios->GetUidForPPC();
gid = ios->GetGidForPPC();
}
}
ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_)
@ -129,8 +133,8 @@ void IOCtlVRequest::DumpUnknown(const std::string& description, LogTypes::LOG_TY
namespace Device
{
Device::Device(const u32 device_id, const std::string& device_name, const DeviceType type)
: m_name(device_name), m_device_id(device_id), m_device_type(type)
Device::Device(Kernel& ios, const std::string& device_name, const DeviceType type)
: m_ios(ios), m_name(device_name), m_device_type(type)
{
}
@ -143,7 +147,6 @@ void Device::DoState(PointerWrap& p)
void Device::DoStateShared(PointerWrap& p)
{
p.Do(m_name);
p.Do(m_device_id);
p.Do(m_device_type);
p.Do(m_is_active);
}

View File

@ -11,7 +11,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -172,7 +172,7 @@ public:
OH0, // OH0 child devices which are created dynamically.
};
Device(u32 device_id, const std::string& device_name, DeviceType type = DeviceType::Static);
Device(Kernel& ios, const std::string& device_name, DeviceType type = DeviceType::Static);
virtual ~Device() = default;
// Release any resources which might interfere with savestating.
@ -181,7 +181,6 @@ public:
void DoStateShared(PointerWrap& p);
const std::string& GetDeviceName() const { return m_name; }
u32 GetDeviceID() const { return m_device_id; }
// Replies to Open and Close requests are sent by the IPC request handler (HandleCommand),
// not by the devices themselves.
virtual ReturnCode Open(const OpenRequest& request);
@ -199,9 +198,10 @@ public:
static IPCCommandResult GetNoReply();
protected:
Kernel& m_ios;
std::string m_name;
// STATE_TO_SAVE
u32 m_device_id;
DeviceType m_device_type;
bool m_is_active = false;

View File

@ -11,10 +11,6 @@ namespace HLE
{
namespace Device
{
Stub::Stub(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
{
}
ReturnCode Stub::Open(const OpenRequest& request)
{
WARN_LOG(IOS, "%s faking Open()", m_name.c_str());

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -19,8 +19,8 @@ namespace Device
class Stub final : public Device
{
public:
Stub(u32 device_id, const std::string& device_name);
// Inherit the constructor from the Device class, since we don't need to do anything special.
using Device::Device;
ReturnCode Open(const OpenRequest& request) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -55,7 +55,7 @@ static void FinishAllStaleImports()
File::CreateDir(import_dir);
}
ES::ES(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
ES::ES(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
FinishAllStaleImports();
@ -155,7 +155,7 @@ IPCCommandResult ES::GetTitleID(const IOCtlVRequest& request)
return GetDefaultReply(IPC_SUCCESS);
}
static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
static bool UpdateUIDAndGID(Kernel& kernel, const IOS::ES::TMDReader& tmd)
{
IOS::ES::UIDSys uid_sys{Common::FromWhichRoot::FROM_SESSION_ROOT};
const u64 title_id = tmd.GetTitleId();
@ -165,8 +165,8 @@ static bool UpdateUIDAndGID(const IOS::ES::TMDReader& tmd)
ERROR_LOG(IOS_ES, "Failed to get UID for title %016" PRIx64, title_id);
return false;
}
SetUIDForPPC(uid);
SetGIDForPPC(tmd.GetGroupId());
kernel.SetUidForPPC(uid);
kernel.SetGidForPPC(tmd.GetGroupId());
return true;
}
@ -197,7 +197,7 @@ IPCCommandResult ES::SetUID(u32 uid, const IOCtlVRequest& request)
if (!tmd.IsValid())
return GetDefaultReply(FS_ENOENT);
if (!UpdateUIDAndGID(tmd))
if (!UpdateUIDAndGID(m_ios, tmd))
{
ERROR_LOG(IOS_ES, "SetUID: Failed to get UID for title %016" PRIx64, title_id);
return GetDefaultReply(ES_SHORT_READ);
@ -225,7 +225,7 @@ bool ES::LaunchTitle(u64 title_id, bool skip_reload)
bool ES::LaunchIOS(u64 ios_title_id)
{
return Reload(ios_title_id);
return m_ios.BootIOS(ios_title_id);
}
bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
@ -266,14 +266,14 @@ bool ES::LaunchPPCTitle(u64 title_id, bool skip_reload)
// Note: the UID/GID is also updated for IOS titles, but since we have no guarantee IOS titles
// are installed, we can only do this for PPC titles.
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(m_ios, s_title_context.tmd))
{
s_title_context.Clear();
INFO_LOG(IOS_ES, "LaunchPPCTitle: Title context changed: (none)");
return false;
}
return BootstrapPPC(content_loader);
return m_ios.BootstrapPPC(content_loader);
}
void ES::Context::DoState(PointerWrap& p)
@ -555,11 +555,9 @@ IPCCommandResult ES::Launch(const IOCtlVRequest& request)
if (!LaunchTitle(TitleID))
return GetDefaultReply(FS_ENOENT);
// Generate a "reply" to the IPC command. ES_LAUNCH is unique because it
// involves restarting IOS; IOS generates two acknowledgements in a row.
// Note: If the launch succeeded, we should not write anything to the command buffer as
// IOS does not even reply unless it failed.
EnqueueCommandAcknowledgement(request.address, 0);
// ES_LAUNCH involves restarting IOS, which results in two acknowledgements in a row
// (one from the previous IOS for this IPC request, and one from the new one as it boots).
// Nothing should be written to the command buffer if the launch succeeded for obvious reasons.
return GetNoReply();
}
@ -570,13 +568,12 @@ IPCCommandResult ES::LaunchBC(const IOCtlVRequest& request)
// Here, IOS checks the clock speed and prevents ioctlv 0x25 from being used in GC mode.
// An alternative way to do this is to check whether the current active IOS is MIOS.
if (GetVersion() == 0x101)
if (m_ios.GetVersion() == 0x101)
return GetDefaultReply(ES_EINVAL);
if (!LaunchTitle(0x0000000100000100))
return GetDefaultReply(FS_ENOENT);
EnqueueCommandAcknowledgement(request.address, 0);
return GetNoReply();
}
@ -633,7 +630,7 @@ s32 ES::DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& tic
// clear the cache to avoid content access mismatches.
DiscIO::CNANDContentManager::Access().ClearCache();
if (!UpdateUIDAndGID(s_title_context.tmd))
if (!UpdateUIDAndGID(*GetIOS(), s_title_context.tmd))
{
return ES_SHORT_READ;
}

View File

@ -12,7 +12,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -43,11 +43,11 @@ struct TitleContext
class ES final : public Device
{
public:
ES(u32 device_id, const std::string& device_name);
ES(Kernel& ios, const std::string& device_name);
static s32 DIVerify(const IOS::ES::TMDReader& tmd, const IOS::ES::TicketReader& ticket);
static void LoadWAD(const std::string& _rContentFile);
static bool LaunchTitle(u64 title_id, bool skip_reload = false);
bool LaunchTitle(u64 title_id, bool skip_reload = false);
// Internal implementation of the ES_DECRYPT ioctlv.
static void DecryptContent(u32 key_index, u8* iv, u8* input, u32 size, u8* new_iv, u8* output);
@ -265,8 +265,8 @@ private:
ContextArray::iterator FindActiveContext(u32 fd);
ContextArray::iterator FindInactiveContext();
static bool LaunchIOS(u64 ios_title_id);
static bool LaunchPPCTitle(u64 title_id, bool skip_reload);
bool LaunchIOS(u64 ios_title_id);
bool LaunchPPCTitle(u64 title_id, bool skip_reload);
static TitleContext& GetTitleContext();
static const DiscIO::CNANDContentLoader& AccessContentDevice(u64 title_id);

View File

@ -33,7 +33,7 @@ static bool IsValidWiiPath(const std::string& path)
namespace Device
{
FS::FS(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
FS::FS(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
const std::string tmp_dir = BuildFilename("/tmp");
File::DeleteDirRecursively(tmp_dir);

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -32,7 +32,7 @@ namespace Device
class FS : public Device
{
public:
FS(u32 device_id, const std::string& device_name);
FS(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -15,7 +15,7 @@
#include "Common/NandPaths.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -71,14 +71,14 @@ void CreateVirtualFATFilesystem()
namespace Device
{
FileIO::FileIO(u32 device_id, const std::string& device_name)
: Device(device_id, device_name, DeviceType::FileIO)
FileIO::FileIO(Kernel& ios, const std::string& device_name)
: Device(ios, device_name, DeviceType::FileIO)
{
}
ReturnCode FileIO::Close(u32 fd)
{
INFO_LOG(IOS_FILEIO, "FileIO: Close %s (DeviceID=%08x)", m_name.c_str(), m_device_id);
INFO_LOG(IOS_FILEIO, "FileIO: Close %s", m_name.c_str());
m_Mode = 0;
// Let go of our pointer to the file, it will automatically close if we are the last handle

View File

@ -9,7 +9,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -30,7 +30,7 @@ namespace Device
class FileIO : public Device
{
public:
FileIO(u32 device_id, const std::string& device_name);
FileIO(Kernel& ios, const std::string& device_name);
ReturnCode Close(u32 fd) override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -0,0 +1,654 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IOS/IOS.h"
#include <algorithm>
#include <array>
#include <cinttypes>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include "Common/Assert.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/Boot/Boot_DOL.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/DI/DI.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/DeviceStub.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/FS/FS.h"
#include "Core/IOS/FS/FileIO.h"
#include "Core/IOS/MIOS.h"
#include "Core/IOS/MemoryValues.h"
#include "Core/IOS/Network/IP/Top.h"
#include "Core/IOS/Network/KD/NetKDRequest.h"
#include "Core/IOS/Network/KD/NetKDTime.h"
#include "Core/IOS/Network/NCD/Manage.h"
#include "Core/IOS/Network/SSL.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/IOS/Network/WD/Command.h"
#include "Core/IOS/SDIO/SDIOSlot0.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/BTReal.h"
#include "Core/IOS/USB/OH0/OH0.h"
#include "Core/IOS/USB/OH0/OH0Device.h"
#include "Core/IOS/USB/USB_HID/HIDv4.h"
#include "Core/IOS/USB/USB_KBD.h"
#include "Core/IOS/USB/USB_VEN/VEN.h"
#include "Core/IOS/WFS/WFSI.h"
#include "Core/IOS/WFS/WFSSRV.h"
#include "Core/PowerPC/PowerPC.h"
#include "DiscIO/NANDContentLoader.h"
namespace IOS
{
namespace HLE
{
static std::unique_ptr<Kernel> s_ios;
constexpr u64 ENQUEUE_REQUEST_FLAG = 0x100000000ULL;
constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
static CoreTiming::EventType* s_event_enqueue;
static CoreTiming::EventType* s_event_sdio_notify;
constexpr u32 ADDR_MEM1_SIZE = 0x3100;
constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104;
constexpr u32 ADDR_MEM1_END = 0x3108;
constexpr u32 ADDR_MEM1_ARENA_BEGIN = 0x310c;
constexpr u32 ADDR_MEM1_ARENA_END = 0x3110;
constexpr u32 ADDR_PH1 = 0x3114;
constexpr u32 ADDR_MEM2_SIZE = 0x3118;
constexpr u32 ADDR_MEM2_SIM_SIZE = 0x311c;
constexpr u32 ADDR_MEM2_END = 0x3120;
constexpr u32 ADDR_MEM2_ARENA_BEGIN = 0x3124;
constexpr u32 ADDR_MEM2_ARENA_END = 0x3128;
constexpr u32 ADDR_PH2 = 0x312c;
constexpr u32 ADDR_IPC_BUFFER_BEGIN = 0x3130;
constexpr u32 ADDR_IPC_BUFFER_END = 0x3134;
constexpr u32 ADDR_HOLLYWOOD_REVISION = 0x3138;
constexpr u32 ADDR_PH3 = 0x313c;
constexpr u32 ADDR_IOS_VERSION = 0x3140;
constexpr u32 ADDR_IOS_DATE = 0x3144;
constexpr u32 ADDR_UNKNOWN_BEGIN = 0x3148;
constexpr u32 ADDR_UNKNOWN_END = 0x314c;
constexpr u32 ADDR_PH4 = 0x3150;
constexpr u32 ADDR_PH5 = 0x3154;
constexpr u32 ADDR_RAM_VENDOR = 0x3158;
constexpr u32 ADDR_BOOT_FLAG = 0x315c;
constexpr u32 ADDR_APPLOADER_FLAG = 0x315d;
constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e;
constexpr u32 ADDR_SYSMENU_SYNC = 0x3160;
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
enum class MemorySetupType
{
IOSReload,
Full,
};
static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
{
auto target_imv = std::find_if(
GetMemoryValues().begin(), GetMemoryValues().end(),
[&](const MemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); });
if (target_imv == GetMemoryValues().end())
{
ERROR_LOG(IOS, "Unknown IOS version: %016" PRIx64, ios_title_id);
return false;
}
if (setup_type == MemorySetupType::IOSReload)
{
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).
//
// This works in a slightly different way on a real console: older IOS versions (< IOS28) all
// have the same range (933E0000 - 93400000), thus they don't write it at boot and just inherit
// all values. However, the range has changed since IOS28. To make things work properly
// after a reload, newer IOSes always write the legacy range before loading an IOS kernel;
// 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->unknown_begin, ADDR_UNKNOWN_BEGIN);
Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_END);
return true;
}
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->unknown_begin, ADDR_UNKNOWN_BEGIN);
Memory::Write_U32(target_imv->unknown_end, ADDR_UNKNOWN_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);
return true;
}
// IOS used by the latest System Menu (4.3).
constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
constexpr u64 MIOS_TITLE_ID = 0x0000000100000101;
Kernel::Kernel(u64 title_id) : m_title_id(title_id)
{
INFO_LOG(IOS, "Starting IOS %016" PRIx64, title_id);
if (!SetupMemory(title_id, MemorySetupType::IOSReload))
WARN_LOG(IOS, "No information about this IOS -- cannot set up memory values");
if (title_id == MIOS_TITLE_ID)
{
MIOS::Load();
return;
}
// IOS re-inits IPC and sends a dummy ack during its boot process.
EnqueueIPCAcknowledgement(0);
AddStaticDevices();
}
Kernel::~Kernel()
{
CoreTiming::RemoveAllEvents(s_event_enqueue);
// Close all devices that were opened
for (auto& device : m_fdmap)
{
if (!device)
continue;
device->Close(0);
}
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
m_device_map.clear();
}
}
// The title ID is a u64 where the first 32 bits are used for the title type.
// For IOS title IDs, the type will always be 00000001 (system), and the lower 32 bits
// are used for the IOS major version -- which is what we want here.
u32 Kernel::GetVersion() const
{
return static_cast<u32>(m_title_id);
}
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
void Kernel::SetUidForPPC(u32 uid)
{
m_ppc_uid = uid;
}
u32 Kernel::GetUidForPPC() const
{
return m_ppc_uid;
}
void Kernel::SetGidForPPC(u16 gid)
{
m_ppc_gid = gid;
}
u16 Kernel::GetGidForPPC() const
{
return m_ppc_gid;
}
// This corresponds to syscall 0x41, which loads a binary from the NAND and bootstraps the PPC.
// Unlike 0x42, IOS will set up some constants in memory before booting the PPC.
bool Kernel::BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader)
{
if (!content_loader.IsValid())
return false;
const auto* content = content_loader.GetContentByIndex(content_loader.GetTMD().GetBootIndex());
if (!content)
return false;
const auto dol_loader = std::make_unique<CDolLoader>(content->m_Data->Get());
if (!dol_loader->IsValid())
return false;
if (!SetupMemory(m_title_id, MemorySetupType::Full))
return false;
dol_loader->Load();
// 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
// because the realmode code at 0x3400 initializes everything itself anyway.
MSR = 0;
PC = 0x3400;
return true;
}
// Similar to syscall 0x42 (ios_boot); this is used to change the current active IOS.
// IOS writes the new version to 0x3140 before restarting, but it does *not* poke any
// of the other constants to the memory. Warning: this resets the kernel instance.
bool Kernel::BootIOS(const u64 ios_title_id)
{
// A real Wii goes through several steps before getting to MIOS.
//
// * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game.
// * BC (similar to boot1) lowers the clock speed to the Flipper's and then launches boot2.
// * boot2 sees the lowered clock speed and launches MIOS (1-101) instead of the System Menu.
//
// Because we currently don't have boot1 and boot2, and BC is only ever used to launch MIOS
// (indirectly via boot2), we can just launch MIOS when BC is launched.
if (ios_title_id == BC_TITLE_ID)
{
NOTICE_LOG(IOS, "BC: Launching MIOS...");
return BootIOS(MIOS_TITLE_ID);
}
// Shut down the active IOS first before switching to the new one.
s_ios.reset();
s_ios = std::make_unique<Kernel>(ios_title_id);
return true;
}
void Kernel::AddDevice(std::unique_ptr<Device::Device> device)
{
_assert_(device->GetDeviceType() == Device::Device::DeviceType::Static);
m_device_map[device->GetDeviceName()] = std::move(device);
}
void Kernel::AddStaticDevices()
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
_assert_msg_(IOS, m_device_map.empty(), "Reinit called while already initialized");
if (!SConfig::GetInstance().m_bt_passthrough_enabled)
AddDevice(std::make_unique<Device::BluetoothEmu>(*this, "/dev/usb/oh1/57e/305"));
else
AddDevice(std::make_unique<Device::BluetoothReal>(*this, "/dev/usb/oh1/57e/305"));
AddDevice(std::make_unique<Device::STMImmediate>(*this, "/dev/stm/immediate"));
AddDevice(std::make_unique<Device::STMEventHook>(*this, "/dev/stm/eventhook"));
AddDevice(std::make_unique<Device::FS>(*this, "/dev/fs"));
AddDevice(std::make_unique<Device::ES>(*this, "/dev/es"));
AddDevice(std::make_unique<Device::DI>(*this, "/dev/di"));
AddDevice(std::make_unique<Device::NetKDRequest>(*this, "/dev/net/kd/request"));
AddDevice(std::make_unique<Device::NetKDTime>(*this, "/dev/net/kd/time"));
AddDevice(std::make_unique<Device::NetNCDManage>(*this, "/dev/net/ncd/manage"));
AddDevice(std::make_unique<Device::NetWDCommand>(*this, "/dev/net/wd/command"));
AddDevice(std::make_unique<Device::NetIPTop>(*this, "/dev/net/ip/top"));
AddDevice(std::make_unique<Device::NetSSL>(*this, "/dev/net/ssl"));
AddDevice(std::make_unique<Device::USB_KBD>(*this, "/dev/usb/kbd"));
AddDevice(std::make_unique<Device::SDIOSlot0>(*this, "/dev/sdio/slot0"));
AddDevice(std::make_unique<Device::Stub>(*this, "/dev/sdio/slot1"));
AddDevice(std::make_unique<Device::USB_HIDv4>(*this, "/dev/usb/hid"));
AddDevice(std::make_unique<Device::OH0>(*this, "/dev/usb/oh0"));
AddDevice(std::make_unique<Device::Stub>(*this, "/dev/usb/oh1"));
AddDevice(std::make_unique<Device::USB_VEN>(*this, "/dev/usb/ven"));
AddDevice(std::make_unique<Device::WFSSRV>(*this, "/dev/usb/wfssrv"));
AddDevice(std::make_unique<Device::WFSI>(*this, "/dev/wfsi"));
}
s32 Kernel::GetFreeDeviceID()
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
if (m_fdmap[i] == nullptr)
{
return i;
}
}
return -1;
}
std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& device_name)
{
std::lock_guard<std::mutex> lock(m_device_map_mutex);
const auto iterator = m_device_map.find(device_name);
return iterator != m_device_map.end() ? iterator->second : nullptr;
}
// Returns the FD for the newly opened device (on success) or an error code.
s32 Kernel::OpenDevice(OpenRequest& request)
{
const s32 new_fd = GetFreeDeviceID();
INFO_LOG(IOS, "Opening %s (mode %d, fd %d)", request.path.c_str(), request.flags, new_fd);
if (new_fd < 0 || new_fd >= IPC_MAX_FDS)
{
ERROR_LOG(IOS, "Couldn't get a free fd, too many open files");
return FS_EFDEXHAUSTED;
}
request.fd = new_fd;
std::shared_ptr<Device::Device> device;
if (request.path.find("/dev/usb/oh0/") == 0 && !GetDeviceByName(request.path))
{
device = std::make_shared<Device::OH0Device>(*this, request.path);
}
else if (request.path.find("/dev/") == 0)
{
device = GetDeviceByName(request.path);
}
else if (request.path.find('/') == 0)
{
device = std::make_shared<Device::FileIO>(*this, request.path);
}
if (!device)
{
ERROR_LOG(IOS, "Unknown device: %s", request.path.c_str());
return IPC_ENOENT;
}
const ReturnCode code = device->Open(request);
if (code < IPC_SUCCESS)
return code;
m_fdmap[new_fd] = device;
return new_fd;
}
IPCCommandResult Kernel::HandleIPCCommand(const Request& request)
{
if (request.command == IPC_CMD_OPEN)
{
OpenRequest open_request{request.address};
const s32 new_fd = OpenDevice(open_request);
return Device::Device::GetDefaultReply(new_fd);
}
const auto device = (request.fd < IPC_MAX_FDS) ? m_fdmap[request.fd] : nullptr;
if (!device)
return Device::Device::GetDefaultReply(IPC_EINVAL);
switch (request.command)
{
case IPC_CMD_CLOSE:
m_fdmap[request.fd].reset();
return Device::Device::GetDefaultReply(device->Close(request.fd));
case IPC_CMD_READ:
return device->Read(ReadWriteRequest{request.address});
case IPC_CMD_WRITE:
return device->Write(ReadWriteRequest{request.address});
case IPC_CMD_SEEK:
return device->Seek(SeekRequest{request.address});
case IPC_CMD_IOCTL:
return device->IOCtl(IOCtlRequest{request.address});
case IPC_CMD_IOCTLV:
return device->IOCtlV(IOCtlVRequest{request.address});
default:
_assert_msg_(IOS, false, "Unexpected command: %x", request.command);
return Device::Device::GetDefaultReply(IPC_EINVAL);
}
}
void Kernel::ExecuteIPCCommand(const u32 address)
{
Request request{address};
IPCCommandResult result = HandleIPCCommand(request);
if (!result.send_reply)
return;
// Ensure replies happen in order
const s64 ticks_until_last_reply = m_last_reply_time - CoreTiming::GetTicks();
if (ticks_until_last_reply > 0)
result.reply_delay_ticks += ticks_until_last_reply;
m_last_reply_time = CoreTiming::GetTicks() + result.reply_delay_ticks;
EnqueueIPCReply(request, result.return_value, static_cast<int>(result.reply_delay_ticks));
}
// Happens AS SOON AS IPC gets a new pointer!
void Kernel::EnqueueIPCRequest(u32 address)
{
CoreTiming::ScheduleEvent(1000, s_event_enqueue, address | ENQUEUE_REQUEST_FLAG);
}
// Called to send a reply to an IOS syscall
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, int cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
// IOS writes back the command that was responded to in the FD field.
Memory::Write_U32(request.command, request.address + 8);
// IOS also overwrites the command type with the reply type.
Memory::Write_U32(IPC_REPLY, request.address);
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
}
void Kernel::EnqueueIPCAcknowledgement(u32 address, int cycles_in_future)
{
CoreTiming::ScheduleEvent(cycles_in_future, s_event_enqueue,
address | ENQUEUE_ACKNOWLEDGEMENT_FLAG);
}
void Kernel::HandleIPCEvent(u64 userdata)
{
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
m_ack_queue.push_back(static_cast<u32>(userdata));
else if (userdata & ENQUEUE_REQUEST_FLAG)
m_request_queue.push_back(static_cast<u32>(userdata));
else
m_reply_queue.push_back(static_cast<u32>(userdata));
UpdateIPC();
}
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
// Takes care of routing ipc <-> ipc HLE
void Kernel::UpdateIPC()
{
if (!IsReady())
return;
if (m_request_queue.size())
{
GenerateAck(m_request_queue.front());
u32 command = m_request_queue.front();
m_request_queue.pop_front();
ExecuteIPCCommand(command);
return;
}
if (m_reply_queue.size())
{
GenerateReply(m_reply_queue.front());
DEBUG_LOG(IOS, "<<-- Reply to IPC Request @ 0x%08x", m_reply_queue.front());
m_reply_queue.pop_front();
return;
}
if (m_ack_queue.size())
{
GenerateAck(m_ack_queue.front());
WARN_LOG(IOS, "<<-- Double-ack to IPC Request @ 0x%08x", m_ack_queue.front());
m_ack_queue.pop_front();
return;
}
}
void Kernel::UpdateDevices()
{
// Check if a hardware device must be updated
for (const auto& entry : m_device_map)
{
if (entry.second->IsOpened())
{
entry.second->Update();
}
}
}
void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
{
WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism);
for (const auto& device : m_device_map)
device.second->UpdateWantDeterminism(new_want_determinism);
}
void Kernel::SDIO_EventNotify()
{
// TODO: Potential race condition: If IsRunning() becomes false after
// it's checked, an event may be scheduled after CoreTiming shuts down.
if (SConfig::GetInstance().bWii && Core::IsRunning())
CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
}
void Kernel::DoState(PointerWrap& p)
{
p.Do(m_request_queue);
p.Do(m_reply_queue);
p.Do(m_last_reply_time);
p.Do(m_title_id);
p.Do(m_ppc_uid);
p.Do(m_ppc_gid);
if (m_title_id == MIOS_TITLE_ID)
return;
// We need to make sure all file handles are closed so IOS::HLE::Device::FS::DoState can
// successfully save or re-create /tmp
for (auto& descriptor : m_fdmap)
{
if (descriptor)
descriptor->PrepareForState(p.GetMode());
}
for (const auto& entry : m_device_map)
entry.second->DoState(p);
if (p.GetMode() == PointerWrap::MODE_READ)
{
for (u32 i = 0; i < IPC_MAX_FDS; i++)
{
u32 exists = 0;
p.Do(exists);
if (exists)
{
auto device_type = Device::Device::DeviceType::Static;
p.Do(device_type);
switch (device_type)
{
case Device::Device::DeviceType::Static:
{
std::string device_name;
p.Do(device_name);
m_fdmap[i] = GetDeviceByName(device_name);
break;
}
case Device::Device::DeviceType::FileIO:
m_fdmap[i] = std::make_shared<Device::FileIO>(*this, "");
m_fdmap[i]->DoState(p);
break;
case Device::Device::DeviceType::OH0:
m_fdmap[i] = std::make_shared<Device::OH0Device>(*this, "");
m_fdmap[i]->DoState(p);
break;
}
}
}
}
else
{
for (auto& descriptor : m_fdmap)
{
u32 exists = descriptor ? 1 : 0;
p.Do(exists);
if (exists)
{
auto device_type = descriptor->GetDeviceType();
p.Do(device_type);
if (device_type == Device::Device::DeviceType::Static)
{
std::string device_name = descriptor->GetDeviceName();
p.Do(device_name);
}
else
{
descriptor->DoState(p);
}
}
}
}
}
void Init()
{
s_event_enqueue = CoreTiming::RegisterEvent("IPCEvent", [](u64 userdata, s64) {
if (s_ios)
s_ios->HandleIPCEvent(userdata);
});
s_event_sdio_notify = CoreTiming::RegisterEvent("SDIO_EventNotify", [](u64, s64) {
if (!s_ios)
return;
auto device = static_cast<Device::SDIOSlot0*>(s_ios->GetDeviceByName("/dev/sdio/slot0").get());
if (device)
device->EventNotify();
});
// Start with IOS80 to simulate part of the Wii boot process.
s_ios = std::make_unique<Kernel>(IOS80_TITLE_ID);
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
// (which bootstraps the PPC). Bootstrapping the PPC results in memory values being set up.
// This means that the constants in the 0x3100 region are always set up by the time
// a game is launched. This is necessary because booting games from the game list skips
// a significant part of a Wii's boot process.
SetupMemory(IOS80_TITLE_ID, MemorySetupType::Full);
}
void Shutdown()
{
s_ios.reset();
}
Kernel* GetIOS()
{
return s_ios.get();
}
} // namespace HLE
} // namespace IOS

120
Source/Core/Core/IOS/IOS.h Normal file
View File

@ -0,0 +1,120 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/CoreTiming.h"
#include "Core/HW/SystemTimers.h"
class PointerWrap;
namespace DiscIO
{
class CNANDContentLoader;
}
namespace IOS
{
namespace HLE
{
namespace Device
{
class Device;
}
struct Request;
struct OpenRequest;
struct IPCCommandResult
{
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
enum IPCCommandType : u32
{
IPC_CMD_OPEN = 1,
IPC_CMD_CLOSE = 2,
IPC_CMD_READ = 3,
IPC_CMD_WRITE = 4,
IPC_CMD_SEEK = 5,
IPC_CMD_IOCTL = 6,
IPC_CMD_IOCTLV = 7,
// This is used for replies to commands.
IPC_REPLY = 8,
};
// HLE for the IOS kernel: IPC, device management, syscalls, and Dolphin-specific, IOS-wide calls.
class Kernel
{
public:
explicit Kernel(u64 ios_title_id);
~Kernel();
void DoState(PointerWrap& p);
void HandleIPCEvent(u64 userdata);
void UpdateIPC();
void UpdateDevices();
void UpdateWantDeterminism(bool new_want_determinism);
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
void SDIO_EventNotify();
void EnqueueIPCRequest(u32 address);
void EnqueueIPCReply(const Request& request, s32 return_value, int cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void SetUidForPPC(u32 uid);
u32 GetUidForPPC() const;
void SetGidForPPC(u16 gid);
u16 GetGidForPPC() const;
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader);
bool BootIOS(u64 ios_title_id);
u32 GetVersion() const;
private:
void ExecuteIPCCommand(u32 address);
IPCCommandResult HandleIPCCommand(const Request& request);
void EnqueueIPCAcknowledgement(u32 address, int cycles_in_future = 0);
void AddDevice(std::unique_ptr<Device::Device> device);
void AddStaticDevices();
s32 GetFreeDeviceID();
s32 OpenDevice(OpenRequest& request);
u64 m_title_id = 0;
static constexpr u8 IPC_MAX_FDS = 0x18;
std::map<std::string, std::shared_ptr<Device::Device>> m_device_map;
std::mutex m_device_map_mutex;
// TODO: make this fdmap per process.
std::array<std::shared_ptr<Device::Device>, IPC_MAX_FDS> m_fdmap;
u32 m_ppc_uid = 0;
u16 m_ppc_gid = 0;
using IPCMsgQueue = std::deque<u32>;
IPCMsgQueue m_request_queue; // ppc -> arm
IPCMsgQueue m_reply_queue; // arm -> ppc
IPCMsgQueue m_ack_queue; // arm -> ppc
u64 m_last_reply_time = 0;
};
// Used for controlling and accessing an IOS instance that is tied to emulation.
void Init();
void Shutdown();
Kernel* GetIOS();
} // namespace HLE
} // namespace IOS

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/CoreTiming.h"
#include "Core/HW/SystemTimers.h"
class PointerWrap;
namespace DiscIO
{
class CNANDContentLoader;
}
namespace IOS
{
namespace HLE
{
namespace Device
{
class Device;
}
struct Request;
struct IPCCommandResult
{
s32 return_value;
bool send_reply;
u64 reply_delay_ticks;
};
enum IPCCommandType : u32
{
IPC_CMD_OPEN = 1,
IPC_CMD_CLOSE = 2,
IPC_CMD_READ = 3,
IPC_CMD_WRITE = 4,
IPC_CMD_SEEK = 5,
IPC_CMD_IOCTL = 6,
IPC_CMD_IOCTLV = 7,
// This is used for replies to commands.
IPC_REPLY = 8,
};
// Init events and devices
void Init();
// Shutdown
void Shutdown();
// Reload IOS (to a possibly different version); write the new version to 0x3140 and set up devices.
bool Reload(u64 ios_title_id);
u32 GetVersion();
void SetUIDForPPC(u32 uid);
u32 GetUIDForPPC();
void SetGIDForPPC(u16 gid);
u16 GetGIDForPPC();
bool BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader);
// Do State
void DoState(PointerWrap& p);
void SDIO_EventNotify();
std::shared_ptr<Device::Device> GetDeviceByName(const std::string& device_name);
std::shared_ptr<Device::Device> AccessDeviceByID(u32 id);
// Update
void Update();
// Update Devices
void UpdateDevices();
void UpdateWantDeterminism(bool new_want_determinism);
void ExecuteCommand(u32 address);
void EnqueueRequest(u32 address);
void EnqueueReply(const Request& request, s32 return_value, int cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
void EnqueueCommandAcknowledgement(u32 address, int cycles_in_future = 0);
} // namespace HLE
} // namespace IOS

View File

@ -0,0 +1,329 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/IOS/MemoryValues.h"
#include "Common/CommonTypes.h"
namespace IOS
{
namespace HLE
{
constexpr u32 MEM1_SIZE = 0x01800000;
constexpr u32 MEM1_END = 0x81800000;
constexpr u32 MEM1_ARENA_BEGIN = 0x00000000;
constexpr u32 MEM1_ARENA_END = 0x81800000;
constexpr u32 MEM2_SIZE = 0x4000000;
constexpr u32 MEM2_ARENA_BEGIN = 0x90000800;
constexpr u32 HOLLYWOOD_REVISION = 0x00000011;
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
constexpr u32 RAM_VENDOR = 0x0000FF01;
constexpr u32 RAM_VENDOR_MIOS = 0xCAFEBABE;
// These values were manually extracted from the relevant IOS binaries.
// The writes are usually contained in a single function that
// mostly writes raw literals to the relevant locations.
// e.g. IOS9, version 1034, content id 0x00000006, function at 0xffff6884
constexpr std::array<MemoryValues, 40> ios_memory_values = {
{{
9, 0x9040a, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
11, 0xb000a, 0x102506, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
12, 0xc020e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
13, 0xd0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
14, 0xe0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
15, 0xf0408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
17, 0x110408, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
20, 0x14000c, 0x102506, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
21, 0x15040f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
22, 0x16050e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93400000, MEM2_ARENA_BEGIN,
0x933E0000, 0x933E0000, 0x93400000, HOLLYWOOD_REVISION,
RAM_VENDOR, PLACEHOLDER, PLACEHOLDER, 0,
},
{
28, 0x1c070f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93800000, MEM2_ARENA_BEGIN,
0x937E0000, 0x937E0000, 0x93800000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93800000, 0x93820000, 0,
},
{
30, 0x1e0a10, 0x40308, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
31, 0x1f0e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
33, 0x210e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
34, 0x220e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
35, 0x230e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
36, 0x240e18, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
37, 0x25161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
38, 0x26101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
40, 0x280911, 0x022308, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
41, 0x290e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
43, 0x2b0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
45, 0x2d0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
46, 0x2e0e17, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
48, 0x30101c, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
50, 0x321319, 0x101008, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
51, 0x331219, 0x071108, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
52, 0x34161d, 0x101008, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
53, 0x35161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
55, 0x37161f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
56, 0x38161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
57, 0x39171f, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
58, 0x3a1820, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
59, 0x3b1c21, 0x101811, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
60, 0x3c181e, 0x112408, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
61, 0x3d161e, 0x030110, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
62, 0x3e191e, 0x022712, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
70, 0x461a1f, 0x060309, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
80, 0x501b20, 0x030310, MEM1_SIZE,
MEM1_SIZE, MEM1_END, MEM1_ARENA_BEGIN, MEM1_ARENA_END,
MEM2_SIZE, MEM2_SIZE, 0x93600000, MEM2_ARENA_BEGIN,
0x935E0000, 0x935E0000, 0x93600000, HOLLYWOOD_REVISION,
RAM_VENDOR, 0x93600000, 0x93620000, 0,
},
{
257,
0x707,
0x82209,
MEM1_SIZE,
MEM1_SIZE,
MEM1_END,
MEM1_ARENA_BEGIN,
MEM1_ARENA_END,
MEM2_SIZE,
MEM2_SIZE,
0x93600000,
MEM2_ARENA_BEGIN,
0x935E0000,
0x935E0000,
0x93600000,
HOLLYWOOD_REVISION,
RAM_VENDOR_MIOS,
PLACEHOLDER,
PLACEHOLDER,
PLACEHOLDER,
}}};
const std::array<MemoryValues, 40>& GetMemoryValues()
{
return ios_memory_values;
}
}
}

View File

@ -0,0 +1,41 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include "Common/CommonTypes.h"
namespace IOS
{
namespace HLE
{
struct MemoryValues
{
u16 ios_number;
u32 ios_version;
u32 ios_date;
u32 mem1_physical_size;
u32 mem1_simulated_size;
u32 mem1_end;
u32 mem1_arena_begin;
u32 mem1_arena_end;
u32 mem2_physical_size;
u32 mem2_simulated_size;
u32 mem2_end;
u32 mem2_arena_begin;
u32 mem2_arena_end;
u32 ipc_buffer_begin;
u32 ipc_buffer_end;
u32 hollywood_revision;
u32 ram_vendor;
u32 unknown_begin;
u32 unknown_end;
u32 sysmenu_sync;
};
const std::array<MemoryValues, 40>& GetMemoryValues();
}
}

View File

@ -61,7 +61,7 @@ namespace HLE
{
namespace Device
{
NetIPTop::NetIPTop(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetIPTop::NetIPTop(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
#ifdef _WIN32
int ret = WSAStartup(MAKEWORD(2, 2), &InitData);

View File

@ -61,7 +61,7 @@ namespace Device
class NetIPTop : public Device
{
public:
NetIPTop(u32 device_id, const std::string& device_name);
NetIPTop(Kernel& ios, const std::string& device_name);
virtual ~NetIPTop();
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -24,8 +24,7 @@ namespace HLE
{
namespace Device
{
NetKDRequest::NetKDRequest(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetKDRequest::NetKDRequest(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -22,7 +22,7 @@ namespace Device
class NetKDRequest : public Device
{
public:
NetKDRequest(u32 device_id, const std::string& device_name);
NetKDRequest(Kernel& ios, const std::string& device_name);
~NetKDRequest() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -16,7 +16,7 @@ namespace HLE
{
namespace Device
{
NetKDTime::NetKDTime(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetKDTime::NetKDTime(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -18,7 +18,7 @@ namespace Device
class NetKDTime : public Device
{
public:
NetKDTime(u32 device_id, const std::string& device_name);
NetKDTime(Kernel& ios, const std::string& device_name);
~NetKDTime() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -19,8 +19,7 @@ namespace HLE
{
namespace Device
{
NetNCDManage::NetNCDManage(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetNCDManage::NetNCDManage(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -20,7 +20,7 @@ namespace Device
class NetNCDManage : public Device
{
public:
NetNCDManage(u32 device_id, const std::string& device_name);
NetNCDManage(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -37,7 +37,7 @@ static constexpr mbedtls_x509_crt_profile mbedtls_x509_crt_profile_wii = {
0, /* No RSA min key size */
};
NetSSL::NetSSL(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
NetSSL::NetSSL(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
for (WII_SSL& ssl : _SSL)
{

View File

@ -19,7 +19,7 @@
// clang-format on
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Device.h"
namespace IOS
@ -90,7 +90,7 @@ namespace Device
class NetSSL : public Device
{
public:
NetSSL(u32 device_id, const std::string& device_name);
NetSSL(Kernel& ios, const std::string& device_name);
virtual ~NetSSL();

View File

@ -16,7 +16,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Network/Socket.h" // No Wii socket support while using NetPlay or TAS
#ifdef _WIN32
@ -579,7 +579,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock,
forceNonBlock);
EnqueueReply(it->request, ReturnValue);
// TODO: remove the dependency on a running IOS instance.
GetIOS()->EnqueueIPCReply(it->request, ReturnValue);
it = pending_sockops.erase(it);
}
else

View File

@ -52,7 +52,7 @@ typedef struct pollfd pollfd_t;
#include "Common/Logging/Log.h"
#include "Common/NonCopyable.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Network/IP/Top.h"
#include "Core/IOS/Network/SSL.h"
@ -234,7 +234,7 @@ public:
{
ERROR_LOG(IOS_NET, "DoSock: Error, fd not found (%08x, %08X, %08X)", sock, request.address,
type);
EnqueueReply(request, -SO_EBADF);
GetIOS()->EnqueueIPCReply(request, -SO_EBADF);
}
else
{

View File

@ -21,8 +21,7 @@ namespace HLE
{
namespace Device
{
NetWDCommand::NetWDCommand(u32 device_id, const std::string& device_name)
: Device(device_id, device_name)
NetWDCommand::NetWDCommand(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -18,7 +18,7 @@ namespace Device
class NetWDCommand : public Device
{
public:
NetWDCommand(u32 device_id, const std::string& device_name);
NetWDCommand(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;

View File

@ -14,7 +14,7 @@
#include "Common/SDCardUtil.h"
#include "Core/ConfigManager.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/SDIO/SDIOSlot0.h"
namespace IOS
@ -23,7 +23,7 @@ namespace HLE
{
namespace Device
{
SDIOSlot0::SDIOSlot0(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
SDIOSlot0::SDIOSlot0(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}
@ -49,7 +49,7 @@ void SDIOSlot0::EventNotify()
if ((SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_INSERT) ||
(!SConfig::GetInstance().m_WiiSDCard && m_event->type == EVENT_REMOVE))
{
EnqueueReply(m_event->request, m_event->type);
m_ios.EnqueueIPCReply(m_event->request, m_event->type);
m_event.reset();
}
}
@ -302,7 +302,7 @@ u32 SDIOSlot0::ExecuteCommand(const Request& request, u32 _BufferIn, u32 _Buffer
// release returns 0
// unknown sd int
// technically we do it out of order, oh well
EnqueueReply(m_event->request, EVENT_INVALID);
m_ios.EnqueueIPCReply(m_event->request, EVENT_INVALID);
m_event.reset();
break;
}

View File

@ -12,7 +12,7 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -26,7 +26,7 @@ namespace Device
class SDIOSlot0 : public Device
{
public:
SDIOSlot0(u32 device_id, const std::string& device_name);
SDIOSlot0(Kernel& ios, const std::string& device_name);
void DoState(PointerWrap& p) override;

View File

@ -39,7 +39,7 @@ IPCCommandResult STMImmediate::IOCtl(const IOCtlRequest& request)
break;
}
Memory::Write_U32(0, s_event_hook_request->buffer_out);
EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
break;
@ -109,7 +109,7 @@ void STMEventHook::TriggerEvent(const u32 event) const
return;
Memory::Write_U32(event, s_event_hook_request->buffer_out);
EnqueueReply(*s_event_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
}

View File

@ -8,7 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
@ -46,7 +46,7 @@ namespace Device
class STMImmediate final : public Device
{
public:
STMImmediate(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
};
@ -54,7 +54,7 @@ public:
class STMEventHook final : public Device
{
public:
STMEventHook(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
ReturnCode Close(u32 fd) override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
void DoState(PointerWrap& p) override;

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
class PointerWrap;
class SysConf;
@ -26,7 +26,7 @@ namespace Device
class BluetoothBase : public Device
{
public:
BluetoothBase(u32 device_id, const std::string& device_name) : Device(device_id, device_name) {}
using Device::Device;
virtual void UpdateSyncButtonState(bool is_held) {}
virtual void TriggerSyncButtonPressedEvent() {}
virtual void TriggerSyncButtonHeldEvent() {}

View File

@ -23,7 +23,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
@ -39,8 +39,8 @@ SQueuedEvent::SQueuedEvent(u32 size, u16 handle) : m_size(size), m_connectionHan
namespace Device
{
BluetoothEmu::BluetoothEmu(u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
BluetoothEmu::BluetoothEmu(Kernel& ios, const std::string& device_name)
: BluetoothBase(ios, device_name)
{
SysConf sysconf{Core::WantsDeterminism() ? Common::FromWhichRoot::FROM_SESSION_ROOT :
Common::FromWhichRoot::FROM_CONFIGURED_ROOT};
@ -105,14 +105,14 @@ BluetoothEmu::~BluetoothEmu()
}
template <typename T>
static void DoStateForMessage(PointerWrap& p, std::unique_ptr<T>& message)
static void DoStateForMessage(Kernel& ios, PointerWrap& p, std::unique_ptr<T>& message)
{
u32 request_address = (message != nullptr) ? message->ios_request.address : 0;
p.Do(request_address);
if (request_address != 0)
{
IOCtlVRequest request{request_address};
message = std::make_unique<T>(request);
message = std::make_unique<T>(ios, request);
}
}
@ -129,9 +129,9 @@ void BluetoothEmu::DoState(PointerWrap& p)
p.Do(m_is_active);
p.Do(m_ControllerBD);
DoStateForMessage(p, m_CtrlSetup);
DoStateForMessage(p, m_HCIEndpoint);
DoStateForMessage(p, m_ACLEndpoint);
DoStateForMessage(m_ios, p, m_CtrlSetup);
DoStateForMessage(m_ios, p, m_HCIEndpoint);
DoStateForMessage(m_ios, p, m_ACLEndpoint);
p.Do(m_last_ticks);
p.DoArray(m_PacketCount);
p.Do(m_ScanEnable);
@ -166,7 +166,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
{
case USB::IOCTLV_USBV0_CTRLMSG: // HCI command is received from the stack
{
m_CtrlSetup = std::make_unique<USB::V0CtrlMessage>(request);
m_CtrlSetup = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
// Replies are generated inside
ExecuteHCICommandMessage(*m_CtrlSetup);
m_CtrlSetup.reset();
@ -176,7 +176,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_BLKMSG:
{
const USB::V0BulkMessage ctrl{request};
const USB::V0BulkMessage ctrl{m_ios, request};
switch (ctrl.endpoint)
{
case ACL_DATA_OUT: // ACL data is received from the stack
@ -195,7 +195,7 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
}
case ACL_DATA_IN: // We are given an ACL buffer to fill
{
m_ACLEndpoint = std::make_unique<USB::V0BulkMessage>(request);
m_ACLEndpoint = std::make_unique<USB::V0BulkMessage>(m_ios, request);
DEBUG_LOG(IOS_WIIMOTE, "ACL_DATA_IN: 0x%08x ", request.address);
send_reply = false;
break;
@ -208,10 +208,10 @@ IPCCommandResult BluetoothEmu::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_INTRMSG:
{
const USB::V0IntrMessage ctrl{request};
const USB::V0IntrMessage ctrl{m_ios, request};
if (ctrl.endpoint == HCI_EVENT) // We are given a HCI buffer to fill
{
m_HCIEndpoint = std::make_unique<USB::V0IntrMessage>(request);
m_HCIEndpoint = std::make_unique<USB::V0IntrMessage>(m_ios, request);
DEBUG_LOG(IOS_WIIMOTE, "HCI_EVENT: 0x%08x ", request.address);
send_reply = false;
}
@ -265,7 +265,7 @@ void BluetoothEmu::SendACLPacket(u16 connection_handle, const u8* data, u32 size
// Write the packet to the buffer
memcpy(reinterpret_cast<u8*>(header) + sizeof(hci_acldata_hdr_t), data, header->length);
EnqueueReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ios.EnqueueIPCReply(m_ACLEndpoint->ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ACLEndpoint.reset();
}
else
@ -293,7 +293,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event)
m_HCIEndpoint->FillBuffer(_event.m_buffer, _event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, _event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, _event.m_size);
m_HCIEndpoint.reset();
}
else // push new one, pop oldest
@ -309,7 +309,7 @@ void BluetoothEmu::AddEventToQueue(const SQueuedEvent& _event)
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
@ -335,7 +335,7 @@ void BluetoothEmu::Update()
m_HCIEndpoint->FillBuffer(event.m_buffer, event.m_size);
// Send a reply to indicate HCI buffer is filled
EnqueueReply(m_HCIEndpoint->ios_request, event.m_size);
m_ios.EnqueueIPCReply(m_HCIEndpoint->ios_request, event.m_size);
m_HCIEndpoint.reset();
m_EventQueue.pop_front();
}
@ -430,7 +430,7 @@ void BluetoothEmu::ACLPool::WriteToEndpoint(USB::V0BulkMessage& endpoint)
m_queue.pop_front();
EnqueueReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
m_ios.EnqueueIPCReply(endpoint.ios_request, sizeof(hci_acldata_hdr_t) + size);
}
bool BluetoothEmu::SendEventInquiryComplete()
@ -1141,7 +1141,7 @@ void BluetoothEmu::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_messa
}
// HCI command is finished, send a reply to command
EnqueueReply(ctrl_message.ios_request, ctrl_message.length);
m_ios.EnqueueIPCReply(ctrl_message.ios_request, ctrl_message.length);
}
//

View File

@ -14,7 +14,7 @@
#include "Common/CommonTypes.h"
#include "Core/HW/Wiimote.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
#include "Core/IOS/USB/Bluetooth/hci.h"
@ -45,7 +45,7 @@ namespace Device
class BluetoothEmu final : public BluetoothBase
{
public:
BluetoothEmu(u32 device_id, const std::string& device_name);
BluetoothEmu(Kernel& ios, const std::string& device_name);
virtual ~BluetoothEmu();
@ -78,17 +78,8 @@ private:
class ACLPool
{
struct Packet
{
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
std::deque<Packet> m_queue;
public:
ACLPool() : m_queue() {}
explicit ACLPool(Kernel& ios) : m_ios(ios), m_queue() {}
void Store(const u8* data, const u16 size, const u16 conn_handle);
void WriteToEndpoint(USB::V0BulkMessage& endpoint);
@ -96,7 +87,17 @@ private:
bool IsEmpty() const { return m_queue.empty(); }
// For SaveStates
void DoState(PointerWrap& p) { p.Do(m_queue); }
} m_acl_pool;
private:
struct Packet
{
u8 data[ACL_PKT_SIZE];
u16 size;
u16 conn_handle;
};
Kernel& m_ios;
std::deque<Packet> m_queue;
} m_acl_pool{m_ios};
u32 m_PacketCount[MAX_BBMOTES] = {};
u64 m_last_ticks = 0;

View File

@ -56,8 +56,8 @@ static bool IsBluetoothDevice(const libusb_interface_descriptor& descriptor)
namespace Device
{
BluetoothReal::BluetoothReal(u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
BluetoothReal::BluetoothReal(Kernel& ios, const std::string& device_name)
: BluetoothBase(ios, device_name)
{
const int ret = libusb_init(&m_libusb_context);
if (ret < 0)
@ -179,7 +179,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_CTRLMSG:
{
std::lock_guard<std::mutex> lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0CtrlMessage>(request);
auto cmd = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
@ -228,7 +228,7 @@ IPCCommandResult BluetoothReal::IOCtlV(const IOCtlVRequest& request)
case USB::IOCTLV_USBV0_INTRMSG:
{
std::lock_guard<std::mutex> lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0IntrMessage>(request);
auto cmd = std::make_unique<USB::V0IntrMessage>(m_ios, request);
if (request.request == USB::IOCTLV_USBV0_INTRMSG)
{
if (m_sync_button_state == SyncButtonState::Pressed)
@ -310,7 +310,7 @@ void BluetoothReal::DoState(PointerWrap& p)
// waiting for the previous request to complete. This is usually not an issue as long as
// the Bluetooth state is the same (same Wii remote connections).
for (const auto& address_to_discard : addresses_to_discard)
EnqueueReply(Request{address_to_discard}, 0);
m_ios.EnqueueIPCReply(Request{address_to_discard}, 0);
// Prevent the callbacks from replying to a request that has already been discarded.
m_current_transfers.clear();
@ -452,7 +452,7 @@ void BluetoothReal::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = m_fake_vendor_command_reply_opcode;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
}
// Due to how the widcomm stack which Nintendo uses is coded, we must never
@ -477,7 +477,7 @@ void BluetoothReal::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
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));
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
}
void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload, const u8 size)
@ -488,7 +488,7 @@ void BluetoothReal::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payl
hci_event.length = size;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
EnqueueReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
}
// When the red sync button is pressed, a HCI event is generated:
@ -638,7 +638,8 @@ void BluetoothReal::HandleCtrlTransfer(libusb_transfer* tr)
}
const auto& command = m_current_transfers.at(tr).command;
command->FillBuffer(libusb_control_transfer_get_data(tr), tr->actual_length);
EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0,
CoreTiming::FromThread::NON_CPU);
m_current_transfers.erase(tr);
}
@ -688,7 +689,8 @@ void BluetoothReal::HandleBulkOrIntrTransfer(libusb_transfer* tr)
const auto& command = m_current_transfers.at(tr).command;
command->FillBuffer(tr->buffer, tr->actual_length);
EnqueueReply(command->ios_request, tr->actual_length, 0, CoreTiming::FromThread::NON_CPU);
m_ios.EnqueueIPCReply(command->ios_request, tr->actual_length, 0,
CoreTiming::FromThread::NON_CPU);
m_current_transfers.erase(tr);
}
} // namespace Device

View File

@ -16,7 +16,7 @@
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Timer.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/IOS/USB/USBV0.h"
@ -48,7 +48,7 @@ namespace Device
class BluetoothReal final : public BluetoothBase
{
public:
BluetoothReal(u32 device_id, const std::string& device_name);
BluetoothReal(Kernel& ios, const std::string& device_name);
~BluetoothReal() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -7,7 +7,7 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
class PointerWrap;
@ -21,10 +21,7 @@ namespace Device
class BluetoothStub final : public BluetoothBase
{
public:
BluetoothStub(const u32 device_id, const std::string& device_name)
: BluetoothBase(device_id, device_name)
{
}
using BluetoothBase::BluetoothBase;
ReturnCode Open(const OpenRequest& request) override;
void DoState(PointerWrap& p) override;
};

View File

@ -932,7 +932,7 @@ void Callback_WiimoteInterruptChannel(int _number, u16 _channelID, const void* _
DEBUG_LOG(WIIMOTE, " Channel: %x", _channelID);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
IOS::HLE::GetIOS()->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->m_WiiMotes[_number].ReceiveL2capData(_channelID, _pData, _Size);
}

View File

@ -33,6 +33,11 @@ void TransferCommand::FillBuffer(const u8* src, const size_t size) const
Memory::CopyToEmu(data_address, src, size);
}
void TransferCommand::OnTransferComplete(s32 return_value) const
{
m_ios.EnqueueIPCReply(ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU);
}
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)));

View File

@ -100,15 +100,19 @@ struct TransferCommand
Request ios_request;
u32 data_address = 0;
TransferCommand(const Request& ios_request_, u32 data_address_)
: ios_request(ios_request_), data_address(data_address_)
TransferCommand(Kernel& ios, const Request& ios_request_, u32 data_address_)
: ios_request(ios_request_), data_address(data_address_), m_ios(ios)
{
}
virtual ~TransferCommand() = default;
// Called after a transfer has completed and before replying to the transfer request.
virtual void OnTransferComplete() const {}
// Called after a transfer has completed to reply to the IPC request.
// This can be overridden for additional processing before replying.
virtual void OnTransferComplete(s32 return_value) const;
std::unique_ptr<u8[]> MakeBuffer(size_t size) const;
void FillBuffer(const u8* src, size_t size) const;
private:
Kernel& m_ios;
};
struct CtrlMessage : TransferCommand

View File

@ -27,7 +27,7 @@ namespace HLE
{
namespace Device
{
USBHost::USBHost(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
USBHost::USBHost(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
#ifdef __LIBUSB__
const int ret = libusb_init(&m_libusb_context);
@ -150,7 +150,7 @@ bool USBHost::AddNewDevices(std::set<u64>& new_devices, DeviceChangeHooks& hooks
continue;
}
auto usb_device = std::make_unique<USB::LibusbDevice>(device, descriptor);
auto usb_device = std::make_unique<USB::LibusbDevice>(m_ios, device, descriptor);
if (!ShouldAddDevice(*usb_device))
{
libusb_unref_device(device);

View File

@ -17,7 +17,7 @@
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Common.h"
class PointerWrap;
@ -33,7 +33,7 @@ namespace Device
class USBHost : public Device
{
public:
USBHost(u32 device_id, const std::string& device_name);
USBHost(Kernel& ios, const std::string& device_name);
virtual ~USBHost();
ReturnCode Open(const OpenRequest& request) override;

View File

@ -15,7 +15,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/LibusbDevice.h"
namespace IOS
@ -24,8 +24,9 @@ namespace HLE
{
namespace USB
{
LibusbDevice::LibusbDevice(libusb_device* device, const libusb_device_descriptor& descriptor)
: m_device(device)
LibusbDevice::LibusbDevice(Kernel& ios, libusb_device* device,
const libusb_device_descriptor& descriptor)
: m_ios(ios), m_device(device)
{
libusb_ref_device(m_device);
m_vid = descriptor.idVendor;
@ -200,14 +201,14 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
}
const int ret = SetAltSetting(static_cast<u8>(cmd->value));
if (ret == 0)
EnqueueReply(cmd->ios_request, cmd->length);
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
return ret;
}
case USBHDR(DIR_HOST2DEVICE, TYPE_STANDARD, REC_DEVICE, REQUEST_SET_CONFIGURATION):
{
const int ret = libusb_set_configuration(m_handle, cmd->value);
if (ret == 0)
EnqueueReply(cmd->ios_request, cmd->length);
m_ios.EnqueueIPCReply(cmd->ios_request, cmd->length);
return ret;
}
}
@ -355,8 +356,7 @@ void LibusbDevice::TransferEndpoint::HandleTransfer(libusb_transfer* transfer,
return_value = IPC_ENOENT;
break;
}
cmd.OnTransferComplete();
EnqueueReply(cmd.ios_request, return_value, 0, CoreTiming::FromThread::NON_CPU);
cmd.OnTransferComplete(return_value);
m_transfers.erase(transfer);
}

View File

@ -43,7 +43,8 @@ private:
class LibusbDevice final : public Device
{
public:
LibusbDevice(libusb_device* device, const libusb_device_descriptor& device_descriptor);
LibusbDevice(Kernel& ios, libusb_device* device,
const libusb_device_descriptor& device_descriptor);
~LibusbDevice();
DeviceDescriptor GetDeviceDescriptor() const override;
std::vector<ConfigDescriptor> GetConfigurations() const override;
@ -61,6 +62,8 @@ public:
int SubmitTransfer(std::unique_ptr<IsoMessage> message) override;
private:
Kernel& m_ios;
std::vector<std::unique_ptr<LibusbConfigDescriptor>> m_config_descriptors;
u16 m_vid = 0;
u16 m_pid = 0;

View File

@ -25,7 +25,7 @@ namespace HLE
{
namespace Device
{
OH0::OH0(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name)
OH0::OH0(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -36,7 +36,7 @@ OH0::~OH0()
ReturnCode OH0::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59)
return IPC_EACCES;
return USBHost::Open(request);
@ -240,7 +240,7 @@ void OH0::TriggerHook(std::map<T, u32>& hooks, T value, const ReturnCode return_
const auto hook = hooks.find(value);
if (hook == hooks.end())
return;
EnqueueReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(Request{hook->second}, return_value, 0, CoreTiming::FromThread::ANY);
hooks.erase(hook);
}
@ -325,26 +325,26 @@ s32 OH0::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
if (!ioctlv.HasNumberOfValidVectors(6, 1) ||
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>(ioctlv));
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)
return IPC_EINVAL;
return device.SubmitTransfer(
std::make_unique<USB::V0BulkMessage>(ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG));
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)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV0_ISOMSG:
if (!ioctlv.HasNumberOfValidVectors(3, 2))
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IsoMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V0IsoMessage>(m_ios, ioctlv));
default:
return IPC_EINVAL;

View File

@ -38,7 +38,7 @@ namespace Device
class OH0 final : public USBHost
{
public:
OH0(u32 device_id, const std::string& device_name);
OH0(Kernel& ios, const std::string& device_name);
~OH0() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -7,7 +7,7 @@
#include <vector>
#include "Common/ChunkFile.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/OH0/OH0.h"
#include "Core/IOS/USB/OH0/OH0Device.h"
@ -37,7 +37,7 @@ static void GetVidPidFromDevicePath(const std::string& device_path, u16& vid, u1
ss >> pid;
}
OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceType::OH0)
OH0Device::OH0Device(Kernel& ios, const std::string& name) : Device(ios, name, DeviceType::OH0)
{
if (!name.empty())
GetVidPidFromDevicePath(name, m_vid, m_pid);
@ -45,7 +45,7 @@ OH0Device::OH0Device(u32 id, const std::string& name) : Device(id, name, DeviceT
void OH0Device::DoState(PointerWrap& p)
{
m_oh0 = std::static_pointer_cast<OH0>(GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
p.Do(m_name);
p.Do(m_vid);
p.Do(m_pid);
@ -54,14 +54,14 @@ void OH0Device::DoState(PointerWrap& p)
ReturnCode OH0Device::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version == 57 || ios_major_version == 58 || ios_major_version == 59)
return IPC_ENOENT;
if (m_vid == 0 && m_pid == 0)
return IPC_ENOENT;
m_oh0 = std::static_pointer_cast<OH0>(GetDeviceByName("/dev/usb/oh0"));
m_oh0 = std::static_pointer_cast<OH0>(m_ios.GetDeviceByName("/dev/usb/oh0"));
ReturnCode return_code;
std::tie(return_code, m_device_id) = m_oh0->DeviceOpen(m_vid, m_pid);

View File

@ -22,7 +22,7 @@ class OH0;
class OH0Device final : public Device
{
public:
OH0Device(u32 device_id, const std::string& device_name);
OH0Device(Kernel& ios, const std::string& device_name);
ReturnCode Open(const OpenRequest& request) override;
ReturnCode Close(u32 fd) override;

View File

@ -17,8 +17,8 @@ namespace HLE
{
namespace USB
{
V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv)
: CtrlMessage(ioctlv, ioctlv.io_vectors[0].address)
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);
@ -27,8 +27,8 @@ V0CtrlMessage::V0CtrlMessage(const IOCtlVRequest& ioctlv)
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
}
V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length)
: BulkMessage(ioctlv, ioctlv.io_vectors[0].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);
if (long_length)
@ -37,15 +37,15 @@ V0BulkMessage::V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length)
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
}
V0IntrMessage::V0IntrMessage(const IOCtlVRequest& ioctlv)
: IntrMessage(ioctlv, ioctlv.io_vectors[0].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);
}
V0IsoMessage::V0IsoMessage(const IOCtlVRequest& ioctlv)
: IsoMessage(ioctlv, ioctlv.io_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);

View File

@ -41,22 +41,22 @@ enum V0Requests
struct V0CtrlMessage final : CtrlMessage
{
explicit V0CtrlMessage(const IOCtlVRequest& ioctlv);
V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V0BulkMessage final : BulkMessage
{
explicit V0BulkMessage(const IOCtlVRequest& ioctlv, bool long_length = false);
V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length = false);
};
struct V0IntrMessage final : IntrMessage
{
explicit V0IntrMessage(const IOCtlVRequest& ioctlv);
V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V0IsoMessage final : IsoMessage
{
explicit V0IsoMessage(const IOCtlVRequest& ioctlv);
V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
} // namespace USB
} // namespace HLE

View File

@ -49,7 +49,7 @@ struct HIDRequest
};
#pragma pack(pop)
V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
@ -64,7 +64,8 @@ V4CtrlMessage::V4CtrlMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
// Since this is just a standard control request, but with additional requirements
// (US for the language and replacing non-ASCII characters with '?'),
// we can simply submit it as a usual control request.
V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMessage(ioctl, -1)
V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl)
: CtrlMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
@ -76,16 +77,17 @@ V4GetUSStringMessage::V4GetUSStringMessage(const IOCtlRequest& ioctl) : CtrlMess
data_address = Common::swap32(hid_request.data_addr);
}
void V4GetUSStringMessage::OnTransferComplete() const
void V4GetUSStringMessage::OnTransferComplete(s32 return_value) const
{
const std::locale& c_locale = std::locale::classic();
std::string message = Memory::GetString(data_address);
std::replace_if(message.begin(), message.end(),
[&c_locale](char c) { return !std::isprint(c, c_locale); }, '?');
Memory::CopyToEmu(data_address, message.c_str(), message.size());
TransferCommand::OnTransferComplete(return_value);
}
V4IntrMessage::V4IntrMessage(const IOCtlRequest& ioctl) : IntrMessage(ioctl, -1)
V4IntrMessage::V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl) : IntrMessage(ios, ioctl, -1)
{
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));

View File

@ -32,18 +32,18 @@ enum V4Requests
struct V4CtrlMessage final : CtrlMessage
{
explicit V4CtrlMessage(const IOCtlRequest& ioctl);
V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl);
};
struct V4GetUSStringMessage final : CtrlMessage
{
explicit V4GetUSStringMessage(const IOCtlRequest& ioctl);
void OnTransferComplete() const override;
V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl);
void OnTransferComplete(s32 return_value) const override;
};
struct V4IntrMessage final : IntrMessage
{
explicit V4IntrMessage(const IOCtlRequest& ioctl);
V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl);
};
} // namespace USB
} // namespace HLE

View File

@ -16,8 +16,8 @@ namespace HLE
{
namespace USB
{
V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv)
: CtrlMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16))
V5CtrlMessage::V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 16))
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address + 8);
request = Memory::Read_U8(ioctlv.in_vectors[0].address + 9);
@ -26,22 +26,22 @@ V5CtrlMessage::V5CtrlMessage(const IOCtlVRequest& ioctlv)
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 14);
}
V5BulkMessage::V5BulkMessage(const IOCtlVRequest& ioctlv)
: BulkMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5BulkMessage::V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: BulkMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 18);
}
V5IntrMessage::V5IntrMessage(const IOCtlVRequest& ioctlv)
: IntrMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5IntrMessage::V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
length = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 14);
}
V5IsoMessage::V5IsoMessage(const IOCtlVRequest& ioctlv)
: IsoMessage(ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, Memory::Read_U32(ioctlv.in_vectors[0].address + 8))
{
num_packets = Memory::Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 17);

View File

@ -36,22 +36,22 @@ enum V5Requests
struct V5CtrlMessage final : CtrlMessage
{
explicit V5CtrlMessage(const IOCtlVRequest& ioctlv);
V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5BulkMessage final : BulkMessage
{
explicit V5BulkMessage(const IOCtlVRequest& ioctlv);
V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5IntrMessage final : IntrMessage
{
explicit V5IntrMessage(const IOCtlVRequest& ioctlv);
V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv);
};
struct V5IsoMessage final : IsoMessage
{
explicit V5IsoMessage(const IOCtlVRequest& cmd_buffer);
V5IsoMessage(Kernel& ios, const IOCtlVRequest& cmd_buffer);
};
} // namespace USB
} // namespace HLE

View File

@ -23,8 +23,7 @@ namespace HLE
{
namespace Device
{
USB_HIDv4::USB_HIDv4(u32 device_id, const std::string& device_name)
: USBHost(device_id, device_name)
USB_HIDv4::USB_HIDv4(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -102,7 +101,7 @@ IPCCommandResult USB_HIDv4::Shutdown(const IOCtlRequest& request)
if (m_devicechange_hook_request != 0)
{
Memory::Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out);
EnqueueReply(*m_devicechange_hook_request, -1);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, -1);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
@ -113,12 +112,12 @@ s32 USB_HIDv4::SubmitTransfer(USB::Device& device, const IOCtlRequest& request)
switch (request.request)
{
case USB::IOCTL_USBV4_CTRLMSG:
return device.SubmitTransfer(std::make_unique<USB::V4CtrlMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4CtrlMessage>(m_ios, request));
case USB::IOCTL_USBV4_GET_US_STRING:
return device.SubmitTransfer(std::make_unique<USB::V4GetUSStringMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4GetUSStringMessage>(m_ios, request));
case USB::IOCTL_USBV4_INTRMSG_IN:
case USB::IOCTL_USBV4_INTRMSG_OUT:
return device.SubmitTransfer(std::make_unique<USB::V4IntrMessage>(request));
return device.SubmitTransfer(std::make_unique<USB::V4IntrMessage>(m_ios, request));
default:
return IPC_EINVAL;
}
@ -204,7 +203,7 @@ void USB_HIDv4::TriggerDeviceChangeReply()
Memory::Write_U32(0xffffffff, dest + offset);
}
EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY);
m_devicechange_hook_request.reset();
}

View File

@ -11,7 +11,7 @@
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Host.h"
class PointerWrap;
@ -25,7 +25,7 @@ namespace Device
class USB_HIDv4 final : public USBHost
{
public:
USB_HIDv4(u32 device_id, const std::string& device_name);
USB_HIDv4(Kernel& ios, const std::string& device_name);
~USB_HIDv4() override;
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -39,7 +39,7 @@ USB_KBD::SMessageData::SMessageData(u32 type, u8 modifiers, u8* pressed_keys)
// TODO: support in netplay/movies.
USB_KBD::USB_KBD(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
USB_KBD::USB_KBD(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -9,7 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -20,7 +20,7 @@ namespace Device
class USB_KBD : public Device
{
public:
USB_KBD(u32 device_id, const std::string& device_name);
USB_KBD(Kernel& ios, const std::string& device_name);
ReturnCode Open(const OpenRequest& request) override;
IPCCommandResult Write(const ReadWriteRequest& request) override;

View File

@ -22,7 +22,7 @@ namespace HLE
{
namespace Device
{
USB_VEN::USB_VEN(u32 device_id, const std::string& device_name) : USBHost(device_id, device_name)
USB_VEN::USB_VEN(Kernel& ios, const std::string& device_name) : USBHost(ios, device_name)
{
}
@ -33,7 +33,7 @@ USB_VEN::~USB_VEN()
ReturnCode USB_VEN::Open(const OpenRequest& request)
{
const u32 ios_major_version = GetVersion();
const u32 ios_major_version = m_ios.GetVersion();
if (ios_major_version != 57 && ios_major_version != 58 && ios_major_version != 59)
return IPC_ENOENT;
return USBHost::Open(request);
@ -197,7 +197,7 @@ IPCCommandResult USB_VEN::Shutdown(const IOCtlRequest& request)
std::lock_guard<std::mutex> lk{m_devicechange_hook_address_mutex};
if (m_devicechange_hook_request)
{
EnqueueReply(*m_devicechange_hook_request, IPC_SUCCESS);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS);
m_devicechange_hook_request.reset();
}
return GetDefaultReply(IPC_SUCCESS);
@ -220,13 +220,13 @@ s32 USB_VEN::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
switch (ioctlv.request)
{
case USB::IOCTLV_USBV5_CTRLMSG:
return device.SubmitTransfer(std::make_unique<USB::V5CtrlMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5CtrlMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_INTRMSG:
return device.SubmitTransfer(std::make_unique<USB::V5IntrMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5IntrMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_BULKMSG:
return device.SubmitTransfer(std::make_unique<USB::V5BulkMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5BulkMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV5_ISOMSG:
return device.SubmitTransfer(std::make_unique<USB::V5IsoMessage>(ioctlv));
return device.SubmitTransfer(std::make_unique<USB::V5IsoMessage>(m_ios, ioctlv));
default:
return IPC_EINVAL;
}
@ -326,7 +326,7 @@ void USB_VEN::TriggerDeviceChangeReply()
&entry, sizeof(entry));
}
EnqueueReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, num_devices, 0, CoreTiming::FromThread::ANY);
m_devicechange_hook_request.reset();
INFO_LOG(IOS_USB, "%d device(s), including interfaces", num_devices);
}

View File

@ -14,7 +14,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Host.h"
class PointerWrap;
@ -28,7 +28,7 @@ namespace Device
class USB_VEN final : public USBHost
{
public:
USB_VEN(u32 device_id, const std::string& device_name);
USB_VEN(Kernel& ios, const std::string& device_name);
~USB_VEN() override;
ReturnCode Open(const OpenRequest& request) override;

View File

@ -80,7 +80,7 @@ void ARCUnpacker::Extract(const WriteCallback& callback)
namespace Device
{
WFSI::WFSI(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
WFSI::WFSI(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
}

View File

@ -13,7 +13,7 @@
#include "Common/CommonTypes.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
namespace IOS
{
@ -39,7 +39,7 @@ namespace Device
class WFSI : public Device
{
public:
WFSI(u32 device_id, const std::string& device_name);
WFSI(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -27,7 +27,7 @@ std::string NativePath(const std::string& wfs_path)
namespace Device
{
WFSSRV::WFSSRV(u32 device_id, const std::string& device_name) : Device(device_id, device_name)
WFSSRV::WFSSRV(Kernel& ios, const std::string& device_name) : Device(ios, device_name)
{
m_device_name = "msc01";
}

View File

@ -10,7 +10,7 @@
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "DiscIO/Volume.h"
namespace IOS
@ -27,7 +27,7 @@ namespace Device
class WFSSRV : public Device
{
public:
WFSSRV(u32 device_id, const std::string& device_name);
WFSSRV(Kernel& ios, const std::string& device_name);
IPCCommandResult IOCtl(const IOCtlRequest& request) override;

View File

@ -533,8 +533,10 @@ void ChangeWiiPads(bool instantly)
if (instantly && (s_controllers >> 4) == controllers)
return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
const auto ios = IOS::HLE::GetIOS();
const auto bt = ios ? std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")) :
nullptr;
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;

View File

@ -71,7 +71,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 82; // Last changed in PR 5333
static const u32 STATE_VERSION = 83; // Last changed in PR 5340
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,

View File

@ -23,7 +23,7 @@
#include "Core/Core.h"
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
@ -139,19 +139,18 @@ bool Host_RendererIsFullscreen()
void Host_ConnectWiimote(int wm_idx, bool connect)
{
if (Core::IsRunning() && SConfig::GetInstance().bWii &&
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
Core::QueueHostJob([=] {
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused);
});
}
Core::QueueHostJob([=] {
const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
Host_UpdateMainFrame();
Core::PauseAndLock(false, was_unpaused);
});
}
void Host_SetWiiMoteConnectionState(int _State)
@ -241,7 +240,8 @@ class PlatformX11 : public Platform
{
if (s_shutdown_requested.TestAndClear())
{
const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
const auto ios = IOS::HLE::GetIOS();
const auto stm = ios ? ios->GetDeviceByName("/dev/stm/eventhook") : nullptr;
if (!s_tried_graceful_shutdown.IsSet() && stm &&
std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled())
{

View File

@ -13,7 +13,7 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "DolphinWX/Config/AddUSBDeviceDiag.h"
#include "DolphinWX/Config/WiiConfigPane.h"
#include "DolphinWX/DolphinSlider.h"
@ -279,7 +279,9 @@ void WiiConfigPane::OnPAL60CheckBoxChanged(wxCommandEvent& event)
void WiiConfigPane::OnSDCardCheckBoxChanged(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiiSDCard = m_sd_card_checkbox->IsChecked();
IOS::HLE::SDIO_EventNotify();
const auto ios = IOS::HLE::GetIOS();
if (ios)
ios->SDIO_EventNotify();
}
void WiiConfigPane::OnConnectKeyboardCheckBoxChanged(wxCommandEvent& event)

View File

@ -27,7 +27,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTReal.h"
#include "Core/NetPlayProto.h"
#include "DolphinWX/Config/GCAdapterConfigDiag.h"
@ -543,13 +543,14 @@ void ControllerConfigDiag::OnBluetoothModeChanged(wxCommandEvent& event)
void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
const auto ios = IOS::HLE::GetIOS();
if (!ios)
{
wxMessageBox(_("A sync can only be triggered when a Wii game is running."),
_("Sync Wii Remotes"), wxICON_WARNING);
return;
}
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)
->TriggerSyncButtonPressedEvent();
@ -557,13 +558,14 @@ void ControllerConfigDiag::OnPassthroughScanButton(wxCommandEvent& event)
void ControllerConfigDiag::OnPassthroughResetButton(wxCommandEvent& event)
{
if (!Core::IsRunning())
const auto ios = IOS::HLE::GetIOS();
if (!ios)
{
wxMessageBox(_("Saved Wii Remote pairings can only be reset when a Wii game is running."),
_("Reset Wii Remote pairings"), wxICON_WARNING);
return;
}
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305");
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)->TriggerSyncButtonHeldEvent();
}

View File

@ -50,7 +50,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/USB/Bluetooth/BTBase.h"
#include "Core/Movie.h"
#include "Core/State.h"
@ -1278,7 +1278,8 @@ void CFrame::ParseHotkeys()
if (SConfig::GetInstance().m_bt_passthrough_enabled)
{
auto device = IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305");
const auto ios = IOS::HLE::GetIOS();
auto device = ios ? ios->GetDeviceByName("/dev/usb/oh1/57e/305") : nullptr;
if (device != nullptr)
std::static_pointer_cast<IOS::HLE::Device::BluetoothBase>(device)->UpdateSyncButtonState(
IsHotkey(HK_TRIGGER_SYNC_BUTTON, true));

View File

@ -42,7 +42,7 @@
#include "Core/HW/Wiimote.h"
#include "Core/Host.h"
#include "Core/HotkeyManager.h"
#include "Core/IOS/IPC.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/STM/STM.h"
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteDevice.h"
@ -880,7 +880,11 @@ void CFrame::DoStop()
bool CFrame::TriggerSTMPowerEvent()
{
const auto stm = IOS::HLE::GetDeviceByName("/dev/stm/eventhook");
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return false;
const auto stm = ios->GetDeviceByName("/dev/stm/eventhook");
if (!stm || !std::static_pointer_cast<IOS::HLE::Device::STMEventHook>(stm)->HasHookInstalled())
return false;
@ -1310,8 +1314,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
!SConfig::GetInstance().m_bt_passthrough_enabled)
{
bool was_unpaused = Core::PauseAndLock(true);
const auto ios = IOS::HLE::GetIOS();
if (!ios)
return;
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
if (bt)
bt->AccessWiiMote(wm_idx | 0x100)->Activate(connect);
const char* message = connect ? "Wii Remote %i connected" : "Wii Remote %i disconnected";
@ -1323,11 +1331,12 @@ void CFrame::ConnectWiimote(int wm_idx, bool connect)
void CFrame::OnConnectWiimote(wxCommandEvent& event)
{
if (SConfig::GetInstance().m_bt_passthrough_enabled)
const auto ios = IOS::HLE::GetIOS();
if (!ios || SConfig::GetInstance().m_bt_passthrough_enabled)
return;
bool was_unpaused = Core::PauseAndLock(true);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
ios->GetDeviceByName("/dev/usb/oh1/57e/305"));
const bool is_connected =
bt && bt->AccessWiiMote((event.GetId() - IDM_CONNECT_WIIMOTE1) | 0x100)->IsConnected();
ConnectWiimote(event.GetId() - IDM_CONNECT_WIIMOTE1, !is_connected);
@ -1486,8 +1495,10 @@ void CFrame::UpdateGUI()
// Tools
GetMenuBar()->FindItem(IDM_CHEATS)->Enable(SConfig::GetInstance().bEnableCheats);
const auto bt = std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
IOS::HLE::GetDeviceByName("/dev/usb/oh1/57e/305"));
const auto ios = IOS::HLE::GetIOS();
const auto bt = ios ? std::static_pointer_cast<IOS::HLE::Device::BluetoothEmu>(
ios->GetDeviceByName("/dev/usb/oh1/57e/305")) :
nullptr;
bool ShouldEnableWiimotes = Running && bt && !SConfig::GetInstance().m_bt_passthrough_enabled;
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(ShouldEnableWiimotes);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(ShouldEnableWiimotes);