diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index 536acd73f7..4824bc8b7e 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -247,7 +247,8 @@ set(LIBS
if(LIBUSB_FOUND)
# Using shared LibUSB
set(LIBS ${LIBS} ${LIBUSB_LIBRARIES})
- set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp)
+ set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp
+ HW/SI_GCAdapter.cpp)
endif(LIBUSB_FOUND)
set(LIBS ${LIBS} ${POLARSSL_LIBRARY})
diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp
index 0305746cf4..7afb655a44 100644
--- a/Source/Core/Core/ConfigManager.cpp
+++ b/Source/Core/Core/ConfigManager.cpp
@@ -341,6 +341,7 @@ void SConfig::SaveCoreSettings(IniFile& ini)
core->Set("FrameSkip", m_FrameSkip);
core->Set("GFXBackend", m_LocalCoreStartupParameter.m_strVideoBackend);
core->Set("GPUDeterminismMode", m_LocalCoreStartupParameter.m_strGPUDeterminismMode);
+ core->Set("GameCubeAdapter", m_GameCubeAdapter);
}
void SConfig::SaveMovieSettings(IniFile& ini)
@@ -574,6 +575,7 @@ void SConfig::LoadCoreSettings(IniFile& ini)
core->Get("FrameSkip", &m_FrameSkip, 0);
core->Get("GFXBackend", &m_LocalCoreStartupParameter.m_strVideoBackend, "");
core->Get("GPUDeterminismMode", &m_LocalCoreStartupParameter.m_strGPUDeterminismMode, "auto");
+ core->Get("GameCubeAdapter", &m_GameCubeAdapter, true);
}
void SConfig::LoadMovieSettings(IniFile& ini)
diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h
index 7c14d9dfb8..badf3fe04b 100644
--- a/Source/Core/Core/ConfigManager.h
+++ b/Source/Core/Core/ConfigManager.h
@@ -107,6 +107,7 @@ struct SConfig : NonCopyable
// Input settings
bool m_BackgroundInput;
+ bool m_GameCubeAdapter;
SysConf* m_SYSCONF;
diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj
index 611658f65f..ae775bcc5a 100644
--- a/Source/Core/Core/Core.vcxproj
+++ b/Source/Core/Core/Core.vcxproj
@@ -147,6 +147,13 @@
+
+
+ 4200;%(DisableSpecificWarnings)
+
@@ -176,7 +183,7 @@
4200;%(DisableSpecificWarnings)
@@ -345,6 +352,7 @@
+
diff --git a/Source/Core/Core/HW/SI.cpp b/Source/Core/Core/HW/SI.cpp
index 0f6b14917c..736853b06b 100644
--- a/Source/Core/Core/HW/SI.cpp
+++ b/Source/Core/Core/HW/SI.cpp
@@ -15,6 +15,9 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/HW/SI.h"
#include "Core/HW/SI_DeviceGBA.h"
+#if defined(__LIBUSB__) || defined (_WIN32)
+#include "Core/HW/SI_GCAdapter.h"
+#endif
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
@@ -56,56 +59,6 @@ enum
SI_EXI_CLOCK_COUNT = 0x3C,
};
-// SI Channel Output
-union USIChannelOut
-{
- u32 Hex;
- struct
- {
- u32 OUTPUT1 : 8;
- u32 OUTPUT0 : 8;
- u32 CMD : 8;
- u32 : 8;
- };
-};
-
-// SI Channel Input High u32
-union USIChannelIn_Hi
-{
- u32 Hex;
- struct
- {
- u32 INPUT3 : 8;
- u32 INPUT2 : 8;
- u32 INPUT1 : 8;
- u32 INPUT0 : 6;
- u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
- u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
- };
-};
-
-// SI Channel Input Low u32
-union USIChannelIn_Lo
-{
- u32 Hex;
- struct
- {
- u32 INPUT7 : 8;
- u32 INPUT6 : 8;
- u32 INPUT5 : 8;
- u32 INPUT4 : 8;
- };
-};
-
-// SI Channel
-struct SSIChannel
-{
- USIChannelOut m_Out;
- USIChannelIn_Hi m_InHi;
- USIChannelIn_Lo m_InLo;
- ISIDevice* m_pDevice;
-};
-
// SI Poll: Controls how often a device is polled
union USIPoll
{
@@ -384,7 +337,9 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex, g_Poll.EN1);
g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex, g_Poll.EN2);
g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex, g_Poll.EN3);
-
+#if defined(__LIBUSB__) || defined (_WIN32)
+ SI_GCAdapter::Output(g_Channel);
+#endif
g_StatusReg.WR = 0;
g_StatusReg.WRST0 = 0;
g_StatusReg.WRST1 = 0;
@@ -473,22 +428,30 @@ static void SetNoResponse(u32 channel)
void ChangeDeviceCallback(u64 userdata, int cyclesLate)
{
u8 channel = (u8)(userdata >> 32);
+ SIDevices device = (SIDevices)(u32)userdata;
- g_Channel[channel].m_Out.Hex = 0;
- g_Channel[channel].m_InHi.Hex = 0;
- g_Channel[channel].m_InLo.Hex = 0;
+ // Skip redundant (spammed) device changes
+ if (GetDeviceType(channel) != device)
+ {
+ g_Channel[channel].m_Out.Hex = 0;
+ g_Channel[channel].m_InHi.Hex = 0;
+ g_Channel[channel].m_InLo.Hex = 0;
- SetNoResponse(channel);
+ SetNoResponse(channel);
- AddDevice((SIDevices)(u32)userdata, channel);
+ AddDevice(device, channel);
+ }
}
void ChangeDevice(SIDevices device, int channel)
{
// Called from GUI, so we need to make it thread safe.
// Let the hardware see no device for .5b cycles
- CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
- CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | device);
+ if (GetDeviceType(channel) != device)
+ {
+ CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
+ CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | device);
+ }
}
void UpdateDevices()
@@ -499,6 +462,29 @@ void UpdateDevices()
g_StatusReg.RDST2 = !!g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex);
g_StatusReg.RDST3 = !!g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex);
+ // Check for connected GC Adapter
+#if defined(__LIBUSB__) || defined (_WIN32)
+ if (SConfig::GetInstance().m_GameCubeAdapter)
+ {
+ g_StatusReg.RDST0 |= (SI_GCAdapter::GetDeviceType(0) != SIDEVICE_NONE);
+ g_StatusReg.RDST1 |= (SI_GCAdapter::GetDeviceType(1) != SIDEVICE_NONE);
+ g_StatusReg.RDST2 |= (SI_GCAdapter::GetDeviceType(2) != SIDEVICE_NONE);
+ g_StatusReg.RDST3 |= (SI_GCAdapter::GetDeviceType(3) != SIDEVICE_NONE);
+
+ for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
+ {
+ SIDevices connected_device = SI_GCAdapter::GetDeviceType(chan);
+ SIDevices configured_device = SConfig::GetInstance().m_SIDevice[chan];
+
+ if (connected_device != SIDEVICE_NONE)
+ ChangeDevice(connected_device, chan);
+ else
+ ChangeDevice(configured_device, chan);
+ }
+
+ SI_GCAdapter::Input(g_Channel);
+ }
+#endif
UpdateInterrupts();
}
diff --git a/Source/Core/Core/HW/SI.h b/Source/Core/Core/HW/SI.h
index 2e06b269a1..2f22996e6e 100644
--- a/Source/Core/Core/HW/SI.h
+++ b/Source/Core/Core/HW/SI.h
@@ -20,6 +20,56 @@ enum
namespace SerialInterface
{
+// SI Channel Output
+union USIChannelOut
+{
+ u32 Hex;
+ struct
+ {
+ u32 OUTPUT1 : 8;
+ u32 OUTPUT0 : 8;
+ u32 CMD : 8;
+ u32 : 8;
+ };
+};
+
+// SI Channel Input High u32
+union USIChannelIn_Hi
+{
+ u32 Hex;
+ struct
+ {
+ u32 INPUT3 : 8;
+ u32 INPUT2 : 8;
+ u32 INPUT1 : 8;
+ u32 INPUT0 : 6;
+ u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
+ u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
+ };
+};
+
+// SI Channel Input Low u32
+union USIChannelIn_Lo
+{
+ u32 Hex;
+ struct
+ {
+ u32 INPUT7 : 8;
+ u32 INPUT6 : 8;
+ u32 INPUT5 : 8;
+ u32 INPUT4 : 8;
+ };
+};
+
+// SI Channel
+struct SSIChannel
+{
+ USIChannelOut m_Out;
+ USIChannelIn_Hi m_InHi;
+ USIChannelIn_Lo m_InLo;
+ ISIDevice* m_pDevice;
+};
+
void Init();
void Shutdown();
void DoState(PointerWrap &p);
diff --git a/Source/Core/Core/HW/SI_GCAdapter.cpp b/Source/Core/Core/HW/SI_GCAdapter.cpp
new file mode 100644
index 0000000000..dad95b3eb2
--- /dev/null
+++ b/Source/Core/Core/HW/SI_GCAdapter.cpp
@@ -0,0 +1,284 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include
+
+#include "Core/ConfigManager.h"
+#include "Core/HW/SI_GCAdapter.h"
+#include "InputCommon/GCPadStatus.h"
+
+static const u8 ENDPOINT_IN = 0x81;
+static const u8 ENDPOINT_OUT = 0x02;
+
+namespace SI_GCAdapter
+{
+
+static libusb_device_handle* handle = nullptr;
+static bool controller_connected[MAX_SI_CHANNELS] = { false, false, false, false };
+static u8 controller_payload[37];
+static u8 controller_last_rumble[4];
+static int controller_payload_size = 0;
+
+static std::thread adapter_thread;
+static bool adapter_thread_running;
+
+static bool libusb_driver_not_supported = false;
+
+void Read()
+{
+ while (adapter_thread_running)
+ {
+ libusb_interrupt_transfer(handle, ENDPOINT_IN, controller_payload, sizeof(controller_payload), &controller_payload_size, 0);
+ Common::YieldCPU();
+ }
+}
+
+void Init()
+{
+ if (handle != nullptr)
+ return;
+
+ libusb_driver_not_supported = false;
+
+ for (int i = 0; i < MAX_SI_CHANNELS; i++)
+ {
+ controller_connected[i] = false;
+ controller_last_rumble[i] = 0;
+ }
+
+ int ret = libusb_init(nullptr);
+
+ if (ret)
+ {
+ ERROR_LOG(SERIALINTERFACE, "libusb_init failed with error: %d", ret);
+ Shutdown();
+ }
+ else
+ {
+ libusb_device** list;
+ ssize_t cnt = libusb_get_device_list(nullptr, &list);
+ for (int d = 0; d < cnt; d++)
+ {
+ libusb_device* device = list[d];
+ libusb_device_descriptor desc;
+ int dRet = libusb_get_device_descriptor(device, &desc);
+ if (dRet)
+ {
+ // could not aquire the descriptor, no point in trying to use it.
+ ERROR_LOG(SERIALINTERFACE, "libusb_get_device_descriptor failed with error: %d", dRet);
+ continue;
+ }
+
+ if (desc.idVendor == 0x057e && desc.idProduct == 0x0337)
+ {
+ NOTICE_LOG(SERIALINTERFACE, "Found GC Adapter with Vendor: %X Product: %X Devnum: %d", desc.idVendor, desc.idProduct, 1);
+
+ u8 bus = libusb_get_bus_number(device);
+ u8 port = libusb_get_device_address(device);
+ ret = libusb_open(device, &handle);
+ if (ret)
+ {
+ if (ret == LIBUSB_ERROR_ACCESS)
+ {
+ if (dRet)
+ {
+ ERROR_LOG(SERIALINTERFACE, "Dolphin does not have access to this device: Bus %03d Device %03d: ID ????:???? (couldn't get id).",
+ bus,
+ port
+ );
+ }
+ else
+ {
+ ERROR_LOG(SERIALINTERFACE, "Dolphin does not have access to this device: Bus %03d Device %03d: ID %04X:%04X.",
+ bus,
+ port,
+ desc.idVendor,
+ desc.idProduct
+ );
+ }
+ }
+ else
+ {
+ ERROR_LOG(SERIALINTERFACE, "libusb_open failed to open device with error = %d", ret);
+ if (ret == LIBUSB_ERROR_NOT_SUPPORTED)
+ libusb_driver_not_supported = true;
+ }
+ Shutdown();
+ }
+ else if ((ret = libusb_kernel_driver_active(handle, 0)) == 1)
+ {
+ if ((ret = libusb_detach_kernel_driver(handle, 0)) && ret != LIBUSB_ERROR_NOT_SUPPORTED)
+ {
+ ERROR_LOG(SERIALINTERFACE, "libusb_detach_kernel_driver failed with error: %d", ret);
+ Shutdown();
+ }
+ }
+ else if (ret != 0 && ret != LIBUSB_ERROR_NOT_SUPPORTED)
+ {
+ ERROR_LOG(SERIALINTERFACE, "libusb_kernel_driver_active error ret = %d", ret);
+ Shutdown();
+ }
+ else if ((ret = libusb_claim_interface(handle, 0)))
+ {
+ ERROR_LOG(SERIALINTERFACE, "libusb_claim_interface failed with error: %d", ret);
+ Shutdown();
+ }
+ else
+ {
+ int tmp = 0;
+ unsigned char payload = 0x13;
+ libusb_interrupt_transfer(handle, ENDPOINT_OUT, &payload, sizeof(payload), &tmp, 0);
+
+ RefreshConnectedDevices();
+
+ adapter_thread_running = true;
+ adapter_thread = std::thread(Read);
+ }
+ }
+ }
+
+ libusb_free_device_list(list, 1);
+ }
+}
+
+void Shutdown()
+{
+ if (handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
+ return;
+
+ if (adapter_thread_running)
+ {
+ adapter_thread_running = false;
+ adapter_thread.join();
+ }
+
+ libusb_close(handle);
+ libusb_driver_not_supported = false;
+
+ for (int i = 0; i < MAX_SI_CHANNELS; i++)
+ controller_connected[i] = false;
+
+ handle = nullptr;
+}
+
+void Input(SerialInterface::SSIChannel* g_Channel)
+{
+ if (handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
+ return;
+
+ if (controller_payload_size != 0x25 || controller_payload[0] != 0x21)
+ {
+ ERROR_LOG(SERIALINTERFACE, "error reading payload (size: %d)", controller_payload_size);
+ Shutdown();
+ }
+ else
+ {
+ for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
+ {
+ bool connected = (controller_payload[1 + (9 * chan)] > 0);
+ if (connected && !controller_connected[chan])
+ NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload[1 + (9 * chan)]);
+
+ controller_connected[chan] = connected;
+
+ if (controller_connected[chan])
+ {
+ g_Channel[chan].m_InHi.Hex = 0;
+ g_Channel[chan].m_InLo.Hex = 0;
+ for (int j = 0; j < 4; j++)
+ {
+ g_Channel[chan].m_InHi.Hex |= (controller_payload[2 + chan + j + (8 * chan) + 0] << (8 * (3 - j)));
+ g_Channel[chan].m_InLo.Hex |= (controller_payload[2 + chan + j + (8 * chan) + 4] << (8 * (3 - j)));
+ }
+
+ u8 buttons_0 = ((g_Channel[chan].m_InHi.Hex >> 24) & 0xf0) >> 4;
+ u8 buttons_1 = (g_Channel[chan].m_InHi.Hex >> 24) & 0x0f;
+ u8 buttons_2 = ((g_Channel[chan].m_InHi.Hex >> 16) & 0xf0) >> 4;
+ u8 buttons_3 = (g_Channel[chan].m_InHi.Hex >> 16) & 0x0f;
+ g_Channel[chan].m_InHi.Hex = buttons_3 << 28 | buttons_1 << 24 | (buttons_2) << 20 | buttons_0 << 16 | (g_Channel[chan].m_InHi.Hex & 0x0000ffff);
+
+ if (controller_payload[1 + (9 * chan)] == 0x10)
+ g_Channel[chan].m_InHi.Hex |= (PAD_USE_ORIGIN << 16);
+ }
+ }
+ }
+}
+
+void Output(SerialInterface::SSIChannel* g_Channel)
+{
+ if (handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
+ return;
+
+ bool rumble_update = false;
+ for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
+ {
+ u8 current_rumble = g_Channel[chan].m_Out.Hex & 0xff;
+ if (current_rumble != controller_last_rumble[chan])
+ rumble_update = true;
+
+ controller_last_rumble[chan] = current_rumble;
+ }
+
+ if (rumble_update)
+ {
+ unsigned char rumble[5] = { 0x11, static_cast(g_Channel[0].m_Out.Hex & 0xff), static_cast(g_Channel[1].m_Out.Hex & 0xff), static_cast(g_Channel[2].m_Out.Hex & 0xff), static_cast(g_Channel[3].m_Out.Hex & 0xff) };
+ int size = 0;
+ libusb_interrupt_transfer(handle, ENDPOINT_OUT, rumble, sizeof(rumble), &size, 0);
+
+ if (size != 0x05)
+ {
+ WARN_LOG(SERIALINTERFACE, "error reading rumble (size: %d)", size);
+ Shutdown();
+ }
+ }
+}
+
+SIDevices GetDeviceType(int channel)
+{
+ if (handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
+ return SIDEVICE_NONE;
+
+ if (controller_connected[channel])
+ return SIDEVICE_GC_CONTROLLER;
+ else
+ return SIDEVICE_NONE;
+}
+
+void RefreshConnectedDevices()
+{
+ if (handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter)
+ return;
+
+ int size = 0;
+ libusb_interrupt_transfer(handle, ENDPOINT_IN, controller_payload, sizeof(controller_payload), &size, 0);
+
+ if (size != 0x25 || controller_payload[0] != 0x21)
+ {
+ WARN_LOG(SERIALINTERFACE, "error reading payload (size: %d)", size);
+ Shutdown();
+ }
+ else
+ {
+ for (int chan = 0; chan < MAX_SI_CHANNELS; chan++)
+ {
+ bool connected = (controller_payload[1 + (9 * chan)] > 0);
+ if (connected && !controller_connected[chan])
+ NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload[1 + (9 * chan)]);
+
+ controller_connected[chan] = connected;
+ }
+ }
+}
+
+bool IsDetected()
+{
+ return handle != nullptr;
+}
+
+bool IsDriverDetected()
+{
+ return !libusb_driver_not_supported;
+}
+
+} // end of namespace SI_GCAdapter
diff --git a/Source/Core/Core/HW/SI_GCAdapter.h b/Source/Core/Core/HW/SI_GCAdapter.h
new file mode 100644
index 0000000000..5095d3fbe8
--- /dev/null
+++ b/Source/Core/Core/HW/SI_GCAdapter.h
@@ -0,0 +1,29 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "Common/Thread.h"
+#include "Core/HW/SI.h"
+
+struct libusb_device_handle;
+struct libusb_device_descriptor;
+struct libusb_config_descriptor;
+struct libusb_interface_descriptor;
+struct libusb_endpoint_descriptor;
+struct libusb_transfer;
+
+namespace SI_GCAdapter
+{
+
+void Init();
+void Shutdown();
+void Input(SerialInterface::SSIChannel* g_Channel);
+void Output(SerialInterface::SSIChannel* g_Channel);
+SIDevices GetDeviceType(int channel);
+void RefreshConnectedDevices();
+bool IsDetected();
+bool IsDriverDetected();
+
+} // end of namespace SI_GCAdapter
diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp
index da7cc6145a..9e3607b438 100644
--- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp
+++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp
@@ -27,6 +27,9 @@
#include "Core/NetPlayProto.h"
#include "Core/HW/GCPad.h"
#include "Core/HW/SI.h"
+#if defined(__LIBUSB__) || defined (_WIN32)
+#include "Core/HW/SI_GCAdapter.h"
+#endif
#include "Core/HW/Wiimote.h"
#include "Core/HW/WiimoteReal/WiimoteReal.h"
#include "DolphinWX/ControllerConfigDiag.h"
@@ -68,7 +71,7 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent)
wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
{
- wxStaticBoxSizer* const gamecube_static_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("GameCube Controllers"));
+ wxStaticBoxSizer* const gamecube_static_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("GameCube Controllers"));
wxFlexGridSizer* const gamecube_flex_sizer = new wxFlexGridSizer(3, 5, 5);
wxStaticText* pad_labels[4];
@@ -101,8 +104,22 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
if (NetPlay::IsNetPlayRunning() || Movie::IsMovieActive())
pad_type_choices[i]->Disable();
+ SIDevices selected_device = SConfig::GetInstance().m_SIDevice[i];
+
+#if defined(__LIBUSB__) || defined (_WIN32)
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ {
+ SI_GCAdapter::RefreshConnectedDevices();
+ if (SI_GCAdapter::GetDeviceType(i) != SIDEVICE_NONE)
+ {
+ pad_type_choices[i]->Disable();
+ selected_device = SI_GCAdapter::GetDeviceType(i);
+ }
+ }
+#endif
+
// Set the saved pad type as the default choice.
- switch (SConfig::GetInstance().m_SIDevice[i])
+ switch (selected_device)
{
case SIDEVICE_GC_CONTROLLER:
pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[1]);
@@ -134,6 +151,36 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
}
gamecube_static_sizer->Add(gamecube_flex_sizer, 1, wxEXPAND, 5);
+ gamecube_static_sizer->AddSpacer(5);
+
+ wxStaticBoxSizer* const gamecube_adapter_group = new wxStaticBoxSizer(wxHORIZONTAL, this, _("GameCube Adapter"));
+ wxBoxSizer* const gamecube_adapter_sizer = new wxBoxSizer(wxHORIZONTAL);
+
+ wxCheckBox* const gamecube_adapter = new wxCheckBox(this, wxID_ANY, _("Direct Connect"));
+ gamecube_adapter->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnGameCubeAdapter, this);
+
+ gamecube_adapter_sizer->Add(gamecube_adapter, 0, wxEXPAND);
+ gamecube_adapter_group->Add(gamecube_adapter_sizer, 0, wxEXPAND);
+ gamecube_static_sizer->Add(gamecube_adapter_group, 0, wxEXPAND);
+
+#if defined(__LIBUSB__) || defined (_WIN32)
+ if (!SI_GCAdapter::IsDetected())
+ {
+ if (!SI_GCAdapter::IsDriverDetected())
+ gamecube_adapter->SetLabelText(_("Driver Not Detected"));
+ else
+ gamecube_adapter->SetLabelText(_("Adapter Not Detected"));
+ gamecube_adapter->SetValue(false);
+ gamecube_adapter->Disable();
+ }
+ else
+ {
+ gamecube_adapter->SetValue(SConfig::GetInstance().m_GameCubeAdapter);
+ if (Core::GetState() != Core::CORE_UNINITIALIZED)
+ gamecube_adapter->Disable();
+ }
+#endif
+
return gamecube_static_sizer;
}
diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.h b/Source/Core/DolphinWX/ControllerConfigDiag.h
index 3fbc56fb76..1c5df13f4f 100644
--- a/Source/Core/DolphinWX/ControllerConfigDiag.h
+++ b/Source/Core/DolphinWX/ControllerConfigDiag.h
@@ -59,6 +59,11 @@ public:
SConfig::GetInstance().m_WiimoteEnableSpeaker = event.IsChecked();
event.Skip();
}
+ void OnGameCubeAdapter(wxCommandEvent& event)
+ {
+ SConfig::GetInstance().m_GameCubeAdapter = event.IsChecked();
+ event.Skip();
+ }
private:
wxStaticBoxSizer* CreateGamecubeSizer();
diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp
index f54b1a9c76..8e260f582d 100644
--- a/Source/Core/UICommon/UICommon.cpp
+++ b/Source/Core/UICommon/UICommon.cpp
@@ -7,6 +7,9 @@
#include "Common/Logging/LogManager.h"
#include "Core/ConfigManager.h"
+#if defined(__LIBUSB__) || defined (_WIN32)
+#include "Core/HW/SI_GCAdapter.h"
+#endif
#include "Core/HW/Wiimote.h"
#include "UICommon/UICommon.h"
@@ -22,7 +25,9 @@ void Init()
SConfig::Init();
VideoBackend::PopulateList();
WiimoteReal::LoadSettings();
-
+#if defined(__LIBUSB__) || defined (_WIN32)
+ SI_GCAdapter::Init();
+#endif
VideoBackend::ActivateBackend(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoBackend);
SetEnableAlert(SConfig::GetInstance().m_LocalCoreStartupParameter.bUsePanicHandlers);
@@ -30,6 +35,9 @@ void Init()
void Shutdown()
{
+#if defined(__LIBUSB__) || defined (_WIN32)
+ SI_GCAdapter::Shutdown();
+#endif
WiimoteReal::Shutdown();
VideoBackend::ClearList();
SConfig::Shutdown();