From 84db29779e6d1a2176bec9feb6d10d04d24b29b6 Mon Sep 17 00:00:00 2001 From: Billiard26 Date: Tue, 10 Aug 2010 04:12:32 +0000 Subject: [PATCH] New Wiimote Plugin: Added a "Hybrid Wiimote" input source type. This allows a real wiimote to be used with an emulated extension.(and in the future, real wiimote with emulated motion plus) If the emulated extension is set to "None", a real extension can be used. Real/Emulated buttons are combined. Real acceleration data is used. Currently, emulated IR data is used.(might change this to allow both) Switching between an emulated and a real extension in-game is a bit testy right now, but if you switch the emu-extension to "None" before connecting a real extension, it usually works. git-svn-id: http://dolphin-emu.googlecode.com/svn/trunk@6082 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Common/Src/FifoQueue.h | 53 ++- .../Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp | 1 + .../Src/WiimoteEmu/EmuSubroutines.cpp | 103 +++-- .../Src/WiimoteEmu/WiimoteEmu.cpp | 474 +++++++++++++-------- .../Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h | 38 +- .../Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h | 2 +- .../Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp | 36 +- .../Src/WiimoteReal/WiimoteReal.cpp | 190 ++++----- .../Src/WiimoteReal/WiimoteReal.h | 47 +- 9 files changed, 565 insertions(+), 379 deletions(-) diff --git a/Source/Core/Common/Src/FifoQueue.h b/Source/Core/Common/Src/FifoQueue.h index 380f4f6da..2060ceee9 100644 --- a/Source/Core/Common/Src/FifoQueue.h +++ b/Source/Core/Common/Src/FifoQueue.h @@ -5,6 +5,8 @@ // a simple lockless thread-safe, // single reader, single writer queue +#include "Atomic.h" + namespace Common { @@ -12,7 +14,7 @@ template class FifoQueue { public: - FifoQueue() + FifoQueue() : m_size(0) { m_write_ptr = m_read_ptr = new ElementPtr(); } @@ -23,9 +25,20 @@ public: delete m_read_ptr; } - bool Empty() const // true if the queue is empty + u32 Size() const { - return (m_read_ptr == m_write_ptr); + return m_size; + } + + bool Empty() const + { + //return (m_read_ptr == m_write_ptr); + return (0 == m_size); + } + + const T& Front() const + { + return *m_read_ptr->current; } void Push(const T& t) @@ -35,42 +48,41 @@ public: // set the next pointer to a new element ptr // then advance the write pointer m_write_ptr = m_write_ptr->next = new ElementPtr(); + Common::AtomicIncrement(m_size); } - bool Pop(T& t) + void Pop() { - // if write pointer points to the same element, queue is empty - if (m_read_ptr == m_write_ptr) - return false; - - // get the element from out of the queue - t = *m_read_ptr->current; - + Common::AtomicDecrement(m_size); ElementPtr *const tmpptr = m_read_ptr; // advance the read pointer m_read_ptr = m_read_ptr->next; - // set the next element to NULL to stop the recursive deletion tmpptr->next = NULL; delete tmpptr; // this also deletes the element - - return true; } - bool Peek(T& t) + bool Pop(T& t) { - // if write pointer points to the same element, queue is empty - if (m_read_ptr == m_write_ptr) + if (Empty()) return false; - // get the element from out of the queue - t = *m_read_ptr->current; + t = Front(); + Pop(); return true; } + // not thread-safe + void Clear() + { + m_size = 0; + delete m_read_ptr; + m_write_ptr = m_read_ptr = new ElementPtr(); + } + private: - // stores a pointer to element at front of queue + // stores a pointer to element // and a pointer to the next ElementPtr class ElementPtr { @@ -94,6 +106,7 @@ private: ElementPtr *volatile m_write_ptr; ElementPtr *volatile m_read_ptr; + volatile u32 m_size; }; } diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp index 2b285e66d..082c4d993 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteConfigDiag.cpp @@ -13,6 +13,7 @@ WiimoteConfigPage::WiimoteConfigPage(wxWindow* const parent, const int index) m_input_src_choice->Append(wxT("None")); m_input_src_choice->Append(wxT("Emulated Wiimote")); m_input_src_choice->Append(wxT("Real Wiimote")); + m_input_src_choice->Append(wxT("Hybrid Wiimote")); m_input_src_choice->Select(g_wiimote_sources[m_index]); _connect_macro_(m_input_src_choice, WiimoteConfigPage::SelectSource, wxEVT_COMMAND_CHOICE_SELECTED, this); diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp index 412d8b69c..5279ae07d 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/EmuSubroutines.cpp @@ -38,23 +38,21 @@ #include "pluginspecs_wiimote.h" #include "WiimoteEmu.h" +#include "WiimoteHid.h" +#include "../WiimoteReal/WiimoteReal.h" + #include "Attachment/Attachment.h" /* Bit shift conversions */ -u32 convert24bit(const u8* src) +u32 swap24(const u8* src) { return (src[0] << 16) | (src[1] << 8) | src[2]; } -u16 convert16bit(const u8* src) -{ - return (src[0] << 8) | src[1]; -} - namespace WiimoteEmu { -void Wiimote::ReportMode(const u16 _channelID, wm_report_mode* dr) +void Wiimote::ReportMode(const wm_report_mode* const dr) { //INFO_LOG(WIIMOTE, "Set data report mode"); //DEBUG_LOG(WIIMOTE, " Rumble: %x", dr->rumble); @@ -92,9 +90,9 @@ void Wiimote::ReportMode(const u16 _channelID, wm_report_mode* dr) The IR enable/disable and speaker enable/disable and mute/unmute values are bit2: 0 = Disable (0x02), 1 = Enable (0x06) */ -void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) +void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) { - INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, _channelID, sr->wm); + INFO_LOG(WIIMOTE, "HidOutputReport (page: %i, cid: 0x%02x, wm: 0x%02x)", m_index, m_reporting_channel, sr->wm); // wiibrew: // In every single Output Report, bit 0 (0x01) of the first byte controls the Rumble feature. @@ -113,7 +111,7 @@ void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) break; case WM_REPORT_MODE : // 0x12 - ReportMode(_channelID, (wm_report_mode*)sr->data); + ReportMode((wm_report_mode*)sr->data); break; case WM_IR_PIXEL_CLOCK : // 0x13 @@ -128,16 +126,16 @@ void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) break; case WM_REQUEST_STATUS : // 0x15 - RequestStatus(_channelID, (wm_request_status*)sr->data); + RequestStatus((wm_request_status*)sr->data); return; // sends its own ack break; case WM_WRITE_DATA : // 0x16 - WriteData(_channelID, (wm_write_data*)sr->data); + WriteData((wm_write_data*)sr->data); break; case WM_READ_DATA : // 0x17 - ReadData(_channelID, (wm_read_data*)sr->data); + ReadData((wm_read_data*)sr->data); return; // sends its own ack break; @@ -175,7 +173,8 @@ void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) } // send ack - SendAck(_channelID, sr->wm); + if (send_ack) + SendAck(sr->wm); } /* This will generate the 0x22 acknowledgement for most Input reports. @@ -183,7 +182,7 @@ void Wiimote::HidOutputReport(const u16 _channelID, wm_report* sr) The first two bytes are the core buttons data, 00 00 means nothing is pressed. The last byte is the success code 00. */ -void Wiimote::SendAck(const u16 _channelID, u8 _reportID) +void Wiimote::SendAck(u8 _reportID) { u8 data[6]; @@ -196,23 +195,16 @@ void Wiimote::SendAck(const u16 _channelID, u8 _reportID) ack->reportID = _reportID; ack->errorID = 0; - g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, sizeof(data)); } -// old comment -/* Here we produce a 0x20 status report to send to the Wii. We currently ignore - the status request rs and all its eventual instructions it may include (for - example turn off rumble or something else) and just send the status - report. */ -void Wiimote::RequestStatus(const u16 _channelID, wm_request_status* rs) +void Wiimote::HandleExtensionSwap() { - //if (rs) - // handle switch extension - if ( m_extension->active_extension != m_extension->switch_extension ) + if (m_extension->active_extension != m_extension->switch_extension) { // if an extension is currently connected and we want to switch to a different extension - if ( (m_extension->active_extension > 0) && m_extension->switch_extension ) + if ((m_extension->active_extension > 0) && m_extension->switch_extension) // detach extension first, wait til next Update() or RequestStatus() call to change to the new extension m_extension->active_extension = 0; else @@ -223,8 +215,18 @@ void Wiimote::RequestStatus(const u16 _channelID, wm_request_status* rs) m_status.extension = m_extension->active_extension ? 1 : 0; // set register, I hate this line - m_register[ 0xa40000 ] = ((WiimoteEmu::Attachment*)m_extension->attachments[ m_extension->active_extension ])->reg; + m_register[0xa40000] = ((WiimoteEmu::Attachment*)m_extension->attachments[m_extension->active_extension])->reg; } +} + +// old comment +/* Here we produce a 0x20 status report to send to the Wii. We currently ignore + the status request rs and all its eventual instructions it may include (for + example turn off rumble or something else) and just send the status + report. */ +void Wiimote::RequestStatus(const wm_request_status* const rs) +{ + HandleExtensionSwap(); // set up report u8 data[8]; @@ -234,14 +236,31 @@ void Wiimote::RequestStatus(const u16 _channelID, wm_request_status* rs) // status values *(wm_status_report*)(data + 2) = m_status; + // hybrid wiimote stuff + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index] && (m_extension->switch_extension <= 0)) + { + using namespace WiimoteReal; + + g_refresh_critsec.Enter(); + if (g_wiimotes[m_index]) + { + wm_request_status rpt; + rpt.rumble = 0; + g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); + } + g_refresh_critsec.Leave(); + + return; + } + // send report - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data)); } /* Write data to Wiimote and Extensions registers. */ -void Wiimote::WriteData(const u16 _channelID, wm_write_data* wd) +void Wiimote::WriteData(const wm_write_data* const wd) { - u32 address = convert24bit(wd->address); + u32 address = swap24(wd->address); // ignore the 0x010000 bit address &= 0xFEFFFF; @@ -324,14 +343,24 @@ void Wiimote::WriteData(const u16 _channelID, wm_write_data* wd) } /* Read data from Wiimote and Extensions registers. */ -void Wiimote::ReadData(const u16 _channelID, wm_read_data* rd) +void Wiimote::ReadData(const wm_read_data* const rd) { - u32 address = convert24bit(rd->address); - u16 size = convert16bit(rd->size); + u32 address = swap24(rd->address); + u16 size = Common::swap16(rd->size); // ignore the 0x010000 bit address &= 0xFEFFFF; + // 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))) + { + 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; + } + ReadRequest rr; u8* block = new u8[size]; @@ -416,14 +445,14 @@ void Wiimote::ReadData(const u16 _channelID, wm_read_data* rd) } // want the requested address, not the above modified one - rr.address = convert24bit(rd->address); + rr.address = swap24(rd->address); rr.size = size; //rr.channel = _channelID; rr.position = 0; rr.data = block; // send up to 16 bytes - SendReadDataReply( _channelID, rr ); + SendReadDataReply(rr); // if there is more data to be sent, add it to the queue if (rr.size) @@ -440,7 +469,7 @@ void Wiimote::ReadData(const u16 _channelID, wm_read_data* rd) bytes in the message, the 0 means no error, the 00 20 means that the message is at the 00 20 offest in the registry that was read. */ -void Wiimote::SendReadDataReply(const u16 _channelID, ReadRequest& _request) +void Wiimote::SendReadDataReply(ReadRequest& _request) { u8 data[23]; data[0] = 0xA1; @@ -488,7 +517,7 @@ void Wiimote::SendReadDataReply(const u16 _channelID, ReadRequest& _request) } // Send a piece - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, data, sizeof(data)); + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, sizeof(data)); } void Wiimote::DoState(PointerWrap& p) diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp index 797160a6d..8d13cca32 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.cpp @@ -7,8 +7,10 @@ #include "WiimoteEmu.h" #include "WiimoteHid.h" -#include -#include +#include "../WiimoteReal/WiimoteReal.h" + +#include "Timer.h" +#include "Common.h" #include "UDPTLayer.h" @@ -38,10 +40,7 @@ static const u8 eeprom_data_16D0[] = { #define SWING_INTENSITY 0x40 -static struct ReportFeatures -{ - u8 core, accel, ir, ext, size; -} const reporting_mode_features[] = +const ReportFeatures reporting_mode_features[] = { //0x30: Core Buttons { 2, 0, 0, 0, 4 }, @@ -324,68 +323,35 @@ std::string Wiimote::GetName() const return std::string("Wiimote") + char('1'+m_index); } -void Wiimote::Update() -{ - const bool is_sideways = m_options->settings[1]->value > 0; - const bool is_upright = m_options->settings[2]->value > 0; +// if windows is focused or background input is enabled +#define HAS_FOCUS (g_WiimoteInitialize.pRendererHasFocus() || (m_options->settings[0]->value != 0)) - // if windows is focused or background input is enabled - const bool is_focus = g_WiimoteInitialize.pRendererHasFocus() || (m_options->settings[0]->value != 0); +bool Wiimote::Step() +{ + const bool has_focus = HAS_FOCUS; + const bool is_sideways = m_options->settings[1]->value != 0; // no rumble if no focus - if (false == is_focus) + if (false == has_focus) m_rumble_on = false; - m_rumble->controls[0]->control_ref->State(m_rumble_on); - - // ----speaker---- -#ifdef USE_WIIMOTE_EMU_SPEAKER - - ALint processed = 0; - alGetSourcei(m_audio_source, AL_BUFFERS_PROCESSED, &processed); - - while (processed--) - { - //PanicAlert("Buffer Processed"); - alSourceUnqueueBuffers(m_audio_source, 1, &m_audio_buffers.front().buffer); - alDeleteBuffers(1, &m_audio_buffers.front().buffer); - delete[] m_audio_buffers.front().samples; - m_audio_buffers.pop(); - } - - // testing speaker crap - //m_rumble->controls[0]->control_ref->State( m_speaker_data.size() > 0 ); - //if ( m_speaker_data.size() ) - //m_speaker_data.pop(); - //while ( m_speaker_data.size() ) - //{ - // std::ofstream file; - // file.open( "test.pcm", std::ios::app | std::ios::out | std::ios::binary ); - // file.put(m_speaker_data.front()); - // file.close(); - // m_speaker_data.pop(); - //} -#endif + m_rumble->controls[0]->control_ref->State(m_rumble_on); // update buttons in status struct m_status.buttons = 0; - if (is_focus) + if (has_focus) { m_buttons->GetState(&m_status.buttons, button_bitmasks); m_dpad->GetState(&m_status.buttons, is_sideways ? dpad_sideways_bitmasks : dpad_bitmasks); UDPTLayer::GetButtons(m_udp, &m_status.buttons); } - - // no channel == not connected i guess - if (0 == m_reporting_channel) - return; // check if there is a read data request if (m_read_requests.size()) { ReadRequest& rr = m_read_requests.front(); // send up to 16 bytes to the wii - SendReadDataReply(m_reporting_channel, rr); + SendReadDataReply(rr); //SendReadDataReply(rr.channel, rr); // if there is no more data, remove from queue @@ -396,179 +362,319 @@ void Wiimote::Update() } // dont send any other reports - return; + return true; } - // -- maybe this should happen before the read request stuff? // check if a status report needs to be sent // this happens on wiimote sync and when extensions are switched if (m_extension->active_extension != m_extension->switch_extension) { - RequestStatus(m_reporting_channel); + RequestStatus(); // Wiibrew: Following a connection or disconnection event on the Extension Port, // data reporting is disabled and the Data Reporting Mode must be reset before new data can arrive. // after a game receives an unrequested status report, // it expects data reports to stop until it sets the reporting mode again m_reporting_auto = false; + + return true; } - if (false == m_reporting_auto) - return; + return false; +} - // figure out what data we need - const ReportFeatures& rpt = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE]; +void Wiimote::GetCoreData(u8* const data) +{ + *(wm_core*)data |= m_status.buttons; +} - // what does the real wiimote do when put in a reporting mode with extension data, - // but with no extension attached? should i just send zeros? sure - //if (rpt.ext && (m_extension->active_extension <= 0)) - //{ - // m_reporting_auto = false; - // return; - //} +void Wiimote::GetAccelData(u8* const data) +{ + const bool has_focus = HAS_FOCUS; + const bool is_sideways = m_options->settings[1]->value != 0; + const bool is_upright = m_options->settings[2]->value != 0; - // set up output report - // made data bigger than needed in case the wii specifies the wrong ir mode for a reporting mode - u8 data[46]; - memset( data, 0, sizeof(data) ); + // ----TILT---- + EmulateTilt((wm_accel*)data, m_tilt, (accel_cal*)&m_eeprom[0x16], has_focus, is_sideways, is_upright); - data[0] = 0xA1; - data[1] = m_reporting_mode; + // ----SWING---- + // ----SHAKE---- + if (has_focus) + { + EmulateSwing((wm_accel*)data, m_swing, (accel_cal*)&m_eeprom[0x16], is_sideways, is_upright); + EmulateShake(data, m_shake, m_shake_step); + // UDP Wiimote + UDPTLayer::GetAcceleration(m_udp, (wm_accel*)data, (accel_cal*)&m_eeprom[0x16]); + } +} - // core buttons - if (rpt.core) - *(wm_core*)(data + rpt.core) = m_status.buttons; +void Wiimote::GetIRData(u8* const data) +{ + const bool has_focus = HAS_FOCUS; + + u16 x[4], y[4]; + memset(x, 0xFF, sizeof(x)); - // ----accelerometer---- - if (rpt.accel) + if (has_focus) { - // ----TILT---- - EmulateTilt((wm_accel*)&data[rpt.accel], m_tilt, (accel_cal*)&m_eeprom[0x16], is_focus, is_sideways, is_upright); + float xx = 10000, yy = 0, zz = 0; + float tx, ty; + + m_ir->GetState(&xx, &yy, &zz, true); + UDPTLayer::GetIR(m_udp, &xx, &yy, &zz); + + m_tilt->GetState(&tx, &ty, 0, PI/2, false); + + // disabled cause my math still fails + const float rsin = 0;//sin(tx); + const float rcos = 1;//cos(tx); - // ----SWING---- - // ----SHAKE---- - if (is_focus) { - EmulateSwing((wm_accel*)&data[rpt.accel], m_swing, (accel_cal*)&m_eeprom[0x16], is_sideways, is_upright); - EmulateShake(data + rpt.accel, m_shake, m_shake_step); - // UDP Wiimote - UDPTLayer::GetAcceleration(m_udp, (wm_accel*)&data[rpt.accel], (accel_cal*)&m_eeprom[0x16]); + const float xxx = (xx * -256 * 0.95f); + const float yyy = (yy * -256 * 0.90f); + + xx = 512 + xxx * rcos + (144 + yyy) * rsin; + yy = 384 + (108 + yyy) * rcos - xxx * rsin; } + + // dot distance of 25 is too little + const unsigned int distance = (unsigned int)(150 + 100 * zz); + + x[0] = (unsigned int)(xx - distance * rcos); + x[1] = (unsigned int)(xx + distance * rcos); + x[2] = (unsigned int)(xx - 1.2f * distance * rcos); + x[3] = (unsigned int)(xx + 1.2f * distance * rcos); + + y[0] = (unsigned int)(yy - 0.75 * distance * rsin); + y[1] = (unsigned int)(yy + 0.75 * distance * rsin); + y[2] = (unsigned int)(yy - 0.75 * 1.2f * distance * rsin); + y[3] = (unsigned int)(yy + 0.75 * 1.2f * distance * rsin); + } - // ----ir---- - if (rpt.ir) + // Fill report with valid data when full handshake was done + if (m_reg_ir->data[0x30]) + // ir mode + switch (m_reg_ir->mode) { - float xx = 10000, yy = 0, zz = 0; - unsigned int x[4], y[4]; + // basic + case 1 : + { + memset(data, 0xFF, 10); + wm_ir_basic* const irdata = (wm_ir_basic*)data; + for (unsigned int i=0; i<2; ++i) + { + if (x[i*2] < 1024 && y[i*2] < 768) + { + irdata[i].x1 = u8(x[i*2]); + irdata[i].x1hi = x[i*2] >> 8; - if (is_focus) + irdata[i].y1 = u8(y[i*2]); + irdata[i].y1hi = y[i*2] >> 8; + } + if (x[i*2+1] < 1024 && y[i*2+1] < 768) + { + irdata[i].x2 = u8(x[i*2+1]); + irdata[i].x2hi = x[i*2+1] >> 8; + + irdata[i].y2 = u8(y[i*2+1]); + irdata[i].y2hi = y[i*2+1] >> 8; + } + } + } + break; + // extended + case 3 : { - m_ir->GetState(&xx, &yy, &zz, true); - UDPTLayer::GetIR(m_udp, &xx, &yy, &zz); + memset(data, 0xFF, 12); + wm_ir_extended* const irdata = (wm_ir_extended*)data; + for (unsigned int i=0; i<4; ++i) + if (x[i] < 1024 && y[i] < 768) + { + irdata[i].x = u8(x[i]); + irdata[i].xhi = x[i] >> 8; - float tx, ty; - m_tilt->GetState(&tx, &ty, 0, 1, false); + irdata[i].y = u8(y[i]); + irdata[i].yhi = y[i] >> 8; - // TODO: fix tilt math stuff + irdata[i].size = 10; + } + } + break; + // full + case 5 : + // UNSUPPORTED + break; + } +} - const float rtan = tan(0.0f/*tx*/); // disabled cause my math fails - const float rsin = sin(rtan); - const float rcos = cos(rtan); +void Wiimote::GetExtData(u8* const data) +{ + const bool has_focus = HAS_FOCUS; - { - const float xxx = (xx * -256 * 0.95f); - const float yyy = (yy * -256 * 0.90f); + m_extension->GetState(data, HAS_FOCUS); - xx = 512 + xxx * rcos + yyy * rsin; - yy = 490 + yyy * rcos + xxx * rsin; - } + // i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this. + // i think it should be unencrpyted in the register, encrypted when read. + memcpy(m_reg_ext->controller_data, data, sizeof(wm_extension)); + + if (0xAA == m_reg_ext->encryption) + wiimote_encrypt(&m_ext_key, data, 0x00, sizeof(wm_extension)); +} - const unsigned int distance = (unsigned int)(200 + 100 * zz); +void Wiimote::Update() +{ + // no channel == not connected i guess + if (0 == m_reporting_channel) + return; - x[0] = (unsigned int)(xx - distance * rcos); - x[1] = (unsigned int)(xx + distance * rcos); - x[2] = (unsigned int)(xx - 1.2f * distance * rcos); - x[3] = (unsigned int)(xx + 1.2f * distance * rcos); + // returns true if a report was sent + if (Step()) + return; - y[0] = (unsigned int)(yy - 0.75 * distance * rsin); - y[1] = (unsigned int)(yy + 0.75 * distance * rsin); - y[2] = (unsigned int)(yy - 0.75 * 1.2f * distance * rsin); - y[3] = (unsigned int)(yy + 0.75 * 1.2f * distance * rsin); + // ----speaker---- +#ifdef USE_WIIMOTE_EMU_SPEAKER - } + ALint processed = 0; + alGetSourcei(m_audio_source, AL_BUFFERS_PROCESSED, &processed); + + while (processed--) + { + //PanicAlert("Buffer Processed"); + alSourceUnqueueBuffers(m_audio_source, 1, &m_audio_buffers.front().buffer); + alDeleteBuffers(1, &m_audio_buffers.front().buffer); + delete[] m_audio_buffers.front().samples; + m_audio_buffers.pop(); + } - // Fill report with valid data when full handshake was done - if (m_reg_ir->data[0x30]) - // ir mode - switch (m_reg_ir->mode) + // testing speaker crap + //m_rumble->controls[0]->control_ref->State( m_speaker_data.size() > 0 ); + //if ( m_speaker_data.size() ) + //m_speaker_data.pop(); + + //while ( m_speaker_data.size() ) + //{ + // std::ofstream file; + // file.open( "test.pcm", std::ios::app | std::ios::out | std::ios::binary ); + // file.put(m_speaker_data.front()); + // file.close(); + // m_speaker_data.pop(); + //} +#endif + + u8 data[MAX_PAYLOAD]; + memset(data, 0, sizeof(data)); + data[0] = 0xA1; + data[1] = m_reporting_mode; + + // figure out what data we need + const ReportFeatures& rptf = reporting_mode_features[m_reporting_mode - WM_REPORT_CORE]; + s8 rptf_size = rptf.size; + + // core buttons + if (rptf.core) + GetCoreData(data + rptf.core); + + // acceleration + if (rptf.accel) + GetAccelData(data + rptf.accel); + + // IR + if (rptf.ir) + GetIRData(data + rptf.ir); + + // extension + if (rptf.ext) + GetExtData(data + rptf.ext); + + // hybrid wiimote stuff + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index]) + { + using namespace WiimoteReal; + + g_refresh_critsec.Enter(); + if (g_wiimotes[m_index]) { - // basic - case 1 : - { - memset(data + rpt.ir, 0xFF, 10); - wm_ir_basic* const irdata = (wm_ir_basic*)(data + rpt.ir); - for (unsigned int i=0; i<2; ++i) + u8* const real_data = g_wiimotes[m_index]->ProcessReadQueue(); + if (real_data) { - if (x[i*2] < 1024 && y[i*2] < 768) + switch (real_data[1]) { - irdata[i].x1 = u8(x[i*2]); - irdata[i].x1hi = x[i*2] >> 8; + // use data reports + default: + if (real_data[1] >= WM_REPORT_CORE) + { + const ReportFeatures& real_rptf = reporting_mode_features[real_data[1] - WM_REPORT_CORE]; + + // force same report type from real-wiimote + if (&real_rptf != &rptf) + rptf_size = 0; + + // core + // mix real-buttons with emu-buttons in the status struct, and in the report + if (real_rptf.core && rptf.core) + { + m_status.buttons |= *(wm_core*)(real_data + real_rptf.core); + *(wm_core*)(data + rptf.core) = m_status.buttons; + } + + // accel + // use real-accel data always i guess + if (real_rptf.accel && rptf.accel) + memcpy(data + rptf.accel, real_data + real_rptf.accel, sizeof(wm_accel)); + + // ir + // TODO + + // ext + // use real-ext data if an emu-extention isn't chosen + if (real_rptf.ext && rptf.ext && (0 == m_extension->switch_extension)) + memcpy(data + rptf.ext, real_data + real_rptf.ext, sizeof(wm_extension)); + } + else if (WM_ACK_DATA != real_data[1] || m_extension->active_extension > 0) + rptf_size = 0; + else + // use real-acks if an emu-extension isn't chosen + rptf_size = -1; + break; + + // use all status reports, after modification of the extension bit + case WM_STATUS_REPORT : + //if (m_extension->switch_extension) + //((wm_status_report*)(real_data + 2))->extension = (m_extension->active_extension > 0); + if (m_extension->active_extension) + ((wm_status_report*)(real_data + 2))->extension = 1; + rptf_size = -1; + break; + + // use all read-data replies + case WM_READ_DATA_REPLY: + rptf_size = -1; + break; - irdata[i].y1 = u8(y[i*2]); - irdata[i].y1hi = y[i*2] >> 8; } - if (x[i*2+1] < 1024 && y[i*2+1] < 768) - { - irdata[i].x2 = u8(x[i*2+1]); - irdata[i].x2hi = x[i*2+1] >> 8; - irdata[i].y2 = u8(y[i*2+1]); - irdata[i].y2hi = y[i*2+1] >> 8; - } - } - } - break; - // extended - case 3 : - { - memset(data + rpt.ir, 0xFF, 12); - wm_ir_extended* const irdata = (wm_ir_extended*)(data + rpt.ir); - for (unsigned int i=0; i<4; ++i) - if (x[i] < 1024 && y[i] < 768) + // copy over report from real-wiimote + if (-1 == rptf_size) { - irdata[i].x = u8(x[i]); - irdata[i].xhi = x[i] >> 8; - - irdata[i].y = u8(y[i]); - irdata[i].yhi = y[i] >> 8; - - irdata[i].size = 10; + memcpy(data, real_data, MAX_PAYLOAD); + rptf_size = MAX_PAYLOAD; } + + if (real_data != g_wiimotes[m_index]->m_last_data_report) + delete[] real_data; } - break; - // full - case 5 : - // UNSUPPORTED - break; } + g_refresh_critsec.Leave(); } - // ----extension---- - if (rpt.ext) - { - m_extension->GetState(data + rpt.ext, is_focus); - - // i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this. - // i think it should be unencrpyted in the register, encrypted when read. - memcpy(m_reg_ext->controller_data, data + rpt.ext, sizeof(wm_extension)); + // don't send a data report if auto reporting is off + if (false == m_reporting_auto && data[2] >= WM_REPORT_CORE) + return; - if (0xAA == m_reg_ext->encryption) { - wiimote_encrypt(&m_ext_key, data + rpt.ext, 0x00, sizeof(wm_extension)); - } - } // send data report - g_WiimoteInitialize.pWiimoteInterruptChannel( m_index, m_reporting_channel, data, rpt.size ); + if (rptf_size) + g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_reporting_channel, data, rptf_size); } void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size) @@ -587,7 +693,7 @@ void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size // this all good? m_reporting_channel = _channelID; - hid_packet* hidp = (hid_packet*)_pData; + const hid_packet* const hidp = (hid_packet*)_pData; INFO_LOG(WIIMOTE, "Emu ControlChannel (page: %i, type: 0x%02x, param: 0x%02x)", m_index, hidp->type, hidp->param); @@ -606,7 +712,7 @@ void Wiimote::ControlChannel(const u16 _channelID, const void* _pData, u32 _Size { // AyuanX: My experiment shows Control Channel is never used // shuffle2: but homebrew uses this, so we'll do what we must :) - HidOutputReport(_channelID, (wm_report*)hidp->data); + HidOutputReport((wm_report*)hidp->data); u8 handshake = HID_HANDSHAKE_SUCCESS; g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, _channelID, &handshake, 1); @@ -631,7 +737,7 @@ void Wiimote::InterruptChannel(const u16 _channelID, const void* _pData, u32 _Si // this all good? m_reporting_channel = _channelID; - hid_packet* hidp = (hid_packet*)_pData; + const hid_packet* const hidp = (hid_packet*)_pData; switch (hidp->type) { @@ -640,8 +746,26 @@ void Wiimote::InterruptChannel(const u16 _channelID, const void* _pData, u32 _Si { case HID_PARAM_OUTPUT : { - wm_report* sr = (wm_report*)hidp->data; - HidOutputReport(_channelID, sr); + const wm_report* const sr = (wm_report*)hidp->data; + + if (WIIMOTE_SRC_HYBRID == g_wiimote_sources[m_index]) + { + switch (sr->wm) + { + // these two types are handled in RequestStatus() & ReadData() + case WM_REQUEST_STATUS : + case WM_READ_DATA : + break; + + default : + WiimoteReal::InterruptChannel(m_index, _channelID, _pData, _Size); + break; + } + + HidOutputReport(sr, m_extension->switch_extension > 0); + } + else + HidOutputReport(sr); } break; @@ -762,7 +886,7 @@ void Wiimote::Register::Read( size_t address, void* dst, size_t length ) } // TODO: i need to test this -void Wiimote::Register::Write( size_t address, void* src, size_t length ) +void Wiimote::Register::Write( size_t address, const void* src, size_t length ) { iterator i = begin(); const const_iterator e = end(); diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h index da01341d2..37e6c42f2 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteEmu.h @@ -8,7 +8,7 @@ // just used to get the OpenAL includes :p //#include -#include +#include "ControllerEmu.h" #include "ChunkFile.h" #include "WiimoteHid.h" @@ -32,6 +32,13 @@ extern SWiimoteInitialize g_WiimoteInitialize; namespace WiimoteEmu { +struct ReportFeatures +{ + u8 core, accel, ir, ext, size; +}; + +extern const ReportFeatures reporting_mode_features[]; + void EmulateShake(u8* const accel_data , ControllerEmu::Buttons* const buttons_group , unsigned int* const shake_step); @@ -77,6 +84,19 @@ public: void LoadDefaults(const ControllerInterface& ciface); +protected: + bool Step(); + void HidOutputReport(const wm_report* const sr, const bool send_ack = true); + void HandleExtensionSwap(); + + void GetCoreData(u8* const data); + void GetAccelData(u8* const data); + void GetIRData(u8* const data); + void GetExtData(u8* const data); + + bool HaveExtension() const { return m_extension->active_extension > 0; } + bool WantExtension() const { return m_extension->switch_extension != 0; } + private: struct ReadRequest { @@ -87,14 +107,12 @@ private: void Reset(); - void ReportMode(const u16 _channelID, wm_report_mode* dr); - void HidOutputReport(const u16 _channelID, wm_report* sr); - void SendAck(const u16 _channelID, u8 _reportID); - void RequestStatus(const u16 _channelID, wm_request_status* rs = NULL); - - void WriteData(const u16 _channelID, wm_write_data* wd); - void ReadData(const u16 _channelID, wm_read_data* rd); - void SendReadDataReply(const u16 _channelID, ReadRequest& _request); + void ReportMode(const wm_report_mode* const dr); + void SendAck(const u8 _reportID); + void RequestStatus(const wm_request_status* const rs = NULL); + void ReadData(const wm_read_data* const rd); + void WriteData(const wm_write_data* const wd); + void SendReadDataReply(ReadRequest& _request); #ifdef USE_WIIMOTE_EMU_SPEAKER void SpeakerData(wm_speaker_data* sd); @@ -131,7 +149,7 @@ private: class Register : public std::map< size_t, std::vector > { public: - void Write( size_t address, void* src, size_t length ); + void Write( size_t address, const void* src, size_t length ); void Read( size_t address, void* dst, size_t length ); } m_register; diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h index c0f73b8c9..a472920a0 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/WiimoteHid.h @@ -205,7 +205,7 @@ struct wm_read_data { u8 space : 2; //see WM_SPACE_* u8 : 5; u8 address[3]; - u8 size[2]; + u16 size; }; #define WM_SPACE_EEPROM 0 diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp index d3e68f8a1..8367c4754 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteNew.cpp @@ -3,9 +3,9 @@ #include "pluginspecs_wiimote.h" #include "WiimoteReal/WiimoteReal.h" +#include "WiimoteEmu/WiimoteEmu.h" #include "ControllerInterface/ControllerInterface.h" -#include "WiimoteEmu/WiimoteEmu.h" #if defined(HAVE_WX) && HAVE_WX #include "WiimoteConfigDiag.h" @@ -127,15 +127,11 @@ void InitPlugin( void* const hwnd ) // void Wiimote_ControlChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : + if (WIIMOTE_SRC_EMU & 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); - break; - case WIIMOTE_SRC_EMU : - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->ControlChannel( _channelID, _pData, _Size ); - break; - } } // __________________________________________________________________________________________________ @@ -169,15 +165,10 @@ unsigned int Wiimote_UnPairWiimotes(void) // void Wiimote_InterruptChannel(int _number, u16 _channelID, const void* _pData, u32 _Size) { - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) + ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->InterruptChannel(_channelID, _pData, _Size); + else WiimoteReal::InterruptChannel(_number, _channelID, _pData, _Size); - break; - case WIIMOTE_SRC_EMU : - ((WiimoteEmu::Wiimote*)g_plugin.controllers[ _number ])->InterruptChannel( _channelID, _pData, _Size ); - break; - } } // __________________________________________________________________________________________________ @@ -201,15 +192,10 @@ void Wiimote_Update(int _number) } _last_number = _number; - switch (g_wiimote_sources[_number]) - { - case WIIMOTE_SRC_REAL : - WiimoteReal::Update(_number); - break; - case WIIMOTE_SRC_EMU : + if (WIIMOTE_SRC_EMU & g_wiimote_sources[_number]) ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update(); - break; - } + else + WiimoteReal::Update(_number); g_plugin.controls_crit.Leave(); } diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp index c1112e642..74c8753f7 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp @@ -19,10 +19,8 @@ #include "Common.h" #include "IniFile.h" -#include "Thread.h" #include "StringUtil.h" #include "Timer.h" -#include "FifoQueue.h" #include "pluginspecs_wiimote.h" #include "wiiuse.h" @@ -46,45 +44,13 @@ Common::CriticalSection g_refresh_critsec, g_wiimote_critsec; THREAD_RETURN WiimoteThreadFunc(void* arg); -class Wiimote -{ -public: - Wiimote(wiimote_t* const wm, const unsigned int index); - ~Wiimote(); - - void ControlChannel(const u16 channel, const void* const data, const u32 size); - void InterruptChannel(const u16 channel, const void* const data, const u32 size); - void Update(); - - void Read(); - void Write(); - void Disconnect(); - void DisableDataReporting(); - - void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); - - // pointer to data, and size of data - typedef std::pair Report; - -private: - void ClearReports(); - - wiimote_t* const m_wiimote; - const unsigned int m_index; - - u16 m_channel; - u8 m_last_data_report[MAX_PAYLOAD]; - bool m_last_data_report_valid; - - Common::FifoQueue m_read_reports; - Common::FifoQueue m_write_reports; -}; +Wiimote *g_wiimotes[4]; Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) : m_wiimote(wm) , m_index(index) , m_channel(0) - , m_last_data_report_valid(false) + , m_last_data_report(NULL) { // disable reporting DisableDataReporting(); @@ -100,7 +66,7 @@ Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) //SendPacket(g_wiimotes_from_wiiuse[i], WM_LEDS, &rpt, sizeof(rpt)); //} - // Rumble briefly + // Rumble briefly, this is a bad spot for the rumble wiiuse_rumble(m_wiimote, 1); SLEEP(200); wiiuse_rumble(m_wiimote, 0); @@ -145,19 +111,26 @@ void Wiimote::SendPacket(const u8 rpt_id, const void* const data, const unsigned void Wiimote::DisableDataReporting() { - wm_report_mode rpt = wm_report_mode(); + wm_report_mode rpt; rpt.mode = WM_REPORT_CORE; + rpt.all_the_time = 0; + rpt.continuous = 0; + rpt.rumble = 0; SendPacket(WM_REPORT_MODE, &rpt, sizeof(rpt)); } void Wiimote::ClearReports() { - m_last_data_report_valid = false; + if (m_last_data_report) + { + delete[] m_last_data_report; + m_last_data_report = NULL; + } Report rpt; - while (m_read_reports.Pop(rpt.first)) - delete[] rpt.first; while (m_write_reports.Pop(rpt)) - delete[] rpt.first; + delete rpt.first; + while (m_read_reports.Pop(rpt.first)) + delete rpt.first; } void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) @@ -177,7 +150,8 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const while (wiiuse_io_read(m_wiimote)) {}; // request status - wm_request_status rpt = wm_request_status(); + wm_request_status rpt; + rpt.rumble = 0; SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } @@ -187,6 +161,24 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const rpt.first = new u8[size]; rpt.second = (u8)size; memcpy(rpt.first, (u8*)data, size); + + // some hax, since we just send the last data report to Dolphin on each Update() call + // , make the wiimote only send updated data reports when data changes + // == less bt traffic, eliminates some unneeded packets + if (WM_REPORT_MODE == ((u8*)data)[1]) + { + // also delete the last data report + if (m_last_data_report) + { + delete[] m_last_data_report; + m_last_data_report = NULL; + } + + // nice var names :p, this seems to be this one + ((wm_report_mode*)(rpt.first + 2))->all_the_time = false; + //((wm_report_mode*)(data + 2))->continuous = false; + } + m_write_reports.Push(rpt); } @@ -198,19 +190,10 @@ void Wiimote::Read() if (wiiuse_io_read(m_wiimote)) { - // a data report, save it - if (m_wiimote->event_buf[1] >= 0x30) - { - memcpy(m_last_data_report, m_wiimote->event_buf, MAX_PAYLOAD); - m_last_data_report_valid = true; - } - else - { - // some other report, add it to queue - u8* const rpt = new u8[MAX_PAYLOAD]; - memcpy(rpt, m_wiimote->event_buf, MAX_PAYLOAD); - m_read_reports.Push(rpt); - } + // add it to queue + u8* const rpt = new u8[MAX_PAYLOAD]; + memcpy(rpt, m_wiimote->event_buf, MAX_PAYLOAD); + m_read_reports.Push(rpt); } } @@ -224,20 +207,37 @@ void Wiimote::Write() } } -void Wiimote::Update() +// returns the next report that should be sent +u8* Wiimote::ProcessReadQueue() { - // do we have some queued reports - u8* rpt; - if (m_read_reports.Pop(rpt)) + // pop through the queued reports + u8* rpt = m_last_data_report; + while (m_read_reports.Pop(rpt)) { + // a data report + if (rpt[1] >= WM_REPORT_CORE) + m_last_data_report = rpt; + // some other kind of report + else + return rpt; + } + + // the queue was empty, or there were only data reports + return rpt; +} + +void Wiimote::Update() +{ + // pop through the queued reports + u8* const rpt = ProcessReadQueue(); + + // send the report + if (rpt) g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, MAX_PAYLOAD); + + // delete the data if it isn't also the last data rpt + if (rpt != m_last_data_report) delete[] rpt; - } - else if (m_last_data_report_valid) - { - // otherwise send the last data report, if there is one - g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, m_last_data_report, MAX_PAYLOAD); - } } void Wiimote::Disconnect() @@ -248,14 +248,14 @@ void Wiimote::Disconnect() DisableDataReporting(); // clear queue - ClearReports(); + u8 *rpt; + while (m_read_reports.Pop(rpt)) + delete rpt; // clear out wiiuse queue, or maybe not, silly? idk while (wiiuse_io_read(m_wiimote)) {}; } -Wiimote* g_wiimotes[4]; - void LoadSettings() { std::string ini_filename = (std::string(File::GetUserPath(D_CONFIG_IDX)) + g_plugin.ini_name + ".ini" ); @@ -284,7 +284,7 @@ unsigned int Initialize() // only call wiiuse_find with the number of slots configured for real wiimotes unsigned int wanted_wiimotes = 0; for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) - if (WIIMOTE_SRC_REAL == g_wiimote_sources[i]) + if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ++wanted_wiimotes; // don't bother initializing wiiuse if we don't want any real wiimotes @@ -320,14 +320,11 @@ unsigned int Initialize() g_wiimote_critsec.Enter(); // enter // create real wiimote class instances, assign wiimotes - for (unsigned int i = 0, w = 0; iall_the_time = false; - //((wm_report_mode*)(data + 2))->continuous = false; - } - g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) - g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, data, _Size); + g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); g_refresh_critsec.Leave(); - - if (data != _pData) - delete[] data; } void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h index 9a31cd4a8..d557afa8b 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.h @@ -21,6 +21,9 @@ #include "wiiuse.h" #include "ChunkFile.h" +#include "Thread.h" +#include "FifoQueue.h" +#include "../WiimoteEmu/WiimoteEmu.h" #include "../../InputCommon/Src/InputConfig.h" @@ -33,13 +36,53 @@ extern SWiimoteInitialize g_WiimoteInitialize; enum { WIIMOTE_SRC_NONE = 0, - WIIMOTE_SRC_EMU, - WIIMOTE_SRC_REAL, + WIIMOTE_SRC_EMU = 1, + WIIMOTE_SRC_REAL = 2, + WIIMOTE_SRC_HYBRID = 3, // emu + real }; namespace WiimoteReal { +class Wiimote +{ + friend class WiimoteEmu::Wiimote; +public: + Wiimote(wiimote_t* const wm, const unsigned int index); + ~Wiimote(); + + void ControlChannel(const u16 channel, const void* const data, const u32 size); + void InterruptChannel(const u16 channel, const void* const data, const u32 size); + void Update(); + + u8* ProcessReadQueue(); + + void Read(); + void Write(); + void Disconnect(); + void DisableDataReporting(); + + void SendPacket(const u8 rpt_id, const void* const data, const unsigned int size); + + // pointer to data, and size of data + typedef std::pair Report; + +protected: + u8 *m_last_data_report; + u16 m_channel; + +private: + void ClearReports(); + + wiimote_t* const m_wiimote; + const unsigned int m_index; + Common::FifoQueue m_read_reports; + Common::FifoQueue m_write_reports; +}; + +extern Common::CriticalSection g_refresh_critsec; +extern Wiimote *g_wiimotes[4]; + unsigned int Initialize(); void Shutdown(); void Refresh(); -- 2.11.4.GIT