Wiimote: Fixed the switching between real and emulated wiimote, the reporting mode is now shared in real/emu dual mode, the accelerator neutral values are shared, the extension is somewhat shared but still doesn't support unplugging and reinserting the extension during gameplay in dual mode. Improved debugging, fixed a bug in movement recording, fixed a bug in report 0x21 eeprom reading so that the game reads the accelerator neutral values from it.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2048 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-01 13:01:50 +00:00
parent 529bf35d6a
commit 888465868d
17 changed files with 806 additions and 260 deletions

View File

@ -37,6 +37,7 @@ struct Config
// Real Wiimote // Real Wiimote
bool bConnectRealWiimote, bUseRealWiimote, bUpdateRealWiimote; bool bConnectRealWiimote, bUseRealWiimote, bUpdateRealWiimote;
int iAccNeutralX, iAccNeutralY, iAccNeutralZ;
}; };
extern Config g_Config; extern Config g_Config;

View File

@ -25,6 +25,7 @@
#include "Timer.h" #include "Timer.h"
#include "wiimote_real.h" // Local #include "wiimote_real.h" // Local
#include "wiimote_hid.h"
#include "main.h" #include "main.h"
#include "ConfigDlg.h" #include "ConfigDlg.h"
#include "Config.h" #include "Config.h"
@ -547,12 +548,27 @@ void ConfigDialog::ConvertToString()
double Recordings = (double)m_vRecording.size(); double Recordings = (double)m_vRecording.size();
double Time = m_vRecording.at(m_vRecording.size() - 1).Time - m_vRecording.at(0).Time; double Time = m_vRecording.at(m_vRecording.size() - 1).Time - m_vRecording.at(0).Time;
int Rate = (int)(Recordings / 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)); m_RecordSpeed[m_iRecordTo]->SetValue(wxString::Format(wxT("%i"), Rate));
// 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(), "Time", TmpTime.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"); file.Save("WiimoteMovement.ini");
} }
@ -639,7 +655,7 @@ void ConfigDialog::DoRecordMovement(u8 _x, u8 _y, u8 _z)
{ {
if (!m_bRecording) return; if (!m_bRecording) return;
Console::Print("DoRecordMovement\n"); //Console::Print("DoRecordMovement\n");
SRecording Tmp; SRecording Tmp;
Tmp.x = _x; Tmp.x = _x;
@ -765,10 +781,13 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
break; break;
case ID_USE_REAL: case ID_USE_REAL:
g_Config.bUseRealWiimote = m_UseRealWiimote->IsChecked(); g_Config.bUseRealWiimote = m_UseRealWiimote->IsChecked();
//if(g_Config.bUseRealWiimote) WiiMoteReal::SetDataReportingMode();
if(g_Config.bUseRealWiimote) WiiMoteReal::ClearEvents();
break; break;
case ID_UPDATE_REAL: case ID_UPDATE_REAL:
g_Config.bUpdateRealWiimote = m_UpdateMeters->IsChecked(); g_Config.bUpdateRealWiimote = m_UpdateMeters->IsChecked();
break; break;
case IDC_RECORD + 1: case IDC_RECORD + 1:
case IDC_RECORD + 2: case IDC_RECORD + 2:
case IDC_RECORD + 3: case IDC_RECORD + 3:
@ -809,14 +828,26 @@ void ConfigDialog::UpdateGUI()
{ {
Console::Print("UpdateGUI: \n"); 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 /* 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
mean that the wiimote must be sent the current reporting mode and the channel ID after it 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 has been initialized. Functions for that are basically already in place so these two options
for that so that this option can be enabled during gameplay. */ could possibly be simplified to one option. */
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

@ -59,6 +59,7 @@
#include "StringUtil.h" // for ArrayToString #include "StringUtil.h" // for ArrayToString
#include "wiimote_hid.h" // Local #include "wiimote_hid.h" // Local
#include "main.h"
#include "EmuMain.h" #include "EmuMain.h"
#include "EmuSubroutines.h" #include "EmuSubroutines.h"
#include "EmuDefinitions.h" #include "EmuDefinitions.h"
@ -83,6 +84,9 @@ namespace WiiMoteEmu
//****************************************************************************** //******************************************************************************
// ===================================================
/* Update the data reporting mode */
// ----------------
void WmDataReporting(u16 _channelID, wm_data_reporting* dr) void WmDataReporting(u16 _channelID, wm_data_reporting* dr)
{ {
LOGV(WII_IPC_WIIMOTE, 0, "==========================================================="); 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, " 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, " All The Time: %x (not only on data change)", dr->all_the_time);
LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode); LOG(WII_IPC_WIIMOTE, " Mode: 0x%02x", dr->mode);
Console::Print("Data reporting mode: 0x%02x\n", dr->mode); Console::Print("Data reporting:\n");
Console::Print("Data reporting channel: 0x%04x\n", _channelID); 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_ReportingMode = dr->mode;
g_ReportingChannel = _channelID; g_ReportingChannel = _channelID;
@ -105,7 +112,7 @@ void WmDataReporting(u16 _channelID, wm_data_reporting* dr)
case WM_REPORT_CORE_ACCEL_IR10_EXT6: case WM_REPORT_CORE_ACCEL_IR10_EXT6:
break; break;
default: default:
PanicAlert("Wiimote: Unknown reporting mode 0x%x", dr->mode); PanicAlert("Wiimote: Unsupported reporting mode 0x%x", dr->mode);
} }
// WmSendAck(_channelID, WM_DATA_REPORTING); // WmSendAck(_channelID, WM_DATA_REPORTING);
@ -132,6 +139,9 @@ void SendReportCore(u16 _channelID)
LOGV(WII_IPC_WIIMOTE, 2, " SendReportCore()"); LOGV(WII_IPC_WIIMOTE, 2, " SendReportCore()");
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); 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, " Channel: %04x", _channelID);
LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); 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); 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, " SendReportCoreAccelIr12()");
LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); 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); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
// Debugging
ReadDebugging(true, DataFrame);
} }
// =================================================== // ===================================================
/* Case 0x35: Core Buttons and Accelerometer with 16 Extension Bytes */ /* 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, " Channel: %04x", _channelID);
LOGV(WII_IPC_WIIMOTE, 2, " Offset: %08x", Offset); 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); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
// Debugging
ReadDebugging(true, DataFrame);
} }
@ -279,15 +272,10 @@ void SendReportCoreAccelIr10Ext(u16 _channelID)
LOGV(WII_IPC_WIIMOTE, 2, " SendReportCoreAccelIr10Ext()"); 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); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
// Debugging
ReadDebugging(true, DataFrame);
} }

View File

@ -41,10 +41,10 @@ namespace WiiMoteEmu
// Definitions and variable declarations // Definitions and variable declarations
//****************************************************************************** //******************************************************************************
u8 g_Leds = 0x0; // 4 bits u8 g_Leds = 0x1; // 4 bits
u8 g_Speaker = 0x1; // 1 = on u8 g_Speaker = 0x1; // 1 = on
u8 g_SpeakerVoice = 0x1; // 1 = on u8 g_SpeakerVoice = 0x0; // 1 = on
u8 g_IR = 0x1; // 1 = on u8 g_IR = 0x0; // 1 = on
u8 g_Eeprom[WIIMOTE_EEPROM_SIZE]; u8 g_Eeprom[WIIMOTE_EEPROM_SIZE];
u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE]; u8 g_RegSpeaker[WIIMOTE_REG_SPEAKER_SIZE];

View File

@ -55,8 +55,16 @@ namespace WiiMoteEmu
#define wBOTTOM 625 #define wBOTTOM 625
#define wSENSOR_BAR_RADIUS 200 #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 // Registry sizes
#define WIIMOTE_EEPROM_SIZE (16*1024) #define WIIMOTE_EEPROM_SIZE (16*1024)
#define WIIMOTE_EEPROM_FREE_SIZE 0x16ff
#define WIIMOTE_REG_SPEAKER_SIZE 10 #define WIIMOTE_REG_SPEAKER_SIZE 10
#define WIIMOTE_REG_EXT_SIZE 0x100 #define WIIMOTE_REG_EXT_SIZE 0x100
#define WIIMOTE_REG_IR_SIZE 0x34 #define WIIMOTE_REG_IR_SIZE 0x34
@ -89,13 +97,13 @@ extern std::vector<wm_ackdelay> AckDelay;
extern wiimote_key g_ExtKey; // extension encryption key 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[] = { static const u8 EepromData_0[] = {
0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
0xA7, 0x74, 0xD3, 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0xA1, 0xAA, 0x8B, 0x99, 0xAE, 0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3,
0x9E, 0x78, 0x30, 0xA7, 0x74, 0xD3, 0x82, 0x82, 0x82, 0x82, 0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E,
0x82, 0x15, 0x9C, 0x9C, 0x9E, 0x38, 0x40, 0x3E, 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[] = { static const u8 EepromData_16D0[] = {

View File

@ -28,10 +28,10 @@
#include "StringUtil.h" // for ArrayToString() #include "StringUtil.h" // for ArrayToString()
#include "IniFile.h" #include "IniFile.h"
#include "main.h" // Local #include "EmuDefinitions.h" // Local
#include "main.h"
#include "wiimote_hid.h" #include "wiimote_hid.h"
#include "EmuSubroutines.h" #include "EmuSubroutines.h"
#include "EmuDefinitions.h"
#include "EmuMain.h" #include "EmuMain.h"
#include "Encryption.h" // for extension encryption #include "Encryption.h" // for extension encryption
#include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd #include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd
@ -149,8 +149,8 @@ void LoadRecordedMovements()
AsciiToHex(StrY.c_str(), TmpY); AsciiToHex(StrY.c_str(), TmpY);
AsciiToHex(StrZ.c_str(), TmpZ); AsciiToHex(StrZ.c_str(), TmpZ);
Tmp.x = (u8)TmpX; Tmp.x = (u8)TmpX;
Tmp.x = (u8)TmpY; Tmp.y = (u8)TmpY;
Tmp.x = (u8)TmpZ; Tmp.z = (u8)TmpZ;
// Go to next set of time values // Go to next set of time values
double Time = (double)atoi(TmpTime.substr(k, 5).c_str()); double Time = (double)atoi(TmpTime.substr(k, 5).c_str());
@ -186,12 +186,18 @@ void Initialize()
{ {
if (g_EmulatedWiiMoteInitialized) return; if (g_EmulatedWiiMoteInitialized) return;
// Write default Eeprom data
memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE); memset(g_Eeprom, 0, WIIMOTE_EEPROM_SIZE);
memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0)); memcpy(g_Eeprom, EepromData_0, sizeof(EepromData_0));
memcpy(g_Eeprom + 0x16D0, EepromData_16D0, sizeof(EepromData_16D0)); 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 /* Extension data for homebrew applications that use the 0x00000000 key. This
writes 0x0000 in encrypted form (0xfefe) to 0xfe in the extension register. */ 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)); memcpy(g_RegExt + 0xfa, classic_id, sizeof(classic_id));
} }
g_ReportingMode = 0;
g_EmulatedWiiMoteInitialized = true; g_EmulatedWiiMoteInitialized = true;
// Load pre-recorded movements // Load pre-recorded movements
LoadRecordedMovements(); 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? // I forgot what these were for?
// g_RegExt[0xfd] = 0x1e; // g_RegExt[0xfd] = 0x1e;
// g_RegExt[0xfc] = 0x9a; // g_RegExt[0xfc] = 0x9a;
@ -285,48 +299,11 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input"); LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_Input");
const u8* data = (const u8*)_pData; const u8* data = (const u8*)_pData;
// -----------------------------------------------------
/* Debugging. We have not yet decided how much of 'data' we will use, it's not determined /* 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. */ by sizeof(data). We have to determine it by looking at the data cases. */
// ----------------- InterruptDebugging(true, data);
/*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());*/
// -----------------------------------
hid_packet* hidp = (hid_packet*) data; hid_packet* hidp = (hid_packet*) data;
switch(hidp->type) switch(hidp->type)
{ {
case HID_TYPE_DATA: 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) //if((data[1] == WM_WRITE_DATA || data[1] == WM_READ_DATA)
// && data[3] == 0xa4) // && 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 //else
//{ //{
@ -413,7 +394,7 @@ void ControlChannel(u16 _channelID, const void* _pData, u32 _Size)
{ {
HidOutputReport(_channelID, (wm_report*)hidp->data); HidOutputReport(_channelID, (wm_report*)hidp->data);
//return handshake // Return handshake
u8 handshake = 0; u8 handshake = 0;
g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1); g_WiimoteInitialize.pWiimoteInput(_channelID, &handshake, 1);
} }

