Wiimote: The first working IR recording, use Alt + the numerical HotKey to play back the IR data associated with a recording

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2078 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-03 00:59:26 +00:00
parent ace2ea395d
commit 220eafad0e
13 changed files with 360 additions and 161 deletions

View file

@ -149,14 +149,15 @@ std::string StringFromFormat(const char* format, ...)
// =================================================== // ===================================================
/* For Debugging. Read out an u8 array. */ /* For Debugging. Read out an u8 array. */
// ---------------- // ----------------
std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len) std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len, bool Spaces)
{ {
//const u8* _data = (const u8*)data; //const u8* _data = (const u8*)data;
std::string Temp; std::string Temp;
for (u32 i = 0; i < size; i++) for (u32 i = 0; i < size; i++)
{ {
char Buffer[128]; char Buffer[128];
sprintf(Buffer, "%02x ", data[i + offset]); if (Spaces) sprintf(Buffer, "%02x ", data[i + offset]);
else sprintf(Buffer, "%02x", data[i + offset]);
if((i + 1) % line_len == 0) Temp.append("\n"); // break long lines if((i + 1) % line_len == 0) Temp.append("\n"); // break long lines
Temp.append(Buffer); Temp.append(Buffer);
} }

View file

@ -34,7 +34,7 @@ void StringFromFormatV(std::string* out, const char* format, va_list args);
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args); bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
// Good // Good
std::string ArrayToString(const u8 *data, u32 size, u32 offset = 0, int line_len = 20); std::string ArrayToString(const u8 *data, u32 size, u32 offset = 0, int line_len = 20, bool Spaces = true);
template<size_t Count> template<size_t Count>

View file

@ -192,6 +192,10 @@ void ConfigDialog::LoadFile()
std::string TmpGameName; file.Get(SaveName.c_str(), "GameName", &TmpGameName, ""); std::string TmpGameName; file.Get(SaveName.c_str(), "GameName", &TmpGameName, "");
m_RecordGameText[i]->SetValue(wxString::FromAscii(TmpGameName.c_str())); m_RecordGameText[i]->SetValue(wxString::FromAscii(TmpGameName.c_str()));
// IR Bytes
std::string TmpIRBytes; file.Get(SaveName.c_str(), "IRBytes", &TmpIRBytes, "");
m_RecordIRBytesText[i]->SetValue(wxString::FromAscii(TmpIRBytes.c_str()));
// Recording speed // Recording speed
int TmpRecordSpeed; file.Get(SaveName.c_str(), "RecordingSpeed", &TmpRecordSpeed, -1); int TmpRecordSpeed; file.Get(SaveName.c_str(), "RecordingSpeed", &TmpRecordSpeed, -1);
if(TmpRecordSpeed != -1) if(TmpRecordSpeed != -1)
@ -343,6 +347,7 @@ void ConfigDialog::CreateGUIControls()
wxStaticBoxSizer * sbRealRoll = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("Roll and Pitch")); wxStaticBoxSizer * sbRealRoll = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("Roll and Pitch"));
wxStaticBoxSizer * sbRealGForce = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("G-Force")); wxStaticBoxSizer * sbRealGForce = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("G-Force"));
wxStaticBoxSizer * sbRealAccel = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("Accelerometer")); wxStaticBoxSizer * sbRealAccel = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("Accelerometer"));
wxStaticBoxSizer * sbRealIR = new wxStaticBoxSizer(wxHORIZONTAL, m_PageReal, wxT("IR"));
// Width and height of the gauges // Width and height of the gauges
static const int Gw = 35, Gh = 130; static const int Gw = 35, Gh = 130;
@ -357,6 +362,12 @@ void ConfigDialog::CreateGUIControls()
m_GaugeAccel[1] = new wxGauge( m_PageReal, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH); m_GaugeAccel[1] = new wxGauge( m_PageReal, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
m_GaugeAccel[2] = new wxGauge( m_PageReal, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH); m_GaugeAccel[2] = new wxGauge( m_PageReal, wxID_ANY, 255, wxDefaultPosition, wxSize(Gw, Gh), wxGA_VERTICAL | wxNO_BORDER | wxGA_SMOOTH);
// The text controls
m_TextIR = new wxStaticText(m_PageReal, wxID_ANY, wxT("Cursor: 000 000\nDistance: 0000"));
// -----------------------------
// The sizers for all gauges together with their label
// -----------
wxBoxSizer * sBoxBattery = new wxBoxSizer(wxVERTICAL); wxBoxSizer * sBoxBattery = new wxBoxSizer(wxVERTICAL);
wxBoxSizer * sBoxRoll[2]; wxBoxSizer * sBoxRoll[2];
sBoxRoll[0] = new wxBoxSizer(wxVERTICAL); sBoxRoll[0] = new wxBoxSizer(wxVERTICAL);
@ -377,7 +388,11 @@ void ConfigDialog::CreateGUIControls()
m_TextX[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextX[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("X"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
m_TextY[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextY[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Y"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
m_TextZ[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[0] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE); m_TextZ[1] = new wxStaticText(m_PageReal, wxID_ANY, wxT("Z"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE);
// ----------------
// -----------------------------
// Set up sizers
// -----------
sBoxBattery->Add(m_GaugeBattery, 0, wxEXPAND | (wxALL), 5); sBoxBattery->Add(m_TextBattery, 0, wxEXPAND | (wxALL), 0); sBoxBattery->Add(m_GaugeBattery, 0, wxEXPAND | (wxALL), 5); sBoxBattery->Add(m_TextBattery, 0, wxEXPAND | (wxALL), 0);
sBoxRoll[0]->Add(m_GaugeRoll[0], 0, wxEXPAND | (wxALL), 5); sBoxRoll[0]->Add(m_TextRoll, 0, wxEXPAND | (wxALL), 0); sBoxRoll[0]->Add(m_GaugeRoll[0], 0, wxEXPAND | (wxALL), 5); sBoxRoll[0]->Add(m_TextRoll, 0, wxEXPAND | (wxALL), 0);
@ -395,12 +410,16 @@ void ConfigDialog::CreateGUIControls()
sbRealRoll->Add(sBoxRoll[0], 0, wxEXPAND | (wxALL), 5); sbRealRoll->Add(sBoxRoll[1], 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); 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); 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); sbRealWiimoteStatus->Add(sbRealBattery, 0, wxEXPAND | (wxLEFT), 0);
sbRealWiimoteStatus->Add(sbRealRoll, 0, wxEXPAND | (wxLEFT), 5); sbRealWiimoteStatus->Add(sbRealRoll, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealGForce, 0, wxEXPAND | (wxLEFT), 5); sbRealWiimoteStatus->Add(sbRealGForce, 0, wxEXPAND | (wxLEFT), 5);
sbRealWiimoteStatus->Add(sbRealAccel, 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.")); m_GaugeBattery->SetToolTip(wxT("Press '+' to show the current status. Press '-' to stop recording the status."));
// ========================================== // ==========================================
@ -423,7 +442,8 @@ void ConfigDialog::CreateGUIControls()
wxStaticText * m_TextHotKey = new wxStaticText(m_PageReal, wxID_ANY, wxT("HotKey"), wxDefaultPosition, wxSize(40, 15), wxALIGN_CENTRE); wxStaticText * m_TextHotKey = new wxStaticText(m_PageReal, wxID_ANY, wxT("HotKey"), wxDefaultPosition, wxSize(40, 15), wxALIGN_CENTRE);
wxStaticText * m_TextMovement = new wxStaticText(m_PageReal, wxID_ANY, wxT("Movement name"), wxDefaultPosition, wxSize(200, 15), wxALIGN_CENTRE); wxStaticText * m_TextMovement = new wxStaticText(m_PageReal, wxID_ANY, wxT("Movement name"), wxDefaultPosition, wxSize(200, 15), wxALIGN_CENTRE);
wxStaticText * m_TextGame = new wxStaticText(m_PageReal, wxID_ANY, wxT("Game name"), wxDefaultPosition, wxSize(200, 15), wxALIGN_CENTRE); wxStaticText * m_TextGame = new wxStaticText(m_PageReal, wxID_ANY, wxT("Game name"), wxDefaultPosition, wxSize(200, 15), wxALIGN_CENTRE);
wxStaticText * m_TextRecSped = new wxStaticText(m_PageReal, wxID_ANY, wxT("R. s."), wxDefaultPosition, wxSize(30, 15), wxALIGN_CENTRE); wxStaticText * m_TextIRBytes = new wxStaticText(m_PageReal, wxID_ANY, wxT("IR"), wxDefaultPosition, wxSize(20, 15), wxALIGN_CENTRE);
wxStaticText * m_TextRecSped = new wxStaticText(m_PageReal, wxID_ANY, wxT("R. s."), wxDefaultPosition, wxSize(33, 15), wxALIGN_CENTRE);
wxStaticText * m_TextPlaySpeed = new wxStaticText(m_PageReal, wxID_ANY, wxT("Pl. s."), wxDefaultPosition, wxSize(40, 15), wxALIGN_CENTRE); wxStaticText * m_TextPlaySpeed = new wxStaticText(m_PageReal, wxID_ANY, wxT("Pl. s."), wxDefaultPosition, wxSize(40, 15), wxALIGN_CENTRE);
m_TextRec->SetToolTip(wxT( m_TextRec->SetToolTip(wxT(
"To record a movement first press this button, then start the recording by pressing 'A' on the Wiimote and stop the recording\n" "To record a movement first press this button, then start the recording by pressing 'A' on the Wiimote and stop the recording\n"
@ -444,6 +464,7 @@ void ConfigDialog::CreateGUIControls()
sRealRecord[0]->Add(m_TextHotKey, 0, wxEXPAND | (wxLEFT), 5); sRealRecord[0]->Add(m_TextHotKey, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextMovement, 0, wxEXPAND | (wxLEFT), 5); sRealRecord[0]->Add(m_TextMovement, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextGame, 0, wxEXPAND | (wxLEFT), 5); sRealRecord[0]->Add(m_TextGame, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextIRBytes, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextRecSped, 0, wxEXPAND | (wxLEFT), 5); sRealRecord[0]->Add(m_TextRecSped, 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[0]->Add(m_TextPlaySpeed, 0, wxEXPAND | (wxLEFT), 5); sRealRecord[0]->Add(m_TextPlaySpeed, 0, wxEXPAND | (wxLEFT), 5);
sbRealRecord->Add(sRealRecord[0], 0, wxEXPAND | (wxALL), 0); sbRealRecord->Add(sRealRecord[0], 0, wxEXPAND | (wxALL), 0);
@ -455,17 +476,20 @@ void ConfigDialog::CreateGUIControls()
m_RecordHotKey[i] = new wxChoice(m_PageReal, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKey); m_RecordHotKey[i] = new wxChoice(m_PageReal, IDC_RECORD + i, wxDefaultPosition, wxDefaultSize, StrHotKey);
m_RecordText[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_TEXT, wxT(""), wxDefaultPosition, wxSize(200, 19)); m_RecordText[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_TEXT, wxT(""), wxDefaultPosition, wxSize(200, 19));
m_RecordGameText[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_GAMETEXT, wxT(""), wxDefaultPosition, wxSize(200, 19)); m_RecordGameText[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_GAMETEXT, wxT(""), wxDefaultPosition, wxSize(200, 19));
m_RecordIRBytesText[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_IRBYTESTEXT, wxT(""), wxDefaultPosition, wxSize(25, 19));
m_RecordSpeed[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_SPEED, wxT(""), wxDefaultPosition, wxSize(30, 19), wxTE_READONLY | wxTE_CENTRE); m_RecordSpeed[i] = new wxTextCtrl(m_PageReal, IDT_RECORD_SPEED, wxT(""), wxDefaultPosition, wxSize(30, 19), wxTE_READONLY | wxTE_CENTRE);
m_RecordPlayBackSpeed[i] = new wxChoice(m_PageReal, IDT_RECORD_PLAYSPEED, wxDefaultPosition, wxDefaultSize, StrPlayBackSpeed); m_RecordPlayBackSpeed[i] = new wxChoice(m_PageReal, IDT_RECORD_PLAYSPEED, wxDefaultPosition, wxDefaultSize, StrPlayBackSpeed);
m_RecordText[i]->SetMaxLength(35); m_RecordText[i]->SetMaxLength(35);
m_RecordGameText[i]->SetMaxLength(35); m_RecordGameText[i]->SetMaxLength(35);
m_RecordIRBytesText[i]->Enable(false);
m_RecordSpeed[i]->Enable(false); m_RecordSpeed[i]->Enable(false);
sRealRecord[i]->Add(m_RecordButton[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordButton[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordHotKey[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordHotKey[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordText[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordGameText[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordGameText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordIRBytesText[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordSpeed[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordSpeed[i], 0, wxEXPAND | (wxLEFT), 5);
sRealRecord[i]->Add(m_RecordPlayBackSpeed[i], 0, wxEXPAND | (wxLEFT), 5); sRealRecord[i]->Add(m_RecordPlayBackSpeed[i], 0, wxEXPAND | (wxLEFT), 5);
@ -519,7 +543,7 @@ void ConfigDialog::ConvertToString()
// Load ini file // Load ini file
IniFile file; IniFile file;
file.Load("WiimoteMovement.ini"); file.Load("WiimoteMovement.ini");
std::string TmpStr = "", TmpTime = ""; std::string TmpStr = "", TmpIR = "", TmpTime = "";
for (int i = 0; i < m_vRecording.size(); i++) for (int i = 0; i < m_vRecording.size(); i++)
{ {
@ -529,19 +553,23 @@ void ConfigDialog::ConvertToString()
TmpStr += StringFromFormat("%02x", m_vRecording.at(i).z); TmpStr += StringFromFormat("%02x", m_vRecording.at(i).z);
if(i < (m_vRecording.size() - 1)) TmpStr += ","; if(i < (m_vRecording.size() - 1)) TmpStr += ",";
/* Break just short of the IniFile.cpp byte limit so that we don't crash file.Load() the next time. // Write the IR data
This limit should never be hit because of the recording limit below. I keep it here just in case. */ TmpIR += ArrayToString(m_vRecording.at(i).IR, IRBytes, 0, 30, false);
if(TmpStr.length() > (1024*10 - 10)) if(i < (m_vRecording.size() - 1)) TmpIR += ",";
{
break;
PanicAlert("Your recording was to long, the entire recording was not saved.");
}
// Write the timestamps. The upper limit is 99 seconds. // Write the timestamps. The upper limit is 99 seconds.
int Time = (int)((m_vRecording.at(i).Time - m_vRecording.at(0).Time) * 1000); int Time = (int)((m_vRecording.at(i).Time - m_vRecording.at(0).Time) * 1000);
TmpTime += StringFromFormat("%05i", Time); TmpTime += StringFromFormat("%05i", Time);
if(i < (m_vRecording.size() - 1)) TmpTime += ","; if(i < (m_vRecording.size() - 1)) TmpTime += ",";
//Console::Print("Time: %f %i\n", m_vRecording.at(i).Time, Time); //Console::Print("Time: %f %i\n", m_vRecording.at(i).Time, Time);
/* Break just short of the IniFile.cpp byte limit so that we don't crash file.Load() the next time.
This limit should never be hit because of the recording limit below. I keep it here just in case. */
if(TmpStr.length() > (1024*10 - 10) || TmpIR.length() > (1024*10 - 10) || TmpTime.length() > (1024*10 - 10))
{
break;
PanicAlert("Your recording was to long, the entire recording was not saved.");
}
} }
// Recordings per second // Recordings per second
@ -553,12 +581,15 @@ void ConfigDialog::ConvertToString()
if (Time == 0 || m_vRecording.size() == 0) Rate = 0; if (Time == 0 || m_vRecording.size() == 0) Rate = 0;
// Update GUI // Update GUI
m_RecordIRBytesText[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), IRBytes));
m_RecordSpeed[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), Rate)); m_RecordSpeed[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), Rate));
// Save file // Save file
std::string SaveName = StringFromFormat("Recording%i", m_iRecordTo); std::string SaveName = StringFromFormat("Recording%i", m_iRecordTo);
file.Set(SaveName.c_str(), "Movement", TmpStr.c_str()); file.Set(SaveName.c_str(), "Movement", TmpStr.c_str());
file.Set(SaveName.c_str(), "IR", TmpIR.c_str());
file.Set(SaveName.c_str(), "Time", TmpTime.c_str()); file.Set(SaveName.c_str(), "Time", TmpTime.c_str());
file.Set(SaveName.c_str(), "IRBytes", IRBytes);
file.Set(SaveName.c_str(), "RecordingSpeed", Rate); file.Set(SaveName.c_str(), "RecordingSpeed", Rate);
// Set a default playback speed if none is set already // Set a default playback speed if none is set already
@ -651,8 +682,11 @@ void ConfigDialog::DoRecordA(bool Pressed)
UpdateGUI(); UpdateGUI();
} }
void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z) void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int _IRBytes)
{ {
//std::string Tmp1 = ArrayToString(_IR, 20, 0, 30);
//Console::Print("DoRecordMovement: %s\n", Tmp1.c_str());
if (!m_bRecording) return; if (!m_bRecording) return;
//Console::Print("DoRecordMovement\n"); //Console::Print("DoRecordMovement\n");
@ -662,8 +696,12 @@ void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z)
Tmp.y = _y; Tmp.y = _y;
Tmp.z = _z; Tmp.z = _z;
Tmp.Time = GetDoubleTime(); Tmp.Time = GetDoubleTime();
memcpy(Tmp.IR, _IR, _IRBytes);
m_vRecording.push_back(Tmp); m_vRecording.push_back(Tmp);
// Save the number of IR bytes
IRBytes = _IRBytes;
/* The upper limit of a recording coincides with the IniFile.cpp limit, each list element /* The upper limit of a recording coincides with the IniFile.cpp limit, each list element
is 7 bytes, therefore be divide by 7 */ is 7 bytes, therefore be divide by 7 */
if (m_vRecording.size() > (10*1024 / 7 - 2) ) if (m_vRecording.size() > (10*1024 / 7 - 2) )
@ -834,8 +872,8 @@ void ConfigDialog::UpdateGUI()
unplugged and reinserted extensions. */ unplugged and reinserted extensions. */
m_NunchuckConnected->SetValue(g_Config.bNunchuckConnected); m_NunchuckConnected->SetValue(g_Config.bNunchuckConnected);
m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected); m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected);
m_NunchuckConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote)); m_NunchuckConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning));
m_ClassicControllerConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote)); m_ClassicControllerConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote && g_EmulatorRunning));
/* I have disabled this option during a running game because it's enough to be able to switch /* I have disabled this option during a running game because it's enough to be able to switch
between using and not using then. To also use the connect option during a running game would between using and not using then. To also use the connect option during a running game would
@ -845,9 +883,6 @@ void ConfigDialog::UpdateGUI()
m_ConnectRealWiimote->Enable(!g_EmulatorRunning); m_ConnectRealWiimote->Enable(!g_EmulatorRunning);
m_UseRealWiimote->Enable(g_RealWiiMotePresent && g_Config.bConnectRealWiimote); m_UseRealWiimote->Enable(g_RealWiiMotePresent && g_Config.bConnectRealWiimote);
// Linux has no FindItem() // Linux has no FindItem()
#ifdef _WIN32 #ifdef _WIN32
for(int i = IDB_RECORD + 1; i < (IDB_RECORD + RECORDING_ROWS + 1); i++) for(int i = IDB_RECORD + 1; i < (IDB_RECORD + RECORDING_ROWS + 1); i++)

View file

@ -48,15 +48,16 @@ class ConfigDialog : public wxDialog
void OnKeyDown(wxKeyEvent& event); void OnKeyDown(wxKeyEvent& event);
void LoadFile(); void SaveFile(); void LoadFile(); void SaveFile();
// Status // General status
wxStaticText * m_TextUpdateRate; wxStaticText * m_TextUpdateRate;
// Wiimote status // Wiimote status
wxGauge *m_GaugeBattery, *m_GaugeRoll[2], *m_GaugeGForce[3], *m_GaugeAccel[3]; wxGauge *m_GaugeBattery, *m_GaugeRoll[2], *m_GaugeGForce[3], *m_GaugeAccel[3];
wxStaticText * m_TextIR;
bool m_bWaitForRecording, m_bRecording, m_bAllowA; bool m_bWaitForRecording, m_bRecording, m_bAllowA;
int m_iRecordTo; int m_iRecordTo;
void RecordMovement(wxCommandEvent& event); void RecordMovement(wxCommandEvent& event);
void DoRecordMovement(u8 _x, u8 _y, u8 _z); void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes);
void DoRecordA(bool Pressed); void DoRecordA(bool Pressed);
void ConvertToString(); void ConvertToString();
wxTimer *m_TimeoutTimer, *m_TimeoutATimer; wxTimer *m_TimeoutTimer, *m_TimeoutATimer;
@ -83,6 +84,7 @@ class ConfigDialog : public wxDialog
wxChoice * m_RecordHotKey[RECORDING_ROWS + 1]; wxChoice * m_RecordHotKey[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordText[RECORDING_ROWS + 1]; wxTextCtrl * m_RecordText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordGameText[RECORDING_ROWS + 1]; wxTextCtrl * m_RecordGameText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordIRBytesText[RECORDING_ROWS + 1];
wxTextCtrl * m_RecordSpeed[RECORDING_ROWS + 1]; wxTextCtrl * m_RecordSpeed[RECORDING_ROWS + 1];
wxChoice * m_RecordPlayBackSpeed[RECORDING_ROWS + 1]; wxChoice * m_RecordPlayBackSpeed[RECORDING_ROWS + 1];
@ -96,6 +98,7 @@ class ConfigDialog : public wxDialog
}; };
*/ */
std::vector<SRecording> m_vRecording; std::vector<SRecording> m_vRecording;
int IRBytes;
enum enum
{ {
@ -116,7 +119,7 @@ class ConfigDialog : public wxDialog
ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS, ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS,
IDB_RECORD = 2000, IDB_RECORD = 2000,
IDC_RECORD = 3000, IDC_RECORD = 3000,
IDT_RECORD_TEXT, IDT_RECORD_GAMETEXT, IDT_RECORD_SPEED, IDT_RECORD_PLAYSPEED IDT_RECORD_TEXT, IDT_RECORD_GAMETEXT, IDT_RECORD_IRBYTESTEXT, IDT_RECORD_SPEED, IDT_RECORD_PLAYSPEED
}; };
void OnClose(wxCloseEvent& event); void OnClose(wxCloseEvent& event);

View file

@ -185,8 +185,10 @@ void SendReportCoreAccelIr12(u16 _channelID) {
FillReportInfo(pReport->c); FillReportInfo(pReport->c);
FillReportAcc(pReport->a); FillReportAcc(pReport->a);
// We settle with emulating two objects, not all four. We leave object 2 and 3 with zero. // We settle with emulating two objects, not all four. We leave object 2 and 3 with 0xff.
FillReportIR(pReport->ir[0], pReport->ir[1]); FillReportIR(pReport->ir[0], pReport->ir[1]);
memset(&pReport->ir[2], 0xff, sizeof(wm_ir_extended));
memset(&pReport->ir[3], 0xff, sizeof(wm_ir_extended));
LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()"); LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()");
LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset);

View file

@ -56,11 +56,11 @@ namespace WiiMoteEmu
#define wSENSOR_BAR_RADIUS 200 #define wSENSOR_BAR_RADIUS 200
// Movement recording // Movement recording
extern int g_RecordingPlaying[2]; extern int g_RecordingPlaying[3];
extern int g_RecordingCounter[2]; extern int g_RecordingCounter[3];
extern int g_RecordingPoint[2]; extern int g_RecordingPoint[3];
extern double g_RecordingStart[2]; extern double g_RecordingStart[3];
extern double g_RecordingCurrentTime[2]; extern double g_RecordingCurrentTime[3];
// Registry sizes // Registry sizes
#define WIIMOTE_EEPROM_SIZE (16*1024) #define WIIMOTE_EEPROM_SIZE (16*1024)

