diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h index 6b57568f9a..02313ac048 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteConstants.h @@ -38,14 +38,14 @@ enum class OutputReportID : u8 Rumble = 0x10, LED = 0x11, ReportMode = 0x12, - IRPixelClock = 0x13, + IRLogicEnable = 0x13, SpeakerEnable = 0x14, RequestStatus = 0x15, WriteData = 0x16, ReadData = 0x17, SpeakerData = 0x18, SpeakerMute = 0x19, - IRLogic = 0x1a, + IRLogicEnable2 = 0x1a, }; enum class LED : u8 diff --git a/Source/Core/Core/HW/WiimoteEmu/Camera.cpp b/Source/Core/Core/HW/WiimoteEmu/Camera.cpp index 93b587c0be..7dc11622e9 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Camera.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Camera.cpp @@ -16,11 +16,15 @@ namespace WiimoteEmu void CameraLogic::Reset() { reg_data = {}; + + m_is_enabled = false; } void CameraLogic::DoState(PointerWrap& p) { p.Do(reg_data); + + // FYI: m_is_enabled is handled elsewhere. } int CameraLogic::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) @@ -28,6 +32,9 @@ int CameraLogic::BusRead(u8 slave_addr, u8 addr, int count, u8* data_out) if (I2C_ADDR != slave_addr) return 0; + if (!m_is_enabled) + return 0; + return RawRead(®_data, addr, count, data_out); } @@ -36,6 +43,9 @@ int CameraLogic::BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) if (I2C_ADDR != slave_addr) return 0; + if (!m_is_enabled) + return 0; + return RawWrite(®_data, addr, count, data_in); } @@ -201,4 +211,9 @@ void CameraLogic::Update(const ControllerEmu::Cursor::StateData& cursor, } } +void CameraLogic::SetEnabled(bool is_enabled) +{ + m_is_enabled = is_enabled; +} + } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/Camera.h b/Source/Core/Core/HW/WiimoteEmu/Camera.h index b42dddd6b9..bd2e4e2a3c 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Camera.h +++ b/Source/Core/Core/HW/WiimoteEmu/Camera.h @@ -68,6 +68,7 @@ public: void DoState(PointerWrap& p); void Update(const ControllerEmu::Cursor::StateData& cursor, const NormalizedAccelData& accel, bool sensor_bar_on_top); + void SetEnabled(bool is_enabled); static constexpr u8 I2C_ADDR = 0x58; @@ -100,5 +101,9 @@ private: int BusWrite(u8 slave_addr, u8 addr, int count, const u8* data_in) override; Register reg_data; + + // When disabled the camera does not respond on the bus. + // Change is triggered by wiimote report 0x13. + bool m_is_enabled; }; } // namespace WiimoteEmu diff --git a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp index 354a748b8f..07c61b9bee 100644 --- a/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/EmuSubroutines.cpp @@ -101,8 +101,8 @@ void Wiimote::HIDOutputReport(const void* data, u32 size) case OutputReportID::ReportMode: InvokeHandler(&Wiimote::HandleReportMode, rpt, rpt_size); break; - case OutputReportID::IRPixelClock: - InvokeHandler(&Wiimote::HandleIRPixelClock, rpt, rpt_size); + case OutputReportID::IRLogicEnable: + InvokeHandler(&Wiimote::HandleIRLogicEnable, rpt, rpt_size); break; case OutputReportID::SpeakerEnable: InvokeHandler(&Wiimote::HandleSpeakerEnable, rpt, rpt_size); @@ -122,8 +122,8 @@ void Wiimote::HIDOutputReport(const void* data, u32 size) case OutputReportID::SpeakerMute: InvokeHandler(&Wiimote::HandleSpeakerMute, rpt, rpt_size); break; - case OutputReportID::IRLogic: - InvokeHandler(&Wiimote::HandleIRLogic, rpt, rpt_size); + case OutputReportID::IRLogicEnable2: + InvokeHandler(&Wiimote::HandleIRLogicEnable2, rpt, rpt_size); break; default: PanicAlert("HidOutputReport: Unknown report ID 0x%02x", int(rpt.rpt_id)); @@ -342,24 +342,26 @@ void Wiimote::HandleReportLeds(const WiimoteCommon::OutputReportLeds& rpt) SendAck(OutputReportID::LED, ErrorCode::Success); } -void Wiimote::HandleIRPixelClock(const WiimoteCommon::OutputReportEnableFeature& rpt) +void Wiimote::HandleIRLogicEnable2(const WiimoteCommon::OutputReportEnableFeature& rpt) { - // INFO_LOG(WIIMOTE, "WM IR Clock: %02x", erpt.enable); - - // FYI: Camera data is currently always updated. Ignoring pixel clock status. + // FYI: We ignore this and update camera data regardless. if (rpt.ack) - SendAck(OutputReportID::IRPixelClock, ErrorCode::Success); + SendAck(OutputReportID::IRLogicEnable2, ErrorCode::Success); } -void Wiimote::HandleIRLogic(const WiimoteCommon::OutputReportEnableFeature& rpt) +void Wiimote::HandleIRLogicEnable(const WiimoteCommon::OutputReportEnableFeature& rpt) { - // FYI: Camera data is currently always updated. We just save this for status reports. + // Note: Wiibrew currently refers to this report (0x13) as "Enable IR Pixel Clock" + // however my testing shows this affects the relevant status bit and whether or not + // the camera responds on the I2C bus. m_status.ir = rpt.enable; + m_camera_logic.SetEnabled(m_status.ir); + if (rpt.ack) - SendAck(OutputReportID::IRLogic, ErrorCode::Success); + SendAck(OutputReportID::IRLogicEnable, ErrorCode::Success); } void Wiimote::HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature& rpt) @@ -372,7 +374,6 @@ void Wiimote::HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature& void Wiimote::HandleSpeakerEnable(const WiimoteCommon::OutputReportEnableFeature& rpt) { - // INFO_LOG(WIIMOTE, "WM Speaker Enable: %02x", erpt.enable); m_status.speaker = rpt.enable; if (rpt.ack) @@ -567,6 +568,9 @@ void Wiimote::DoState(PointerWrap& p) m_speaker_logic.DoState(p); m_camera_logic.DoState(p); + if (p.GetMode() == PointerWrap::MODE_READ) + m_camera_logic.SetEnabled(m_status.ir); + p.Do(m_is_motion_plus_attached); p.Do(m_active_extension); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index e050226d09..6e31340c3a 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -445,13 +445,6 @@ void Wiimote::SendDataReport() const auto cursor = m_ir->GetState(true); m_camera_logic.Update(cursor, norm_accel, m_sensor_bar_on_top); - if (!m_status.ir) - { - // TODO: What does a real wiimote send in this case? 0xFFs ? - // I'm assuming it still reads from the bus? - DEBUG_LOG(WIIMOTE, "Game is reading IR data without enabling IR logic first."); - } - // The real wiimote reads camera data from the i2c bus starting at offset 0x37: const u8 camera_data_offset = CameraLogic::REPORT_DATA_OFFSET + rpt_builder.GetIRDataFormatOffset(); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index cfc9054d18..09b918ca9d 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -156,8 +156,8 @@ private: void HandleRequestStatus(const WiimoteCommon::OutputReportRequestStatus&); void HandleReadData(const WiimoteCommon::OutputReportReadData&); void HandleWriteData(const WiimoteCommon::OutputReportWriteData&); - void HandleIRPixelClock(const WiimoteCommon::OutputReportEnableFeature&); - void HandleIRLogic(const WiimoteCommon::OutputReportEnableFeature&); + void HandleIRLogicEnable(const WiimoteCommon::OutputReportEnableFeature&); + void HandleIRLogicEnable2(const WiimoteCommon::OutputReportEnableFeature&); void HandleSpeakerMute(const WiimoteCommon::OutputReportEnableFeature&); void HandleSpeakerEnable(const WiimoteCommon::OutputReportEnableFeature&); void HandleSpeakerData(const WiimoteCommon::OutputReportSpeakerData&);