View File

@ -46,11 +46,8 @@
#include "StringUtil.h" #include "StringUtil.h"
#include "pluginspecs_wiimote.h" #include "pluginspecs_wiimote.h"
#include "main.h" // Local #include "EmuMain.h" // Local
#include "wiimote_hid.h"
#include "EmuMain.h"
#include "EmuSubroutines.h" #include "EmuSubroutines.h"
#include "EmuDefinitions.h"
#include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd #include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd
#include "Config.h" // for g_Config #include "Config.h" // for g_Config
///////////////////////////////// /////////////////////////////////
@ -141,7 +138,8 @@ void HidOutputReport(u16 _channelID, wm_report* sr) {
// =================================================== // ===================================================
/* Generate the right address for wm reports. */ /* Generate the right address for wm reports. */
// ---------------- // ----------------
int WriteWmReport(u8* dst, u8 channel) { int WriteWmReport(u8* dst, u8 channel)
{
u32 Offset = 0; u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(dst + Offset); hid_packet* pHidHeader = (hid_packet*)(dst + Offset);
Offset += sizeof(hid_packet); 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, " WMSendAck()");
LOGV(WII_IPC_WIIMOTE, 2, " Report ID: %02x", _reportID); 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()); //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. /* Debug. Write the report for extension registry writes.
if((_reportID == 0x16 || _reportID == 0x17) && ((address >> 16) & 0xfe) == 0xa4) 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); 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 /* Now we determine what address space we are reading from. Space 0 is Eeprom and
space 1 and 2 is the registers. */ space 1 and 2 is the registers. */
if(rd->space == 0) if(rd->space == WM_SPACE_EEPROM)
{ {
if (address + size > WIIMOTE_EEPROM_SIZE) if (address + size > WIIMOTE_EEPROM_SIZE)
{ {
PanicAlert("WmReadData: address + size out of bounds!"); PanicAlert("WmReadData: address + size out of bounds");
return; 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) 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; block = g_RegSpeaker;
blockSize = WIIMOTE_REG_SPEAKER_SIZE; blockSize = WIIMOTE_REG_SPEAKER_SIZE;
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: g_RegSpeaker"); 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()); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
//Console::Print("Read RegSpkr: Size %i Address %08x Offset %08x\nData %s\n", Console::Print("Read RegSpkr: Size %i Address %08x Offset %08x\nData %s\n",
// size, address, (address & 0xffff), Tmp.c_str()); size, address, (address & 0xffff), Tmp.c_str());*/
break; break;
case 0xA4: case 0xA4:
block = g_RegExt; block = g_RegExt;
blockSize = WIIMOTE_REG_EXT_SIZE; blockSize = WIIMOTE_REG_EXT_SIZE;
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa4: Read ExtReg ****************************"); 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()); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
//Console::Print("Read RegExt: Size %i Address %08x Offset %08x\nData %s\n", Console::Print("Read RegExt: Size %i Address %08x Offset %08x\nData %s\n",
// size, address, (address & 0xffff), Tmp.c_str()); size, address, (address & 0xffff), Tmp.c_str());*/
break; break;
case 0xB0: case 0xB0:
block = g_RegIr; block = g_RegIr;
blockSize = WIIMOTE_REG_IR_SIZE; blockSize = WIIMOTE_REG_IR_SIZE;
LOGV(WII_IPC_WIIMOTE, 0, " Case: 0xb0 g_RegIr"); 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()); //LOGV(WII_IPC_WIIMOTE, 0, " Data: %s", Temp.c_str());
//Console::Print("Read RegIR: Size %i Address %08x Offset %08x\nData %s\n", Console::Print("Read RegIR: Size %i Address %08x Offset %08x\nData %s\n",
// size, address, (address & 0xffff), Tmp.c_str()); size, address, (address & 0xffff), Tmp.c_str());*/
break; break;
default: default:
PanicAlert("WmWriteData: bad register block!"); 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 // 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; return;
} }
memcpy(g_Eeprom + address, wd->data, wd->size); 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 // Write to registers
else if(wd->size <= 16 && (wd->space == WM_SPACE_REGS1 || wd->space == WM_SPACE_REGS2)) 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; block = g_RegSpeaker;
blockSize = WIIMOTE_REG_SPEAKER_SIZE; blockSize = WIIMOTE_REG_SPEAKER_SIZE;
LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: RegSpeaker"); LOGV(WII_IPC_WIIMOTE, 0, " Case 0xa2: RegSpeaker");
//Console::Print("Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n", /*Console::Print("Write RegSpeaker: Size: %i, Address: %08x, Offset: %08x\n",
// wd->size, address, (address & 0xffff)); wd->size, address, (address & 0xffff));
//Console::Print("Data: %s\n", Temp.c_str()); Console::Print("Data: %s\n", Temp.c_str());*/
break; break;
case 0xA4: case 0xA4:
block = g_RegExt; // Extension Controller register block = g_RegExt; // Extension Controller register
@ -399,7 +404,6 @@ void WmWriteData(u16 _channelID, wm_write_data* wd)
return; return;
} }
// Remove for example 0xa40000 from the address // Remove for example 0xa40000 from the address
address &= 0xFFFF; address &= 0xFFFF;
@ -455,51 +459,70 @@ void SendReadDataReply(u16 _channelID, void* _Base, u16 _Address, u8 _Size)
{ {
LOGV(WII_IPC_WIIMOTE, 0, "========================================="); LOGV(WII_IPC_WIIMOTE, 0, "=========================================");
int dataOffset = 0; int dataOffset = 0;
const u8* data = (const u8*)_Base;
while (_Size > 0) while (_Size > 0)
{ {
u8 DataFrame[1024]; u8 DataFrame[1024];
u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY); u32 Offset = WriteWmReport(DataFrame, WM_READ_DATA_REPLY);
// Limit the size to 16 bytes
int copySize = _Size; int copySize = _Size;
if (copySize > 16) if (copySize > 16) copySize = 16;
{
copySize = 16;
}
// Connect pReply->data to the empty DataFrame
wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset); wm_read_data_reply* pReply = (wm_read_data_reply*)(DataFrame + Offset);
Offset += sizeof(wm_read_data_reply); Offset += sizeof(wm_read_data_reply);
pReply->buttons = 0; pReply->buttons = 0;
pReply->error = 0; pReply->error = 0;
pReply->size = (copySize - 1) & 0xF; pReply->size = (copySize - 1) & 0xf;
pReply->address = Common::swap16(_Address + dataOffset); pReply->address = Common::swap16(_Address + dataOffset);
// Write a pice of _Base to DataFrame
memcpy(pReply->data, data + dataOffset, copySize);
// Write a pice // Check if we have less than 16 bytes left to send
memcpy(pReply->data + dataOffset, _Base, copySize); if(copySize < 16)
if(copySize < 16) // check if we have less than 16 bytes left to send
{
memset(pReply->data + copySize, 0, 16 - copySize); memset(pReply->data + copySize, 0, 16 - copySize);
}
// Update DataOffset for the next loop
dataOffset += copySize; 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, " SendReadDataReply()");
LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons); LOG(WII_IPC_WIIMOTE, " Buttons: 0x%04x", pReply->buttons);
LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error); LOG(WII_IPC_WIIMOTE, " Error: 0x%x", pReply->error);
LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size); LOG(WII_IPC_WIIMOTE, " Size: 0x%x", pReply->size);
LOG(WII_IPC_WIIMOTE, " Address: 0x%04x", pReply->address); 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 // Send a piece
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
_Size -= copySize; _Size -= copySize;
// Debugging
ReadDebugging(true, DataFrame);
} }
if (_Size != 0) if (_Size != 0)
{
PanicAlert("WiiMote-Plugin: SendReadDataReply() failed"); PanicAlert("WiiMote-Plugin: SendReadDataReply() failed");
}
LOGV(WII_IPC_WIIMOTE, 0, "=========================================="); LOGV(WII_IPC_WIIMOTE, 0, "==========================================");
} }
// ================ // ================
@ -551,6 +574,9 @@ void WmRequestStatus(u16 _channelID, wm_request_status* rs)
g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset); g_WiimoteInitialize.pWiimoteInput(_channelID, DataFrame, Offset);
LOGV(WII_IPC_WIIMOTE, 0, "================================================="); LOGV(WII_IPC_WIIMOTE, 0, "=================================================");
// Debugging
ReadDebugging(true, DataFrame);
} }
} // WiiMoteEmu } // WiiMoteEmu

