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

@ -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");
}

View File

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

View File

@ -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++)

View File

@ -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];

View File

@ -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);
}

View File

@ -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];

View File

@ -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[] = {

View File

@ -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);
}

View File

@ -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

View File

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

View File

@ -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;
}

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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