Saving real Wiimote state

because that's simpler than reconnecting
This commit is contained in:
John Peterson 2013-05-31 07:12:59 +02:00 committed by Rachel Bryk
parent 748ee50536
commit 0fd3acd152
15 changed files with 815 additions and 64 deletions

View File

@ -162,6 +162,7 @@ const char* GetLastErrorMsg();
namespace Common
{
inline u8 swap8(u8 _data) {return _data;}
inline u32 swap24(const u8* _data) {return (_data[0] << 16) | (_data[1] << 8) | _data[2];}
#ifdef _WIN32
inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}

View File

@ -243,7 +243,6 @@ void SConfig::SaveSettings()
ini.Set("Core", "WiiSDCard", m_WiiSDCard);
ini.Set("Core", "WiiKeyboard", m_WiiKeyboard);
ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad);
ini.Set("Core", "WiimoteContinuousScanning", m_WiimoteContinuousScanning);
ini.Set("Core", "WiimoteEnableSpeaker", m_WiimoteEnableSpeaker);
ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer);
@ -400,7 +399,6 @@ void SConfig::LoadSettings()
ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false);
ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false);
ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true);
ini.Get("Core", "WiimoteContinuousScanning", &m_WiimoteContinuousScanning, false);
ini.Get("Core", "WiimoteEnableSpeaker", &m_WiimoteEnableSpeaker, true);
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);

View File

@ -28,7 +28,6 @@ struct SConfig : NonCopyable
// Wii Devices
bool m_WiiSDCard;
bool m_WiiKeyboard;
bool m_WiimoteReconnectOnLoad;
bool m_WiimoteContinuousScanning;
bool m_WiimoteEnableSpeaker;

View File

@ -504,9 +504,11 @@ void SetState(EState _State)
break;
case CORE_PAUSE:
CCPU::EnableStepping(true); // Break
Wiimote::Pause();
break;
case CORE_RUN:
CCPU::EnableStepping(false);
Wiimote::Resume();
break;
default:
PanicAlertT("Invalid state");

View File

@ -32,8 +32,7 @@ void Shutdown()
delete *i;
g_plugin.controllers.clear();
// WiimoteReal is shutdown on app exit
//WiimoteReal::Shutdown();
WiimoteReal::Shutdown();
g_controller_interface.Shutdown();
}
@ -58,6 +57,17 @@ void Initialize(void* const hwnd)
Movie::ChangeWiiPads();
}
void Resume()
{
WiimoteReal::Resume();
}
void Pause()
{
WiimoteReal::Pause();
}
// __________________________________________________________________________________________________
// Function: ControlChannel
// Purpose: An L2CAP packet is passed from the Core to the Wiimote,
@ -72,11 +82,8 @@ void Initialize(void* const hwnd)
//
void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
if (WIIMOTE_SRC_HYBRID & g_wiimote_sources[_number])
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->ControlChannel(_channelID, _pData, _Size);
if (WIIMOTE_SRC_REAL & g_wiimote_sources[_number])
WiimoteReal::ControlChannel(_number, _channelID, _pData, _Size);
}
// __________________________________________________________________________________________________
@ -93,10 +100,8 @@ void ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
//
void InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size)
{
if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number])
if (WIIMOTE_SRC_HYBRID & g_wiimote_sources[_number])
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->InterruptChannel(_channelID, _pData, _Size);
else
WiimoteReal::InterruptChannel(_number, _channelID, _pData, _Size);
}
// __________________________________________________________________________________________________

View File

@ -36,6 +36,8 @@ namespace Wiimote
void Shutdown();
void Initialize(void* const hwnd);
void Resume();
void Pause();
unsigned int GetAttached();
void DoState(u8 **ptr, PointerWrap::Mode mode);
@ -53,6 +55,8 @@ namespace WiimoteReal
void Initialize();
void Shutdown();
void Resume();
void Pause();
void Refresh();
void LoadSettings();

View File

