Wiimote: Switch between emulated and real Wiimote during gameplay.

Notice: It's currently not very user friendly and can crash or fail under some circumstances. I'll make it better momentarily. You currently have to first open the Wiimote config window and the start a game to be able to use switch back and forth after that.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2011 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-01-25 23:07:15 +00:00
parent c9ca6ef55a
commit 8eeb1d0202
15 changed files with 771 additions and 355 deletions

View File

@ -407,26 +407,24 @@ THREAD_RETURN EmuThread(void *pArg)
if (!_CoreParameter.bUseDualCore) if (!_CoreParameter.bUseDualCore)
{ {
#ifdef _WIN32 #ifdef _WIN32
cpuThread = new Common::Thread(CpuThread, pArg); cpuThread = new Common::Thread(CpuThread, pArg);
//Common::SetCurrentThreadName("Idle thread"); //Common::SetCurrentThreadName("Idle thread");
//TODO(ector) : investigate using GetMessage instead .. although //TODO(ector) : investigate using GetMessage instead .. although
//then we lose the powerdown check. ... unless powerdown sends a message :P //then we lose the powerdown check. ... unless powerdown sends a message :P
while (PowerPC::state != PowerPC::CPU_POWERDOWN) while (PowerPC::state != PowerPC::CPU_POWERDOWN)
{ {
if (Callback_PeekMessages) { if (Callback_PeekMessages) Callback_PeekMessages();
Callback_PeekMessages(); Common::SleepCurrentThread(20);
} }
Common::SleepCurrentThread(20); #else
} // In single-core mode, the Emulation main thread is also the CPU thread
#else CpuThread(pArg);
// In single-core mode, the Emulation main thread is also the CPU thread #endif
CpuThread(pArg);
#endif
} }
else else
{ {
Plugins.GetVideo()->Video_Prepare(); //wglMakeCurrent Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
cpuThread = new Common::Thread(CpuThread, pArg); cpuThread = new Common::Thread(CpuThread, pArg);
Common::SetCurrentThreadName("Video thread"); Common::SetCurrentThreadName("Video thread");
Plugins.GetVideo()->Video_EnterLoop(); Plugins.GetVideo()->Video_EnterLoop();

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9.00" Version="9,00"
Name="Plugin_Wiimote" Name="Plugin_Wiimote"
ProjectGUID="{8D612734-FAA5-4B8A-804F-4DEA2367D495}" ProjectGUID="{8D612734-FAA5-4B8A-804F-4DEA2367D495}"
RootNamespace="Plugin_Wiimote" RootNamespace="Plugin_Wiimote"
@ -515,14 +515,6 @@
<References> <References>
</References> </References>
<Files> <Files>
<Filter
Name="misc"
>
<File
RelativePath="..\..\PluginSpecs\pluginspecs_wiimote.h"
>
</File>
</Filter>
<Filter <Filter
Name="Debugging" Name="Debugging"
> >
@ -586,6 +578,10 @@
<Filter <Filter
Name="Real Wiimote" Name="Real Wiimote"
> >
<File
RelativePath=".\Src\ReadWiimote.cpp"
>
</File>
<File <File
RelativePath=".\Src\wiimote_real.cpp" RelativePath=".\Src\wiimote_real.cpp"
> >
@ -619,6 +615,14 @@
RelativePath=".\Src\main.cpp" RelativePath=".\Src\main.cpp"
> >
</File> </File>
<File
RelativePath=".\Src\main.h"
>
</File>
<File
RelativePath="..\..\PluginSpecs\pluginspecs_wiimote.h"
>
</File>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View File

@ -39,6 +39,9 @@ void Config::Load()
iniFile.Get("Settings", "WideScreen", &bWideScreen, false); iniFile.Get("Settings", "WideScreen", &bWideScreen, false);
iniFile.Get("Settings", "NunchuckConnected", &bNunchuckConnected, false); iniFile.Get("Settings", "NunchuckConnected", &bNunchuckConnected, false);
iniFile.Get("Settings", "ClassicControllerConnected", &bClassicControllerConnected, false); iniFile.Get("Settings", "ClassicControllerConnected", &bClassicControllerConnected, false);
iniFile.Get("Real", "Connect", &bConnectRealWiimote, true);
iniFile.Get("Real", "Use", &bUseRealWiimote, true);
} }
void Config::Save() void Config::Save()
@ -50,6 +53,8 @@ void Config::Save()
iniFile.Set("Settings", "NunchuckConnected", bNunchuckConnected); iniFile.Set("Settings", "NunchuckConnected", bNunchuckConnected);
iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected); iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected);
iniFile.Set("Real", "Connect", bConnectRealWiimote);
iniFile.Set("Real", "Use", bUseRealWiimote);
iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini");
} }

View File

@ -30,10 +30,13 @@ struct Config
void Load(); void Load();
void Save(); void Save();
// General // Emulated Wiimote
bool bSidewaysDPad; bool bSidewaysDPad;
bool bWideScreen; bool bWideScreen;
bool bNunchuckConnected, bClassicControllerConnected; bool bNunchuckConnected, bClassicControllerConnected;
// Real Wiimote
bool bConnectRealWiimote, bUseRealWiimote;
}; };
extern Config g_Config; extern Config g_Config;

View File

