mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
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:
parent
3af93e8cf3
commit
a80429b020
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
|
||||
|
Loading…
Reference in New Issue
Block a user