summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsnzgoo <snzgoo@gmail.com>2010-05-07 22:39:06 +0000
committersnzgoo <snzgoo@gmail.com>2010-05-07 22:39:06 +0000
commit7742e1a6dd4baec8e660cb1acf6fcda0da9cebd7 (patch)
tree160eb08bcff260e79ade73b72067194f83a033ff
parentf6ce87765f798c36deb9e0c85e20599a16b0896d (diff)
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
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/ConfigBasicDlg.cpp8
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.cpp12
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/ConfigPadDlg.h2
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp65
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp4
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h36
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp70
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp167
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h8
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp200
-rw-r--r--Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h33
11 files changed, 529 insertions, 76 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 defined(HAVE_WX) && HAVE_WX
- FillReportExtension(pReport->ext);
-#endif
- }
- else if(WiiMapping[g_ID].iExtensionConnected == EXT_CLASSIC_CONTROLLER)
+ if ((WiiMapping[g_ID].bMotionPlusConnected) && (( WiiMapping[g_ID].iExtensionConnected == EXT_NUNCHUK ) || (WiiMapping[g_ID].iExtensionConnected == EXT_NONE)) )
{
-#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;