Emulated Wiimote: Updated the accelerometer recording to record the gravity forces in all directions instead of recording raw data, to bypass problem of different Wiimotes having different neutral values

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2316 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-20 09:57:17 +00:00
parent cefa910d92
commit 489816dce7
12 changed files with 333 additions and 167 deletions

View File

@ -64,7 +64,6 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CHECKBOX(ID_CONNECT_REAL, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_USE_REAL, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_UPDATE_REAL, ConfigDialog::GeneralSettingsChanged)
EVT_CHOICE(ID_NEUTRAL_CHOICE, ConfigDialog::GeneralSettingsChanged)
// Recording
EVT_CHOICE(IDC_RECORD + 1, ConfigDialog::GeneralSettingsChanged)
@ -658,20 +657,22 @@ void ConfigDialog::CreateGUIControls()
m_SizeBasicGeneralLeft[i] = new wxBoxSizer(wxVERTICAL);
m_SizeBasicGeneralRight[i] = new wxBoxSizer(wxVERTICAL);
m_SizeBasicGeneralLeft[i]->Add(m_SizeBasic[i], 0, wxEXPAND | (wxUP), 0);
m_SizeBasicGeneralLeft[i]->Add(m_SizeReal[i], 0, wxEXPAND | (wxUP), 0);
m_SizeBasicGeneralLeft[i]->Add(m_SizeExtensions[i], 0, wxEXPAND | (wxUP), 5);
m_SizeBasicGeneralRight[i]->Add(m_SizeReal[i], 0, wxEXPAND | (wxUP), 0);
m_SizeBasicGeneralRight[i]->Add(m_SizeBasic[i], 0, wxEXPAND | (wxUP), 0);
m_SizeBasicGeneralRight[i]->Add(m_SizeEmu[i], 0, wxEXPAND | (wxUP), 5);
m_SizeBasicGeneralRight[i]->Add(m_SizerIRPointer[i], 0, wxEXPAND | (wxUP), 5);
m_SizeBasicGeneral[i]->Add(m_SizeBasicGeneralLeft[i], 0, wxEXPAND | (wxUP), 0);
m_SizeBasicGeneral[i]->Add(m_SizeBasicGeneralRight[i], 0, wxEXPAND | (wxLEFT), 10);
m_SizeBasicGeneral[i]->Add(m_SizeBasicGeneralRight[i], 0, wxEXPAND | (wxLEFT), 5);
// ------------------------
///////////////////////////
////////////////////////////////////////////////////////////////////////
// Gamepad input
// ----------------
@ -1305,7 +1306,7 @@ void ConfigDialog::DoUseReal()
// Disable the checkbox for a moment
SetCursor(wxCursor(wxCURSOR_WAIT));
m_bEnableUseRealWiimote = false;
// We don't need this, there is already a message queue that allows the nessesary timeout
// We may not need this if there is already a message queue that allows the nessesary timeout
//sleep(100);
/* Start the timer to allow the approximate time it takes for the Wiimote to come online
@ -1438,14 +1439,6 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_UPDATE_REAL:
g_Config.bUpdateRealWiimote = m_UpdateMeters->IsChecked();
break;
case ID_NEUTRAL_CHOICE:
g_Config.iAccNeutralX = m_AccNeutralChoice[0]->GetSelection();
g_Config.iAccNeutralY = m_AccNeutralChoice[1]->GetSelection();
g_Config.iAccNeutralZ = m_AccNeutralChoice[2]->GetSelection();
//g_Config.iAccNunNeutralX = m_AccNunNeutralChoice[0]->GetSelection();
//g_Config.iAccNunNeutralY = m_AccNunNeutralChoice[1]->GetSelection();
//g_Config.iAccNunNeutralZ = m_AccNunNeutralChoice[2]->GetSelection();
break;
case IDC_RECORD + 1:
case IDC_RECORD + 2:

View File

@ -59,11 +59,11 @@ class ConfigDialog : public wxDialog
wxGauge *m_GaugeBattery, *m_GaugeRoll[2], *m_GaugeGForce[3], *m_GaugeAccel[3];
wxStaticBitmap *m_bmpDotLeftIn[4], *m_bmpDotLeftOut[4], *m_bmpDotRightIn[4], *m_bmpDotRightOut[4],
*m_bmpDeadZoneLeftIn[4], *m_bmpDeadZoneRightIn[4];
wxStaticText *m_TextIR, *m_TextAccNeutralCurrent;
wxStaticText *m_TextIR;
bool m_bWaitForRecording, m_bRecording, m_bAllowA;
int m_iRecordTo;
void RecordMovement(wxCommandEvent& event);
void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes);
void DoRecordMovement(int _x, int _y, int _z, const u8 *_IR, int IRBytes);
void DoRecordA(bool Pressed);
void Convert2Box(int &x);
void ConvertToString();
@ -131,7 +131,6 @@ class ConfigDialog : public wxDialog
// Real Wiimote settings
wxCheckBox *m_ConnectRealWiimote[4], *m_UseRealWiimote[4], *m_UpdateMeters;
wxChoice *m_AccNeutralChoice[3], *m_AccNunNeutralChoice[3];
wxPanel *m_pLeftInStatus[4], *m_pLeftOutStatus[4], *m_pRightInStatus[4], *m_pRightOutStatus[4];
wxStaticBitmap *m_bmpSquareLeftIn[4], *m_bmpSquareLeftOut[4], *m_bmpSquareRightIn[4], *m_bmpSquareRightOut[4];
@ -207,7 +206,7 @@ class ConfigDialog : public wxDialog
IDCB_NUNCHUCK_STICK,
// Real
ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS, ID_NEUTRAL_CHOICE,
ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS,
IDB_RECORD = 2000,
IDC_RECORD = 3000,
IDC_PLAY_WIIMOTE, IDC_PLAY_NUNCHUCK, IDC_PLAY_IR, IDT_RECORD_TEXT, IDT_RECORD_GAMETEXT, IDT_RECORD_IRBYTESTEXT, IDT_RECORD_SPEED, IDT_RECORD_PLAYSPEED

View File

@ -136,7 +136,6 @@ void ConfigDialog::CreateGUIControlsRecording()
// ---------------------------------------------
// Status
// ----------------
wxStaticBoxSizer * sbRealStatus = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Status"));
m_TextUpdateRate = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Update rate: 000 times/s"));
m_UpdateMeters = new wxCheckBox(m_PageRecording, ID_UPDATE_REAL, wxT("Update gauges"));
@ -146,47 +145,8 @@ void ConfigDialog::CreateGUIControlsRecording()
"You can turn this off when a game is running to avoid a potential slowdown that may come from redrawing the\n"
"configuration screen. Remember that you also need to press '+' on your Wiimote before you can record movements."
));
sbRealStatus->Add(m_TextUpdateRate, 0, wxEXPAND | (wxALL), 5);
sbRealStatus->Add(m_UpdateMeters, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxUP), 5);
// -----------------------
// ---------------------------------------------
// Wiimote accelerometer neutral values
// ----------------
wxStaticBoxSizer * sbRealNeutral = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Wiimote neutral"));
wxStaticText * m_TextAccNeutralTarget = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Target: 132 132 159"));
m_TextAccNeutralCurrent = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Current: 000 000 000"));
wxArrayString StrAccNeutral;
for(int i = 0; i < 31; i++) StrAccNeutral.Add(wxString::Format(wxT("%i"), i));
for(int i = 0; i < 3; i++) m_AccNeutralChoice[i] = new wxChoice(m_PageRecording, ID_NEUTRAL_CHOICE, wxDefaultPosition, wxDefaultSize, StrAccNeutral);
m_AccNeutralChoice[0]->SetSelection(g_Config.iAccNeutralX);
m_AccNeutralChoice[1]->SetSelection(g_Config.iAccNeutralY);
m_AccNeutralChoice[2]->SetSelection(g_Config.iAccNeutralZ);
wxBoxSizer * sbRealWiimoteNeutralChoices = new wxBoxSizer(wxHORIZONTAL);
sbRealWiimoteNeutralChoices->Add(m_AccNeutralChoice[0], 0, wxEXPAND | (wxALL), 0);
sbRealWiimoteNeutralChoices->Add(m_AccNeutralChoice[1], 0, wxEXPAND | (wxLEFT), 2);
sbRealWiimoteNeutralChoices->Add(m_AccNeutralChoice[2], 0, wxEXPAND | (wxLEFT), 2);
sbRealNeutral->Add(m_TextAccNeutralTarget, 0, wxEXPAND | (wxALL), 5);
sbRealNeutral->Add(m_TextAccNeutralCurrent, 0, wxEXPAND | (wxLEFT | wxRIGHT), 5);
sbRealNeutral->Add(sbRealWiimoteNeutralChoices, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxUP), 5);
m_TextAccNeutralTarget->SetToolTip(wxT(
"To produce compatible accelerometer recordings that can be shared with other users without problems"
" you have to adjust the Current value to the Target value before you make a recording."
));
// Wiimote Status
wxBoxSizer * sbRealWiimoteStatus = new wxBoxSizer(wxHORIZONTAL);
wxStaticBoxSizer * sbRealBattery = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Battery"));
wxStaticBoxSizer * sbRealRoll = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Roll and Pitch"));
wxStaticBoxSizer * sbRealGForce = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("G-Force"));
wxStaticBoxSizer * sbRealAccel = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Accelerometer"));
wxStaticBoxSizer * sbRealIR = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("IR"));
// Width and height of the gauges
static const int Gw = 35, Gh = 110;
@ -203,7 +163,7 @@ void ConfigDialog::CreateGUIControlsRecording()
// The text controls
m_TextIR = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Cursor: 000 000\nDistance: 0000"));
// -----------------------------
// ------------------------------------
// The sizers for all gauges together with their label
// -----------
wxBoxSizer * sBoxBattery = new wxBoxSizer(wxVERTICAL);
@ -228,34 +188,51 @@ void ConfigDialog::CreateGUIControlsRecording()
m_TextZ[0] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[1] = new wxStaticText(m_PageRecording, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
// ----------------
// -----------------------------
// Set up sizers
// ----------------------------------------------
// Row 1 Sizers
// -----------
sBoxBattery->Add(m_GaugeBattery, 0, wxEXPAND | (wxALL), 5); sBoxBattery->Add(m_TextBattery, 0, wxEXPAND | (wxALL), 0);
sBoxBattery->Add(m_GaugeBattery, 0, wxEXPAND | (wxALL), 0); sBoxBattery->Add(m_TextBattery, 0, wxEXPAND | (wxUP), 5);
sBoxRoll[0]->Add(m_GaugeRoll[0], 0, wxEXPAND | (wxALL), 5); sBoxRoll[0]->Add(m_TextRoll, 0, wxEXPAND | (wxALL), 0);
sBoxRoll[1]->Add(m_GaugeRoll[1], 0, wxEXPAND | (wxALL), 5); sBoxRoll[1]->Add(m_TextPitch, 0, wxEXPAND | (wxALL), 0);
sBoxRoll[0]->Add(m_GaugeRoll[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxRoll[0]->Add(m_TextRoll, 0, wxEXPAND | (wxUP), 5);
sBoxRoll[1]->Add(m_GaugeRoll[1], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxRoll[1]->Add(m_TextPitch, 0, wxEXPAND | (wxUP), 5);
sBoxGForce[0]->Add(m_GaugeGForce[0], 0, wxEXPAND | (wxALL), 5); sBoxGForce[0]->Add(m_TextX[0], 0, wxEXPAND | (wxALL), 0);
sBoxGForce[1]->Add(m_GaugeGForce[1], 0, wxEXPAND | (wxALL), 5); sBoxGForce[1]->Add(m_TextY[0], 0, wxEXPAND | (wxALL), 0);
sBoxGForce[2]->Add(m_GaugeGForce[2], 0, wxEXPAND | (wxALL), 5); sBoxGForce[2]->Add(m_TextZ[0], 0, wxEXPAND | (wxALL), 0);
sBoxGForce[0]->Add(m_GaugeGForce[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxGForce[0]->Add(m_TextX[0], 0, wxEXPAND | (wxUP), 5);
sBoxGForce[1]->Add(m_GaugeGForce[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxGForce[1]->Add(m_TextY[0], 0, wxEXPAND | (wxUP), 5);
sBoxGForce[2]->Add(m_GaugeGForce[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxGForce[2]->Add(m_TextZ[0], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[0]->Add(m_GaugeAccel[0], 0, wxEXPAND | (wxALL), 5); sBoxAccel[0]->Add(m_TextX[1], 0, wxEXPAND | (wxALL), 0);
sBoxAccel[1]->Add(m_GaugeAccel[1], 0, wxEXPAND | (wxALL), 5); sBoxAccel[1]->Add(m_TextY[1], 0, wxEXPAND | (wxALL), 0);
sBoxAccel[2]->Add(m_GaugeAccel[2], 0, wxEXPAND | (wxALL), 5); sBoxAccel[2]->Add(m_TextZ[1], 0, wxEXPAND | (wxALL), 0);
sBoxAccel[0]->Add(m_GaugeAccel[0], 0, wxEXPAND | (wxUP | wxDOWN | wxLEFT), 0); sBoxAccel[0]->Add(m_TextX[1], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[1]->Add(m_GaugeAccel[1], 0, wxEXPAND | (wxUP | wxDOWN), 0); sBoxAccel[1]->Add(m_TextY[1], 0, wxEXPAND | (wxUP), 5);
sBoxAccel[2]->Add(m_GaugeAccel[2], 0, wxEXPAND | (wxUP | wxDOWN | wxRIGHT), 0); sBoxAccel[2]->Add(m_TextZ[1], 0, wxEXPAND | (wxUP), 5);
wxStaticBoxSizer * sbRealStatus = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Status"));
wxStaticBoxSizer * sbRealIR = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("IR"));
wxStaticBoxSizer * sbRealBattery = new wxStaticBoxSizer(wxVERTICAL, m_PageRecording, wxT("Battery"));
wxStaticBoxSizer * sbRealRoll = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Roll and Pitch"));
wxStaticBoxSizer * sbRealGForce = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("G-Force"));
wxStaticBoxSizer * sbRealAccel = new wxStaticBoxSizer(wxHORIZONTAL, m_PageRecording, wxT("Accelerometer"));
// Status
sbRealStatus->Add(m_TextUpdateRate, 0, wxEXPAND | (wxALL), 5);
sbRealStatus->Add(m_UpdateMeters, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
sbRealIR->Add(m_TextIR, 0, wxEXPAND | (wxALL), 5);
sbRealBattery->Add(sBoxBattery, 0, wxEXPAND | (wxALL), 5);
sbRealRoll->Add(sBoxRoll[0], 0, wxEXPAND | (wxALL), 5); sbRealRoll->Add(sBoxRoll[1], 0, wxEXPAND | (wxALL), 5);
sbRealGForce->Add(sBoxGForce[0], 0, wxEXPAND | (wxALL), 5); sbRealGForce->Add(sBoxGForce[1], 0, wxEXPAND | (wxALL), 5); sbRealGForce->Add(sBoxGForce[2], 0, wxEXPAND | (wxALL), 5);
sbRealAccel->Add(sBoxAccel[0], 0, wxEXPAND | (wxALL), 5); sbRealAccel->Add(sBoxAccel[1], 0, wxEXPAND | (wxALL), 5); sbRealAccel->Add(sBoxAccel[2], 0, wxEXPAND | (wxALL), 5);
sbRealIR->Add(m_TextIR, 0, wxEXPAND | (wxALL), 5);
sbRealWiimoteStatus->Add(sbRealBattery, 0, wxEXPAND | (wxLEFT), 0);
// Vertical leftmost status
wxBoxSizer * sbStatusLeft = new wxBoxSizer(wxVERTICAL);
sbStatusLeft->Add(sbRealStatus, 0, wxEXPAND | (wxLEFT), 0);
sbStatusLeft->Add(sbRealIR, 0, wxEXPAND | (wxLEFT), 0);
wxBoxSizer * sbRealWiimoteStatus = new wxBoxSizer(wxHORIZONTAL);
sbRealWiimoteStatus->Add(sbStatusLeft, 0, wxEXPAND | (wxLEFT), 0);
sbRealWiimoteStatus->Add(sbRealBattery, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealRoll, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealGForce, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealAccel, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealIR, 0, wxEXPAND | (wxLEFT), 5);
// ----------------
// --------------------
// Tool tips
m_GaugeBattery->SetToolTip(wxT("Press '+' to show the current status. Press '-' to stop recording the status."));
@ -337,6 +314,9 @@ void ConfigDialog::CreateGUIControlsRecording()
m_RecordIRBytesText[i]->Enable(false);
m_RecordSpeed[i]->Enable(false);
// ------------------------------------
// Row 2 Sizers
// -----------
sRealRecord[i]->Add(m_RecordButton[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordHotKeySwitch[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordHotKeyWiimote[i], 0, wxEXPAND | (wxLEFT), 2);
@ -352,17 +332,11 @@ void ConfigDialog::CreateGUIControlsRecording()
}
// ==========================================
// ----------------------------------------------------------------------
// Set up sizers
// Set up sizers for the whole page
// ----------------
wxBoxSizer * sRealBasicStatus = new wxBoxSizer(wxHORIZONTAL);
sRealBasicStatus->Add(sbRealStatus, 0, wxEXPAND | (wxLEFT), 0);
sRealBasicStatus->Add(sbRealNeutral, 0, wxEXPAND | (wxLEFT), 5);
m_sRecordingMain = new wxBoxSizer(wxVERTICAL);
m_sRecordingMain->Add(sRealBasicStatus, 0, wxEXPAND | (wxALL), 5);
m_sRecordingMain->Add(sbRealWiimoteStatus, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_sRecordingMain->Add(sbRealWiimoteStatus, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxUP), 5);
m_sRecordingMain->Add(sbRealRecord, 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_PageRecording->SetSizer(m_sRecordingMain);
@ -384,11 +358,13 @@ void ConfigDialog::ConvertToString()
for (int i = 0; i < m_vRecording.size(); i++)
{
// Write the movement data
TmpStr += StringFromFormat("%02x", m_vRecording.at(i).x);
TmpStr += StringFromFormat("%02x", m_vRecording.at(i).y);
TmpStr += StringFromFormat("%02x", m_vRecording.at(i).z);
TmpStr += StringFromFormat("%s", m_vRecording.at(i).x >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).x).c_str() : StringFromFormat("%04i", m_vRecording.at(i).x).c_str());
TmpStr += StringFromFormat("%s", m_vRecording.at(i).y >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).y).c_str() : StringFromFormat("%04i", m_vRecording.at(i).y).c_str());
TmpStr += StringFromFormat("%s", m_vRecording.at(i).z >= 0 ? StringFromFormat("+%03i", m_vRecording.at(i).z).c_str() : StringFromFormat("%04i", m_vRecording.at(i).z).c_str());
if(i < (m_vRecording.size() - 1)) TmpStr += ",";
//Console::Print("%s\n", TmpStr.c_str());
// Write the IR data
TmpIR += ArrayToString(m_vRecording.at(i).IR, IRBytes, 0, 30, false);
if(i < (m_vRecording.size() - 1)) TmpIR += ",";
@ -517,7 +493,7 @@ void ConfigDialog::DoRecordA(bool Pressed)
UpdateGUI();
}
void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int _IRBytes)
void ConfigDialog::DoRecordMovement(int _x, int _y, int _z, const u8 *_IR, int _IRBytes)
{
//std::string Tmp1 = ArrayToString(_IR, 20, 0, 30);
//Console::Print("DoRecordMovement: %s\n", Tmp1.c_str());

View File

@ -51,8 +51,10 @@ namespace WiiMoteEmu
#define TOP 215
#define RIGHT 752
#define BOTTOM 705
/* Since the width of the entire screen is 1024 a reasonable sensor bar width is perhaps 200,
given how small most sensor bars are compared to the total TV width */
/* Since the width of the entire virtual screen is 1024 a reasonable sensor bar width is perhaps 200,
given how small most sensor bars are compared to the total TV width. When I tried the distance with
my Wiimote from around three meters distance from the sensor bar (that has around 15 cm beteen the
IR lights) I got a dot distance of around 110 (and a dot size of between 1 and 2). */
#define SENSOR_BAR_RADIUS 100
// Movement recording
@ -101,6 +103,7 @@ extern bool g_Encryption;
static const u8 EepromData_0[] = {
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
// Accelerometer neutral values
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E
};
@ -179,11 +182,13 @@ struct SDot
{
int Rx, Ry, X, Y;
bool Visible;
u8 Size; /**< size of the IR dot (0-15) */
int Size; // Size of the IR dot (0-15)
int Order; // Increasing order from low to higher x-axis values
};
struct SIR
{
SDot Dot[4];
int Distance;
};
// Keyboard input

