diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp index 423f373337..89b200bad4 100644 --- a/Source/Core/Core/HW/SI/SI.cpp +++ b/Source/Core/Core/HW/SI/SI.cpp @@ -59,6 +59,12 @@ SerialInterfaceManager::SerialInterfaceManager(Core::System& system) : m_system( SerialInterfaceManager::~SerialInterfaceManager() = default; +static constexpr u32 GetRDSTBit(u32 channel) +{ + // Returns bit for RDST0,1,2,3 + return 0x20000000 >> (channel * 8); +} + void SerialInterfaceManager::SetNoResponse(u32 channel) { // raise the NO RESPONSE error @@ -357,27 +363,23 @@ void SerialInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base) for (u32 i = 0; i < u32(MAX_SI_CHANNELS); ++i) { // We need to clear the RDST bit for the SI channel when reading. - // CH0 -> Bit 24 + 5 - // CH1 -> Bit 16 + 5 - // CH2 -> Bit 8 + 5 - // CH3 -> Bit 0 + 5 - const u32 rdst_bit = 8 * (3 - i) + 5; + const u32 clear_rdst = ~GetRDSTBit(i); mmio->Register(base | (SI_CHANNEL_0_OUT + 0xC * i), MMIO::DirectRead(&m_channel[i].out.hex), MMIO::DirectWrite(&m_channel[i].out.hex)); mmio->Register(base | (SI_CHANNEL_0_IN_HI + 0xC * i), - MMIO::ComplexRead([i, rdst_bit](Core::System& system, u32) { + MMIO::ComplexRead([i, clear_rdst](Core::System& system, u32) { auto& si = system.GetSerialInterface(); - si.m_status_reg.hex &= ~(1U << rdst_bit); + si.m_status_reg.hex &= clear_rdst; si.UpdateInterrupts(); return si.m_channel[i].in_hi.hex; }), MMIO::DirectWrite(&m_channel[i].in_hi.hex)); mmio->Register(base | (SI_CHANNEL_0_IN_LO + 0xC * i), - MMIO::ComplexRead([i, rdst_bit](Core::System& system, u32) { + MMIO::ComplexRead([i, clear_rdst](Core::System& system, u32) { auto& si = system.GetSerialInterface(); - si.m_status_reg.hex &= ~(1U << rdst_bit); + si.m_status_reg.hex &= clear_rdst; si.UpdateInterrupts(); return si.m_channel[i].in_lo.hex; }), @@ -554,14 +556,23 @@ void SerialInterfaceManager::UpdateDevices() g_controller_interface.UpdateInput(); // Update channels and set the status bit if there's new data - m_status_reg.RDST0 = - !!m_channel[0].device->GetData(m_channel[0].in_hi.hex, m_channel[0].in_lo.hex); - m_status_reg.RDST1 = - !!m_channel[1].device->GetData(m_channel[1].in_hi.hex, m_channel[1].in_lo.hex); - m_status_reg.RDST2 = - !!m_channel[2].device->GetData(m_channel[2].in_hi.hex, m_channel[2].in_lo.hex); - m_status_reg.RDST3 = - !!m_channel[3].device->GetData(m_channel[3].in_hi.hex, m_channel[3].in_lo.hex); + for (u32 i = 0; i != MAX_SI_CHANNELS; ++i) + { + // ERRLATCH bit is maintained. + u32 errlatch = m_channel[i].in_hi.ERRLATCH.Value(); + if (m_channel[i].device->GetData(m_channel[i].in_hi.hex, m_channel[i].in_lo.hex)) + { + m_status_reg.hex |= GetRDSTBit(i); + } + else + { + errlatch = 1; + m_channel[i].in_hi.ERRSTAT = 1; + SetNoResponse(i); + } + + m_channel[i].in_hi.ERRLATCH = errlatch; + } UpdateInterrupts(); diff --git a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp index f8150a6339..f3867cf1fc 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceGCController.cpp @@ -175,10 +175,7 @@ bool CSIDevice_GCController::GetData(u32& hi, u32& low) GCPadStatus pad_status = GetPadStatus(); if (!pad_status.isConnected) - { - hi = 0x80000000; - return true; - } + return false; if (HandleButtonCombos(pad_status) == COMBO_ORIGIN) pad_status.button |= PAD_GET_ORIGIN; diff --git a/Source/Core/Core/HW/SI/SI_DeviceNull.cpp b/Source/Core/Core/HW/SI/SI_DeviceNull.cpp index e7d7afd836..076765fd3c 100644 --- a/Source/Core/Core/HW/SI/SI_DeviceNull.cpp +++ b/Source/Core/Core/HW/SI/SI_DeviceNull.cpp @@ -17,8 +17,7 @@ int CSIDevice_Null::RunBuffer(u8* buffer, int request_length) bool CSIDevice_Null::GetData(u32& hi, u32& low) { - hi = 0x80000000; - return true; + return false; } void CSIDevice_Null::SendCommand(u32 command, u8 poll)