@ -23,14 +23,15 @@
#include "ConfigDlg.h" #include "ConfigDlg.h"
#include "Config.h" #include "Config.h"
#include "EmuSubroutines.h" // for WmRequestStatus #include "EmuSubroutines.h" // for WmRequestStatus
#include "main.h"
#include "wiimote_real.h"
///////////////////////////// /////////////////////////////
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// Defines // Definitions
// ------------ // ------------
#ifndef _WIN32
#define Sleep(x) usleep(x*1000)
#endif
///////////////////////// /////////////////////////
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
@ -44,6 +45,10 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CHECKBOX(ID_WIDESCREEN, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_WIDESCREEN, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_NUNCHUCKCONNECTED, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_CLASSICCONTROLLERCONNECTED, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_CONNECT_REAL, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_USE_REAL, ConfigDialog::GeneralSettingsChanged)
END_EVENT_TABLE() END_EVENT_TABLE()
///////////////////////////// /////////////////////////////
@ -57,6 +62,8 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl
ConfigDialog::~ConfigDialog() ConfigDialog::~ConfigDialog()
{ {
g_FrameOpen = false;
if (!g_EmulatorRunning) Shutdown();
} }
@ -76,7 +83,10 @@ void ConfigDialog::CreateGUIControls()
//m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); //m_About = new wxButton(this, ID_ABOUTOGL, wxT("About"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_Close = new wxButton(this, ID_CLOSE, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Put notebook and buttons in sizers
////////////////////////////////////////////
// Put notebook and buttons in sMain
// ----------------
wxBoxSizer* sButtons; wxBoxSizer* sButtons;
sButtons = new wxBoxSizer(wxHORIZONTAL); sButtons = new wxBoxSizer(wxHORIZONTAL);
//sButtons->Add(m_About, 0, wxALL, 5); // there is no about //sButtons->Add(m_About, 0, wxALL, 5); // there is no about
@ -87,10 +97,14 @@ void ConfigDialog::CreateGUIControls()
sMain = new wxBoxSizer(wxVERTICAL); sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5);
sMain->Add(sButtons, 0, wxEXPAND, 5); sMain->Add(sButtons, 0, wxEXPAND, 5);
/////////////////////////////////
////////////////////////////////////////////
// Emulated Wiimote
// ----------------
// General // General
sbBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageEmu, wxT("Basic Settings")); wxStaticBoxSizer * sEmulatedBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageEmu, wxT("Basic Settings"));
m_SidewaysDPad = new wxCheckBox(m_PageEmu, ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_SidewaysDPad = new wxCheckBox(m_PageEmu, ID_SIDEWAYSDPAD, wxT("Sideways D-Pad"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_SidewaysDPad->SetValue(g_Config.bSidewaysDPad); m_SidewaysDPad->SetValue(g_Config.bSidewaysDPad);
m_WideScreen = new wxCheckBox(m_PageEmu, ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_WideScreen = new wxCheckBox(m_PageEmu, ID_WIDESCREEN, wxT("WideScreen Mode (for correct aiming)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@ -100,30 +114,56 @@ void ConfigDialog::CreateGUIControls()
m_ClassicControllerConnected = new wxCheckBox(m_PageEmu, ID_CLASSICCONTROLLERCONNECTED, wxT("Classic Controller connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_ClassicControllerConnected = new wxCheckBox(m_PageEmu, ID_CLASSICCONTROLLERCONNECTED, wxT("Classic Controller connected"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected); m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected);
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Set up sGeneral and sBasic // Set up sGeneral and sBasic
// Usage: The wxGBPosition() must have a column and row // Usage: The wxGBPosition() must have a column and row
// ---------------- // ----------------
sGeneral = new wxBoxSizer(wxVERTICAL); wxBoxSizer * sEmulatedMain = new wxBoxSizer(wxVERTICAL);
sBasic = new wxGridBagSizer(0, 0); wxGridBagSizer * GbsBasic = new wxGridBagSizer(0, 0);
sBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); GbsBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5);
sBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); GbsBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5);
sBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); GbsBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5);
sBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); GbsBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5);
sbBasic->Add(sBasic); sEmulatedBasic->Add(GbsBasic);
sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); sEmulatedMain->Add(sEmulatedBasic, 0, wxEXPAND | (wxALL), 5);
/////////////////////////////////
m_PageEmu->SetSizer(sGeneral);
sGeneral->Layout();
this->SetSizer(sMain); ////////////////////////////////////////////
this->Layout(); // Real Wiimote
// ---------------- // ----------------
// General
wxStaticBoxSizer * sbRealBasic = new wxStaticBoxSizer(wxVERTICAL, m_PageReal, wxT("Basic Settings"));
m_ConnectRealWiimote = new wxCheckBox(m_PageReal, ID_CONNECT_REAL, wxT("Connect real Wiimote"));
m_UseRealWiimote = new wxCheckBox(m_PageReal, ID_USE_REAL, wxT("Use real Wiimote"));
m_ConnectRealWiimote->SetToolTip(wxT("Connected to the real wiimote"));
m_UseRealWiimote->SetToolTip(wxT("Use the real Wiimote in the game"));
m_ConnectRealWiimote->SetValue(g_Config.bConnectRealWiimote);
m_UseRealWiimote->SetValue(g_Config.bUseRealWiimote);
// ----------------------------------------------------------------------
// Set up sizers
// ----------------
wxBoxSizer * sRealMain = new wxBoxSizer(wxVERTICAL);
sRealMain->Add(sbRealBasic, 0, wxEXPAND | (wxALL), 5);
sbRealBasic->Add(m_ConnectRealWiimote, 0, wxEXPAND | (wxALL), 5);
sbRealBasic->Add(m_UseRealWiimote, 0, wxEXPAND | (wxALL), 5);
/////////////////////////////////
////////////////////////////////////////////
// Set sizers and layout
// ----------------
m_PageEmu->SetSizer(sEmulatedMain);
m_PageReal->SetSizer(sRealMain);
this->SetSizer(sMain);
//sEmulatedMain->Layout();
this->Layout();
Fit(); Fit();
Center(); Center();
/////////////////////////////////
} }
void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event))
@ -141,7 +181,27 @@ void ConfigDialog::AboutClick(wxCommandEvent& WXUNUSED (event))
{ {
} }
////////////////////////// /////////////////////////////////
// ===================================================
/* Do use real wiimote */
// ----------------
void ConfigDialog::DoConnectReal()
{
g_Config.bConnectRealWiimote = m_ConnectRealWiimote->IsChecked();
if(g_Config.bConnectRealWiimote)
{
if (!g_RealWiiMoteInitialized) WiiMoteReal::Initialize();
}
else
{
if (g_RealWiiMoteInitialized) WiiMoteReal::Shutdown();
}
}
// =================================================== // ===================================================
@ -159,7 +219,7 @@ void ConfigDialog::DoExtensionConnectedDisconnected()
// =================================================== // ===================================================
/* Change general Emulated Wii Remote settings */ /* Change settings */
// ---------------- // ----------------
void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
{ {
@ -214,5 +274,31 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id)); memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id));
DoExtensionConnectedDisconnected(); DoExtensionConnectedDisconnected();
break; break;
//////////////////////////
// Real Wiimote
// -----------
case ID_CONNECT_REAL:
DoConnectReal();
break;
case ID_USE_REAL:
g_Config.bUseRealWiimote = m_UseRealWiimote->IsChecked();
break;
/////////////////
} }
UpdateGUI();
}
// =======================================================
// Update the enabled/disabled status
// -------------
void ConfigDialog::UpdateGUI()
{
// Save status
m_ConnectRealWiimote->Enable(g_RealWiiMotePresent);
m_UseRealWiimote->Enable(g_RealWiiMotePresent && g_Config.bConnectRealWiimote);
} }

