From 8eeb1d02025eef549a935d1df6fe4ca0cbbaf9ca Mon Sep 17 00:00:00 2001 From: John Peterson Date: Sun, 25 Jan 2009 23:07:15 +0000 Subject: [PATCH] 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 --- Source/Core/Core/Src/Core.cpp | 32 +- .../Plugin_Wiimote/Plugin_Wiimote.vcproj | 22 +- Source/Plugins/Plugin_Wiimote/Src/Config.cpp | 5 + Source/Plugins/Plugin_Wiimote/Src/Config.h | 5 +- .../Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp | 128 ++++- Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h | 22 +- .../Plugin_Wiimote/Src/DataReports.cpp | 4 +- Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp | 11 +- .../Plugin_Wiimote/Src/EmuSubroutines.cpp | 6 +- .../Plugin_Wiimote/Src/ReadWiimote.cpp | 139 +++++ Source/Plugins/Plugin_Wiimote/Src/SConscript | 1 + Source/Plugins/Plugin_Wiimote/Src/main.cpp | 173 +++--- Source/Plugins/Plugin_Wiimote/Src/main.h | 51 ++ .../Plugin_Wiimote/Src/wiimote_real.cpp | 508 ++++++++++-------- .../Plugins/Plugin_Wiimote/Src/wiimote_real.h | 19 +- 15 files changed, 771 insertions(+), 355 deletions(-) create mode 100644 Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp create mode 100644 Source/Plugins/Plugin_Wiimote/Src/main.h diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index e4b363ee33..565a47d1ae 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -407,26 +407,24 @@ THREAD_RETURN EmuThread(void *pArg) if (!_CoreParameter.bUseDualCore) { -#ifdef _WIN32 - cpuThread = new Common::Thread(CpuThread, pArg); - //Common::SetCurrentThreadName("Idle thread"); - //TODO(ector) : investigate using GetMessage instead .. although - //then we lose the powerdown check. ... unless powerdown sends a message :P - while (PowerPC::state != PowerPC::CPU_POWERDOWN) - { - if (Callback_PeekMessages) { - Callback_PeekMessages(); - } - Common::SleepCurrentThread(20); - } -#else - // In single-core mode, the Emulation main thread is also the CPU thread - CpuThread(pArg); -#endif + #ifdef _WIN32 + cpuThread = new Common::Thread(CpuThread, pArg); + //Common::SetCurrentThreadName("Idle thread"); + //TODO(ector) : investigate using GetMessage instead .. although + //then we lose the powerdown check. ... unless powerdown sends a message :P + while (PowerPC::state != PowerPC::CPU_POWERDOWN) + { + if (Callback_PeekMessages) Callback_PeekMessages(); + Common::SleepCurrentThread(20); + } + #else + // In single-core mode, the Emulation main thread is also the CPU thread + CpuThread(pArg); + #endif } else { - Plugins.GetVideo()->Video_Prepare(); //wglMakeCurrent + Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent cpuThread = new Common::Thread(CpuThread, pArg); Common::SetCurrentThreadName("Video thread"); Plugins.GetVideo()->Video_EnterLoop(); diff --git a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj index 1b8168b9eb..6ff346bb9e 100644 --- a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj +++ b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj @@ -1,7 +1,7 @@ - - - - @@ -586,6 +578,10 @@ + + @@ -619,6 +615,14 @@ RelativePath=".\Src\main.cpp" > + + + + diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index 8a6ae7c715..4ba6af0ceb 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -39,6 +39,9 @@ void Config::Load() iniFile.Get("Settings", "WideScreen", &bWideScreen, false); iniFile.Get("Settings", "NunchuckConnected", &bNunchuckConnected, false); iniFile.Get("Settings", "ClassicControllerConnected", &bClassicControllerConnected, false); + + iniFile.Get("Real", "Connect", &bConnectRealWiimote, true); + iniFile.Get("Real", "Use", &bUseRealWiimote, true); } void Config::Save() @@ -50,6 +53,8 @@ void Config::Save() iniFile.Set("Settings", "NunchuckConnected", bNunchuckConnected); iniFile.Set("Settings", "ClassicControllerConnected", bClassicControllerConnected); + iniFile.Set("Real", "Connect", bConnectRealWiimote); + iniFile.Set("Real", "Use", bUseRealWiimote); iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index f3d87d692f..e1dab9f3af 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -30,10 +30,13 @@ struct Config void Load(); void Save(); - // General + // Emulated Wiimote bool bSidewaysDPad; bool bWideScreen; bool bNunchuckConnected, bClassicControllerConnected; + + // Real Wiimote + bool bConnectRealWiimote, bUseRealWiimote; }; extern Config g_Config; diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 20462d60d5..327d952fca 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -23,14 +23,15 @@ #include "ConfigDlg.h" #include "Config.h" #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_NUNCHUCKCONNECTED, 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() ///////////////////////////// @@ -57,6 +62,8 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl 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_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; sButtons = new wxBoxSizer(wxHORIZONTAL); //sButtons->Add(m_About, 0, wxALL, 5); // there is no about @@ -87,10 +97,14 @@ void ConfigDialog::CreateGUIControls() sMain = new wxBoxSizer(wxVERTICAL); sMain->Add(m_Notebook, 1, wxEXPAND|wxALL, 5); sMain->Add(sButtons, 0, wxEXPAND, 5); + ///////////////////////////////// + //////////////////////////////////////////// + // Emulated Wiimote + // ---------------- // 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->SetValue(g_Config.bSidewaysDPad); 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->SetValue(g_Config.bClassicControllerConnected); - // ---------------------------------------------------------------------- // Set up sGeneral and sBasic // Usage: The wxGBPosition() must have a column and row // ---------------- - sGeneral = new wxBoxSizer(wxVERTICAL); - sBasic = new wxGridBagSizer(0, 0); - sBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); - sbBasic->Add(sBasic); - sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); + wxBoxSizer * sEmulatedMain = new wxBoxSizer(wxVERTICAL); + wxGridBagSizer * GbsBasic = new wxGridBagSizer(0, 0); + GbsBasic->Add(m_SidewaysDPad, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5); + GbsBasic->Add(m_WideScreen, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL, 5); + GbsBasic->Add(m_NunchuckConnected, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); + GbsBasic->Add(m_ClassicControllerConnected, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); + sEmulatedBasic->Add(GbsBasic); + 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(); Center(); + ///////////////////////////////// } 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) { @@ -214,5 +274,31 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id)); DoExtensionConnectedDisconnected(); 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); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 4c34c4fe00..bac5d801ae 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -43,20 +43,18 @@ class ConfigDialog : public wxDialog private: DECLARE_EVENT_TABLE(); - - wxBoxSizer* sGeneral; - wxStaticBoxSizer* sbBasic; - wxGridBagSizer* sBasic; wxButton *m_About; wxButton *m_Close; wxNotebook *m_Notebook; wxPanel *m_PageEmu, *m_PageReal; - wxCheckBox *m_SidewaysDPad; // general settings + wxCheckBox *m_SidewaysDPad; // Emulated Wiimote settings wxCheckBox *m_WideScreen; wxCheckBox *m_NunchuckConnected, *m_ClassicControllerConnected; + wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote; // Real Wiimote settings + enum { ID_CLOSE = 1000, @@ -66,17 +64,25 @@ class ConfigDialog : public wxDialog ID_PAGEEMU, ID_PAGEREAL, - ID_SIDEWAYSDPAD, + ID_SIDEWAYSDPAD, // Emulated ID_WIDESCREEN, - ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED + ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED, + + // Real + ID_CONNECT_REAL, ID_USE_REAL }; void OnClose(wxCloseEvent& event); void CreateGUIControls(); void AboutClick(wxCommandEvent& event); - void DoExtensionConnectedDisconnected(); + + void DoConnectReal(); // Real + + void DoExtensionConnectedDisconnected(); // Emulated + void GeneralSettingsChanged(wxCommandEvent& event); + void UpdateGUI(); }; #endif diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index 42496ebbbb..3ac92b0ecf 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -91,8 +91,8 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr) 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, " Mode: 0x%02x", 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 mode: 0x%02x\n", dr->mode); + Console::Print("Data reporting channel: 0x%04x\n", _channelID); g_ReportingMode = dr->mode; g_ReportingChannel = _channelID; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index a0080c04bd..7eebfa57d0 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -267,7 +267,7 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) //if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA) // && data[3] == 0xa4) //{ - CreateAckDelay((u8)_channelID, (u16)sr->channel); + if (!g_Config.bUseRealWiimote) CreateAckDelay((u8)_channelID, (u16)sr->channel); //} //else //{ @@ -353,15 +353,16 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) void Update() { //LOG(WII_IPC_WIIMOTE, "Wiimote_Update"); + Console::Print("g_ReportingMode %i\n", g_ReportingMode); switch(g_ReportingMode) { case 0: break; - case WM_REPORT_CORE: SendReportCore(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_EXT16: SendReportCoreAccelExt16(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_IR12: SendReportCoreAccelIr12(g_ReportingChannel); break; + case WM_REPORT_CORE_ACCEL_EXT16: SendReportCoreAccelExt16(g_ReportingChannel); break; case WM_REPORT_CORE_ACCEL_IR10_EXT6: SendReportCoreAccelIr10Ext(g_ReportingChannel);break; } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index df3908346d..66396e9d53 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -97,12 +97,12 @@ void HidOutputReport(u16 _channelID, wm_report* sr) { WmDataReporting(_channelID, (wm_data_reporting*)sr->data); break; 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); //Console::Print("\n%s: InterruptChannel: %s\n", Tm().c_str(), Temp.c_str()); break; case WM_READ_DATA: // 0x17 - WmReadData(_channelID, (wm_read_data*)sr->data); + if (!g_Config.bUseRealWiimote) WmReadData(_channelID, (wm_read_data*)sr->data); break; /* 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; case WM_WRITE_DATA: // 0x16 - WmWriteData(_channelID, (wm_write_data*)sr->data); + if (!g_Config.bUseRealWiimote) WmWriteData(_channelID, (wm_write_data*)sr->data); break; case WM_SPEAKER_ENABLE: // 0x14 LOGV(WII_IPC_WIIMOTE, 1, " WM Speaker Enable 0x%02x: 0x%02x", sr->channel, sr->data[0]); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp new file mode 100644 index 0000000000..40c988391f --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -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 // 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 \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/SConscript b/Source/Plugins/Plugin_Wiimote/Src/SConscript index 805feb2cdc..5a5650d212 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/SConscript +++ b/Source/Plugins/Plugin_Wiimote/Src/SConscript @@ -29,6 +29,7 @@ cxxflags = [ '-fPIC' ] if wmenv['HAVE_WIIUSE']: libs += [ 'wiiuse' ] files += [ "wiimote_real.cpp" ] + files += [ "ReadWiimote.cpp" ] cxxflags += ['-DHAVE_WIIUSE'] wmenv.Append( diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index db5a3b5e12..5e72dbb24a 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -25,16 +25,16 @@ #include "ConsoleWindow.h" // For Start, Print, GetHwnd #if defined(HAVE_WX) && HAVE_WX -#include -#include "ConfigDlg.h" + #include + #include "ConfigDlg.h" #endif +#define EXCLUDEMAIN_H // Avoid certain declarations in main.h +#include "Main.h" // Local #include "pluginspecs_wiimote.h" - #include "EmuMain.h" - #if HAVE_WIIUSE -#include "wiimote_real.h" + #include "wiimote_real.h" #endif /////////////////////////////////// @@ -44,7 +44,10 @@ // ŻŻŻŻŻŻŻŻŻŻŻŻŻ 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; @@ -105,67 +108,64 @@ extern "C" void GetDllInfo (PLUGIN_INFO* _PluginInfo) { _PluginInfo->Version = 0x0100; _PluginInfo->Type = PLUGIN_TYPE_WIIMOTE; -#ifdef DEBUGFAST - sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (DebugFast)"); -#else -#ifndef _DEBUG - sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin"); -#else - sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (Debug)"); -#endif -#endif + #ifdef DEBUGFAST + sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (DebugFast)"); + #else + #ifndef _DEBUG + sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin"); + #else + sprintf(_PluginInfo->Name, "Dolphin Wiimote Plugin (Debug)"); + #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) { #if defined(HAVE_WX) && HAVE_WX + wxWindow win; -#ifdef _WIN32 - win.SetHWND(_hParent); -#endif + + #ifdef _WIN32 + win.SetHWND(_hParent); + #endif + + DoInitialize(); + g_FrameOpen = true; ConfigDialog frame(&win); frame.ShowModal(); -#ifdef _WIN32 - win.SetHWND(0); -#endif + //frame.Show(); + + #ifdef _WIN32 + win.SetHWND(0); + #endif + #endif } extern "C" void Initialize(void *init) { + // Declarations 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; - /* 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_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 + g_EmulatorRunning = true; - 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); } -extern "C" void Shutdown(void) -{ -#if HAVE_WIIUSE - WiiMoteReal::Shutdown(); -#endif - WiiMoteEmu::Shutdown(); -} // =================================================== /* 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 - if (! g_UseRealWiiMote) + //if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) WiiMoteEmu::InterruptChannel(_channelID, _pData, _Size); #if HAVE_WIIUSE - else + //else if (g_RealWiiMotePresent) WiiMoteReal::InterruptChannel(_channelID, _pData, _Size); #endif 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) { 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()); } - - if (! g_UseRealWiiMote) - WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); + if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) + WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); #if HAVE_WIIUSE - else - WiiMoteReal::ControlChannel(_channelID, _pData, _Size); + else if (g_RealWiiMotePresent) + WiiMoteReal::ControlChannel(_channelID, _pData, _Size); #endif 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() { - if (! g_UseRealWiiMote) - WiiMoteEmu::Update(); + if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) + WiiMoteEmu::Update(); #if HAVE_WIIUSE - else - WiiMoteReal::Update(); + else if (g_RealWiiMotePresent) + WiiMoteReal::Update(); #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, ...) { char Msg[512]; @@ -285,4 +318,6 @@ void __Logv(int log, int v, const char *_fmt, ...) g_WiimoteInitialize.pLog(Msg, v); } -// ================ + + + diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.h b/Source/Plugins/Plugin_Wiimote/Src/main.h new file mode 100644 index 0000000000..731f790373 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote/Src/main.h @@ -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 // 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 \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 9a6edb8dcc..8e783c755f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -15,6 +15,11 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ + +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻ +#include // System #include "pluginspecs_wiimote.h" #include "wiiuse.h" @@ -22,273 +27,340 @@ #include "Common.h" #include "Thread.h" +#include "StringUtil.h" +#include "ConsoleWindow.h" #include "wiimote_hid.h" +#include "main.h" #include "EmuMain.h" - +#define EXCLUDE_H // Avoid certain declarations in main.h +#include "wiimote_real.h" extern SWiimoteInitialize g_WiimoteInitialize; -//extern void __Log(int log, const char *format, ...); -//extern void __Log(int log, int v, const char *format, ...); +//////////////////////////////////////// namespace WiiMoteReal { -#define MAX_WIIMOTES 1 //****************************************************************************** // Forwarding //****************************************************************************** - class CWiiMote; +class CWiiMote; + #ifdef _WIN32 - DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg); #else - void* ReadWiimote_ThreadFunc(void* arg); + void* ReadWiimote_ThreadFunc(void* arg); #endif //****************************************************************************** // Variable declarations //****************************************************************************** - wiimote_t** g_WiiMotesFromWiiUse = NULL; - Common::Thread* g_pReadThread = NULL; - int g_NumberOfWiiMotes; - CWiiMote* g_WiiMotes[MAX_WIIMOTES]; - bool g_Shutdown = false; +wiimote_t** g_WiiMotesFromWiiUse = NULL; +Common::Thread* g_pReadThread = NULL; +int g_NumberOfWiiMotes; +CWiiMote* g_WiiMotes[MAX_WIIMOTES]; +bool g_Shutdown = false; +bool g_LocalThread = true; //****************************************************************************** // 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: - - CWiiMote(u8 _WiimoteNumber, wiimote_t* _pWiimote) - : m_WiimoteNumber(_WiimoteNumber) - , m_channelID(0) - , m_pWiiMote(_pWiimote) - , m_pCriticalSection(NULL) - , m_LastReportValid(false) + SEvent WriteEvent; + memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); + m_EventWriteQueue.push(WriteEvent); + } + m_pCriticalSection->Leave(); +} +///////////////////// + + +////////////////////////////////////////// +// Read data from wiimote (but don't send it to the core, just filter and queue) +// --------------- +void ReadData() +{ + 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(); + + // Filter out reports + if (pBuffer[0] >= 0x30) { - SEvent WriteEvent; - memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); - m_EventWriteQueue.push(WriteEvent); + // Copy Buffer to LastReport + memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD); + 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 - { - 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]; - }; - typedef std::queue 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); + m_pCriticalSection->Leave(); } + + //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 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 //****************************************************************************** - 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); - - // Call Wiiuse.dll - g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); - g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); - - for (int i=0; i 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; iSendData(_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; iUpdate(); - } + g_WiiMotes[i]->Update(); } +} +////////////////////////////////// +// Continuously read the Wiimote status +// --------------- #ifdef _WIN32 - DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) + DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) #else - void *ReadWiimote_ThreadFunc(void* arg) + void *ReadWiimote_ThreadFunc(void* arg) #endif +{ + while (!g_Shutdown) { - while (!g_Shutdown) - { - for (int i=0; iReadData(); - } - } - return 0; + if(g_EmulatorRunning) + for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData(); + else + ReadWiimote(); } + return 0; +} +//////////////////// + }; // end of namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h index 92ba15af75..3c3b3ad078 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h @@ -19,16 +19,31 @@ #ifndef WIIMOTE_REAL_H #define WIIMOTE_REAL_H + +////////////////////////////////////////////////////////////////////////////////////////// +// Includes +// ŻŻŻŻŻŻŻŻŻŻŻŻŻ +#include "wiiuse.h" +/////////////////////////////////// + + namespace WiiMoteReal { +#define MAX_WIIMOTES 1 + int Initialize(); void DoState(void* ptr, int mode); void Shutdown(void); 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 ReadWiimote(); -}; +#ifndef EXCLUDE_H + extern wiimote_t** g_WiiMotesFromWiiUse; +#endif + +}; // WiiMoteReal #endif \ No newline at end of file