mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-04 03:46:42 +01:00
IOS: Reorder functions in IOS.cpp
Puts them in a more logical order.
This commit is contained in:
parent
2fc5047d26
commit
58fe0f12a4
@ -64,12 +64,6 @@ constexpr u64 ENQUEUE_ACKNOWLEDGEMENT_FLAG = 0x200000000ULL;
|
|||||||
static CoreTiming::EventType* s_event_enqueue;
|
static CoreTiming::EventType* s_event_enqueue;
|
||||||
static CoreTiming::EventType* s_event_sdio_notify;
|
static CoreTiming::EventType* s_event_sdio_notify;
|
||||||
|
|
||||||
enum class MemorySetupType
|
|
||||||
{
|
|
||||||
IOSReload,
|
|
||||||
Full,
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr u32 ADDR_MEM1_SIZE = 0x3100;
|
constexpr u32 ADDR_MEM1_SIZE = 0x3100;
|
||||||
constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104;
|
constexpr u32 ADDR_MEM1_SIM_SIZE = 0x3104;
|
||||||
constexpr u32 ADDR_MEM1_END = 0x3108;
|
constexpr u32 ADDR_MEM1_END = 0x3108;
|
||||||
@ -97,16 +91,14 @@ constexpr u32 ADDR_BOOT_FLAG = 0x315c;
|
|||||||
constexpr u32 ADDR_APPLOADER_FLAG = 0x315d;
|
constexpr u32 ADDR_APPLOADER_FLAG = 0x315d;
|
||||||
constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e;
|
constexpr u32 ADDR_DEVKIT_BOOT_PROGRAM_VERSION = 0x315e;
|
||||||
constexpr u32 ADDR_SYSMENU_SYNC = 0x3160;
|
constexpr u32 ADDR_SYSMENU_SYNC = 0x3160;
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
|
constexpr u32 PLACEHOLDER = 0xDEADBEEF;
|
||||||
|
|
||||||
|
enum class MemorySetupType
|
||||||
|
{
|
||||||
|
IOSReload,
|
||||||
|
Full,
|
||||||
|
};
|
||||||
|
|
||||||
static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
|
static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
|
||||||
{
|
{
|
||||||
auto target_imv = std::find_if(
|
auto target_imv = std::find_if(
|
||||||
@ -175,44 +167,6 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
|
|||||||
return true;
|
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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// IOS used by the latest System Menu (4.3).
|
// IOS used by the latest System Menu (4.3).
|
||||||
constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
|
constexpr u64 IOS80_TITLE_ID = 0x0000000100000050;
|
||||||
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
constexpr u64 BC_TITLE_ID = 0x0000000100000100;
|
||||||
@ -255,77 +209,12 @@ Kernel::~Kernel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::HandleIPCEvent(u64 userdata)
|
// 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
|
||||||
{
|
{
|
||||||
if (userdata & ENQUEUE_ACKNOWLEDGEMENT_FLAG)
|
return static_cast<u32>(m_title_id);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
|
||||||
@ -379,12 +268,67 @@ bool Kernel::BootstrapPPC(const DiscIO::CNANDContentLoader& content_loader)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Kernel::SDIO_EventNotify()
|
// 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)
|
||||||
{
|
{
|
||||||
// TODO: Potential race condition: If IsRunning() becomes false after
|
// A real Wii goes through several steps before getting to MIOS.
|
||||||
// it's checked, an event may be scheduled after CoreTiming shuts down.
|
//
|
||||||
if (SConfig::GetInstance().bWii && Core::IsRunning())
|
// * The System Menu detects a GameCube disc and launches BC (1-100) instead of the game.
|
||||||
CoreTiming::ScheduleEvent(0, s_event_sdio_notify, 0, CoreTiming::FromThread::NON_CPU);
|
// * 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()
|
s32 Kernel::GetFreeDeviceID()
|
||||||
@ -407,84 +351,6 @@ std::shared_ptr<Device::Device> Kernel::GetDeviceByName(const std::string& devic
|
|||||||
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
return iterator != m_device_map.end() ? iterator->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the FD for the newly opened device (on success) or an error code.
|
// Returns the FD for the newly opened device (on success) or an error code.
|
||||||
s32 Kernel::OpenDevice(OpenRequest& request)
|
s32 Kernel::OpenDevice(OpenRequest& request)
|
||||||
{
|
{
|
||||||
@ -599,6 +465,18 @@ void Kernel::EnqueueIPCAcknowledgement(u32 address, int cycles_in_future)
|
|||||||
address | ENQUEUE_ACKNOWLEDGEMENT_FLAG);
|
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
|
// This is called every IPC_HLE_PERIOD from SystemTimers.cpp
|
||||||
// Takes care of routing ipc <-> ipc HLE
|
// Takes care of routing ipc <-> ipc HLE
|
||||||
void Kernel::UpdateIPC()
|
void Kernel::UpdateIPC()
|
||||||
@ -650,5 +528,127 @@ void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
|
|||||||
for (const auto& device : m_device_map)
|
for (const auto& device : m_device_map)
|
||||||
device.second->UpdateWantDeterminism(new_want_determinism);
|
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 HLE
|
||||||
} // namespace IOS
|
} // namespace IOS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user