329 changes: 265 additions & 64 deletions Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp

Large diffs are not rendered by default.

19 changes: 12 additions & 7 deletions Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm
Expand Up @@ -116,22 +116,21 @@ - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel
void WiimoteScanner::Update()
{}

std::vector<Wiimote*> WiimoteScanner::FindWiimotes()
void WiimoteScanner::FindWiimotes(std::vector<Wiimote*> & found_wiimotes, Wiimote* & found_board)
{
// TODO: find the device in the constructor and save it for later

std::vector<Wiimote*> wiimotes;
IOBluetoothHostController *bth;
IOBluetoothDeviceInquiry *bti;
SearchBT *sbt;
NSEnumerator *en;
found_board = NULL;

bth = [[IOBluetoothHostController alloc] init];
if ([bth addressAsString] == nil)
{
WARN_LOG(WIIMOTE, "No bluetooth host controller");
[bth release];
return wiimotes;
return;
}

sbt = [[SearchBT alloc] init];
Expand Down Expand Up @@ -162,14 +161,20 @@ - (void) l2capChannelClosed: (IOBluetoothL2CAPChannel *) l2capChannel

Wiimote *wm = new Wiimote();
wm->btd = dev;
wiimotes.push_back(wm);

if(IsBalanceBoardName([[dev name] UTF8String]))
{
found_board = wm;
}
else
{
found_wiimotes.push_back(wm);
}
}

[bth release];
[bti release];
[sbt release];

return wiimotes;
}

bool WiimoteScanner::IsReady() const
Expand Down
149 changes: 105 additions & 44 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp
Expand Up @@ -17,12 +17,13 @@

#include "../WiimoteEmu/WiimoteHid.h"

unsigned int g_wiimote_sources[MAX_WIIMOTES];
unsigned int g_wiimote_sources[MAX_BBMOTES];

namespace WiimoteReal
{

void HandleFoundWiimotes(const std::vector<Wiimote*>&);
void TryToConnectBalanceBoard(Wiimote*);
void TryToConnectWiimote(Wiimote*);
void HandleWiimoteDisconnect(int index);
void DoneWithWiimote(int index);
Expand All @@ -31,8 +32,7 @@ bool g_real_wiimotes_initialized = false;

std::recursive_mutex g_refresh_lock;

Wiimote* g_wiimotes[MAX_WIIMOTES];

Wiimote* g_wiimotes[MAX_BBMOTES];
WiimoteScanner g_wiimote_scanner;

Wiimote::Wiimote()
Expand Down Expand Up @@ -285,7 +285,7 @@ bool Wiimote::Prepare(int _index)
u8 const mode_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_REPORT_MODE, 0, WM_REPORT_CORE};

// Set the active LEDs and turn on rumble.
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << index | 0x1)};
u8 const led_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_LEDS, u8(WIIMOTE_LED_1 << (index%WIIMOTE_BALANCE_BOARD) | 0x1)};

// Turn off rumble
u8 rumble_report[] = {WM_SET_REPORT | WM_BT_OUTPUT, WM_RUMBLE, 0};
Expand Down Expand Up @@ -325,11 +325,25 @@ unsigned int CalculateWantedWiimotes()
return wanted_wiimotes;
}

unsigned int CalculateWantedBB()
{
unsigned int wanted_bb = 0;
if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD] && !g_wiimotes[WIIMOTE_BALANCE_BOARD])
++wanted_bb;
return wanted_bb;
}

void WiimoteScanner::WantWiimotes(bool do_want)
{
m_want_wiimotes = do_want;
}


void WiimoteScanner::WantBB(bool do_want)
{
m_want_bb = do_want;
}

