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:
parent
529bf35d6a
commit
888465868d
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ struct Config
|
|||
|
||||
// Real Wiimote
|
||||
bool bConnectRealWiimote, bUseRealWiimote, bUpdateRealWiimote;
|
||||
int iAccNeutralX, iAccNeutralY, iAccNeutralZ;
|
||||
};
|
||||
|
||||
extern Config g_Config;
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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<wm_ackdelay> 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[] = {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "Common.h" // Common
|
||||
|
||||
#include "main.h"
|
||||
#include "wiimote_hid.h" // Local
|
||||
#include "EmuDefinitions.h"
|
||||
#include "Encryption.h"
|
||||
|
|
|
@ -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<u8> 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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue