Now Dolphin officially supports Multi-WiiMote (up to 4)

* You can connect/disconnect one or more WiiMote from Menu->Tools any time (must pause game first)

* Up to 4 Emulated Wiimotes can work together at the same timer

(PS: "Wiimote_Real" needs to be rewritten to support Multi-WiiMote, and it could be broken already now)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4736 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx
2009-12-27 19:31:02 +00:00
parent 4483f2c7b5
commit d62d6b0c33
36 changed files with 2046 additions and 2749 deletions

View File

@ -148,16 +148,6 @@ bool GetRealWiimote()
return g_bRealWiimote;
}
// This doesn't work yet, I don't understand how the connection work yet
void ReconnectWiimote()
{
// This seems to be a hack that just sets some IPC registers to zero. Dubious.
/* JP: Yes, it's basically nothing right now, I could not figure out how to reset the Wiimote
for reconnection */
HW::InitWiimote();
INFO_LOG(CONSOLE, "ReconnectWiimote()\n");
}
bool isRunning()
{
return (GetState() != CORE_UNINITIALIZED) || g_bHwInit;

View File

@ -61,7 +61,6 @@ namespace Core
void* GetWindowHandle();
bool GetRealWiimote();
void ReconnectWiimote();
extern bool bReadTrace;
extern bool bWriteTrace;

View File

@ -44,9 +44,11 @@ CWII_IPC_HLE_Device_usb_oh1_57e_305::CWII_IPC_HLE_Device_usb_oh1_57e_305(u32 _De
, m_LastCmd(0)
, m_FreqDividerSync(0)
{
// Activate the first one Wiimote by default
// Activate only first Wiimote by default
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 0, true));
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 1));
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 2));
m_WiiMotes.push_back(CWII_IPC_HLE_WiiMote(this, 3));
// The BCM2045's btaddr:
m_ControllerBD.b[0] = 0x11;
@ -89,6 +91,14 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::DoState(PointerWrap &p)
p.Do(m_PacketCount[i]);
p.Do(m_FreqDividerMote[i]);
}
for (unsigned int i = 0; i < m_WiiMotes.size(); i++)
m_WiiMotes[i].DoState(p);
}
bool CWII_IPC_HLE_Device_usb_oh1_57e_305::RemoteDisconnect(u16 _connectionHandle)
{
return SendEventDisconnect(_connectionHandle, 0x13);
}
// ===================================================
@ -483,7 +493,7 @@ u32 CWII_IPC_HLE_Device_usb_oh1_57e_305::Update()
for (unsigned int i = 0; i < m_WiiMotes.size(); i++)
{
m_FreqDividerMote[i]++;
if (m_WiiMotes[i].IsLinked() && m_FreqDividerMote[i] >= 150)
if (m_WiiMotes[i].IsConnected() == 3 && m_FreqDividerMote[i] >= 150)
{
m_FreqDividerMote[i] = 0;
CPluginManager::GetInstance().GetWiimote(0)->Wiimote_Update(i);
@ -1390,13 +1400,13 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandDisconnect(u8* _Input)
SendEventDisconnect(pDiscon->con_handle, pDiscon->reason);
PanicAlert("Wiimote (%i) has been disconnected by system due to idle time out.\n"
"Don't panic, this is quite a normal behavior for power saving.\n\n"
"To reconnect, Pasue game and Click \"Menu -> Tools -> Connect Wiimote\"", (pDiscon->con_handle & 0xFF) + 1);
CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(pDiscon->con_handle);
if (pWiimote)
pWiimote->EventDisconnect();
// Send disconnect message to plugin
u8 Message = WIIMOTE_RECONNECT;
CPluginManager::GetInstance().GetWiimote(0)->Wiimote_ControlChannel(pDiscon->con_handle & 0xFF, 99, &Message, 0);
pWiimote->EventDisconnect();
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandAcceptCon(u8* _Input)
@ -1582,15 +1592,6 @@ void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandSniffMode(u8* _Input)
DEBUG_LOG(WII_IPC_WIIMOTE, " timeout: 0x%04x", pSniffMode->timeout);
SendEventModeChange(pSniffMode->con_handle, 0x02, pSniffMode->max_interval); // 0x02 - sniff mode
// Now it is a good time to activate next wiimote
u16 NextHandle = pSniffMode->con_handle + 1;
if ((NextHandle & 0xFFu) < m_WiiMotes.size())
{
CWII_IPC_HLE_WiiMote* pWiimote = AccessWiiMote(NextHandle);
if (pWiimote)
pWiimote->Activate(true);
}
}
void CWII_IPC_HLE_Device_usb_oh1_57e_305::CommandWriteLinkPolicy(u8* _Input)

View File

@ -83,6 +83,8 @@ public:
void PurgeACLPool();
void PurgeHCIPool();
bool RemoteDisconnect(u16 _connectionHandle);
//hack for wiimote plugin
public:

View File

@ -30,10 +30,13 @@
static CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb;
CWII_IPC_HLE_Device_usb_oh1_57e_305* GetUsbPointer()
{
return s_Usb;
}
CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305* _pHost, int _Number, bool ready)
: m_Linked(false)
, m_HIDControlChannel_Connected(false)
: m_HIDControlChannel_Connected(false)
, m_HIDControlChannel_ConnectedWait(false)
, m_HIDControlChannel_Config(false)
, m_HIDControlChannel_ConfigWait(false)
@ -44,7 +47,6 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
, m_Name("Nintendo RVL-CNT-01")
, m_pHost(_pHost)
{
INFO_LOG(WII_IPC_WIIMOTE, "Wiimote: #%i Constructed", _Number);
@ -78,6 +80,10 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
lmp_subversion = 0x229;
}
void CWII_IPC_HLE_WiiMote::DoState(PointerWrap &p)
{
p.Do(m_Connected);
}
//
//
@ -92,7 +98,7 @@ CWII_IPC_HLE_WiiMote::CWII_IPC_HLE_WiiMote(CWII_IPC_HLE_Device_usb_oh1_57e_305*
bool CWII_IPC_HLE_WiiMote::LinkChannel()
{
if ((m_Connected <= 0) || (m_Linked == true))
if (m_Connected != 2)
return false;
// try to connect HID_CONTROL_CHANNEL
@ -139,7 +145,7 @@ bool CWII_IPC_HLE_WiiMote::LinkChannel()
return true;
}
m_Linked = true;
m_Connected = 3;
UpdateStatus();
return false;
@ -221,22 +227,29 @@ void CWII_IPC_HLE_WiiMote::UpdateStatus()
//
void CWII_IPC_HLE_WiiMote::Activate(bool ready)
{
if (ready)
if (ready && m_Connected == -1)
{
m_Connected = 0;
else
m_Connected = -1;
}
else if (!ready)
{
m_pHost->RemoteDisconnect(m_ConnectionHandle);
EventDisconnect();
}
}
void CWII_IPC_HLE_WiiMote::EventConnectionAccepted()
{
m_Connected = 1;
m_Linked = false;
m_Connected = 2;
}
void CWII_IPC_HLE_WiiMote::EventDisconnect()
{
// Send disconnect message to plugin
u8 Message = WIIMOTE_DISCONNECT;
CPluginManager::GetInstance().GetWiimote(0)->Wiimote_ControlChannel(m_ConnectionHandle & 0xFF, 99, &Message, 0);
m_Connected = -1;
m_Linked = false;
// Clear channel flags
ResetChannels();
}
@ -249,7 +262,7 @@ bool CWII_IPC_HLE_WiiMote::EventPagingChanged(u8 _pageMode)
if ((_pageMode & 0x2) == 0)
return false;
m_Connected = -1;
m_Connected = 1;
return true;
}