void WiimoteScanner::StartScanning()
{
if (!m_run_thread)
Expand All @@ -352,7 +366,7 @@ void CheckForDisconnectedWiimotes()
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
if (g_wiimotes[i] && !g_wiimotes[i]->IsConnected())
HandleWiimoteDisconnect(i);
}
Expand All @@ -366,12 +380,13 @@ void WiimoteScanner::ThreadFunc()
while (m_run_thread)
{
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;

//NOTICE_LOG(WIIMOTE, "In loop");

if (m_want_wiimotes)
if (m_want_wiimotes || m_want_bb)
{
found_wiimotes = FindWiimotes();
FindWiimotes(found_wiimotes, found_board);
}
else
{
Expand All @@ -384,7 +399,10 @@ void WiimoteScanner::ThreadFunc()
// TODO: this is a fairly lame place for this
CheckForDisconnectedWiimotes();

HandleFoundWiimotes(found_wiimotes);
if(m_want_wiimotes)
HandleFoundWiimotes(found_wiimotes);
if(m_want_bb && found_board)
TryToConnectBalanceBoard(found_board);

//std::this_thread::yield();
Common::SleepCurrentThread(500);
Expand Down Expand Up @@ -439,6 +457,10 @@ void LoadSettings()

sec.Get("Source", &g_wiimote_sources[i], i ? WIIMOTE_SRC_NONE : WIIMOTE_SRC_EMU);
}

std::string secname("BalanceBoard");
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
sec.Get("Source", &g_wiimote_sources[WIIMOTE_BALANCE_BOARD], WIIMOTE_SRC_NONE);
}

// config dialog calls this when some settings change
Expand All @@ -452,6 +474,7 @@ void Initialize()
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());

if (g_real_wiimotes_initialized)
return;
Expand All @@ -474,20 +497,21 @@ void Shutdown(void)

g_real_wiimotes_initialized = false;

for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_BBMOTES; ++i)
HandleWiimoteDisconnect(i);
}

void ChangeWiimoteSource(unsigned int index, int source)
{
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

g_wiimote_sources[index] = source;
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());

// kill real connection (or swap to different slot)
DoneWithWiimote(index);
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
g_wiimote_sources[index] = source;
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());


// kill real connection (or swap to different slot)
DoneWithWiimote(index);
}

// reconnect to the emulator
Expand All @@ -500,7 +524,7 @@ void TryToConnectWiimote(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);

for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
Expand All @@ -525,16 +549,41 @@ void TryToConnectWiimote(Wiimote* wm)
delete wm;
}

void TryToConnectBalanceBoard(Wiimote* wm)
{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);

if (WIIMOTE_SRC_REAL & g_wiimote_sources[WIIMOTE_BALANCE_BOARD]
&& !g_wiimotes[WIIMOTE_BALANCE_BOARD])
{
if (wm->Connect() && wm->Prepare(WIIMOTE_BALANCE_BOARD))
{
NOTICE_LOG(WIIMOTE, "Connected to Balance Board %i.", WIIMOTE_BALANCE_BOARD + 1);

std::swap(g_wiimotes[WIIMOTE_BALANCE_BOARD], wm);
g_wiimotes[WIIMOTE_BALANCE_BOARD]->StartThread();

Host_ConnectWiimote(WIIMOTE_BALANCE_BOARD, true);
}
}

g_wiimote_scanner.WantBB(0 != CalculateWantedBB());

lk.unlock();

delete wm;
}

void DoneWithWiimote(int index)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

if (g_wiimotes[index])
{
g_wiimotes[index]->StopThread();

// First see if we can use this real Wiimote in another slot.
for (unsigned int i = 0; i != MAX_WIIMOTES; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]
&& !g_wiimotes[i])
Expand All @@ -560,9 +609,11 @@ void HandleWiimoteDisconnect(int index)
Wiimote* wm = NULL;

{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);
std::swap(wm, g_wiimotes[index]);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

std::swap(wm, g_wiimotes[index]);
g_wiimote_scanner.WantWiimotes(0 != CalculateWantedWiimotes());
g_wiimote_scanner.WantBB(0 != CalculateWantedBB());
}

if (wm)
Expand All @@ -583,31 +634,35 @@ void Refresh()
g_wiimote_scanner.StopScanning();