View File

@ -44,19 +44,17 @@ class ConfigDialog : public wxDialog
private: private:
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
wxBoxSizer* sGeneral;
wxStaticBoxSizer* sbBasic;
wxGridBagSizer* sBasic;
wxButton *m_About; wxButton *m_About;
wxButton *m_Close; wxButton *m_Close;
wxNotebook *m_Notebook; wxNotebook *m_Notebook;
wxPanel *m_PageEmu, *m_PageReal; wxPanel *m_PageEmu, *m_PageReal;
wxCheckBox *m_SidewaysDPad; // general settings wxCheckBox *m_SidewaysDPad; // Emulated Wiimote settings
wxCheckBox *m_WideScreen; wxCheckBox *m_WideScreen;
wxCheckBox *m_NunchuckConnected, *m_ClassicControllerConnected; wxCheckBox *m_NunchuckConnected, *m_ClassicControllerConnected;
wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote; // Real Wiimote settings
enum enum
{ {
ID_CLOSE = 1000, ID_CLOSE = 1000,
@ -66,17 +64,25 @@ class ConfigDialog : public wxDialog
ID_PAGEEMU, ID_PAGEEMU,
ID_PAGEREAL, ID_PAGEREAL,
ID_SIDEWAYSDPAD, ID_SIDEWAYSDPAD, // Emulated
ID_WIDESCREEN, ID_WIDESCREEN,
ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED,
// Real
ID_CONNECT_REAL, ID_USE_REAL
}; };
void OnClose(wxCloseEvent& event); void OnClose(wxCloseEvent& event);
void CreateGUIControls(); void CreateGUIControls();
void AboutClick(wxCommandEvent& event); void AboutClick(wxCommandEvent& event);
void DoExtensionConnectedDisconnected();
void DoConnectReal(); // Real
void DoExtensionConnectedDisconnected(); // Emulated
void GeneralSettingsChanged(wxCommandEvent& event); void GeneralSettingsChanged(wxCommandEvent& event);
void UpdateGUI();
}; };
#endif #endif

View File

@ -91,8 +91,8 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr)
LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous); LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous);
LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time);
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
//Console::Print("Data reporting mode: 0x%02x\n", dr->mode); Console::Print("Data reporting mode: 0x%02x\n", dr->mode);
//Console::Print("Data reporting channel: 0x%04x\n", _channelID); Console::Print("Data reporting channel: 0x%04x\n", _channelID);
g_ReportingMode = dr->mode; g_ReportingMode = dr->mode;
g_ReportingChannel = _channelID; g_ReportingChannel = _channelID;

View File

@ -267,7 +267,7 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
//if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA) //if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA)
// && data[3] == 0xa4) // && data[3] == 0xa4)
//{ //{
CreateAckDelay((u8)_channelID, (u16)sr->channel); if (!g_Config.bUseRealWiimote) CreateAckDelay((u8)_channelID, (u16)sr->channel);
//} //}
//else //else
//{ //{
@ -353,15 +353,16 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
void Update() void Update()
{ {
//LOG(WII_IPC_WIIMOTE, "Wiimote_Update"); //LOG(WII_IPC_WIIMOTE, "Wiimote_Update");
Console::Print("g_ReportingMode %i\n", g_ReportingMode);
switch(g_ReportingMode) switch(g_ReportingMode)
{ {
case 0: case 0:
break; break;
case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break; case WM_REPORT_CORE: SendReportCore(g_ReportingChannel); break;
case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break; case WM_REPORT_CORE_ACCEL: SendReportCoreAccel(g_ReportingChannel); break;
case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel);break; case WM_REPORT_CORE_ACCEL_IR12: SendReportCoreAccelIr12(g_ReportingChannel); break;
case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel);break; case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel); break;
case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break; case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break;
} }

View File

