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))
//{ if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) CreateAckDelay((u8)_channelID, (u16)sr->channel);
// 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);
//}
//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)
@ -124,25 +141,53 @@ 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 relative distance between between them control the calibration. WideScreen mode // --------------------------------------
has its own settings. */ /* The calibration is controlled by these values, their absolute value and
the relative distance between between them control the calibration. WideScreen mode
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))
{
/* These are the default neutral values for the nunchuck accelerometer according to the calibration
data we have in nunchuck_calibration[] */
_ext.ax = 0x80;
_ext.ay = 0x80;
_ext.az = 0xb3;
}
} }
// --------------------- // ---------------------
#endif
/* These are the default neutral values for the nunchuck accelerometer according // ------------------------------------
to a source. */ // The default joystick and button values unless we use them
_ext.ax = 0x80; // --------------
_ext.ay = 0x80; _ext.jx = 0x80;
_ext.az = 0xb3;
_ext.ax += abc;
abc ++;
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);
} }
// 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));
frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z); // 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