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