From 7742e1a6dd4baec8e660cb1acf6fcda0da9cebd7 Mon Sep 17 00:00:00 2001 From: snzgoo Date: Fri, 7 May 2010 22:39:06 +0000 Subject: [PATCH] Stage1: Introducing MotionPlus as emulated extension, allowing us to boot games that require the MotionPlus itself. I also already implemented most of the needed data structures and datareport handling for the motionplus-nunchuk passthrough mode, which I'll add up next as well. Wii Sports Resort is now bootable by just using an emulated wiimote (only working under the old wiimote plugin atm, I asked billiard to port my commit into his plugin since he knows his plugin better than me and its less work for him than for me, I kept most parts of my code in modules to simplify that task). Upcoming stage2: Faking the motionplus on the fly on real wiimotes, that means you will be able to play, e.g. Redsteel2 with a real wiimote and nunchuk or wii sports resort with just your real wiimote. and nunchuk, but w/o the need of having a real motionpluscontroller connected. The new Zelda 2010 will benefit by that, since it will require a motionplus controller. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5438 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_Wiimote/Src/ConfigBasicDlg.cpp | 8 +- .../Plugin_Wiimote/Src/ConfigPadDlg.cpp | 12 +- .../Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h | 2 +- .../Plugin_Wiimote/Src/DataReports.cpp | 67 +++--- .../Plugin_Wiimote/Src/EmuDefinitions.cpp | 4 + .../Plugin_Wiimote/Src/EmuDefinitions.h | 36 +++- Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp | 70 ++++-- .../Plugin_Wiimote/Src/EmuSubroutines.cpp | 167 +++++++++++++-- .../Plugin_Wiimote/Src/EmuSubroutines.h | 8 +- .../Plugins/Plugin_Wiimote/Src/FillReport.cpp | 200 +++++++++++++++++- .../Plugins/Plugin_Wiimote/Src/wiimote_hid.h | 33 +++ 11 files changed, 530 insertions(+), 77 deletions(-) diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigBasicDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigBasicDlg.cpp index 0989882b5a..e39f767193 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigBasicDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigBasicDlg.cpp @@ -167,7 +167,6 @@ void WiimoteBasicConfigDialog::CreateGUIControls() m_UprightWiimote[i]->SetToolTip(wxT("Treat the upright position as neutral")); m_WiiMotionPlusConnected[i] = new wxCheckBox(m_Controller[i], IDC_MOTIONPLUSCONNECTED, wxT("Wii Motion Plus Connected")); - m_WiiMotionPlusConnected[i]->Enable(false); m_Extension[i] = new wxChoice(m_Controller[i], IDC_EXTCONNECTED, wxDefaultPosition, wxDefaultSize, arrayStringFor_extension, 0, wxDefaultValidator); @@ -382,7 +381,7 @@ void WiimoteBasicConfigDialog::DoUseReal() // Are we using an extension now? The report that it's removed, then reconnected. bool UsingExtension = false; - if (WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected != WiiMoteEmu::EXT_NONE) + if ((WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected != WiiMoteEmu::EXT_NONE) || ( WiiMoteEmu::WiiMapping[m_Page].bMotionPlusConnected)) UsingExtension = true; DEBUG_LOG(WIIMOTE, "DoUseReal() Connect extension: %i", !UsingExtension); @@ -466,6 +465,11 @@ void WiimoteBasicConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) break; case IDC_MOTIONPLUSCONNECTED: WiiMoteEmu::WiiMapping[m_Page].bMotionPlusConnected = m_WiiMotionPlusConnected[m_Page]->IsChecked(); + DoExtensionConnectedDisconnected(WiiMoteEmu::EXT_NONE); + if (g_EmulatorRunning) + SLEEP(25); + WiiMoteEmu::UpdateExtRegisterBlocks(m_Page); + DoExtensionConnectedDisconnected(); break; case IDC_WIIAUTORECONNECT: WiiMoteEmu::WiiMapping[m_Page].bWiiAutoReconnect = m_WiiAutoReconnect[m_Page]->IsChecked(); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp index 5b88660aa2..77e2114c86 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp @@ -755,7 +755,7 @@ void WiimotePadConfigDialog::CreatePadGUIControls() m_gWiimote[i]->Add(m_sWmVertRight[i], 0, (wxLEFT | wxRIGHT | wxDOWN), 1); // Extension Mapping - if(WiiMoteEmu::WiiMapping[i].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUCK) + if(WiiMoteEmu::WiiMapping[i].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUK) { // Stick controls m_NunchuckTextStick[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Stick")); @@ -763,11 +763,11 @@ void WiimotePadConfigDialog::CreatePadGUIControls() for (int x = 0; x <= IDB_NC_SHAKE - IDB_NC_Z; x++) { - m_statictext_NunChuck[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, ncText[x]); + m_statictext_Nunchuk[x][i] = new wxStaticText(m_Controller[i], wxID_ANY, ncText[x]); m_Button_NunChuck[x][i] = new wxButton(m_Controller[i], x + IDB_NC_Z, wxEmptyString, wxDefaultPosition, wxSize(BtW, BtH)); m_Button_NunChuck[x][i]->SetFont(m_SmallFont); m_Sizer_NunChuck[x][i] = new wxBoxSizer(wxHORIZONTAL); - m_Sizer_NunChuck[x][i]->Add(m_statictext_NunChuck[x][i], 0, (wxUP), 4); + m_Sizer_NunChuck[x][i]->Add(m_statictext_Nunchuk[x][i], 0, (wxUP), 4); m_Sizer_NunChuck[x][i]->Add(m_Button_NunChuck[x][i], 0, (wxLEFT), 2); } @@ -895,7 +895,7 @@ void WiimotePadConfigDialog::CreatePadGUIControls() m_sHorizControllerMapping[i]->Add(m_gWiimote[i], 0, (wxLEFT), 5); switch(WiiMoteEmu::WiiMapping[i].iExtensionConnected) { - case WiiMoteEmu::EXT_NUNCHUCK: + case WiiMoteEmu::EXT_NUNCHUK: m_sHorizControllerMapping[i]->Add(m_gNunchuck[i], 0, (wxLEFT), 5); break; case WiiMoteEmu::EXT_CLASSIC_CONTROLLER: @@ -1074,7 +1074,7 @@ void WiimotePadConfigDialog::UpdateGUI() m_Button_Wiimote[x][m_Page]->SetLabel(wxString::FromAscii( InputCommon::VKToString(WiiMoteEmu::WiiMapping[m_Page].Button[x + WiiMoteEmu::EWM_A]).c_str())); } - if(WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUCK) + if(WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUK) { m_NunchuckComboStick[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Stick.NC); for (int x = 0; x <= IDB_NC_SHAKE - IDB_NC_Z; x++) @@ -1104,7 +1104,7 @@ void WiimotePadConfigDialog::UpdateGUI() InputCommon::XKeyToString(WiiMoteEmu::WiiMapping[m_Page].Button[x + WiiMoteEmu::EWM_A], keyStr); m_Button_Wiimote[x][m_Page]->SetLabel(wxString::FromAscii(keyStr)); } - if(WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUCK) + if(WiiMoteEmu::WiiMapping[m_Page].iExtensionConnected == WiiMoteEmu::EXT_NUNCHUK) { m_NunchuckComboStick[m_Page]->SetSelection(WiiMoteEmu::WiiMapping[m_Page].Stick.NC); for (int x = 0; x <= IDB_NC_SHAKE - IDB_NC_Z; x++) diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h index c89f9db6fe..895923c753 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h @@ -257,7 +257,7 @@ class WiimotePadConfigDialog : public wxDialog *m_tTriggerSource[MAX_WIIMOTES], *m_statictext_Analog[IDB_TRIGGER_R - IDB_ANALOG_LEFT_X + 1][MAX_WIIMOTES], *m_statictext_Wiimote[IDB_WM_SHAKE - IDB_WM_A + 1][MAX_WIIMOTES], - *m_statictext_NunChuck[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES], + *m_statictext_Nunchuk[IDB_NC_SHAKE - IDB_NC_Z + 1][MAX_WIIMOTES], *m_statictext_Classic[IDB_CC_RD - IDB_CC_A + 1][MAX_WIIMOTES], *m_statictext_GH3[IDB_GH3_STRUM_DOWN - IDB_GH3_GREEN + 1][MAX_WIIMOTES], *m_NunchuckTextStick[5], diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index 4f8cf340bc..d9a4a8676f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -196,7 +196,7 @@ void SendReportCoreAccelExt16(u16 _channelID) FillReportAcc(pReport->a); #endif - if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUCK) + if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK) { #if defined(HAVE_WX) && HAVE_WX FillReportExtension(pReport->ext); @@ -233,38 +233,53 @@ void SendReportCoreAccelIr10Ext(u16 _channelID) memset(pReport, 0, sizeof(wm_report_core_accel_ir10_ext6)); // Make a classic extension struct - wm_classic_extension _ext; - wm_GH3_extension _GH3_ext; - memset(&_ext, 0, sizeof(wm_classic_extension)); - memset(&_GH3_ext, 0, sizeof(wm_GH3_extension)); + #if defined(HAVE_WX) && HAVE_WX FillReportInfo(pReport->c); FillReportAcc(pReport->a); FillReportIRBasic(pReport->ir[0], pReport->ir[1]); -#endif - if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUCK) + if ((WiiMapping[g_ID].bMotionPlusConnected) && (( WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK ) || (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)) ) { -#if defined(HAVE_WX) && HAVE_WX - FillReportExtension(pReport->ext); -#endif - } - else if(WiiMapping[g_ID].iExtensionConnected == EXT_CLASSIC_CONTROLLER) - { -#if defined(HAVE_WX) && HAVE_WX - FillReportClassicExtension(_ext); -#endif - // Copy _ext to pReport->ext - memcpy(&pReport->ext, &_ext, sizeof(_ext)); - } - else if(WiiMapping[g_ID].iExtensionConnected == EXT_GUITARHERO) - { -#if defined(HAVE_WX) && HAVE_WX - FillReportGuitarHero3Extension(_GH3_ext); -#endif - memcpy(&pReport->ext, &_GH3_ext, sizeof(_GH3_ext)); - } + if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK) + { + FillReportMotionPlus(pReport->ext, true); + } + else if (WiiMapping[g_ID].iExtensionConnected == EXT_NONE) + { + FillReportMotionPlus(pReport->ext, false); + + } + + } + else { + if(WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK) + { + FillReportExtension(pReport->ext); + } + else if(WiiMapping[g_ID].iExtensionConnected == EXT_CLASSIC_CONTROLLER) + { + wm_classic_extension _ext; + memset(&_ext, 0, sizeof(wm_classic_extension)); + + FillReportClassicExtension(_ext); + + // Copy _ext to pReport->ext + memcpy(&pReport->ext, &_ext, sizeof(_ext)); + } + else if(WiiMapping[g_ID].iExtensionConnected == EXT_GUITARHERO) + { + + wm_GH3_extension _GH3_ext; + memset(&_GH3_ext, 0, sizeof(wm_GH3_extension)); + FillReportGuitarHero3Extension(_GH3_ext); + + memcpy(&pReport->ext, &_GH3_ext, sizeof(_GH3_ext)); + } + + } + #endif INFO_LOG(WIIMOTE, " SendReportCoreAccelIr10Ext(0x37)"); DEBUG_LOG(WIIMOTE, " Channel: %04x", _channelID); DEBUG_LOG(WIIMOTE, " Size: %08x", Offset); diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index 81846f8f62..a72871d96f 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -44,12 +44,16 @@ u8 g_IRClock[MAX_WIIMOTES]; u8 g_IR[MAX_WIIMOTES]; u8 g_Leds[MAX_WIIMOTES]; u8 g_Speaker[MAX_WIIMOTES]; +u8 g_MotionPlus[MAX_WIIMOTES]; u8 g_SpeakerMute[MAX_WIIMOTES]; +int g_MotionPlusReadError[MAX_WIIMOTES]; u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; int g_ID; // Current refreshing Wiimote bool g_ReportingAuto[MAX_WIIMOTES]; // Auto report or passive report +bool g_MotionPlusConnected[MAX_WIIMOTES]; //MotionPlusinitiated +bool g_InterleavedData[MAX_WIIMOTES]; //sending alternated data packets from the nunchuk/motionplus u8 g_ReportingMode[MAX_WIIMOTES]; // The reporting mode and channel id u16 g_ReportingChannel[MAX_WIIMOTES]; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index 548cd17a50..79ef3f9ee3 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -86,14 +86,17 @@ extern u8 g_IRClock[MAX_WIIMOTES]; extern u8 g_IR[MAX_WIIMOTES]; extern u8 g_Leds[MAX_WIIMOTES]; extern u8 g_Speaker[MAX_WIIMOTES]; +extern u8 g_MotionPlus[MAX_WIIMOTES]; extern u8 g_SpeakerMute[MAX_WIIMOTES]; +extern int g_MotionPlusReadError[MAX_WIIMOTES]; extern u8 g_RegExtTmp[WIIMOTE_REG_EXT_SIZE]; extern int g_ID; extern bool g_ReportingAuto[MAX_WIIMOTES]; extern u8 g_ReportingMode[MAX_WIIMOTES]; extern u16 g_ReportingChannel[MAX_WIIMOTES]; +extern bool g_InterleavedData[MAX_WIIMOTES]; extern wiimote_key g_ExtKey[MAX_WIIMOTES]; // extension encryption key extern bool g_Encryption; @@ -113,7 +116,24 @@ static const u8 EepromData_16D0[] = { 0x33, 0xCC, 0x44, 0xBB, 0x00, 0x00, 0x66, 0x99, 0x77, 0x88, 0x00, 0x00, 0x2B, 0x01, 0xE8, 0x13 }; - +static const u8 motionplus_register[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x79, 0x83, 0x73, 0x54, 0x72, 0xE8, 0x30, 0xC3, 0xCC, 0x4A, 0x34, 0xFC, 0xC8, 0x4F, 0xCC, 0x5B, +0x77, 0x49, 0x75, 0xA4, 0x73, 0x9A, 0x35, 0x52, 0xCA, 0x22, 0x37, 0x26, 0x2D, 0xE5, 0xB5, 0xA2, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x78, 0x76, 0xDD, 0xF5, 0x6A, 0x3C, 0xCF, 0xF7, 0x2A, 0x0E, 0x32, 0xEE, 0x82, 0xFE, 0x2E, 0xFD, +0x19, 0xE7, 0x0A, 0xCA, 0x67, 0x3B, 0x3A, 0x75, 0xF6, 0x45, 0x55, 0x8E, 0x9D, 0x33, 0xCC, 0xEA, +0x6E, 0x52, 0xC6, 0xC6, 0x16, 0x9B, 0xEE, 0x12, 0x2E, 0x3F, 0x77, 0xB1, 0xA1, 0x80, 0x0B, 0x0E, +0xC2, 0x25, 0x05, 0xEA, 0xC3, 0x2F, 0x85, 0x1E, 0x31, 0x53, 0x74, 0xC7, 0xF1, 0x93, 0xF1, 0x2D, +0xC1, 0x6D, 0x84, 0x2A, 0xD8, 0x6F, 0x8A, 0xE5, 0x2D, 0x3B, 0x7B, 0xCC, 0xD2, 0x59, 0xD5, 0xD1, +0x9F, 0x5B, 0x6F, 0xAE, 0x82, 0xDE, 0xEA, 0xC3, 0x73, 0x42, 0x06, 0xA9, 0x77, 0xFF, 0x61, 0xA8, +0x1A, 0x70, 0xE4, 0x16, 0x90, 0x7A, 0x80, 0xF7, 0x79, 0x4B, 0x41, 0x18, 0x82, 0x6C, 0x62, 0x1A, +0x3B, 0xBF, 0xFC, 0xFF, 0x2C, 0xF2, 0x32, 0x97, 0xB8, 0x2F, 0x17, 0xE7, 0xBD, 0x35, 0x1D, 0x0A, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0xff, 0xff, 0x00, 0x00, 0xa6, 0x20, 0x00, 0x05 +}; /* Default calibration for the nunchuck. It should be written to 0x20 - 0x3f of the extension register. 0x80 is the neutral x and y accelerators and 0xb3 is the @@ -133,6 +153,12 @@ static const u8 wireless_nunchuck_calibration[] = 255, 0, 125, 255, 0, 126, 0xed, 0x43 }; +/* Default calibration for the motion plus*/ +static const u8 motion_plus_calibration[] = +{ + 0x79, 0xbe, 0x77, 0x5a, 0x77, 0x38, 0x2f, 0x90, 0xcd, 0x3b, 0x2f, 0xfd, 0xc8, 0x29, 0x9c, 0x75, + 0x7d, 0xd4, 0x78, 0xef, 0x78, 0x8a, 0x35, 0xa6, 0xc9, 0x9b, 0x33, 0x50, 0x2d, 0x00, 0xbd, 0x23 +}; /* Classic Controller calibration */ static const u8 classic_calibration[] = @@ -146,6 +172,11 @@ static const u8 nunchuck_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00 }; static const u8 classic_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x01 }; static const u8 gh3glp_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x01, 0x03 }; static const u8 ghwtdrums_id[] = { 0x01, 0x00, 0xa4, 0x20, 0x01, 0x03 }; +static const u8 wbb_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x4, 0x02 }; +static const u8 motionplus_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x04, 0x05 }; +static const u8 motionplusnunchuk_id[] = { 0x00, 0x00, 0xa4, 0x20, 0x05, 0x05 }; +//initial control packet for datatransfers over 0x37 reports +static const u8 motionpluscheck_id[] = { 0xa3, 0x62, 0x45, 0xaa, 0x04, 0x02}; // The id for nothing inserted static const u8 nothing_id[] = { 0x00, 0x00, 0x00, 0x00, 0x2e, 0x2e }; // The id for a partially inserted extension @@ -155,9 +186,10 @@ static const u8 partially_id[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; enum EExtensionType { EXT_NONE = 0, - EXT_NUNCHUCK, + EXT_NUNCHUK, EXT_CLASSIC_CONTROLLER, EXT_GUITARHERO, + EXT_WBB, }; enum EInputType diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 875c0d1347..1b651d2162 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -416,6 +416,8 @@ void ResetVariables() for (int i = 0; i < MAX_WIIMOTES; i++) { g_ReportingAuto[i] = false; + g_MotionPlusReadError[i] = 0; + g_InterleavedData[i] = false; g_ReportingMode[i] = 0; g_ReportingChannel[i] = 0; WiiMapping[i].Motion.TiltWM.Shake = 0; @@ -492,25 +494,56 @@ void InitCalibration() // Update the extension calibration values with our default values void UpdateExtRegisterBlocks(int Slot) { - // Copy extension id and calibration to its register - if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUCK) + if (WiiMapping[Slot].bMotionPlusConnected) { - memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); - memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration)); - memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id)); - } - else if(WiiMapping[Slot].iExtensionConnected == EXT_CLASSIC_CONTROLLER) - { - memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration)); - memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration)); - memcpy(g_RegExt[Slot] + 0xfa, classic_id, sizeof(classic_id)); - } - else if(WiiMapping[Slot].iExtensionConnected == EXT_GUITARHERO) - { - // TODO get the correct values here - memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration)); - memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration)); - memcpy(g_RegExt[Slot] + 0xfa, gh3glp_id, sizeof(gh3glp_id)); + // Copy extension id and calibration to its register + if (WiiMapping[Slot].iExtensionConnected == EXT_NONE) + { + memset(g_RegExt[Slot],0,sizeof(g_RegExt[0])); + memcpy(g_RegMotionPlus[Slot], motionplus_register, sizeof(motionplus_register)); + memcpy(g_RegMotionPlus[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration)); //reg 32bytes 0x20-3f; + g_MotionPlus[Slot] = 0; + //memcpy(g_RegMotionPlus[Slot] + 0xfa, motionplus_id, sizeof(motionplus_id)); + } + else if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK) + { + memset(g_RegMotionPlus[Slot],0,sizeof(g_RegExt[0])); + memcpy(g_RegMotionPlus[Slot], motionplus_register, sizeof(motionplus_register)); + memcpy(g_RegMotionPlus[Slot] + 0x20, motion_plus_calibration, sizeof(motion_plus_calibration)); //reg 32bytes 0x20-3f; + memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id)); + g_MotionPlus[Slot] = 1; + } + g_MotionPlusReadError[Slot] = 0; + + } else { + + + // Copy extension id and calibration to its register + if(WiiMapping[Slot].iExtensionConnected == EXT_NUNCHUK) + { + memcpy(g_RegExt[Slot] + 0x20, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt[Slot] + 0x30, nunchuck_calibration, sizeof(nunchuck_calibration)); + memcpy(g_RegExt[Slot] + 0xfa, nunchuck_id, sizeof(nunchuck_id)); + } + else if(WiiMapping[Slot].iExtensionConnected == EXT_CLASSIC_CONTROLLER) + { + memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt[Slot] + 0xfa, classic_id, sizeof(classic_id)); + } + else if(WiiMapping[Slot].iExtensionConnected == EXT_GUITARHERO) + { + // TODO get the correct values here + memcpy(g_RegExt[Slot] + 0x20, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt[Slot] + 0x30, classic_calibration, sizeof(classic_calibration)); + memcpy(g_RegExt[Slot] + 0xfa, gh3glp_id, sizeof(gh3glp_id)); + } + else if(WiiMapping[Slot].iExtensionConnected == EXT_WBB) + { + // TODO + } } INFO_LOG(WIIMOTE, "UpdateExtRegisterBlocks()"); @@ -546,6 +579,7 @@ void DoState(PointerWrap &p) p.Do(g_IR[i]); p.Do(g_Leds[i]); p.Do(g_Speaker[i]); + p.Do(g_MotionPlus[i]); //p.Do(g_SpeakerMute[i]); p.Do(g_ExtKey[i]); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index dd683c33fb..a9f7034963 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -45,7 +45,6 @@ extern SWiimoteInitialize g_WiimoteInitialize; namespace WiiMoteEmu { - extern void PAD_Rumble(u8 _numPAD, unsigned int _uType); /* Here we process the Output Reports that the Wii sends. Our response will be @@ -190,7 +189,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) { u32 address = convert24bit(rd->address); u16 size = convert16bit(rd->size); - + u8 addressHI = (address >> 16) & 0xFE; INFO_LOG(WIIMOTE, "Read data"); DEBUG_LOG(WIIMOTE, " Read data Space: %x", rd->space); DEBUG_LOG(WIIMOTE, " Read data Address: 0x%06x", address); @@ -205,7 +204,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) PanicAlert("WmReadData: address + size out of bounds"); return; } - SendReadDataReply(_channelID, g_Eeprom[g_ID] + address, address, (int)size); + SendReadDataReply(_channelID, g_Eeprom[g_ID] + address, address, addressHI, (int)size); /*DEBUG_LOG(WIIMOTE, "Read RegEeprom: Size: %i, Address: %08x, Offset: %08x", size, address, (address & 0xffff));*/ } @@ -213,7 +212,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) { u8* block; u32 blockSize; - switch((address >> 16) & 0xFE) + switch(addressHI) { case 0xA2: block = g_RegSpeaker[g_ID]; @@ -230,10 +229,6 @@ void WmReadData(u16 _channelID, wm_read_data* rd) // MotionPlus is pretty much just a dummy atm :p case 0xA6: block = g_RegMotionPlus[g_ID]; - block[0xFC] = 0xA6; - block[0xFD] = 0x20; - block[0xFE] = 0x00; - block[0xFF] = 0x05; blockSize = WIIMOTE_REG_EXT_SIZE; DEBUG_LOG(WIIMOTE, " Case 0xa6: MotionPlusReg [%x]", address); break; @@ -251,7 +246,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) } // Encrypt data that is read from the Wiimote Extension Register - if(((address >> 16) & 0xfe) == 0xa4) + if(addressHI == 0xa4) { // Check if encrypted reads is on if(g_RegExt[g_ID][0xf0] == 0xaa) @@ -274,9 +269,13 @@ void WmReadData(u16 _channelID, wm_read_data* rd) PanicAlert("WmReadData: address + size out of bounds! [%d %d %d]", address, size, blockSize); return; } - + //3x read error due activated(or not present device, which is not the case), WII will await a status report after init and attempting to read from write-only area @A600FE/FF + if ((g_MotionPlusReadError[g_ID] == 2) && (g_RegExt[g_ID][0xFF]== 0x05)) { //if motionplus is active, its in the current ExtReg, 0xFF will be always 0x05 + WmRequestStatus(_channelID, (wm_request_status*) rd, 1); + } // Let this function process the message and send it to the Wii - SendReadDataReply(_channelID, block + address, address, (u8)size); + SendReadDataReply(_channelID, block + address, address, addressHI, (u8)size); + } else { @@ -295,7 +294,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) _Address: The starting address inside the registry, this is used to check for out of bounds reading _Size: The total size to send */ -void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size) +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size) { int dataOffset = 0; const u8* data = (const u8*)_Base; @@ -340,6 +339,24 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size) pReply->size = 0x0f; pReply->error = 0x08; } + if (WiiMapping[g_ID].bMotionPlusConnected) + { + //MP+ will try to read from this Registeraddress, expecting an error if a previous WM+ activation has been succesful + //it also returns an error if there was no WM+ present at all + if (((_Address == 0x00FE ) || (_Address == 0x00FF )) && (_AddressHI == 0xA6)) + { + //Check if MP+ is activated, resp. if its in the current RegExt. + if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05)) + { + pReply->size = 0x0f; + pReply->error = 0x07; //error: write-only area when activated/or not present + // we use the read error at the same time as an indicator whether we need to send a faked 0x37 report or not + g_MotionPlusReadError[g_ID]++; + + } + } + } + // Logging DEBUG_LOG(WIIMOTE, "SendReadDataReply"); @@ -369,12 +386,11 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size) void WmWriteData(u16 _channelID, wm_write_data* wd) { u32 address = convert24bit(wd->address); - + u8 addressHI = (address >> 16) & 0xFE; INFO_LOG(WIIMOTE, "Write data"); DEBUG_LOG(WIIMOTE, " Space: %x", wd->space); DEBUG_LOG(WIIMOTE, " Address: 0x%06x", address); DEBUG_LOG(WIIMOTE, " Size: 0x%02x", wd->size); - // Write to EEPROM if(wd->size <= 16 && wd->space == WM_SPACE_EEPROM) { @@ -390,7 +406,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) { u8* block; u32 blockSize; - switch((address >> 16) & 0xFE) + switch(addressHI) { case 0xA2: block = g_RegSpeaker[g_ID]; @@ -422,7 +438,6 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) return; } - // Remove for example 0xa40000 from the address address &= 0xFFFF; // Check if the address is within bounds @@ -430,7 +445,7 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) PanicAlert("WmWriteData: address + size out of bounds!"); return; } - + // Finally write the registers to the right structure memcpy(block + address, wd->data, wd->size); @@ -442,7 +457,10 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) if(address >= 0x40 && address <= 0x4c) wiimote_gen_key(&g_ExtKey[g_ID], &g_RegExt[g_ID][0x40]); } - + if (WiiMapping[g_ID].bMotionPlusConnected) { + HandlingMotionPlusWrites(wd->data, addressHI, address); + } + } else { @@ -487,7 +505,7 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension) if (Extension == -1) { // Read config value for the first time - pStatus->extension = (WiiMapping[g_ID].iExtensionConnected == EXT_NONE) ? 0 : 1; + pStatus->extension = ((g_MotionPlus[g_ID]) || (WiiMapping[g_ID].iExtensionConnected != EXT_NONE)) ? 1 : 0; } else { @@ -501,10 +519,121 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs, int Extension) DEBUG_LOG(WIIMOTE, " IR: %x", pStatus->ir); DEBUG_LOG(WIIMOTE, " LEDs: %x", pStatus->leds); + g_WiimoteInitialize.pWiimoteInput(g_ID, _channelID, DataFrame, Offset); // Debugging //ReadDebugging(true, DataFrame, Offset); } + +void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address){ + switch (addressHI) + { + case 0xA4: + switch (address) + { + case 0x00FE: + if (data[0] == 0x00) { + if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05)) + { + SwapExtRegisters(); + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address); + } + else { + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM+ already inactive", data[0], addressHI, address); + } + g_MotionPlus[g_ID] = 1; + } + break; + + case 0x00FB: + //1. Initializing the extension: writing 0x55 ->0xA400F0 and then 0x00 to 0xA400FB. + //2. Disables an active wiimote; ext disconnect. + if (data[0] == 0x00) { + //1. connecting extension + if ((g_RegExt[g_ID][0xFF] != 0x05) && (g_RegMotionPlus[g_ID][0xFF] == 0x05)) + { + g_RegMotionPlus[g_ID][0xFE] = 0x04; + g_RegMotionPlus[g_ID][0xF7] = 0x08; //control init byte, ingame check + SwapExtRegisters(); + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping rgisters", data[0], addressHI, address); + g_MotionPlus[g_ID] = 0; + } //2. disconnecting extension + else if ((g_RegExt[g_ID][0xFF] == 0x05) && (g_RegMotionPlus[g_ID][0xFF] != 0x05)){ + g_RegExt[g_ID][0xFE] = 0x04; + g_MotionPlus[g_ID] = 1; + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Disabling WM+ and swapping registers back", data[0], addressHI, address); + } + } + break; + } + break; + + case 0xA6: + switch (address) + { + case 0x00FE: + //Enabling WM+, swapping extension registers + if (data[0] == 0x05) { + if ((g_RegExt[g_ID][0xFF] != 0x05) && (g_RegMotionPlus[g_ID][0xFF] == 0x05) ) { + //The WII will try to read from the readprotected A6 WM+ register now, we need to reply with an error each time, + //plus sent an statusreport 0x20(depending on if nunchuk inserted or not) + g_MotionPlusReadError[g_ID] = 0; + g_MotionPlus[g_ID] = 1; + SwapExtRegisters(); + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: Enabling WM+ and swapping rgisters back", data[0], addressHI, address); + } + else { + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: WM already enabled no register swapping", data[0], addressHI, address); + } + } + break; + + case 0x00F0: //init() WM+, this will change some control bits in the WM+ register + if (data[0] == 0x55) { //enables passthroug, convert to 0405* A6 swap + if ((g_RegMotionPlus[g_ID][0xFF] == 0x05)) + { + //control init byte, ingame check + g_RegMotionPlus[g_ID][0xF7] = 0x08; + + //motion plus id + g_RegMotionPlus[g_ID][0xFE] = 0x05; + + //we will swap the register on write to 0x00FE + } + else if (g_RegExt[g_ID][0xFF] == 0x05) { //if the wiimote is already active, we will init() the WM+ directly in the ExtReg + g_RegExt[g_ID][0xFE] = 0x05; + g_RegExt[g_ID][0xF7] = 0x08; + } + g_MotionPlus[g_ID] = 0; + } + break; + + default: + DEBUG_LOG(WIIMOTE, "Writing [0x%02x] to [0x%02x:%04x]: unknown reason", data[0], addressHI, address); + break; + } + break; + } +} + +//Swapping Ext/WM+-registers +void SwapExtRegisters(){ + + memset(g_RegExtTmp, 0, sizeof(g_RegExtTmp)); + memcpy(g_RegExtTmp, g_RegExt[g_ID], sizeof(g_RegExt[0])); + memset(g_RegExt[0], 0, sizeof(g_RegExt[0])); + memcpy(g_RegExt[g_ID], g_RegMotionPlus[g_ID], sizeof(g_RegMotionPlus[0])); + memset(g_RegMotionPlus[0], 0, sizeof(g_RegMotionPlus[0])); + memcpy(g_RegMotionPlus[g_ID], g_RegExtTmp, sizeof(g_RegExtTmp)); + + if (g_RegMotionPlus[g_ID][0xFC]) { + g_RegMotionPlus[g_ID][0xFC] = 0xa6; + } + if (g_RegExt[g_ID][0xFC]) { + g_RegExt[g_ID][0xFC] = 0xa4; + } +} + } // WiiMoteEmu diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h index a96dca3c26..f77ac49a0b 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h @@ -51,7 +51,9 @@ void SendReportCoreAccelIr10Ext(u16 _channelID); int WriteWmReportHdr(u8* dst, u8 wm); void WmSendAck(u16 _channelID, u8 _reportID); -void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, int _Size); +void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _AddressHI, int _Size); +void SwapExtRegisters(); +void HandlingMotionPlusWrites(u8* data, u8 addressHI, u32 address); void FillReportAcc(wm_accel& _acc); void FillReportInfo(wm_core& _core); @@ -60,7 +62,9 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1); void FillReportExtension(wm_extension& _ext); void FillReportClassicExtension(wm_classic_extension& _ext); void FillReportGuitarHero3Extension(wm_GH3_extension& _ext); - +void FillReportMotionPlusNunchukExtension(wm_extension& _ext); +void FillReportMotionPlusNoExtension(wm_extension& _ext); +void FillReportMotionPlus(wm_extension& ext, bool extension); } // namespace #endif //_EMU_DECLARATIONS_ diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index a54eb23914..7d336e1d4e 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -710,7 +710,8 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) );*/ // ------------------ } - +/* Generate the 6 byte extension report for the motionplus&nunchuk, encrypted. The bytes +void FillReportExtension(wm_extension& _ext) /* Generate the 6 byte extension report for the Nunchuck, encrypted. The bytes are JX JY AX AY AZ BT. */ @@ -1247,4 +1248,201 @@ void FillReportGuitarHero3Extension(wm_GH3_extension& _ext) memcpy(&_ext, Tmp, sizeof(_ext)); } +/* Generate the 6 byte extension report for the MotionPlus Controller. + pass-through mode supported for MotionPlus+Nunchuk */ +void FillReportMotionPlus(wm_extension& ext, bool extension){ + + //sending initial control packet, this must be sent first, its some kind of verifiation, all control bits are set to 0! + if (g_MotionPlusReadError[g_ID]) { + + memcpy(&ext, motionpluscheck_id, sizeof(motionpluscheck_id)); + g_MotionPlus[g_ID] = (extension) ? 1 : 0; + g_MotionPlusReadError[g_ID] = 0; + + } //nunchuk inserted + else if (extension == 1) { + + switch (g_InterleavedData[g_ID]) + { + case false://MPlus + FillReportMotionPlusNoExtension(ext); + break; + + case true: //Nunchuk + FillReportMotionPlusNunchukExtension(ext); + break; + } + //alternate between nunchuk and wm+ interleaved reports + g_InterleavedData[g_ID] = g_InterleavedData[g_ID] ? false : true; + + }//no additional extension inserted, no interleaving, always sending mp+ data + else if (extension == 0) { + + FillReportMotionPlusNoExtension(ext); + g_InterleavedData[g_ID] = false; + + } +} + +void FillReportMotionPlusNoExtension(wm_extension& _ext) +{ + wm_mp_nc_0 ext; + memset(&ext, 0, sizeof(wm_mp_nc_0)); + ext.YawLeftLS = 0x00; //dummy data atm + ext.RollLeftLS = 0x00; + ext.PitchDownLS = 0x00; + ext.pitchfast = 0x00; + ext.yawfast = 0x00; + ext.YawLeftHI = 0x00; + ext.ExtCon = 0x00; // 0 (important, since we don't use a nunchuk here) + ext.rollfast = 0x00; + ext.RollLeftHI = 0x00; + ext.dummy = 0x00; // 0 (important) + ext.mpdata = 0x01; //1 (important, using MP+ report instead of NC report) + ext.PitchDownHI = 0x00; + memcpy(&_ext, &ext, sizeof(ext)); + +} + + +void FillReportMotionPlusNunchukExtension(wm_extension& _ext) +{ + wm_mp_nc_1 ext; + memset(&ext, 0, sizeof(wm_mp_nc_1)); + ext.jx = g_nu.jx.center; + ext.jy = g_nu.jy.center; + + // Use the neutral values + ext.ax = g_nu.cal_zero.x; + ext.ay = g_nu.cal_zero.y; + ext.az = g_nu.cal_zero.z + g_nu.cal_g.z; + ext.axLS = 0x00; + ext.ayLS = 0x00; + ext.azLS = 0x00; + + ext.bz = 0x01; + ext.bc = 0x01; + ext.dummy = 0; //0 (important) + ext.mpdata = 0; //0 NC report, interleaved data (important) + ext.ExtCon = 1; // must be 1 when in NC-MP+ Mode + + + if (IsFocus()) + { + int acc_x = g_nu.cal_zero.x; + int acc_y = g_nu.cal_zero.y; + int acc_z = g_nu.cal_zero.z + g_nu.cal_g.z; + + if (IsKey(ENC_SHAKE) && !WiiMapping[g_ID].Motion.TiltNC.Shake) + WiiMapping[g_ID].Motion.TiltNC.Shake = 1; + + // Step the shake simulation one step + ShakeToAccelerometer(acc_x, acc_y, acc_z, WiiMapping[g_ID].Motion.TiltNC); + + // Tilt Nunchuck, allow the shake function to interrupt it + if (!WiiMapping[g_ID].Motion.TiltNC.Shake) + TiltNunchuck(acc_x, acc_y, acc_z); + + // Boundary check + if (acc_x > 0xFF) acc_x = 0xFF; + else if (acc_x < 0x00) acc_x = 0x00; + if (acc_y > 0xFF) acc_y = 0xFF; + else if (acc_y < 0x00) acc_y = 0x00; + if (acc_z > 0xFF) acc_z = 0xFF; + else if (acc_z < 0x00) acc_z = 0x00; + + ext.ax = acc_x; + ext.ay = acc_y; + ext.az = acc_z>>1; + ext.azLS = acc_z<<1; //LS0=0 + + + // Update the analog stick + if (WiiMapping[g_ID].Stick.NC == FROM_KEYBOARD) + { + // Set the max values to the current calibration values + if(IsKey(ENC_L)) // x + ext.jx = g_nu.jx.min; + if(IsKey(ENC_R)) + ext.jx = g_nu.jx.max; + + if(IsKey(ENC_D)) // y + ext.jy = g_nu.jy.min; + if(IsKey(ENC_U)) + ext.jy = g_nu.jy.max; + + // On a real stick, the initialization value of center is 0x80, + // but after a first time touch, the center value automatically changes to 0x7F + if(ext.jx != g_nu.jx.center) + g_nu.jx.center = 0x7F; + if(ext.jy != g_nu.jy.center) + g_nu.jy.center = 0x7F; + } + else + { + // Get adjusted pad state values + int _Lx = WiiMapping[g_ID].AxisState.Lx; + int _Ly = WiiMapping[g_ID].AxisState.Ly; + int _Rx = WiiMapping[g_ID].AxisState.Rx; + int _Ry = WiiMapping[g_ID].AxisState.Ry; + + // The Y-axis is inverted + _Ly = 0xff - _Ly; + _Ry = 0xff - _Ry; + + /* This is if we are also using a real Nunchuck that we are sharing the + calibration with. It's not needed if we are using our default + values. We adjust the values to the configured range, we even allow + the center to not be 0x80. */ + if(g_nu.jx.max != 0xff || g_nu.jy.max != 0xff + || g_nu.jx.min != 0 || g_nu.jy.min != 0 + || g_nu.jx.center != 0x80 || g_nu.jy.center != 0x80) + { + float Lx = (float)_Lx; + float Ly = (float)_Ly; + float Rx = (float)_Rx; + float Ry = (float)_Ry; + //float Tl = (float)_Tl; + //float Tr = (float)_Tr; + + float XRangePos = (float) (g_nu.jx.max - g_nu.jx.center); + float XRangeNeg = (float) (g_nu.jx.center - g_nu.jx.min); + float YRangePos = (float) (g_nu.jy.max - g_nu.jy.center); + float YRangeNeg = (float) (g_nu.jy.center - g_nu.jy.min); + if (Lx > 0x80) Lx = Lx * (XRangePos / 128.0); + if (Lx < 0x80) Lx = Lx * (XRangeNeg / 128.0); + if (Lx == 0x80) Lx = (float)g_nu.jx.center; + if (Ly > 0x80) Ly = Ly * (YRangePos / 128.0); + if (Ly < 0x80) Ly = Ly * (YRangeNeg / 128.0); + if (Ly == 0x80) Lx = (float)g_nu.jy.center; + // Boundaries + _Lx = (int)Lx; + _Ly = (int)Ly; + _Rx = (int)Rx; + _Ry = (int)Ry; + if (_Lx > 0xff) _Lx = 0xff; if (_Lx < 0) _Lx = 0; + if (_Rx > 0xff) _Rx = 0xff; if (_Rx < 0) _Rx = 0; + if (_Ly > 0xff) _Ly = 0xff; if (_Ly < 0) _Ly = 0; + if (_Ry > 0xff) _Ry = 0xff; if (_Ry < 0) _Ry = 0; + } + + if (WiiMapping[g_ID].Stick.NC == FROM_ANALOG1) + { + ext.jx = _Lx; + ext.jy = _Ly; + } + else // ANALOG2 + { + ext.jx = _Rx; + ext.jy = _Ry; + } + } + + if(IsKey(ENC_C)) ext.bc = 0x00; /////////////// + if(IsKey(ENC_Z)) ext.bz = 0x00; + + } + memcpy(&_ext, &ext, sizeof(ext)); +} + } // end of namespace diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index 105b5c9409..30414967e1 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -138,6 +138,39 @@ struct wm_classic_extension wm_cc_5 b2; // byte 5 }; +struct wm_mp_nc_0 //motionplus+nunchuk_pass-through +{ + u8 YawLeftLS; //7e + u8 RollLeftLS; //82 + u8 PitchDownLS; //83 + u8 pitchfast : 1; //1 + u8 yawfast : 1; //0 + u8 YawLeftHI : 6; //01 1010 /1a + u8 ExtCon : 1; // 1 usually + u8 rollfast : 1; //0 + u8 RollLeftHI : 6; //00 1010 + u8 dummy : 1; // 0 usually. 1 in dem fall mhh + u8 mpdata : 1; //1 in this case, interleaved motion+ data + u8 PitchDownHI : 6;//01 1100 +}; // default for yaw/roll/pitch around 0x1F7F + +struct wm_mp_nc_1 //motionplus+nunchuk_pass-through +{ + u8 jx; + u8 jy; + u8 ax; + u8 ay; + u8 ExtCon : 1; // 1 usually + u8 az : 7; + u8 dummy : 1; //0 always + u8 mpdata : 1; //0 when nunchuk interleaved data + u8 bz : 1; + u8 bc : 1; + u8 axLS : 1; // ls 1, ls0 = 0 by default, + u8 ayLS : 1; + u8 azLS : 2; +}; + struct wm_GH3_extension { u8 SX : 6;