View File

@ -18,11 +18,14 @@
#define _WII_IPC_HLE_WII_MOTE_
#include <map>
#include "hci.h"
#include <string>
#include "hci.h"
#include "ChunkFile.h"
class CWII_IPC_HLE_Device_usb_oh1_57e_305;
CWII_IPC_HLE_Device_usb_oh1_57e_305* GetUsbPointer();
enum
{
SDP_CHANNEL = 0x01,
@ -188,15 +191,15 @@ public:
virtual ~CWII_IPC_HLE_WiiMote()
{}
void DoState(PointerWrap &p);
// ugly Host handling....
// we really have to clean all this code
int IsConnected() const { return m_Connected; }
bool LinkChannel();
void ResetChannels();
void Activate(bool ready);
bool IsConnected() const { return (m_Connected > 0) ? true : false; }
bool IsLinked() const { return m_Linked; }
void ShowStatus(const void* _pData); // Show status
void UpdateStatus(); // Update status
void ExecuteL2capCmd(u8* _pData, u32 _Size); // From CPU
@ -218,9 +221,9 @@ public:
private:
// state machine
int m_Connected; // 0: ready, -1: inactive/connecting, 1: connected
bool m_Linked;
// -1: inactive, 0: ready, 1: connecting 2: linking 3: connected & linked
int m_Connected;
bool m_HIDControlChannel_Connected;
bool m_HIDControlChannel_ConnectedWait;
bool m_HIDControlChannel_Config;

View File

@ -157,12 +157,6 @@ int abc = 0;
else
main_frame->bRenderToMain = true;
return 0;
case WIIMOTE_RECONNECT:
// The Wiimote plugin has been shut down, now reconnect the Wiimote
//INFO_LOG(CONSOLE, "WIIMOTE_RECONNECT\n");
Core::ReconnectWiimote();
return 0;
}
break;
}
@ -233,6 +227,10 @@ EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard)
EVT_MENU(IDM_CHEATS, CFrame::OnShow_CheatsWindow)
EVT_MENU(IDM_CHANGEDISC, CFrame::OnChangeDisc)
EVT_MENU(IDM_LOAD_WII_MENU, CFrame::OnLoadWiiMenu)
EVT_MENU(IDM_CONNECT_WIIMOTE1, CFrame::OnConnectWiimote)
EVT_MENU(IDM_CONNECT_WIIMOTE2, CFrame::OnConnectWiimote)
EVT_MENU(IDM_CONNECT_WIIMOTE3, CFrame::OnConnectWiimote)
EVT_MENU(IDM_CONNECT_WIIMOTE4, CFrame::OnConnectWiimote)
EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen)
EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore)
EVT_MENU(IDM_TOGGLE_SKIPIDLE, CFrame::OnToggleSkipIdle)

