Core/IOS/WiiIPC: Refactor to class, move to System.

This commit is contained in:
Admiral H. Curtiss 2024-01-11 06:48:17 +01:00
parent be7f4ab244
commit 17753d5168
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
9 changed files with 234 additions and 166 deletions

View File

@ -56,7 +56,7 @@ void Init(Core::System& system, const Sram* override_sram)
if (SConfig::GetInstance().bWii)
{
IOS::Init();
system.GetWiiIPC().Init();
IOS::HLE::Init(system); // Depends on Memory
}
}
@ -65,7 +65,7 @@ void Shutdown(Core::System& system)
{
// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
system.GetWiiIPC().Shutdown();
system.GetSystemTimers().Shutdown();
system.GetCPU().Shutdown();
@ -110,7 +110,7 @@ void DoState(Core::System& system, PointerWrap& p)
if (SConfig::GetInstance().bWii)
{
IOS::DoState(p);
system.GetWiiIPC().DoState(p);
p.DoMarker("IOS");
IOS::HLE::GetIOS()->DoState(p);
p.DoMarker("IOS::HLE");

View File

@ -63,7 +63,7 @@ void MemoryManager::InitMMIO(bool is_wii)
m_system.GetAudioInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00);
if (is_wii)
{
IOS::RegisterMMIO(m_mmio_mapping.get(), 0x0D000000);
m_system.GetWiiIPC().RegisterMMIO(m_mmio_mapping.get(), 0x0D000000);
m_system.GetDVDInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006000, true);
m_system.GetSerialInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006400);
m_system.GetExpansionInterface().RegisterMMIO(m_mmio_mapping.get(), 0x0D006800);

View File