@ -97,12 +97,12 @@ void HidOutputReport(u16 _channelID, wm_report* sr) {
WmDataReporting(_channelID, (wm_data_reporting*)sr->data); WmDataReporting(_channelID, (wm_data_reporting*)sr->data);
break; break;
case WM_REQUEST_STATUS: // 0x15 case WM_REQUEST_STATUS: // 0x15
WmRequestStatus(_channelID, (wm_request_status*)sr->data); if (!g_Config.bUseRealWiimote) WmRequestStatus(_channelID, (wm_request_status*)sr->data);
//Temp = ArrayToString(sr->data, sizeof(wm_request_status), 0); //Temp = ArrayToString(sr->data, sizeof(wm_request_status), 0);
//Console::Print("\n%s: InterruptChannel: %s\n", Tm().c_str(), Temp.c_str()); //Console::Print("\n%s: InterruptChannel: %s\n", Tm().c_str(), Temp.c_str());
break; break;
case WM_READ_DATA: // 0x17 case WM_READ_DATA: // 0x17
WmReadData(_channelID, (wm_read_data*)sr->data); if (!g_Config.bUseRealWiimote) WmReadData(_channelID, (wm_read_data*)sr->data);
break; break;
/* This enables or disables the IR lights, we update the global variable g_IR /* This enables or disables the IR lights, we update the global variable g_IR
@ -116,7 +116,7 @@ void HidOutputReport(u16 _channelID, wm_report* sr) {
break; break;
case WM_WRITE_DATA: // 0x16 case WM_WRITE_DATA: // 0x16
WmWriteData(_channelID, (wm_write_data*)sr->data); if (!g_Config.bUseRealWiimote) WmWriteData(_channelID, (wm_write_data*)sr->data);
break; break;
case WM_SPEAKER_ENABLE: // 0x14 case WM_SPEAKER_ENABLE: // 0x14
LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]);

View File

@ -0,0 +1,139 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯
#include <iostream> // System
#include "pluginspecs_wiimote.h"
#include "wiiuse.h" // Externals
#include "ConsoleWindow.h" // Common
#include "wiimote_real.h" // Local
////////////////////////////////////////
namespace WiiMoteReal
{
void handle_ctrl_status(struct wiimote_t* wm)
{
printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid);
printf("attachment: %i\n", wm->exp.type);
printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm));
printf("ir: %i\n", WIIUSE_USING_IR(wm));
printf("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4));
printf("battery: %f %%\n", wm->battery_level);
}
void handle_event(struct wiimote_t* wm)
{
printf("\n\n--- EVENT [id %i] ---\n", wm->unid);
/* if a button is pressed, report it */
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) printf("B pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) printf("UP pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) printf("DOWN pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_LEFT)) printf("LEFT pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_RIGHT)) printf("RIGHT pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) printf("MINUS pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) printf("PLUS pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) printf("ONE pressed\n");
//if (IS_PRESSED(wm, WIIMOTE_BUTTON_ONE)) g_Run = false;
if (IS_PRESSED(wm, WIIMOTE_BUTTON_TWO)) printf("TWO pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_HOME)) printf("HOME pressed\n");
}
void ReadWiimote()
{
if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES))
{
/*
* This happens if something happened on any wiimote.
* So go through each one and check if anything happened.
*/
int i = 0;
for (; i < MAX_WIIMOTES; ++i)
{
switch (g_WiiMotesFromWiiUse[i]->event)
{
case WIIUSE_EVENT:
/* a generic event occured */
handle_event(g_WiiMotesFromWiiUse[i]);
break;
case WIIUSE_STATUS:
/* a status event occured */
handle_ctrl_status(g_WiiMotesFromWiiUse[i]);
break;
case WIIUSE_DISCONNECT:
case WIIUSE_UNEXPECTED_DISCONNECT:
/* the wiimote disconnected */
//handle_disconnect(wiimotes[i]);
break;
case WIIUSE_READ_DATA:
/*
* Data we requested to read was returned.
* Take a look at wiimotes[i]->read_req
* for the data.
*/
break;
case WIIUSE_NUNCHUK_INSERTED:
/*
* a nunchuk was inserted
* This is a good place to set any nunchuk specific
* threshold values. By default they are the same
* as the wiimote.
*/
//wiiuse_set_nunchuk_orient_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 90.0f);
//wiiuse_set_nunchuk_accel_threshold((struct nunchuk_t*)&wiimotes[i]->exp.nunchuk, 100);
printf("Nunchuk inserted.\n");
break;
case WIIUSE_CLASSIC_CTRL_INSERTED:
//printf("Classic controller inserted.\n");
break;
case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
/* some expansion was inserted */
//handle_ctrl_status(wiimotes[i]);
printf("Guitar Hero 3 controller inserted.\n");
break;
case WIIUSE_NUNCHUK_REMOVED:
case WIIUSE_CLASSIC_CTRL_REMOVED:
case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
/* some expansion was removed */
//handle_ctrl_status(wiimotes[i]);
printf("An expansion was removed.\n");
break;
default:
break;
}
}
}
}
}; // end of namespace

View File

