forked from dolphin-emu/dolphin
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
This commit is contained in:
Binary file not shown.
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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[] =
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace HLE_Misc
|
||||
void FZ_sqrt_internal();
|
||||
void FZ_rsqrt_internal();
|
||||
void HBReload();
|
||||
void IsBusyStream();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -16,79 +16,111 @@
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "WiimoteEmu.h"
|
||||
|
||||
//#define WIIMOTE_SPEAKER_DUMP
|
||||
#ifdef WIIMOTE_SPEAKER_DUMP
|
||||
#include <fstream>
|
||||
#include "WaveFile.h"
|
||||
#include <stdlib.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ private:
|
||||
std::thread m_wiimote_thread;
|
||||
Common::FifoQueue<Report> m_read_reports;
|
||||
Common::FifoQueue<Report> m_write_reports;
|
||||
Common::FifoQueue<Report> m_audio_reports;
|
||||
};
|
||||
|
||||
extern Common::CriticalSection g_refresh_critsec;
|
||||
|
||||
@@ -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:");
|
||||
|
||||
@@ -171,10 +171,10 @@ private:
|
||||
std::queue<ACLQ> 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
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
// All structs in this file are packed
|
||||
#pragma pack(push, 1)
|
||||
|
||||
@@ -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<u8>("BT.BAR"));
|
||||
WiiSensBarSens->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<u32>("BT.SENS"));
|
||||
WiimoteMotor->SetValue(SConfig::GetInstance().m_SYSCONF->GetData<bool>("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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user