@ -29,15 +29,662 @@
#include "Attachment/Attachment.h"
/* Bit shift conversions */
static u32 swap24(const u8* src)
{
return (src[0] << 16) | (src[1] << 8) | src[2];
}
namespace WiimoteEmu
{
void Spy(Wiimote* wm_, const void* data_, int size_)
{
#if 0
// enable log
bool logCom = true;
bool logData = true;
bool logMP = false;
bool logAudio = false;
std::string Name, TmpData;
static int c;
int size;
u16 SampleValue;
bool AudioData = false;
bool DataReport = false;
static std::queue<u32> dataRep;
static u8 dataReply[3] = {0};
bool emu = wm_;
static Wiimote* wm = 0;
// a container for f.e. the extension encryption key
if (!wm_ && !wm)
wm = new Wiimote(0);
else
wm = wm_;
// ignore emulated Wiimote data
if (emu) return;
const hid_packet* const hidp = (hid_packet*)data_;
const wm_report* const sr = (wm_report*)hidp->data;
// use a non-pointer array because that makes read syntax shorter
u8 data[32] = {};
memcpy(data, data_, size_);
switch(data[1])
{
case WM_RUMBLE:
size = 1;
if (logCom) Name.append("WM_RUMBLE");
break;
case WM_LEDS:
size = sizeof(wm_leds);
if (logCom) Name.append("WM_LEDS");
break;
case WM_REPORT_MODE:
size = sizeof(wm_report_mode);
if (logCom) Name.append("WM_REPORT_MODE");
ERROR_LOG(CONSOLE, "WM_REPORT_MODE: 0x%02x", data[3]);
break;
case WM_IR_PIXEL_CLOCK:
if (logCom) Name.append("WM_IR_PIXEL_CLOCK");
break;
case WM_SPEAKER_ENABLE:
if (logCom) Name.append("WM_SPEAKER_ENABLE");
NOTICE_LOG(CONSOLE, "Speaker on: %d", sr->enable);
break;
case WM_REQUEST_STATUS:
size = sizeof(wm_request_status);
if (logCom) Name.append("WM_REQUEST_STATUS");
NOTICE_LOG(CONSOLE, "WM_REQUEST_STATUS: %s", ArrayToString(data, size+2, 0).c_str());
break;
case WM_WRITE_DATA:
{
if (logCom) Name.append("W 0x16");
size = sizeof(wm_write_data);
wm_write_data* wd = (wm_write_data*)sr->data;
u32 address = Common::swap24(wd->address);
address &= ~0x010000;
switch(data[2] >> 0x01)
{
case WM_SPACE_EEPROM:
if (logCom) Name.append(" REG_EEPROM"); break;
case WM_SPACE_REGS1:
case WM_SPACE_REGS2: {
const u8 region_offset = (u8)address;
void *region_ptr = NULL;
int region_size = 0;
switch(data[3])
{
case 0xa2:
if (logCom)
{
Name.append(" REG_SPEAKER");
if(data[6] == 7)
{
//INFO_LOG(CONSOLE, "Sound configuration:");
if(data[8] == 0x00)
{
//memcpy(&SampleValue, &data[9], 2);
//NOTICE_LOG(CONSOLE, " Data format: 4-bit ADPCM (%i Hz)", 6000000 / SampleValue);
//NOTICE_LOG(CONSOLE, " Volume: %02i%%", (data[11] / 0x40) * 100);
}
else if (data[8] == 0x40)
{
//memcpy(&SampleValue, &data[9], 2);
//NOTICE_LOG(CONSOLE, " Data format: 8-bit PCM (%i Hz)", 12000000 / SampleValue);
//NOTICE_LOG(CONSOLE, " Volume: %02i%%", (data[11] / 0xff) * 100);
}
}
}
break;
case 0xa4:
if (logCom) Name.append(" REG_EXT");
// Update the encryption mode
if (data[5] == 0xf0) {
if (!emu)
wm->m_reg_ext.encryption = wd->data[0];
//NOTICE_LOG(CONSOLE, "Extension encryption: %u", wm->m_reg_ext.encryption);
}
region_ptr = &wm->m_reg_ext;
break;
case 0xa6 :
if (logCom) Name.append(" REG_M+");
// update the encryption mode
if (data[5] == 0xf0) {
if (!emu)
wm->m_reg_motion_plus.activated = wd->data[0];
//NOTICE_LOG(CONSOLE, "Extension enryption: %u", wm->m_reg_ext.encryption);
}
region_ptr = &wm->m_reg_motion_plus;
break;
case 0xb0:
if (logCom) Name.append(" REG_IR"); break;
}
// save register
if (!emu && region_ptr)
memcpy((u8*)region_ptr + region_offset, wd->data, wd->size);
// save key
if (region_offset >= 0x40 && region_offset <= 0x4c) {
if(!emu)
wiimote_gen_key(&wm->m_ext_key, wm->m_reg_ext.encryption_key);
INFO_LOG(CONSOLE, "Writing key: %s", ArrayToString((u8*)&wm->m_ext_key, sizeof(wm->m_ext_key), 0, 30).c_str());
}
if (data[3] == 0xa4 || data[3] == 0xa6) {
//DEBUG_LOG(CONSOLE, "M+: %s", ArrayToString((u8*)&wm->m_reg_motion_plus, sizeof(wm->m_reg_motion_plus), 0, 30).c_str());
//DEBUG_LOG(CONSOLE, "M+: %s", ArrayToString((u8*)&wm->m_reg_motion_plus.ext_identifier, sizeof(wm->m_reg_motion_plus.ext_identifier), 0, 30).c_str());
NOTICE_LOG(CONSOLE, "W[0x%02x 0x%02x|%d]: %s", data[3], region_offset, wd->size, ArrayToString(wd->data, wd->size, 0).c_str());
}
break;
}
}
break;
}
case WM_READ_DATA:
{
if (logCom) Name.append("R");
size = sizeof(wm_read_data);
wm_read_data* rd = (wm_read_data*)sr->data;
u32 address = Common::swap24(rd->address);
u8 addressLO = address & 0xFFFF;
address &= 0xFEFFFF;
u16 size = Common::swap16(rd->size);
u8 *const block = new u8[size];
void *region_ptr = NULL;
dataRep.push(((data[2]>>1)<<16) + ((data[3])<<8) + addressLO);
switch(data[2]>>1)
{
case WM_SPACE_EEPROM:
if (logCom) Name.append(" REG_EEPROM");
if (!emu)
memcpy(block, wm->m_eeprom + address, size);
break;
case WM_SPACE_REGS1:
case WM_SPACE_REGS2:
// ignore second byte for extension area
if (address>>16 == 0xA4) address &= 0xFF00FF;
const u8 region_offset = (u8)address;
switch(data[3])
{
case 0xa2:
if (logCom) Name.append(" REG_SPEAKER");
region_ptr = &wm->m_reg_speaker;
break;
case 0xa4:
if (logCom) Name.append(" REG_EXT");
region_ptr = &wm->m_reg_motion_plus;
break;
case 0xa6:
if (logCom) Name.append(" REG_M+");
region_ptr = &wm->m_reg_motion_plus;
break;
case 0xb0:
if (logCom) Name.append(" REG_IR");
region_ptr = &wm->m_reg_ir;
break;
}
//if (!emu && region_ptr)
//memcpy(block, (u8*)region_ptr + region_offset, size);
//WARN_LOG(CONSOLE, "READING[0x%02x 0x%02x|%d]: %s", data[3], region_offset, size, ArrayToString(block, size, 0, 30).c_str());
break;
}
break;
}
case WM_WRITE_SPEAKER_DATA:
if (logCom) Name.append("WM_SPEAKER_DATA");
size = 21;
break;
case WM_SPEAKER_MUTE:
if (logCom) Name.append("WM_SPEAKER");
size = 1;
NOTICE_LOG(CONSOLE, "Speaker mute: %d", sr->enable);
break;
case WM_IR_LOGIC:
if (logCom) Name.append("WM_IR");
size = 1;
break;
case WM_STATUS_REPORT:
size = sizeof(wm_status_report);
Name = "WM_STATUS_REPORT";
//INFO_LOG(CONSOLE, "WM_STATUS_REPORT: %s", ArrayToString(data, size+2, 0).c_str());
{
wm_status_report* pStatus = (wm_status_report*)(data + 2);
ERROR_LOG(CONSOLE, ""
"Statusreport extension: %i",
//"Speaker enabled: %i"
//"IR camera enabled: %i"
//"LED 1: %i\n"
//"LED 2: %i\n"
//"LED 3: %i\n"
//"LED 4: %i\n"
//"Battery low: %i\n"
//"Battery level: %i",
pStatus->extension
//pStatus->speaker,
//pStatus->ir,
//(pStatus->leds >> 0),
//(pStatus->leds >> 1),
//(pStatus->leds >> 2),
//(pStatus->leds >> 3),
//pStatus->battery_low,
//pStatus->battery
);
}
break;
case WM_READ_DATA_REPLY:
{
size = sizeof(wm_read_data_reply);
Name = "R_REPLY";
u8 data2[32];
memset(data2, 0, sizeof(data2));
memcpy(data2, data, size_);
wm_read_data_reply* const rdr = (wm_read_data_reply*)(data2 + 2);
bool decrypted = false;
if(!dataRep.empty())
{
dataReply[0] = (dataRep.front()>>16)&0x00FF;
dataReply[1] = (dataRep.front()>>8)&0x00FF;
dataReply[2] = dataRep.front()&0x00FF;
dataRep.pop();
}
switch(dataReply[0])
{
case WM_SPACE_EEPROM:
if (logCom)
Name.append(" REG_EEPROM");
// Wiimote calibration
if(data[4] == 0xf0 && data[5] == 0x00 && data[6] == 0x10) {
if(data[6] == 0x10) {
accel_cal* calib = (accel_cal*)&rdr->data[6];
ERROR_LOG(CONSOLE, "Wiimote calibration:");
//SERROR_LOG(CONSOLE, "%s", ArrayToString(rdr->data, rdr->size).c_str());
ERROR_LOG(CONSOLE, "Cal_zero.x: %i", calib->zero_g.x);
ERROR_LOG(CONSOLE, "Cal_zero.y: %i", calib->zero_g.y);
ERROR_LOG(CONSOLE, "Cal_zero.z: %i", calib->zero_g.z);
ERROR_LOG(CONSOLE, "Cal_g.x: %i", calib->one_g.x);
ERROR_LOG(CONSOLE, "Cal_g.y: %i", calib->one_g.y);
ERROR_LOG(CONSOLE, "Cal_g.z: %i", calib->one_g.z);
// save
if (!emu)
memcpy(wm->m_eeprom + 0x16, rdr->data + 6, rdr->size);
}
}
break;
case WM_SPACE_REGS1:
case WM_SPACE_REGS2:
switch(dataReply[1])
{
case 0xa2: if (logCom) Name.append(" REG_SPEAKER"); break;
case 0xa4: if (logCom) Name.append(" REG_EXT"); break;
case 0xa6: if (logCom) Name.append(" REG_M+"); break;
case 0xb0: if (logCom) Name.append(" REG_IR"); break;
}
}
// save key
if (!emu && rdr->address>>8 == 0x40)
{
memcpy(((u8*)&wm->m_reg_ext.encryption_key), rdr->data, rdr->size+1);
wiimote_gen_key(&wm->m_ext_key, wm->m_reg_ext.encryption_key);
NOTICE_LOG(CONSOLE, "Reading key: %s", ArrayToString(((u8*)&wm->m_ext_key), sizeof(wm->m_ext_key), 0, 30).c_str());
}
// select decryption
//if(((!wm->GetMotionPlusActive() && ((u8*)&wm->m_reg_ext)[0xf0] == 0xaa) || (wm->GetMotionPlusActive() && ((u8*)&wm->m_reg_motion_plus)[0xf0] == 0xaa)) && rdr->address>>8 < 0xf0) {
//if(((((u8*)&wm->m_reg_ext)[0xf0] == 0xaa) || ((u8*)&wm->m_reg_motion_plus)[0xf0] == 0xaa) && rdr->address>>8 < 0xf0) {
//if(!wm->GetMotionPlusActive() && ((u8*)&wm->m_reg_ext)[0xf0] == 0xaa && rdr->address>>8 < 0xf0) {
//if(!wm->GetMotionPlusActive() && ((u8*)&wm->m_reg_ext)[0xf0] == 0xaa) {
// SWARN_LOG(CONSOLE, "key %s", ArrayToString(((u8*)&wm->m_ext_key), sizeof(wm->m_ext_key), 0, 30).c_str());
// SWARN_LOG(CONSOLE, "decrypt %s", ArrayToString(rdr->data, rdr->size+1, 0, 30).c_str());
// wiimote_decrypt(&wm->m_ext_key, rdr->data, dataReply[2]&0xffff, rdr->size+1);
// SWARN_LOG(CONSOLE, "decrypt %s", ArrayToString(rdr->data, rdr->size+1, 0, 30).c_str());
// decrypted = true;
//}
// save data
if (!emu && !rdr->error)
{
//if (dataReply[1] == 0xa4 && wm->GetMotionPlusActive())
//memcpy(&((u8*)&wm->m_reg_motion_plus)[rdr->address>>8], rdr->data, rdr->size+1);
//if (dataReply[1] == 0xa4 && !wm->GetMotionPlusActive())
//if (dataReply[1] == 0xa4)
// memcpy(&((u8*)&wm->m_reg_ext)[rdr->address>>8], rdr->data, rdr->size+1);
//if (!wm->GetMotionPlusActive() && wm->GetMotionPlusAttached())
//if (dataReply[1] == 0xa6)
// memcpy(&((u8*)&wm->m_reg_motion_plus)[rdr->address>>8], rdr->data, rdr->size+1);
//INFO_LOG(CONSOLE, "Saving[0x%2x:0x%2x]: %s", dataReply[1], rdr->address>>8, ArrayToString(rdr->data, rdr->size+1).c_str());
}
if (!rdr->error && rdr->address>>8 >= 0xf0 && rdr->address>>8 <= 0xff)
{
//INFO_LOG(CONSOLE, "Extension ID: %s", ArrayToString(rdr->data, rdr->size+1).c_str());
}
// Nunchuck calibration
if(data[4] == 0xf0 && data[5] == 0x00 && (data[6] == 0x20 || data[6] == 0x30))
{
// log
//TmpData = StringFromFormat("Read[%s] (enc): %s", (Emu ? "Emu" : "Real"), ArrayToString(data, size + 2).c_str());
// decrypt
//if(((u8*)&wm->m_reg_ext)[0xf0] == 0xaa) {
// wiimote_decrypt(&wm->m_ext_key, &data[0x07], 0x00, (data[4] >> 0x04) + 1);
//if (wm->m_extension->name == "NUNCHUCK") {
// INFO_LOG(CONSOLE, "\nGame got the Nunchuck calibration:\n");
// INFO_LOG(CONSOLE, "Cal_zero.x: %i\n", data[7 + 0]);
// INFO_LOG(CONSOLE, "Cal_zero.y: %i\n", data[7 + 1]);
// INFO_LOG(CONSOLE, "Cal_zero.z: %i\n", data[7 + 2]);
// INFO_LOG(CONSOLE, "Cal_g.x: %i\n", data[7 + 4]);
// INFO_LOG(CONSOLE, "Cal_g.y: %i\n", data[7 + 5]);
// INFO_LOG(CONSOLE, "Cal_g.z: %i\n", data[7 + 6]);
// INFO_LOG(CONSOLE, "Js.Max.x: %i\n", data[7 + 8]);
// INFO_LOG(CONSOLE, "Js.Min.x: %i\n", data[7 + 9]);
// INFO_LOG(CONSOLE, "Js.Center.x: %i\n", data[7 + 10]);
// INFO_LOG(CONSOLE, "Js.Max.y: %i\n", data[7 + 11]);
// INFO_LOG(CONSOLE, "Js.Min.y: %i\n", data[7 + 12]);
// INFO_LOG(CONSOLE, "JS.Center.y: %i\n\n", data[7 + 13]);
//}
//else // g_Config.bClassicControllerConnected {
// INFO_LOG(CONSOLE, "\nGame got the Classic Controller calibration:\n");
// INFO_LOG(CONSOLE, "Lx.Max: %i\n", data[7 + 0]);
// INFO_LOG(CONSOLE, "Lx.Min: %i\n", data[7 + 1]);
// INFO_LOG(CONSOLE, "Lx.Center: %i\n", data[7 + 2]);
// INFO_LOG(CONSOLE, "Ly.Max: %i\n", data[7 + 3]);
// INFO_LOG(CONSOLE, "Ly.Min: %i\n", data[7 + 4]);
// INFO_LOG(CONSOLE, "Ly.Center: %i\n", data[7 + 5]);
// INFO_LOG(CONSOLE, "Rx.Max.x: %i\n", data[7 + 6]);
// INFO_LOG(CONSOLE, "Rx.Min.x: %i\n", data[7 + 7]);
// INFO_LOG(CONSOLE, "Rx.Center.x: %i\n", data[7 + 8]);
// INFO_LOG(CONSOLE, "Ry.Max.y: %i\n", data[7 + 9]);
// INFO_LOG(CONSOLE, "Ry.Min: %i\n", data[7 + 10]);
// INFO_LOG(CONSOLE, "Ry.Center: %i\n\n", data[7 + 11]);
// INFO_LOG(CONSOLE, "Lt.Neutral: %i\n", data[7 + 12]);
// INFO_LOG(CONSOLE, "Rt.Neutral %i\n\n", data[7 + 13]);
//}
// save values
if (!emu)
{
// Save to registry
if(data[7 + 0] != 0xff)
{
//memcpy((u8*)&wm->m_reg_ext.calibration, &data[7], 0x10);
//memcpy((u8*)&wm->m_reg_ext.unknown3, &data[7], 0x10);
}
// Save the default values that should work with Wireless Nunchucks
else
{
//WiimoteEmu::SetDefaultExtensionRegistry();
}
//WiimoteEmu::UpdateEeprom();
}
// third party Nunchuck
else if(data[7] == 0xff)
{
//memcpy(wm->m_reg_ext + 0x20, WiimoteEmu::wireless_nunchuck_calibration, sizeof(WiimoteEmu::wireless_nunchuck_calibration));
//memcpy(wm->m_reg_ext + 0x30, WiimoteEmu::wireless_nunchuck_calibration, sizeof(WiimoteEmu::wireless_nunchuck_calibration));
}
// print encrypted data
//INFO_LOG(CONSOLE, "WM_READ_DATA_REPLY: Extension calibration: %s", TmpData.c_str());
}
if (dataReply[1] == 0xa4 || dataReply[1] == 0xa6)
{
if(rdr->error == 7 || rdr->error == 8)
{
WARN_LOG(CONSOLE, "R%s[0x%02x 0x%02x]: e-%d", decrypted?"*":"", dataReply[1], rdr->address>>8, rdr->error);
}
else
{
WARN_LOG(CONSOLE, "R%s[0x%02x 0x%02x|%d]: %s", decrypted?"*":"", dataReply[1], rdr->address>>8, rdr->size+1, ArrayToString(rdr->data, rdr->size+1, 0).c_str());
}
}
break;
}
case WM_ACK_DATA:
size = sizeof(wm_acknowledge);
Name = "WM_ACK_DATA";
//INFO_LOG(CONSOLE, "ACK 0x%02x", data[4]);
break;
case WM_REPORT_CORE:
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:
size = 15;
NOTICE_LOG(CONSOLE, "Debugging[%s]: Unknown channel 0x%02x", (emu ? "E" : "R"), data[1]);
break;
}
//if (DataReport && wm->GetMotionPlusActive())
//{
// if (data[1] == WM_REPORT_CORE_ACCEL_IR10_EXT6)
// static bool extension = false;
// if (extension != (bool)(data[17+4]&1))
// ERROR_LOG(CONSOLE, "Datareport extension %d", data[17+4]&1);
// extension = data[17+4]&1;
//}
if (!DataReport && logCom && size <= 30)
{
ERROR_LOG_S(CONSOLE, "Com[%s] %s: %s", (emu ? "E" : "R"), Name.c_str(), ArrayToString(data, size + 2, 0).c_str());
}
if (logAudio && AudioData)
{
//DEBUG_LOG(CONSOLE, "%s: %s\n", Name.c_str(), ArrayToString(data, std::min(10,size), 0, 30).c_str());
}
if (DataReport && (logData || logMP))
{
// decrypt extension data
//if (data[1] == 0x37 && !wm->GetMotionPlusActive())
//if (data[1] == 0x37)
// wiimote_decrypt(&wm->m_ext_key, &data[17], 0x00, 0x06);
//if (data[1] == 0x35)
// wiimote_decrypt(&wm->m_ext_key, &data[7], 0x00, 0x06);
//if (data[1] == 0x35 || data[1] == 0x37)
//{
// if (!g_DebugMP && mp->is_mp_data) return;
// if (!g_DebugData && !mp->is_mp_data) return;
//}
std::string SCore = "", SAcc = "", SIR = "", SExt = "", SExtID = "";
wm_core* core = (wm_core*)sr->data;
accel_cal* calib = (accel_cal*)&wm->m_eeprom[0x16];
wm_accel* accel = (wm_accel*)&data[4];
//SCore = StringFromFormat(
// "%d %d %d %d ",
// core->xL,
// core->yL,
// core->zL,
// core->unknown);
SAcc = StringFromFormat(
//"%3d %3d %3d"
//" | %3d %3d %3d"
//" | %3d %3d %3d"
"| %5.2f %5.2f %5.2f"
//, calib->zero_g.x, calib->zero_g.y, calib->zero_g.z
//, (calib->zero_g.x<<2) + calib->zero_g.xL, (calib->zero_g.y<<2) + calib->zero_g.yL, (calib->zero_g.z<<2) + calib->zero_g.zL
//, calib->one_g.x, calib->one_g.y, calib->one_g.z
//, (calib->one_g.x<<2) + calib->one_g.xL, (calib->one_g.y<<2) + calib->one_g.yL, (calib->one_g.z<<2) + calib->one_g.zL
//, accel->x, accel->y, accel->z
//, (accel->x<<2) + core->xL, (accel->y<<2) + core->yL, (accel->z<<2) + core->zL
, (accel->x - calib->zero_g.x) / float(calib->one_g.x-calib->zero_g.x), (accel->y - calib->zero_g.y) / float(calib->one_g.y-calib->zero_g.y), (accel->z - calib->zero_g.z) / float(calib->one_g.z-calib->zero_g.z));
NOTICE_LOG(CONSOLE, "%d", size);
if (data[1] == WM_REPORT_CORE_ACCEL_IR12)
{
wm_ir_extended *ir = (wm_ir_extended*)&data[7];
SIR = StringFromFormat(
"%4u %4u | %u"
, ir->x | ir->xhi << 8
, ir->y | ir->yhi << 8
, ir->size);
}
if (data[1] == WM_REPORT_CORE_ACCEL_EXT16)
{
wm_extension *nc = (wm_extension*)&data[7];
SExt = StringFromFormat(
"%02x %02x | %02x %02x %02x | %02x"
, nc->jx, nc->jy
, nc->ax, nc->ay, nc->az
, nc->bt);
}
if (data[1] == WM_REPORT_CORE_ACCEL_IR10_EXT6)
{
wm_ir_basic *ir = (wm_ir_basic*)&data[7];
SIR = StringFromFormat(
"%4u %4u %4u %4u"
, ir->x1 | ir->x1hi << 8
, ir->y1 | ir->y1hi << 8
, ir->x2 | ir->x2hi << 8
, ir->y2 | ir->y1hi << 8);
/*
wm_motionplus *mp = (wm_motionplus*)&data[17];
wm_nc_mp *nc_mp = (wm_nc_mp *)&data[17];
if (mp->is_mp_data)
{
SExt = StringFromFormat(""
//"%02x %02x %02x %02x %02x %02x"
//"| %04x %04x %04x
" %5.2f %5.2f %5.2f"
" %s%s%s"
//, mp->roll1, mp->roll2
//, mp->pitch1, mp->pitch2
//, mp->yaw1, mp->yaw2
//, mp->pitch2<<8 | mp->pitch1
//, mp->roll2<<8 | mp->roll1
//, mp->yaw2<<8 | mp->yaw1
//, mp->pitch2<<8 | mp->pitch1
//, mp->roll2<<8 | mp->roll1
//, mp->yaw2<<8 | mp->yaw1
, float((mp->pitch2<<8 | mp->pitch1) - 0x1f7f) / float(0x1fff)
, float((mp->roll2<<8 | mp->roll1) - 0x1f7f) / float(0x1fff)
, float((mp->yaw2<<8 | mp->yaw1) - 0x1f7f) / float(0x1fff)
, mp->pitch_slow?"*":" ", mp->roll_slow?"*":" ", mp->yaw_slow?"*":" ");
}
else
{
SExt = StringFromFormat(
"%02x %02x | %02x %02x | %02x %02x %02x | %02x %02x %02x",
nc_mp->bz, nc_mp->bc,
nc_mp->jx, nc_mp->jy,
nc_mp->ax+nc_mp->axL, nc_mp->ay+nc_mp->ayL, (nc_mp->az<<1)+nc_mp->azL);
}
SExtID = StringFromFormat(
"[%s|%d|%d]"
, mp->is_mp_data ? "+" : "e"
, mp->is_mp_data ? mp->extension_connected : nc_mp->extension_connected
, wm->m_extension->active_extension);
*/
//DEBUG_LOG_S(CONSOLE, "M+ %d Extension %d %d %s", mp->is_mp_data, mp->is_mp_data ?
// mp->extension_connected : ((wm_nc_mp*)&data[17])->extension_connected, wm->m_extension->active_extension,
// ArrayToString(((u8*)&wm->m_reg_motion_plus.ext_identifier), sizeof(wm->m_reg_motion_plus.ext_identifier), 0).c_str());
}
// select log data
WARN_LOG_S(CONSOLE, "Data"
"[%s]"
" | id %s"
" | %s"
" | c %s"
" | a %s"
" | ir %s"
" | ext %s"
//" | %s"
//" | %s"
//" | %s"
, (emu ? "E" : "R")
, SExtID.c_str()
, ArrayToString(data, 2, 0).c_str()
, SCore.c_str()
, SAcc.c_str()
, SIR.c_str()
, SExt.c_str()
//, ArrayToString(&data[4], 3, 0).c_str()
//, (accel->x - 0x7f) / float(0xff), (accel->y - 0x7f) / float(0xff), (accel->z - 0x7f) / float(0xff)
//, ArrayToString(&data[17], 6, 0).c_str(),
);
}
#endif
}
void Wiimote::ReportMode(const wm_report_mode* const dr)
{
//INFO_LOG(WIIMOTE, "Set data report mode");
@ -64,7 +711,7 @@ void Wiimote::ReportMode(const wm_report_mode* const dr)
an Input Report back to the Wii. Input and Output is from the Wii's
perspective, Output means data to the Wiimote (from the Wii), Input means
data from the Wiimote.
The call browser:
1. Wiimote_InterruptChannel > InterruptChannel > HidOutputReport
@ -231,7 +878,7 @@ void Wiimote::RequestStatus(const wm_request_status* const rs)
*(wm_status_report*)(data + 2) = m_status;
// hybrid wiimote stuff
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0))
if (WIIMOTE_SRC_REAL & g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0))
{
using namespace WiimoteReal;
@ -253,7 +900,7 @@ void Wiimote::RequestStatus(const wm_request_status* const rs)
/* Write data to Wiimote and Extensions registers. */
void Wiimote::WriteData(const wm_write_data* const wd)
{
u32 address = swap24(wd->address);
u32 address = Common::swap24(wd->address);
// ignore the 0x010000 bit
address &= ~0x010000;
@ -290,7 +937,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
}
}
break;
case WM_SPACE_REGS1 :
case WM_SPACE_REGS2 :
{
@ -354,7 +1001,7 @@ void Wiimote::WriteData(const wm_write_data* const wd)
if (&m_reg_ext == region_ptr)
{
// Run the key generation on all writes in the key area, it doesn't matter
// Run the key generation on all writes in the key area, it doesn't matter
// that we send it parts of a key, only the last full key will have an effect
if (address >= 0xa40040 && address <= 0xa4004c)
wiimote_gen_key(&m_ext_key, m_reg_ext.encryption_key);
@ -381,9 +1028,9 @@ void Wiimote::WriteData(const wm_write_data* const wd)
}
/* Read data from Wiimote and Extensions registers. */
void Wiimote::ReadData(const wm_read_data* const rd)
void Wiimote::ReadData(const wm_read_data* const rd)
{
u32 address = swap24(rd->address);
u32 address = Common::swap24(rd->address);
u16 size = Common::swap16(rd->size);
// ignore the 0x010000 bit
@ -391,10 +1038,10 @@ void Wiimote::ReadData(const wm_read_data* const rd)
// hybrid wiimote stuff
// relay the read data request to real-wiimote
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && ((0xA4 != (address >> 16)) || (m_extension->switch_extension <= 0)))
if (WIIMOTE_SRC_REAL & g_wiimote_sources[m_index] && ((0xA4 != (address >> 16)) || (m_extension->switch_extension <= 0)))
{
WiimoteReal::InterruptChannel(m_index, m_reporting_channel, ((u8*)rd) - 2, sizeof(wm_read_data) + 2); // hacky
// don't want emu-wiimote to send reply
return;
}
@ -408,9 +1055,9 @@ void Wiimote::ReadData(const wm_read_data* const rd)
{
//PanicAlert("ReadData: reading from EEPROM: address: 0x%x size: 0x%x", address, size);
// Read from EEPROM
if (address + size >= WIIMOTE_EEPROM_FREE_SIZE)
if (address + size >= WIIMOTE_EEPROM_FREE_SIZE)
{
if (address + size > WIIMOTE_EEPROM_SIZE)
if (address + size > WIIMOTE_EEPROM_SIZE)
{
PanicAlert("ReadData: address + size out of bounds");
delete [] block;
@ -503,7 +1150,7 @@ void Wiimote::ReadData(const wm_read_data* const rd)
}
// want the requested address, not the above modified one
rr.address = swap24(rd->address);
rr.address = Common::swap24(rd->address);
rr.size = size;
//rr.channel = _channelID;
rr.position = 0;
@ -643,6 +1290,21 @@ void Wiimote::DoState(PointerWrap& p)
}
}
p.DoMarker("Wiimote");
if (p.GetMode() == PointerWrap::MODE_READ)
RealState();
}
// load real Wiimote state
void Wiimote::RealState()
{
using namespace WiimoteReal;
if (g_wiimotes[m_index])
{
g_wiimotes[m_index]->SetChannel(m_reporting_channel);
g_wiimotes[m_index]->EnableDataReporting(m_reporting_mode);
}
}
}