View File

@ -45,6 +45,11 @@ namespace WiiMoteEmu
{
//******************************************************************************
// Accelerometer functions
//******************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////
// Test the calculations
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
@ -203,15 +208,61 @@ void PitchAccelerometerToDegree(u8 _x, u8 _y, u8 _z, int &_Roll, int &_Pitch, in
}
//******************************************************************************
// IR data functions
//******************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////
// Calculate dot positions from the basic 10 byte IR data
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
void IRData2DotsBasic(u8 *Data)
{
struct SDot* Dot = g_Wm.IR.Dot;
Dot[0].Rx = 1023 - (Data[0] | ((Data[2] & 0x30) << 4));
Dot[0].Ry = Data[1] | ((Data[2] & 0xc0) << 2);
Dot[1].Rx = 1023 - (Data[3] | ((Data[2] & 0x03) << 8));
Dot[1].Ry = Data[4] | ((Data[2] & 0x0c) << 6);
Dot[2].Rx = 1023 - (Data[5] | ((Data[7] & 0x30) << 4));
Dot[2].Ry = Data[6] | ((Data[7] & 0xc0) << 2);
Dot[3].Rx = 1023 - (Data[8] | ((Data[7] & 0x03) << 8));
Dot[3].Ry = Data[9] | ((Data[7] & 0x0c) << 6);
/* set each IR spot to visible if spot is in range */
for (int i = 0; i < 4; ++i)
{
if (Dot[i].Ry == 1023)
{
Dot[i].Visible = 0;
}
else
{
Dot[i].Visible = 1;
Dot[i].Size = 0; /* since we don't know the size, set it as 0 */
}
// For now we let our virtual resolution be the same as the default one
Dot[i].X = Dot[i].Rx; Dot[i].Y = Dot[i].Ry;
}
// Calculate the other values
ReorderIRDots();
IRData2Distance();
}
//////////////////////////////////////////////////////////////////////////////////////////
// Calculate dot positions from the extented 12 byte IR data
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
void IRData2Dots(u8 *Data)
{
struct SDot* Dot = g_Wm.IR.Dot;
//SDot Dot[4];
for (int i = 0; i < 4; ++i)
{
@ -228,13 +279,88 @@ void IRData2Dots(u8 *Data)
else
Dot[i].Visible = true;
// Write to the global IR variable
//g_Wm.IR.Dot[i] = Dot[i];
//Console::Print("Rx: %i\n", Dot[i].Rx);
// For now we let our virtual resolution be the same as the default one
Dot[i].X = Dot[i].Rx; Dot[i].Y = Dot[i].Ry;
}
// Calculate the other values
ReorderIRDots();
IRData2Distance();
}
////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Reorder the IR dots according to their x-axis value
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
void ReorderIRDots()
{
// Create a shortcut
struct SDot* Dot = g_Wm.IR.Dot;
// Variables
int i, j, order;
// Reset the dot ordering to zero
for (i = 0; i < 4; ++i)
Dot[i].Order = 0;
for (order = 1; order < 5; ++order)
{
i = 0;
//
for (; !Dot[i].Visible || Dot[i].Order; ++i)
if (i > 4) return;
//
for (j = 0; j < 4; ++j)
{
if (Dot[j].Visible && !Dot[j].Order && (Dot[j].X < Dot[i].X))
i = j;
}
Dot[i].Order = order;
}
}
////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Calculate dot positions from the extented 12 byte IR data
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
void IRData2Distance()
{
// Create a shortcut
struct SDot* Dot = g_Wm.IR.Dot;
// Make these ones global
int i1, i2;
for (i1 = 0; i1 < 4; ++i1)
if (Dot[i1].Visible) break;
// Only one dot was visible, we can not calculate the distance
if (i1 == 4) { g_Wm.IR.Distance = 0; return; }
// Look at the next dot
for (i2 = i1 + 1; i2 < 4; ++i2)
if (Dot[i2].Visible) break;
// Only one dot was visible, we can not calculate the distance
if (i2 == 4) { g_Wm.IR.Distance = 0; return; }
/* For the emulated Wiimote the y distance is always zero so then the distance is the
simple distance between the x dots, i.e. the sensor bar width */
int xd = Dot[i2].X - Dot[i1].X;
int yd = Dot[i2].Y - Dot[i1].Y;
// Save the distance
g_Wm.IR.Distance = (int)sqrt((float)(xd*xd) + (float)(yd*yd));
}
////////////////////////////////
} // WiiMoteEmu

