From a80429b0209391e1548db01696a72b411652b78a Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Wed, 2 Mar 2011 12:06:06 +0000 Subject: [PATCH] Fix the wiimote speaker problem in the core and remove the HLE patch for it. Real wiimote tested on windows, untested but should work on linux, dunno about osx. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7272 8ced0084-cf51-0410-be5f-012b33b47a6e --- Data/Sys/totaldb.dsy | Bin 723116 -> 722980 bytes Source/Core/Core/Src/Boot/Boot.cpp | 14 -- Source/Core/Core/Src/ConfigManager.cpp | 4 +- Source/Core/Core/Src/ConfigManager.h | 1 - Source/Core/Core/Src/HLE/HLE.cpp | 3 +- Source/Core/Core/Src/HLE/HLE_Misc.cpp | 37 ------ Source/Core/Core/Src/HLE/HLE_Misc.h | 1 - .../Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 18 ++- .../Core/Core/Src/HW/WiimoteEmu/Speaker.cpp | 90 +++++++++---- .../Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h | 19 ++- Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp | 7 + .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 39 ++++-- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 1 + .../Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp | 125 +++++++++--------- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h | 4 +- Source/Core/Core/Src/IPC_HLE/hci.h | 12 +- Source/Core/DolphinWX/Src/ConfigMain.cpp | 19 +-- Source/Core/DolphinWX/Src/ConfigMain.h | 2 - 18 files changed, 196 insertions(+), 200 deletions(-) diff --git a/Data/Sys/totaldb.dsy b/Data/Sys/totaldb.dsy index bd758342b055c1cb9fb8db53cbdb6873fd76253c..790a942eaefc071dfcad998bcc985dc239e2582f 100644 GIT binary patch delta 45 zcmZ28QD?~n9mXS#jIE4}t&B{qjLfZ!EUk>Jt&D7~jO?w99IcF;t&Ch-8M&1?03Tfn AZ~y=R delta 72 zcmZ27L1)cG9mb=LjIE4}t&B{qjLfZ!EUk>Jt&D7~jO?w99IcF;t&Ch-8M&1?gy*i? c>teykz~EWzR9ajaTvC)9KiN>Hn2CV_0J$|1(f|Me diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index c5cc037823..ff1a437255 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -47,7 +47,6 @@ #include "../ConfigManager.h" #include "VolumeCreator.h" // DiscIO #include "NANDContentLoader.h" -#include "CommonPaths.h" void CBoot::Load_FST(bool _bIsWii) { @@ -218,19 +217,6 @@ bool CBoot::BootUp() EmulatedBS2(_StartupPara.bWii); } - // Scan for common HLE functions - if (!_StartupPara.bEnableDebugging) - { - PPCAnalyst::FindFunctions(0x80000000, 0x81800000, &g_symbolDB); - SignatureDB db; - if (db.Load((File::GetSysDirectory() + TOTALDB).c_str())) - { - db.Apply(&g_symbolDB); - } - HLE::PatchFunctions(); - g_symbolDB.Clear(); - } - /* Try to load the symbol map if there is one, and then scan it for and eventually replace code */ if (LoadMapFromFilename(_StartupPara.m_strFilename, gameID)) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index 7c6c14e325..6e1404abc5 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -222,7 +222,6 @@ void SConfig::SaveSettings() ini.Set("Core", "WiiSDCard", m_WiiSDCard); ini.Set("Core", "WiiKeyboard", m_WiiKeyboard); - ini.Set("Core", "WiimoteSpeaker", m_WiimoteSpeaker); ini.Set("Core", "WiimoteReconnectOnLoad", m_WiimoteReconnectOnLoad); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); @@ -350,8 +349,7 @@ void SConfig::LoadSettings() ini.Get("Core", "WiiSDCard", &m_WiiSDCard, false); ini.Get("Core", "WiiKeyboard", &m_WiiKeyboard, false); - ini.Get("Core", "WiimoteSpeaker", &m_WiimoteSpeaker, false); - ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); + ini.Get("Core", "WiimoteReconnectOnLoad", &m_WiimoteReconnectOnLoad, true); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index 87b0a9ef06..a3d66bde9c 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -33,7 +33,6 @@ struct SConfig : NonCopyable bool m_WiiKeyboard; bool m_WiiAutoReconnect[4]; bool m_WiiAutoUnpair; - int m_WiimoteSpeaker; bool m_WiimoteReconnectOnLoad; // name of the last used filename diff --git a/Source/Core/Core/Src/HLE/HLE.cpp b/Source/Core/Core/Src/HLE/HLE.cpp index 565ccdb157..84c6b2eb86 100644 --- a/Source/Core/Core/Src/HLE/HLE.cpp +++ b/Source/Core/Core/Src/HLE/HLE.cpp @@ -59,6 +59,7 @@ static const SPatch OSPatches[] = // debug out is very nice ;) { "OSReport", HLE_OS::HLE_GeneralDebugPrint }, { "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, + { "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, { "OSPanic", HLE_OS::HLE_OSPanic }, { "vprintf", HLE_OS::HLE_GeneralDebugPrint }, { "printf", HLE_OS::HLE_GeneralDebugPrint }, @@ -93,8 +94,6 @@ static const SPatch OSPatches[] = // Name doesn't matter, installed in CBoot::BootUp() { "HBReload", HLE_Misc::HBReload }, - // hax :| - { "IsBusyStrm_", HLE_Misc::IsBusyStream }, }; static const SPatch OSBreakPoints[] = diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.cpp b/Source/Core/Core/Src/HLE/HLE_Misc.cpp index 82633076db..d69bf09680 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/Src/HLE/HLE_Misc.cpp @@ -22,8 +22,6 @@ #include "../PowerPC/PowerPC.h" #include "../HW/Memmap.h" #include "../Host.h" -#include "CoreTiming.h" -#include "ConfigManager.h" namespace HLE_Misc { @@ -284,39 +282,4 @@ void HBReload() Host_Message(WM_USER_STOP); } -u8 isBusyPoll = 0; - -// Hack: Wiimotes are never too busy to process speaker data -void IsBusyStream() -{ - if (SConfig::GetInstance().m_WiimoteSpeaker == 1) - { - GPR(3) = 0; - } - else if (SConfig::GetInstance().m_WiimoteSpeaker == 2) - { - isBusyPoll++; - - // Signal that the wiimote is idle for a few cycles, allowing sound - // to be processed. - if (isBusyPoll < 5) - { - // Wiimote is idle - GPR(3) = 0; - } - else - { - // Wiimote is busy - GPR(3) = 1; - if (isBusyPoll >= 8) - isBusyPoll = 0; - } - } - else - { - GPR(3) = 1; - } - NPC = LR; -} - } diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.h b/Source/Core/Core/Src/HLE/HLE_Misc.h index dd3bef679f..6c932258a7 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.h +++ b/Source/Core/Core/Src/HLE/HLE_Misc.h @@ -39,7 +39,6 @@ namespace HLE_Misc void FZ_sqrt_internal(); void FZ_rsqrt_internal(); void HBReload(); - void IsBusyStream(); } #endif diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 65435f4c6c..319da3d5f5 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -118,7 +118,7 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) break; case WM_SPEAKER_ENABLE : // 0x14 - //INFO_LOG(WIIMOTE, "WM Speaker Enable: 0x%02x", sr->data[0]); + //ERROR_LOG(WIIMOTE, "WM Speaker Enable: %02x", sr->enable); //PanicAlert( "WM Speaker Enable: %d", sr->data[0] ); m_status.speaker = sr->enable; if (false == sr->ack) @@ -140,13 +140,17 @@ void Wiimote::HidOutputReport(const wm_report* const sr, const bool send_ack) break; case WM_WRITE_SPEAKER_DATA : // 0x18 + { + //wm_speaker_data *spkz = (wm_speaker_data*)sr->data; + //ERROR_LOG(WIIMOTE, "WM_WRITE_SPEAKER_DATA len:%x %s", spkz->length, + // ArrayToString(spkz->data, spkz->length, 100, false).c_str()); Wiimote::SpeakerData((wm_speaker_data*)sr->data); - // TODO: Does this need an ack? + } return; // no ack break; case WM_SPEAKER_MUTE : // 0x19 - //INFO_LOG(WIIMOTE, "WM Speaker Mute: 0x%02x", sr->data[0]); + //ERROR_LOG(WIIMOTE, "WM Speaker Mute: %02x", sr->enable); //PanicAlert( "WM Speaker Mute: %d", sr->data[0] & 0x04 ); // testing //if (sr->data[0] & 0x04) @@ -354,6 +358,14 @@ void Wiimote::WriteData(const wm_write_data* const wd) else return; // TODO: generate a writedata error reply + /* TODO? + if (region_ptr == &m_reg_speaker) + { + ERROR_LOG(WIIMOTE, "Write to speaker reg %x %s", address, + ArrayToString(wd->data, wd->size, 100, false).c_str()); + } + */ + if (&m_reg_ext == region_ptr) { // Run the key generation on all writes in the key area, it doesn't matter diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp index 0db7b09fe8..ba01239bf2 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/Speaker.cpp @@ -16,79 +16,111 @@ // http://code.google.com/p/dolphin-emu/ #include "WiimoteEmu.h" + +//#define WIIMOTE_SPEAKER_DUMP +#ifdef WIIMOTE_SPEAKER_DUMP #include +#include "WaveFile.h" +#include +#include "FileUtil.h" +#endif -// Yamaha ADPCM decoder code based on The ffmpeg Project (Copyright (c) 2001-2003) - -typedef struct ADPCMChannelStatus +namespace WiimoteEmu { - int predictor; - int step; -} ADPCMChannelStatus; -static const int yamaha_difflookup[] = { +// Yamaha ADPCM decoder code based on The ffmpeg Project (Copyright (s) 2001-2003) + +static const s32 yamaha_difflookup[] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 }; -static const int yamaha_indexscale[] = { +static const s32 yamaha_indexscale[] = { 230, 230, 230, 230, 307, 409, 512, 614, 230, 230, 230, 230, 307, 409, 512, 614 }; -static u16 av_clip_int16(int a) +static u16 av_clip16(s32 a) { if ((a+32768) & ~65535) return (a>>31) ^ 32767; else return a; } -static int av_clip(int a, int amin, int amax) +static s32 av_clip(s32 a, s32 amin, s32 amax) { if (a < amin) return amin; else if (a > amax) return amax; else return a; } -static s16 adpcm_yamaha_expand_nibble(ADPCMChannelStatus *c, unsigned char nibble) +static s16 adpcm_yamaha_expand_nibble(ADPCMState& s, u8 nibble) { - if(!c->step) { - c->predictor = 0; - c->step = 127; + if(!s.step) { + s.predictor = 0; + s.step = 0; } - c->predictor += (c->step * yamaha_difflookup[nibble]) / 8; - c->predictor = av_clip_int16(c->predictor); - c->step = (c->step * yamaha_indexscale[nibble]) >> 8; - c->step = av_clip(c->step, 127, 24567); - return c->predictor; + s.predictor += (s.step * yamaha_difflookup[nibble]) / 8; + s.predictor = av_clip16(s.predictor); + s.step = (s.step * yamaha_indexscale[nibble]) >> 8; + s.step = av_clip(s.step, 127, 24576); + return s.predictor; } -namespace WiimoteEmu -{ -ADPCMChannelStatus cs; +#ifdef WIIMOTE_SPEAKER_DUMP +std::ofstream ofile; +WaveFileWriter wav; + +void stopdamnwav(){wav.Stop();ofile.close();} +#endif void Wiimote::SpeakerData(wm_speaker_data* sd) { - s16 samples[40]; + // TODO consider using static max size instead of new + s16 *samples = new s16[sd->length * 2]; if (m_reg_speaker.format == 0x40) { // 8 bit PCM - for (int i = 0; i < 20; ++i) + for (int i = 0; i < sd->length; ++i) { samples[i] = (s16)(s8)sd->data[i]; } } else if (m_reg_speaker.format == 0x00) { - // 4 bit Yamaha ADPCM - // TODO: The first byte of the source data = length? - for (int i = 0; i < 20; ++i) + // 4 bit Yamaha ADPCM (same as dreamcast) + for (int i = 0; i < sd->length; ++i) { - samples[i * 2] = adpcm_yamaha_expand_nibble(&cs, sd->data[i] & 0x0F); - samples[i * 2 + 1] = adpcm_yamaha_expand_nibble(&cs, (sd->data[i] >> 4) & 0x0F); + samples[i * 2] = adpcm_yamaha_expand_nibble(m_adpcm_state, (sd->data[i] >> 4) & 0xf); + samples[i * 2 + 1] = adpcm_yamaha_expand_nibble(m_adpcm_state, sd->data[i] & 0xf); } } + +#ifdef WIIMOTE_SPEAKER_DUMP + std::stringstream name; + static int num = 0; + + if (num == 0) + { + File::Delete("rmtdump.wav"); + File::Delete("rmtdump.bin"); + atexit(stopdamnwav); + ofile.open("rmtdump.bin", ofile.binary | ofile.out); + wav.Start("rmtdump.wav", 6000/*Common::swap16(m_reg_speaker.sample_rate)*/); + } + wav.AddMonoSamples(samples, sd->length*2); + if (ofile.good()) + { + for (int i = 0; i < sd->length; i++) + { + ofile << sd->data[i]; + } + } + num++; +#endif + + delete[] samples; } } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 8e5ec4b25a..9577146f88 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -50,7 +50,12 @@ struct ReportFeatures struct AccelData { double x,y,z; -}; +}; + +struct ADPCMState +{ + s32 predictor, step; +}; extern const ReportFeatures reporting_mode_features[]; @@ -167,6 +172,8 @@ private: wm_status_report m_status; + ADPCMState m_adpcm_state; + // read data request queue // maybe it isn't actualy a queue // maybe read requests cancel any current requests @@ -224,11 +231,17 @@ private: struct SpeakerReg { - u16 unknown; + u8 unused_0; + u8 unk_1; u8 format; + // seems to always play at 6khz no matter what this is set to? + // or maybe it only applies to pcm input u16 sample_rate; u8 volume; - u8 unk[4]; + u8 unk_6; + u8 unk_7; + u8 play; + u8 unk_9; } m_reg_speaker; }; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 013451cf4b..5a3db0d7ef 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -239,6 +239,13 @@ bool Wiimote::Connect() m_wiimote_thread = std::thread(std::mem_fun(&Wiimote::ThreadFunc), this); + // This isn't as drastic as it sounds, since the process in which the threads + // reside is normal priority. Needed for keeping audio reports at a decent rate + if (!SetThreadPriority(m_wiimote_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL)) + { + ERROR_LOG(WIIMOTE, "Failed to set wiimote thread priority"); + } + NOTICE_LOG(WIIMOTE, "Connected to wiimote %i.", index + 1); return true; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 479e4e0a33..15621abce5 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -159,13 +159,19 @@ void Wiimote::InterruptChannel(const u16 channel, const void* const data, const // //((wm_report_mode*)(data + 2))->continuous = false; //} + if (rpt.first[0] == 0xa2 && rpt.first[1] == 0x18 && rpt.second == 23) + { + m_audio_reports.Push(rpt); + return; + } + m_write_reports.Push(rpt); } bool Wiimote::Read() { Report rpt; - + rpt.first = new unsigned char[MAX_PAYLOAD]; rpt.second = IORead(rpt.first); @@ -182,15 +188,23 @@ bool Wiimote::Read() bool Wiimote::Write() { Report rpt; + bool audio_written = false; + + if (m_audio_reports.Pop(rpt)) + { + IOWrite(rpt.first, rpt.second); + delete[] rpt.first; + audio_written = true; + } + if (m_write_reports.Pop(rpt)) { IOWrite(rpt.first, rpt.second); delete[] rpt.first; - return true; - } + } - return false; + return audio_written; } // Returns the next report that should be sent @@ -308,14 +322,19 @@ void Wiimote::ThreadFunc() // main loop while (IsConnected()) { - // hopefully this is alright +#ifdef __APPLE__ while (Write()) {} - -#ifndef __APPLE__ - // sleep if there was nothing to read - if (false == Read()) + Common::SleepCurrentThread(1); +#else + bool read = false; + while (Write() || (read = true, Read())) + { + if (m_audio_reports.Size() && !read) + Read(); + Common::SleepCurrentThread(m_audio_reports.Size() ? 5 : 2); + read = false; + } #endif - Common::SleepCurrentThread(1); } } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 635784e91a..1ab6edb78d 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -98,6 +98,7 @@ private: std::thread m_wiimote_thread; Common::FifoQueue m_read_reports; Common::FifoQueue m_write_reports; + Common::FifoQueue m_audio_reports; }; extern Common::CriticalSection g_refresh_critsec; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 840f304637..e361c30d53 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -23,16 +23,18 @@ #include "WII_IPC_HLE.h" #include "WII_IPC_HLE_Device_usb.h" #include "../ConfigManager.h" +#include "CoreTiming.h" + #define WIIMOTESIZE 0x46 #define BTDINFSIZE WIIMOTESIZE * 0x10 + // The device class CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _DeviceID, const std::string& _rDeviceName) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) , m_ScanEnable(0) , m_HCIEndpoint(0) , m_ACLEndpoint(0) - , m_WiimoteUpdate_Freq(0) - , m_NumCompPackets_Freq(0) + , m_last_ticks(0) { // Activate only first Wiimote by default @@ -108,8 +110,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p) p.Do(m_ACLSetup); p.Do(m_HCIEndpoint); p.Do(m_ACLEndpoint); - p.Do(m_NumCompPackets_Freq); - p.Do(m_WiimoteUpdate_Freq); + p.Do(m_last_ticks); u32 size; if (p.GetMode() == PointerWrap::MODE_READ) @@ -163,8 +164,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::Open(u32 _CommandAddress, u32 _Mode) { m_ScanEnable = 0; - m_NumCompPackets_Freq = 0; - m_WiimoteUpdate_Freq = 0; + m_last_ticks = 0; memset(m_PacketCount, 0, sizeof(m_PacketCount)); m_HCIEndpoint.m_address = 0; @@ -179,8 +179,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::Close(u32 _CommandAddress, bool _bForc { m_ScanEnable = 0; - m_NumCompPackets_Freq = 0; - m_WiimoteUpdate_Freq = 0; + m_last_ticks = 0; memset(m_PacketCount, 0, sizeof(m_PacketCount)); m_HCIEndpoint.m_address = 0; @@ -348,6 +347,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8 return; INFO_LOG(WII_IPC_WIIMOTE, "Send ACL Packet to ConnectionHandle 0x%04x", _ConnectionHandle); + IncDataPacket(_ConnectionHandle); pWiiMote->ExecuteL2capCmd(_pData, _Size); } @@ -357,12 +357,21 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendToDevice(u16 _ConnectionHandle, u8 // AyuanX: Basically, our WII_IPC_HLE is efficient enough to send the packet immediately // rather than enqueue it to some other memory // But...the only exception comes from the Wiimote_Plugin +void CWII_IPC_HLE_Device_usb_oh1_57e_305::IncDataPacket(u16 _ConnectionHandle) +{ + m_PacketCount[_ConnectionHandle & 0xff]++; + + if (m_PacketCount[_ConnectionHandle & 0xff] > 10) + { + DEBUG_LOG(WII_IPC_WIIMOTE, "ACL buffer overflow"); + m_PacketCount[_ConnectionHandle & 0xff] = 10; + } +} + void CWII_IPC_HLE_Device_usb_oh1_57e_305::SendACLPacket(u16 _ConnectionHandle, u8* _pData, u32 _Size) { DEBUG_LOG(WII_IPC_WIIMOTE, "ACL packet from %x ready to send to stack...", _ConnectionHandle); - m_PacketCount[_ConnectionHandle & 0xff]++; - if (m_ACLEndpoint.IsValid() && !m_HCIEndpoint.IsValid() && m_EventQueue.empty()) { DEBUG_LOG(WII_IPC_WIIMOTE, "ACL endpoint valid, sending packet to %08x", m_ACLEndpoint.m_address); @@ -395,9 +404,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e { DEBUG_LOG(WII_IPC_WIIMOTE, "HCI event %x completed...", ((hci_event_hdr_t*)_event.m_buffer)->event); - if (_event.m_connectionHandle) - m_PacketCount[_event.m_connectionHandle & 0xff]++; - if (m_HCIEndpoint.IsValid()) { if (m_EventQueue.empty()) // fast path :) @@ -439,6 +445,7 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::AddEventToQueue(const SQueuedEvent& _e u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() { + bool packet_transferred = false; // check hci queue if (!m_EventQueue.empty() && m_HCIEndpoint.IsValid()) { @@ -455,7 +462,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() WII_IPC_HLE_Interface::EnqReply(m_HCIEndpoint.m_address); m_HCIEndpoint.Invalidate(); m_EventQueue.pop(); - return true; + packet_transferred = true; } // check acl queue @@ -478,7 +485,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() WII_IPC_HLE_Interface::EnqReply(m_ACLEndpoint.m_address); m_ACLEndpoint.Invalidate(); m_ACLQ.pop(); - return true; + packet_transferred = true; } // We wait for ScanEnable to be sent from the bt stack through HCI_CMD_WRITE_SCAN_ENABLE @@ -486,22 +493,16 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() // // FiRES: TODO find a better way to do this - // Supposedly this delay is needed for real wiimotes - // TODO try removing this hack, or handling real wiimotes better - static int counter = Core::GetRealWiimote() ? 1000 : 0; // Create ACL connection if (m_HCIEndpoint.IsValid() && (m_ScanEnable & HCI_PAGE_SCAN_ENABLE)) { - if (--counter < 0) + for (unsigned int i = 0; i < m_WiiMotes.size(); i++) { - for (unsigned int i = 0; i < m_WiiMotes.size(); i++) + if (m_WiiMotes[i].EventPagingChanged(m_ScanEnable)) { - if (m_WiiMotes[i].EventPagingChanged(m_ScanEnable)) - { - Host_SetWiiMoteConnectionState(1); - SendEventRequestConnection(m_WiiMotes[i]); - //return true; - } + Host_SetWiiMoteConnectionState(1); + SendEventRequestConnection(m_WiiMotes[i]); + //return true; } } } @@ -516,44 +517,29 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update() } } - // The Real Wiimote sends report at a fixed frequency of 100Hz - // So let's make it also 100Hz here - // Calculation: 1500Hz (IPC_HLE) / 100Hz (WiiMote) = 15 - if (m_ACLEndpoint.IsValid()) + // The Real Wiimote sends report every ~6.66ms. + // 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 + // perfect "radio quality" (WPADGetRadioSensitivity) and yet still have some + // idle time. + static int wiimote_to_update = 0; + const u64 interval = 729000000u / 200; // 5ms behaves well + u64 each_wiimote_interval = interval / m_WiiMotes.size(); + u64 now = CoreTiming::GetTicks(); + if (now - m_last_ticks > each_wiimote_interval) { - if (++m_WiimoteUpdate_Freq > 15) - m_WiimoteUpdate_Freq = 0; - for (unsigned int i = 0; i < m_WiiMotes.size(); i++) + if (m_WiiMotes[wiimote_to_update].IsConnected()) { - if (m_WiiMotes[i].IsConnected() && m_WiimoteUpdate_Freq == 15 / (i + 1)) - { - NetPlay_WiimoteUpdate(i); - Wiimote::Update(i); - //return true; - } + NetPlay_WiimoteUpdate(wiimote_to_update); + Wiimote::Update(wiimote_to_update); } + wiimote_to_update = ++wiimote_to_update % m_WiiMotes.size(); + m_last_ticks = now; } - ////////////////////////////////////////////////////////////////////////// - // This event should be sent periodically after ACL connection is accepted - // or CPU will disconnect WiiMote automatically - // but don't send too many or it will jam the bus and cost extra CPU time - ////////////////////////////////////////////////////////////////////////// - // "When the Host has completed one or more HCI Data Packet(s) it shall send a - // Host_Number_Of_Completed_Packets command to the Controller, until it - // finally reports that all pending HCI Data Packets have been completed. The - // frequency at which this command is sent is manufacturer specific." - // -- Figuring out the "correct" rate could be annoying, so our guess will suffice :p - if (m_HCIEndpoint.IsValid()) - { - if (++m_NumCompPackets_Freq > 500) - { - m_NumCompPackets_Freq = 0; - SendEventNumberOfCompletedPackets(); - } - } + SendEventNumberOfCompletedPackets(); - return false; + return packet_transferred; } bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventInquiryComplete() @@ -913,20 +899,29 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets() event_hdr->length = sizeof(hci_num_compl_pkts_ep); event->num_con_handles = 0; + u32 acc = 0; + for (unsigned int i = 0; i < m_WiiMotes.size(); i++) { event_hdr->length += sizeof(hci_num_compl_pkts_info); event->num_con_handles++; info->compl_pkts = m_PacketCount[i]; info->con_handle = m_WiiMotes[i].GetConnectionHandle(); - info++; - m_PacketCount[i] = 0; DEBUG_LOG(WII_IPC_WIIMOTE, " Connection_Handle: 0x%04x", info->con_handle); DEBUG_LOG(WII_IPC_WIIMOTE, " Number_Of_Completed_Packets: %i", info->compl_pkts); + + acc += info->compl_pkts; + m_PacketCount[i] = 0; + info++; } - AddEventToQueue(Event); + if (acc) + AddEventToQueue(Event); + else + { + INFO_LOG(WII_IPC_WIIMOTE, "SendEventNumberOfCompletedPackets: no packets; no event"); + } return true; } @@ -1771,11 +1766,13 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandReadBufferSize(u8* _Input) { hci_read_buffer_size_rp Reply; Reply.status = 0x00; - Reply.max_acl_size = 0x0FFF; //339; - Reply.num_acl_pkts = 0xFF; //10; + Reply.max_acl_size = 339; + // Due to how the widcomm stack which nintendo uses is coded, we must never + // let the stack think the controller is buffering more than 10 data packets + // - it will cause a u8 underflow and royally screw things up. + Reply.num_acl_pkts = 10; Reply.max_sco_size = 64; Reply.num_sco_pkts = 0; - // AyuanX: Are these parameters fixed or adjustable ??? INFO_LOG(WII_IPC_WIIMOTE, "Command: HCI_CMD_READ_BUFFER_SIZE:"); DEBUG_LOG(WII_IPC_WIIMOTE, "return:"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h index 6e8bcfb67c..ef08a068ce 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h @@ -171,10 +171,10 @@ private: std::queue m_ACLQ; u32 m_PacketCount[4]; - u32 m_WiimoteUpdate_Freq; - u32 m_NumCompPackets_Freq; + u64 m_last_ticks; // Send ACL data to a device (wiimote) + void IncDataPacket(u16 _ConnectionHandle); void SendToDevice(u16 _ConnectionHandle, u8* _pData, u32 _Size); // Events diff --git a/Source/Core/Core/Src/IPC_HLE/hci.h b/Source/Core/Core/Src/IPC_HLE/hci.h index 01220d059f..1c59d4036b 100644 --- a/Source/Core/Core/Src/IPC_HLE/hci.h +++ b/Source/Core/Core/Src/IPC_HLE/hci.h @@ -79,17 +79,7 @@ #pragma once -// msvc >= msvc10 has stdint.h/cstdint -#ifdef _MSC_VER - typedef u8 uint8_t; - typedef s8 int8_t; - typedef u16 uint16_t; - typedef s16 int16_t; - typedef u32 uint32_t; - typedef s32 int32_t; -#else - #include -#endif +#include // All structs in this file are packed #pragma pack(push, 1) diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 920b779875..24f995d572 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -164,7 +164,6 @@ EVT_CHOICE(ID_WII_IPL_LNG, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_SD_CARD, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_KEYBOARD, CConfigMain::WiiSettingsChanged) -EVT_CHECKBOX(ID_WII_WIIMOTE_SPEAKER, CConfigMain::WiiSettingsChanged) EVT_CHECKBOX(ID_WII_WIIMOTE_RECONNECT, CConfigMain::WiiSettingsChanged) @@ -504,12 +503,6 @@ void CConfigMain::InitializeGUIValues() WiiSensBarPos->SetSelection(SConfig::GetInstance().m_SYSCONF->GetData("BT.BAR")); WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.SENS")); WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData("BT.MOT")); - if (SConfig::GetInstance().m_WiimoteSpeaker == 1) - WiimoteSpeaker->Set3StateValue(wxCHK_CHECKED); - else if (SConfig::GetInstance().m_WiimoteSpeaker == 2) - WiimoteSpeaker->Set3StateValue(wxCHK_UNDETERMINED); - else - WiimoteSpeaker->Set3StateValue(wxCHK_UNCHECKED); WiimoteReconnectOnLoad->SetValue(SConfig::GetInstance().m_WiimoteReconnectOnLoad); // Wii - Misc @@ -832,7 +825,6 @@ void CConfigMain::CreateGUIControls() WiiSensBarPos = new wxChoice(WiiPage, ID_WII_BT_BAR, wxDefaultPosition, wxDefaultSize, arrayStringFor_WiiSensBarPos, 0, wxDefaultValidator); WiiSensBarSens = new wxSlider(WiiPage, ID_WII_BT_SENS, 0, 0, 4); WiimoteMotor = new wxCheckBox(WiiPage, ID_WII_BT_MOT, _("Wiimote Motor"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); - WiimoteSpeaker = new wxCheckBox(WiiPage, ID_WII_WIIMOTE_SPEAKER, _("Wiimote Speaker"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER, wxDefaultValidator); WiimoteReconnectOnLoad = new wxCheckBox(WiiPage, ID_WII_WIIMOTE_RECONNECT, _("Reconnect Wiimote On Load State"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); // Misc Settings @@ -854,8 +846,7 @@ void CConfigMain::CreateGUIControls() wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL|wxALL, 5); sWiimoteSettings->Add(WiiSensBarSens, wxGBPosition(1, 1), wxDefaultSpan, wxEXPAND|wxALL, 5); sWiimoteSettings->Add(WiimoteMotor, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5); - sWiimoteSettings->Add(WiimoteSpeaker, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); - sWiimoteSettings->Add(WiimoteReconnectOnLoad, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5); + sWiimoteSettings->Add(WiimoteReconnectOnLoad, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); sbWiimoteSettings = new wxStaticBoxSizer(wxHORIZONTAL, WiiPage, _("Wiimote Settings")); sbWiimoteSettings->Add(sWiimoteSettings); @@ -1276,14 +1267,6 @@ void CConfigMain::WiiSettingsChanged(wxCommandEvent& event) case ID_WII_BT_MOT: SConfig::GetInstance().m_SYSCONF->SetData("BT.MOT", WiimoteMotor->IsChecked()); break; - case ID_WII_WIIMOTE_SPEAKER: - if (WiimoteSpeaker->Get3StateValue() == wxCHK_CHECKED) - SConfig::GetInstance().m_WiimoteSpeaker = 1; - else if (WiimoteSpeaker->Get3StateValue() == wxCHK_UNDETERMINED) - SConfig::GetInstance().m_WiimoteSpeaker = 2; - else - SConfig::GetInstance().m_WiimoteSpeaker = 0; - break; case ID_WII_WIIMOTE_RECONNECT: SConfig::GetInstance().m_WiimoteReconnectOnLoad = WiimoteReconnectOnLoad->IsChecked(); break; diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index b70f88b3d0..007978b43a 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -117,7 +117,6 @@ private: ID_WII_BT_BAR, ID_WII_BT_SENS, ID_WII_BT_MOT, - ID_WII_WIIMOTE_SPEAKER, ID_WII_WIIMOTE_RECONNECT, ID_WII_IPL_SSV, @@ -220,7 +219,6 @@ private: wxChoice* WiiSensBarPos; wxSlider* WiiSensBarSens; wxCheckBox* WiimoteMotor; - wxCheckBox* WiimoteSpeaker; wxCheckBox* WiimoteReconnectOnLoad; // Misc