View File

@ -781,7 +781,10 @@ void Wiimote::Update()
// send data report
if (rptf_size)
{
WiimoteEmu::Spy(this, data, rptf_size);
Core::Callback_WiimoteInterruptChannel(m_index, m_reporting_channel, data, rptf_size);
}
}
void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size)
@ -853,7 +856,7 @@ void Wiimote::InterruptChannel(const u16 _channelID, const void* _pData, u32 _Si
{
const wm_report* const sr = (wm_report*)hidp->data;
if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index])
if (WIIMOTE_SRC_REAL & g_wiimote_sources[m_index])
{
switch (sr->wm)
{

View File

@ -24,6 +24,11 @@
#define WIIMOTE_REG_EXT_SIZE 0x100
#define WIIMOTE_REG_IR_SIZE 0x34
namespace WiimoteReal
{
class Wiimote;
}
namespace WiimoteEmu
{
@ -66,6 +71,8 @@ inline double trim(double a)
class Wiimote : public ControllerEmu
{
friend class WiimoteReal::Wiimote;
friend void Spy(Wiimote* wm_, const void* data_, int size_);
public:
enum
@ -92,6 +99,7 @@ public:
void ControlChannel(const u16 _channelID, const void* _pData, u32 _Size);
void DoState(PointerWrap& p);
void RealState();
void LoadDefaults(const ControllerInterface& ciface);
@ -235,6 +243,8 @@ private:
} m_reg_speaker;
};
void Spy(Wiimote* wm_, const void* data_, int size_);
}
#endif

View File

@ -597,6 +597,8 @@ int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index
}
}
WiimoteEmu::Spy(NULL, buf, bytes + 1);
return bytes + 1;
}
@ -611,6 +613,8 @@ int Wiimote::IORead(u8* buf)
int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len)
{
WiimoteEmu::Spy(NULL, buf, len);
switch (stack)
{
case MSBT_STACK_UNKNOWN:

View File

@ -110,6 +110,22 @@ void Wiimote::DisableDataReporting()
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
}
void Wiimote::EnableDataReporting(u8 mode)
{
m_last_input_report.clear();
wm_report_mode rpt = {};
rpt.mode = mode;
rpt.all_the_time = 1;
rpt.continuous = 1;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
}
void Wiimote::SetChannel(u16 channel)
{
m_channel = channel;
}
void Wiimote::ClearReadQueue()
{
Report rpt;
@ -314,6 +330,44 @@ void Wiimote::EmuStop()
NOTICE_LOG(WIIMOTE, "Stopping Wiimote data reporting.");
}
void Wiimote::EmuResume()
{
WiimoteEmu::Wiimote *const wm = (WiimoteEmu::Wiimote*)::Wiimote::GetPlugin()->controllers[index];
m_last_input_report.clear();
wm_report_mode rpt = {};
rpt.mode = wm->m_reporting_mode;
rpt.all_the_time = 1;
rpt.continuous = 1;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
NOTICE_LOG(WIIMOTE, "Resuming Wiimote data reporting.");
}
void Wiimote::EmuPause()
{
m_last_input_report.clear();
wm_report_mode rpt = {};
rpt.mode = WM_REPORT_CORE;
rpt.all_the_time = 0;
rpt.continuous = 0;
QueueReport(WM_REPORT_MODE, &rpt, sizeof(rpt));
NOTICE_LOG(WIIMOTE, "Pausing Wiimote data reporting.");
}
unsigned int CalculateConnectedWiimotes()
{
unsigned int connected_wiimotes = 0;
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
if (g_wiimotes[i])
++connected_wiimotes;
return connected_wiimotes;
}
unsigned int CalculateWantedWiimotes()
{
// Figure out how many real Wiimotes are required
@ -470,12 +524,26 @@ void Initialize()
g_wiimote_scanner.StartScanning();
else
g_wiimote_scanner.StopScanning();
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
// wait for connection because it should exist before state load
int timeout = 100;
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;
g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board);
if (SConfig::GetInstance().m_WiimoteContinuousScanning)
{
while(CalculateWantedWiimotes() && CalculateConnectedWiimotes() < found_wiimotes.size() && timeout)
{
Common::SleepCurrentThread(100);
timeout--;
}
}
if (g_real_wiimotes_initialized)
return;
@ -485,7 +553,14 @@ void Initialize()
}
void Shutdown(void)
{
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuStop();
// WiimoteReal is shutdown on app exit
return;
g_wiimote_scanner.StopScanning();
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
@ -501,6 +576,20 @@ void Shutdown(void)
HandleWiimoteDisconnect(i);
}
void Resume()
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuResume();
}
void Pause()
{
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && g_wiimotes[i]->IsConnected())
g_wiimotes[i]->EmuPause();
}
void ChangeWiimoteSource(unsigned int index, int source)
{
{

View File

@ -47,6 +47,8 @@ public:
// "handshake" / stop packets
void EmuStart();
void EmuStop();
void EmuResume();
void EmuPause();
// connecting and disconnecting from physical devices
// (using address inserted by FindWiimotes)
@ -59,6 +61,8 @@ public:
bool Prepare(int index);
void DisableDataReporting();
void EnableDataReporting(u8 mode);
void SetChannel(u16 channel);
void QueueReport(u8 rpt_id, const void* data, unsigned int size);

View File

@ -138,27 +138,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
m_WiiMotes[i].DoState(p);
// Reset the connection of real and hybrid wiimotes
if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad)
{
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i])
continue;
// TODO: Selectively clear real wiimote messages if possible. Or create a real wiimote channel and reporting mode pre-setup to vacate the need for m_WiimoteReconnectOnLoad.
m_EventQueue.clear();
if (!m_WiiMotes[i].IsInactive())
{
m_WiiMotes[i].Activate(false);
m_WiiMotes[i].Activate(true);
}
else
{
m_WiiMotes[i].Activate(false);
}
}
}
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::RemoteDisconnect(u16 _connectionHandle)