View File

@ -28,7 +28,7 @@
#include <string> #include <string>
#include "Common.h" // Common #include "Common.h" // Common
#include "main.h"
#include "wiimote_hid.h" // Local #include "wiimote_hid.h" // Local
#include "EmuDefinitions.h" #include "EmuDefinitions.h"
#include "Encryption.h" #include "Encryption.h"

View File

@ -48,74 +48,85 @@ namespace WiiMoteEmu
//****************************************************************************** //******************************************************************************
// ------------------------------------------ // ------------------------------------------
// Variables // Variables: 0 = Wiimote, 1 = Nunchuck
// ---------------- // ----------------
int g_RecordingPlaying = -1; int g_RecordingPlaying[2]; //g_RecordingPlaying[0] = -1; g_RecordingPlaying[1] = -1;
int g_RecordingCounter = 0; int g_RecordingCounter[2]; //g_RecordingCounter[0] = 0; g_RecordingCounter[1] = 0;
int g_RecordingPoint = 0; int g_RecordingPoint[2]; //g_RecordingPoint[0] = 0; g_RecordingPoint[1] = 0;
double g_RecordingStart = 0; double g_RecordingStart[2]; //g_RecordingStart[0] = 0; g_RecordingStart[1] = 0;
double g_RecordingCurrentTime = 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 // 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"); Console::Print("Empty\n\n");
return; return;
} }
// Return if the playback speed is unset // 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); Console::Print("PlaybackSpeed empty: %i\n\n", g_RecordingPlaying[Wm]);
g_RecordingPlaying = -1; g_RecordingPlaying[Wm] = -1;
return; return;
} }
// Get starting time // 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 // Get current time
g_RecordingCurrentTime = GetDoubleTime() - g_RecordingStart; g_RecordingCurrentTime[Wm] = GetDoubleTime() - g_RecordingStart[Wm];
// Modify the current time // 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 // Select reading
for (int i = 0; i < VRecording.at(g_RecordingPlaying).Recording.size(); i++) for (int i = 0; i < VRecording.at(g_RecordingPlaying[Wm]).Recording.size(); i++)
if (VRecording.at(g_RecordingPlaying).Recording.at(i).Time > g_RecordingCurrentTime) if (VRecording.at(g_RecordingPlaying[Wm]).Recording.at(i).Time > g_RecordingCurrentTime[Wm])
{ {
g_RecordingPoint = i; g_RecordingPoint[Wm] = i;
break; // Break loop break; // Break loop
} }
// Return if we are at the end of the list // Return if we are at the end of the list
if(g_RecordingCurrentTime >= if(g_RecordingCurrentTime[Wm] >=
VRecording.at(g_RecordingPlaying).Recording.at( VRecording.at(g_RecordingPlaying[Wm]).Recording.at(
VRecording.at(g_RecordingPlaying).Recording.size() - 1).Time) VRecording.at(g_RecordingPlaying[Wm]).Recording.size() - 1).Time)
{ {
g_RecordingCounter = 0; g_RecordingCounter[Wm] = 0;
g_RecordingPlaying = -1; g_RecordingPlaying[Wm] = -1;
g_RecordingStart = 0; g_RecordingStart[Wm] = 0;
g_RecordingCurrentTime = 0; g_RecordingCurrentTime[Wm] = 0;
Console::Print("End\n\n"); Console::Print("End\n\n");
return; return;
} }
// Update values // Update values
_x = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).x; _x = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).x;
_y = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).y; _y = VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).y;
_z = VRecording.at(g_RecordingPlaying).Recording.at(g_RecordingPoint).z; _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, if (g_DebugAccelerometer)
VRecording.at(g_RecordingPlaying).Recording.size(), g_RecordingPoint {
); 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 // 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 a = 1, b = 1, c = 2, d = -2; // for debugging
//int consoleDisplay = 0; //int consoleDisplay = 0;
int X = 0x84, Y = 0x84, Z = 0x9f; // neutral values u8 x, y, z;
u8 x = X, y = Y, z = Z;
int shake = -1, yhistsize = 15; // for the shake function int shake = -1, yhistsize = 15; // for the shake function
std::vector<u8> yhist(15); // for the tilt function std::vector<u8> yhist(15); // for the tilt function
void FillReportAcc(wm_accel& _acc) 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 #ifdef _WIN32
// ------------------------------------ // ------------------------------------
// Recorded movements // Recorded movements
// -------------- // --------------
// Check for a playback command // Check for a playback command
if(g_RecordingPlaying < 0) if(g_RecordingPlaying[0] < 0)
{ {
g_RecordingPlaying = RecordingCheckKeys(true); g_RecordingPlaying[0] = RecordingCheckKeys(true);
} }
else else
{ {
RecordingPlay(_acc.x, _acc.y, _acc.z); RecordingPlay(_acc.x, _acc.y, _acc.z, 0);
//Console::Print("X: %u\n", _acc.x); //Console::Print("X, Y, Z: %u %u %u\n", _acc.x, _acc.y, _acc.z);
return; if (_acc.x != 0 && _acc.y != 0 && _acc.z != 0) return;
} }
// --------------------- // ---------------------
@ -326,7 +339,7 @@ void FillReportAcc(wm_accel& _acc)
y = Y; y = Y;
shake = -1; shake = -1;
} }
else // the default Y and Z if nothing is pressed else // the default Z if nothing is pressed
{ {
z = Z; 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) void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
{ {
/* See description above */ /* See description above */
@ -596,7 +611,7 @@ void FillReportIRBasic(wm_ir_basic& _ir0, wm_ir_basic& _ir1)
// ---------------------------- // ----------------------------
// 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))
@ -617,7 +632,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)
@ -644,13 +659,13 @@ void FillReportExtension(wm_extension& _ext)
// Recorded movements // Recorded movements
// -------------- // --------------
// Check for a playback command // Check for a playback command
if(g_RecordingPlaying < 0) if(g_RecordingPlaying[1] < 0)
{ {
g_RecordingPlaying = RecordingCheckKeys(false); g_RecordingPlaying[1] = RecordingCheckKeys(false);
} }
else else
{ {
RecordingPlay(_ext.ax, _ext.ay, _ext.az); RecordingPlay(_ext.ax, _ext.ay, _ext.az, 1);
//Console::Print("X: %u\n", _acc.x); //Console::Print("X: %u\n", _acc.x);
return; return;
} }

View File

@ -26,8 +26,11 @@
#include "ConsoleWindow.h" // Common #include "ConsoleWindow.h" // Common
#include "StringUtil.h" #include "StringUtil.h"
#include "Timer.h"
#include "wiimote_real.h" // Local #include "wiimote_real.h" // Local
#include "wiimote_hid.h"
#include "EmuDefinitions.h"
#include "main.h" #include "main.h"
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h" #include "ConfigDlg.h"
@ -54,7 +57,7 @@ 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");
@ -76,7 +79,6 @@ void handle_event(struct wiimote_t* wm)
wiiuse_motion_sensing(wm, 0); wiiuse_motion_sensing(wm, 0);
g_MotionSensing = false; g_MotionSensing = false;
} }
/* /*
* Pressing plus will tell the wiimote we are interested in movement. * Pressing plus will tell the wiimote we are interested in movement.
*/ */
@ -86,23 +88,35 @@ void handle_event(struct wiimote_t* wm)
g_MotionSensing = true; 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 the accelerometer is turned on then print angles */
if (WIIUSE_USING_ACC(wm)) if (WIIUSE_USING_ACC(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\n", wm->accel.x, wm->accel.y, wm->accel.z);
//Console::Print("%s", Tmp.c_str());
if(frame) if(frame)
{ {
if(g_Config.bUpdateRealWiimote) 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[0]->SetValue(wm->orient.roll + 180);
frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180); frame->m_GaugeRoll[1]->SetValue(wm->orient.pitch + 180);
@ -113,18 +127,65 @@ void handle_event(struct wiimote_t* wm)
frame->m_GaugeAccel[0]->SetValue(wm->accel.x); frame->m_GaugeAccel[0]->SetValue(wm->accel.x);
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);
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); frame->DoRecordMovement(wm->accel.x, wm->accel.y, wm->accel.z);
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);
} }
} }
// 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() void ReadWiimote()
{ {
handle_event(g_WiiMotesFromWiiUse[0]);
// Read formatted data
if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES)) if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES))
{ {
/* /*
@ -138,7 +199,7 @@ void ReadWiimote()
{ {
case WIIUSE_EVENT: case WIIUSE_EVENT:
/* a generic event occured */ /* a generic event occured */
handle_event(g_WiiMotesFromWiiUse[i]); //handle_event(g_WiiMotesFromWiiUse[i]);
break; break;
case WIIUSE_STATUS: case WIIUSE_STATUS:

View File

@ -25,7 +25,10 @@
#include "Timer.h" #include "Timer.h"
#define EXCLUDEMAIN_H // Avoid certain declarations in main.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 #if defined(HAVE_WX) && HAVE_WX
#include "ConfigDlg.h" #include "ConfigDlg.h"
#endif #endif
@ -43,12 +46,21 @@
// ¯¯¯¯¯¯¯¯¯¯¯¯¯ // ¯¯¯¯¯¯¯¯¯¯¯¯¯
SWiimoteInitialize g_WiimoteInitialize; SWiimoteInitialize g_WiimoteInitialize;
// General
bool g_EmulatorRunning = false; bool g_EmulatorRunning = false;
bool g_FrameOpen = false; bool g_FrameOpen = false;
bool g_RealWiiMotePresent = false; bool g_RealWiiMotePresent = false;
bool g_RealWiiMoteInitialized = false; bool g_RealWiiMoteInitialized = false;
bool g_EmulatedWiiMoteInitialized = 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 // Update speed
int g_UpdateCounter = 0; int g_UpdateCounter = 0;
double g_UpdateTime = 0; double g_UpdateTime = 0;
@ -145,12 +157,11 @@ void DllConfig(HWND _hParent)
#endif #endif
//Console::Open(); //Console::Open();
DoInitialize();
g_FrameOpen = true; g_FrameOpen = true;
frame = new ConfigDialog(&win); frame = new ConfigDialog(&win);
DoInitialize();
frame->ShowModal(); frame->ShowModal();
//frame.Show(); //frame.Show();
@ -258,12 +269,13 @@ extern "C" void Wiimote_ControlChannel(u16 _channelID, const void* _pData, u32 _
LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel"); LOGV(WII_IPC_WIIMOTE, 3, "Wiimote_ControlChannel");
std::string Temp = ArrayToString(data, _Size); std::string Temp = ArrayToString(data, _Size);
LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str()); LOGV(WII_IPC_WIIMOTE, 3, " Data: %s", Temp.c_str());
//PanicAlert("Wiimote_ControlChannel");
} }
if (!g_RealWiiMotePresent) //if (!g_RealWiiMotePresent)
WiiMoteEmu::ControlChannel(_channelID, _pData, _Size); WiiMoteEmu::ControlChannel(_channelID, _pData, _Size);
#if HAVE_WIIUSE #if HAVE_WIIUSE
else if (g_RealWiiMotePresent)
WiiMoteReal::ControlChannel(_channelID, _pData, _Size); WiiMoteReal::ControlChannel(_channelID, _pData, _Size);
#endif #endif
@ -290,12 +302,27 @@ extern "C" void Wiimote_Update()
g_UpdateWriteScreen++; 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) if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent)
WiiMoteEmu::Update(); WiiMoteEmu::Update();
#if HAVE_WIIUSE #if HAVE_WIIUSE
else if (g_RealWiiMotePresent) else if (g_RealWiiMotePresent)
WiiMoteReal::Update(); WiiMoteReal::Update();
#endif #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() extern "C" unsigned int Wiimote_GetAttachedControllers()
@ -309,6 +336,225 @@ extern "C" unsigned int Wiimote_GetAttachedControllers()
// Supporting functions // 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 /* 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 of the form seconds.milleseconds for example 1234.123. The leding seconds have no particular meaning
@ -376,12 +622,13 @@ void DoInitialize()
// ---------------------------------------- // ----------------------------------------
// Debugging window // Debugging window
// ---------- // ----------
/*Console::Open(100, 750, "Wiimote"); // give room for 20 rows /*Console::Open(130, 1000, "Wiimote"); // give room for 20 rows
Console::Print("Wiimote console opened\n"); Console::Print("\n\n\nWiimote console opened\n");
// Move window // Move window
//MoveWindow(Console::GetHwnd(), 0,400, 100*8,10*14, true); // small 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 // Load config settings

View File

@ -40,6 +40,8 @@
void DoInitialize(); void DoInitialize();
double GetDoubleTime(); double GetDoubleTime();
int GetUpdateRate(); int GetUpdateRate();
void InterruptDebugging(bool Emu, const void* _pData);
void ReadDebugging(bool Emu, const void* _pData);
// Movement recording // Movement recording
#define RECORDING_ROWS 15 #define RECORDING_ROWS 15
@ -58,12 +60,21 @@ struct SRecordingAll
}; };
#ifndef EXCLUDEMAIN_H #ifndef EXCLUDEMAIN_H
// General
extern bool g_EmulatorRunning; extern bool g_EmulatorRunning;
extern bool g_FrameOpen; extern bool g_FrameOpen;
extern bool g_RealWiiMotePresent; extern bool g_RealWiiMotePresent;
extern bool g_RealWiiMoteInitialized; extern bool g_RealWiiMoteInitialized;
extern bool g_EmulatedWiiMoteInitialized; 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 // Update speed
extern int g_UpdateCounter; extern int g_UpdateCounter;
extern double g_UpdateTime; extern double g_UpdateTime;

View File

@ -25,7 +25,7 @@
#pragma pack(push, 1) #pragma pack(push, 1)
#endif #endif
//source: HID_010_SPC_PFL/1.0 (official HID specification) // Source: HID_010_SPC_PFL/1.0 (official HID specification)
struct hid_packet { struct hid_packet {
u8 param : 4; u8 param : 4;
@ -225,6 +225,10 @@ struct wm_classic_extension
wm_cc_5 b2; // byte 5 wm_cc_5 b2; // byte 5
}; };
//******************************************************************************
// Data reports
//******************************************************************************
#define WM_REPORT_CORE 0x30 #define WM_REPORT_CORE 0x30
struct wm_report_core { struct wm_report_core {
wm_core c; wm_core c;
@ -282,8 +286,23 @@ struct wm_report_ext21
#define WM_SPEAKER_MUTE 0x19 #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) #if defined(_MSC_VER)
#pragma pack(pop) #pragma pack(pop)
#endif #endif
#endif //WIIMOTE_HID_H #endif //WIIMOTE_HID_H

View File

@ -29,6 +29,7 @@
#include "Thread.h" #include "Thread.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "ConsoleWindow.h" #include "ConsoleWindow.h"
#include "Timer.h"
#include "wiimote_hid.h" #include "wiimote_hid.h"
#include "main.h" #include "main.h"
@ -70,6 +71,8 @@ CWiiMote* g_WiiMotes[MAX_WIIMOTES];
bool g_Shutdown = false; bool g_Shutdown = false;
bool g_LocalThread = true; bool g_LocalThread = true;
bool g_MotionSensing = false; bool g_MotionSensing = false;
u64 g_UpdateTime = 0;
int g_UpdateCounter = 0;
//****************************************************************************** //******************************************************************************
// Probably this class should be in its own file // 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) 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(); m_pCriticalSection->Enter();
{ {
SEvent WriteEvent; SEvent WriteEvent;
memcpy(WriteEvent.m_PayLoad, _pData+1, _Size-1); memcpy(WriteEvent.m_PayLoad, _pData + 1, _Size - 1);
m_EventWriteQueue.push(WriteEvent); 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(); 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 /* Read and write data to the Wiimote */
using the real Wiimote we only allow it to receive data mode changes, but don't ask for any data in
return */
// --------------- // ---------------
void ReadData() void ReadData()
{ {
@ -136,45 +141,62 @@ void ReadData()
// Send data to the Wiimote // Send data to the Wiimote
if (!m_EventWriteQueue.empty()) 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(); SEvent& rEvent = m_EventWriteQueue.front();
wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD); wiiuse_io_write(m_pWiiMote, (byte*)rEvent.m_PayLoad, MAX_PAYLOAD);
m_EventWriteQueue.pop(); 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(); m_pCriticalSection->Leave();
// Don't queue up data if we are not using the real Wiimote // Read data from wiimote (but don't send it to the core, just filter and queue)
if(g_Config.bUseRealWiimote) if (wiiuse_io_read(m_pWiiMote))
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... // Filter out data reports
if (m_channelID > 0) 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 // Check if the data reporting mode is okay
if (pBuffer[0] >= 0x30) //if (g_EmulatorRunning && pBuffer[0] != WiiMoteEmu::g_ReportingMode)
{ // SetDataReportingMode();
// 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();
} }
else
{
// Copy Buffer to ImportantEvent
SEvent ImportantEvent;
memcpy(ImportantEvent.m_PayLoad, pBuffer, MAX_PAYLOAD);
//std::string Temp = ArrayToString(pBuffer, sizeof(pBuffer), 0); // Put it in the read queue right away
//Console::Print("Data:\n%s\n", Temp.c_str()); 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()) if (m_EventReadQueue.empty())
{ {
// Send the same data as last time // Send the data report
if (m_LastReportValid) SendEvent(m_LastReport); if (m_LastReportValid) SendEvent(m_LastReport);
} }
else else
{ {
// Send all the new data we have collected // Send a 0x20, 0x21 or 0x22 report
SendEvent(m_EventReadQueue.front()); SendEvent(m_EventReadQueue.front());
m_EventReadQueue.pop(); 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: private:
struct SEvent struct SEvent
@ -217,23 +252,22 @@ private:
u8 m_WiimoteNumber; // Just for debugging u8 m_WiimoteNumber; // Just for debugging
u16 m_channelID; u16 m_channelID;
CEventQueue m_EventReadQueue; // Read from Wiimote
CEventQueue m_EventWriteQueue; // Write to Wiimote
Common::CriticalSection* m_pCriticalSection; Common::CriticalSection* m_pCriticalSection;
CEventQueue m_EventReadQueue;
CEventQueue m_EventWriteQueue;
bool m_LastReportValid; bool m_LastReportValid;
SEvent m_LastReport; SEvent m_LastReport;
wiimote_t* m_pWiiMote; // This is g_WiiMotesFromWiiUse[] wiimote_t* m_pWiiMote; // This is g_WiiMotesFromWiiUse[]
////////////////////////////////////////// //////////////////////////////////////////
// Send event // Send queued data to the core
// --------------- // ---------------
void SendEvent(SEvent& _rEvent) void SendEvent(SEvent& _rEvent)
{ {
// We don't have an answer channel // We don't have an answer channel
if (m_channelID == 0) return; if (m_channelID == 0) return;
// Check event buffer; // Check event buffer
u8 Buffer[1024]; u8 Buffer[1024];
u32 Offset = 0; u32 Offset = 0;
hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset); hid_packet* pHidHeader = (hid_packet*)(Buffer + Offset);
@ -241,19 +275,15 @@ void SendEvent(SEvent& _rEvent)
pHidHeader->type = HID_TYPE_DATA; pHidHeader->type = HID_TYPE_DATA;
pHidHeader->param = HID_PARAM_INPUT; pHidHeader->param = HID_PARAM_INPUT;
// Create the buffer
memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD); memcpy(&Buffer[Offset], _rEvent.m_PayLoad, MAX_PAYLOAD);
Offset += MAX_PAYLOAD; Offset += MAX_PAYLOAD;
/* Debugging // Send it
//if(GetAsyncKeyState('V')) g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset);
{
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());
}*/
g_WiimoteInitialize.pWiimoteInput(m_channelID, Buffer, Offset); // Debugging
ReadDebugging(false, Buffer);
} }
///////////////////// /////////////////////
}; };
@ -264,6 +294,113 @@ void SendEvent(SEvent& _rEvent)
// Function Definitions // 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 // Flash lights, and if connecting, also rumble
void FlashLights(bool Connect) void FlashLights(bool Connect)
{ {
@ -281,28 +418,45 @@ void FlashLights(bool Connect)
int Initialize() int Initialize()
{ {
// Return if already initialized
if (g_RealWiiMoteInitialized) return g_NumberOfWiiMotes; if (g_RealWiiMoteInitialized) return g_NumberOfWiiMotes;
// Clear the wiimote classes
memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES); memset(g_WiiMotes, 0, sizeof(CWiiMote*) * MAX_WIIMOTES);
// Call Wiiuse.dll // Call Wiiuse.dll
g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES); g_WiiMotesFromWiiUse = wiiuse_init(MAX_WIIMOTES);
g_NumberOfWiiMotes = wiiuse_find(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 5); 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); 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) if (!g_EmulatorRunning)
{ {
// Do I need this? // I don't seem to need wiiuse_connect()
//int Connect = wiiuse_connect(g_WiiMotesFromWiiUse, MAX_WIIMOTES); //int Connect = wiiuse_connect(g_WiiMotesFromWiiUse, MAX_WIIMOTES);
//Console::Print("Connected: %i\n", Connect); //Console::Print("Connected: %i\n", Connect);
//wiiuse_set_timeout(g_WiiMotesFromWiiUse, MAX_WIIMOTES, 500, 1000);
//wiiuse_set_flags(g_WiiMotesFromWiiUse[0], WIIUSE_CONTINUOUS, NULL);
FlashLights(true); FlashLights(true);
} }
else else
@ -386,10 +540,8 @@ void Update()
////////////////////////////////// //////////////////////////////////
/* Continuously read the Wiimote status. However, the actual sending of data occurs in Update(). If we are /* 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 not currently using the real Wiimote we allow the separate ReadWiimote() function to run. Wo don't use
out how to manually send the current data reporting mode to the real Wiimote so that we can entirely turn them at the same time to avoid a potential collision. */
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(). */
// --------------- // ---------------
#ifdef _WIN32 #ifdef _WIN32
DWORD WINAPI ReadWiimote_ThreadFunc(void* arg) DWORD WINAPI ReadWiimote_ThreadFunc(void* arg)
@ -399,9 +551,9 @@ void Update()
{ {
while (!g_Shutdown) while (!g_Shutdown)
{ {
if(g_EmulatorRunning) if(g_Config.bUseRealWiimote)
for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData(); for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData();
if (!g_Config.bUseRealWiimote) else
ReadWiimote(); ReadWiimote();
} }
return 0; return 0;

View File

@ -38,12 +38,18 @@ void Shutdown(void);
void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size); void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(u16 _channelID, const void* _pData, u32 _Size); void ControlChannel(u16 _channelID, const void* _pData, u32 _Size);
void Update(); void Update();
void SendAcc(u8 _ReportID);
void SetDataReportingMode(u8 ReportingMode = 0);
void ClearEvents();
void ReadWiimote(); void ReadWiimote();
#ifndef EXCLUDE_H #ifndef EXCLUDE_H
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 u64 g_UpdateTime;
extern int g_UpdateCounter;
#endif #endif
}; // WiiMoteReal }; // WiiMoteReal