// Copyright 2010 Dolphin Emulator Project // Licensed under GPLv2+ // Refer to the license.txt file included. #include "Core/HW/Wiimote.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/IOS/IOS.h" #include "Core/IOS/USB/Bluetooth/BTEmu.h" #include "Core/IOS/USB/Bluetooth/WiimoteDevice.h" #include "Core/Movie.h" #include "Core/NetPlayClient.h" #include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h" #include "InputCommon/InputConfig.h" // Limit the amount of wiimote connect requests, when a button is pressed in disconnected state static std::array s_last_connect_request_counter; namespace WiimoteCommon { static std::array, MAX_BBMOTES> s_wiimote_sources; WiimoteSource GetSource(unsigned int index) { return s_wiimote_sources[index]; } void SetSource(unsigned int index, WiimoteSource source) { const WiimoteSource previous_source = s_wiimote_sources[index].exchange(source); if (previous_source == source) { // No change. Do nothing. return; } WiimoteReal::HandleWiimoteSourceChange(index); Core::RunAsCPUThread([index] { UpdateSource(index); }); } void UpdateSource(unsigned int index) { const auto ios = IOS::HLE::GetIOS(); if (!ios) return; if (s_wiimote_sources[index] != WiimoteSource::Emulated) return; const auto bluetooth = std::static_pointer_cast( ios->GetDeviceByName("/dev/usb/oh1/57e/305")); if (!bluetooth) return; bluetooth->AccessWiimoteByIndex(index)->SetSource(GetHIDWiimoteSource(index)); } HIDWiimote* GetHIDWiimoteSource(unsigned int index) { HIDWiimote* hid_source = nullptr; switch (GetSource(index)) { case WiimoteSource::Emulated: hid_source = static_cast(::Wiimote::GetConfig()->GetController(index)); break; case WiimoteSource::Real: hid_source = WiimoteReal::g_wiimotes[index].get(); break; default: break; } return hid_source; } } // namespace WiimoteCommon namespace Wiimote { static InputConfig s_config(WIIMOTE_INI_NAME, _trans("Wii Remote"), "Wiimote"); InputConfig* GetConfig() { return &s_config; } ControllerEmu::ControlGroup* GetWiimoteGroup(int number, WiimoteEmu::WiimoteGroup group) { return static_cast(s_config.GetController(number))->GetWiimoteGroup(group); } ControllerEmu::ControlGroup* GetNunchukGroup(int number, WiimoteEmu::NunchukGroup group) { return static_cast(s_config.GetController(number))->GetNunchukGroup(group); } ControllerEmu::ControlGroup* GetClassicGroup(int number, WiimoteEmu::ClassicGroup group) { return static_cast(s_config.GetController(number))->GetClassicGroup(group); } ControllerEmu::ControlGroup* GetGuitarGroup(int number, WiimoteEmu::GuitarGroup group) { return static_cast(s_config.GetController(number))->GetGuitarGroup(group); } ControllerEmu::ControlGroup* GetDrumsGroup(int number, WiimoteEmu::DrumsGroup group) { return static_cast(s_config.GetController(number))->GetDrumsGroup(group); } ControllerEmu::ControlGroup* GetTurntableGroup(int number, WiimoteEmu::TurntableGroup group) { return static_cast(s_config.GetController(number)) ->GetTurntableGroup(group); } ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTabletGroup group) { return static_cast(s_config.GetController(number)) ->GetUDrawTabletGroup(group); } ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number, WiimoteEmu::DrawsomeTabletGroup group) { return static_cast(s_config.GetController(number)) ->GetDrawsomeTabletGroup(group); } ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group) { return static_cast(s_config.GetController(number))->GetTaTaConGroup(group); } void Shutdown() { s_config.UnregisterHotplugCallback(); s_config.ClearControllers(); WiimoteReal::Stop(); } void Initialize(InitializeMode init_mode) { if (s_config.ControllersNeedToBeCreated()) { for (unsigned int i = WIIMOTE_CHAN_0; i < MAX_BBMOTES; ++i) s_config.CreateController(i); } s_config.RegisterHotplugCallback(); LoadConfig(); WiimoteReal::Initialize(init_mode); // Reload Wiimotes with our settings if (Movie::IsMovieActive()) Movie::ChangeWiiPads(); } void ResetAllWiimotes() { for (int i = WIIMOTE_CHAN_0; i < MAX_BBMOTES; ++i) static_cast(s_config.GetController(i))->Reset(); } void LoadConfig() { s_config.LoadConfig(false); s_last_connect_request_counter.fill(0); } void Resume() { WiimoteReal::Resume(); } void Pause() { WiimoteReal::Pause(); } void DoState(PointerWrap& p) { for (int i = 0; i < MAX_BBMOTES; ++i) { const WiimoteSource source = WiimoteCommon::GetSource(i); auto state_wiimote_source = u8(source); p.Do(state_wiimote_source); if (WiimoteSource(state_wiimote_source) == WiimoteSource::Emulated) { // Sync complete state of emulated wiimotes. static_cast(s_config.GetController(i))->DoState(p); } if (p.GetMode() == PointerWrap::MODE_READ) { // If using a real wiimote or the save-state source does not match the current source, // then force a reconnection on load. if (source == WiimoteSource::Real || source != WiimoteSource(state_wiimote_source)) WiimoteCommon::UpdateSource(i); } } } } // namespace Wiimote