{
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
std::vector<Wiimote*> found_wiimotes;

if (0 != CalculateWantedWiimotes())
{
// Don't hang Dolphin when searching
lk.unlock();
found_wiimotes = g_wiimote_scanner.FindWiimotes();
lk.lock();
}
std::unique_lock<std::recursive_mutex> lk(g_refresh_lock);
std::vector<Wiimote*> found_wiimotes;
Wiimote* found_board = NULL;

if (0 != CalculateWantedWiimotes() || 0 != CalculateWantedBB())
{
// Don't hang Dolphin when searching
lk.unlock();
g_wiimote_scanner.FindWiimotes(found_wiimotes, found_board);
lk.lock();
}

CheckForDisconnectedWiimotes();
CheckForDisconnectedWiimotes();

// Brief rumble for already connected Wiimotes.
for (int i = 0; i != MAX_WIIMOTES; ++i)
{
if (g_wiimotes[i])
// Brief rumble for already connected Wiimotes.
// Don't do this for Balance Board as it doesn't have rumble anyway.
for (int i = 0; i < MAX_WIIMOTES; ++i)
{
g_wiimotes[i]->StopThread();
g_wiimotes[i]->Prepare(i);
g_wiimotes[i]->StartThread();
if (g_wiimotes[i])
{
g_wiimotes[i]->StopThread();
g_wiimotes[i]->Prepare(i);
g_wiimotes[i]->StartThread();
}
}
}

HandleFoundWiimotes(found_wiimotes);
HandleFoundWiimotes(found_wiimotes);
if(found_board)
TryToConnectBalanceBoard(found_board);
}

Initialize();
Expand All @@ -616,7 +671,6 @@ void Refresh()
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{
std::lock_guard<std::recursive_mutex> lk(g_refresh_lock);

if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
}
Expand Down Expand Up @@ -656,7 +710,14 @@ bool IsValidBluetoothName(const std::string& name)
{
return
"Nintendo RVL-CNT-01" == name ||
"Nintendo RVL-CNT-01-TR" == name;
"Nintendo RVL-CNT-01-TR" == name ||
IsBalanceBoardName(name);
}

bool IsBalanceBoardName(const std::string& name)
{
return
"Nintendo RVL-WBC-01" == name;
}

}; // end of namespace
10 changes: 6 additions & 4 deletions Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h
Expand Up @@ -117,11 +117,12 @@ class WiimoteScanner
bool IsReady() const;

void WantWiimotes(bool do_want);
void WantBB(bool do_want);

void StartScanning();
void StopScanning();

std::vector<Wiimote*> FindWiimotes();
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&);

// function called when not looking for more wiimotes
void Update();
Expand All @@ -133,10 +134,10 @@ class WiimoteScanner

volatile bool m_run_thread;
volatile bool m_want_wiimotes;
volatile bool m_want_bb;

#if defined(_WIN32)


void CheckDeviceType(std::basic_string<TCHAR> &devicepath, bool &real_wiimote, bool &is_bb);
#elif defined(__linux__) && HAVE_BLUEZ
int device_id;
int device_sock;
Expand All @@ -145,7 +146,7 @@ class WiimoteScanner

extern std::recursive_mutex g_refresh_lock;
extern WiimoteScanner g_wiimote_scanner;
extern Wiimote *g_wiimotes[4];
extern Wiimote *g_wiimotes[MAX_BBMOTES];

void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);
Expand All @@ -158,6 +159,7 @@ int FindWiimotes(Wiimote** wm, int max_wiimotes);
void ChangeWiimoteSource(unsigned int index, int source);

bool IsValidBluetoothName(const std::string& name);
bool IsBalanceBoardName(const std::string& name);

}; // WiimoteReal

Expand Down
68 changes: 50 additions & 18 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp
Expand Up @@ -32,7 +32,7 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
}
else
{
u8 maxWM = min<u8>(BT_DINF.num_registered, CONF_PAD_MAX_ACTIVE);
u8 maxWM = min<u8>(BT_DINF.num_registered, MAX_BBMOTES);
bdaddr_t tmpBD = BDADDR_ANY;
u8 i = 0;
while (i < maxWM)
Expand All @@ -43,28 +43,60 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
tmpBD.b[2] = BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3];
tmpBD.b[1] = BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4];
tmpBD.b[0] = BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5];
if(i == WIIMOTE_BALANCE_BOARD)
{
const char * wmName = "Nintendo RVL-WBC-01";
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.balance_board.name, wmName, 20);
}
else
{
const char * wmName = "Nintendo RVL-CNT-01";
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.active[i].name, wmName, 20);
}

INFO_LOG(WII_IPC_WIIMOTE, "Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
i++;
}
while (i < CONF_PAD_MAX_ACTIVE)
while (i < MAX_BBMOTES)
{
const char * wmName = "Nintendo RVL-CNT-01";
++BT_DINF.num_registered;
BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);

INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
if(i == WIIMOTE_BALANCE_BOARD)
{
const char * wmName = "Nintendo RVL-WBC-01";
++BT_DINF.num_registered;
BT_DINF.balance_board.bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.balance_board.bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.balance_board.bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.balance_board.bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.balance_board.bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.balance_board.bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);
memcpy(BT_DINF.balance_board.name, wmName, 20);

INFO_LOG(WII_IPC_WIIMOTE, "Balance Board %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));
}
else
{
const char * wmName = "Nintendo RVL-CNT-01";
++BT_DINF.num_registered;
BT_DINF.active[i].bdaddr[0] = BT_DINF.registered[i].bdaddr[0] = tmpBD.b[5] = i;
BT_DINF.active[i].bdaddr[1] = BT_DINF.registered[i].bdaddr[1] = tmpBD.b[4] = 0;
BT_DINF.active[i].bdaddr[2] = BT_DINF.registered[i].bdaddr[2] = tmpBD.b[3] = 0x79;
BT_DINF.active[i].bdaddr[3] = BT_DINF.registered[i].bdaddr[3] = tmpBD.b[2] = 0x19;
BT_DINF.active[i].bdaddr[4] = BT_DINF.registered[i].bdaddr[4] = tmpBD.b[1] = 2;
BT_DINF.active[i].bdaddr[5] = BT_DINF.registered[i].bdaddr[5] = tmpBD.b[0] = 0x11;
memcpy(BT_DINF.registered[i].name, wmName, 20);

INFO_LOG(WII_IPC_WIIMOTE, "Adding to SYSConf Wiimote %d BT ID %x,%x,%x,%x,%x,%x", i, tmpBD.b[0], tmpBD.b[1], tmpBD.b[2], tmpBD.b[3], tmpBD.b[4], tmpBD.b[5]);
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, i, tmpBD, false));

}
i++;
}

// save now so that when games load sysconf file it includes the new wiimotes
// and the correct order for connected wiimotes
if (!SConfig::GetInstance().m_SYSCONF->SetArrayData("BT.DINF", (u8*)&BT_DINF, sizeof(_conf_pads)) || !SConfig::GetInstance().m_SYSCONF->Save())
Expand Down Expand Up @@ -99,18 +131,18 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
p.DoPOD(m_HCIEndpoint);
p.DoPOD(m_ACLEndpoint);
p.Do(m_last_ticks);
p.DoArray(m_PacketCount,4);
p.DoArray(m_PacketCount,MAX_BBMOTES);
p.Do(m_ScanEnable);
p.Do(m_EventQueue);
m_acl_pool.DoState(p);

for (unsigned int i = 0; i < 4; i++)
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
m_WiiMotes[i].DoState(p);

