mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-26 23:59:54 -06:00
245 lines
6.3 KiB
C++
245 lines
6.3 KiB
C++
// Copyright 2010 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "Core/HW/Wiimote.h"
|
|
|
|
#include <optional>
|
|
|
|
#include "Common/ChunkFile.h"
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/Config/Config.h"
|
|
|
|
#include "Core/Config/WiimoteSettings.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 "Core/WiiUtils.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<u8, MAX_BBMOTES> s_last_connect_request_counter;
|
|
|
|
namespace
|
|
{
|
|
static std::array<std::atomic<WiimoteSource>, MAX_BBMOTES> s_wiimote_sources;
|
|
static std::optional<size_t> s_config_callback_id = std::nullopt;
|
|
|
|
WiimoteSource GetSource(unsigned int index)
|
|
{
|
|
return s_wiimote_sources[index];
|
|
}
|
|
|
|
void OnSourceChanged(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] { WiimoteCommon::UpdateSource(index); });
|
|
}
|
|
|
|
void RefreshConfig()
|
|
{
|
|
for (int i = 0; i < MAX_BBMOTES; ++i)
|
|
OnSourceChanged(i, Config::Get(Config::GetInfoForWiimoteSource(i)));
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace WiimoteCommon
|
|
{
|
|
void UpdateSource(unsigned int index)
|
|
{
|
|
const auto bluetooth = WiiUtils::GetBluetoothEmuDevice();
|
|
if (bluetooth == nullptr)
|
|
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<WiimoteEmu::Wiimote*>(::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<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetWiimoteGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetNunchukGroup(int number, WiimoteEmu::NunchukGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetNunchukGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetClassicGroup(int number, WiimoteEmu::ClassicGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetClassicGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetGuitarGroup(int number, WiimoteEmu::GuitarGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetGuitarGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetDrumsGroup(int number, WiimoteEmu::DrumsGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetDrumsGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetTurntableGroup(int number, WiimoteEmu::TurntableGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
|
->GetTurntableGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetUDrawTabletGroup(int number, WiimoteEmu::UDrawTabletGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
|
->GetUDrawTabletGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetDrawsomeTabletGroup(int number,
|
|
WiimoteEmu::DrawsomeTabletGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
|
->GetDrawsomeTabletGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetTaTaConGroup(int number, WiimoteEmu::TaTaConGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))->GetTaTaConGroup(group);
|
|
}
|
|
|
|
ControllerEmu::ControlGroup* GetShinkansenGroup(int number, WiimoteEmu::ShinkansenGroup group)
|
|
{
|
|
return static_cast<WiimoteEmu::Wiimote*>(s_config.GetController(number))
|
|
->GetShinkansenGroup(group);
|
|
}
|
|
|
|
void Shutdown()
|
|
{
|
|
s_config.UnregisterHotplugCallback();
|
|
|
|
s_config.ClearControllers();
|
|
|
|
WiimoteReal::Stop();
|
|
|
|
if (s_config_callback_id)
|
|
{
|
|
Config::RemoveConfigChangedCallback(*s_config_callback_id);
|
|
s_config_callback_id = std::nullopt;
|
|
}
|
|
}
|
|
|
|
void Initialize(InitializeMode init_mode)
|
|
{
|
|
if (s_config.ControllersNeedToBeCreated())
|
|
{
|
|
for (unsigned int i = WIIMOTE_CHAN_0; i < MAX_BBMOTES; ++i)
|
|
s_config.CreateController<WiimoteEmu::Wiimote>(i);
|
|
}
|
|
|
|
s_config.RegisterHotplugCallback();
|
|
|
|
LoadConfig();
|
|
|
|
if (!s_config_callback_id)
|
|
s_config_callback_id = Config::AddConfigChangedCallback(RefreshConfig);
|
|
RefreshConfig();
|
|
|
|
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<WiimoteEmu::Wiimote*>(s_config.GetController(i))->Reset();
|
|
}
|
|
|
|
void LoadConfig()
|
|
{
|
|
s_config.LoadConfig(InputConfig::InputClass::Wii);
|
|
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 = 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<WiimoteEmu::Wiimote*>(s_config.GetController(i))->DoState(p);
|
|
}
|
|
|
|
if (p.IsReadMode())
|
|
{
|
|
// 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
|