696 changes: 679 additions & 17 deletions Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp
Expand Up @@ -781,7 +781,10 @@ void Wiimote::Update()

// send data report
if (rptf_size)
{
WiimoteEmu::Spy(this, data, rptf_size);
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, data, rptf_size);
}
}

void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size)
Expand Down Expand Up @@ -853,7 +856,7 @@ void Wiimote::InterruptChannel(const u16 _channelID, const void* _pData, u32 _Si
{
const wm_report* const sr = (wm_report*)hidp->data;

if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index])
if (WIIMOTE_SRC_REAL & g_wiimote_sources[m_index])
{
switch (sr->wm)
{
Expand Down
10 changes: 10 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h
Expand Up @@ -24,6 +24,11 @@
#define WIIMOTE_REG_EXT_SIZE 0x100
#define WIIMOTE_REG_IR_SIZE 0x34

namespace WiimoteReal
{
class Wiimote;
}

namespace WiimoteEmu
{

Expand Down Expand Up @@ -66,6 +71,8 @@ inline double trim(double a)

class Wiimote : public ControllerEmu
{
friend class WiimoteReal::Wiimote;
friend void Spy(Wiimote* wm_, const void* data_, int size_);
public:

enum
Expand All @@ -92,6 +99,7 @@ class Wiimote : public ControllerEmu
void ControlChannel(const u16 _channelID, const void* _pData, u32 _Size);

void DoState(PointerWrap& p);
void RealState();

void LoadDefaults(const ControllerInterface& ciface);

Expand Down Expand Up @@ -235,6 +243,8 @@ class Wiimote : public ControllerEmu
} m_reg_speaker;
};

void Spy(Wiimote* wm_, const void* data_, int size_);

}

#endif
4 changes: 4 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp
Expand Up @@ -597,6 +597,8 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
}
}

WiimoteEmu::Spy(NULL, buf, bytes + 1);

return bytes + 1;
}

Expand All @@ -611,6 +613,8 @@ int Wiimote::IORead(u8* buf)

int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len)
{
WiimoteEmu::Spy(NULL, buf, len);

switch (stack)
{
case MSBT_STACK_UNKNOWN:
Expand Down
99 changes: 95 additions & 4 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
Expand Up @@ -110,6 +110,22 @@ void Wiimote::DisableDataReporting()
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
}

void Wiimote::EnableDataReporting(u8 mode)
{
m_last_input_report.clear();

wm_report_mode rpt = {};
rpt.mode = mode;
rpt.all_the_time = 1;
rpt.continuous = 1;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
}

void Wiimote::SetChannel(u16 channel)
{
m_channel = channel;
}

void Wiimote::ClearReadQueue()
{
Report rpt;
Expand Down Expand Up @@ -152,6 +168,7 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const

auto const data = static_cast<const u8*>(_data);
Report rpt(data, data + size);
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetPlugin()->controllers[index];

// Convert output DATA packets to SET_REPORT packets.
// Nintendo Wiimotes work without this translation, but 3rd
Expand All @@ -173,7 +190,8 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const _data, const
}
}
else if (rpt[1] == WM_WRITE_SPEAKER_DATA
&& !SConfig::GetInstance().m_WiimoteEnableSpeaker)
&& (!SConfig::GetInstance().m_WiimoteEnableSpeaker
|| (!wm->m_status.speaker || wm->m_speaker_mute)))
{
// Translate speaker data reports into rumble reports.
rpt[1] = WM_RUMBLE;
Expand Down Expand Up @@ -314,6 +332,44 @@ void Wiimote::EmuStop()
NOTICE_LOG(WIIMOTE, "Stopping Wiimote data reporting.");
}

void Wiimote::EmuResume()
{
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetPlugin()->controllers[index];

m_last_input_report.clear();

wm_report_mode rpt = {};
rpt.mode = wm->m_reporting_mode;
rpt.all_the_time = 1;
rpt.continuous = 1;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));

NOTICE_LOG(WIIMOTE, "Resuming Wiimote data reporting.");
}

void Wiimote::EmuPause()
{
m_last_input_report.clear();

wm_report_mode rpt = {};
rpt.mode = WM_REPORT_CORE;
rpt.all_the_time = 0;
rpt.continuous = 0;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));

NOTICE_LOG(WIIMOTE, "Pausing Wiimote data reporting.");
}

unsigned int CalculateConnectedWiimotes()
{
unsigned int connected_wiimotes = 0;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
if (g_wiimotes[i])
++connected_wiimotes;

return connected_wiimotes;
}

unsigned int CalculateWantedWiimotes()
{
// Figure out how many real Wiimotes are required
Expand Down Expand Up @@ -470,12 +526,26 @@ void Initialize()
g_wiimote_scanner.StartScanning();
else
g_wiimote_scanner.StopScanning();

std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());


// wait for connection because it should exist before state load
int timeout = 100;
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;
g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board);
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
{
while(CalculateWantedWiimotes() && CalculateConnectedWiimotes() < found_wiimotes.size() && timeout)
{
Common::SleepCurrentThread(100);
timeout--;
}
}

if (g_real_wiimotes_initialized)
return;

Expand All @@ -485,7 +555,14 @@ void Initialize()
}

void Shutdown(void)
{
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuStop();

// WiimoteReal is shutdown on app exit
return;

g_wiimote_scanner.StopScanning();

std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
Expand All @@ -501,6 +578,20 @@ void Shutdown(void)
HandleWiimoteDisconnect(i);
}