View File

@ -96,7 +96,7 @@ void GetMousePos(float& x, float& y)
// ===================================================
/* Homebrew encryption for 0x00000000 encryption keys. */
/* Homebrew encryption for 16 byte zero keys. */
// ----------------
void CryptBuffer(u8* _buffer, u8 _size)
{
@ -122,7 +122,7 @@ void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
// ----------------
void LoadRecordedMovements()
{
Console::Print("LoadRecordedMovements()");
Console::Print("LoadRecordedMovements()\n");
IniFile file;
file.Load("WiimoteMovement.ini");
@ -157,21 +157,23 @@ void LoadRecordedMovements()
VRecording.at(i).IRBytes = TmpIRBytes;
SRecording Tmp;
for (int j = 0, k = 0, l = 0; j < TmpMovement.length(); j+=7)
for (int j = 0, k = 0, l = 0; j < TmpMovement.length(); j+=13)
{
// Skip blank savings
if (TmpMovement.length() < 3) continue;
std::string StrX = TmpMovement.substr(j, 2);
std::string StrY = TmpMovement.substr(j + 2, 2);
std::string StrZ = TmpMovement.substr(j + 4, 2);
u32 TmpX, TmpY, TmpZ;
AsciiToHex(StrX.c_str(), TmpX);
AsciiToHex(StrY.c_str(), TmpY);
AsciiToHex(StrZ.c_str(), TmpZ);
Tmp.x = (u8)TmpX;
Tmp.y = (u8)TmpY;
Tmp.z = (u8)TmpZ;
// Avoid going to far, this can only happen with modified ini files, but we check for it anyway
if (TmpMovement.length() < j + 12) continue;
// Skip old style recordings
if (TmpMovement.substr(j, 1) != "-" && TmpMovement.substr(j, 1) != "+") continue;
std::string StrX = TmpMovement.substr(j, 4);
std::string StrY = TmpMovement.substr(j + 4, 4);
std::string StrZ = TmpMovement.substr(j + 8, 4);
Tmp.x = atoi(StrX.c_str());
Tmp.y = atoi(StrY.c_str());
Tmp.z = atoi(StrZ.c_str());
// ---------------------------------
// Go to next set of IR values
@ -220,16 +222,16 @@ void LoadRecordedMovements()
// ---------------------------------
// Logging
// ---------
std::string TmpIRLog;
if(TmpIRBytes > 0)
/*std::string TmpIRLog;
if(TmpIRBytes > 0 && VRecording.size() > i)
TmpIRLog = ArrayToString(VRecording.at(i).Recording.at(0).IR, TmpIRBytes, 0, 30);
else
TmpIRLog = "";
/*
Console::Print("Size:%i HotKey:%i PlSpeed:%i IR: %s\n",
VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed,
TmpIRLog.c_str()
Console::Print("Size:%i HotKey:%i PlSpeed:%i IR:%s X:%i Y:%i Z:%i\n",
VRecording.at(i).Recording.size(), VRecording.at(i).HotKeyWiimote, VRecording.at(i).PlaybackSpeed,
TmpIRLog.c_str(),
VRecording.at(i).Recording.at(0).x, VRecording.at(i).Recording.at(0).y, VRecording.at(i).Recording.at(0).z
);*/
// ---------------------
}
@ -257,7 +259,7 @@ void UpdateEeprom()
g_nu.jy.center = g_RegExt[0x2d];
Console::Print("\nUpdateEeprom: %i %i %i\n",
WiiMoteEmu::g_Eeprom[22], WiiMoteEmu::g_Eeprom[23], WiiMoteEmu::g_Eeprom[27]);
WiiMoteEmu::g_Eeprom[22], WiiMoteEmu::g_Eeprom[23], WiiMoteEmu::g_Eeprom[28]);
Console::Print("UpdateExtension: %i %i %i %i %i\n\n",
WiiMoteEmu::g_RegExt[0x2a], WiiMoteEmu::g_RegExt[0x2d],

View File

@ -64,6 +64,9 @@ void AdjustAngles(float &Roll, float &Pitch);
// IR data
void IRData2Dots(u8 *Data);
void IRData2DotsBasic(u8 *Data);
void ReorderIRDots();
void IRData2Distance();
}; // WiiMoteEmu

View File

@ -57,6 +57,33 @@ double g_RecordingStart[3]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0;
double g_RecordingCurrentTime[3]; //g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0;
// --------------------------
// Convert from -350 to -3.5 g
int G2Accelerometer(int _G, int XYZ)
{
float G = (float)_G / 100.0;
float Neutral, OneG, Accelerometer;
switch(XYZ)
{
case 0:
OneG = (float)g_accel.cal_g.x;
Neutral = (float)g_accel.cal_zero.x;
break;
case 1:
OneG = (float)g_accel.cal_g.y;
Neutral = (float)g_accel.cal_zero.y;
break;
case 2:
OneG = (float)g_accel.cal_g.z;
Neutral = (float)g_accel.cal_zero.z;
break;
default: PanicAlert("There is a syntax error in a function that is calling G2Accelerometer(%i, %i)", _G, XYZ);
}
Accelerometer = Neutral + (OneG * G);
return (int)Accelerometer;
}
template<class IRReportType>
bool RecordingPlayAccIR(u8 &_x, u8 &_y, u8 &_z, IRReportType &_IR, int Wm)
{
@ -132,9 +159,9 @@ bool RecordingPlayAccIR(u8 &_x, u8 &_y, u8 &_z, IRReportType &_IR, int Wm)
}
// Update accelerometer values
_x = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x;
_y = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y;
_z = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).z;
_x = G2Accelerometer(VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x, 0);
_y = G2Accelerometer(VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y, 1);
_z = G2Accelerometer(VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).z, 2);
// Update IR values
if(Wm == WM_RECORDING_IR) memcpy(&_IR, VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).IR, IRBytes);

