diff --git a/Source/Core/Core/HW/SI.cpp b/Source/Core/Core/HW/SI.cpp index 736853b06b..a25c956f8f 100644 --- a/Source/Core/Core/HW/SI.cpp +++ b/Source/Core/Core/HW/SI.cpp @@ -15,9 +15,6 @@ #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" @@ -59,6 +56,56 @@ 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 { @@ -337,9 +384,7 @@ 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; @@ -462,29 +507,6 @@ 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 2f22996e6e..2e06b269a1 100644 --- a/Source/Core/Core/HW/SI.h +++ b/Source/Core/Core/HW/SI.h @@ -20,56 +20,6 @@ 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_DeviceGCController.cpp b/Source/Core/Core/HW/SI_DeviceGCController.cpp index 667df524ae..699e560e43 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCController.cpp @@ -12,6 +12,9 @@ #include "Core/HW/SI.h" #include "Core/HW/SI_Device.h" #include "Core/HW/SI_DeviceGCController.h" +#if defined(__LIBUSB__) || defined (_WIN32) +#include "Core/HW/SI_GCAdapter.h" +#endif #include "Core/HW/SystemTimers.h" // --- standard GameCube controller --- @@ -110,6 +113,11 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) memset(&PadStatus, 0, sizeof(PadStatus)); Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus); + +#if defined(__LIBUSB__) || defined (_WIN32) + SI_GCAdapter::Input(ISIDevice::m_iDeviceNumber, &PadStatus); +#endif + Movie::CallGCInputManip(&PadStatus, ISIDevice::m_iDeviceNumber); Movie::SetPolledDevice(); @@ -248,6 +256,9 @@ void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll) // get the correct pad number that should rumble locally when using netplay const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); +#if defined(__LIBUSB__) || defined (_WIN32) + SI_GCAdapter::Output(numPAD, command.Parameter1 & 0xff); +#endif if (numPAD < 4) { if (uType == 1 && uStrength > 2) diff --git a/Source/Core/Core/HW/SI_GCAdapter.cpp b/Source/Core/Core/HW/SI_GCAdapter.cpp index f446ed52cf..d7119f5148 100644 --- a/Source/Core/Core/HW/SI_GCAdapter.cpp +++ b/Source/Core/Core/HW/SI_GCAdapter.cpp @@ -6,7 +6,6 @@ #include "Core/ConfigManager.h" #include "Core/HW/SI_GCAdapter.h" -#include "InputCommon/GCPadStatus.h" namespace SI_GCAdapter { @@ -19,7 +18,7 @@ enum ControllerTypes static libusb_device_handle* s_handle = nullptr; static u8 s_controller_type[MAX_SI_CHANNELS] = { CONTROLLER_NONE, CONTROLLER_NONE, CONTROLLER_NONE, CONTROLLER_NONE }; -static u8 s_controller_last_rumble[4]; +static u8 s_controller_rumble[4]; static std::mutex s_mutex; static u8 s_controller_payload[37]; @@ -60,7 +59,7 @@ void Init() for (int i = 0; i < MAX_SI_CHANNELS; i++) { s_controller_type[i] = CONTROLLER_NONE; - s_controller_last_rumble[i] = 0; + s_controller_rumble[i] = 0; } int ret = libusb_init(nullptr); @@ -196,7 +195,7 @@ void Shutdown() s_handle = nullptr; } -void Input(SerialInterface::SSIChannel* g_Channel) +void Input(int chan, GCPadStatus* pad) { if (s_handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter) return; @@ -215,60 +214,43 @@ void Input(SerialInterface::SSIChannel* g_Channel) } else { - for (int chan = 0; chan < MAX_SI_CHANNELS; chan++) + u8 type = controller_payload_copy[1 + (9 * chan)] >> 4; + if (type != CONTROLLER_NONE && s_controller_type[chan] == CONTROLLER_NONE) + NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload_copy[1 + (9 * chan)]); + + s_controller_type[chan] = type; + + if (s_controller_type[chan] != CONTROLLER_NONE) { - u8 type = controller_payload_copy[1 + (9 * chan)] >> 4; - if (type != CONTROLLER_NONE && s_controller_type[chan] == CONTROLLER_NONE) - NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload_copy[1 + (9 * chan)]); + pad->button = controller_payload_copy[1 + (9 * chan) + 1] << 8; - s_controller_type[chan] = type; + u8 b = controller_payload_copy[1 + (9 * chan) + 2]; + if (b & (1 << 0)) pad->button |= PAD_BUTTON_START; + if (b & (1 << 1)) pad->button |= PAD_TRIGGER_Z; + if (b & (1 << 2)) pad->button |= PAD_TRIGGER_R; + if (b & (1 << 3)) pad->button |= PAD_TRIGGER_L; - if (s_controller_type[chan] != CONTROLLER_NONE) - { - 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_copy[2 + chan + j + (8 * chan) + 0] << (8 * (3 - j))); - g_Channel[chan].m_InLo.Hex |= (controller_payload_copy[2 + chan + j + (8 * chan) + 4] << (8 * (3 - j))); - } - - u8 buttons_0 = (g_Channel[chan].m_InHi.Hex >> 28) & 0x0f; - u8 buttons_1 = (g_Channel[chan].m_InHi.Hex >> 24) & 0x0f; - u8 buttons_2 = (g_Channel[chan].m_InHi.Hex >> 20) & 0x0f; - 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 (type == CONTROLLER_WIRED || type == CONTROLLER_WIRELESS) - g_Channel[chan].m_InHi.Hex |= (PAD_USE_ORIGIN << 16); - } + pad->stickX = controller_payload_copy[1 + (9 * chan) + 3]; + pad->stickY = controller_payload_copy[1 + (9 * chan) + 4]; + pad->substickX = controller_payload_copy[1 + (9 * chan) + 5]; + pad->substickY = controller_payload_copy[1 + (9 * chan) + 6]; + pad->triggerLeft = controller_payload_copy[1 + (9 * chan) + 7]; + pad->triggerRight = controller_payload_copy[1 + (9 * chan) + 8]; } } } -void Output(SerialInterface::SSIChannel* g_Channel) +void Output(int chan, u8 rumble) { if (s_handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter) return; - bool rumble_update = false; - u8 current_rumble[4] = { 0, 0, 0, 0 }; - - for (int chan = 0; chan < MAX_SI_CHANNELS; chan++) + // Skip over rumble commands if it has not changed or the controller is wireless + if (rumble != s_controller_rumble[chan] && s_controller_type[chan] != CONTROLLER_WIRELESS) { - // Skip over rumble commands if the controller is wireless - if (s_controller_type[chan] != CONTROLLER_WIRELESS) - current_rumble[chan] = g_Channel[chan].m_Out.Hex & 0xff; + s_controller_rumble[chan] = rumble; - if (current_rumble[chan] != s_controller_last_rumble[chan]) - rumble_update = true; - - s_controller_last_rumble[chan] = current_rumble[chan]; - } - - if (rumble_update) - { - unsigned char rumble[5] = { 0x11, current_rumble[0], current_rumble[1], current_rumble[2], current_rumble[3] }; + unsigned char rumble[5] = { 0x11, s_controller_rumble[0], s_controller_rumble[1], s_controller_rumble[2], s_controller_rumble[3] }; int size = 0; libusb_interrupt_transfer(s_handle, s_endpoint_out, rumble, sizeof(rumble), &size, 0); diff --git a/Source/Core/Core/HW/SI_GCAdapter.h b/Source/Core/Core/HW/SI_GCAdapter.h index 07fe64f7ef..11560aa95d 100644 --- a/Source/Core/Core/HW/SI_GCAdapter.h +++ b/Source/Core/Core/HW/SI_GCAdapter.h @@ -6,14 +6,15 @@ #include "Common/Thread.h" #include "Core/HW/SI.h" +#include "InputCommon/GCPadStatus.h" namespace SI_GCAdapter { void Init(); void Shutdown(); -void Input(SerialInterface::SSIChannel* g_Channel); -void Output(SerialInterface::SSIChannel* g_Channel); +void Input(int chan, GCPadStatus* pad); +void Output(int chan, u8 rumble); SIDevices GetDeviceType(int channel); void RefreshConnectedDevices(); bool IsDetected(); diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 9e3607b438..f1a36c7efa 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -104,22 +104,8 @@ 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 (selected_device) + switch (SConfig::GetInstance().m_SIDevice[i]) { case SIDEVICE_GC_CONTROLLER: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[1]);