mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
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
This commit is contained in:
parent
f6ce87765f
commit
7742e1a6dd
@ -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();
|
||||
|
@ -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++)
|
||||
|
@ -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],
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user