void Resume()
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuResume();
}

void Pause()
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuPause();
}

void ChangeWiimoteSource(unsigned int index, int source)
{
{
Expand Down
4 changes: 4 additions & 0 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
Expand Up @@ -47,6 +47,8 @@ friend class WiimoteEmu::Wiimote;
// "handshake" / stop packets
void EmuStart();
void EmuStop();
void EmuResume();
void EmuPause();

// connecting and disconnecting from physical devices
// (using address inserted by FindWiimotes)
Expand All @@ -59,6 +61,8 @@ friend class WiimoteEmu::Wiimote;
bool Prepare(int index);

void DisableDataReporting();
void EnableDataReporting(u8 mode);
void SetChannel(u16 channel);

void QueueReport(u8 rpt_id, const void* data, unsigned int size);

Expand Down
37 changes: 7 additions & 30 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
Expand Up @@ -138,27 +138,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)

for (unsigned int i = 0; i < MAX_BBMOTES; i++)
m_WiiMotes[i].DoState(p);

// Reset the connection of real and hybrid wiimotes
if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad)
{
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i])
continue;
// TODO: Selectively clear real wiimote messages if possible. Or create a real wiimote channel and reporting mode pre-setup to vacate the need for m_WiimoteReconnectOnLoad.
m_EventQueue.clear();
if (!m_WiiMotes[i].IsInactive())
{
m_WiiMotes[i].Activate(false);
m_WiiMotes[i].Activate(true);
}
else
{
m_WiiMotes[i].Activate(false);
}
}
}
}

bool CWII_IPC_HLE_Device_usb_oh1_57e_305::RemoteDisconnect(u16 _connectionHandle)
Expand Down Expand Up @@ -508,18 +487,16 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()

// The Real Wiimote sends report every ~5ms (200 Hz).
const u64 interval = SystemTimers::GetTicksPerSecond() / 200;
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
const u64 now = CoreTiming::GetTicks();

if (now - m_last_ticks > each_wiimote_interval)
if (now - m_last_ticks > interval)
{
static int wiimote_to_update = 0;
if (m_WiiMotes[wiimote_to_update].IsConnected())
{
NetPlay_WiimoteUpdate(wiimote_to_update);
Wiimote::Update(wiimote_to_update);
}
wiimote_to_update = (wiimote_to_update + 1) % m_WiiMotes.size();
for (unsigned int i = 0; i < m_WiiMotes.size(); i++)
if (m_WiiMotes[i].IsConnected())
{
NetPlay_WiimoteUpdate(i);
Wiimote::Update(i);
}
m_last_ticks = now;
}

Expand Down
2 changes: 2 additions & 0 deletions Source/Core/DolphinWX/Src/Main.cpp
Expand Up @@ -658,6 +658,8 @@ void Host_SetWiiMoteConnectionState(int _State)
// Update field 1 or 2
event.SetInt(1);

NOTICE_LOG(WIIMOTE, event.GetString().c_str());

main_frame->GetEventHandler()->AddPendingEvent(event);
}

Expand Down
4 changes: 0 additions & 4 deletions Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
Expand Up @@ -106,7 +106,6 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxSlider* const WiiSensBarSens = new wxSlider(this, wxID_ANY, 0, 0, 4, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
wxSlider* const WiimoteSpkVolume = new wxSlider(this, wxID_ANY, 0, 0, 127);
wxCheckBox* const WiimoteMotor = new wxCheckBox(this, wxID_ANY, _("Wiimote Motor"));
wxCheckBox* const WiimoteReconnectOnLoad = new wxCheckBox(this, wxID_ANY, _("Reconnect Wiimote on State Loading"));

wxStaticText* const WiiSensBarPosText = new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:"));
wxStaticText* const WiiSensBarSensText = new wxStaticText(this, wxID_ANY, _("IR Sensitivity:"));
Expand Down Expand Up @@ -143,13 +142,11 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u32>("BT.SENS"));
WiimoteSpkVolume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.SPKV"));
WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<bool>("BT.MOT"));
WiimoteReconnectOnLoad->SetValue(SConfig::GetInstance().m_WiimoteReconnectOnLoad);

WiiSensBarPos->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::OnSensorBarPos, this);
WiiSensBarSens->Bind(wxEVT_COMMAND_SLIDER_UPDATED, &WiimoteConfigDiag::OnSensorBarSensitivity, this);
WiimoteSpkVolume->Bind(wxEVT_COMMAND_SLIDER_UPDATED, &WiimoteConfigDiag::OnSpeakerVolume, this);
WiimoteMotor->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnMotor, this);
WiimoteReconnectOnLoad->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnReconnectOnLoad, this);


// "General Settings" layout
Expand All @@ -175,7 +172,6 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin

wxGridSizer* const general_wiimote_sizer = new wxGridSizer(1, 5, 5);
general_wiimote_sizer->Add(WiimoteMotor);
general_wiimote_sizer->Add(WiimoteReconnectOnLoad);

general_sizer->Add(choice_sizer);
general_sizer->Add(general_wiimote_sizer);
Expand Down
5 changes: 0 additions & 5 deletions Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
Expand Up @@ -52,11 +52,6 @@ class WiimoteConfigDiag : public wxDialog
SConfig::GetInstance().m_SYSCONF->SetData("BT.MOT", event.GetInt());
event.Skip();
}
void OnReconnectOnLoad(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteReconnectOnLoad = event.IsChecked();
event.Skip();
}
void OnContinuousScanning(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked();
Expand Down