Apply (a variation of) the first patch attached to issue 4608. This should limit the amount of ACL packet loss due to the 200Hz timing (which is now 150Hz if you disable Wiimote Speaker) and the handling of the ACL pool when it's occasionally full (which this improves by dropping one packet instead of letting the "pointers" overlap which would make packets unreachable).

See comment #6 for more details on the changes to WII_IPC_HLE_Device_usb.

In addition to that, rework some comments a bit (such as those from the
original patch; plus Ayuanx's one about maintaining Wiimote timing, which lost
relevance since r7272 which made Wiimote::Update timing independent from IPC
timing), and remove an unused global variable (event for watchdog hack)...

In short, this should address *some* of the Wiimote disconnection and/or "forgotten extension" problems that appeared with r7272 and/or r7394.  To prevent the "ACL queue is full" warnings from appearing (View->Show Log), pay attention to the amount of enabled Wiimotes (use as few as possible, connect the extra Wiimotes only when needed), and make sure to disable the "Disable Wiimote Speaker" option (if unneeded or causing problems) in the game properties.  If possible, make sure to use real Wiimotes instead of emulated ones, as well.
If Wiimotes disconnect forever (and cannot be reconnected using the Alt+Fx hotkeys), open the Wiimote config window, set the faulty Wiimote's type to "None", close/reopen the window, and set the previous Wiimote type back.

Note that it's not a *complete* fix for issue 4608!  This only fixes about half (or maybe third) of the possible causes of this issue...  But at least this should make the accurate Wiimote emulation (I mean, with the limitation of the ACL queue included) more usable in some cases (such as multi-player).
Nope, I didn't (and can't yet) perform in-depth tests on the real hardware myself (unlike some developers), I just rely on the given "accurate" code and numbers (such as the 10-packet limit implemented by godisgovernment)...
Maybe I'll get to fixing other problem "causes" (if I feel like doing it), maybe not in a while...  After all, I have other hobbies, and it's the summer holidays for me...

Anyway, feel free to test and comment.

Update issue 4667
Update issue 4608
Update issue 4604
Update issue 4583
Update issue 4436
Update issue 4353
Update issue 4013

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7675 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
DimitriPilot3 2011-07-12 15:49:08 +00:00
parent ebce13fba7
commit bb827eb837
3 changed files with 34 additions and 12 deletions

View File

@ -113,7 +113,6 @@ int et_AI;
int et_AudioDMA; int et_AudioDMA;
int et_DSP; int et_DSP;
int et_IPC_HLE; int et_IPC_HLE;
int et_FakeGPWD; // DC watchdog hack
int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
// These are badly educated guesses // These are badly educated guesses
@ -244,11 +243,12 @@ void Init()
// AyuanX: TO BE TWEAKED // AyuanX: TO BE TWEAKED
// Now the 1500 is a pure assumption // Now the 1500 is a pure assumption
// We need to figure out the real frequency though // We need to figure out the real frequency though
// PS: When this period is tweaked, the interval
// in WII_IPC_HLE_Device_usb.cpp should also be tweaked accordingly // FIXME: does Wiimote Speaker support really require a different interval? (issue 4608)
// to guarantee WiiMote updates at a fixed 100Hz const int interval = SConfig::GetInstance().m_LocalCoreStartupParameter.
int interval = SConfig::GetInstance().m_LocalCoreStartupParameter.bDisableWiimoteSpeaker?1250:1500; bDisableWiimoteSpeaker ? 1250 : 1500;
int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.bVBeam?2:1; const int fields = SConfig::GetInstance().m_LocalCoreStartupParameter.
bVBeam ? 2 : 1;
IPC_HLE_PERIOD = GetTicksPerSecond() / (interval * fields); IPC_HLE_PERIOD = GetTicksPerSecond() / (interval * fields);
} }
else else

View File

@ -18,6 +18,7 @@
#include "../Core.h" #include "../Core.h"
#include "../Debugger/Debugger_SymbolMap.h" #include "../Debugger/Debugger_SymbolMap.h"
#include "../Host.h" #include "../Host.h"
#include "../HW/SystemTimers.h"
#include "../HW/Wiimote.h" #include "../HW/Wiimote.h"
#include "../HW/WII_IPC.h" #include "../HW/WII_IPC.h"
#include "WII_IPC_HLE.h" #include "WII_IPC_HLE.h"
@ -495,17 +496,24 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
} }
} }
// The Real Wiimote sends report every ~6.66ms. // The Real Wiimote sends report every ~6.66ms (150 Hz).
// However, we don't actually reach here at dependable intervals, so we // However, we don't actually reach here at dependable intervals, so we
// instead just timeslice in such a way that makes the stack think we have // instead just timeslice in such a way that makes the stack think we have
// perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some // perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some
// idle time. // idle time.
static int wiimote_to_update = 0; // Somehow, Dolphin's Wiimote Speaker support requires using an update interval
const u64 interval = 729000000u / 200; // 5ms behaves well // of 5ms (200 Hz) for its output to work. This increased frequency tends to
u64 each_wiimote_interval = interval / m_WiiMotes.size(); // fill the ACL queue (even) quicker than it can be processed by Dolphin,
u64 now = CoreTiming::GetTicks(); // especially during simultaneous requests involving many (emulated) Wiimotes...
// Thus, we only use that interval when the option is enabled. See issue 4608.
const u64 interval = SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().
m_LocalCoreStartupParameter.bDisableWiimoteSpeaker ? 150 : 200);
const u64 each_wiimote_interval = interval / m_WiiMotes.size();
const u64 now = CoreTiming::GetTicks();
if (now - m_last_ticks > each_wiimote_interval) if (now - m_last_ticks > each_wiimote_interval)
{ {
static int wiimote_to_update = 0;
if (m_WiiMotes[wiimote_to_update].IsConnected()) if (m_WiiMotes[wiimote_to_update].IsConnected())
{ {
NetPlay_WiimoteUpdate(wiimote_to_update); NetPlay_WiimoteUpdate(wiimote_to_update);

View File

@ -182,10 +182,24 @@ private:
{ {
_dbg_assert_msg_(WII_IPC_WIIMOTE, _dbg_assert_msg_(WII_IPC_WIIMOTE,
size < m_acl_pkt_size, "acl packet too large for pool"); size < m_acl_pkt_size, "acl packet too large for pool");
const int next_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num;
if (next_write_ptr == m_read_ptr)
{
// Many simultaneous exchanges of ACL packets tend to cause the
// 10-packet limit to be exceeded. Typically, this occurs when
// many emulated Wiimotes are requesting connections at once.
// See issue 4608 for more info.
ERROR_LOG(WII_IPC_WIIMOTE, "ACL queue is full - current packet will be "
"dropped! (m_write_ptr(%d) was about to overlap m_read_ptr(%d))",
m_write_ptr, m_read_ptr);
return;
}
memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size); memcpy(m_pool + m_acl_pkt_size * m_write_ptr, data, size);
m_info[m_write_ptr].size = size; m_info[m_write_ptr].size = size;
m_info[m_write_ptr].conn_handle = conn_handle; m_info[m_write_ptr].conn_handle = conn_handle;
m_write_ptr = (m_write_ptr + 1) % m_acl_pkts_num; m_write_ptr = next_write_ptr;
} }
void WriteToEndpoint(CtrlBuffer& endpoint); void WriteToEndpoint(CtrlBuffer& endpoint);