// Reset the connection of real and hybrid wiimotes
if (p.GetMode() == PointerWrap::MODE_READ && SConfig::GetInstance().m_WiimoteReconnectOnLoad)
{
for (unsigned int i = 0; i < 4; i++)
for (unsigned int i = 0; i < MAX_BBMOTES; i++)
{
if (WIIMOTE_SRC_EMU == g_wiimote_sources[i] || WIIMOTE_SRC_NONE == g_wiimote_sources[i])
continue;
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.h
Expand Up @@ -12,6 +12,7 @@
#include "WII_IPC_HLE.h"
#include "WII_IPC_HLE_Device.h"
#include "WII_IPC_HLE_WiiMote.h"
#include "../HW/Wiimote.h"

struct SQueuedEvent
{
Expand Down Expand Up @@ -193,7 +194,7 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device
}
} m_acl_pool;

u32 m_PacketCount[4];
u32 m_PacketCount[MAX_BBMOTES];
u64 m_last_ticks;

// Send ACL data to a device (wiimote)
Expand Down Expand Up @@ -274,7 +275,6 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device

#pragma pack(push,1)
#define CONF_PAD_MAX_REGISTERED 10
#define CONF_PAD_MAX_ACTIVE 4

struct _conf_pad_device
{
Expand All @@ -286,7 +286,7 @@ class CWII_IPC_HLE_Device_usb_oh1_57e_305 : public IWII_IPC_HLE_Device
{
u8 num_registered;
_conf_pad_device registered[CONF_PAD_MAX_REGISTERED];
_conf_pad_device active[CONF_PAD_MAX_ACTIVE];
_conf_pad_device active[MAX_WIIMOTES];
_conf_pad_device balance_board;
u8 unknown[0x45];
};
Expand Down
6 changes: 3 additions & 3 deletions Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_WiiMote.cpp
Expand Up @@ -37,7 +37,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
, m_HIDInterruptChannel_Config(false)
, m_HIDInterruptChannel_ConfigWait(false)
, m_BD(_BD)
, m_Name("Nintendo RVL-CNT-01")
, m_Name(_Number == WIIMOTE_BALANCE_BOARD ? "Nintendo RVL-WBC-01" : "Nintendo RVL-CNT-01")
, m_pHost(_pHost)
{
DEBUG_LOG(WII_IPC_WIIMOTE, "Wiimote: #%i Constructed", _Number);
Expand Down Expand Up @@ -277,13 +277,13 @@ void CWII_IPC_HLE_WiiMote::ExecuteL2capCmd(u8* _pData, u32 _Size)
break;

case L2CAP_PSM_HID_CNTL:
if (number < 4)
if (number < MAX_BBMOTES)
Wiimote::ControlChannel(number, pHeader->dcid, pData, DataSize);
break;

case L2CAP_PSM_HID_INTR:
{
if (number < 4)
if (number < MAX_BBMOTES)
{
DEBUG_LOG(WIIMOTE, "Wiimote_InterruptChannel");
DEBUG_LOG(WIIMOTE, " Channel ID: %04x", pHeader->dcid);
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/Core/Src/Movie.cpp
Expand Up @@ -392,7 +392,7 @@ void ChangeWiiPads(bool instantly)
if (instantly && (g_numPads >> 4) == controllers)
return;

for (int i = 0; i < 4; i++)
for (int i = 0; i < MAX_BBMOTES; i++)
{
g_wiimote_sources[i] = IsUsingWiimote(i) ? WIIMOTE_SRC_EMU : WIIMOTE_SRC_NONE;
GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(IsUsingWiimote(i));
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/DolphinWX/Src/InputConfigDiag.cpp
Expand Up @@ -5,6 +5,7 @@
#include "InputConfigDiag.h"
#include "UDPConfigDiag.h"
#include "WxUtils.h"
#include "HW/Wiimote.h"

void GamepadPage::ConfigUDPWii(wxCommandEvent &event)
{
Expand Down Expand Up @@ -947,7 +948,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputPlugin& plugin
, m_plugin(plugin)
{
m_pad_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
for (unsigned int i = 0; i < plugin.controllers.size(); ++i)
for (unsigned int i = 0; i < std::min(plugin.controllers.size(), (size_t)MAX_WIIMOTES); ++i)
{
GamepadPage* gp = new GamepadPage(m_pad_notebook, m_plugin, i, this);
m_padpages.push_back(gp);
Expand Down
44 changes: 36 additions & 8 deletions Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp
Expand Up @@ -15,7 +15,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wxStaticText* wiimote_label[4];
wxChoice* wiimote_source_ch[4];

for (unsigned int i = 0; i < 4; ++i)
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
{
wxString str;
str.Printf(_("Wiimote %i"), i + 1);
Expand Down Expand Up @@ -54,8 +54,25 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin
wiimote_sizer->Add(wiimote_configure_bt[i]);
}
wiimote_group->Add(wiimote_sizer, 1, wxEXPAND, 5 );


// "BalanceBoard" layout
wxStaticBoxSizer* const bb_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Balance Board"));
wxFlexGridSizer* const bb_sizer = new wxFlexGridSizer(1, 5, 5);
int source_ctrl_id = wxWindow::NewControlId();
m_wiimote_index_from_ctrl_id.insert(std::pair<wxWindowID, unsigned int>(source_ctrl_id, WIIMOTE_BALANCE_BOARD));
const wxString src_choices[] = { _("None"), _("Real Balance Board") };
wxChoice* bb_source = new wxChoice(this, source_ctrl_id, wxDefaultPosition, wxDefaultSize, sizeof(src_choices)/sizeof(*src_choices), src_choices);
bb_source->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &WiimoteConfigDiag::SelectSource, this);

m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] = g_wiimote_sources[WIIMOTE_BALANCE_BOARD];
bb_source->Select(m_orig_wiimote_sources[WIIMOTE_BALANCE_BOARD] ? 1 : 0);

bb_sizer->Add(bb_source, 0, wxALIGN_CENTER_VERTICAL);

bb_group->Add(bb_sizer, 1, wxEXPAND, 5 );


// "Real wiimotes" controls
wxButton* const refresh_btn = new wxButton(this, -1, _("Refresh"), wxDefaultPosition);
refresh_btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &WiimoteConfigDiag::RefreshRealWiimotes, this);
Expand Down Expand Up @@ -166,6 +183,7 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin

// Dialog layout
main_sizer->Add(wiimote_group, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(bb_group, 0, wxEXPAND | wxALL, 5);
main_sizer->Add(real_wiimotes_group, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(general_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
Expand Down Expand Up @@ -196,17 +214,23 @@ void WiimoteConfigDiag::SelectSource(wxCommandEvent& event)
// Revert if the dialog is canceled.
int index = m_wiimote_index_from_ctrl_id[event.GetId()];

WiimoteReal::ChangeWiimoteSource(index, event.GetInt());

if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
wiimote_configure_bt[index]->Disable();
if(index != WIIMOTE_BALANCE_BOARD)
{
WiimoteReal::ChangeWiimoteSource(index, event.GetInt());
if (g_wiimote_sources[index] != WIIMOTE_SRC_EMU && g_wiimote_sources[index] != WIIMOTE_SRC_HYBRID)
wiimote_configure_bt[index]->Disable();
else
wiimote_configure_bt[index]->Enable();
}
else
wiimote_configure_bt[index]->Enable();
{
WiimoteReal::ChangeWiimoteSource(index, event.GetInt() ? WIIMOTE_SRC_REAL : WIIMOTE_SRC_NONE);
}
}

void WiimoteConfigDiag::RevertSource()
{
for (int i = 0; i < 4; ++i)
for (int i = 0; i < MAX_BBMOTES; ++i)
g_wiimote_sources[i] = m_orig_wiimote_sources[i];
}

Expand All @@ -225,6 +249,10 @@ void WiimoteConfigDiag::Save(wxCommandEvent& event)

sec.Set("Source", (int)g_wiimote_sources[i]);
}

std::string secname("BalanceBoard");
IniFile::Section& sec = *inifile.GetOrCreateSection(secname.c_str());
sec.Set("Source", (int)g_wiimote_sources[WIIMOTE_BALANCE_BOARD]);

inifile.Save(ini_filename);

Expand Down
4 changes: 2 additions & 2 deletions Source/Core/DolphinWX/Src/WiimoteConfigDiag.h
Expand Up @@ -76,9 +76,9 @@ class WiimoteConfigDiag : public wxDialog
wxNotebook* m_pad_notebook;

std::map<wxWindowID, unsigned int> m_wiimote_index_from_ctrl_id;
unsigned int m_orig_wiimote_sources[4];
unsigned int m_orig_wiimote_sources[MAX_BBMOTES];

wxButton* wiimote_configure_bt[4];
wxButton* wiimote_configure_bt[MAX_WIIMOTES];
std::map<wxWindowID, unsigned int> m_wiimote_index_from_conf_bt_id;
};

Expand Down
7 changes: 4 additions & 3 deletions Source/Core/InputCommon/Src/InputConfig.cpp
Expand Up @@ -4,6 +4,7 @@

#include "InputConfig.h"
#include "../../Core/Src/ConfigManager.h"
#include "../../Core/Src/HW/Wiimote.h"

InputPlugin::~InputPlugin()
{
Expand All @@ -18,9 +19,9 @@ bool InputPlugin::LoadConfig(bool isGC)
{
IniFile inifile;
IniFile game_ini;
bool useProfile[4] = {false, false, false, false};
std::string num[4] = {"1", "2", "3", "4"};
std::string profile[4];
bool useProfile[MAX_BBMOTES] = {false, false, false, false, false};
std::string num[MAX_BBMOTES] = {"1", "2", "3", "4", "BB"};
std::string profile[MAX_BBMOTES];
std::string path;

if (SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() != "00000000")
Expand Down