@ -29,6 +29,7 @@ cxxflags = [ '-fPIC' ]
if wmenv['HAVE_WIIUSE']: if wmenv['HAVE_WIIUSE']:
libs += [ 'wiiuse' ] libs += [ 'wiiuse' ]
files += [ "wiimote_real.cpp" ] files += [ "wiimote_real.cpp" ]
files += [ "ReadWiimote.cpp" ]
cxxflags += ['-DHAVE_WIIUSE'] cxxflags += ['-DHAVE_WIIUSE']
wmenv.Append( wmenv.Append(

View File

@ -25,16 +25,16 @@
#include "ConsoleWindow.h" // For Start, Print, GetHwnd #include "ConsoleWindow.h" // For Start, Print, GetHwnd
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
#include <wx/aboutdlg.h> #include <wx/aboutdlg.h>
#include "ConfigDlg.h" #include "ConfigDlg.h"
#endif #endif
#define EXCLUDEMAIN_H // Avoid certain declarations in main.h
#include "Main.h" // Local
#include "pluginspecs_wiimote.h" #include "pluginspecs_wiimote.h"
#include "EmuMain.h" #include "EmuMain.h"
#if HAVE_WIIUSE #if HAVE_WIIUSE
#include "wiimote_real.h" #include "wiimote_real.h"
#endif #endif
/////////////////////////////////// ///////////////////////////////////
@ -44,7 +44,10 @@
// ¯¯¯¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯¯¯¯
SWiimoteInitialize g_WiimoteInitialize; SWiimoteInitialize g_WiimoteInitialize;
bool g_UseRealWiiMote = false; bool g_EmulatorRunning = false;
bool g_FrameOpen = false;
bool g_RealWiiMotePresent = false;
bool g_RealWiiMoteInitialized = false;
HINSTANCE g_hInstance; HINSTANCE g_hInstance;
@ -105,67 +108,64 @@ extern "C" void GetDllInfo (PLUGIN_INFO* _PluginInfo)
{ {
_PluginInfo->Version = 0x0100; _PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_WIIMOTE; _PluginInfo->Type = PLUGIN_TYPE_WIIMOTE;
#ifdef DEBUGFAST #ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (DebugFast)"); sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (DebugFast)");
#else #else
#ifndef _DEBUG #ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin"); sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin");
#else #else
sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (Debug)"); sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (Debug)");
#endif #endif
#endif #endif
} }
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) { void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {}
}
void DllDebugger(HWND _hParent, bool Show) { void DllDebugger(HWND _hParent, bool Show) {}
}
void DllConfig(HWND _hParent) void DllConfig(HWND _hParent)
{ {
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
wxWindow win; wxWindow win;
#ifdef _WIN32
win.SetHWND(_hParent); #ifdef _WIN32
#endif win.SetHWND(_hParent);
#endif
DoInitialize();
g_FrameOpen = true;
ConfigDialog frame(&win); ConfigDialog frame(&win);
frame.ShowModal(); frame.ShowModal();
#ifdef _WIN32 //frame.Show();
win.SetHWND(0);
#endif #ifdef _WIN32
win.SetHWND(0);
#endif
#endif #endif
} }
extern "C" void Initialize(void *init) extern "C" void Initialize(void *init)
{ {
// Declarations
SWiimoteInitialize _WiimoteInitialize = *(SWiimoteInitialize *)init; SWiimoteInitialize _WiimoteInitialize = *(SWiimoteInitialize *)init;
// ----------------------------------------
// Debugging window
// ----------
/*Console::Open(100, 750, "Wiimote"); // give room for 20 rows
Console::Print("Wiimote console opened\n");
// Move window
//MoveWindow(Console::GetHwnd(), 0,400, 100*8,10*14, true); // small window
MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window*/
// ---------------
g_WiimoteInitialize = _WiimoteInitialize; g_WiimoteInitialize = _WiimoteInitialize;
/* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote, g_EmulatorRunning = true;
to check if there is a real wiimote connected. We will initiate wiiuse.dll, but
we will return before creating a new thread for it if we find no real Wiimotes.
Then g_UseRealWiiMote will also be false. This function call will be done
instantly if there is no real Wiimote connected. I'm not sure how long time
it takes if a Wiimote is connected. */
#if HAVE_WIIUSE
g_UseRealWiiMote = WiiMoteReal::Initialize() > 0;
#endif
g_Config.Load(); // load config settings
WiiMoteEmu::Initialize(); DoInitialize();
}
extern "C" void Shutdown(void)
{
// We will only shutdown when both a game and the frame is closed
if (g_FrameOpen) { g_EmulatorRunning = false; return; }
#if HAVE_WIIUSE
if(g_RealWiiMoteInitialized) WiiMoteReal::Shutdown();
#endif
WiiMoteEmu::Shutdown();
} }
@ -177,13 +177,6 @@ extern "C" void DoState(unsigned char **ptr, int mode)
WiiMoteEmu::DoState(ptr, mode); WiiMoteEmu::DoState(ptr, mode);
} }
extern "C" void Shutdown(void)
{
#if HAVE_WIIUSE
WiiMoteReal::Shutdown();
#endif
WiiMoteEmu::Shutdown();
}
// =================================================== // ===================================================
/* This function produce Wiimote Input (reports from the Wiimote) in response /* This function produce Wiimote Input (reports from the Wiimote) in response
@ -203,16 +196,21 @@ extern "C" void Wiimote_InterruptChannel(u16 _channelID, const void* _pData, u32
} }
// Decice where to send the message // Decice where to send the message
if (! g_UseRealWiiMote) //if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent)
WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size); WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size);
#if HAVE_WIIUSE #if HAVE_WIIUSE
else //else if (g_RealWiiMotePresent)
WiiMoteReal::InterruptChannel(_channelID, _pData, _Size); WiiMoteReal::InterruptChannel(_channelID, _pData, _Size);
#endif #endif
LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
} }
// ==============================
// ===================================================
/* Function: Used for the initial Bluetooth HID handshake. */
// ----------------
extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size) extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
{ {
LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
@ -225,16 +223,16 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
} }
if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent)
if (! g_UseRealWiiMote) WiiMoteEmu::ControlChannel(_channelID, _pData, _Size);
WiiMoteEmu::ControlChannel(_channelID, _pData, _Size);
#if HAVE_WIIUSE #if HAVE_WIIUSE
else else if (g_RealWiiMotePresent)
WiiMoteReal::ControlChannel(_channelID, _pData, _Size); WiiMoteReal::ControlChannel(_channelID, _pData, _Size);
#endif #endif
LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); LOGV(WII_IPC_WIIMOTE, 3, "=============================================================");
} }
// ==============================
// =================================================== // ===================================================
@ -243,11 +241,11 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
// ---------------- // ----------------
extern "C" void Wiimote_Update() extern "C" void Wiimote_Update()
{ {
if (! g_UseRealWiiMote) if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent)
WiiMoteEmu::Update(); WiiMoteEmu::Update();
#if HAVE_WIIUSE #if HAVE_WIIUSE
else else if (g_RealWiiMotePresent)
WiiMoteReal::Update(); WiiMoteReal::Update();
#endif #endif
} }
@ -258,9 +256,44 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
// ================ // ================
// =================================================== //******************************************************************************
/* Logging functions. */ // Supporting functions
// ---------------- //******************************************************************************
void DoInitialize()
{
// ----------------------------------------
// Debugging window
// ----------
/*Console::Open(100, 750, "Wiimote"); // give room for 20 rows
Console::Print("Wiimote console opened\n");
// Move window
//MoveWindow(Console::GetHwnd(), 0,400, 100*8,10*14, true); // small window
MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window*/
// ---------------
// Load config settings
g_Config.Load();
/* We will run WiiMoteReal::Initialize() even if we are not using a real wiimote,
to check if there is a real wiimote connected. We will initiate wiiuse.dll, but
we will return before creating a new thread for it if we find no real Wiimotes.
Then g_RealWiiMotePresent will also be false. This function call will be done
instantly if there is no real Wiimote connected. I'm not sure how long time
it takes if a Wiimote is connected. */
#if HAVE_WIIUSE
if (g_Config.bConnectRealWiimote) WiiMoteReal::Initialize();
#endif
WiiMoteEmu::Initialize();
}
//******************************************************************************
// Logging functions
//******************************************************************************
void __Log(int log, const char *_fmt, ...) void __Log(int log, const char *_fmt, ...)
{ {
char Msg[512]; char Msg[512];
@ -285,4 +318,6 @@ void __Logv(int log, int v, const char *_fmt, ...)
g_WiimoteInitialize.pLog(Msg, v); g_WiimoteInitialize.pLog(Msg, v);
} }
// ================