@ -11,6 +11,7 @@
#include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/IOS/IOS.h"
#include "Core/System.h"
// This is the intercommunication between ARM and PPC. Currently only PPC actually uses it, because
// of the IOS HLE
@ -19,8 +20,8 @@
// X2 Reload (a new IOS is being loaded, old one doesn't need to reply anymore)
// Y1 Command executed and reply available in HW_IPC_ARMMSG
// Y2 Command acknowledge
// ppc_msg is a pointer to 0x40byte command structure
// arm_msg is, similarly, starlet's response buffer*
// m_ppc_msg is a pointer to 0x40byte command structure
// m_arm_msg is, similarly, starlet's response buffer*
namespace IOS
{
@ -54,164 +55,123 @@ enum
UNK_1D0 = 0x1d0,
};
struct CtrlRegister
{
u8 X1 : 1;
u8 X2 : 1;
u8 Y1 : 1;
u8 Y2 : 1;
u8 IX1 : 1;
u8 IX2 : 1;
u8 IY1 : 1;
u8 IY2 : 1;
CtrlRegister() { X1 = X2 = Y1 = Y2 = IX1 = IX2 = IY1 = IY2 = 0; }
inline u8 ppc() { return (IY2 << 5) | (IY1 << 4) | (X2 << 3) | (Y1 << 2) | (Y2 << 1) | X1; }
inline u8 arm() { return (IX2 << 5) | (IX1 << 4) | (Y2 << 3) | (X1 << 2) | (X2 << 1) | Y1; }
inline void ppc(u32 v)
{
X1 = v & 1;
X2 = (v >> 3) & 1;
if ((v >> 2) & 1)
Y1 = 0;
if ((v >> 1) & 1)
Y2 = 0;
IY1 = (v >> 4) & 1;
IY2 = (v >> 5) & 1;
}
inline void arm(u32 v)
{
Y1 = v & 1;
Y2 = (v >> 3) & 1;
if ((v >> 2) & 1)
X1 = 0;
if ((v >> 1) & 1)
X2 = 0;
IX1 = (v >> 4) & 1;
IX2 = (v >> 5) & 1;
}
};
// STATE_TO_SAVE
static u32 ppc_msg;
static u32 arm_msg;
static CtrlRegister ctrl;
static u32 ppc_irq_flags;
static u32 ppc_irq_masks;
static u32 arm_irq_flags;
static u32 arm_irq_masks;
// Indicates which pins are accessible by broadway. Writable by starlet only.
static constexpr Common::Flags<GPIO> gpio_owner = {GPIO::SLOT_LED, GPIO::SLOT_IN, GPIO::SENSOR_BAR,
GPIO::DO_EJECT, GPIO::AVE_SCL, GPIO::AVE_SDA};
static Common::Flags<GPIO> gpio_dir;
Common::Flags<GPIO> g_gpio_out;
static u32 resets;
static CoreTiming::EventType* updateInterrupts;
static void UpdateInterrupts(Core::System& system, u64 userdata, s64 cyclesLate);
void DoState(PointerWrap& p)
WiiIPC::WiiIPC(Core::System& system) : m_system(system)
{
p.Do(ppc_msg);
p.Do(arm_msg);
p.Do(ctrl);
p.Do(ppc_irq_flags);
p.Do(ppc_irq_masks);
p.Do(arm_irq_flags);
p.Do(arm_irq_masks);
p.Do(g_gpio_out);
}
static void InitState()
{
ctrl = CtrlRegister();
ppc_msg = 0;
arm_msg = 0;
WiiIPC::~WiiIPC() = default;
ppc_irq_flags = 0;
ppc_irq_masks = 0;
arm_irq_flags = 0;
arm_irq_masks = 0;
void WiiIPC::DoState(PointerWrap& p)
{
p.Do(m_ppc_msg);
p.Do(m_arm_msg);
p.Do(m_ctrl);
p.Do(m_ppc_irq_flags);
p.Do(m_ppc_irq_masks);
p.Do(m_arm_irq_flags);
p.Do(m_arm_irq_masks);
p.Do(m_gpio_out);
}
void WiiIPC::InitState()
{
m_ctrl = CtrlRegister();
m_ppc_msg = 0;
m_arm_msg = 0;
m_ppc_irq_flags = 0;
m_ppc_irq_masks = 0;
m_arm_irq_flags = 0;
m_arm_irq_masks = 0;
// The only inputs are POWER, EJECT_BTN, SLOT_IN, and EEP_MISO; Broadway only has access to
// SLOT_IN
gpio_dir = {
m_gpio_dir = {
GPIO::POWER, GPIO::SHUTDOWN, GPIO::FAN, GPIO::DC_DC, GPIO::DI_SPIN, GPIO::SLOT_LED,
GPIO::SENSOR_BAR, GPIO::DO_EJECT, GPIO::EEP_CS, GPIO::EEP_CLK, GPIO::EEP_MOSI, GPIO::AVE_SCL,
GPIO::AVE_SDA, GPIO::DEBUG0, GPIO::DEBUG1, GPIO::DEBUG2, GPIO::DEBUG3, GPIO::DEBUG4,
GPIO::DEBUG5, GPIO::DEBUG6, GPIO::DEBUG7,
};
g_gpio_out = {};
m_gpio_out = {};
// A cleared bit indicates the device is reset/off, so set everything to 1 (this may not exactly
// match hardware)
resets = 0xffffffff;
m_resets = 0xffffffff;
ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
m_ppc_irq_masks |= INT_CAUSE_IPC_BROADWAY;
}
void Init()
void WiiIPC::Init()
{
InitState();
updateInterrupts =
Core::System::GetInstance().GetCoreTiming().RegisterEvent("IPCInterrupt", UpdateInterrupts);
m_event_type_update_interrupts =
m_system.GetCoreTiming().RegisterEvent("IPCInterrupt", UpdateInterruptsCallback);
}
void Reset()
void WiiIPC::Reset()
{
INFO_LOG_FMT(WII_IPC, "Resetting ...");
InitState();
}
void Shutdown()
void WiiIPC::Shutdown()
{
}
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
void WiiIPC::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead<u32>(), MMIO::DirectWrite<u32>(&ppc_msg));
mmio->Register(base | IPC_PPCMSG, MMIO::InvalidRead<u32>(), MMIO::DirectWrite<u32>(&m_ppc_msg));
mmio->Register(base | IPC_PPCCTRL,
MMIO::ComplexRead<u32>([](Core::System&, u32) { return ctrl.ppc(); }),
mmio->Register(base | IPC_PPCCTRL, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
auto& wii_ipc = system.GetWiiIPC();
return wii_ipc.m_ctrl.ppc();
}),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
ctrl.ppc(val);
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_ctrl.ppc(val);
// The IPC interrupt is triggered when IY1/IY2 is set and
// Y1/Y2 is written to -- even when this results in clearing the bit.
if ((val >> 2 & 1 && ctrl.IY1) || (val >> 1 & 1 && ctrl.IY2))
ppc_irq_flags |= INT_CAUSE_IPC_BROADWAY;
if (ctrl.X1)
HLE::GetIOS()->EnqueueIPCRequest(ppc_msg);
if ((val >> 2 & 1 && wii_ipc.m_ctrl.IY1) || (val >> 1 & 1 && wii_ipc.m_ctrl.IY2))
wii_ipc.m_ppc_irq_flags |= INT_CAUSE_IPC_BROADWAY;
if (wii_ipc.m_ctrl.X1)
HLE::GetIOS()->EnqueueIPCRequest(wii_ipc.m_ppc_msg);
HLE::GetIOS()->UpdateIPC();
system.GetCoreTiming().ScheduleEvent(0, updateInterrupts, 0);
system.GetCoreTiming().ScheduleEvent(0, wii_ipc.m_event_type_update_interrupts,
0);
}));
mmio->Register(base | IPC_ARMMSG, MMIO::DirectRead<u32>(&arm_msg), MMIO::InvalidWrite<u32>());
mmio->Register(base | IPC_ARMMSG, MMIO::DirectRead<u32>(&m_arm_msg), MMIO::InvalidWrite<u32>());
mmio->Register(base | PPC_IRQFLAG, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
ppc_irq_flags &= ~val;
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_ppc_irq_flags &= ~val;
HLE::GetIOS()->UpdateIPC();
system.GetCoreTiming().ScheduleEvent(0, updateInterrupts, 0);
system.GetCoreTiming().ScheduleEvent(0, wii_ipc.m_event_type_update_interrupts,
0);
}));
mmio->Register(base | PPC_IRQMASK, MMIO::InvalidRead<u32>(),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
ppc_irq_masks = val;
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
Reset();
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_ppc_irq_masks = val;
if (wii_ipc.m_ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
wii_ipc.Reset();
HLE::GetIOS()->UpdateIPC();
system.GetCoreTiming().ScheduleEvent(0, updateInterrupts, 0);
system.GetCoreTiming().ScheduleEvent(0, wii_ipc.m_event_type_update_interrupts,
0);
}));
mmio->Register(base | GPIOB_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex),
mmio->Register(base | GPIOB_OUT, MMIO::DirectRead<u32>(&m_gpio_out.m_hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
g_gpio_out.m_hex =
(val & gpio_owner.m_hex) | (g_gpio_out.m_hex & ~gpio_owner.m_hex);
if (g_gpio_out[GPIO::DO_EJECT])
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_gpio_out.m_hex =
(val & gpio_owner.m_hex) | (wii_ipc.m_gpio_out.m_hex & ~gpio_owner.m_hex);
if (wii_ipc.m_gpio_out[GPIO::DO_EJECT])
{
INFO_LOG_FMT(WII_IPC, "Ejecting disc due to GPIO write");
system.GetDVDInterface().EjectDisc(DVD::EjectCause::Software);
@ -219,9 +179,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// SENSOR_BAR is checked by WiimoteEmu::CameraLogic
// TODO: AVE, SLOT_LED
}));
mmio->Register(base | GPIOB_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
gpio_dir.m_hex = (val & gpio_owner.m_hex) | (gpio_dir.m_hex & ~gpio_owner.m_hex);
mmio->Register(base | GPIOB_DIR, MMIO::DirectRead<u32>(&m_gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_gpio_dir.m_hex =
(val & gpio_owner.m_hex) | (wii_ipc.m_gpio_dir.m_hex & ~gpio_owner.m_hex);
}));
mmio->Register(base | GPIOB_IN, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
Common::Flags<GPIO> gpio_in;
@ -240,11 +202,12 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// Also: The HW_GPIO registers always have read access to all pins, but any writes (changes) must
// go through the HW_GPIOB registers if the corresponding bit is set in the HW_GPIO_OWNER
// register.
mmio->Register(base | GPIO_OUT, MMIO::DirectRead<u32>(&g_gpio_out.m_hex),
mmio->Register(base | GPIO_OUT, MMIO::DirectRead<u32>(&m_gpio_out.m_hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
g_gpio_out.m_hex =
(g_gpio_out.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex);
if (g_gpio_out[GPIO::DO_EJECT])
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_gpio_out.m_hex =
(wii_ipc.m_gpio_out.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex);
if (wii_ipc.m_gpio_out[GPIO::DO_EJECT])
{
INFO_LOG_FMT(WII_IPC, "Ejecting disc due to GPIO write");
system.GetDVDInterface().EjectDisc(DVD::EjectCause::Software);
@ -252,9 +215,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// SENSOR_BAR is checked by WiimoteEmu::CameraLogic
// TODO: AVE, SLOT_LED
}));
mmio->Register(base | GPIO_DIR, MMIO::DirectRead<u32>(&gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](Core::System&, u32, u32 val) {
gpio_dir.m_hex = (gpio_dir.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex);
mmio->Register(base | GPIO_DIR, MMIO::DirectRead<u32>(&m_gpio_dir.m_hex),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
auto& wii_ipc = system.GetWiiIPC();
wii_ipc.m_gpio_dir.m_hex =
(wii_ipc.m_gpio_dir.m_hex & gpio_owner.m_hex) | (val & ~gpio_owner.m_hex);
}));
mmio->Register(base | GPIO_IN, MMIO::ComplexRead<u32>([](Core::System& system, u32) {
Common::Flags<GPIO> gpio_in;
@ -263,15 +228,16 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}),
MMIO::Nop<u32>());
mmio->Register(base | HW_RESETS, MMIO::DirectRead<u32>(&resets),
mmio->Register(base | HW_RESETS, MMIO::DirectRead<u32>(&m_resets),
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
// A reset occurs when the corresponding bit is cleared
const bool di_reset_triggered = (resets & 0x400) && !(val & 0x400);
resets = val;
auto& wii_ipc = system.GetWiiIPC();
const bool di_reset_triggered = (wii_ipc.m_resets & 0x400) && !(val & 0x400);
wii_ipc.m_resets = val;
if (di_reset_triggered)
{
// The GPIO *disables* spinning up the drive
const bool spinup = !g_gpio_out[GPIO::DI_SPIN];
const bool spinup = !wii_ipc.m_gpio_out[GPIO::DI_SPIN];
INFO_LOG_FMT(WII_IPC, "Resetting DI {} spinup", spinup ? "with" : "without");
system.GetDVDInterface().ResetDrive(spinup);
}
@ -285,53 +251,59 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
mmio->Register(base | UNK_1D0, MMIO::Constant<u32>(0), MMIO::Nop<u32>());
}
static void UpdateInterrupts(Core::System& system, u64 userdata, s64 cyclesLate)
void WiiIPC::UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late)
{
if ((ctrl.Y1 & ctrl.IY1) || (ctrl.Y2 & ctrl.IY2))
{
ppc_irq_flags |= INT_CAUSE_IPC_BROADWAY;
system.GetWiiIPC().UpdateInterrupts();
}
if ((ctrl.X1 & ctrl.IX1) || (ctrl.X2 & ctrl.IX2))
void WiiIPC::UpdateInterrupts()
{
ppc_irq_flags |= INT_CAUSE_IPC_STARLET;
if ((m_ctrl.Y1 & m_ctrl.IY1) || (m_ctrl.Y2 & m_ctrl.IY2))
{
m_ppc_irq_flags |= INT_CAUSE_IPC_BROADWAY;
}
if ((m_ctrl.X1 & m_ctrl.IX1) || (m_ctrl.X2 & m_ctrl.IX2))
{
m_ppc_irq_flags |= INT_CAUSE_IPC_STARLET;
}
// Generate interrupt on PI if any of the devices behind starlet have an interrupt and mask is set
system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_WII_IPC,
!!(ppc_irq_flags & ppc_irq_masks));
m_system.GetProcessorInterface().SetInterrupt(ProcessorInterface::INT_CAUSE_WII_IPC,
!!(m_ppc_irq_flags & m_ppc_irq_masks));
}
void ClearX1()
void WiiIPC::ClearX1()
{
ctrl.X1 = 0;
m_ctrl.X1 = 0;
}
void GenerateAck(u32 address)
void WiiIPC::GenerateAck(u32 address)
{
ctrl.Y2 = 1;
DEBUG_LOG_FMT(WII_IPC, "GenerateAck: {:08x} | {:08x} [R:{} A:{} E:{}]", ppc_msg, address, ctrl.Y1,
ctrl.Y2, ctrl.X1);
m_ctrl.Y2 = 1;
DEBUG_LOG_FMT(WII_IPC, "GenerateAck: {:08x} | {:08x} [R:{} A:{} E:{}]", m_ppc_msg, address,
m_ctrl.Y1, m_ctrl.Y2, m_ctrl.X1);
// Based on a hardware test, the IPC interrupt takes approximately 100 TB ticks to fire
// after Y2 is seen in the control register.
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(100 * SystemTimers::TIMER_RATIO,
updateInterrupts);
m_system.GetCoreTiming().ScheduleEvent(100 * SystemTimers::TIMER_RATIO,
m_event_type_update_interrupts);
}
void GenerateReply(u32 address)
void WiiIPC::GenerateReply(u32 address)
{
arm_msg = address;
ctrl.Y1 = 1;
DEBUG_LOG_FMT(WII_IPC, "GenerateReply: {:08x} | {:08x} [R:{} A:{} E:{}]", ppc_msg, address,
ctrl.Y1, ctrl.Y2, ctrl.X1);
m_arm_msg = address;
m_ctrl.Y1 = 1;
DEBUG_LOG_FMT(WII_IPC, "GenerateReply: {:08x} | {:08x} [R:{} A:{} E:{}]", m_ppc_msg, address,
m_ctrl.Y1, m_ctrl.Y2, m_ctrl.X1);
// Based on a hardware test, the IPC interrupt takes approximately 100 TB ticks to fire
// after Y1 is seen in the control register.
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(100 * SystemTimers::TIMER_RATIO,
updateInterrupts);
m_system.GetCoreTiming().ScheduleEvent(100 * SystemTimers::TIMER_RATIO,
m_event_type_update_interrupts);
}
bool IsReady()
bool WiiIPC::IsReady() const
{
return ((ctrl.Y1 == 0) && (ctrl.Y2 == 0) && ((ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
return ((m_ctrl.Y1 == 0) && (m_ctrl.Y2 == 0) &&
((m_ppc_irq_flags & INT_CAUSE_IPC_BROADWAY) == 0));
}
} // namespace IOS

View File

@ -7,6 +7,14 @@
#include "Common/CommonTypes.h"
class PointerWrap;
namespace Core
{
class System;
}
namespace CoreTiming
{
struct EventType;
}
namespace MMIO
{
class Mapping;
@ -63,7 +71,54 @@ enum class GPIO : u32
DEBUG7 = 0x800000,
};
extern Common::Flags<GPIO> g_gpio_out;
struct CtrlRegister
{
u8 X1 : 1;
u8 X2 : 1;
u8 Y1 : 1;
u8 Y2 : 1;
u8 IX1 : 1;
u8 IX2 : 1;
u8 IY1 : 1;
u8 IY2 : 1;
CtrlRegister() { X1 = X2 = Y1 = Y2 = IX1 = IX2 = IY1 = IY2 = 0; }
inline u8 ppc() { return (IY2 << 5) | (IY1 << 4) | (X2 << 3) | (Y1 << 2) | (Y2 << 1) | X1; }
inline u8 arm() { return (IX2 << 5) | (IX1 << 4) | (Y2 << 3) | (X1 << 2) | (X2 << 1) | Y1; }
inline void ppc(u32 v)
{
X1 = v & 1;
X2 = (v >> 3) & 1;
if ((v >> 2) & 1)
Y1 = 0;
if ((v >> 1) & 1)
Y2 = 0;
IY1 = (v >> 4) & 1;
IY2 = (v >> 5) & 1;
}
inline void arm(u32 v)
{
Y1 = v & 1;
Y2 = (v >> 3) & 1;
if ((v >> 2) & 1)
X1 = 0;
if ((v >> 1) & 1)
X2 = 0;
IX1 = (v >> 4) & 1;
IX2 = (v >> 5) & 1;
}
};
class WiiIPC
{
public:
explicit WiiIPC(Core::System& system);
WiiIPC(const WiiIPC&) = delete;
WiiIPC(WiiIPC&&) = delete;
WiiIPC& operator=(const WiiIPC&) = delete;
WiiIPC& operator=(WiiIPC&&) = delete;
~WiiIPC();
void Init();
void Reset();
@ -76,5 +131,32 @@ void ClearX1();
void GenerateAck(u32 address);
void GenerateReply(u32 address);
bool IsReady();
bool IsReady() const;
Common::Flags<GPIO> GetGPIOOutFlags() const { return m_gpio_out; }
private:
void InitState();
static void UpdateInterruptsCallback(Core::System& system, u64 userdata, s64 cycles_late);
void UpdateInterrupts();
u32 m_ppc_msg = 0;
u32 m_arm_msg = 0;
CtrlRegister m_ctrl{};
u32 m_ppc_irq_flags = 0;
u32 m_ppc_irq_masks = 0;
u32 m_arm_irq_flags = 0;
u32 m_arm_irq_masks = 0;
Common::Flags<GPIO> m_gpio_dir{};
Common::Flags<GPIO> m_gpio_out{};
u32 m_resets = 0;
CoreTiming::EventType* m_event_type_update_interrupts = nullptr;
Core::System& m_system;
};
} // namespace IOS

View File

@ -234,7 +234,6 @@ public:
{
}
protected:
EmulationKernel& GetEmulationKernel() const { return static_cast<EmulationKernel&>(m_ios); }
Core::System& GetSystem() const { return GetEmulationKernel().GetSystem(); }

View File

@ -539,7 +539,7 @@ void EmulationKernel::InitIPC()
return;
INFO_LOG_FMT(IOS, "IPC initialised.");
GenerateAck(0);
m_system.GetWiiIPC().GenerateAck(0);
}
void EmulationKernel::AddDevice(std::unique_ptr<Device> device)
@ -816,13 +816,14 @@ void EmulationKernel::HandleIPCEvent(u64 userdata)
void EmulationKernel::UpdateIPC()
{
if (m_ipc_paused || !IsReady())
auto& wii_ipc = m_system.GetWiiIPC();
if (m_ipc_paused || !wii_ipc.IsReady())
return;
if (!m_request_queue.empty())
{
ClearX1();
GenerateAck(m_request_queue.front());
wii_ipc.ClearX1();
wii_ipc.GenerateAck(m_request_queue.front());
u32 command = m_request_queue.front();
m_request_queue.pop_front();
ExecuteIPCCommand(command);
@ -831,7 +832,7 @@ void EmulationKernel::UpdateIPC()
if (!m_reply_queue.empty())
{
GenerateReply(m_reply_queue.front());
wii_ipc.GenerateReply(m_reply_queue.front());
DEBUG_LOG_FMT(IOS, "<<-- Reply to IPC Request @ {:#010x}", m_reply_queue.front());
m_reply_queue.pop_front();
return;

View File

@ -27,6 +27,7 @@
#include "Core/IOS/USB/Bluetooth/BTEmu.h"
#include "Core/IOS/USB/Bluetooth/WiimoteHIDAttr.h"
#include "Core/IOS/USB/Bluetooth/l2cap.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -368,8 +369,9 @@ WiimoteDevice::PrepareInput(WiimoteEmu::DesiredWiimoteState* wiimote_state)
const auto* channel = FindChannelWithPSM(L2CAP_PSM_HID_INTR);
if (channel && channel->IsComplete())
{
auto gpio_out = m_host->GetSystem().GetWiiIPC().GetGPIOOutFlags();
m_hid_source->PrepareInput(wiimote_state,
IOS::g_gpio_out[IOS::GPIO::SENSOR_BAR] ?
gpio_out[IOS::GPIO::SENSOR_BAR] ?
WiimoteCommon::HIDWiimote::SensorBarState::Enabled :
WiimoteCommon::HIDWiimote::SensorBarState::Disabled);
return NextUpdateInputCall::Update;

View File

@ -24,6 +24,7 @@
#include "Core/HW/Sram.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "Core/HW/WII_IPC.h"
#include "Core/PowerPC/Interpreter/Interpreter.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
@ -45,7 +46,7 @@ struct System::Impl
explicit Impl(System& system)
: m_audio_interface(system), m_core_timing(system), m_command_processor{system},
m_cpu(system), m_dsp(system), m_dvd_interface(system), m_dvd_thread(system),
m_expansion_interface(system), m_fifo{system}, m_gp_fifo(system),
m_expansion_interface(system), m_fifo{system}, m_gp_fifo(system), m_wii_ipc(system),
m_memory(system), m_pixel_engine{system}, m_power_pc(system),
m_mmu(system, m_memory, m_power_pc), m_processor_interface(system),
m_serial_interface(system), m_system_timers(system), m_video_interface(system),
@ -72,6 +73,7 @@ struct System::Impl
HSP::HSPManager m_hsp;
IOS::HLE::USB::InfinityBase m_infinity_base;
IOS::HLE::USB::SkylanderPortal m_skylander_portal;
IOS::WiiIPC m_wii_ipc;
Memory::MemoryManager m_memory;
MemoryInterface::MemoryInterfaceManager m_memory_interface;
PixelEngine::PixelEngineManager m_pixel_engine;
@ -219,6 +221,11 @@ IOS::HLE::USB::InfinityBase& System::GetInfinityBase() const
return m_impl->m_infinity_base;
}
IOS::WiiIPC& System::GetWiiIPC() const
{
return m_impl->m_wii_ipc;
}
Memory::MemoryManager& System::GetMemory() const
{
return m_impl->m_memory;

View File

@ -56,6 +56,10 @@ namespace HSP
{
class HSPManager;
}
namespace IOS
{
class WiiIPC;
}
namespace IOS::HLE::USB
{
class SkylanderPortal;
@ -151,6 +155,7 @@ public:
JitInterface& GetJitInterface() const;
IOS::HLE::USB::SkylanderPortal& GetSkylanderPortal() const;
IOS::HLE::USB::InfinityBase& GetInfinityBase() const;
IOS::WiiIPC& GetWiiIPC() const;
Memory::MemoryManager& GetMemory() const;
MemoryInterface::MemoryInterfaceManager& GetMemoryInterface() const;
PowerPC::MMU& GetMMU() const;