View File

@ -174,10 +174,15 @@ void handle_event(struct wiimote_t* wm)
if(frame)
{
// Produce adjusted accelerometer values
u8 AccelX = 0, AccelY = 0, AccelZ = 0;
if((wm->accel.x + g_Config.iAccNunNeutralX) <= 255) AccelX = wm->accel.x + g_Config.iAccNeutralX;
if((wm->accel.y + g_Config.iAccNunNeutralY) <= 255) AccelY = wm->accel.y + g_Config.iAccNeutralY;
if((wm->accel.z + g_Config.iAccNunNeutralZ) <= 255) AccelZ = wm->accel.z + g_Config.iAccNeutralZ;
float _Gx = (float)(wm->accel.x - wm->accel_calib.cal_zero.x) / (float)wm->accel_calib.cal_g.x;
float _Gy = (float)(wm->accel.y - wm->accel_calib.cal_zero.y) / (float)wm->accel_calib.cal_g.y;
float _Gz = (float)(wm->accel.z - wm->accel_calib.cal_zero.z) / (float)wm->accel_calib.cal_g.z;
// Conver the data to integers
int Gx = (int)(_Gx * 100);
int Gy = (int)(_Gy * 100);
int Gz = (int)(_Gz * 100);
// And for the Nunchuck
u8 AccelNX = 0, AccelNY = 0, AccelNZ = 0;
if(wm->exp.type == EXP_NUNCHUK)
@ -193,28 +198,29 @@ void handle_event(struct wiimote_t* wm)
frame->m_GaugeRoll[0]->SetValue(wm->orient.roll + 180);
frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180);
// Show g. forces between -3 and 3
frame->m_GaugeGForce[0]->SetValue((int)floor((wm->gforce.x * 100) + 300.5));
frame->m_GaugeGForce[1]->SetValue((int)floor((wm->gforce.y * 100) + 300.5));
frame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5));
frame->m_GaugeAccel[0]->SetValue(AccelX);
frame->m_GaugeAccel[1]->SetValue(AccelY);
frame->m_GaugeAccel[2]->SetValue(AccelZ);
frame->m_GaugeAccel[0]->SetValue(wm->accel.x);
frame->m_GaugeAccel[1]->SetValue(wm->accel.y);
frame->m_GaugeAccel[2]->SetValue(wm->accel.z);
frame->m_TextIR->SetLabel(wxString::Format(
wxT("Cursor: %03u %03u\nDistance:%4.0f"), wm->ir.x, wm->ir.y, wm->ir.z));
frame->m_TextAccNeutralCurrent->SetLabel(wxString::Format(
wxT("Current: %03u %03u %03u"), AccelX, AccelY, AccelZ));
//frame->m_TextAccNeutralCurrent->SetLabel(wxString::Format(
// wxT("Current: %03u %03u %03u"), Gx, Gy, Gz));
if(frame->m_bRecording)
Console::Print("Wiiuse Recorded accel x, y, z: %03i %03i %03i\n", AccelX, AccelY, AccelZ);
//Console::Print("Wiiuse Recorded accel x, y, z: %02x %02x %02x\n", AccelX, AccelY, AccelZ);
Console::Print("Wiiuse Recorded accel x, y, z: %03i %03i %03i\n", Gx, Gy, Gz);
//Console::Print("Wiiuse Recorded accel x, y, z: %02x %02x %02x\n", Gx, Gy, Gz);
}
// Send the data to be saved
//const u8* data = (const u8*)wm->event_buf;
frame->DoRecordMovement(AccelX, AccelY, AccelZ, (g_EventBuffer + 6),
frame->DoRecordMovement(Gx, Gy, Gz, (g_EventBuffer + 6),
(WIIUSE_USING_EXP(wm) ? 10 : 12));
// Turn recording on and off
@ -248,9 +254,6 @@ void handle_event(struct wiimote_t* wm)
#if defined(HAVE_WX) && HAVE_WX
if (frame)
{
frame->m_TextAccNeutralCurrent->SetLabel(wxT("Current: 000 000 000"));
frame->m_GaugeRoll[0]->SetValue(0);
frame->m_GaugeRoll[1]->SetValue(0);
@ -285,7 +288,7 @@ void ReadWiimote()
wiiuse_io_read() and wiiuse_io_write() loop again. */
if (g_RunTemporary)
{
// This holds if the update rate of wiiuse_poll() is kept at the default value of 10 ms
// The SecondsToWait holds if the update rate of wiiuse_poll() is kept at the default value of 10 ms
static const int SecondsToWait = 2;
g_RunTemporaryCountdown++;
if(g_RunTemporaryCountdown > (SecondsToWait * 100))
@ -334,10 +337,8 @@ void ReadWiimote()
{
Temp = ArrayToString(g_WiiMotesFromWiiUse[0]->read_req->buf, sizeof(WiiMoteEmu::EepromData_0), 0, 30);
memcpy(WiiMoteEmu::g_Eeprom, g_WiiMotesFromWiiUse[0]->read_req->buf, sizeof(WiiMoteEmu::EepromData_0));
WiiMoteEmu::UpdateEeprom();
Console::Print("EEPROM: %s\n", Temp.c_str());
Console::Print("Got neutral values: %i %i %i\n",
WiiMoteEmu::g_Eeprom[22],WiiMoteEmu::g_Eeprom[23], WiiMoteEmu::g_Eeprom[27]);
WiiMoteEmu::UpdateEeprom();
g_RunTemporary = false;
}
break;

View File

@ -517,7 +517,8 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
//(pStatus->leds >> 3),
pStatus->battery_low
);
// Update the global extension settings
/* Update the global (for both the real and emulated) extension settings from whatever
the real Wiimote use. We will enable the extension from the 0x21 report. */
if(!Emu && !pStatus->extension)
{
DisableExtensions();
@ -533,7 +534,9 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
// data[4]: Size and error
// data[5, 6]: The registry offset
// ---------------------------------------------------------------------
// Show the extension ID
// --------------------------
if ((data[4] == 0x10 || data[4] == 0x20 || data[4] == 0x50) && data[5] == 0x00 && (data[6] == 0xfa || data[6] == 0xfe))
{
if(data[4] == 0x10)
@ -550,7 +553,8 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
wiimote_decrypt(&WiiMoteEmu::g_ExtKey, &data[0x07], 0x02, (data[4] >> 0x04) + 1);
}
// Update the global extension settings
/* Update the global extension settings. Enable the emulated extension from reading
what the real Wiimote has connected. To keep the emulated and real Wiimote in sync. */
if(data[4] == 0x10)
{
if (!Emu) DisableExtensions();
@ -578,8 +582,31 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
Console::Print("Game got the decrypted extension ID: %02x%02x%02x%02x%02x%02x\n\n", data[7], data[8], data[9], data[10], data[11], data[12]);
}
}
// ---------------------------------------------
// Show the nunchuck neutral values
// ---------------------------------------------------------------------
// Show the Wiimote neutral values
// --------------------------
/* The only difference between the Nunchuck and Wiimote that we go after is calibration here is
the offset in memory. If needed we can check the preceding 0x17 request to. */
if(data[4] == 0xf0 && data[5] == 0x00 && data[6] == 0x10)
{
if(data[6] == 0x10)
{
Console::Print("\nGame got the Wiimote calibration:\n");
Console::Print("Cal_zero.x: %i\n", data[7 + 6]);
Console::Print("Cal_zero.y: %i\n", data[7 + 7]);
Console::Print("Cal_zero.z: %i\n", data[7 + 8]);
Console::Print("Cal_g.x: %i\n", data[7 + 10]);
Console::Print("Cal_g.y: %i\n", data[7 + 11]);
Console::Print("Cal_g.z: %i\n", data[7 +12]);
}
}
// ---------------------------------------------
// ---------------------------------------------------------------------
// Show the Nunchuck neutral values
// --------------------------
if(data[4] == 0xf0 && data[5] == 0x00 && (data[6] == 0x20 || data[6] == 0x30))
{
// Save the encrypted data
@ -630,6 +657,7 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
// Show the encrypted data
Console::Print("%s", TmpData.c_str());
}
// ---------------------------------------------
break;
case WM_WRITE_DATA_REPLY: // 0x22
@ -731,21 +759,26 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
float Gy = WiiMoteEmu::AccelerometerToG((float)data[5], (float)g_accel.cal_zero.y, (float)g_accel.cal_g.y);
float Gz = WiiMoteEmu::AccelerometerToG((float)data[6], (float)g_accel.cal_zero.z, (float)g_accel.cal_g.z);
std::string GForce = StringFromFormat("%s %s %s",
(Gx >= 0) ? StringFromFormat(" %i", (int)Gx).c_str() : StringFromFormat("%i", (int)Gx).c_str(),
(Gy >= 0) ? StringFromFormat(" %i", (int)Gy).c_str() : StringFromFormat("%i", (int)Gy).c_str(),
(Gz >= 0) ? StringFromFormat(" %i", (int)Gz).c_str() : StringFromFormat("%i", (int)Gz).c_str());
((int)Gx >= 0) ? StringFromFormat(" %i", (int)Gx).c_str() : StringFromFormat("%i", (int)Gx).c_str(),
((int)Gy >= 0) ? StringFromFormat(" %i", (int)Gy).c_str() : StringFromFormat("%i", (int)Gy).c_str(),
((int)Gz >= 0) ? StringFromFormat(" %i", (int)Gz).c_str() : StringFromFormat("%i", (int)Gz).c_str());
// Show the IR data
WiiMoteEmu::IRData2Dots(&data[7]);
// Calculate the IR data
if (data[1] == WM_REPORT_CORE_ACCEL_IR10_EXT6) WiiMoteEmu::IRData2DotsBasic(&data[7]); else WiiMoteEmu::IRData2Dots(&data[7]);
std::string IRData;
// Create a shortcut
struct WiiMoteEmu::SDot* Dot = WiiMoteEmu::g_Wm.IR.Dot;
for (int i = 0; i < 4; ++i)
{
if(WiiMoteEmu::g_Wm.IR.Dot[i].Visible)
IRData += StringFromFormat("[%i] X:%04i Y:%04i ", i, WiiMoteEmu::g_Wm.IR.Dot[i].Rx, WiiMoteEmu::g_Wm.IR.Dot[i].Ry);
if(Dot[i].Visible)
IRData += StringFromFormat("[%i] X:%04i Y:%04i Size:%i ", Dot[i].Order, Dot[i].Rx, Dot[i].Ry, Dot[i].Size);
else
IRData += StringFromFormat("[%i]", i);
IRData += StringFromFormat("[%i]", Dot[i].Order);
}
// Dot distance
IRData += StringFromFormat(" | Distance:%i", WiiMoteEmu::g_Wm.IR.Distance);
//Console::Print("Read[%s]: 0x%02x | %s | %s | %s\n", (Emu ? "Emu" : "Real"), data[1], RollPitch.c_str(), GForce.c_str(), IRData.c_str()); // Formatted data only
//Console::Print("Read[%s]: %s | %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), IRData.c_str()); // IR data
Console::Print("Read[%s]: %s| %s | %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), RollPitch.c_str(), GForce.c_str()); // Accelerometer
//Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp

View File

@ -51,9 +51,9 @@ void OpenConsole(bool Open = false);
#define WM_RECORDING_IR 2
struct SRecording
{
u8 x;
u8 y;
u8 z;
int x;
int y;
int z;
double Time;
u8 IR[12];
};

View File

@ -379,10 +379,11 @@ int Initialize()
// If we are not using the emulated wiimote we can run the thread temporary until the data has beeen copied
if(g_Config.bUseRealWiimote) g_RunTemporary = true;
/* Allocate memory and copy the Wiimote eeprom accelerometer neutral values to g_Eeprom. We can't
change the neutral values the wiimote will report, I think, unless we update its eeprom? In any
case it's probably better to let the current calibration be where it is and adjust the global
values after that. I don't feel comfortable with overwriting critical data on a lot of Wiimotes. */
/* Allocate memory and copy the Wiimote eeprom accelerometer neutral values to g_Eeprom. Unlike with
and extension we have to do this here, because this data is only read once when the Wiimote
is connected. Also, we can't change the neutral values the wiimote will report, I think, unless
we update its eeprom? In any case it's probably better to let the current calibration be where it
is and adjust the global values after that to avoid overwriting critical data on any Wiimote. */
byte *data = (byte*)malloc(sizeof(byte) * sizeof(WiiMoteEmu::EepromData_0));
wiiuse_read_data(g_WiiMotesFromWiiUse[0], data, 0, sizeof(WiiMoteEmu::EepromData_0));