View file

@ -126,17 +126,27 @@ void LoadRecordedMovements()
for(int i = 0; i < RECORDING_ROWS; i++) for(int i = 0; i < RECORDING_ROWS; i++)
{ {
// Logging
Console::Print("Recording%i ", i + 1);
// Get row name // Get row name
std::string SaveName = StringFromFormat("Recording%i", i + 1); std::string SaveName = StringFromFormat("Recording%i", i + 1);
// Get movement // Get movement
std::string TmpMovement; file.Get(SaveName.c_str(), "Movement", &TmpMovement, ""); std::string TmpMovement; file.Get(SaveName.c_str(), "Movement", &TmpMovement, "");
// Get IR
std::string TmpIR; file.Get(SaveName.c_str(), "IR", &TmpIR, "");
// Get time // Get time
std::string TmpTime; file.Get(SaveName.c_str(), "Time", &TmpTime, ""); std::string TmpTime; file.Get(SaveName.c_str(), "Time", &TmpTime, "");
// Get IR bytes
int TmpIRBytes; file.Get(SaveName.c_str(), "IRBytes", &TmpIRBytes, 0);
VRecording.at(i).IRBytes = TmpIRBytes;
SRecording Tmp; SRecording Tmp;
for (int j = 0, k = 0; j < TmpMovement.length(); j+=7) for (int j = 0, k = 0, l = 0; j < TmpMovement.length(); j+=7)
{ {
// Skip blank savings // Skip blank savings
if (TmpMovement.length() < 3) continue; if (TmpMovement.length() < 3) continue;
@ -152,26 +162,62 @@ void LoadRecordedMovements()
Tmp.y = (u8)TmpY; Tmp.y = (u8)TmpY;
Tmp.z = (u8)TmpZ; Tmp.z = (u8)TmpZ;
// Go to next set of time values // ---------------------------------
double Time = (double)atoi(TmpTime.substr(k, 5).c_str()); // Go to next set of IR values
Tmp.Time = (double)(Time/1000); // ---------
VRecording.at(i).Recording.push_back(Tmp); // If there is no IR data saving we fill the array with zeroes. This should only be able to occur from manual ini editing
k += 6; // but we check for it anyway
if (TmpIRBytes == 0) for(int i = 0; i < 12; i++) Tmp.IR[i] = 0;
for(int ii = 0; ii < TmpIRBytes; ii++)
{
if(TmpIR.length() < (k + i + TmpIRBytes)) continue; // Safety check
std::string TmpStr = TmpIR.substr(k + ii*2, 2);
u32 TmpU32;
AsciiToHex(TmpStr.c_str(), TmpU32);
Tmp.IR[ii] = (u8)TmpU32;
}
if (TmpIRBytes == 10) k += (10*2 + 1); else k += (12*2 + 1);
// ---------------------
// Go to next set of time values
double Time = (double)atoi(TmpTime.substr(l, 5).c_str());
Tmp.Time = (double)(Time/1000);
l += 6;
// Save the values
VRecording.at(i).Recording.push_back(Tmp);
// ---------------------------------
// Log results
// ---------
//Console::Print("Time:%f\n", Tmp.Time); //Console::Print("Time:%f\n", Tmp.Time);
//std::string TmpIRLog = ArrayToString(Tmp.IR, TmpIRBytes, 0, 30);
//Console::Print("IR: %s\n", TmpIRLog.c_str());
//Console::Print("\n");
} }
// HotKey // Get HotKey
int TmpRecordHotKey; file.Get(SaveName.c_str(), "HotKey", &TmpRecordHotKey, -1); int TmpRecordHotKey; file.Get(SaveName.c_str(), "HotKey", &TmpRecordHotKey, -1);
VRecording.at(i).HotKey = TmpRecordHotKey; VRecording.at(i).HotKey = TmpRecordHotKey;
// Recording speed // Get Recording speed
int TmpPlaybackSpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaybackSpeed, -1); int TmpPlaybackSpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaybackSpeed, -1);
VRecording.at(i).PlaybackSpeed = TmpPlaybackSpeed; VRecording.at(i).PlaybackSpeed = TmpPlaybackSpeed;
Console::Print("Size:%i HotKey:%i Speed:%i\n", // ---------------------------------
VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed // Logging
// ---------
std::string TmpIRLog;
if(TmpIRBytes > 0)
TmpIRLog = ArrayToString(VRecording.at(i).Recording.at(0).IR, TmpIRBytes, 0, 30);
else
TmpIRLog = "";
Console::Print("Size:%i HotKey:%i Speed:%i IR: %s\n",
VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed,
TmpIRLog.c_str()
); );
// ---------------------
} }
} }
// ================ // ================
@ -331,22 +377,10 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
for now I'm delaying all inputs. Both for status changes and Eeprom for now I'm delaying all inputs. Both for status changes and Eeprom
and registry reads and writes. */ and registry reads and writes. */
// Limit the delay to certain registry reads and writes // There are no 0x22 replys to these report from the real wiimote from what I could see
//if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA) // Report 0x10 that seems to be only used for rumble
// && data[3] == 0xa4) if(!(data[1] == WM_READ_DATA && data[2] == 0x00) && !(data[1] == WM_REQUEST_STATUS))
//{
// There are no 0x22 replys to these report from the real wiimote
if(!(data[1] == WM_READ_DATA && data[2] == 0x00)
&& !(data[1] == WM_REQUEST_STATUS)
)
if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) CreateAckDelay((u8)_channelID, (u16)sr->channel); if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) CreateAckDelay((u8)_channelID, (u16)sr->channel);
//}
//else
//{
//wm_write_data *wd = (wm_write_data*)sr->data;
//u32 address = convert24bit(wd->address);
//WmSendAck(_channelID, sr->channel, address);
//}
} }
break; break;