View File

@ -106,7 +106,6 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxSlider* const WiiSensBarSens = new wxSlider(this, wxID_ANY, 0, 0, 4, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
wxSlider* const WiimoteSpkVolume = new wxSlider(this, wxID_ANY, 0, 0, 127);
wxCheckBox* const WiimoteMotor = new wxCheckBox(this, wxID_ANY, _("Wiimote Motor"));
wxCheckBox* const WiimoteReconnectOnLoad = new wxCheckBox(this, wxID_ANY, _("Reconnect Wiimote on State Loading"));
wxStaticText* const WiiSensBarPosText = new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:"));
wxStaticText* const WiiSensBarSensText = new wxStaticText(this, wxID_ANY, _("IR Sensitivity:"));
@ -143,13 +142,11 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u32>("BT.SENS"));
WiimoteSpkVolume->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u8>("BT.SPKV"));
WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<bool>("BT.MOT"));
WiimoteReconnectOnLoad->SetValue(SConfig::GetInstance().m_WiimoteReconnectOnLoad);
WiiSensBarPos->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::OnSensorBarPos, this);
WiiSensBarSens->Bind(wxEVT_COMMAND_SLIDER_UPDATED, &WiimoteConfigDiag::OnSensorBarSensitivity, this);
WiimoteSpkVolume->Bind(wxEVT_COMMAND_SLIDER_UPDATED, &WiimoteConfigDiag::OnSpeakerVolume, this);
WiimoteMotor->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnMotor, this);
WiimoteReconnectOnLoad->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &WiimoteConfigDiag::OnReconnectOnLoad, this);
// "General Settings" layout
@ -175,7 +172,6 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxGridSizer* const general_wiimote_sizer = new wxGridSizer(1, 5, 5);
general_wiimote_sizer->Add(WiimoteMotor);
general_wiimote_sizer->Add(WiimoteReconnectOnLoad);
general_sizer->Add(choice_sizer);
general_sizer->Add(general_wiimote_sizer);

View File

@ -52,11 +52,6 @@ public:
SConfig::GetInstance().m_SYSCONF->SetData("BT.MOT", event.GetInt());
event.Skip();
}
void OnReconnectOnLoad(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteReconnectOnLoad = event.IsChecked();
event.Skip();
}
void OnContinuousScanning(wxCommandEvent& event)
{
SConfig::GetInstance().m_WiimoteContinuousScanning = event.IsChecked();