diff --git a/Source/Core/Common/Common.vcproj b/Source/Core/Common/Common.vcproj index faf070d84e..384ab34680 100644 --- a/Source/Core/Common/Common.vcproj +++ b/Source/Core/Common/Common.vcproj @@ -665,6 +665,10 @@ RelativePath=".\Src\ExtendedTrace.h" > + + diff --git a/Source/Core/Common/Src/FifoQueue.h b/Source/Core/Common/Src/FifoQueue.h new file mode 100644 index 0000000000..380f4f6da4 --- /dev/null +++ b/Source/Core/Common/Src/FifoQueue.h @@ -0,0 +1,101 @@ + +#ifndef _FIFO_QUEUE_H_ +#define _FIFO_QUEUE_H_ + +// a simple lockless thread-safe, +// single reader, single writer queue + +namespace Common +{ + +template +class FifoQueue +{ +public: + FifoQueue() + { + m_write_ptr = m_read_ptr = new ElementPtr(); + } + + ~FifoQueue() + { + // this will empty out the whole queue + delete m_read_ptr; + } + + bool Empty() const // true if the queue is empty + { + return (m_read_ptr == m_write_ptr); + } + + void Push(const T& t) + { + // create the element, add it to the queue + m_write_ptr->current = new T(t); + // set the next pointer to a new element ptr + // then advance the write pointer + m_write_ptr = m_write_ptr->next = new ElementPtr(); + } + + bool Pop(T& t) + { + // 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; + + 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) + { + // 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; + + return true; + } + +private: + // stores a pointer to element at front of queue + // and a pointer to the next ElementPtr + class ElementPtr + { + public: + ElementPtr() : current(NULL), next(NULL) {} + + ~ElementPtr() + { + if (current) + { + delete current; + // recusion ftw + if (next) + delete next; + } + } + + T *volatile current; + ElementPtr *volatile next; + }; + + ElementPtr *volatile m_write_ptr; + ElementPtr *volatile m_read_ptr; +}; + +} + +#endif diff --git a/Source/Core/Core/Src/GeckoCode.cpp b/Source/Core/Core/Src/GeckoCode.cpp index 560e8d9ff6..590f56980c 100644 --- a/Source/Core/Core/Src/GeckoCode.cpp +++ b/Source/Core/Core/Src/GeckoCode.cpp @@ -3,6 +3,7 @@ #include "Thread.h" #include "HW/Memmap.h" +#include "ConfigManager.h" #include "vector" @@ -142,6 +143,8 @@ bool RunGeckoCode(GeckoCode& gecko_code) bool RunActiveCodes() { + if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) + return true; if (false == active_codes_lock.TryEnter()) return true; diff --git a/Source/Core/InputUICommon/Src/ConfigDiag.cpp b/Source/Core/InputUICommon/Src/ConfigDiag.cpp index b9f14703a6..ec4ee31a2b 100644 --- a/Source/Core/InputUICommon/Src/ConfigDiag.cpp +++ b/Source/Core/InputUICommon/Src/ConfigDiag.cpp @@ -533,7 +533,7 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser( wxWindow* const parent, w button_sizer->Add(add_button, 1, 0, 5); } - range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT * 2, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ ); + range_slider = new wxSlider( parent, -1, SLIDER_TICK_COUNT, 0, SLIDER_TICK_COUNT * 5, wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/ ); range_slider->SetValue( control_reference->range * SLIDER_TICK_COUNT ); diff --git a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp index dd82375b23..4cfedf47cd 100644 --- a/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp +++ b/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteReal/WiimoteReal.cpp @@ -22,6 +22,7 @@ #include "Thread.h" #include "StringUtil.h" #include "Timer.h" +#include "FifoQueue.h" #include "pluginspecs_wiimote.h" #include "wiiuse.h" @@ -41,7 +42,7 @@ volatile unsigned int g_wiimotes_lastfound = 0; volatile bool g_run_wiimote_thread = false; Common::Thread *g_wiimote_thread = NULL; -Common::CriticalSection g_wiimote_critsec; +Common::CriticalSection g_refresh_critsec, g_wiimote_critsec; THREAD_RETURN WiimoteThreadFunc(void* arg); @@ -67,6 +68,7 @@ public: void Update(); void Read(); + void Write(); void Disconnect(); void DisableDataReporting(); @@ -80,7 +82,8 @@ private: u8 m_last_data_report[MAX_PAYLOAD]; bool m_last_data_report_valid; - std::queue m_reports; + Common::FifoQueue m_read_reports; + Common::FifoQueue m_write_reports; }; Wiimote::Wiimote(wiimote_t* const wm, const unsigned int index) @@ -126,7 +129,7 @@ Wiimote::~Wiimote() //{ // //u8* const rpt = new u8[2]; // //rpt[0] = 0XA1; rpt[1] = 0x15; - // //m_reports.push(rpt); + // //m_read_reports.push(rpt); // //Update(); // const u8 rpt[] = { 0xA1, 0x15 }; @@ -144,11 +147,11 @@ void Wiimote::DisableDataReporting() void Wiimote::ClearReports() { m_last_data_report_valid = false; - while (m_reports.size()) - { - delete[] m_reports.front(); - m_reports.pop(); - } + u8* rpt; + while (m_read_reports.Pop(rpt)) + delete[] rpt; + while (m_write_reports.Pop(rpt)) + delete[] rpt; } void Wiimote::ControlChannel(const u16 channel, const void* const data, const u32 size) @@ -172,8 +175,11 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const SendPacket(m_wiimote, WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } - m_channel = channel; - wiiuse_io_write(m_wiimote, (byte*)data, size); + m_channel = channel; // this right? + + u8* const rpt = new u8[MAX_PAYLOAD]; + memcpy(rpt, (byte*)data, MAX_PAYLOAD); + m_write_reports.Push(rpt); } void Wiimote::Read() @@ -195,18 +201,27 @@ void Wiimote::Read() // some other report, add it to queue u8* const rpt = new u8[MAX_PAYLOAD]; memcpy(rpt, m_wiimote->event_buf, MAX_PAYLOAD); - m_reports.push(rpt); + m_read_reports.Push(rpt); } } } +void Wiimote::Write() +{ + u8* rpt; + if (m_write_reports.Pop(rpt)) + { + wiiuse_io_write(m_wiimote, rpt, MAX_PAYLOAD); + delete[] rpt; + } +} + void Wiimote::Update() { // do we have some queued reports - if (m_reports.size()) + u8* rpt; + if (m_read_reports.Pop(rpt)) { - u8* const rpt = m_reports.front(); - m_reports.pop(); g_WiimoteInitialize.pWiimoteInterruptChannel(m_index, m_channel, rpt, MAX_PAYLOAD); delete[] rpt; } @@ -358,9 +373,11 @@ void Shutdown(void) #endif } -#ifdef __linux__ -void Refresh() +void Refresh() // this gets called from the GUI thread { + g_refresh_critsec.Enter(); + +#ifdef __linux__ // make sure real wiimotes have been initialized if (!g_real_wiimotes_initialized) { @@ -402,22 +419,18 @@ void Refresh() g_wiimotes_found = num_wiimotes; g_wiimote_critsec.Leave(); // leave - - return; -} -#else -void Refresh() -{ +#else // windows/ OSX + // should be fine i think Shutdown(); - Initialize(); -} + Initialize(); #endif + g_refresh_critsec.Leave(); +} + void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - g_wiimote_critsec.Enter(); // enter - u8* data = (u8*)_pData; // some hax, since we just send the last data report to Dolphin on each Update() call @@ -434,10 +447,12 @@ void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u3 //((wm_report_mode*)(data + 2))->continuous = false; } + g_refresh_critsec.Enter(); + if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, data, _Size); - g_wiimote_critsec.Leave(); // leave + g_refresh_critsec.Leave(); if (data != _pData) delete[] data; @@ -445,24 +460,24 @@ void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u3 void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - g_wiimote_critsec.Enter(); // enter + g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); - g_wiimote_critsec.Leave(); // leave + g_refresh_critsec.Leave(); } // Read the Wiimote once void Update(int _WiimoteNumber) { - g_wiimote_critsec.Enter(); // enter + g_refresh_critsec.Enter(); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); - g_wiimote_critsec.Leave(); // leave + g_refresh_critsec.Leave(); } void StateChange(PLUGIN_EMUSTATE newState) @@ -476,7 +491,7 @@ void StateChange(PLUGIN_EMUSTATE newState) THREAD_RETURN WiimoteThreadFunc(void* arg) { - Common::SetCurrentThreadName("Wiimote Read"); + Common::SetCurrentThreadName("Wiimote Thread"); while (g_run_wiimote_thread) { @@ -484,11 +499,13 @@ THREAD_RETURN WiimoteThreadFunc(void* arg) for (unsigned int i=0; iRead(); + g_wiimotes[i]->Write(); + } g_wiimote_critsec.Leave(); // leave - // hmmm, i get occasional lockups without this :/ Common::SleepCurrentThread(1); }