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;