From fcdd2a8e17714e8a6485ae06a6c67e696a06e438 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Sat, 7 Feb 2009 03:16:41 +0000 Subject: [PATCH] Wiimote: 1. Fixed the dual mode. You should now be able to change between the real and emulated Wiimote at any time, even when the Nunchuck is connected. It also supports third party Wireless Nunchucks that never sends any calibration values. The Nunchuck status should be automatically updated. The Nunchuck stick may get stuck, but that should fix itself if you disconnect and reconnect again. The only important problems seems to be that the real Wiimote fails to answer sometimes so that the Core functions disconnect it. 2. Began looking at how to reconnect the Wiimote after an unwanted HCI disconnect command git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2129 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/Common.h | 67 ++++-- Source/Core/Common/Src/ConsoleWindow.cpp | 7 +- Source/Core/Common/Src/StringUtil.cpp | 12 +- Source/Core/Core/Src/Core.cpp | 8 +- Source/Core/Core/Src/Core.h | 1 + Source/Core/Core/Src/HW/HW.cpp | 6 + Source/Core/Core/Src/HW/HW.h | 1 + .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 13 +- Source/Core/DolphinWX/Src/Frame.cpp | 15 +- Source/MusicMod.sln | 2 + Source/PluginSpecs/PluginSpecs.h | 15 ++ .../Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp | 12 +- .../Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp | 69 ++++-- Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h | 3 +- .../Plugin_Wiimote/Src/EmuDefinitions.cpp | 2 +- .../Plugin_Wiimote/Src/EmuDefinitions.h | 19 +- Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp | 26 +++ .../Plugin_Wiimote/Src/EmuSubroutines.cpp | 22 +- .../Plugin_Wiimote/Src/EmuSubroutines.h | 2 +- .../Plugins/Plugin_Wiimote/Src/FillReport.cpp | 73 +++--- .../Plugin_Wiimote/Src/ReadWiimote.cpp | 12 +- Source/Plugins/Plugin_Wiimote/Src/main.cpp | 217 ++++++++++++++---- Source/Plugins/Plugin_Wiimote/Src/main.h | 6 + .../Plugins/Plugin_Wiimote/Src/wiimote_hid.h | 9 + .../Plugin_Wiimote/Src/wiimote_real.cpp | 103 +-------- .../Plugins/Plugin_Wiimote/Src/wiimote_real.h | 3 + 26 files changed, 466 insertions(+), 259 deletions(-) diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index 646f335027..ac8f57e772 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -18,11 +18,19 @@ #ifndef _COMMON_H #define _COMMON_H + +////////////////////////////////////////////////////////////////////////////////////////// +// Settings +// ----------------- #define _CRTDBG_MAP_ALLOC #define _CRTDBG_MAP_ALLOC_NEW - #define CHECK_HEAP_INTEGRITY() +////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////// +// Include +// ----------------- #ifdef _WIN32 #ifdef _DEBUG #include @@ -49,30 +57,37 @@ #include #include "Paths.h" +/////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////////////////// +// Settings +// ----------------- // Darwin ABI requires that stack frames be aligned to 16-byte boundaries. // This probably wouldn't break anyone either, but hey #ifdef __APPLE__ -#define STACKALIGN __attribute__((__force_align_arg_pointer__)) + #define STACKALIGN __attribute__((__force_align_arg_pointer__)) #else -#define STACKALIGN + #define STACKALIGN #endif + // Function Cross-Compatibility #ifdef _WIN32 -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#define unlink _unlink -#define snprintf _snprintf + #define strcasecmp _stricmp + #define strncasecmp _strnicmp + #define unlink _unlink + #define snprintf _snprintf #else -#define _stricmp strcasecmp -#define _strnicmp strncasecmp -#define _unlink unlink -#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) + #define _stricmp strcasecmp + #define _strnicmp strncasecmp + #define _unlink unlink + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #endif -#ifdef _WIN32 +#ifdef _WIN32 // By default, MS' stdio implementation does not support 64-bit offsets. // This little hack fixes that, keeping the code portable to linux where fseek and fread // do support 64-bit offsets in modern distributions. @@ -164,9 +179,19 @@ template inline T min(const T& a, const T& b) {return a > b ? b : a;} template inline T max(const T& a, const T& b) {return a > b ? a : b;} +/////////////////////////////////// + + +// ************************************************************************************** +// Utility functions +// ************************************************************************************** + + + +////////////////////////////////////////////////////////////////////////////////////////// // Byte ordering - +// ----------------- namespace Common { inline u8 swap8(u8 _data) {return(_data);} @@ -194,12 +219,12 @@ inline u64 swap64(u64 data) {return(((u64)swap32(data) << 32) | swap32(data >> 3 #endif } // end of namespace Common +/////////////////////////////////// -// Utility functions - - +////////////////////////////////////////////////////////////////////////////////////////// // Message alerts +// ----------------- enum MSG_TYPE { INFORMATION, @@ -223,10 +248,12 @@ extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* fo #define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__) #define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__) #endif +/////////////////////////////////// - +////////////////////////////////////////////////////////////////////////////////////////// // Logging +// ----------------- // dummy class class LogTypes @@ -328,9 +355,12 @@ void Host_UpdateLogDisplay(); #define _assert_(a) #define _assert_msg_(...) #endif +/////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// // Compile time asserts +// ----------------- namespace { @@ -346,8 +376,9 @@ namespace #endif #endif } +/////////////////////////////////////// -#endif // #ifndef _COMMON_H +#endif // _COMMON_H diff --git a/Source/Core/Common/Src/ConsoleWindow.cpp b/Source/Core/Common/Src/ConsoleWindow.cpp index 9e6404b9fe..68273e013d 100644 --- a/Source/Core/Common/Src/ConsoleWindow.cpp +++ b/Source/Core/Common/Src/ConsoleWindow.cpp @@ -95,16 +95,19 @@ void Close() // Print to screen and file int Print(const char *fmt, ...) { + // Maximum bytes, mind this value to avoid an overrun + static const int MAX_BYTES = 1024*20; + #if defined(_WIN32) if(__hStdOut) { #endif - char s[1024*20]; // Warning, mind this value + char s[MAX_BYTES]; va_list argptr; int cnt; // To store the vsnprintf return message va_start(argptr, fmt); - cnt = vsnprintf(s, 500, fmt, argptr); + cnt = vsnprintf(s, MAX_BYTES, fmt, argptr); va_end(argptr); diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 27ec6a7a2d..9a7da21740 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -151,16 +151,14 @@ std::string StringFromFormat(const char* format, ...) // ---------------- std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len, bool Spaces) { - std::string Temp; + std::string Tmp, Spc; + if (Spaces) Spc = " "; else Spc = ""; for (u32 i = 0; i < size; i++) { - char Buffer[128]; - if (Spaces) sprintf(Buffer, "%02x ", data[i + offset]); - else sprintf(Buffer, "%02x", data[i + offset]); - if(i > 0 && i % line_len == 0) Temp.append("\n"); // break long lines - Temp.append(Buffer); + Tmp += StringFromFormat("%02x%s", data[i + offset], Spc.c_str()); + if(i > 1 && (i + 1) % line_len == 0) Tmp.append("\n"); // break long lines } - return Temp; + return Tmp; } // ================ diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index a8c20f33b3..381fda36c0 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -144,6 +144,12 @@ bool GetRealWiimote() { return g_bRealWiimote; } +// This doesn't work yet, I don't understand how the connection work yet +void ReconnectWiimote() +{ + HW::InitWiimote(); + Console::Print("ReconnectWiimote()\n"); +} ///////////////////////////////////// @@ -293,7 +299,7 @@ THREAD_RETURN EmuThread(void *pArg) LOG(OSREPORT, "Dualcore = %s", _CoreParameter.bUseDualCore ? "Yes" : "No"); HW::Init(); - + emuThreadGoing.Set(); // Load the VideoPlugin diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h index d784882e6f..3dcf8ae49b 100644 --- a/Source/Core/Core/Src/Core.h +++ b/Source/Core/Core/Src/Core.h @@ -60,6 +60,7 @@ namespace Core bool MakeScreenshot(const std::string& _rFilename); void* GetWindowHandle(); bool GetRealWiimote(); + void ReconnectWiimote(); extern bool bReadTrace; extern bool bWriteTrace; diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp index d861f77082..15c3f8fe5d 100644 --- a/Source/Core/Core/Src/HW/HW.cpp +++ b/Source/Core/Core/Src/HW/HW.cpp @@ -108,4 +108,10 @@ namespace HW AudioInterface::DoState(p); WII_IPCInterface::DoState(p); } + + // Restart Wiimote + void InitWiimote() + { + WII_IPCInterface::Init(); + } } diff --git a/Source/Core/Core/Src/HW/HW.h b/Source/Core/Core/Src/HW/HW.h index 131f08072f..667e60f4d3 100644 --- a/Source/Core/Core/Src/HW/HW.h +++ b/Source/Core/Core/Src/HW/HW.h @@ -26,6 +26,7 @@ namespace HW void Init(); void Shutdown(); void DoState(PointerWrap &p); + void InitWiimote(); } #endif diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 718d85f95e..b71f8fbce8 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -19,12 +19,13 @@ ////////////////////////////////////////////////////////////////////////////////////////// // Include // ŻŻŻŻŻŻŻŻŻŻŻŻŻ -#include "WII_IPC_HLE_Device_usb.h" -#include "../PluginManager.h" +#include "ConsoleWindow.h" // Common #include "../Core.h" // Local core functions #include "../Debugger/Debugger_SymbolMap.h" #include "../Host.h" +#include "../PluginManager.h" +#include "WII_IPC_HLE_Device_usb.h" /////////////////////// @@ -1783,6 +1784,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input) "anyway. It is strongly recommed to save and/or restart the\n" "emulation."); } + Console::Print("IPC CommandDisconnect\n"); + + // Send message to plugin + /* + Common::PluginWiimote* mote = CPluginManager::GetInstance().GetWiimote(0); + u8 Message = WIIMOTE_RECONNECT; + mote->Wiimote_ControlChannel(99, &Message, 0); + */ } void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkSupervisionTimeout(u8* _Input) diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 254c469763..17ae644c67 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -47,6 +47,7 @@ be accessed from Core::GetWindowHandle(). #include "Common.h" // Common #include "FileUtil.h" #include "Timer.h" +#include "ConsoleWindow.h" #include "ConfigManager.h" // Core #include "Core.h" @@ -170,16 +171,26 @@ int abc = 0; switch(wParam) { // Stop - case 5: + case OPENGL_WM_USER_STOP: main_frame->DoStop(); return 0; // Don't bother letting wxWidgets process this at all - case 15: + case OPENGL_WM_USER_CREATE: // We don't have a local setting for bRenderToMain but we can detect it this way instead //PanicAlert("main call %i %i %i %i", lParam, (HWND)Core::GetWindowHandle(), MSWGetParent_((HWND)Core::GetWindowHandle()), (HWND)this->GetHWND()); if (lParam == NULL) main_frame->bRenderToMain = false; else main_frame->bRenderToMain = true; return 0; + + case NJOY_RELOAD: + // DirectInput in nJoy has failed + return 0; + + case WIIMOTE_RECONNECT: + // The Wiimote plugin has been shut down, now reconnect the Wiimote + Console::Print("WIIMOTE_RECONNECT\n"); + Core::ReconnectWiimote(); + return 0; } break; diff --git a/Source/MusicMod.sln b/Source/MusicMod.sln index 96371edfe1..5db2e937be 100644 --- a/Source/MusicMod.sln +++ b/Source/MusicMod.sln @@ -56,6 +56,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DolphinWX", "Core\DolphinWX\DolphinWX.vcproj", "{A72606EF-C5C1-4954-90AD-F0F93A8D97D9}" ProjectSection(ProjectDependencies) = postProject {48AD7E0A-25B1-4974-A1E3-03F8C438D34F} = {48AD7E0A-25B1-4974-A1E3-03F8C438D34F} + {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160} = {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160} {0318BA30-EF48-441A-9E10-DC85EFAE39F0} = {0318BA30-EF48-441A-9E10-DC85EFAE39F0} {8D612734-FAA5-4B8A-804F-4DEA2367D495} = {8D612734-FAA5-4B8A-804F-4DEA2367D495} {71B16F46-0B00-4EDA-B253-D6D9D03A215C} = {71B16F46-0B00-4EDA-B253-D6D9D03A215C} @@ -228,6 +229,7 @@ Global {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.DebugFast|Win32.ActiveCfg = DebugFast|Win32 {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.DebugFast|x64.ActiveCfg = DebugFast|x64 {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.ActiveCfg = Release|Win32 + {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|Win32.Build.0 = Release|Win32 {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.ActiveCfg = Release|x64 {CFDCEE0E-FA45-4F72-9FCC-0B88F5A75160}.Release|x64.Build.0 = Release|x64 {C573CAF7-EE6A-458E-8049-16C0BF34C2E9}.Debug|Win32.ActiveCfg = Debug|Win32 diff --git a/Source/PluginSpecs/PluginSpecs.h b/Source/PluginSpecs/PluginSpecs.h index c35acc4b9c..252f3cd2ca 100644 --- a/Source/PluginSpecs/PluginSpecs.h +++ b/Source/PluginSpecs/PluginSpecs.h @@ -17,6 +17,21 @@ /////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// +/* Plugin communication. I place this here rather in Common.h since these messages are only received + at one place, by the CPanel in Frame.cpp. That way I don't have to rebuild if any of this is changed */ +// ----------------- +enum PLUGIN_COMM +{ + // Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on + OPENGL_WM_USER_STOP = 10, + OPENGL_WM_USER_CREATE, + NJOY_RELOAD, // Reload nJoy if DirectInput has failed + WIIMOTE_RECONNECT // Reconnect the Wiimote if it has disconnected +}; +/////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////////////////// // System specific declarations and definitions // ------------ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp index f0552897f8..287e47ed7c 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp @@ -138,7 +138,7 @@ namespace EmuWindow switch( iMsg ) { case WM_CREATE: - PostMessage(m_hMain, WM_USER, 15, (int)m_hParent); // 15 = WM_USER_CREATE, make enum table if it's confusing + PostMessage(m_hMain, WM_USER, OPENGL_WM_USER_CREATE, (int)m_hParent); break; case WM_PAINT: @@ -154,13 +154,15 @@ namespace EmuWindow //PostQuitMessage(0); /* The fullscreen option for Windows users is not very user friendly. With this the user - can only get out of the fullscreen mode by pressing Esc or Alt + F4. But that also - closes*/ + can only get out of the fullscreen mode by pressing Esc or Alt + F4. Esc also stops + the emulation. Todo: But currently it hangs, so I have disabled the shutdown. */ //if(m_hParent == NULL) ExitProcess(0); if(m_hParent == NULL) - { + { if (g_Config.bFullscreen) - PostMessage(m_hMain, WM_USER, 5, 0); // Stop + { + //PostMessage(m_hMain, WM_USER, OPENGL_WM_USER_STOP, 0); // Stop + } else // Toggle maximize and restore if (IsZoomed(hWnd)) ShowWindow(hWnd, SW_RESTORE); else ShowWindow(hWnd, SW_MAXIMIZE); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 2722c2afec..1a58af50b8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -765,7 +765,7 @@ void ConfigDialog::CreateGUIControls() // =================================================== -/* Do use real wiimote */ +/* Do connect real wiimote */ // ---------------- void ConfigDialog::DoConnectReal() { @@ -777,15 +777,53 @@ void ConfigDialog::DoConnectReal() } else { - if (g_RealWiiMoteInitialized) WiiMoteReal::Shutdown(); + Console::Print("Post Message: %i\n", g_RealWiiMoteInitialized); + if (g_RealWiiMoteInitialized) + { + WiiMoteReal::Shutdown(); + /* + if (g_WiimoteUnexpectedDisconnect) + { + #ifdef _WIN32 + PostMessage(g_ParentHWND, WM_USER, WIIMOTE_RECONNECT, 0); + g_WiimoteUnexpectedDisconnect = false; + #endif + } + */ + } } } +// =================================================== +/* Do use real wiimote. We let the game set up the real Wiimote reporting mode and init the Extension when we change + want to use it again. */ +// ---------------- +void ConfigDialog::DoUseReal() +{ + // Clear any eventual events in the Wiimote queue + WiiMoteReal::ClearEvents(); + + // Are we using an extension now? The report that it's removed, then reconnected. + bool UsingExtension = false; + if (g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected) + UsingExtension = true; + + Console::Print("\nDoUseReal() Connect extension: %i\n", !UsingExtension); + DoExtensionConnectedDisconnected(UsingExtension ? 0 : 1); + // Sleep this thread + sleep(100); + UsingExtension = !UsingExtension; + Console::Print("\nDoUseReal() Connect extension: %i\n", !UsingExtension); + DoExtensionConnectedDisconnected(UsingExtension ? 1 : 0); + // Sleep again, to allow the approximate time it takes for the Wiimote to come online + sleep(200); +} + // =================================================== /* Generate connect/disconnect status event */ // ---------------- -void ConfigDialog::DoExtensionConnectedDisconnected() +void ConfigDialog::DoExtensionConnectedDisconnected(int Extension) { // There is no need for this if no game is running if(!g_EmulatorRunning) return; @@ -795,7 +833,7 @@ void ConfigDialog::DoExtensionConnectedDisconnected() // Check if a game is running, in that case change the status if(WiiMoteEmu::g_ReportingChannel > 0) - WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs); + WiiMoteEmu::WmRequestStatus(WiiMoteEmu::g_ReportingChannel, rs, Extension); } // =================================================== @@ -809,9 +847,9 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) DoConnectReal(); break; case ID_USE_REAL: + // Enable the Wiimote thread g_Config.bUseRealWiimote = m_UseRealWiimote[Page]->IsChecked(); - //if(g_Config.bUseRealWiimote) WiiMoteReal::SetDataReportingMode(); - if(g_Config.bUseRealWiimote) WiiMoteReal::ClearEvents(); + if(g_Config.bUseRealWiimote) DoUseReal(); break; case ID_SIDEWAYSDPAD: @@ -842,8 +880,8 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) g_Config.bNunchuckConnected = m_NunchuckConnected[Page]->IsChecked(); // Copy the calibration data - memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration, - sizeof(WiiMoteEmu::nunchuck_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::nunchuck_calibration, sizeof(WiiMoteEmu::nunchuck_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::nunchuck_calibration, sizeof(WiiMoteEmu::nunchuck_calibration)); memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::nunchuck_id, sizeof(WiiMoteEmu::nunchuck_id)); // Generate connect/disconnect status event @@ -862,8 +900,8 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) g_Config.bClassicControllerConnected = m_ClassicControllerConnected[Page]->IsChecked(); // Copy the calibration data - memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration, - sizeof(WiiMoteEmu::classic_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::classic_calibration, sizeof(WiiMoteEmu::classic_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::classic_calibration, sizeof(WiiMoteEmu::classic_calibration)); memcpy(WiiMoteEmu::g_RegExt + 0xfa, WiiMoteEmu::classic_id, sizeof(WiiMoteEmu::classic_id)); // Generate connect/disconnect status event DoExtensionConnectedDisconnected(); @@ -925,14 +963,13 @@ void ConfigDialog::UpdateGUI() { Console::Print("UpdateGUI: \n"); - /* We can't allow different values for this one if we are using the real and emulated wiimote - side by side so that we can switch between between during gameplay. We update the checked - or unchecked values from the g_Config settings, and we make sure they are up to date with - unplugged and reinserted extensions. */ + /* We only allow a change of extension if we are not currently using the real Wiimote, if it's in use the status will be updated + from the data scanning functions in main.cpp */ + bool AllowExtensionChange = !(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_Config.bUseRealWiimote && g_EmulatorRunning); m_NunchuckConnected[Page]->SetValue(g_Config.bNunchuckConnected); m_ClassicControllerConnected[Page]->SetValue(g_Config.bClassicControllerConnected); - m_NunchuckConnected[Page]->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning)); - m_ClassicControllerConnected[Page]->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning)); + m_NunchuckConnected[Page]->Enable(AllowExtensionChange); + m_ClassicControllerConnected[Page]->Enable(AllowExtensionChange); /* I have disabled this option during a running game because it's enough to be able to switch between using and not using then. To also use the connect option during a running game would diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 8823e5107c..b8eb634be4 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -156,8 +156,9 @@ class ConfigDialog : public wxDialog void AboutClick(wxCommandEvent& event); void DoConnectReal(); // Real + void DoUseReal(); - void DoExtensionConnectedDisconnected(); // Emulated + void DoExtensionConnectedDisconnected(int Extension = -1); // Emulated void GeneralSettingsChanged(wxCommandEvent& event); }; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index 667af949fd..9845c397f6 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -50,7 +50,6 @@ u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; -u8 g_RegExtTmpReport[WIIMOTE_REG_EXT_SIZE]; u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; u8 g_ReportingMode; // The reporting mode and channel id @@ -59,6 +58,7 @@ u16 g_ReportingChannel; std::vector AckDelay; // Ackk delay wiimote_key g_ExtKey; // The extension encryption key +bool g_Encryption; // Encryption on or off } // namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index 69fcf2cd57..7366e89232 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -78,7 +78,6 @@ extern u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; extern u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; extern u8 g_RegExt[WIIMOTE_REG_EXT_SIZE]; extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; -extern u8 g_RegExtTmpReport[WIIMOTE_REG_EXT_SIZE]; extern u8 g_RegIr[WIIMOTE_REG_IR_SIZE]; extern u8 g_ReportingMode; @@ -95,6 +94,7 @@ struct wm_ackdelay extern std::vector AckDelay; extern wiimote_key g_ExtKey; // extension encryption key +extern bool g_Encryption; /* An example of a factory default first bytes of the Eeprom memory. There are differences between different Wiimotes, my Wiimote had different neutral values for the accelerometer. */ @@ -120,11 +120,15 @@ static const u8 nunchuck_calibration[] = 0x80,0x80,0x80,0x00, // accelerometer x, y, z neutral 0xb3,0xb3,0xb3,0x00, // x, y, z g-force values - 0xe0, 0x20, 0x80, 0xe0, // 0x80 = analog stick x and y axis center - 0x20, 0x80, 0xee, 0x43, - - 0x80,0x80,0x80,0x00, 0xb3,0xb3,0xb3,0x00, // repeat - 0xe0,0x20,0x80,0xe0, 0x20,0x80,0xee,0x43 + 0xff, 0x00, 0x80, 0xff, // 0x80 = analog stick x and y axis center + 0x00, 0x80, 0xee, 0x43 // checksum on the last two bytes +}; +static const u8 wireless_nunchuck_calibration[] = +{ + 128, 128, 128, 0x00, + 181, 181, 181, 0x00, + 255, 0, 125, 255, + 0, 126, 0xed, 0x43 }; /* Classic Controller calibration. 0x80 is the neutral for the analog triggers and @@ -133,9 +137,6 @@ static const u8 nunchuck_calibration[] = static const u8 classic_calibration[] = { 0xe4,0x1c,0x80,0xe4, 0x1c,0x80,0xd8,0x28, - 0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea, - - 0xe4,0x1c,0x80,0xe4, 0x1c,0x80,0xd8,0x28, // repeat 0x80,0xd8,0x28,0x80, 0x20,0x20,0x95,0xea }; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 7a4e98b5e2..f2d54f94e1 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -232,10 +232,33 @@ void UpdateEeprom() g_accel.cal_g.y = g_Eeprom[27] - g_Eeprom[24]; g_accel.cal_g.z = g_Eeprom[28] - g_Eeprom[24]; + g_nu.cal_zero.x = g_RegExt[0x20]; + g_nu.cal_zero.y = g_RegExt[0x21]; + g_nu.cal_zero.z = g_RegExt[0x22]; + g_nu.jx.max = g_RegExt[0x28]; + g_nu.jx.min = g_RegExt[0x29]; + g_nu.jx.center = g_RegExt[0x2a]; + g_nu.jy.max = g_RegExt[0x2b]; + g_nu.jy.min = g_RegExt[0x2c]; + g_nu.jy.center = g_RegExt[0x2d]; + Console::Print("UpdateEeprom: %i %i %i\n", WiiMoteEmu::g_Eeprom[22], WiiMoteEmu::g_Eeprom[23], WiiMoteEmu::g_Eeprom[27]); } +// Calculate checksum for the nunchuck calibration. The last two bytes. +void ExtensionChecksum(u8 * Calibration) +{ + u8 sum = 0; u8 Byte15, Byte16; + for (int i = 0; i < sizeof(Calibration) - 2; i++) + { + sum += Calibration[i]; + printf("Plus 0x%02x\n", Calibration[i]); + } + Byte15 = sum + 0x55; // Byte 15 + Byte16 = sum + 0xaa; // Byte 16 +} + // Set initial values void ResetVariables() { @@ -246,6 +269,7 @@ void ResetVariables() g_ReportingMode = 0; g_ReportingChannel = 0; + g_Encryption = false; g_EmulatedWiiMoteInitialized = false; } @@ -277,11 +301,13 @@ void Initialize() if(g_Config.bNunchuckConnected) { memcpy(g_RegExt + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration)); memcpy(g_RegExt + 0xfa, nunchuck_id, sizeof(nunchuck_id)); } else if(g_Config.bClassicControllerConnected) { memcpy(g_RegExt + 0x20, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt + 0x30, classic_calibration, sizeof(classic_calibration)); memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id)); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index d6f779afd8..a33d64fbc9 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -370,6 +370,7 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) // Add header values pReply->buttons = 0; pReply->error = 0; + // 0x1 means two bytes, 0xf means 16 bytes pReply->size = (copySize - 1) & 0xf; pReply->address = Common::swap16(_Address + dataOffset); @@ -534,7 +535,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) request rs and all its eventual instructions it may include (for example turn off rumble or something else) and just send the status report. */ // ---------------- -void WmRequestStatus(u16 _channelID, wm_request_status* rs) +void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension) { //PanicAlert("WmRequestStatus"); LOGV(WII_IPC_WIIMOTE, 0, "================================================"); @@ -562,11 +563,22 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs) 0x55 - 0xff: level 4 */ pStatus->battery = 0x5f; // fully charged - // Read config value for this one - if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected) - pStatus->extension = 1; + // Check if we have a specific order about the extension status + if (Extension == -1) + { + // Read config value for this one + if(g_Config.bNunchuckConnected || g_Config.bClassicControllerConnected) + pStatus->extension = 1; + else + pStatus->extension = 0; + } else - pStatus->extension = 0; + { + if(Extension) + pStatus->extension = 1; + else + pStatus->extension = 0; + } LOGV(WII_IPC_WIIMOTE, 0, " Extension: %x", pStatus->extension); LOGV(WII_IPC_WIIMOTE, 0, " SendStatusReport()"); diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h index 2717be0fe5..ac8e7110a1 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h @@ -53,7 +53,7 @@ void HidOutputReport(u16 _channelID, wm_report* sr); void WmLeds(u16 _channelID, wm_leds* leds); void WmReadData(u16 _channelID, wm_read_data* rd); void WmWriteData(u16 _channelID, wm_write_data* wd); -void WmRequestStatus(u16 _channelID, wm_request_status* rs); +void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension = -1); void WmRequestStatus_(u16 _channelID, int a); void WmDataReporting(u16 _channelID, wm_data_reporting* dr); diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 6987ee9cbc..9e1623e0bd 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -777,57 +777,45 @@ void FillReportExtension(wm_extension& _ext) // ------------------------------------ // The default joystick and button values unless we use them // -------------- - _ext.jx = 0x80; - _ext.jy = 0x80; + _ext.jx = g_nu.jx.center; + _ext.jy = g_nu.jy.center; _ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active // --------------------- - #ifdef _WIN32 - /* We use a 192 range (32 to 224) that match our calibration values in nunchuck_calibration[] */ - if(GetAsyncKeyState(VK_NUMPAD4)) // left - _ext.jx = 0x20; + // Set the max values to the current calibration values + if(GetAsyncKeyState(VK_NUMPAD4)) // x + _ext.jx = g_nu.jx.min; + if(GetAsyncKeyState(VK_NUMPAD6)) + _ext.jx = g_nu.jx.max; + if(GetAsyncKeyState(VK_NUMPAD5)) // y + _ext.jy = g_nu.jy.min; if(GetAsyncKeyState(VK_NUMPAD8)) - _ext.jy = 0xe0; - - if(GetAsyncKeyState(VK_NUMPAD6)) // right - _ext.jx = 0xe0; - - if(GetAsyncKeyState(VK_NUMPAD5)) - _ext.jy = 0x20; - + _ext.jy = g_nu.jy.max; if(GetAsyncKeyState('C')) _ext.bt = 0x01; - if(GetAsyncKeyState('Z')) - _ext.bt = 0x02; - + _ext.bt = 0x02; if(GetAsyncKeyState('C') && GetAsyncKeyState('Z')) _ext.bt = 0x00; #else // TODO linux port #endif - /* Here we use g_RegExtTmpReport as a temporary storage for the enryption function because - the type if array may have some importance for wiimote_encrypt(). We avoid using - g_RegExtTmp that is used in EmuMain.cpp because if this runs on a different thread - there is a small chance that they may interfer with each other. */ - - // Clear g_RegExtTmpReport by copying zeroes to it, this may not be needed - memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp)); - - /* Write the nunchuck inputs to it. We begin writing at 0x08, but it could also be - 0x00, the important thing is that we begin at an address evenly divisible - by 0x08 */ - memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext)); + /* Here we encrypt the report */ + // Create a temporary storage for the data + u8 Tmp[sizeof(_ext)]; + // Clear the array by copying zeroes to it + memset(Tmp, 0, sizeof(_ext)); + // Copy the data to it + memcpy(Tmp, &_ext, sizeof(_ext)); // Encrypt it - wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, sizeof(_ext)); - - // Write it back to the extension - memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext)); + wiimote_encrypt(&g_ExtKey, Tmp, 0x00, sizeof(_ext)); + // Write it back to the struct + memcpy(&_ext, Tmp, sizeof(_ext)); } // ======================= @@ -1002,17 +990,18 @@ void FillReportClassicExtension(wm_classic_extension& _ext) // TODO linux port #endif - // Clear g_RegExtTmp by copying zeroes to it - memset(g_RegExtTmpReport, 0, sizeof(g_RegExtTmp)); - - /* Write the nunchuck inputs to it. We begin writing at 0x08, see comment above. */ - memcpy(g_RegExtTmpReport + 0x08, &_ext, sizeof(_ext)); + /* Here we encrypt the report */ + // Create a temporary storage for the data + u8 Tmp[sizeof(_ext)]; + // Clear the array by copying zeroes to it + memset(Tmp, 0, sizeof(_ext)); + // Copy the data to it + memcpy(Tmp, &_ext, sizeof(_ext)); // Encrypt it - wiimote_encrypt(&g_ExtKey, &g_RegExtTmpReport[0x08], 0x08, 0x06); - - // Write it back - memcpy(&_ext, &g_RegExtTmpReport[0x08], sizeof(_ext)); + wiimote_encrypt(&g_ExtKey, Tmp, 0x00, sizeof(_ext)); + // Write it back to the struct + memcpy(&_ext, Tmp, sizeof(_ext)); } // ======================= diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index c414dca671..71970916f8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -39,6 +39,11 @@ namespace WiiMoteReal { +int GetReportSize(struct wiimote_t* wm) +{ + // The report size is 0x33 = 18, 0x37 = 22 withouth the leading (a1) byte + if(WIIUSE_USING_EXP(wm)) return 22; else return 18; +} void handle_ctrl_status(struct wiimote_t* wm) { @@ -51,12 +56,11 @@ void handle_ctrl_status(struct wiimote_t* wm) Console::Print("battery: %f %%\n", wm->battery_level); } - bool IRDataOK(struct wiimote_t* wm) { //Console::Print("IRDataOK: "); // The report size is 0x33 = 18, 0x37 = 22 withouth the leading (a1) byte - int ReportSize; if(WIIUSE_USING_EXP(wm)) ReportSize = 22; else ReportSize = 18; + int ReportSize = GetReportSize(wm); for(int i = 0; i < ReportSize; i++) { //Console::Print("%02x ", wm->event_buf[i]); @@ -246,6 +250,8 @@ void ReadWiimote() be needed. But I still use it becase it seemed like state_changed() or the threshold values or something else might fail so that only huge status changed were reported. */ handle_event(g_WiiMotesFromWiiUse[0]); + + // Declaration std::string Temp; /* Timeout for data reading. This is used in Initialize() to read the Eeprom, if we have not gotten @@ -282,7 +288,7 @@ void ReadWiimote() case WIIUSE_STATUS: /* a status event occured */ - handle_ctrl_status(g_WiiMotesFromWiiUse[i]); + //handle_ctrl_status(g_WiiMotesFromWiiUse[i]); break; case WIIUSE_DISCONNECT: diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 2a0856bcb6..176569054e 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -16,6 +16,22 @@ // http://code.google.com/p/dolphin-emu/ +////////////////////////////////////////////////////////////////////////////////////////// +// Current issues +/* ŻŻŻŻŻŻŻŻŻŻŻŻŻ + +The real Wiimote fails to answer the core correctly sometmes. Leading to an unwanted disconnection. And +there is currenty no functions to reconnect with the game. There are two ways to solve this: + 1. Make a reconnect function in the IOS emulation + 2. Detect failed answers in this plugin and solve it by replacing them with emulated answers. + +The first solution seems easier, if I knew a little better how the /dev/usb/oh1 and Wiimote functions +worked. + +/////////////////////////////////////////////*/ + + + ////////////////////////////////////////////////////////////////////////////////////////// // Includes // ŻŻŻŻŻŻŻŻŻŻŻŻŻ @@ -52,14 +68,17 @@ bool g_FrameOpen = false; bool g_RealWiiMotePresent = false; bool g_RealWiiMoteInitialized = false; bool g_EmulatedWiiMoteInitialized = false; +bool g_WiimoteUnexpectedDisconnect = false; // Settings accel_cal g_accel; +nu_cal g_nu; // Debugging bool g_DebugAccelerometer = false; bool g_DebugData = false; bool g_DebugComm = true; +bool g_DebugCustom = false; // Update speed int g_UpdateCounter = 0; @@ -74,6 +93,10 @@ std::vector VRecording(RECORDING_ROWS); // DLL instance HINSTANCE g_hInstance; +#ifdef _WIN32 +HWND g_ParentHWND = NULL; +#endif + #if defined(HAVE_WX) && HAVE_WX wxWindow win; ConfigDialog *frame = NULL; @@ -178,6 +201,10 @@ extern "C" void Initialize(void *init) SWiimoteInitialize _WiimoteInitialize = *(SWiimoteInitialize *)init; g_WiimoteInitialize = _WiimoteInitialize; + #ifdef _WIN32 + g_ParentHWND = GetParent(g_WiimoteInitialize.hWnd); + #endif + g_EmulatorRunning = true; #if defined(HAVE_WX) && HAVE_WX @@ -265,6 +292,16 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _ LOGV(WII_IPC_WIIMOTE, 3, "============================================================="); const u8* data = (const u8*)_pData; + // Check for custom communication + if(_channelID == 99 && data[0] == WIIMOTE_RECONNECT) + { + Console::Print("\n\nWiimote Disconnected\n\n"); + g_EmulatorRunning = false; + g_WiimoteUnexpectedDisconnect = true; + if (frame) frame->UpdateGUI(); + return; + } + // Debugging { LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel"); @@ -315,14 +352,17 @@ extern "C" void Wiimote_Update() // Debugging #ifdef _WIN32 - if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; + if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; // Page Down else if (GetAsyncKeyState(VK_HOME) && !g_DebugComm ) g_DebugComm = true; - if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; + if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; // Page Up else if (GetAsyncKeyState(VK_PRIOR) && !g_DebugData ) g_DebugData = true; - if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; + if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; // Home else if (GetAsyncKeyState(VK_NEXT) && !g_DebugAccelerometer ) g_DebugAccelerometer = true; + + if( GetAsyncKeyState(VK_END) && g_DebugCustom ) { g_DebugCustom = false; Console::Print("Custom Debug: Off\n");} // End + else if (GetAsyncKeyState(VK_END) && !g_DebugCustom ) {g_DebugCustom = true; Console::Print("Custom Debug: Off\n");} #endif } @@ -353,6 +393,17 @@ bool IsFocus() #endif } +// Turn off all extensions +void DisableExtensions() +{ + //g_Config.bMotionPlus = false; + g_Config.bNunchuckConnected = false; + g_Config.bClassicControllerConnected = false; + //g_Config.bBalanceBoard = false; + //g_Config.bGuitar = false; + //g_Config.bDrums = false; +} + void ReadDebugging(bool Emu, const void* _pData, int Size) { // @@ -361,32 +412,38 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) int size; bool DataReport = false; - std::string Name; + std::string Name, TmpData; switch(data[1]) { case WM_STATUS_REPORT: // 0x20 size = sizeof(wm_status_report); Name = "WM_STATUS_REPORT"; { - /*wm_status_report* pStatus = (wm_status_report*)(data + 2); - Console::Print("" + wm_status_report* pStatus = (wm_status_report*)(data + 2); + Console::Print("\n" "Extension Controller: %i\n" - "Speaker enabled: %i\n" - "IR camera enabled: %i\n" - "LED 1: %i\n" - "LED 2: %i\n" - "LED 3: %i\n" - "LED 4: %i\n" + //"Speaker enabled: %i\n" + //"IR camera enabled: %i\n" + //"LED 1: %i\n" + //"LED 2: %i\n" + //"LED 3: %i\n" + //"LED 4: %i\n" "Battery low: %i\n\n", pStatus->extension, - pStatus->speaker, - pStatus->ir, - (pStatus->leds >> 0), - (pStatus->leds >> 1), - (pStatus->leds >> 2), - (pStatus->leds >> 3), + //pStatus->speaker, + //pStatus->ir, + //(pStatus->leds >> 0), + //(pStatus->leds >> 1), + //(pStatus->leds >> 2), + //(pStatus->leds >> 3), pStatus->battery_low - );*/ + ); + // Update the global extension settings + if(!Emu && !pStatus->extension) + { + DisableExtensions(); + if (frame) frame->UpdateGUI(); + } } break; case WM_READ_DATA_REPLY: // 0x21 @@ -395,17 +452,56 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) // data[4]: Size and error // data[5, 6]: The registry offset - // Show the accelerometer neutral values - if (data[5] == 0x00 && data[6] == 0x10) + // Show the extension ID + if ((data[4] == 0x10 || data[4] == 0x20 || data[4] == 0x50) && data[5] == 0x00 && (data[6] == 0xfa || data[6] == 0xfe)) { - Console::Print("\nGame got the Wiimote accelerometer neutral values: %i %i %i\n\n", - data[13], data[14], data[19]); + if(data[4] == 0x10) + Console::Print("\n\nGame got the encrypted extension ID: %02x%02x\n", data[7], data[8]); + else if(data[4] == 0x50) + Console::Print("\n\nGame got the encrypted extension ID: %02x%02x%02x%02x%02x%02x\n", data[7], data[8], data[9], data[10], data[11], data[12]); + + // We have already sent the data report so we can safely decrypt it now + if(WiiMoteEmu::g_Encryption) + { + if(data[4] == 0x10) + wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x06, (data[4] >> 0x04) + 1); + if(data[4] == 0x50) + wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x02, (data[4] >> 0x04) + 1); + } + + // Update the global extension settings + if(data[4] == 0x10) + { + if (!Emu) DisableExtensions(); + if (!Emu && data[7] == 0x00 && data[8] == 0x00) g_Config.bNunchuckConnected = true; + if (!Emu && data[7] == 0x01 && data[8] == 0x01) g_Config.bClassicControllerConnected = true; + g_Config.Save(); + WiiMoteEmu::UpdateEeprom(); + if (frame) frame->UpdateGUI(); + Console::Print("Game got the decrypted extension ID: %02x%02x\n\n", data[7], data[8]); + } + else if(data[4] == 0x50) + { + if (!Emu) DisableExtensions(); + if (!Emu && data[11] == 0x00 && data[12] == 0x00) g_Config.bNunchuckConnected = true; + if (!Emu && data[11] == 0x01 && data[12] == 0x01) g_Config.bClassicControllerConnected = true; + g_Config.Save(); + WiiMoteEmu::UpdateEeprom(); + if (frame) frame->UpdateGUI(); + Console::Print("Game got the decrypted extension ID: %02x%02x%02x%02x%02x%02x\n\n", data[7], data[8], data[9], data[10], data[11], data[12]); + } } + // Show the nunchuck neutral values - // We have already sent the data report so we can safely decrypt it now - wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[7], 0x00, Size - 7); - if(data[4] == 0xf0 && data[5] == 0x00 && data[6] == 0x20) + if(data[4] == 0xf0 && data[5] == 0x00 && (data[6] == 0x20 || data[6] == 0x30)) { + // Save the encrypted data + TmpData = StringFromFormat("Read[%s] (enc): %s\n", (Emu ? "Emu" : "Real"), ArrayToString(data, size + 2, 0, 30).c_str()); + + // We have already sent the data report so we can safely decrypt it now + if(WiiMoteEmu::g_Encryption) + wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x00, (data[4] >> 0x04) + 1); + Console::Print("\nGame got the Nunchuck calibration:\n"); Console::Print("Cal_zero.x: %i\n", data[7 + 0]); Console::Print("Cal_zero.y: %i\n", data[7 + 1]); @@ -419,6 +515,22 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) Console::Print("Js.Max.y: %i\n", data[7 + 11]); Console::Print("Js.Min.y: %i\n", data[7 + 12]); Console::Print("JS.Center.y: %i\n\n", data[7 + 13]); + + // Save the values + if (!Emu && data[7 + 0] != 0xff) + { + memcpy(WiiMoteEmu::g_RegExt + 0x20, &data[7], 0x10); + memcpy(WiiMoteEmu::g_RegExt + 0x30, &data[7], 0x10); + } + // We got a third party nunchuck + else if(data[7 + 0] == 0xff) + { + memcpy(WiiMoteEmu::g_RegExt + 0x20, WiiMoteEmu::wireless_nunchuck_calibration, sizeof(WiiMoteEmu::wireless_nunchuck_calibration)); + memcpy(WiiMoteEmu::g_RegExt + 0x30, WiiMoteEmu::wireless_nunchuck_calibration, sizeof(WiiMoteEmu::wireless_nunchuck_calibration)); + } + + // Show the encrypted data + Console::Print("%s", TmpData.c_str()); } break; @@ -459,7 +571,8 @@ void ReadDebugging(bool Emu, const void* _pData, int Size) DataReport = true; break; default: - PanicAlert("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]); + //PanicAlert("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]); + Console::Print("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]); return; } @@ -513,29 +626,31 @@ void InterruptDebugging(bool Emu, const void* _pData) // const u8* data = (const u8*)_pData; - if (g_DebugComm) Console::Print("Write[%s] ", (Emu ? "Emu" : "Real")); - + std::string Name; int size; + + if (g_DebugComm) Name += StringFromFormat("Write[%s] ", (Emu ? "Emu" : "Real")); + switch(data[1]) { case 0x10: size = 4; // I don't know the size - if (g_DebugComm) Console::Print("0x10"); + if (g_DebugComm) Name.append("0x10"); break; case WM_LEDS: // 0x11 size = sizeof(wm_leds); - if (g_DebugComm) Console::Print("WM_LEDS"); + if (g_DebugComm) Name.append("WM_LEDS"); break; case WM_DATA_REPORTING: // 0x12 size = sizeof(wm_data_reporting); - if (g_DebugComm) Console::Print("WM_DATA_REPORTING"); + if (g_DebugComm) Name.append("WM_DATA_REPORTING"); break; case WM_REQUEST_STATUS: // 0x15 size = sizeof(wm_request_status); - if (g_DebugComm) Console::Print("WM_REQUEST_STATUS"); + if (g_DebugComm) Name.append("WM_REQUEST_STATUS"); break; case WM_WRITE_DATA: // 0x16 - if (g_DebugComm) Console::Print("WM_WRITE_DATA"); + if (g_DebugComm) Name.append("WM_WRITE_DATA"); size = sizeof(wm_write_data); // data[2]: The address space 0, 1 or 2 // data[3]: The registry type @@ -544,17 +659,27 @@ void InterruptDebugging(bool Emu, const void* _pData) switch(data[2] >> 0x01) { case WM_SPACE_EEPROM: - if (g_DebugComm) Console::Print(" REG_EEPROM"); break; + if (g_DebugComm) Name.append(" REG_EEPROM"); break; case WM_SPACE_REGS1: case WM_SPACE_REGS2: switch(data[3]) { case 0xa2: - if (g_DebugComm) Console::Print(" REG_SPEAKER"); break; + if (g_DebugComm) Name.append(" REG_SPEAKER"); break; case 0xa4: - if (g_DebugComm) Console::Print(" REG_EXT"); break; + if (g_DebugComm) Name.append(" REG_EXT"); + // Update the encryption mode + if (data[3] == 0xa4 && data[5] == 0xf0) + { + if (data[7] == 0xaa) + WiiMoteEmu::g_Encryption = true; + else if (data[7] == 0x55) + WiiMoteEmu::g_Encryption = false; + Console::Print("\nExtension enryption turned %s\n\n", WiiMoteEmu::g_Encryption ? "On" : "Off"); + } + break; case 0xb0: - if (g_DebugComm) Console::Print(" REG_IR"); break; + if (g_DebugComm) Name.append(" REG_IR"); break; } break; } @@ -565,33 +690,33 @@ void InterruptDebugging(bool Emu, const void* _pData) // data[3]: The registry type // data[5]: The registry offset // data[7]: The number of bytes, 6 and 7 together - if (g_DebugComm) Console::Print("WM_READ_DATA"); + if (g_DebugComm) Name.append("WM_READ_DATA"); switch(data[2] >> 0x01) { case WM_SPACE_EEPROM: - if (g_DebugComm) Console::Print(" REG_EEPROM"); break; + if (g_DebugComm) Name.append(" REG_EEPROM"); break; case WM_SPACE_REGS1: case WM_SPACE_REGS2: switch(data[3]) { case 0xa2: - if (g_DebugComm) Console::Print(" REG_SPEAKER"); break; + if (g_DebugComm) Name.append(" REG_SPEAKER"); break; case 0xa4: - if (g_DebugComm) Console::Print(" REG_EXT"); break; + if (g_DebugComm) Name.append(" REG_EXT"); break; case 0xb0: - if (g_DebugComm) Console::Print(" REG_IR"); break; + if (g_DebugComm) Name.append(" REG_IR"); break; } break; } break; case WM_IR_PIXEL_CLOCK: // 0x13 case WM_IR_LOGIC: // 0x1a - if (g_DebugComm) Console::Print("WM_IR"); + if (g_DebugComm) Name.append("WM_IR"); size = 1; break; case WM_SPEAKER_ENABLE: // 0x14 case WM_SPEAKER_MUTE: - if (g_DebugComm) Console::Print("WM_SPEAKER"); + if (g_DebugComm) Name.append("WM_SPEAKER"); size = 1; break; default: @@ -603,7 +728,7 @@ void InterruptDebugging(bool Emu, const void* _pData) { std::string Temp = ArrayToString(data, size + 2, 0, 30); //LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); - Console::Print(": %s\n", Temp.c_str()); // No timestamp + Console::Print("%s: %s\n", Name.c_str(), Temp.c_str()); // No timestamp //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp } } diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.h b/Source/Plugins/Plugin_Wiimote/Src/main.h index cff3f478eb..e3037d77a8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.h +++ b/Source/Plugins/Plugin_Wiimote/Src/main.h @@ -71,14 +71,20 @@ struct SRecordingAll extern bool g_RealWiiMotePresent; extern bool g_RealWiiMoteInitialized; extern bool g_EmulatedWiiMoteInitialized; + extern bool g_WiimoteUnexpectedDisconnect; + #ifdef _WIN32 + extern HWND g_ParentHWND; + #endif // Settings extern accel_cal g_accel; + extern nu_cal g_nu; // Debugging extern bool g_DebugAccelerometer; extern bool g_DebugData; extern bool g_DebugComm; + extern bool g_DebugCustom; // Update speed extern int g_UpdateCounter; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index ad58653a2c..d728dafd39 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -300,6 +300,15 @@ struct accel_cal wm_accel cal_g; /**< 1g difference around 0cal */ }; +struct nu_js { + u8 max, min, center; +}; +struct nu_cal +{ + wm_accel cal_zero; // zero calibratio + nu_js jx; // + nu_js jy; // +}; #pragma pack(pop) diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 801a586112..99c0749bc8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -177,12 +177,6 @@ void ReadData() // Copy Buffer to LastReport memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD); m_LastReportValid = true; - - /* Check if the data reporting mode is okay. This should not cause any harm outside the dual mode - (being able to switch between the real and emulated wiimote) because WiiMoteEmu::g_ReportingMode - should always have the right reporting mode. */ - if (g_EmulatorRunning && pBuffer[0] != WiiMoteEmu::g_ReportingMode) - SetDataReportingMode(); } else { @@ -327,89 +321,6 @@ void ClearEvents() g_WiiMotes[i]->ClearEvents(); } -// Update the data reporting mode if we are switching between the emulated and the real Wiimote -void SetDataReportingMode(u8 ReportingMode) -{ - // Don't allow this to run to often - if (Common::Timer::GetTimeSinceJan1970() == g_UpdateTime) return; - - // Save the time - g_UpdateTime = Common::Timer::GetTimeSinceJan1970(); - - // Decide if we should we use custom values - if (ReportingMode == 0) ReportingMode = WiiMoteEmu::g_ReportingMode; - - // Just in case this should happen - if (ReportingMode == 0) ReportingMode = 0x30; - - // Shortcut - wiimote_t* wm = WiiMoteReal::g_WiiMotesFromWiiUse[0]; - - switch(ReportingMode) // See Wiimote_Update() - { - case WM_REPORT_CORE: - wiiuse_motion_sensing(wm, 0); - wiiuse_set_ir(wm, 0); - break; - case WM_REPORT_CORE_ACCEL: - wiiuse_motion_sensing(wm, 1); - wiiuse_set_ir(wm, 0); - break; - case WM_REPORT_CORE_ACCEL_IR12: - wiiuse_motion_sensing(wm, 1); - wiiuse_set_ir(wm, 1); - break; - case WM_REPORT_CORE_ACCEL_EXT16: - wiiuse_motion_sensing(wm, 1); - wiiuse_set_ir(wm, 0); - break; - case WM_REPORT_CORE_ACCEL_IR10_EXT6: - wiiuse_motion_sensing(wm, 1); - wiiuse_set_ir(wm, 1); - break; - } - - /* On occasion something in this function caused an instant reboot of Windows XP SP3 - with Bluesoleil 6. So I'm trying to use the API functions to reach the same goal. */ - /*byte DataReporting[MAX_PAYLOAD]; - byte IR0[MAX_PAYLOAD]; - byte IR1[MAX_PAYLOAD]; - - DataReporting[0] = 0x12; // Report 0x12 - DataReporting[1] = 0x06; // Continuous reporting - DataReporting[2] = ReportingMode; // Reporting mode - - IR0[0] = 0x13; // Report 0x13 - if (IR) IR0[1] = 0x06; else IR0[1] = 0x02; - IR1[0] = 0x1a; // Report 0x1a - if (IR) IR1[1] = 0x06; else IR1[1] = 0x02; - - // Calibrate IR - static const u8 IR_0[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01, - 0x01 }; - static const u8 IR_1[] = { 0x16, 0x04, 0xb0, 0x00, 0x00, 0x09, - 0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xaa, 0x00, 0x64 }; - static const u8 IR_2[] = { 0x16, 0x04, 0xb0, 0x00, 0x1a, 0x02, - 0x63, 0x03 }; - static const u8 IR_3[] = { 0x16, 0x04, 0xb0, 0x00, 0x33, 0x01, - 0x03 }; - static const u8 IR_4[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01, - 0x08 }; - - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)DataReporting, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR0, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR1, MAX_PAYLOAD); - - if (IR) - { - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_0, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_1, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_2, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_3, MAX_PAYLOAD); - wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_4, MAX_PAYLOAD); - }*/ -} - // Flash lights, and if connecting, also rumble void FlashLights(bool Connect) { @@ -458,7 +369,7 @@ int Initialize() 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 + // Create a new thread and start listening for Wiimote data if (g_NumberOfWiiMotes > 0) g_pReadThread = new Common::Thread(ReadWiimote_ThreadFunc, NULL); @@ -472,12 +383,11 @@ int Initialize() byte *data = (byte*)malloc(sizeof(byte) * sizeof(WiiMoteEmu::EepromData_0)); wiiuse_read_data(g_WiiMotesFromWiiUse[0], data, 0, sizeof(WiiMoteEmu::EepromData_0)); - // Update the global extension settings - g_Config.bNunchuckConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_NUNCHUK); - g_Config.bClassicControllerConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_CLASSIC); + // Don't run the Wiimote thread if no wiimotes were found + if (g_NumberOfWiiMotes > 0) g_Shutdown = false; - // Initialized - if (g_NumberOfWiiMotes > 0) { g_RealWiiMoteInitialized = true; g_Shutdown = false; } + // Initialized, even if we didn't find a Wiimote + g_RealWiiMoteInitialized = true; return g_NumberOfWiiMotes; } @@ -510,9 +420,6 @@ void Shutdown(void) // Clean up wiiuse wiiuse_cleanup(g_WiiMotesFromWiiUse, g_NumberOfWiiMotes); - // Uninitialized - g_RealWiiMoteInitialized = false; - // Uninitialized g_RealWiiMoteInitialized = false; g_RealWiiMotePresent = false; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h index f66933e188..0b1c7e1edd 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h @@ -42,7 +42,10 @@ void Update(); void SendAcc(u8 _ReportID); void SetDataReportingMode(u8 ReportingMode = 0); void ClearEvents(); + +// The alternative Wiimote loop void ReadWiimote(); +bool IRDataOK(struct wiimote_t* wm); #ifndef EXCLUDE_H extern wiimote_t** g_WiiMotesFromWiiUse;