diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index 1f722aabe5..6a93dfd558 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -56,7 +56,7 @@ void Config::Save() iniFile.Set("Real", "Connect", bConnectRealWiimote); iniFile.Set("Real", "Use", bUseRealWiimote); - iniFile.Set("Real", "UpdateStatus", bUpdateRealWiimote); + iniFile.Set("Real", "UpdateStatus", bUpdateRealWiimote); iniFile.Save(FULL_CONFIG_DIR "Wiimote.ini"); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index 2889f9e93e..e42677c7ef 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -37,6 +37,7 @@ struct Config // Real Wiimote bool bConnectRealWiimote, bUseRealWiimote, bUpdateRealWiimote; + int iAccNeutralX, iAccNeutralY, iAccNeutralZ; }; extern Config g_Config; diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 72121f27e8..b79799e70a 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -25,6 +25,7 @@ #include "Timer.h" #include "wiimote_real.h" // Local +#include "wiimote_hid.h" #include "main.h" #include "ConfigDlg.h" #include "Config.h" @@ -547,12 +548,27 @@ void ConfigDialog::ConvertToString() double Recordings = (double)m_vRecording.size(); double Time = m_vRecording.at(m_vRecording.size() - 1).Time - m_vRecording.at(0).Time; int Rate = (int)(Recordings / Time); + + // If time or the number of recordings are zero we set the Rate to zero + if (Time == 0 || m_vRecording.size() == 0) Rate = 0; + + // Update GUI m_RecordSpeed[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), Rate)); + // Save file std::string SaveName = StringFromFormat("Recording%i", m_iRecordTo); file.Set(SaveName.c_str(), "Movement", TmpStr.c_str()); file.Set(SaveName.c_str(), "Time", TmpTime.c_str()); - file.Set(SaveName.c_str(), "RecordingSpeed", Rate); + file.Set(SaveName.c_str(), "RecordingSpeed", Rate); + + // Set a default playback speed if none is set already + int TmpPlaySpeed; file.Get(SaveName.c_str(), "PlaybackSpeed", &TmpPlaySpeed, -1); + if (TmpPlaySpeed == -1) + { + file.Set(SaveName.c_str(), "PlaybackSpeed", 3); + m_RecordPlayBackSpeed[m_iRecordTo]->SetSelection(3); + } + file.Save("WiimoteMovement.ini"); } @@ -639,7 +655,7 @@ void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z) { if (!m_bRecording) return; - Console::Print("DoRecordMovement\n"); + //Console::Print("DoRecordMovement\n"); SRecording Tmp; Tmp.x = _x; @@ -765,10 +781,13 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event) break; case ID_USE_REAL: g_Config.bUseRealWiimote = m_UseRealWiimote->IsChecked(); + //if(g_Config.bUseRealWiimote) WiiMoteReal::SetDataReportingMode(); + if(g_Config.bUseRealWiimote) WiiMoteReal::ClearEvents(); break; case ID_UPDATE_REAL: g_Config.bUpdateRealWiimote = m_UpdateMeters->IsChecked(); break; + case IDC_RECORD + 1: case IDC_RECORD + 2: case IDC_RECORD + 3: @@ -809,14 +828,26 @@ void ConfigDialog::UpdateGUI() { Console::Print("UpdateGUI: \n"); + /* We can't allow different values for this one if we are using the real and emulated wiimote + side by side so that we can switch between between during gameplay. We update the checked + or unchecked values from the g_Config settings, and we make sure they are up to date with + unplugged and reinserted extensions. */ + m_NunchuckConnected->SetValue(g_Config.bNunchuckConnected); + m_ClassicControllerConnected->SetValue(g_Config.bClassicControllerConnected); + m_NunchuckConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote)); + m_ClassicControllerConnected->Enable(!(g_RealWiiMotePresent && g_Config.bConnectRealWiimote)); + /* 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 mean that the wiimote must be sent the current reporting mode and the channel ID after it - has been initialized. If you know how to set that manually please feel free to make functions - for that so that this option can be enabled during gameplay. */ + has been initialized. Functions for that are basically already in place so these two options + could possibly be simplified to one option. */ m_ConnectRealWiimote->Enable(!g_EmulatorRunning); m_UseRealWiimote->Enable(g_RealWiiMotePresent && g_Config.bConnectRealWiimote); + + + // Linux has no FindItem() #ifdef _WIN32 for(int i = IDB_RECORD + 1; i < (IDB_RECORD + RECORDING_ROWS + 1); i++) diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index b404f9c221..ae32e3fdf1 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -76,7 +76,7 @@ class ConfigDialog : public wxDialog wxCheckBox *m_WideScreen; wxCheckBox *m_NunchuckConnected, *m_ClassicControllerConnected; - wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote, *m_UpdateMeters; // Real Wiimote settings + wxCheckBox *m_ConnectRealWiimote, *m_UseRealWiimote, *m_UpdateMeters; // Real Wiimote settings //static const int RECORDING_ROWS = 15; wxButton * m_RecordButton[RECORDING_ROWS + 1]; diff --git a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp index 1326e8449b..495e6b1158 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/DataReports.cpp @@ -59,6 +59,7 @@ #include "StringUtil.h" // for ArrayToString #include "wiimote_hid.h" // Local +#include "main.h" #include "EmuMain.h" #include "EmuSubroutines.h" #include "EmuDefinitions.h" @@ -83,6 +84,9 @@ namespace WiiMoteEmu //****************************************************************************** +// =================================================== +/* Update the data reporting mode */ +// ---------------- void WmDataReporting(u16 _channelID, wm_data_reporting* dr) { LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); @@ -91,8 +95,11 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr) LOG(WII_IPC_WIIMOTE, " Continuous: %x", dr->continuous); LOG(WII_IPC_WIIMOTE, " All The Time: %x (not only on data change)", dr->all_the_time); LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); - Console::Print("Data reporting mode: 0x%02x\n", dr->mode); - Console::Print("Data reporting channel: 0x%04x\n", _channelID); + Console::Print("Data reporting:\n"); + Console::Print(" Continuous: %x\n", dr->continuous); + Console::Print(" All The Time: %x (not only on data change)\n", dr->all_the_time); + Console::Print(" Mode: 0x%02x\n", dr->mode); + Console::Print(" Channel: 0x%04x\n", _channelID); g_ReportingMode = dr->mode; g_ReportingChannel = _channelID; @@ -105,7 +112,7 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr) case WM_REPORT_CORE_ACCEL_IR10_EXT6: break; default: - PanicAlert("Wiimote: Unknown reporting mode 0x%x", dr->mode); + PanicAlert("Wiimote: Unsupported reporting mode 0x%x", dr->mode); } // WmSendAck(_channelID, WM_DATA_REPORTING); @@ -132,6 +139,9 @@ void SendReportCore(u16 _channelID) LOGV(WII_IPC_WIIMOTE, 2, " SendReportCore()"); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } @@ -154,15 +164,10 @@ void SendReportCoreAccel(u16 _channelID) LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - Console::Print("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } @@ -186,20 +191,13 @@ void SendReportCoreAccelIr12(u16 _channelID) { LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr12()"); LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - Console::Print("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } - - // =================================================== /* Case 0x35: Core Buttons and Accelerometer with 16 Extension Bytes */ // ---------------- @@ -234,15 +232,10 @@ void SendReportCoreAccelExt16(u16 _channelID) LOGV(WII_IPC_WIIMOTE, 2, " Channel: %04x", _channelID); LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = WiiMoteEmu::ArrayToString(DataFrame, Offset, 0, 30); - Console::Print("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } @@ -279,15 +272,10 @@ void SendReportCoreAccelIr10Ext(u16 _channelID) LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr10Ext()"); - // Debugging -#ifdef _WIN32 - /*if(GetAsyncKeyState('V')) - { - std::string Temp = ArrayToString(DataFrame, Offset, 0, 30); - Console::Print("DataFrame: %s\n", Temp.c_str()); - }*/ -#endif g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp index afa6ae3fec..dfc6d58737 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.cpp @@ -41,10 +41,10 @@ namespace WiiMoteEmu // Definitions and variable declarations //****************************************************************************** -u8 g_Leds = 0x0; // 4 bits +u8 g_Leds = 0x1; // 4 bits u8 g_Speaker = 0x1; // 1 = on -u8 g_SpeakerVoice = 0x1; // 1 = on -u8 g_IR = 0x1; // 1 = on +u8 g_SpeakerVoice = 0x0; // 1 = on +u8 g_IR = 0x0; // 1 = on u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h index ca88d33515..d634c270a6 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDefinitions.h @@ -55,8 +55,16 @@ namespace WiiMoteEmu #define wBOTTOM 625 #define wSENSOR_BAR_RADIUS 200 +// Movement recording +extern int g_RecordingPlaying[2]; +extern int g_RecordingCounter[2]; +extern int g_RecordingPoint[2]; +extern double g_RecordingStart[2]; +extern double g_RecordingCurrentTime[2]; + // Registry sizes #define WIIMOTE_EEPROM_SIZE (16*1024) +#define WIIMOTE_EEPROM_FREE_SIZE 0x16ff #define WIIMOTE_REG_SPEAKER_SIZE 10 #define WIIMOTE_REG_EXT_SIZE 0x100 #define WIIMOTE_REG_IR_SIZE 0x34 @@ -89,13 +97,13 @@ extern std::vector AckDelay; extern wiimote_key g_ExtKey; // extension encryption key +/* An example of a factory default first bytes of the Eeprom memory. There are differences between + different Wiimotes, my Wiimote had different neutral values for the accelerometer. */ static const u8 EepromData_0[] = { - 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, - 0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE, - 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, 0x82, 0x82, - 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E, - 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, - 0x40, 0x3E + 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, + 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, + 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E, + 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E }; static const u8 EepromData_16D0[] = { diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 392fda5ed5..123c685965 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -28,10 +28,10 @@ #include "StringUtil.h" // for ArrayToString() #include "IniFile.h" -#include "main.h" // Local +#include "EmuDefinitions.h" // Local +#include "main.h" #include "wiimote_hid.h" #include "EmuSubroutines.h" -#include "EmuDefinitions.h" #include "EmuMain.h" #include "Encryption.h" // for extension encryption #include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd @@ -149,8 +149,8 @@ void LoadRecordedMovements() AsciiToHex(StrY.c_str(), TmpY); AsciiToHex(StrZ.c_str(), TmpZ); Tmp.x = (u8)TmpX; - Tmp.x = (u8)TmpY; - Tmp.x = (u8)TmpZ; + Tmp.y = (u8)TmpY; + Tmp.z = (u8)TmpZ; // Go to next set of time values double Time = (double)atoi(TmpTime.substr(k, 5).c_str()); @@ -186,12 +186,18 @@ void Initialize() { if (g_EmulatedWiiMoteInitialized) return; + // Write default Eeprom data memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE); memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0)); memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0)); - g_ReportingMode = 0; - + // Write default accelerometer neutral values + g_accel.cal_zero.x = g_Eeprom[22]; + g_accel.cal_zero.y = g_Eeprom[23]; + g_accel.cal_zero.z = g_Eeprom[24]; + g_accel.cal_g.x = g_Eeprom[26]; + g_accel.cal_g.y = g_Eeprom[27]; + g_accel.cal_g.z = g_Eeprom[28]; /* Extension data for homebrew applications that use the 0x00000000 key. This writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */ @@ -210,11 +216,19 @@ void Initialize() memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id)); } + g_ReportingMode = 0; g_EmulatedWiiMoteInitialized = true; // Load pre-recorded movements LoadRecordedMovements(); + // Set default recording values + g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1; + g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0; + g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0; + g_RecordingStart[0] = 0; g_RecordingStart[1] = 0; + g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0; + // I forgot what these were for? // g_RegExt[0xfd] = 0x1e; // g_RegExt[0xfc] = 0x9a; @@ -285,48 +299,11 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); const u8* data = (const u8*)_pData; - // ----------------------------------------------------- /* Debugging. We have not yet decided how much of 'data' we will use, it's not determined by sizeof(data). We have to determine it by looking at the data cases. */ - // ----------------- - /*int size; - switch(data[1]) - { - case 0x10: - size = 4; // I don't know the size - break; - case WM_LEDS: // 0x11 - size = sizeof(wm_leds); - break; - case WM_DATA_REPORTING: // 0x12 - size = sizeof(wm_data_reporting); - break; - case WM_REQUEST_STATUS: // 0x15 - size = sizeof(wm_request_status); - break; - case WM_WRITE_DATA: // 0x16 - size = sizeof(wm_write_data); - break; - case WM_READ_DATA: // 0x17 - size = sizeof(wm_read_data); - break; - case WM_IR_PIXEL_CLOCK: // 0x13 - case WM_IR_LOGIC: // 0x1a - case WM_SPEAKER_ENABLE: // 0x14 - case WM_SPEAKER_MUTE: - size = 1; - break; - default: - PanicAlert("HidOutputReport: Unknown channel 0x%02x", data[1]); - return; - } - std::string Temp = ArrayToString(data, size + 2, 0, 30); - //LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); - Console::Print("\n%s: InterruptChannel: %s\n", Tm(true).c_str(), Temp.c_str());*/ - // ----------------------------------- + InterruptDebugging(true, data); hid_packet* hidp = (hid_packet*) data; - switch(hidp->type) { case HID_TYPE_DATA: @@ -351,7 +328,11 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size) //if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA) // && data[3] == 0xa4) //{ - 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 //{ @@ -413,7 +394,7 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size) { HidOutputReport(_channelID, (wm_report*)hidp->data); - //return handshake + // Return handshake u8 handshake = 0; g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1); } diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp index 4d9727f546..5fa1087adc 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.cpp @@ -46,11 +46,8 @@ #include "StringUtil.h" #include "pluginspecs_wiimote.h" -#include "main.h" // Local -#include "wiimote_hid.h" -#include "EmuMain.h" +#include "EmuMain.h" // Local #include "EmuSubroutines.h" -#include "EmuDefinitions.h" #include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd #include "Config.h" // for g_Config ///////////////////////////////// @@ -141,7 +138,8 @@ void HidOutputReport(u16 _channelID, wm_report* sr) { // =================================================== /* Generate the right address for wm reports. */ // ---------------- -int WriteWmReport(u8* dst, u8 channel) { +int WriteWmReport(u8* dst, u8 channel) +{ u32 Offset = 0; hid_packet* pHidHeader = (hid_packet*)(dst + Offset); Offset += sizeof(hid_packet); @@ -196,9 +194,9 @@ void WmSendAck(u16 _channelID, u8 _reportID, u32 address) LOGV(WII_IPC_WIIMOTE, 2, " WMSendAck()"); LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID); - std::string Temp = ArrayToString(DataFrame, Offset, 0); + //std::string Temp = ArrayToString(DataFrame, Offset, 0); //LOGV(WII_IPC_WIIMOTE, 2, " Data: %s", Temp.c_str()); - Console::Print("%s: WMSendAck: %s\n", Tm(true).c_str(), Temp.c_str()); + //Console::Print("%s: WMSendAck: %s\n", Tm(true).c_str(), Temp.c_str()); /* Debug. Write the report for extension registry writes. if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4) @@ -208,6 +206,9 @@ void WmSendAck(u16 _channelID, u8 _reportID, u32 address) }*/ g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); + + // Debugging + ReadDebugging(true, DataFrame); } @@ -231,14 +232,16 @@ void WmReadData(u16 _channelID, wm_read_data* rd) /* Now we determine what address space we are reading from. Space 0 is Eeprom and space 1 and 2 is the registers. */ - if(rd->space == 0) + if(rd->space == WM_SPACE_EEPROM) { if (address + size > WIIMOTE_EEPROM_SIZE) { - PanicAlert("WmReadData: address + size out of bounds!"); + PanicAlert("WmReadData: address + size out of bounds"); return; } - SendReadDataReply(_channelID, g_Eeprom+address, address, (u8)size); + SendReadDataReply(_channelID, g_Eeprom + address, address, (u8)size); + /*Console::Print("Read RegEeprom: Size: %i, Address: %08x, Offset: %08x\n", + size, address, (address & 0xffff));*/ } else if(rd->space == WM_SPACE_REGS1 || rd->space == WM_SPACE_REGS2) { @@ -250,28 +253,28 @@ void WmReadData(u16 _channelID, wm_read_data* rd) block = g_RegSpeaker; blockSize = WIIMOTE_REG_SPEAKER_SIZE; LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); - //Tmp = ArrayToString(g_RegSpeaker, size, (address & 0xffff)); + /*Tmp = ArrayToString(g_RegSpeaker, size, (address & 0xffff)); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - //Console::Print("Read RegSpkr: Size %i Address %08x Offset %08x\nData %s\n", - // size, address, (address & 0xffff), Tmp.c_str()); + Console::Print("Read RegSpkr: Size %i Address %08x Offset %08x\nData %s\n", + size, address, (address & 0xffff), Tmp.c_str());*/ break; case 0xA4: block = g_RegExt; blockSize = WIIMOTE_REG_EXT_SIZE; LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************"); - //Tmp = ArrayToString(g_RegExt, size, (address & 0xffff)); + /*Tmp = ArrayToString(g_RegExt, size, (address & 0xffff)); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - //Console::Print("Read RegExt: Size %i Address %08x Offset %08x\nData %s\n", - // size, address, (address & 0xffff), Tmp.c_str()); + Console::Print("Read RegExt: Size %i Address %08x Offset %08x\nData %s\n", + size, address, (address & 0xffff), Tmp.c_str());*/ break; case 0xB0: block = g_RegIr; blockSize = WIIMOTE_REG_IR_SIZE; LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr"); - //Tmp = ArrayToString(g_RegIr, size, (address & 0xffff)); + /*Tmp = ArrayToString(g_RegIr, size, (address & 0xffff)); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str()); - //Console::Print("Read RegIR: Size %i Address %08x Offset %08x\nData %s\n", - // size, address, (address & 0xffff), Tmp.c_str()); + Console::Print("Read RegIR: Size %i Address %08x Offset %08x\nData %s\n", + size, address, (address & 0xffff), Tmp.c_str());*/ break; default: PanicAlert("WmWriteData: bad register block!"); @@ -320,7 +323,7 @@ void WmReadData(u16 _channelID, wm_read_data* rd) } // Let this function process the message and send it to the Wii - SendReadDataReply(_channelID, block+address, address, (u8)size); + SendReadDataReply(_channelID, block + address, address, (u8)size); } @@ -360,6 +363,8 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) return; } memcpy(g_Eeprom + address, wd->data, wd->size); + /*Console::Print("Write RegEeprom: Size: %i, Address: %08x, Offset: %08x\n", + wd->size, address, (address & 0xffff));*/ } // Write to registers else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2)) @@ -372,9 +377,9 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) block = g_RegSpeaker; blockSize = WIIMOTE_REG_SPEAKER_SIZE; LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: RegSpeaker"); - //Console::Print("Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n", - // wd->size, address, (address & 0xffff)); - //Console::Print("Data: %s\n", Temp.c_str()); + /*Console::Print("Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n", + wd->size, address, (address & 0xffff)); + Console::Print("Data: %s\n", Temp.c_str());*/ break; case 0xA4: block = g_RegExt; // Extension Controller register @@ -398,7 +403,6 @@ void WmWriteData(u16 _channelID, wm_write_data* wd) PanicAlert("WmWriteData: bad register block!"); return; } - // Remove for example 0xa40000 from the address address &= 0xFFFF; @@ -455,51 +459,70 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size) { LOGV(WII_IPC_WIIMOTE, 0, "========================================="); int dataOffset = 0; + const u8* data = (const u8*)_Base; while (_Size > 0) { u8 DataFrame[1024]; u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY); + // Limit the size to 16 bytes int copySize = _Size; - if (copySize > 16) - { - copySize = 16; - } + if (copySize > 16) copySize = 16; + // Connect pReply->data to the empty DataFrame wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); Offset += sizeof(wm_read_data_reply); pReply->buttons = 0; pReply->error = 0; - pReply->size = (copySize - 1) & 0xF; + pReply->size = (copySize - 1) & 0xf; pReply->address = Common::swap16(_Address + dataOffset); + // Write a pice of _Base to DataFrame + memcpy(pReply->data, data + dataOffset, copySize); - // Write a pice - memcpy(pReply->data + dataOffset, _Base, copySize); - - if(copySize < 16) // check if we have less than 16 bytes left to send - { + // Check if we have less than 16 bytes left to send + if(copySize < 16) memset(pReply->data + copySize, 0, 16 - copySize); - } + + // Update DataOffset for the next loop dataOffset += copySize; + /* Out of bounds. The real Wiimote generate an error for the first request to 0x1770 + if we dont't replicate that the game will never read the capibration data at the + beginning of Eeprom. I think this error is supposed to occur when we try to read above + the freely usable space that ends at 0x16ff. */ + if (Common::swap16(pReply->address + pReply->size) > WIIMOTE_EEPROM_FREE_SIZE) + { + pReply->size = 0x0f; + pReply->error = 0x08; + } + // Logging LOG(WII_IPC_WIIMOTE, " SendReadDataReply()"); LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons); LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error); LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size); LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address); + /**/Console::Print(" SendReadDataReply()\n"); + Console::Print(" dataOffset: 0x%x\n", dataOffset); + Console::Print(" copySize: 0x%x\n", copySize); + Console::Print(" Size: 0x%x\n", pReply->size); + Console::Print(" Address: 0x%04x\n", Common::swap16(pReply->address)); + + //std::string Temp = ArrayToString(data, 0x40); + //Console::Print("Eeprom: %s\n", Temp.c_str()); // Send a piece g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); _Size -= copySize; + + // Debugging + ReadDebugging(true, DataFrame); } if (_Size != 0) - { PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); - } LOGV(WII_IPC_WIIMOTE, 0, "=========================================="); } // ================ @@ -551,6 +574,9 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs) g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); LOGV(WII_IPC_WIIMOTE, 0, "================================================="); + + // Debugging + ReadDebugging(true, DataFrame); } } // WiiMoteEmu diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h index dd772ad824..2717be0fe5 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuSubroutines.h @@ -28,7 +28,7 @@ #include #include "Common.h" // Common - +#include "main.h" #include "wiimote_hid.h" // Local #include "EmuDefinitions.h" #include "Encryption.h" diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index 0f37c17e89..437f2227f9 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -48,74 +48,85 @@ namespace WiiMoteEmu //****************************************************************************** // ------------------------------------------ -// Variables +// Variables: 0 = Wiimote, 1 = Nunchuck // ---------------- -int g_RecordingPlaying = -1; -int g_RecordingCounter = 0; -int g_RecordingPoint = 0; -double g_RecordingStart = 0; -double g_RecordingCurrentTime = 0; +int g_RecordingPlaying[2]; //g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1; +int g_RecordingCounter[2]; //g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0; +int g_RecordingPoint[2]; //g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0; +double g_RecordingStart[2]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0; +double g_RecordingCurrentTime[2]; //g_RecordingCurrentTime[0] = 0; g_RecordingCurrentTime[1] = 0; // -------------------------- -void RecordingPlay(u8 &_x, u8 &_y, u8 &_z) +void RecordingPlay(u8 &_x, u8 &_y, u8 &_z, int Wm) { // Return if the list is empty - if(VRecording.at(g_RecordingPlaying).Recording.size() == 0) + if(VRecording.at(g_RecordingPlaying[Wm]).Recording.size() == 0) { - g_RecordingPlaying = -1; + g_RecordingPlaying[Wm] = -1; Console::Print("Empty\n\n"); return; } // Return if the playback speed is unset - if(VRecording.at(g_RecordingPlaying).PlaybackSpeed < 0) + if(VRecording.at(g_RecordingPlaying[Wm]).PlaybackSpeed < 0) { - Console::Print("PlaybackSpeed empty: %i\n\n", g_RecordingPlaying); - g_RecordingPlaying = -1; + Console::Print("PlaybackSpeed empty: %i\n\n", g_RecordingPlaying[Wm]); + g_RecordingPlaying[Wm] = -1; return; } // Get starting time - if(g_RecordingCounter == 0) g_RecordingStart = GetDoubleTime(); + if(g_RecordingCounter[Wm] == 0) + { + Console::Print("\n\nBegin\n"); + g_RecordingStart[Wm] = GetDoubleTime(); + } // Get current time - g_RecordingCurrentTime = GetDoubleTime() - g_RecordingStart; + g_RecordingCurrentTime[Wm] = GetDoubleTime() - g_RecordingStart[Wm]; // Modify the current time - g_RecordingCurrentTime *= ((25.0 + (double)VRecording.at(g_RecordingPlaying).PlaybackSpeed * 25.0) / 100.0); + g_RecordingCurrentTime[Wm] *= ((25.0 + (double)VRecording.at(g_RecordingPlaying[Wm]).PlaybackSpeed * 25.0) / 100.0); // Select reading - for (int i = 0; i < VRecording.at(g_RecordingPlaying).Recording.size(); i++) - if (VRecording.at(g_RecordingPlaying).Recording.at(i).Time > g_RecordingCurrentTime) + for (int i = 0; i < VRecording.at(g_RecordingPlaying[Wm]).Recording.size(); i++) + if (VRecording.at(g_RecordingPlaying[Wm]).Recording.at(i).Time > g_RecordingCurrentTime[Wm]) { - g_RecordingPoint = i; + g_RecordingPoint[Wm] = i; break; // Break loop } // Return if we are at the end of the list - if(g_RecordingCurrentTime >= - VRecording.at(g_RecordingPlaying).Recording.at( - VRecording.at(g_RecordingPlaying).Recording.size() - 1).Time) + if(g_RecordingCurrentTime[Wm] >= + VRecording.at(g_RecordingPlaying[Wm]).Recording.at( + VRecording.at(g_RecordingPlaying[Wm]).Recording.size() - 1).Time) { - g_RecordingCounter = 0; - g_RecordingPlaying = -1; - g_RecordingStart = 0; - g_RecordingCurrentTime = 0; + g_RecordingCounter[Wm] = 0; + g_RecordingPlaying[Wm] = -1; + g_RecordingStart[Wm] = 0; + g_RecordingCurrentTime[Wm] = 0; Console::Print("End\n\n"); return; } // Update values - _x = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).x; - _y = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).y; - _z = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).z; + _x = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x; + _y = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y; + _z = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).z; - Console::Print("Current time: %f %f %i %i\n", - VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).Time, g_RecordingCurrentTime, - VRecording.at(g_RecordingPlaying).Recording.size(), g_RecordingPoint - ); + /**/ + if (g_DebugAccelerometer) + { + Console::ClearScreen(); + Console::Print("Current time: %f %f %i %i\n", + VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).Time, g_RecordingCurrentTime[Wm], + VRecording.at(g_RecordingPlaying[Wm]).Recording.size(), g_RecordingPoint[Wm] + ); + Console::Print("Accel x, y, z: %03u %03u %03u\n\n", _x, _y, _z); + } + - g_RecordingCounter++; + g_RecordingCounter[Wm]++; } // Check if we should play a recording @@ -249,27 +260,29 @@ void FillReportInfo(wm_core& _core) //int a = 1, b = 1, c = 2, d = -2; // for debugging //int consoleDisplay = 0; -int X = 0x84, Y = 0x84, Z = 0x9f; // neutral values -u8 x = X, y = Y, z = Z; +u8 x, y, z; int shake = -1, yhistsize = 15; // for the shake function std::vector yhist(15); // for the tilt function void FillReportAcc(wm_accel& _acc) { + // Create shortcut names for the default neutral values + int X = g_accel.cal_zero.x, Y = g_accel.cal_zero.y, Z = g_accel.cal_zero.z + g_accel.cal_g.z; + #ifdef _WIN32 // ------------------------------------ // Recorded movements // -------------- // Check for a playback command - if(g_RecordingPlaying < 0) + if(g_RecordingPlaying[0] < 0) { - g_RecordingPlaying = RecordingCheckKeys(true); + g_RecordingPlaying[0] = RecordingCheckKeys(true); } else { - RecordingPlay(_acc.x, _acc.y, _acc.z); - //Console::Print("X: %u\n", _acc.x); - return; + RecordingPlay(_acc.x, _acc.y, _acc.z, 0); + //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; } // --------------------- @@ -326,7 +339,7 @@ void FillReportAcc(wm_accel& _acc) y = Y; shake = -1; } - else // the default Y and Z if nothing is pressed + else // the default Z if nothing is pressed { z = Z; } @@ -542,7 +555,9 @@ void FillReportIR(wm_ir_extended& _ir0, wm_ir_extended& _ir1) );*/ } - +/////////////////////////////////////////////////////////////////// +// The extended 10 byte reporting +// --------------- void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) { /* See description above */ @@ -596,7 +611,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) // ---------------------------- // Debugging for calibration // ---------- - /* + if(GetAsyncKeyState(VK_NUMPAD1)) Right +=1; else if(GetAsyncKeyState(VK_NUMPAD2)) @@ -617,7 +632,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1) SensorBarRadius += 1; else if(GetAsyncKeyState(VK_DELETE)) SensorBarRadius -= 1; - +/* //ClearScreen(); //if(consoleDisplay == 1) @@ -644,13 +659,13 @@ void FillReportExtension(wm_extension& _ext) // Recorded movements // -------------- // Check for a playback command - if(g_RecordingPlaying < 0) + if(g_RecordingPlaying[1] < 0) { - g_RecordingPlaying = RecordingCheckKeys(false); + g_RecordingPlaying[1] = RecordingCheckKeys(false); } else { - RecordingPlay(_ext.ax, _ext.ay, _ext.az); + RecordingPlay(_ext.ax, _ext.ay, _ext.az, 1); //Console::Print("X: %u\n", _acc.x); return; } diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index d52bd96f7e..ec915c0854 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -26,8 +26,11 @@ #include "ConsoleWindow.h" // Common #include "StringUtil.h" +#include "Timer.h" #include "wiimote_real.h" // Local +#include "wiimote_hid.h" +#include "EmuDefinitions.h" #include "main.h" #if defined(HAVE_WX) && HAVE_WX #include "ConfigDlg.h" @@ -54,7 +57,7 @@ void handle_event(struct wiimote_t* wm) printf("\n\n--- EVENT [id %i] ---\n", wm->unid); /* 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_UP)) Console::Print("UP pressed\n"); if (IS_PRESSED(wm, WIIMOTE_BUTTON_DOWN)) Console::Print("DOWN pressed\n"); @@ -76,7 +79,6 @@ void handle_event(struct wiimote_t* wm) wiiuse_motion_sensing(wm, 0); g_MotionSensing = false; } - /* * Pressing plus will tell the wiimote we are interested in movement. */ @@ -86,45 +88,104 @@ void handle_event(struct wiimote_t* wm) g_MotionSensing = true; } + // Turn IR reporting on and off + 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); + + /* Print battery status */ + if(frame) + if(g_Config.bUpdateRealWiimote) + frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); + /* If the accelerometer is turned on then print angles */ if (WIIUSE_USING_ACC(wm)) { + std::string Tmp; Tmp += StringFromFormat("Roll: %2.1f ", wm->orient.roll); Tmp += StringFromFormat("Pitch: %2.1f ", wm->orient.pitch); 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("Accel x, y, z: %03i %03i %03i\n\n", wm->accel.x, wm->accel.y, wm->accel.z); - //Console::Print("%s", Tmp.c_str()); if(frame) { if(g_Config.bUpdateRealWiimote) - { - frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); + { + // Disabled for now, they serve a limited purpose anyway. Enabled again. + /**/ frame->m_GaugeRoll[0]->SetValue(wm->orient.roll + 180); frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180); frame->m_GaugeGForce[0]->SetValue((int)floor((wm->gforce.x * 100) + 300.5)); frame->m_GaugeGForce[1]->SetValue((int)floor((wm->gforce.y * 100) + 300.5)); - frame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5)); + frame->m_GaugeGForce[2]->SetValue((int)floor((wm->gforce.z * 100) + 300.5)); frame->m_GaugeAccel[0]->SetValue(wm->accel.x); frame->m_GaugeAccel[1]->SetValue(wm->accel.y); frame->m_GaugeAccel[2]->SetValue(wm->accel.z); + + 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); } frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z); - if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) frame->DoRecordA(true); else frame->DoRecordA(false); } } + // Otherwise remove the values + else + { + if (frame) + { + frame->m_GaugeAccel[0]->SetValue(0); + frame->m_GaugeAccel[1]->SetValue(0); + frame->m_GaugeAccel[2]->SetValue(0); + } + } + + + /* + * 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() { + handle_event(g_WiiMotesFromWiiUse[0]); + + // Read formatted data if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES)) { /* @@ -138,7 +199,7 @@ void ReadWiimote() { case WIIUSE_EVENT: /* a generic event occured */ - handle_event(g_WiiMotesFromWiiUse[i]); + //handle_event(g_WiiMotesFromWiiUse[i]); break; case WIIUSE_STATUS: diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 42ce0caa1b..0c2787832a 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -25,7 +25,10 @@ #include "Timer.h" #define EXCLUDEMAIN_H // Avoid certain declarations in main.h -#include "main.h" // Local +#include "EmuDefinitions.h" // Local +#include "wiimote_hid.h" +#include "main.h" +#include "Logging.h" #if defined(HAVE_WX) && HAVE_WX #include "ConfigDlg.h" #endif @@ -43,12 +46,21 @@ // ŻŻŻŻŻŻŻŻŻŻŻŻŻ SWiimoteInitialize g_WiimoteInitialize; +// General bool g_EmulatorRunning = false; bool g_FrameOpen = false; bool g_RealWiiMotePresent = false; bool g_RealWiiMoteInitialized = false; bool g_EmulatedWiiMoteInitialized = false; +// Settings +accel_cal g_accel; + +// Debugging +bool g_DebugAccelerometer = false; +bool g_DebugData = false; +bool g_DebugComm = true; + // Update speed int g_UpdateCounter = 0; double g_UpdateTime = 0; @@ -145,12 +157,11 @@ void DllConfig(HWND _hParent) #endif //Console::Open(); + DoInitialize(); g_FrameOpen = true; frame = new ConfigDialog(&win); - DoInitialize(); - frame->ShowModal(); //frame.Show(); @@ -258,12 +269,13 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _ LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel"); std::string Temp = ArrayToString(data, _Size); LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + //PanicAlert("Wiimote_ControlChannel"); } - if (!g_RealWiiMotePresent) + //if (!g_RealWiiMotePresent) WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); #if HAVE_WIIUSE - else + if (g_RealWiiMotePresent) WiiMoteReal::ControlChannel(_channelID, _pData, _Size); #endif @@ -290,12 +302,27 @@ extern "C" void Wiimote_Update() g_UpdateWriteScreen++; } + // This functions will send: + // Emulated Wiimote: Only data reports 0x30-0x37 + // Real Wiimote: Both data reports 0x30-0x37 and all other read reports if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) WiiMoteEmu::Update(); #if HAVE_WIIUSE else if (g_RealWiiMotePresent) WiiMoteReal::Update(); #endif + + // Debugging +#ifdef _WIN32 + if( GetAsyncKeyState(VK_HOME) && g_DebugComm ) g_DebugComm = false; + else if (GetAsyncKeyState(VK_HOME) && !g_DebugComm ) g_DebugComm = true; + + if( GetAsyncKeyState(VK_PRIOR) && g_DebugData ) g_DebugData = false; + else if (GetAsyncKeyState(VK_PRIOR) && !g_DebugData ) g_DebugData = true; + + if( GetAsyncKeyState(VK_NEXT) && g_DebugAccelerometer ) g_DebugAccelerometer = false; + else if (GetAsyncKeyState(VK_NEXT) && !g_DebugAccelerometer ) g_DebugAccelerometer = true; +#endif } extern "C" unsigned int Wiimote_GetAttachedControllers() @@ -309,6 +336,225 @@ extern "C" unsigned int Wiimote_GetAttachedControllers() // Supporting functions //****************************************************************************** +void ReadDebugging(bool Emu, const void* _pData) +{ + // + const u8* data = (const u8*)_pData; + + int size; + bool DataReport = false; + std::string Name; + switch(data[1]) + { + case WM_STATUS_REPORT: // 0x20 + size = sizeof(wm_status_report); + Name = "WM_STATUS_REPORT"; + { + wm_status_report* pStatus = (wm_status_report*)(data + 2); + Console::Print("" + "Extension Controller: %i\n" + "Speaker enabled: %i\n" + "IR camera enabled: %i\n" + "LED 1: %i\n" + "LED 2: %i\n" + "LED 3: %i\n" + "LED 4: %i\n" + "Battery low: %i\n\n", + pStatus->extension, + pStatus->speaker, + pStatus->ir, + (pStatus->leds >> 0), + (pStatus->leds >> 1), + (pStatus->leds >> 2), + (pStatus->leds >> 3), + pStatus->battery_low + ); + } + break; + case WM_READ_DATA_REPLY: // 0x21 + size = sizeof(wm_read_data_reply); + Name = "REPLY"; + // Pick up accelerometer neutral values + if (data[5] == 0x00 && data[6] == 0x10) + { + g_accel.cal_zero.x = data[13]; + g_accel.cal_zero.y = data[14]; + g_accel.cal_zero.z = data[15]; + + g_accel.cal_g.x = data[17] - data[13]; + g_accel.cal_g.y = data[18] - data[14]; + g_accel.cal_g.z = data[19] - data[15]; + + //Console::Print("Got neutral values: %i %i %i\n", + // g_accel.cal_zero.x, g_accel.cal_zero.y, g_accel.cal_zero.z + g_accel.cal_g.z); + } + break; + case WM_WRITE_DATA_REPLY: // 0x22 + size = sizeof(wm_acknowledge) - 1; + Name = "REPLY"; + break; + case WM_REPORT_CORE: // 0x30-0x37 + size = sizeof(wm_report_core); + DataReport = true; + break; + case WM_REPORT_CORE_ACCEL: + size = sizeof(wm_report_core_accel); + DataReport = true; + break; + case WM_REPORT_CORE_EXT8: + size = sizeof(wm_report_core_accel_ir12); + DataReport = true; + break; + case WM_REPORT_CORE_ACCEL_IR12: + size = sizeof(wm_report_core_accel_ir12); + DataReport = true; + break; + case WM_REPORT_CORE_EXT19: + size = sizeof(wm_report_core_accel_ext16); + DataReport = true; + break; + case WM_REPORT_CORE_ACCEL_EXT16: + size = sizeof(wm_report_core_accel_ext16); + DataReport = true; + break; + case WM_REPORT_CORE_IR10_EXT9: + size = sizeof(wm_report_core_accel_ir10_ext6); + DataReport = true; + break; + case WM_REPORT_CORE_ACCEL_IR10_EXT6: + size = sizeof(wm_report_core_accel_ir10_ext6); + DataReport = true; + break; + default: + PanicAlert("%s ReadDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]); + return; + } + + if (!DataReport && g_DebugComm) + { + std::string Temp = ArrayToString(data, size + 2, 0, 30); + //LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + Console::Print("Read[%s] %s: %s\n", (Emu ? "Emu" : "Real"), Name.c_str(), Temp.c_str()); // No timestamp + //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp + } + + if (DataReport && g_DebugData) + { + std::string Temp = ArrayToString(data, size + 2, 0, 30); + //LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + + // Format accelerometer values + if(Temp.length() > 20) + { + std::string Tmp1 = Temp.substr(0, 12); + std::string Tmp2 = Temp.substr(20, (Temp.length() - 20)); + std::string Temp = Tmp1 + StringFromFormat("%03i %03i %03i", data[4], data[5], data[6]) + Tmp2; + } + + Console::Print("Read[%s]: %s\n", (Emu ? "Emu" : "Real"), Temp.c_str()); // No timestamp + //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp + } + if(g_DebugAccelerometer) + { + // Accelerometer only + Console::ClearScreen(); + Console::Print("Accel x, y, z: %03u %03u %03u\n", data[4], data[5], data[6]); + } +} + + +void InterruptDebugging(bool Emu, const void* _pData) +{ + // + const u8* data = (const u8*)_pData; + + if (g_DebugComm) Console::Print("Write[%s] ", (Emu ? "Emu" : "Real")); + + int size; + switch(data[1]) + { + case 0x10: + size = 4; // I don't know the size + if (g_DebugComm) Console::Print("0x10"); + break; + case WM_LEDS: // 0x11 + size = sizeof(wm_leds); + if (g_DebugComm) Console::Print("WM_LEDS"); + break; + case WM_DATA_REPORTING: // 0x12 + size = sizeof(wm_data_reporting); + if (g_DebugComm) Console::Print("WM_DATA_REPORTING"); + break; + case WM_REQUEST_STATUS: // 0x15 + size = sizeof(wm_request_status); + if (g_DebugComm) Console::Print("WM_REQUEST_STATUS"); + break; + case WM_WRITE_DATA: // 0x16 + if (g_DebugComm) Console::Print("WM_WRITE_DATA"); + size = sizeof(wm_write_data); + switch(data[2] >> 0x01) + { + case WM_SPACE_EEPROM: + if (g_DebugComm) Console::Print(" REG_EEPROM"); break; + case WM_SPACE_REGS1: + case WM_SPACE_REGS2: + switch(data[3]) + { + case 0xa2: + if (g_DebugComm) Console::Print(" REG_SPEAKER"); break; + case 0xa4: + if (g_DebugComm) Console::Print(" REG_EXT"); break; + case 0xb0: + if (g_DebugComm) Console::Print(" REG_IR"); break; + } + break; + } + break; + case WM_READ_DATA: // 0x17 + size = sizeof(wm_read_data); + if (g_DebugComm) Console::Print("WM_READ_DATA"); + switch(data[2] >> 0x01) + { + case WM_SPACE_EEPROM: + if (g_DebugComm) Console::Print(" REG_EEPROM"); break; + case WM_SPACE_REGS1: + case WM_SPACE_REGS2: + switch(data[3]) + { + case 0xa2: + if (g_DebugComm) Console::Print(" REG_SPEAKER"); break; + case 0xa4: + if (g_DebugComm) Console::Print(" REG_EXT"); break; + case 0xb0: + if (g_DebugComm) Console::Print(" REG_IR"); break; + } + break; + } + break; + case WM_IR_PIXEL_CLOCK: // 0x13 + case WM_IR_LOGIC: // 0x1a + if (g_DebugComm) Console::Print("WM_IR"); + size = 1; + break; + case WM_SPEAKER_ENABLE: // 0x14 + case WM_SPEAKER_MUTE: + if (g_DebugComm) Console::Print("WM_SPEAKER"); + size = 1; + break; + default: + size = 15; + Console::Print("%s InterruptDebugging: Unknown channel 0x%02x", (Emu ? "Emu" : "Real"), data[1]); + break; + } + if (g_DebugComm) + { + std::string Temp = ArrayToString(data, size + 2, 0, 30); + //LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); + Console::Print(": %s\n", Temp.c_str()); // No timestamp + //Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp + } +} + /* Returns a timestamp with three decimals for precise time comparisons. The return format is of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning @@ -376,12 +622,13 @@ void DoInitialize() // ---------------------------------------- // Debugging window // ---------- - /*Console::Open(100, 750, "Wiimote"); // give room for 20 rows - Console::Print("Wiimote console opened\n"); + /*Console::Open(130, 1000, "Wiimote"); // give room for 20 rows + Console::Print("\n\n\nWiimote console opened\n"); // Move window //MoveWindow(Console::GetHwnd(), 0,400, 100*8,10*14, true); // small window - MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window*/ + //MoveWindow(Console::GetHwnd(), 400,0, 100*8,70*14, true); // big window + MoveWindow(Console::GetHwnd(), 200,0, 130*8,70*14, true); // big wide window*/ // --------------- // Load config settings diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.h b/Source/Plugins/Plugin_Wiimote/Src/main.h index c9bebf2f39..1374cc2e57 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.h +++ b/Source/Plugins/Plugin_Wiimote/Src/main.h @@ -40,6 +40,8 @@ void DoInitialize(); double GetDoubleTime(); int GetUpdateRate(); +void InterruptDebugging(bool Emu, const void* _pData); +void ReadDebugging(bool Emu, const void* _pData); // Movement recording #define RECORDING_ROWS 15 @@ -58,12 +60,21 @@ struct SRecordingAll }; #ifndef EXCLUDEMAIN_H + // General extern bool g_EmulatorRunning; extern bool g_FrameOpen; extern bool g_RealWiiMotePresent; extern bool g_RealWiiMoteInitialized; extern bool g_EmulatedWiiMoteInitialized; + // Settings + extern accel_cal g_accel; + + // Debugging + extern bool g_DebugAccelerometer; + extern bool g_DebugData; + extern bool g_DebugComm; + // Update speed extern int g_UpdateCounter; extern double g_UpdateTime; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index b792591632..eee012a6b3 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -25,7 +25,7 @@ #pragma pack(push, 1) #endif -//source: HID_010_SPC_PFL/1.0 (official HID specification) +// Source: HID_010_SPC_PFL/1.0 (official HID specification) struct hid_packet { u8 param : 4; @@ -225,6 +225,10 @@ struct wm_classic_extension wm_cc_5 b2; // byte 5 }; +//****************************************************************************** +// Data reports +//****************************************************************************** + #define WM_REPORT_CORE 0x30 struct wm_report_core { wm_core c; @@ -282,8 +286,23 @@ struct wm_report_ext21 #define WM_SPEAKER_MUTE 0x19 +//****************************************************************************** +// Custom structs +//****************************************************************************** + +/** + * @struct accel_t + * @brief Accelerometer struct. For any device with an accelerometer. + */ +struct accel_cal +{ + wm_accel cal_zero; /**< zero calibration */ + wm_accel cal_g; /**< 1g difference around 0cal */ +}; + + #if defined(_MSC_VER) -#pragma pack(pop) + #pragma pack(pop) #endif #endif //WIIMOTE_HID_H diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index 2bb79af4c2..4ce422786b 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -29,6 +29,7 @@ #include "Thread.h" #include "StringUtil.h" #include "ConsoleWindow.h" +#include "Timer.h" #include "wiimote_hid.h" #include "main.h" @@ -70,6 +71,8 @@ CWiiMote* g_WiiMotes[MAX_WIIMOTES]; bool g_Shutdown = false; bool g_LocalThread = true; bool g_MotionSensing = false; +u64 g_UpdateTime = 0; +int g_UpdateCounter = 0; //****************************************************************************** // Probably this class should be in its own file @@ -107,7 +110,7 @@ virtual ~CWiiMote() ////////////////////////////////////////// -// Send raw HID data from the core to wiimote +// Queue raw HID data from the core to the wiimote // --------------- void SendData(u16 _channelID, const u8* _pData, u32 _Size) { @@ -116,8 +119,12 @@ void SendData(u16 _channelID, const u8* _pData, u32 _Size) m_pCriticalSection->Enter(); { SEvent WriteEvent; - memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); + memcpy(WriteEvent.m_PayLoad, _pData + 1, _Size - 1); m_EventWriteQueue.push(WriteEvent); + + // Debugging + //std::string Temp = ArrayToString(WriteEvent.m_PayLoad, 28, 0, 30); + //Console::Print("Wiimote Write:\n%s\n", Temp.c_str()); } m_pCriticalSection->Leave(); } @@ -125,9 +132,7 @@ void SendData(u16 _channelID, const u8* _pData, u32 _Size) ////////////////////////////////////////////////// -/* Read data from wiimote (but don't send it to the core, just filter and queue). If we are not currently - using the real Wiimote we only allow it to receive data mode changes, but don't ask for any data in - return */ +/* Read and write data to the Wiimote */ // --------------- void ReadData() { @@ -136,45 +141,62 @@ void ReadData() // Send data to the Wiimote if (!m_EventWriteQueue.empty()) { - Console::Print("Writing data to the Wiimote\n"); + //Console::Print("Writing data to the Wiimote\n"); SEvent& rEvent = m_EventWriteQueue.front(); wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); m_EventWriteQueue.pop(); + +#ifdef _WIN32 + // Debugging. Move the data one step to the right first. + memcpy(rEvent.m_PayLoad + 1, rEvent.m_PayLoad, sizeof(rEvent.m_PayLoad) - 1); + rEvent.m_PayLoad[0] = 0xa2; + InterruptDebugging(false, rEvent.m_PayLoad); +#endif } m_pCriticalSection->Leave(); - // Don't queue up data if we are not using the real Wiimote - if(g_Config.bUseRealWiimote) - if (wiiuse_io_read(m_pWiiMote)) + // Read data from wiimote (but don't send it to the core, just filter and queue) + if (wiiuse_io_read(m_pWiiMote)) + { + const byte* pBuffer = m_pWiiMote->event_buf; + + // Check if we have a channel (connection) if so save the data... + if (m_channelID > 0) { - const byte* pBuffer = m_pWiiMote->event_buf; + m_pCriticalSection->Enter(); - // Check if we have a channel (connection) if so save the data... - if (m_channelID > 0) + // Filter out data reports + if (pBuffer[0] >= 0x30) { - m_pCriticalSection->Enter(); + // Copy Buffer to LastReport + memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD); + m_LastReportValid = true; - // Filter out reports - if (pBuffer[0] >= 0x30) - { - // Copy Buffer to LastReport - memcpy(m_LastReport.m_PayLoad, pBuffer, MAX_PAYLOAD); - m_LastReportValid = true; - } - else - { - // Copy Buffer to ImportantEvent - SEvent ImportantEvent; - memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD); - m_EventReadQueue.push(ImportantEvent); - } - m_pCriticalSection->Leave(); + // Check if the data reporting mode is okay + //if (g_EmulatorRunning && pBuffer[0] != WiiMoteEmu::g_ReportingMode) + // SetDataReportingMode(); } + else + { + // Copy Buffer to ImportantEvent + SEvent ImportantEvent; + memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD); - //std::string Temp = ArrayToString(pBuffer, sizeof(pBuffer), 0); - //Console::Print("Data:\n%s\n", Temp.c_str()); + // Put it in the read queue right away + m_EventReadQueue.push(ImportantEvent); + } + m_pCriticalSection->Leave(); } +#ifdef _WIN32 + /* Debugging + //if(GetAsyncKeyState('V')) + { + std::string Temp = ArrayToString(pBuffer, 20, 0, 30); + Console::Print("Data: %s\n", Temp.c_str()); + } */ +#endif + } }; ///////////////////// @@ -189,12 +211,12 @@ void Update() if (m_EventReadQueue.empty()) { - // Send the same data as last time + // Send the data report if (m_LastReportValid) SendEvent(m_LastReport); } else { - // Send all the new data we have collected + // Send a 0x20, 0x21 or 0x22 report SendEvent(m_EventReadQueue.front()); m_EventReadQueue.pop(); } @@ -203,6 +225,19 @@ void Update() }; ///////////////////// + +////////////////////////////////////////// +// Clear events +// --------------- +void ClearEvents() +{ + while (!m_EventReadQueue.empty()) + m_EventReadQueue.pop(); + while (!m_EventWriteQueue.empty()) + m_EventWriteQueue.pop(); +} +///////////////////// + private: struct SEvent @@ -217,23 +252,22 @@ private: u8 m_WiimoteNumber; // Just for debugging u16 m_channelID; - + CEventQueue m_EventReadQueue; // Read from Wiimote + CEventQueue m_EventWriteQueue; // Write to Wiimote Common::CriticalSection* m_pCriticalSection; - CEventQueue m_EventReadQueue; - CEventQueue m_EventWriteQueue; bool m_LastReportValid; SEvent m_LastReport; wiimote_t* m_pWiiMote; // This is g_WiiMotesFromWiiUse[] ////////////////////////////////////////// -// Send event +// Send queued data to the core // --------------- void SendEvent(SEvent& _rEvent) { // We don't have an answer channel if (m_channelID == 0) return; - // Check event buffer; + // Check event buffer u8 Buffer[1024]; u32 Offset = 0; hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset); @@ -241,19 +275,15 @@ void SendEvent(SEvent& _rEvent) pHidHeader->type = HID_TYPE_DATA; pHidHeader->param = HID_PARAM_INPUT; + // Create the buffer memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD); Offset += MAX_PAYLOAD; - /* Debugging - //if(GetAsyncKeyState('V')) - { - std::string Temp = ArrayToString(Buffer, Offset, 0, 30); - Console::ClearScreen(); - Console::Print("Reporting Mode: 0x%02x\n", WiiMoteEmu::g_ReportingMode); - Console::Print("DataFrame: %s\n", Temp.c_str()); - }*/ + // Send it + g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); - g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); + // Debugging + ReadDebugging(false, Buffer); } ///////////////////// }; @@ -264,6 +294,113 @@ void SendEvent(SEvent& _rEvent) // Function Definitions //****************************************************************************** +void SendAcc(u8 _ReportID) +{ + byte DataAcc[MAX_PAYLOAD]; + + DataAcc[0] = 0x22; // Report 0x12 + DataAcc[1] = 0x00; // Core buttons + DataAcc[2] = 0x00; + DataAcc[3] = _ReportID; // Reporting mode + + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)DataAcc, MAX_PAYLOAD); + + std::string Temp = ArrayToString(DataAcc, 28, 0, 30); + Console::Print("SendAcc: %s\n", Temp.c_str()); + + //22 00 00 _reportID 00 +} + +// Clear any potential queued events +void ClearEvents() +{ + for (int i = 0; i < g_NumberOfWiiMotes; i++) + g_WiiMotes[i]->ClearEvents(); +} + +// Update the data reporting mode if we are switching between the emulated and the real Wiimote +void SetDataReportingMode(u8 ReportingMode) +{ + // Don't allow this to run to often + if (Common::Timer::GetTimeSinceJan1970() == g_UpdateTime) return; + + // Save the time + g_UpdateTime = Common::Timer::GetTimeSinceJan1970(); + + // Decide if we should we use custom values + if (ReportingMode == 0) ReportingMode = WiiMoteEmu::g_ReportingMode; + + // Just in case this should happen + if (ReportingMode == 0) ReportingMode = 0x30; + + // Shortcut + wiimote_t* wm = WiiMoteReal::g_WiiMotesFromWiiUse[0]; + + switch(ReportingMode) // See Wiimote_Update() + { + case WM_REPORT_CORE: + wiiuse_motion_sensing(wm, 0); + wiiuse_set_ir(wm, 0); + break; + case WM_REPORT_CORE_ACCEL: + wiiuse_motion_sensing(wm, 1); + wiiuse_set_ir(wm, 0); + break; + case WM_REPORT_CORE_ACCEL_IR12: + wiiuse_motion_sensing(wm, 1); + wiiuse_set_ir(wm, 1); + break; + case WM_REPORT_CORE_ACCEL_EXT16: + wiiuse_motion_sensing(wm, 1); + wiiuse_set_ir(wm, 0); + break; + case WM_REPORT_CORE_ACCEL_IR10_EXT6: + wiiuse_motion_sensing(wm, 1); + wiiuse_set_ir(wm, 1); + break; + } + + /* On occasion something in this function caused an instant reboot of Windows XP SP3 + with Bluesoleil 6. So I'm trying to use the API functions to reach the same goal. */ + /*byte DataReporting[MAX_PAYLOAD]; + byte IR0[MAX_PAYLOAD]; + byte IR1[MAX_PAYLOAD]; + + DataReporting[0] = 0x12; // Report 0x12 + DataReporting[1] = 0x06; // Continuous reporting + DataReporting[2] = ReportingMode; // Reporting mode + + IR0[0] = 0x13; // Report 0x13 + if (IR) IR0[1] = 0x06; else IR0[1] = 0x02; + IR1[0] = 0x1a; // Report 0x1a + if (IR) IR1[1] = 0x06; else IR1[1] = 0x02; + + // Calibrate IR + static const u8 IR_0[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01, + 0x01 }; + static const u8 IR_1[] = { 0x16, 0x04, 0xb0, 0x00, 0x00, 0x09, + 0x02, 0x00, 0x00, 0x71, 0x01, 0x00, 0xaa, 0x00, 0x64 }; + static const u8 IR_2[] = { 0x16, 0x04, 0xb0, 0x00, 0x1a, 0x02, + 0x63, 0x03 }; + static const u8 IR_3[] = { 0x16, 0x04, 0xb0, 0x00, 0x33, 0x01, + 0x03 }; + static const u8 IR_4[] = { 0x16, 0x04, 0xb0, 0x00, 0x30, 0x01, + 0x08 }; + + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)DataReporting, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR0, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR1, MAX_PAYLOAD); + + if (IR) + { + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_0, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_1, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_2, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_3, MAX_PAYLOAD); + wiiuse_io_write(WiiMoteReal::g_WiiMotesFromWiiUse[0], (byte*)IR_4, MAX_PAYLOAD); + }*/ +} + // Flash lights, and if connecting, also rumble void FlashLights(bool Connect) { @@ -281,27 +418,44 @@ void FlashLights(bool Connect) int Initialize() { + // Return if already initialized if (g_RealWiiMoteInitialized) return g_NumberOfWiiMotes; + // Clear the wiimote classes memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); // Call Wiiuse.dll g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); - if (g_NumberOfWiiMotes > 0) g_RealWiiMotePresent = true; + // Remove the wiiuse_poll() threshold + wiiuse_set_accel_threshold(g_WiiMotesFromWiiUse[0], 0); + // Update the global accelerometer neutral values + while(g_WiiMotesFromWiiUse[0]->accel_calib.cal_zero.x == 0) + {wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES);} + g_accel.cal_zero.x = g_WiiMotesFromWiiUse[0]->accel_calib.cal_zero.x; + g_accel.cal_zero.y = g_WiiMotesFromWiiUse[0]->accel_calib.cal_zero.y; + g_accel.cal_zero.z = g_WiiMotesFromWiiUse[0]->accel_calib.cal_zero.z; + g_accel.cal_g.x = g_WiiMotesFromWiiUse[0]->accel_calib.cal_g.x; + g_accel.cal_g.y = g_WiiMotesFromWiiUse[0]->accel_calib.cal_g.y; + g_accel.cal_g.z = g_WiiMotesFromWiiUse[0]->accel_calib.cal_g.z; + Console::Print("Got neutral values: %i %i %i\n", + g_accel.cal_zero.x, g_accel.cal_zero.y, g_accel.cal_zero.z + g_accel.cal_g.z); + + // Update the global extension settings + g_Config.bNunchuckConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_NUNCHUK); + g_Config.bClassicControllerConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_CLASSIC); + + if (g_NumberOfWiiMotes > 0) g_RealWiiMotePresent = true; Console::Print("Found No of Wiimotes: %i\n", g_NumberOfWiiMotes); - // For the status window + // If we are connecting from the config window without a game running we flash the lights if (!g_EmulatorRunning) { - // Do I need this? + // I don't seem to need wiiuse_connect() //int Connect = wiiuse_connect(g_WiiMotesFromWiiUse, MAX_WIIMOTES); - //Console::Print("Connected: %i\n", Connect); - - //wiiuse_set_timeout(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 500, 1000); - //wiiuse_set_flags(g_WiiMotesFromWiiUse[0], WIIUSE_CONTINUOUS, NULL); + //Console::Print("Connected: %i\n", Connect); FlashLights(true); } @@ -386,10 +540,8 @@ void Update() ////////////////////////////////// /* Continuously read the Wiimote status. However, the actual sending of data occurs in Update(). If we are - not currently using the real Wiimote we allow the separate ReadWiimote() function to run. Todo: Figure - out how to manually send the current data reporting mode to the real Wiimote so that we can entirely turn - off ReadData() (including wiiuse_io_write()) while we are not using the real wiimote. For example to risk - interrupting accelerometer recordings by a wiiuse_io_write(). */ + not currently using the real Wiimote we allow the separate ReadWiimote() function to run. Wo don't use + them at the same time to avoid a potential collision. */ // --------------- #ifdef _WIN32 DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) @@ -399,9 +551,9 @@ void Update() { while (!g_Shutdown) { - if(g_EmulatorRunning) + if(g_Config.bUseRealWiimote) for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData(); - if (!g_Config.bUseRealWiimote) + else ReadWiimote(); } return 0; diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h index efdf384fe9..130075a0b4 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h @@ -38,12 +38,18 @@ void Shutdown(void); void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size); void ControlChannel(u16 _channelID, const void* _pData, u32 _Size); void Update(); + +void SendAcc(u8 _ReportID); +void SetDataReportingMode(u8 ReportingMode = 0); +void ClearEvents(); void ReadWiimote(); #ifndef EXCLUDE_H extern wiimote_t** g_WiiMotesFromWiiUse; extern int g_NumberOfWiiMotes; extern bool g_MotionSensing; + extern u64 g_UpdateTime; + extern int g_UpdateCounter; #endif }; // WiiMoteReal