View File

@ -311,6 +311,7 @@ class CFrame : public wxFrame
void OnShow_CheatsWindow(wxCommandEvent& event);
void OnLoadWiiMenu(wxCommandEvent& event);
void OnConnectWiimote(wxCommandEvent& event);
void GameListChanged(wxCommandEvent& event);
void OnGameListCtrl_ItemActivated(wxListEvent& event);

View File

@ -62,6 +62,7 @@ Core::GetWindowHandle().
#include "OnFrame.h"
#include "HW/DVDInterface.h"
#include "HW/ProcessorInterface.h"
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "State.h"
#include "VolumeHandler.h"
#include "NANDContentLoader.h"
@ -90,6 +91,7 @@ extern "C" {
#include "../resources/KDE.h"
};
// Other Windows
wxCheatsWindow* CheatsWindow;
@ -194,6 +196,11 @@ void CFrame::CreateMenu()
{
toolsMenu->Append(IDM_LOAD_WII_MENU, _T("Load Wii Menu"));
}
toolsMenu->AppendSeparator();
toolsMenu->AppendCheckItem(IDM_CONNECT_WIIMOTE1, _T("Connect Wiimote 1"));
toolsMenu->AppendCheckItem(IDM_CONNECT_WIIMOTE2, _T("Connect Wiimote 2"));
toolsMenu->AppendCheckItem(IDM_CONNECT_WIIMOTE3, _T("Connect Wiimote 3"));
toolsMenu->AppendCheckItem(IDM_CONNECT_WIIMOTE4, _T("Connect Wiimote 4"));
m_MenuBar->Append(toolsMenu, _T("&Tools"));
@ -780,6 +787,12 @@ void CFrame::OnLoadWiiMenu(wxCommandEvent& WXUNUSED (event))
BootManager::BootCore(FULL_WII_MENU_DIR);
}
void CFrame::OnConnectWiimote(wxCommandEvent& event)
{
int Id = event.GetId() - IDM_CONNECT_WIIMOTE1;
GetUsbPointer()->AccessWiiMote(Id | 0x100)->Activate(event.IsChecked());
}
// Toogle fullscreen. In Windows the fullscreen mode is accomplished by expanding the m_Panel to cover
// the entire screen (when we render to the main window).
void CFrame::OnToggleFullscreen(wxCommandEvent& WXUNUSED (event))
@ -918,6 +931,18 @@ void CFrame::UpdateGUI()
if (DiscIO::CNANDContentManager::Access().GetNANDLoader(FULL_WII_MENU_DIR).IsValid())
GetMenuBar()->FindItem(IDM_LOAD_WII_MENU)->Enable(!Initialized);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Enable(Paused && Core::GetStartupParameter().bWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Enable(Paused && Core::GetStartupParameter().bWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Enable(Paused && Core::GetStartupParameter().bWii);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Enable(Paused && Core::GetStartupParameter().bWii);
if (Initialized && Core::GetStartupParameter().bWii)
{
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE1)->Check(GetUsbPointer()->AccessWiiMote(0x0100)->IsConnected() == 3);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE2)->Check(GetUsbPointer()->AccessWiiMote(0x0101)->IsConnected() == 3);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE3)->Check(GetUsbPointer()->AccessWiiMote(0x0102)->IsConnected() == 3);
GetMenuBar()->FindItem(IDM_CONNECT_WIIMOTE4)->Check(GetUsbPointer()->AccessWiiMote(0x0103)->IsConnected() == 3);
}
if (Running)
{
if (m_ToolBar)

View File

@ -95,6 +95,10 @@ enum
IDM_PROPERTIES,
IDM_LOAD_WII_MENU,
IDM_LUA,
IDM_CONNECT_WIIMOTE1,
IDM_CONNECT_WIIMOTE2,
IDM_CONNECT_WIIMOTE3,
IDM_CONNECT_WIIMOTE4,
IDM_LISTWAD,
IDM_LISTWII,

View File

@ -59,7 +59,6 @@
namespace InputCommon
{
// Settings
// ----------
// Show a status window with the detected axes, buttons and so on
@ -88,6 +87,7 @@ struct CONTROLLER_STATE // GC PAD INFO/STATE
struct CONTROLLER_MAPPING // GC PAD MAPPING
{
bool enable;
int buttons[8]; // (See above)
int dpad; // (See above)
int dpad2[4]; // (See above)
@ -100,7 +100,6 @@ struct CONTROLLER_MAPPING // GC PAD MAPPING
std::string SRadius, SDiagonal, SRadiusC, SDiagonalC;
bool bRadiusOnOff, bSquareToCircle, bRadiusOnOffC, bSquareToCircleC;
bool rumble;
bool enable;
int eventnum; // Linux Event Number, Can't be found dynamically yet
};
@ -169,74 +168,6 @@ enum
XI_TRIGGER_R
};
union PadAxis
{
int keyForControls[6];
struct
{
int Lx;
int Ly;
int Rx;
int Ry;
int Tl; // Trigger
int Tr; // Trigger
};
};
struct PadWiimote
{
int keyForControls[16];
// Order is A, B, 1, 2, +, -, Home
// L, R, U, D, RollL, RollR, PitchU, PitchD, Shake
};
struct PadNunchuck
{
int keyForControls[11];
// Order is Z, C, L, R, U, D, RollL, RollR, PitchU, PitchD, Shake
};
struct PadClassicController
{
int keyForControls[23];
// Order is A, B, X, Y, +, -, Home
// Tl, Zl, Zr, Tr, Dl, Dr, Du, Dd
// Ll, Lr, Lu, Ld, Rl, Rr, Ru, Rd
};
struct PadGH3Controller
{
int keyForControls[14];
// Order is Green, Red, Yellow, Blue, Orange,
// +, -, Whammy,
// Al, Ar, Au, Ad,
// StrumUp, StrumDown
};
struct CONTROLLER_STATE_NEW // GC PAD INFO/STATE
{
PadAxis Axis; // 6 Axes (Main, Sub, Triggers)
SDL_Joystick *joy; // SDL joystick device
};
struct CONTROLLER_MAPPING_NEW // GC PAD MAPPING
{
PadAxis Axis; // (See above)
PadWiimote Wm;
PadNunchuck Nc;
PadClassicController Cc;
PadGH3Controller GH3c;
bool enabled; // Pad attached?
bool Rumble;
int RumbleStrength;
int DeadZoneL; // Analog 1 Deadzone
int DeadZoneR; // Analog 2 Deadzone
int ID; // SDL joystick device ID
int controllertype; // D-Pad type: Hat or custom buttons
int triggertype; // SDL or XInput trigger
std::string SDiagonal;
bool bSquareToCircle;
bool bCircle2Square;
};
// Declarations
// ---------