View File

@ -0,0 +1,51 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef MAIN_H
#define MAIN_H
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯
#include <iostream> // System
////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// ¯¯¯¯¯¯¯¯¯
#ifndef _WIN32
#define Sleep(x) usleep(x*1000)
#endif
////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Declarations
// ¯¯¯¯¯¯¯¯¯
void DoInitialize();
#ifndef EXCLUDEMAIN_H
extern bool g_EmulatorRunning;
extern bool g_FrameOpen;
extern bool g_RealWiiMotePresent;
extern bool g_RealWiiMoteInitialized;
#endif
////////////////////////////////
#endif // MAIN_H

View File

@ -15,6 +15,11 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯
#include <iostream> // System
#include "pluginspecs_wiimote.h" #include "pluginspecs_wiimote.h"
#include "wiiuse.h" #include "wiiuse.h"
@ -22,273 +27,340 @@
#include "Common.h" #include "Common.h"
#include "Thread.h" #include "Thread.h"
#include "StringUtil.h"
#include "ConsoleWindow.h"
#include "wiimote_hid.h" #include "wiimote_hid.h"
#include "main.h"
#include "EmuMain.h" #include "EmuMain.h"
#define EXCLUDE_H // Avoid certain declarations in main.h
#include "wiimote_real.h"
extern SWiimoteInitialize g_WiimoteInitialize; extern SWiimoteInitialize g_WiimoteInitialize;
//extern void __Log(int log, const char *format, ...); ////////////////////////////////////////
//extern void __Log(int log, int v, const char *format, ...);
namespace WiiMoteReal namespace WiiMoteReal
{ {
#define MAX_WIIMOTES 1
//****************************************************************************** //******************************************************************************
// Forwarding // Forwarding
//****************************************************************************** //******************************************************************************
class CWiiMote; class CWiiMote;
#ifdef _WIN32 #ifdef _WIN32
DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); DWORD WINAPI ReadWiimote_ThreadFunc(void* arg);
#else #else
void* ReadWiimote_ThreadFunc(void* arg); void* ReadWiimote_ThreadFunc(void* arg);
#endif #endif
//****************************************************************************** //******************************************************************************
// Variable declarations // Variable declarations
//****************************************************************************** //******************************************************************************
wiimote_t** g_WiiMotesFromWiiUse = NULL; wiimote_t** g_WiiMotesFromWiiUse = NULL;
Common::Thread* g_pReadThread = NULL; Common::Thread* g_pReadThread = NULL;
int g_NumberOfWiiMotes; int g_NumberOfWiiMotes;
CWiiMote* g_WiiMotes[MAX_WIIMOTES]; CWiiMote* g_WiiMotes[MAX_WIIMOTES];
bool g_Shutdown = false; bool g_Shutdown = false;
bool g_LocalThread = true;
//****************************************************************************** //******************************************************************************
// Probably this class should be in its own file // Probably this class should be in its own file
//****************************************************************************** //******************************************************************************
class CWiiMote class CWiiMote
{
public:
//////////////////////////////////////////
// On create and on uncreate
// ---------------
CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote)
: m_WiimoteNumber(_WiimoteNumber)
, m_channelID(0)
, m_pWiiMote(_pWiimote)
, m_pCriticalSection(NULL)
, m_LastReportValid(false)
{
m_pCriticalSection = new Common::CriticalSection();
//wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4);
#ifdef _WIN32
// F|RES: i dunno if we really need this
CancelIo(m_pWiiMote->dev_handle);
#endif
}
virtual ~CWiiMote()
{
delete m_pCriticalSection;
};
//////////////////////
//////////////////////////////////////////
// Send raw HID data from the core to wiimote
// ---------------
void SendData(u16 _channelID, const u8* _pData, u32 _Size)
{
m_channelID = _channelID;
m_pCriticalSection->Enter();
{ {
public: SEvent WriteEvent;
memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1);
m_EventWriteQueue.push(WriteEvent);
}
m_pCriticalSection->Leave();
}
/////////////////////
CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote)
: m_WiimoteNumber(_WiimoteNumber) //////////////////////////////////////////
, m_channelID(0) // Read data from wiimote (but don't send it to the core, just filter and queue)
, m_pWiiMote(_pWiimote) // ---------------
, m_pCriticalSection(NULL) void ReadData()
, m_LastReportValid(false) {
m_pCriticalSection->Enter();
// Send data to the Wiimote
if (!m_EventWriteQueue.empty())
{
SEvent& rEvent = m_EventWriteQueue.front();
wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD);
m_EventWriteQueue.pop();
}
m_pCriticalSection->Leave();
if (wiiuse_io_read(m_pWiiMote))
{
const byte* pBuffer = m_pWiiMote->event_buf;
// Check if we have a channel (connection) if so save the data...
if (m_channelID > 0)
{ {
m_pCriticalSection = new Common::CriticalSection();
wiiuse_set_leds(m_pWiiMote, WIIMOTE_LED_4);
#ifdef _WIN32
// F|RES: i dunno if we really need this
CancelIo(m_pWiiMote->dev_handle);
#endif
}
virtual ~CWiiMote()
{
delete m_pCriticalSection;
};
// send raw HID data from the core to wiimote
void SendData(u16 _channelID, const u8* _pData, u32 _Size)
{
m_channelID = _channelID;
m_pCriticalSection->Enter(); m_pCriticalSection->Enter();
// Filter out reports
if (pBuffer[0] >= 0x30)
{ {
SEvent WriteEvent; // Copy Buffer to LastReport
memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_EventWriteQueue.push(WriteEvent); m_LastReportValid = true;
} }
m_pCriticalSection->Leave();
}
// read data from wiimote (but don't send it to the core, just filter
// and queue)
void ReadData()
{
m_pCriticalSection->Enter();
if (!m_EventWriteQueue.empty())
{
SEvent& rEvent = m_EventWriteQueue.front();
wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD);
m_EventWriteQueue.pop();
}
m_pCriticalSection->Leave();
if (wiiuse_io_read(m_pWiiMote))
{
const byte* pBuffer = m_pWiiMote->event_buf;
// check if we have a channel (connection) if so save the
// data...
if (m_channelID > 0)
{
m_pCriticalSection->Enter();
// filter out reports
if (pBuffer[0] >= 0x30)
{
memcpy(m_LastReport.m_PayLoad, pBuffer,
MAX_PAYLOAD);
m_LastReportValid = true;
}
else
{
SEvent ImportantEvent;
memcpy(ImportantEvent.m_PayLoad, pBuffer,
MAX_PAYLOAD);
m_EventReadQueue.push(ImportantEvent);
}
m_pCriticalSection->Leave();
}
}
};
// send queued data to the core
void Update()
{
m_pCriticalSection->Enter();
if (m_EventReadQueue.empty())
{
if (m_LastReportValid)
SendEvent(m_LastReport);
}
else else
{
SendEvent(m_EventReadQueue.front());
m_EventReadQueue.pop();
}
m_pCriticalSection->Leave();
};
private:
struct SEvent
{
SEvent()
{ {
memset(m_PayLoad, 0, MAX_PAYLOAD); // Copy Buffer to ImportantEvent
SEvent ImportantEvent;
memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD);
m_EventReadQueue.push(ImportantEvent);
} }
byte m_PayLoad[MAX_PAYLOAD]; m_pCriticalSection->Leave();
};
typedef std::queue<SEvent> CEventQueue;
u8 m_WiimoteNumber; // just for debugging
u16 m_channelID;
wiimote_t* m_pWiiMote;
Common::CriticalSection* m_pCriticalSection;
CEventQueue m_EventReadQueue;
CEventQueue m_EventWriteQueue;
bool m_LastReportValid;
SEvent m_LastReport;
void SendEvent(SEvent& _rEvent)
{
// we don't have an answer channel
if (m_channelID == 0)
return;
// check event buffer;
u8 Buffer[1024];
u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset);
Offset += sizeof(hid_packet);
pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT;
memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD);
Offset += MAX_PAYLOAD;
g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset);
} }
//std::string Temp = ArrayToString(pBuffer, sizeof(pBuffer), 0);
//Console::Print("Data:\n%s\n", Temp.c_str());
}
};
/////////////////////
//////////////////////////////////////////
// Send queued data to the core
// ---------------
void Update()
{
// Thread function
m_pCriticalSection->Enter();
if (m_EventReadQueue.empty())
{
if (m_LastReportValid) SendEvent(m_LastReport);
}
else
{
SendEvent(m_EventReadQueue.front());
m_EventReadQueue.pop();
}
m_pCriticalSection->Leave();
};
/////////////////////
private:
struct SEvent
{
SEvent()
{
memset(m_PayLoad, 0, MAX_PAYLOAD);
}
byte m_PayLoad[MAX_PAYLOAD];
}; };
typedef std::queue<SEvent> CEventQueue;
u8 m_WiimoteNumber; // Just for debugging
u16 m_channelID;
Common::CriticalSection* m_pCriticalSection;
CEventQueue m_EventReadQueue;
CEventQueue m_EventWriteQueue;
bool m_LastReportValid;
SEvent m_LastReport;
wiimote_t* m_pWiiMote; // This is g_WiiMotesFromWiiUse[]
//////////////////////////////////////////
// Send event
// ---------------
void SendEvent(SEvent& _rEvent)
{
// We don't have an answer channel
if (m_channelID == 0) return;
// Check event buffer;
u8 Buffer[1024];
u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset);
Offset += sizeof(hid_packet);
pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT;
memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD);
Offset += MAX_PAYLOAD;
g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset);
}
/////////////////////
};
//****************************************************************************** //******************************************************************************
// Function Definitions // Function Definitions
//****************************************************************************** //******************************************************************************
int Initialize() int Initialize()
{
if (g_RealWiiMoteInitialized) return g_NumberOfWiiMotes;
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
// Call Wiiuse.dll
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5);
if (g_NumberOfWiiMotes > 0) g_RealWiiMotePresent = true;
Console::Print("Found No of Wiimotes: %i\n", g_NumberOfWiiMotes);
// For the status window
if (!g_EmulatorRunning)
{
// Do I need this?
//int Connect = wiiuse_connect(g_WiiMotesFromWiiUse, MAX_WIIMOTES);
//Console::Print("Connected: %i\n", Connect);
wiiuse_rumble(g_WiiMotesFromWiiUse[0], 1);
wiiuse_set_leds(g_WiiMotesFromWiiUse[0], WIIMOTE_LED_4);
Sleep(40);
wiiuse_set_leds(g_WiiMotesFromWiiUse[0], WIIMOTE_LED_NONE);
Sleep(40);
wiiuse_set_leds(g_WiiMotesFromWiiUse[0], WIIMOTE_LED_4);
Sleep(120);
wiiuse_rumble(g_WiiMotesFromWiiUse[0], 0);
}
else
{
//wiiuse_disconnect(g_WiiMotesFromWiiUse);
}
// Create Wiimote clasess
for (int i = 0; i < g_NumberOfWiiMotes; i++)
g_WiiMotes[i] = new CWiiMote(i + 1, g_WiiMotesFromWiiUse[i]);
// Create a nee thread and start listening for Wiimote data
if (g_NumberOfWiiMotes > 0)
g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL);
// Initialized
if (g_NumberOfWiiMotes > 0) { g_RealWiiMoteInitialized = true; g_Shutdown = false; }
return g_NumberOfWiiMotes;
}
void DoState(void* ptr, int mode) {}
void Shutdown(void)
{
g_Shutdown = true;
// Stop the thread
if (g_pReadThread != NULL)
{
g_pReadThread->WaitForDeath();
delete g_pReadThread;
g_pReadThread = NULL;
}
// Delete the wiimotes
for (int i = 0; i < g_NumberOfWiiMotes; i++)
{
delete g_WiiMotes[i];
g_WiiMotes[i] = NULL;
}
// Clean up wiiuse
wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes);
// Uninitialized
g_RealWiiMoteInitialized = false;
}
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
{
g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size);
}
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
{
g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size);
}
//////////////////////////////////
// Read the Wiimote once
// ---------------
void Update()
{
for (int i = 0; i < g_NumberOfWiiMotes; i++)
{ {
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); g_WiiMotes[i]->Update();
// Call Wiiuse.dll
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5);
for (int i=0; i<g_NumberOfWiiMotes; i++)
{
g_WiiMotes[i] = new CWiiMote(i+1, g_WiiMotesFromWiiUse[i]);
}
if (g_NumberOfWiiMotes > 0)
g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL);
return g_NumberOfWiiMotes;
}
void DoState(void* ptr, int mode)
{}
void Shutdown(void)
{
g_Shutdown = true;
// stop the thread
if (g_pReadThread != NULL)
{
g_pReadThread->WaitForDeath();
delete g_pReadThread;
g_pReadThread = NULL;
}
// delete the wiimotes
for (int i=0; i<g_NumberOfWiiMotes; i++)
{
delete g_WiiMotes[i];
g_WiiMotes[i] = NULL;
}
// clean up wiiuse
wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes);
}
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
{
g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size);
}
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
{
g_WiiMotes[0]->SendData(_channelID, (const u8*)_pData, _Size);
}
void Update()
{
for (int i=0; i<g_NumberOfWiiMotes; i++)
{
g_WiiMotes[i]->Update();
}
} }
}
//////////////////////////////////
// Continuously read the Wiimote status
// ---------------
#ifdef _WIN32 #ifdef _WIN32
DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) DWORD WINAPI ReadWiimote_ThreadFunc(void* arg)
#else #else
void *ReadWiimote_ThreadFunc(void* arg) void *ReadWiimote_ThreadFunc(void* arg)
#endif #endif
{
while (!g_Shutdown)
{ {
while (!g_Shutdown) if(g_EmulatorRunning)
{ for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData();
for (int i=0; i<g_NumberOfWiiMotes; i++) else
{ ReadWiimote();
g_WiiMotes[i]->ReadData();
}
}
return 0;
} }
return 0;
}
////////////////////
}; // end of namespace }; // end of namespace

View File

@ -19,16 +19,31 @@
#ifndef WIIMOTE_REAL_H #ifndef WIIMOTE_REAL_H
#define WIIMOTE_REAL_H #define WIIMOTE_REAL_H
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
#include "wiiuse.h"
///////////////////////////////////
namespace WiiMoteReal namespace WiiMoteReal
{ {
#define MAX_WIIMOTES 1
int Initialize(); int Initialize();
void DoState(void* ptr, int mode); void DoState(void* ptr, int mode);
void Shutdown(void); void Shutdown(void);
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size); void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) ; void ControlChannel(u16 _channelID, const void* _pData, u32 _Size);
void Update(); void Update();
void ReadWiimote();
}; #ifndef EXCLUDE_H
extern wiimote_t** g_WiiMotesFromWiiUse;
#endif
}; // WiiMoteReal
#endif #endif