View file

@ -43,28 +43,29 @@ namespace WiiMoteEmu
{ {
//****************************************************************************** //**************************************************************************************
// Recorded movements // Recorded movements
//****************************************************************************** //**************************************************************************************
// ------------------------------------------ // ------------------------------------------
// Variables: 0 = Wiimote, 1 = Nunchuck // Variables: 0 = Wiimote, 1 = Nunchuck
// ---------------- // ----------------
int g_RecordingPlaying[2]; //g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1; int g_RecordingPlaying[3]; //g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1;
int g_RecordingCounter[2]; //g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0; int g_RecordingCounter[3]; //g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0;
int g_RecordingPoint[2]; //g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0; int g_RecordingPoint[3]; //g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0;
double g_RecordingStart[2]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0; double g_RecordingStart[3]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0;
double g_RecordingCurrentTime[2]; //g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0; double g_RecordingCurrentTime[3]; //g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0;
// -------------------------- // --------------------------
void RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm) template<class IRReportType>
bool RecordingPlayAccIR(u8 &_x, u8 &_y, u8 &_z, IRReportType &_IR, int Wm)
{ {
// Return if the list is empty // Return if the list is empty
if(VRecording.at(g_RecordingPlaying[Wm]).Recording.size() == 0) if(VRecording.at(g_RecordingPlaying[Wm]).Recording.size() == 0)
{ {
g_RecordingPlaying[Wm] = -1; g_RecordingPlaying[Wm] = -1;
Console::Print("Empty\n\n"); Console::Print("Empty\n\n");
return; return false;
} }
// Return if the playback speed is unset // Return if the playback speed is unset
@ -72,7 +73,22 @@ void RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm)
{ {
Console::Print("PlaybackSpeed empty: %i\n\n", g_RecordingPlaying[Wm]); Console::Print("PlaybackSpeed empty: %i\n\n", g_RecordingPlaying[Wm]);
g_RecordingPlaying[Wm] = -1; g_RecordingPlaying[Wm] = -1;
return; return false;
}
// Get IR bytes
int IRBytes = VRecording.at(g_RecordingPlaying[Wm]).IRBytes;
// Return if the IR mode is wrong
if (Wm == WM_RECORDING_IR
&& ( (IRBytes == 12 && !(g_ReportingMode == 0x33))
|| (IRBytes == 10 && !(g_ReportingMode == 0x36 || g_ReportingMode == 0x37))
)
)
{
Console::Print("Wrong IR mode: %i\n\n", g_RecordingPlaying[Wm]);
g_RecordingPlaying[Wm] = -1;
return false;
} }
// Get starting time // Get starting time
@ -106,13 +122,14 @@ void RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm)
g_RecordingStart[Wm] = 0; g_RecordingStart[Wm] = 0;
g_RecordingCurrentTime[Wm] = 0; g_RecordingCurrentTime[Wm] = 0;
Console::Print("End\n\n"); Console::Print("End\n\n");
return; return false;
} }
// Update values // Update values
_x = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x; _x = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x;
_y = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y; _y = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y;
_z = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).z; _z = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).z;
if(Wm == WM_RECORDING_IR) memcpy(&_IR, VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).IR, IRBytes);
/**/ /**/
if (g_DebugAccelerometer) if (g_DebugAccelerometer)
@ -125,24 +142,52 @@ void RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm)
Console::Print("Accel x, y, z: %03u %03u %03u\n\n", _x, _y, _z); Console::Print("Accel x, y, z: %03u %03u %03u\n\n", _x, _y, _z);
} }
g_RecordingCounter[Wm]++; g_RecordingCounter[Wm]++;
return true;
}
/* Because the playback is neatly controlled by RecordingPlayAccIR() we use these functions to be able to
use RecordingPlayAccIR() for both accelerometer and IR recordings */
bool RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm)
{
wm_ir_basic IR;
return RecordingPlayAccIR(_x, _y, _z, IR, Wm);
}
template<class IRReportType>
bool RecordingPlayIR(IRReportType &_IR)
{
u8 x, y, z;
return RecordingPlayAccIR(x, y, z, _IR, 2);
} }
// Check if we should play a recording // Check if we should start the playback of a recording. Once it has been started it can not currently
int RecordingCheckKeys(bool Wiimote) // be stopped, it will always run to the end of the recording.
int RecordingCheckKeys(int Wiimote)
{ {
#ifdef _WIN32 #ifdef _WIN32
//Console::Print("RecordingCheckKeys\n"); //Console::Print("RecordingCheckKeys: %i\n", Wiimote);
// Return if we don't have both a Shift and Ctrl // ------------------------------------
// Don't allow multiple action keys
// --------------
// Return if we have both a Shift, Ctrl, and Alt
if ( GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_MENU) ) return -1;
// Return if we have both a Shift and Ctrl
if ( (GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_CONTROL)) ) return -1; if ( (GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_CONTROL)) ) return -1;
// Return if we have both a Ctrl and Alt
if ( (GetAsyncKeyState(VK_CONTROL) && GetAsyncKeyState(VK_MENU)) ) return -1;
// Return if we have both a Shift and Alt
if ( (GetAsyncKeyState(VK_SHIFT) && GetAsyncKeyState(VK_MENU)) ) return -1;
// ---------------------
// Return if we don't have both a Wiimote and Shift // Return if we don't have both a Wiimote and Shift
if ( Wiimote && !GetAsyncKeyState(VK_SHIFT) ) return -1; if ( Wiimote == 0 && !GetAsyncKeyState(VK_SHIFT) ) return -1;
// Return if we don't have both a Nunchuck and Ctrl // Return if we don't have both a Nunchuck and Ctrl
if ( !Wiimote && !GetAsyncKeyState(VK_CONTROL) ) return -1; if ( Wiimote == 1 && !GetAsyncKeyState(VK_CONTROL) ) return -1;
// Return if we don't have both a IR call and Alt
if ( Wiimote == 2 && !GetAsyncKeyState(VK_MENU) ) return -1;
// Check if we have exactly one numerical key // Check if we have exactly one numerical key
int Keys = 0; int Keys = 0;
@ -279,13 +324,13 @@ void FillReportAcc(wm_accel& _acc)
// Check for a playback command // Check for a playback command
if(g_RecordingPlaying[0] < 0) if(g_RecordingPlaying[0] < 0)
{ {
g_RecordingPlaying[0] = RecordingCheckKeys(true); g_RecordingPlaying[0] = RecordingCheckKeys(0);
} }
else else
{ {
RecordingPlay(_acc.x, _acc.y, _acc.z, 0); // If the recording reached the end or failed somehow we will not return
if (RecordingPlay(_acc.x, _acc.y, _acc.z, 0)) return;
//Console::Print("X, Y, Z: %u %u %u\n", _acc.x, _acc.y, _acc.z); //Console::Print("X, Y, Z: %u %u %u\n", _acc.x, _acc.y, _acc.z);
if (_acc.x != 0 && _acc.y != 0 && _acc.z != 0) return;
} }
// --------------------- // ---------------------
@ -481,10 +526,27 @@ void FillReportAcc(wm_accel& _acc)
// --------------- // ---------------
void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1) void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
{ {
// ------------------------------------
// Recorded movements
// --------------
// Check for a playback command
if(g_RecordingPlaying[2] < 0)
{
g_RecordingPlaying[2] = RecordingCheckKeys(2);
}
else
{
//Console::Print("X, Y, Z: %u %u %u\n", _acc.x, _acc.y, _acc.z);
if (RecordingPlayIR(_ir0)) return;
}
// ---------------------
/* DESCRIPTION: The calibration is controlled by these values, their absolute value and
// --------------------------------------
/* The calibration is controlled by these values, their absolute value and
the relative distance between between them control the calibration. WideScreen mode the relative distance between between them control the calibration. WideScreen mode
has its own settings. */ has its own settings. */
// ----------
int Top, Left, Right, Bottom, SensorBarRadius; int Top, Left, Right, Bottom, SensorBarRadius;
if(g_Config.bWideScreen) if(g_Config.bWideScreen)
{ {
@ -496,9 +558,10 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
Top = TOP; Left = LEFT; Right = RIGHT; Top = TOP; Left = LEFT; Right = RIGHT;
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
} }
// ------------------
/* Fill with 0xff if empty. The real Wiimote seems to use 0xff when it sees to ojbects, at least from /* Fill with 0xff if empty. The real Wiimote seems to use 0xff when it doesn't see a certain point,
how WiiMoteReal::SendEvent() works. */ at least from how WiiMoteReal::SendEvent() works. */
memset(&_ir0, 0xff, sizeof(wm_ir_extended)); memset(&_ir0, 0xff, sizeof(wm_ir_extended));
memset(&_ir1, 0xff, sizeof(wm_ir_extended)); memset(&_ir1, 0xff, sizeof(wm_ir_extended));
@ -508,6 +571,9 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
// If we are outside the screen leave the values at 0xff // If we are outside the screen leave the values at 0xff
if(MouseX > 1 || MouseX < 0 || MouseY > 1 || MouseY < 0) return; if(MouseX > 1 || MouseX < 0 || MouseY > 1 || MouseY < 0) return;
// --------------------------------------
// Actual position calculation
// ----------
int y0 = Top + (MouseY * (Bottom - Top)); int y0 = Top + (MouseY * (Bottom - Top));
int y1 = Top + (MouseY * (Bottom - Top)); int y1 = Top + (MouseY * (Bottom - Top));
@ -527,7 +593,7 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
_ir1.size = 10; _ir1.size = 10;
_ir1.xHi = x1 >> 8; _ir1.xHi = x1 >> 8;
_ir1.yHi = y1 >> 8; _ir1.yHi = y1 >> 8;
// ------------------
// ---------------------------- // ----------------------------
// Debugging for calibration // Debugging for calibration
@ -565,14 +631,33 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1)
_ir0.y, _ir0.yHi, _ir1.y, _ir1.yHi, _ir0.y, _ir0.yHi, _ir1.y, _ir1.yHi,
_ir0.size, _ir1.size _ir0.size, _ir1.size
);*/ );*/
// ------------------
} }
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// The extended 10 byte reporting // The 10 byte reporting used when an extension is connected
// --------------- // ---------------
void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
{ {
/* See description above */ // ------------------------------------
// Recorded movements
// --------------
// Check for a playback command
if(g_RecordingPlaying[2] < 0)
{
g_RecordingPlaying[2] = RecordingCheckKeys(2);
}
// We are playing back a recording, we don't accept any manual input this time
else
{
//Console::Print("X, Y, Z: %u %u %u\n", _acc.x, _acc.y, _acc.z);
if (RecordingPlayIR(_ir0)) return;
}
// ---------------------
// --------------------------------------
/* See calibration description above */
// ----------
int Top, Left, Right, Bottom, SensorBarRadius; int Top, Left, Right, Bottom, SensorBarRadius;
if(g_Config.bWideScreen) if(g_Config.bWideScreen)
@ -585,6 +670,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
Top = TOP; Left = LEFT; Right = RIGHT; Top = TOP; Left = LEFT; Right = RIGHT;
Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS; Bottom = BOTTOM; SensorBarRadius = SENSOR_BAR_RADIUS;
} }
// ------------------
// Fill with 0xff if empty // Fill with 0xff if empty
memset(&_ir0, 0xff, sizeof(wm_ir_basic)); memset(&_ir0, 0xff, sizeof(wm_ir_basic));
@ -602,8 +688,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
int x1 = Left + (MouseX * (Right - Left)) - SensorBarRadius; int x1 = Left + (MouseX * (Right - Left)) - SensorBarRadius;
int x2 = Left + (MouseX * (Right - Left)) + SensorBarRadius; int x2 = Left + (MouseX * (Right - Left)) + SensorBarRadius;
/* As with the extented report we settle with emulating two out of four /* As with the extented report we settle with emulating two out of four possible objects */
possible objects */
x1 = 1023 - x1; x1 = 1023 - x1;
_ir0.x1 = x1 & 0xff; _ir0.x1 = x1 & 0xff;
_ir0.y1 = y1 & 0xff; _ir0.y1 = y1 & 0xff;
@ -620,10 +705,10 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
//_ir1.x1Hi = (x1 >> 8) & 0x3; //_ir1.x1Hi = (x1 >> 8) & 0x3;
//_ir1.y1Hi = (y1 >> 8) & 0x3; //_ir1.y1Hi = (y1 >> 8) & 0x3;
// ---------------------------- // ------------------------------------
// Debugging for calibration // Debugging for calibration
// ---------- // ----------
/*
if(GetAsyncKeyState(VK_NUMPAD1)) if(GetAsyncKeyState(VK_NUMPAD1))
Right +=1; Right +=1;
else if(GetAsyncKeyState(VK_NUMPAD2)) else if(GetAsyncKeyState(VK_NUMPAD2))
@ -644,7 +729,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
SensorBarRadius += 1; SensorBarRadius += 1;
else if(GetAsyncKeyState(VK_DELETE)) else if(GetAsyncKeyState(VK_DELETE))
SensorBarRadius -= 1; SensorBarRadius -= 1;
/*
//ClearScreen(); //ClearScreen();
//if(consoleDisplay == 1) //if(consoleDisplay == 1)
@ -658,53 +743,56 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
_ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi, _ir1.x1, _ir1.x1Hi, _ir1.x2, _ir1.x2Hi,
_ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi _ir1.y1, _ir1.y1Hi, _ir1.y2, _ir1.y2Hi
);*/ );*/
// ------------------
} }
int abc = 0;
//**************************************************************************************
// Extensions
//**************************************************************************************
// =================================================== // ===================================================
/* Generate the 6 byte extension report for the Nunchuck, encrypted. The bytes are JX JY AX AY AZ BT. */ /* Generate the 6 byte extension report for the Nunchuck, encrypted. The bytes are JX JY AX AY AZ BT. */
// ---------------- // ----------------
void FillReportExtension(wm_extension& _ext) void FillReportExtension(wm_extension& _ext)
{ {
#ifdef _WIN32
// ------------------------------------ // ------------------------------------
// Recorded movements // Recorded movements
// -------------- // --------------
// Check for a playback command // Check for a playback command
if(g_RecordingPlaying[1] < 0) if(g_RecordingPlaying[1] < 0)
{ {
g_RecordingPlaying[1] = RecordingCheckKeys(false); g_RecordingPlaying[1] = RecordingCheckKeys(1);
} }
// We should play back the accelerometer values
else else
{ {
RecordingPlay(_ext.ax, _ext.ay, _ext.az, 1);
//Console::Print("X: %u\n", _acc.x); //Console::Print("X: %u\n", _acc.x);
return; //
} if (!RecordingPlay(_ext.ax, _ext.ay, _ext.az, 1))
// --------------------- {
#endif /* These are the default neutral values for the nunchuck accelerometer according to the calibration
data we have in nunchuck_calibration[] */
/* These are the default neutral values for the nunchuck accelerometer according
to a source. */
_ext.ax = 0x80; _ext.ax = 0x80;
_ext.ay = 0x80; _ext.ay = 0x80;
_ext.az = 0xb3; _ext.az = 0xb3;
}
}
// ---------------------
// ------------------------------------
_ext.ax += abc; // The default joystick and button values unless we use them
// --------------
abc ++; _ext.jx = 0x80;
if (abc > 50) abc = 0;
_ext.jx = 0x80; // these are the default values unless we use them
_ext.jy = 0x80; _ext.jy = 0x80;
_ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active _ext.bt = 0x03; // 0x03 means no button pressed, the button is zero active
// ---------------------
#ifdef _WIN32 #ifdef _WIN32
/* We use a 192 range (32 to 224) that match our calibration values in /* We use a 192 range (32 to 224) that match our calibration values in nunchuck_calibration[] */
nunchuck_calibration */
if(GetAsyncKeyState(VK_NUMPAD4)) // left if(GetAsyncKeyState(VK_NUMPAD4)) // left
_ext.jx = 0x20; _ext.jx = 0x20;

View file

@ -53,12 +53,30 @@ void handle_ctrl_status(struct wiimote_t* wm)
printf("battery: %f %%\n", wm->battery_level); printf("battery: %f %%\n", wm->battery_level);
} }
bool IRDataOK(struct wiimote_t* wm)
{
//Console::Print("IRDataOK: ");
// The report size is 0x33 = 18, 0x37 = 22 withouth the leading (a1) byte
int ReportSize; if(WIIUSE_USING_EXP(wm)) ReportSize = 22; else ReportSize = 18;
for(int i = 0; i < ReportSize; i++)
{
//Console::Print("%02x ", wm->event_buf[i]);
if (wm->event_buf[i] > 0)
{
//Console::Print("\n");
return true;
}
}
return false;
}
void handle_event(struct wiimote_t* wm) void handle_event(struct wiimote_t* wm)
{ {
printf("\n\n--- EVENT [id %i] ---\n", wm->unid); printf("\n\n--- EVENT [id %i] ---\n", wm->unid);
/* if a button is pressed, report it */ /* if a button is pressed, report it */
//if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) Console::Print("B pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_B)) Console::Print("B pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) Console::Print("UP pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_UP)) Console::Print("UP pressed\n");
if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) Console::Print("DOWN pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) Console::Print("DOWN pressed\n");
@ -78,22 +96,19 @@ void handle_event(struct wiimote_t* wm)
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS)) if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_MINUS))
{ {
wiiuse_motion_sensing(wm, 0); wiiuse_motion_sensing(wm, 0);
wiiuse_set_ir(wm, 0);
g_MotionSensing = false; g_MotionSensing = false;
} }
/* // Turn aceelerometer and IR reporting on, there is some kind of bug that prevents us from turing these on
* Pressing plus will tell the wiimote we are interested in movement. // directly after each other, so we have to wait for another wiiuse_poll() this way
*/
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS)) if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_PLUS))
{ {
wiiuse_motion_sensing(wm, 1); wiiuse_motion_sensing(wm, 1);
g_MotionSensing = true; g_MotionSensing = true;
} }
// Turn IR reporting on
// Turn IR reporting on and off if (g_MotionSensing && !WIIUSE_USING_IR(wm))
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
wiiuse_set_ir(wm, 1); wiiuse_set_ir(wm, 1);
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
wiiuse_set_ir(wm, 0);
/* Print battery status */ /* Print battery status */
if(frame) if(frame)
@ -101,15 +116,42 @@ void handle_event(struct wiimote_t* wm)
frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
/* If the accelerometer is turned on then print angles */ /* If the accelerometer is turned on then print angles */
if (WIIUSE_USING_ACC(wm)) if (WIIUSE_USING_ACC(wm) && WIIUSE_USING_IR(wm))
{ {
std::string Tmp; std::string Tmp;
Tmp += StringFromFormat("Roll: %2.1f ", wm->orient.roll); Tmp += StringFromFormat("Roll: %2.1f ", wm->orient.roll);
Tmp += StringFromFormat("Pitch: %2.1f ", wm->orient.pitch); Tmp += StringFromFormat("Pitch: %2.1f ", wm->orient.pitch);
Tmp += StringFromFormat("Battery: %1.2f\n", wm->battery_level); Tmp += StringFromFormat("Battery: %1.2f\n", wm->battery_level);
Tmp += StringFromFormat("G-Force x, y, z: %1.2f %1.2f %1.2f\n", wm->gforce.x, wm->gforce.y, wm->gforce.z); Tmp += StringFromFormat("G-Force x, y, z: %1.2f %1.2f %1.2f\n", wm->gforce.x, wm->gforce.y, wm->gforce.z);
Tmp += StringFromFormat("Accel x, y, z: %03i %03i %03i\n\n", wm->accel.x, wm->accel.y, wm->accel.z); Tmp += StringFromFormat("Accel x, y, z: %03i %03i %03i\n", wm->accel.x, wm->accel.y, wm->accel.z);
// The report size is 0x33 = 18, 0x37 = 22
int ReportSize; if(WIIUSE_USING_EXP(wm)) ReportSize = 22; else ReportSize = 18;
// wm->event_buf is cleared at the end of all wiiuse_poll(), so wm->event_buf will always be zero
// after that. To get the raw IR data we need to read the wiimote again. This seems to work most of the time,
// it seems to fails with a regular interval about each tenth read.
if(wiiuse_io_read(wm))
{
// Check that it's not zero
if (IRDataOK(wm)) memcpy(g_EventBuffer, wm->event_buf, ReportSize);
}
// Go through each of the 4 possible IR sources
for (int i = 0; i < 4; ++i)
{
// Check if the source is visible
if (wm->ir.dot[i].visible)
Tmp += StringFromFormat("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
}
Tmp += StringFromFormat("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
Tmp += StringFromFormat("IR z distance: %f\n", wm->ir.z);
std::string TmpData = ArrayToString(g_EventBuffer, ReportSize, 0, 30);
Tmp += "Data: " + TmpData;
Console::ClearScreen();
Console::Print("%s\n\n", Tmp.c_str());
if(frame) if(frame)
{ {
@ -129,11 +171,19 @@ void handle_event(struct wiimote_t* wm)
frame->m_GaugeAccel[1]->SetValue(wm->accel.y); frame->m_GaugeAccel[1]->SetValue(wm->accel.y);
frame->m_GaugeAccel[2]->SetValue(wm->accel.z); frame->m_GaugeAccel[2]->SetValue(wm->accel.z);
frame->m_TextIR->SetLabel(wxString::Format(
"Cursor: %03u %03u\nDistance:%4.0f", wm->ir.x, wm->ir.y, wm->ir.z));
if(frame->m_bRecording) if(frame->m_bRecording)
Console::Print("Wiiuse Recorded accel x, y, z: %03i %03i %03i\n", wm->accel.x, wm->accel.y, wm->accel.z); Console::Print("Wiiuse Recorded accel x, y, z: %03i %03i %03i\n", wm->accel.x, wm->accel.y, wm->accel.z);
} }
frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z); // Send the data to be saved
//const u8* data = (const u8*)wm->event_buf;
frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z, (g_EventBuffer + 6),
(WIIUSE_USING_EXP(wm) ? 10 : 12));
// Turn recording on and off
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) frame->DoRecordA(true); if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) frame->DoRecordA(true);
else frame->DoRecordA(false); else frame->DoRecordA(false);
} }
@ -143,43 +193,20 @@ void handle_event(struct wiimote_t* wm)
{ {
if (frame) if (frame)
{ {
frame->m_GaugeRoll[0]->SetValue(0);
frame->m_GaugeRoll[1]->SetValue(0);
frame->m_GaugeGForce[0]->SetValue(0);
frame->m_GaugeGForce[1]->SetValue(0);
frame->m_GaugeGForce[2]->SetValue(0);
frame->m_GaugeAccel[0]->SetValue(0); frame->m_GaugeAccel[0]->SetValue(0);
frame->m_GaugeAccel[1]->SetValue(0); frame->m_GaugeAccel[1]->SetValue(0);
frame->m_GaugeAccel[2]->SetValue(0); frame->m_GaugeAccel[2]->SetValue(0);
frame->m_TextIR->SetLabel(wxT("Cursor:\nDistance:"));
} }
} }
/*
* If IR tracking is enabled then print the coordinates
* on the virtual screen that the wiimote is pointing to.
*
* Also make sure that we see at least 1 dot.
*/
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_UP))
wiiuse_set_ir(wm, 1);
if (IS_JUST_PRESSED(wm, WIIMOTE_BUTTON_DOWN))
wiiuse_set_ir(wm, 0);
if (WIIUSE_USING_IR(wm))
{
/*Console::ClearScreen();
// Go through each of the 4 possible IR sources
for (int i = 0; i < 4; ++i)
{
// Check if the source is visible
if (wm->ir.dot[i].visible)
Console::Print("IR source %i: (%u, %u)\n", i, wm->ir.dot[i].x, wm->ir.dot[i].y);
}
Console::Print("IR cursor: (%u, %u)\n", wm->ir.x, wm->ir.y);
Console::Print("IR z distance: %f\n", wm->ir.z);
const byte* pBuffer = wm->event_buf;
std::string Temp = ArrayToString(pBuffer, 20, 0, 30);
Console::Print("Data: %s\n", Temp.c_str());*/
}
} }
void ReadWiimote() void ReadWiimote()
@ -246,13 +273,13 @@ void ReadWiimote()
break; break;
case WIIUSE_CLASSIC_CTRL_INSERTED: case WIIUSE_CLASSIC_CTRL_INSERTED:
//printf("Classic controller inserted.\n"); Console::Print("Classic controller inserted.\n");
break; break;
case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED: case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
/* some expansion was inserted */ /* some expansion was inserted */
//handle_ctrl_status(wiimotes[i]); //handle_ctrl_status(wiimotes[i]);
printf("Guitar Hero 3 controller inserted.\n"); Console::Print("Guitar Hero 3 controller inserted.\n");
break; break;
case WIIUSE_NUNCHUK_REMOVED: case WIIUSE_NUNCHUK_REMOVED:
@ -260,7 +287,7 @@ void ReadWiimote()
case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED: case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
/* some expansion was removed */ /* some expansion was removed */
//handle_ctrl_status(wiimotes[i]); //handle_ctrl_status(wiimotes[i]);
printf("An expansion was removed.\n"); Console::Print("An expansion was removed.\n");
break; break;
default: default:

View file

@ -46,18 +46,23 @@ bool IsFocus();
// Movement recording // Movement recording
#define RECORDING_ROWS 15 #define RECORDING_ROWS 15
#define WM_RECORDING_WIIMOTE 0
#define WM_RECORDING_NUNCHUCK 1
#define WM_RECORDING_IR 2
struct SRecording struct SRecording
{ {
u8 x; u8 x;
u8 y; u8 y;
u8 z; u8 z;
double Time; double Time;
u8 IR[12];
}; };
struct SRecordingAll struct SRecordingAll
{ {
std::vector<SRecording> Recording; std::vector<SRecording> Recording;
int HotKey; int HotKey;
int PlaybackSpeed; int PlaybackSpeed;
int IRBytes;
}; };
#ifndef EXCLUDEMAIN_H #ifndef EXCLUDEMAIN_H

View file

@ -154,7 +154,7 @@ struct wm_accel {
u8 x, y, z; u8 x, y, z;
}; };
//filled with 0xFF if empty // Filled with 0xFF if empty
struct wm_ir_basic struct wm_ir_basic
{ {
u8 x1; u8 x1;

View file

@ -70,10 +70,12 @@ int g_NumberOfWiiMotes;
CWiiMote* g_WiiMotes[MAX_WIIMOTES]; CWiiMote* g_WiiMotes[MAX_WIIMOTES];
bool g_Shutdown = false; bool g_Shutdown = false;
bool g_LocalThread = true; bool g_LocalThread = true;
bool g_IRSensing = false;
bool g_MotionSensing = false; bool g_MotionSensing = false;
u64 g_UpdateTime = 0; u64 g_UpdateTime = 0;
int g_UpdateCounter = 0; int g_UpdateCounter = 0;
bool g_RunTemporary = false; bool g_RunTemporary = false;
u8 g_EventBuffer[32];
//****************************************************************************** //******************************************************************************
// Probably this class should be in its own file // Probably this class should be in its own file

View file

@ -48,9 +48,11 @@ void ReadWiimote();
extern wiimote_t** g_WiiMotesFromWiiUse; extern wiimote_t** g_WiiMotesFromWiiUse;
extern int g_NumberOfWiiMotes; extern int g_NumberOfWiiMotes;
extern bool g_MotionSensing; extern bool g_MotionSensing;
extern bool g_IRSensing;
extern u64 g_UpdateTime; extern u64 g_UpdateTime;
extern int g_UpdateCounter; extern int g_UpdateCounter;
extern bool g_RunTemporary; extern bool g_RunTemporary;
extern u8 g_EventBuffer[32];
#endif #endif
}; // WiiMoteReal }; // WiiMoteReal