From e462422ef7c99d752dd3505044fbc9c43969a071 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Wed, 8 Jul 2015 04:10:18 +0200 Subject: [PATCH 1/3] Wiimote: (Re-)Connect a disconnected emulated Wiimote when a mapped button is pressed. --- Source/Core/Core/HW/Wiimote.cpp | 22 +++++++++---------- Source/Core/Core/HW/Wiimote.h | 2 +- Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp | 22 +++++++++++++++++++ Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h | 5 +++++ .../Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 7 +++--- 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/Source/Core/Core/HW/Wiimote.cpp b/Source/Core/Core/HW/Wiimote.cpp index 378cc6f52f..a49689dd4e 100644 --- a/Source/Core/Core/HW/Wiimote.cpp +++ b/Source/Core/Core/HW/Wiimote.cpp @@ -114,22 +114,20 @@ void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size // input: _number: [Description needed] // output: none // -void Update(int _number) +void Update(int _number, bool _connected) { - //PanicAlert( "Wiimote_Update" ); - - // if we are on the next input cycle, update output and input - static int _last_number = 4; - if (_number <= _last_number) + if (_connected) { - g_controller_interface.UpdateInput(); + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) + ((WiimoteEmu::Wiimote*)s_config.controllers[_number])->Update(); + else + WiimoteReal::Update(_number); } - _last_number = _number; - - if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) - ((WiimoteEmu::Wiimote*)s_config.controllers[_number])->Update(); else - WiimoteReal::Update(_number); + { + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) + ((WiimoteEmu::Wiimote*)s_config.controllers[_number])->ConnectOnInput(); + } } // __________________________________________________________________________________________________ diff --git a/Source/Core/Core/HW/Wiimote.h b/Source/Core/Core/HW/Wiimote.h index 4d64f902b3..051d7cc3e8 100644 --- a/Source/Core/Core/HW/Wiimote.h +++ b/Source/Core/Core/HW/Wiimote.h @@ -48,7 +48,7 @@ InputConfig* GetConfig(); void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size); void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size); -void Update(int _number); +void Update(int _number, bool _connected); } diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 1d54096bc0..2744cd3156 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -249,6 +249,7 @@ void Wiimote::Reset() Wiimote::Wiimote( const unsigned int index ) : m_index(index) + , m_last_connect_request_counter(0) , ir_sin(0) , ir_cos(1) // , m_sound_stream( nullptr ) @@ -876,6 +877,27 @@ void Wiimote::InterruptChannel(const u16 _channelID, const void* _pData, u32 _Si } } +void Wiimote::ConnectOnInput() +{ + if (m_last_connect_request_counter > 0) + { + --m_last_connect_request_counter; + return; + } + + u16 buttons = 0; + m_buttons->GetState(&buttons, button_bitmasks); + m_dpad->GetState(&buttons, dpad_bitmasks); + + if (buttons != 0) + { + Host_ConnectWiimote(m_index, true); + // arbitrary value so it doesn't try to send multiple requests before Dolphin can react + // if Wiimotes are polled at 200Hz then this results in one request being sent per 500ms + m_last_connect_request_counter = 100; + } +} + void Wiimote::LoadDefaults(const ControllerInterface& ciface) { ControllerEmu::LoadDefaults(ciface); diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h index f0ce9a5e38..a62d2919cd 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.h @@ -121,6 +121,7 @@ public: void Update(); void InterruptChannel(const u16 _channelID, const void* _pData, u32 _Size); void ControlChannel(const u16 _channelID, const void* _pData, u32 _Size); + void ConnectOnInput(); void DoState(PointerWrap& p); void RealState(); @@ -239,6 +240,10 @@ private: u8 play; u8 unk_9; } m_reg_speaker; + + // limits the amount of connect requests we send when a button is pressed in disconnected state + u8 m_last_connect_request_counter; + #pragma pack(pop) }; diff --git a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index bfd90e4652..9cf809afdd 100644 --- a/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -15,6 +15,7 @@ #include "Core/IPC_HLE/WII_IPC_HLE.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "Core/IPC_HLE/WII_IPC_HLE_WiiMote.h" +#include "InputCommon/ControllerInterface/ControllerInterface.h" void CWII_IPC_HLE_Device_usb_oh1_57e_305::EnqueueReply(u32 CommandAddress) @@ -490,11 +491,9 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() if (now - m_last_ticks > interval) { + g_controller_interface.UpdateInput(); for (unsigned int i = 0; i < m_WiiMotes.size(); i++) - if (m_WiiMotes[i].IsConnected()) - { - Wiimote::Update(i); - } + Wiimote::Update(i, m_WiiMotes[i].IsConnected()); m_last_ticks = now; } From 5594b107eb4e43ab4f0c3466bf531cb0a3112f2b Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Fri, 10 Jul 2015 18:16:55 +0200 Subject: [PATCH 2/3] Wiimote: (Re-)Connect a disconnected real Wiimote when a button is pressed. Where disconnected is defined as: The real physical device is still connected to the PC, but the emulated Wii sees the Wiimote as disconnected. --- Source/Core/Core/HW/Wiimote.cpp | 2 + .../Core/Core/HW/WiimoteReal/WiimoteReal.cpp | 50 +++++++++++++++++++ Source/Core/Core/HW/WiimoteReal/WiimoteReal.h | 3 ++ 3 files changed, 55 insertions(+) diff --git a/Source/Core/Core/HW/Wiimote.cpp b/Source/Core/Core/HW/Wiimote.cpp index a49689dd4e..2c6cc4ec8d 100644 --- a/Source/Core/Core/HW/Wiimote.cpp +++ b/Source/Core/Core/HW/Wiimote.cpp @@ -127,6 +127,8 @@ void Update(int _number, bool _connected) { if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) ((WiimoteEmu::Wiimote*)s_config.controllers[_number])->ConnectOnInput(); + if (WIIMOTE_SRC_REAL & g_wiimote_sources[_number]) + WiimoteReal::ConnectOnInput(_number); } } diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp index ab8dcc8460..7dc4b86f04 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.cpp @@ -41,6 +41,7 @@ Wiimote::Wiimote() : m_index() , m_last_input_report() , m_channel(0) + , m_last_connect_request_counter(0) , m_rumble_state() , m_need_prepare() {} @@ -299,6 +300,43 @@ void Wiimote::Update() } } +void Wiimote::ConnectOnInput() +{ + if (m_last_connect_request_counter > 0) + { + --m_last_connect_request_counter; + return; + } + + const Report& rpt = ProcessReadQueue(); + if (rpt.size() >= 4) + { + switch (rpt[1]) + { + case WM_REPORT_CORE: + case WM_REPORT_CORE_ACCEL: + case WM_REPORT_CORE_EXT8: + case WM_REPORT_CORE_ACCEL_IR12: + case WM_REPORT_CORE_EXT19: + case WM_REPORT_CORE_ACCEL_EXT16: + case WM_REPORT_CORE_IR10_EXT9: + case WM_REPORT_CORE_ACCEL_IR10_EXT6: + case WM_REPORT_INTERLEAVE1: + case WM_REPORT_INTERLEAVE2: + // check any button without checking accelerometer data + if ((rpt[2] & 0x1F) != 0 || (rpt[3] & 0x9F) != 0) + { + Host_ConnectWiimote(m_index, true); + // see WiimoteEmu::Wiimote::ConnectOnInput(), same idea here + m_last_connect_request_counter = 100; + } + break; + default: + break; + } + } +} + void Wiimote::Prepare(int _index) { m_index = _index; @@ -847,6 +885,18 @@ void Update(int _WiimoteNumber) g_refresh_lock.unlock(); } +void ConnectOnInput(int _WiimoteNumber) +{ + // see Update() above + if (!g_refresh_lock.try_lock()) + return; + + if (g_wiimotes[_WiimoteNumber]) + g_wiimotes[_WiimoteNumber]->ConnectOnInput(); + + g_refresh_lock.unlock(); +} + void StateChange(EMUSTATE_CHANGE newState) { //std::lock_guard lk(g_refresh_lock); diff --git a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h index 2047314392..9c8b5f1815 100644 --- a/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/HW/WiimoteReal/WiimoteReal.h @@ -36,6 +36,7 @@ public: void ControlChannel(const u16 channel, const void* const data, const u32 size); void InterruptChannel(const u16 channel, const void* const data, const u32 size); void Update(); + void ConnectOnInput(); const Report& ProcessReadQueue(); @@ -80,6 +81,7 @@ protected: Wiimote(); Report m_last_input_report; u16 m_channel; + u8 m_last_connect_request_counter; private: void ClearReadQueue(); @@ -154,6 +156,7 @@ extern Wiimote *g_wiimotes[MAX_BBMOTES]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); void Update(int _WiimoteNumber); +void ConnectOnInput(int _WiimoteNumber); void DoState(PointerWrap &p); void StateChange(EMUSTATE_CHANGE newState); From 935292c6fcc99d6a10126cfb4b2acaa2d29974e5 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Thu, 16 Jul 2015 02:00:56 +0200 Subject: [PATCH 3/3] DolphinWX: In Host_ConnectWiimote(), instead of calling CFrame::ConnectWiimote() directly, dispatch an event that will call it for us in the GUI thread. This eliminates a possible stutter/short freeze that can happen during PowerPC::Pause(). --- Source/Core/DolphinWX/Frame.cpp | 16 ++++++++++++++++ Source/Core/DolphinWX/Globals.h | 12 ++++++++++++ Source/Core/DolphinWX/Main.cpp | 11 ++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index 759c2bdc6e..e58a8c4ce1 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -776,6 +776,22 @@ void CFrame::OnHostMessage(wxCommandEvent& event) case IDM_STOPPED: OnStopped(); break; + + case IDM_FORCE_CONNECT_WIIMOTE1: + case IDM_FORCE_CONNECT_WIIMOTE2: + case IDM_FORCE_CONNECT_WIIMOTE3: + case IDM_FORCE_CONNECT_WIIMOTE4: + case IDM_FORCE_CONNECT_BALANCEBOARD: + ConnectWiimote(event.GetId() - IDM_FORCE_CONNECT_WIIMOTE1, true); + break; + + case IDM_FORCE_DISCONNECT_WIIMOTE1: + case IDM_FORCE_DISCONNECT_WIIMOTE2: + case IDM_FORCE_DISCONNECT_WIIMOTE3: + case IDM_FORCE_DISCONNECT_WIIMOTE4: + case IDM_FORCE_DISCONNECT_BALANCEBOARD: + ConnectWiimote(event.GetId() - IDM_FORCE_DISCONNECT_WIIMOTE1, false); + break; } } diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index 2b327b0fad..cd3a981e07 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -298,6 +298,18 @@ enum IDM_HOST_MESSAGE, IDM_FULLSCREEN_REQUEST, + // Used for Host_ConnectWiimote() + IDM_FORCE_CONNECT_WIIMOTE1, + IDM_FORCE_CONNECT_WIIMOTE2, + IDM_FORCE_CONNECT_WIIMOTE3, + IDM_FORCE_CONNECT_WIIMOTE4, + IDM_FORCE_CONNECT_BALANCEBOARD, + IDM_FORCE_DISCONNECT_WIIMOTE1, + IDM_FORCE_DISCONNECT_WIIMOTE2, + IDM_FORCE_DISCONNECT_WIIMOTE3, + IDM_FORCE_DISCONNECT_WIIMOTE4, + IDM_FORCE_DISCONNECT_BALANCEBOARD, + IDM_MPANEL, ID_STATUSBAR, IDM_FREELOOK_DECREASE_SPEED, diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp index 59de81fff6..194ca7b566 100644 --- a/Source/Core/DolphinWX/Main.cpp +++ b/Source/Core/DolphinWX/Main.cpp @@ -540,7 +540,16 @@ bool Host_RendererIsFullscreen() void Host_ConnectWiimote(int wm_idx, bool connect) { - CFrame::ConnectWiimote(wm_idx, connect); + if (connect) + { + wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_FORCE_CONNECT_WIIMOTE1 + wm_idx); + main_frame->GetEventHandler()->AddPendingEvent(event); + } + else + { + wxCommandEvent event(wxEVT_HOST_COMMAND, IDM_FORCE_DISCONNECT_WIIMOTE1 + wm_idx); + main_frame->GetEventHandler()->AddPendingEvent(event); + } } void Host_ShowVideoConfig(void* parent, const std::string& backend_name,