From 371e9f4fae0cd60004d7cfd13cc832bc18808de2 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 31 Dec 2015 10:27:51 -0600 Subject: [PATCH 1/7] Move SI_GCAdapter over to InputCommon --- Source/Core/Core/CMakeLists.txt | 3 +-- Source/Core/Core/Core.cpp | 10 ++++------ Source/Core/Core/Core.vcxproj | 8 -------- Source/Core/Core/Core.vcxproj.filters | 6 ------ Source/Core/DolphinWX/ControllerConfigDiag.cpp | 4 +--- Source/Core/DolphinWX/ControllerConfigDiag.h | 2 +- Source/Core/InputCommon/CMakeLists.txt | 6 ++++-- .../HW/SI_GCAdapter.cpp => InputCommon/GCAdapter.cpp} | 0 .../HW/SI_GCAdapter.h => InputCommon/GCAdapter.h} | 0 Source/Core/InputCommon/InputCommon.vcxproj | 10 +++++++++- Source/Core/InputCommon/InputCommon.vcxproj.filters | 4 +++- Source/Core/UICommon/UICommon.cpp | 9 ++++----- 12 files changed, 27 insertions(+), 35 deletions(-) rename Source/Core/{Core/HW/SI_GCAdapter.cpp => InputCommon/GCAdapter.cpp} (100%) rename Source/Core/{Core/HW/SI_GCAdapter.h => InputCommon/GCAdapter.h} (100%) diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 10a51b4a65..b37c78e309 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -239,8 +239,7 @@ set(LIBS if(LIBUSB_FOUND) # Using shared LibUSB set(LIBS ${LIBS} ${LIBUSB_LIBRARIES}) - set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp - HW/SI_GCAdapter.cpp) + set(SRCS ${SRCS} IPC_HLE/WII_IPC_HLE_Device_hid.cpp) endif(LIBUSB_FOUND) set(LIBS ${LIBS} ${MBEDTLS_LIBRARIES}) diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index c49d89c847..0d614c9634 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -48,9 +48,6 @@ #include "Core/HW/HW.h" #include "Core/HW/Memmap.h" #include "Core/HW/ProcessorInterface.h" -#if defined(__LIBUSB__) || defined(_WIN32) -#include "Core/HW/SI_GCAdapter.h" -#endif #include "Core/HW/SystemTimers.h" #include "Core/HW/VideoInterface.h" #include "Core/HW/Wiimote.h" @@ -65,6 +62,7 @@ #endif #include "DiscIO/FileMonitor.h" +#include "InputCommon/GCAdapter.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/VideoBackendBase.h" @@ -285,7 +283,7 @@ void Stop() // - Hammertime! g_video_backend->Video_ExitLoop(); } #if defined(__LIBUSB__) || defined(_WIN32) - SI_GCAdapter::ResetRumble(); + GCAdapter::ResetRumble(); #endif #ifdef USE_MEMORYWATCHER @@ -630,7 +628,7 @@ void SetState(EState _State) CPU::EnableStepping(true); // Break Wiimote::Pause(); #if defined(__LIBUSB__) || defined(_WIN32) - SI_GCAdapter::ResetRumble(); + GCAdapter::ResetRumble(); #endif break; case CORE_RUN: @@ -741,7 +739,7 @@ bool PauseAndLock(bool doLock, bool unpauseOnUnlock) g_video_backend->PauseAndLock(doLock, unpauseOnUnlock); #if defined(__LIBUSB__) || defined(_WIN32) - SI_GCAdapter::ResetRumble(); + GCAdapter::ResetRumble(); #endif return wasUnpaused; } diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 05af583ed2..87f7e52bd4 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -148,13 +148,6 @@ - - - 4200;%(DisableSpecificWarnings) - @@ -360,7 +353,6 @@ - diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index a374defc07..855ee5edcb 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -720,9 +720,6 @@ PowerPC - - HW %28Flipper/Hollywood%29\SI - Serial Interface - PowerPC\JitCommon @@ -1241,9 +1238,6 @@ HW %28Flipper/Hollywood%29\GCKeyboard - - HW %28Flipper/Hollywood%29\SI - Serial Interface - PowerPC\Jit64Common diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 149247dd81..85154040ea 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -26,13 +26,11 @@ #include "Core/HW/GCKeyboard.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" #include "DolphinWX/InputConfigDiag.h" +#include "InputCommon/GCAdapter.h" #if defined(HAVE_XRANDR) && HAVE_XRANDR #include "DolphinWX/X11Utils.h" diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.h b/Source/Core/DolphinWX/ControllerConfigDiag.h index f679992b54..7bfc76bca7 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.h +++ b/Source/Core/DolphinWX/ControllerConfigDiag.h @@ -10,8 +10,8 @@ #include "Common/SysConf.h" #include "Core/ConfigManager.h" -#include "Core/HW/SI_GCAdapter.h" #include "Core/HW/Wiimote.h" +#include "InputCommon/GCAdapter.h" class InputConfig; class wxButton; diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index b200625000..254dffce10 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -3,8 +3,6 @@ set(SRCS ControllerEmu.cpp ControllerInterface/ControllerInterface.cpp ControllerInterface/Device.cpp ControllerInterface/ExpressionParser.cpp) - - set(LIBS common) if(WIN32) @@ -37,6 +35,10 @@ elseif(ANDROID) ControllerInterface/Android/Android.cpp) endif() +if(LIBUSB_FOUND) + set(SRCS ${SRCS} GCAdapter.cpp) +endif(LIBUSB_FOUND) + if(LIBEVDEV_FOUND AND LIBUDEV_FOUND) set(SRCS ${SRCS} ControllerInterface/evdev/evdev.cpp) set(LIBS ${LIBS} ${LIBEVDEV_LIBRARY} ${LIBUDEV_LIBRARY}) diff --git a/Source/Core/Core/HW/SI_GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp similarity index 100% rename from Source/Core/Core/HW/SI_GCAdapter.cpp rename to Source/Core/InputCommon/GCAdapter.cpp diff --git a/Source/Core/Core/HW/SI_GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h similarity index 100% rename from Source/Core/Core/HW/SI_GCAdapter.h rename to Source/Core/InputCommon/GCAdapter.h diff --git a/Source/Core/InputCommon/InputCommon.vcxproj b/Source/Core/InputCommon/InputCommon.vcxproj index 347c06e770..3e63243949 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj +++ b/Source/Core/InputCommon/InputCommon.vcxproj @@ -52,6 +52,13 @@ + + + 4200;%(DisableSpecificWarnings) + @@ -66,6 +73,7 @@ + @@ -80,4 +88,4 @@ - \ No newline at end of file + diff --git a/Source/Core/InputCommon/InputCommon.vcxproj.filters b/Source/Core/InputCommon/InputCommon.vcxproj.filters index 3c16ad5f26..6a63852303 100644 --- a/Source/Core/InputCommon/InputCommon.vcxproj.filters +++ b/Source/Core/InputCommon/InputCommon.vcxproj.filters @@ -16,6 +16,7 @@ + ControllerInterface\DInput @@ -47,6 +48,7 @@ + @@ -83,4 +85,4 @@ - \ No newline at end of file + diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 5ba825f5e2..8a4e76c535 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -11,11 +11,10 @@ #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 "InputCommon/GCAdapter.h" + #include "UICommon/UICommon.h" #include "VideoCommon/VideoBackendBase.h" @@ -30,7 +29,7 @@ void Init() VideoBackend::PopulateList(); WiimoteReal::LoadSettings(); #if defined(__LIBUSB__) || defined (_WIN32) - SI_GCAdapter::Init(); + GCAdapter::Init(); #endif VideoBackend::ActivateBackend(SConfig::GetInstance().m_strVideoBackend); @@ -40,7 +39,7 @@ void Init() void Shutdown() { #if defined(__LIBUSB__) || defined (_WIN32) - SI_GCAdapter::Shutdown(); + GCAdapter::Shutdown(); #endif WiimoteReal::Shutdown(); VideoBackend::ClearList(); From 6e932af8312650a7373630742776979440bebb9c Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 31 Dec 2015 10:33:48 -0600 Subject: [PATCH 2/7] Add two missing values that can fit in GCPadStatus --- Source/Core/InputCommon/GCPadStatus.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/InputCommon/GCPadStatus.h b/Source/Core/InputCommon/GCPadStatus.h index d6bb972de1..deecb30523 100644 --- a/Source/Core/InputCommon/GCPadStatus.h +++ b/Source/Core/InputCommon/GCPadStatus.h @@ -17,6 +17,8 @@ enum PadError enum { PAD_USE_ORIGIN = 0x0080, + PAD_GET_ORIGIN = 0x2000, + PAD_ERR_STATUS = 0x8000, }; enum PadButton From 49410576e945ba7bf762b83a474005f1babc5b54 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 31 Dec 2015 11:09:47 -0600 Subject: [PATCH 3/7] Make the Wii U Gamecube adapter work with less magic. The Wii U Gamecube controller adapter setup has always been a bit weird. It tries to be as automatic as possible to make the user experience as easy as possible. The problem with this approach is that it brings a large disconnect in the user experience because you have the Gamecube controller setup with regular gamepads and then for some reason below that you have a "direct connect" option which will cause the Gamecube Adapter to overwrite the regular inputs if something was connected. While this works and allows the user to only click one checkbox to get the device working, it breaks the user's experience because they don't really know what "direct connect" means and won't look it up to figure out what it is. Just expecting the device to work (At least one occurence of this in the IRC channel in the last week). This way around also had the terrible nature of making the code more filthy than it needed to be. The GCAdapter namespace was parasitic and hooked in to the regular GC Controller SI class to overwrite the data that it was getting from the default configuration. Now instead we have a specific SIDevice class for the Wii U Gamecube adapter. This class is fairly simple and is a child of the regular SI Gamecube Pad device and only reimplements what it needs to. This also gives the ability to configure controllers individually, which allows the user to configure rumble individually per pad input. Overall the code is cleaner, and it fits more in line with how the rest of Dolphin works. --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/ConfigManager.cpp | 6 +- Source/Core/Core/ConfigManager.h | 3 +- Source/Core/Core/Core.vcxproj | 2 + Source/Core/Core/Core.vcxproj.filters | 6 + Source/Core/Core/HW/SI_Device.cpp | 4 + Source/Core/Core/HW/SI_Device.h | 3 +- Source/Core/Core/HW/SI_DeviceGCAdapter.cpp | 147 ++++++++++++++++++ Source/Core/Core/HW/SI_DeviceGCAdapter.h | 20 +++ Source/Core/Core/HW/SI_DeviceGCController.cpp | 62 +++----- Source/Core/DolphinWX/CMakeLists.txt | 1 + .../DolphinWX/Config/GCAdapterConfigDiag.cpp | 78 ++++++++++ .../DolphinWX/Config/GCAdapterConfigDiag.h | 35 +++++ .../Core/DolphinWX/ControllerConfigDiag.cpp | 112 ++++--------- Source/Core/DolphinWX/ControllerConfigDiag.h | 23 +-- Source/Core/DolphinWX/DolphinWX.vcxproj | 4 +- .../Core/DolphinWX/DolphinWX.vcxproj.filters | 8 +- Source/Core/InputCommon/GCAdapter.cpp | 48 +++++- Source/Core/InputCommon/GCAdapter.h | 6 +- 19 files changed, 412 insertions(+), 157 deletions(-) create mode 100644 Source/Core/Core/HW/SI_DeviceGCAdapter.cpp create mode 100644 Source/Core/Core/HW/SI_DeviceGCAdapter.h create mode 100644 Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp create mode 100644 Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index b37c78e309..b035b64859 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -113,6 +113,7 @@ set(SRCS ActionReplay.cpp HW/SI_Device.cpp HW/SI_DeviceDanceMat.cpp HW/SI_DeviceGBA.cpp + HW/SI_DeviceGCAdapter.cpp HW/SI_DeviceGCController.cpp HW/SI_DeviceGCSteeringWheel.cpp HW/SI_DeviceKeyboard.cpp diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index db933bceaf..5e9901f5d8 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -254,6 +254,7 @@ void SConfig::SaveCoreSettings(IniFile& ini) for (int i = 0; i < MAX_SI_CHANNELS; ++i) { core->Set(StringFromFormat("SIDevice%i", i), m_SIDevice[i]); + core->Set(StringFromFormat("AdapterRumble%i", i), m_AdapterRumble[i]); } core->Set("WiiSDCard", m_WiiSDCard); core->Set("WiiKeyboard", m_WiiKeyboard); @@ -267,8 +268,6 @@ void SConfig::SaveCoreSettings(IniFile& ini) core->Set("OverclockEnable", m_OCEnable); core->Set("GFXBackend", m_strVideoBackend); core->Set("GPUDeterminismMode", m_strGPUDeterminismMode); - core->Set("GameCubeAdapter", m_GameCubeAdapter); - core->Set("AdapterRumble", m_AdapterRumble); core->Set("PerfMapDir", m_perfDir); } @@ -509,6 +508,7 @@ void SConfig::LoadCoreSettings(IniFile& ini) for (int i = 0; i < MAX_SI_CHANNELS; ++i) { core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE); + core->Get(StringFromFormat("AdapterRumble%i", i), &m_AdapterRumble[i], true); } core->Get("WiiSDCard", &m_WiiSDCard, false); core->Get("WiiKeyboard", &m_WiiKeyboard, false); @@ -532,8 +532,6 @@ void SConfig::LoadCoreSettings(IniFile& ini) core->Get("FrameSkip", &m_FrameSkip, 0); core->Get("GFXBackend", &m_strVideoBackend, ""); core->Get("GPUDeterminismMode", &m_strGPUDeterminismMode, "auto"); - core->Get("GameCubeAdapter", &m_GameCubeAdapter, false); - core->Get("AdapterRumble", &m_AdapterRumble, true); core->Get("PerfMapDir", &m_perfDir, ""); } diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index de2be855e8..880e93bc8a 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -265,8 +265,7 @@ struct SConfig : NonCopyable // Input settings bool m_BackgroundInput; - bool m_GameCubeAdapter; - bool m_AdapterRumble; + bool m_AdapterRumble[4]; SysConf* m_SYSCONF; diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 87f7e52bd4..490e724006 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -145,6 +145,7 @@ + @@ -350,6 +351,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 855ee5edcb..1a3df6a407 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -447,6 +447,9 @@ HW %28Flipper/Hollywood%29\SI - Serial Interface + + HW %28Flipper/Hollywood%29\SI - Serial Interface + HW %28Flipper/Hollywood%29\SI - Serial Interface @@ -988,6 +991,9 @@ HW %28Flipper/Hollywood%29\SI - Serial Interface + + HW %28Flipper/Hollywood%29\SI - Serial Interface + HW %28Flipper/Hollywood%29\SI - Serial Interface diff --git a/Source/Core/Core/HW/SI_Device.cpp b/Source/Core/Core/HW/SI_Device.cpp index 9546cba42f..fb9b9ec638 100644 --- a/Source/Core/Core/HW/SI_Device.cpp +++ b/Source/Core/Core/HW/SI_Device.cpp @@ -11,6 +11,7 @@ #include "Core/HW/SI_DeviceAMBaseboard.h" #include "Core/HW/SI_DeviceDanceMat.h" #include "Core/HW/SI_DeviceGBA.h" +#include "Core/HW/SI_DeviceGCAdapter.h" #include "Core/HW/SI_DeviceGCController.h" #include "Core/HW/SI_DeviceGCSteeringWheel.h" #include "Core/HW/SI_DeviceKeyboard.h" @@ -73,6 +74,9 @@ std::unique_ptr SIDevice_Create(const SIDevices device, const int por case SIDEVICE_GC_CONTROLLER: return std::make_unique(device, port_number); + case SIDEVICE_WIIU_ADAPTER: + return std::make_unique(device, port_number); + case SIDEVICE_DANCEMAT: return std::make_unique(device, port_number); diff --git a/Source/Core/Core/HW/SI_Device.h b/Source/Core/Core/HW/SI_Device.h index abaf25cbd3..866ae98e2a 100644 --- a/Source/Core/Core/HW/SI_Device.h +++ b/Source/Core/Core/HW/SI_Device.h @@ -61,7 +61,8 @@ enum SIDevices : int SIDEVICE_GC_STEERING, SIDEVICE_DANCEMAT, SIDEVICE_GC_TARUKONGA, - SIDEVICE_AM_BASEBOARD + SIDEVICE_AM_BASEBOARD, + SIDEVICE_WIIU_ADAPTER, }; diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp new file mode 100644 index 0000000000..70215aa6a8 --- /dev/null +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp @@ -0,0 +1,147 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Common/MsgHandler.h" +#include "Common/Logging/Log.h" +#include "Core/Movie.h" +#include "Core/HW/SI_DeviceGCAdapter.h" + +GCPadStatus CSIDevice_GCAdapter::GetPadStatus() +{ + GCPadStatus PadStatus; + memset(&PadStatus, 0, sizeof(PadStatus)); + +#if defined(__LIBUSB__) || defined (_WIN32) + GCAdapter::Input(ISIDevice::m_iDeviceNumber, &PadStatus); +#endif + + HandleMoviePadStatus(&PadStatus); + + return PadStatus; +} + +int CSIDevice_GCAdapter::RunBuffer(u8* _pBuffer, int _iLength) +{ + // For debug logging only + ISIDevice::RunBuffer(_pBuffer, _iLength); + + // Read the command + EBufferCommands command = static_cast(_pBuffer[3]); + +#if defined(__LIBUSB__) || defined (_WIN32) + // get the correct pad number that should rumble locally when using netplay + const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); + if (!GCAdapter::DeviceConnected(numPAD)) +#endif + { + reinterpret_cast(_pBuffer)[0] = SI_NONE; + return 4; + } + + // Handle it + switch (command) + { + case CMD_RESET: + case CMD_ID: + *(u32*)&_pBuffer[0] = SI_GC_CONTROLLER; + break; + + case CMD_DIRECT: + { + INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength); + u32 high, low; + GetData(high, low); + for (int i = 0; i < (_iLength - 1) / 2; i++) + { + _pBuffer[i + 0] = (high >> (i * 8)) & 0xff; + _pBuffer[i + 4] = (low >> (i * 8)) & 0xff; + } + } + break; + + case CMD_ORIGIN: + { + INFO_LOG(SERIALINTERFACE, "PAD - Get Origin"); + + Calibrate(); + + u8* pCalibration = reinterpret_cast(&m_Origin); + for (int i = 0; i < (int)sizeof(SOrigin); i++) + { + _pBuffer[i ^ 3] = *pCalibration++; + } + } + break; + + // Recalibrate (FiRES: i am not 100 percent sure about this) + case CMD_RECALIBRATE: + { + INFO_LOG(SERIALINTERFACE, "PAD - Recalibrate"); + + Calibrate(); + + u8* pCalibration = reinterpret_cast(&m_Origin); + for (int i = 0; i < (int)sizeof(SOrigin); i++) + { + _pBuffer[i ^ 3] = *pCalibration++; + } + } + break; + + // DEFAULT + default: + { + ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command); + PanicAlert("SI: Unknown command (0x%x)", command); + } + break; + } + + return _iLength; +} + +void CSIDevice_GCAdapter::SendCommand(u32 _Cmd, u8 _Poll) +{ + UCommand command(_Cmd); + + switch (command.Command) + { + // Costis sent it in some demos :) + case 0x00: + break; + + case CMD_WRITE: + { +#if defined(__LIBUSB__) || defined (_WIN32) + unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard + unsigned int uStrength = command.Parameter2; + + // get the correct pad number that should rumble locally when using netplay + const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); + + if (numPAD < 4) + { + if (uType == 1 && uStrength > 2) + GCAdapter::Output(numPAD, 1); + else + GCAdapter::Output(numPAD, 0); + } +#endif + if (!_Poll) + { + m_Mode = command.Parameter2; + INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode); + } + } + break; + + default: + { + ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd); + PanicAlert("SI: Unknown direct command"); + } + break; + } +} + diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.h b/Source/Core/Core/HW/SI_DeviceGCAdapter.h new file mode 100644 index 0000000000..05c73253fc --- /dev/null +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.h @@ -0,0 +1,20 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "Core/HW/SI_Device.h" +#include "Core/HW/SI_DeviceGCController.h" +#include "InputCommon/GCAdapter.h" +#include "InputCommon/GCPadStatus.h" + +class CSIDevice_GCAdapter : public CSIDevice_GCController +{ +public: + CSIDevice_GCAdapter(SIDevices device, int _iDeviceNumber) : CSIDevice_GCController(device, _iDeviceNumber) {} + + GCPadStatus GetPadStatus() override; + int RunBuffer(u8* _pBuffer, int _iLength) override; + void SendCommand(u32 _Cmd, u8 _Poll) override; +}; diff --git a/Source/Core/Core/HW/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI_DeviceGCController.cpp index ccf27baac4..3b2a191b2e 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCController.cpp @@ -13,9 +13,6 @@ #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" #include "InputCommon/GCPadStatus.h" @@ -119,6 +116,30 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength) return _iLength; } +void CSIDevice_GCController::HandleMoviePadStatus(GCPadStatus* PadStatus) +{ + Movie::CallGCInputManip(PadStatus, ISIDevice::m_iDeviceNumber); + + Movie::SetPolledDevice(); + if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, PadStatus)) + { + } + else if (Movie::IsPlayingInput()) + { + Movie::PlayController(PadStatus, ISIDevice::m_iDeviceNumber); + Movie::InputUpdate(); + } + else if (Movie::IsRecordingInput()) + { + Movie::RecordInput(PadStatus, ISIDevice::m_iDeviceNumber); + Movie::InputUpdate(); + } + else + { + Movie::CheckPadStatus(PadStatus, ISIDevice::m_iDeviceNumber); + } +} + GCPadStatus CSIDevice_GCController::GetPadStatus() { GCPadStatus PadStatus; @@ -126,31 +147,7 @@ GCPadStatus CSIDevice_GCController::GetPadStatus() 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(); - if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, &PadStatus)) - { - } - else if (Movie::IsPlayingInput()) - { - Movie::PlayController(&PadStatus, ISIDevice::m_iDeviceNumber); - Movie::InputUpdate(); - } - else if (Movie::IsRecordingInput()) - { - Movie::RecordInput(&PadStatus, ISIDevice::m_iDeviceNumber); - Movie::InputUpdate(); - } - else - { - Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber); - } - + HandleMoviePadStatus(&PadStatus); return PadStatus; } @@ -281,15 +278,6 @@ 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) - if (numPAD < 4) - { - if (uType == 1 && uStrength > 2) - SI_GCAdapter::Output(numPAD, 1); - else - SI_GCAdapter::Output(numPAD, 0); - } -#endif if (numPAD < 4) { if (uType == 1 && uStrength > 2) diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index d9cdb9bd9b..1c17ccd207 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -10,6 +10,7 @@ set(GUI_SRCS Config/AudioConfigPane.cpp Config/ConfigMain.cpp Config/GameCubeConfigPane.cpp + Config/GCAdapterConfigDiag.cpp Config/GeneralConfigPane.cpp Config/InterfaceConfigPane.cpp Config/PathConfigPane.cpp diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp new file mode 100644 index 0000000000..21d64a686d --- /dev/null +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp @@ -0,0 +1,78 @@ +// Copyright 2010 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include "Common/CommonTypes.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "DolphinWX/Config/GCAdapterConfigDiag.h" +#include "InputCommon/GCAdapter.h" + +wxDEFINE_EVENT(wxEVT_ADAPTER_UPDATE, wxCommandEvent); + + +GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& name, const int tab_num) + : wxDialog(parent, wxID_ANY, name, wxPoint(128,-1)), m_pad_id(tab_num) +{ + wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL); + + + wxCheckBox* const gamecube_rumble = new wxCheckBox(this, wxID_ANY, _("Rumble")); + gamecube_rumble->SetValue(SConfig::GetInstance().m_AdapterRumble[m_pad_id]); + gamecube_rumble->Bind(wxEVT_CHECKBOX, &GCAdapterConfigDiag::OnAdapterRumble, this); + + m_adapter_status = new wxStaticText(this, wxID_ANY, _("Adapter Not Detected")); + +#if defined(__LIBUSB__) || defined (_WIN32) + if (!GCAdapter::IsDetected()) + { + if (!GCAdapter::IsDriverDetected()) + { + m_adapter_status->SetLabelText(_("Driver Not Detected")); + gamecube_rumble->Disable(); + } + } + else + { + m_adapter_status->SetLabelText(_("Adapter Detected")); + } + GCAdapter::SetAdapterCallback(std::bind(&GCAdapterConfigDiag::ScheduleAdapterUpdate, this)); +#endif + + szr->Add(m_adapter_status, 0, wxEXPAND); + szr->Add(gamecube_rumble, 0, wxEXPAND); + szr->Add(CreateButtonSizer(wxOK | wxNO_DEFAULT), 0, wxEXPAND|wxALL, 5); + + SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED); + SetSizerAndFit(szr); + Center(); + + Bind(wxEVT_ADAPTER_UPDATE, &GCAdapterConfigDiag::UpdateAdapter, this); +} + +void GCAdapterConfigDiag::ScheduleAdapterUpdate() +{ + wxQueueEvent(this, new wxCommandEvent(wxEVT_ADAPTER_UPDATE)); +} + +void GCAdapterConfigDiag::UpdateAdapter(wxCommandEvent& ev) +{ +#if defined(__LIBUSB__) || defined (_WIN32) + bool unpause = Core::PauseAndLock(true); + if (GCAdapter::IsDetected()) + m_adapter_status->SetLabelText(_("Adapter Detected")); + else + m_adapter_status->SetLabelText(_("Adapter Not Detected")); + Core::PauseAndLock(false, unpause); +#endif +} + +GCAdapterConfigDiag::~GCAdapterConfigDiag() +{ +#if defined(__LIBUSB__) || defined (_WIN32) + GCAdapter::SetAdapterCallback(nullptr); +#endif +} diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h new file mode 100644 index 0000000000..fa7bf471d8 --- /dev/null +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h @@ -0,0 +1,35 @@ +// Copyright 2010 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Core/ConfigManager.h" + +class GCAdapterConfigDiag : public wxDialog +{ +public: + GCAdapterConfigDiag(wxWindow* const parent, const wxString& name, const int tab_num = 0); + ~GCAdapterConfigDiag(); + + void ScheduleAdapterUpdate(); + void UpdateAdapter(wxCommandEvent& ev); + +private: + wxStaticText* m_adapter_status; + int m_pad_id; + + void OnAdapterRumble(wxCommandEvent& event) + { + SConfig::GetInstance().m_AdapterRumble[m_pad_id] = event.IsChecked(); + } +}; diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 85154040ea..1e736ce56b 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -30,20 +30,20 @@ #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "DolphinWX/ControllerConfigDiag.h" #include "DolphinWX/InputConfigDiag.h" +#include "DolphinWX/Config/GCAdapterConfigDiag.h" #include "InputCommon/GCAdapter.h" #if defined(HAVE_XRANDR) && HAVE_XRANDR #include "DolphinWX/X11Utils.h" #endif -wxDEFINE_EVENT(wxEVT_ADAPTER_UPDATE, wxCommandEvent); - ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent) : wxDialog(parent, wxID_ANY, _("Dolphin Controller Configuration")) { m_gc_pad_type_strs = {{ _("None"), _("Standard Controller"), + _("GameCube Adapter for Wii U"), _("Steering Wheel"), _("Dance Mat"), _("TaruKonga (Bongos)"), @@ -68,7 +68,6 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent) SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED); SetSizerAndFit(main_sizer); Center(); - Bind(wxEVT_ADAPTER_UPDATE, &ControllerConfigDiag::UpdateAdapter, this); } wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer() @@ -111,24 +110,27 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer() case SIDEVICE_GC_CONTROLLER: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[1]); break; - case SIDEVICE_GC_STEERING: + case SIDEVICE_WIIU_ADAPTER: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[2]); break; - case SIDEVICE_DANCEMAT: + case SIDEVICE_GC_STEERING: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[3]); break; - case SIDEVICE_GC_TARUKONGA: + case SIDEVICE_DANCEMAT: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[4]); break; - case SIDEVICE_GC_GBA: + case SIDEVICE_GC_TARUKONGA: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[5]); + break; + case SIDEVICE_GC_GBA: + pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[6]); gamecube_configure_bt[i]->Disable(); break; case SIDEVICE_GC_KEYBOARD: - pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[6]); + pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[7]); break; case SIDEVICE_AM_BASEBOARD: - pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[7]); + pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[8]); break; default: pad_type_choices[i]->SetStringSelection(m_gc_pad_type_strs[0]); @@ -145,67 +147,9 @@ 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(wxVERTICAL, 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); - - wxCheckBox* const gamecube_rumble = new wxCheckBox(this, wxID_ANY, _("Rumble")); - gamecube_rumble->SetValue(SConfig::GetInstance().m_AdapterRumble); - gamecube_rumble->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnAdapterRumble, this); - - m_adapter_status = new wxStaticText(this, wxID_ANY, _("Adapter Not Detected")); - - gamecube_adapter_group->Add(m_adapter_status, 0, wxEXPAND); - gamecube_adapter_sizer->Add(gamecube_adapter, 0, wxEXPAND); - gamecube_adapter_sizer->Add(gamecube_rumble, 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) - gamecube_adapter->SetValue(SConfig::GetInstance().m_GameCubeAdapter); - if (!SI_GCAdapter::IsDetected()) - { - if (!SI_GCAdapter::IsDriverDetected()) - { - m_adapter_status->SetLabelText(_("Driver Not Detected")); - gamecube_adapter->Disable(); - gamecube_adapter->SetValue(false); - gamecube_rumble->Disable(); - } - } - else - { - m_adapter_status->SetLabelText(_("Adapter Detected")); - } - if (Core::GetState() != Core::CORE_UNINITIALIZED) - { - gamecube_adapter->Disable(); - } - SI_GCAdapter::SetAdapterCallback(std::bind(&ControllerConfigDiag::ScheduleAdapterUpdate, this)); -#endif - return gamecube_static_sizer; } -void ControllerConfigDiag::ScheduleAdapterUpdate() -{ - wxQueueEvent(this, new wxCommandEvent(wxEVT_ADAPTER_UPDATE)); -} - -void ControllerConfigDiag::UpdateAdapter(wxCommandEvent& ev) -{ -#if defined(__LIBUSB__) || defined (_WIN32) - bool unpause = Core::PauseAndLock(true); - if (SI_GCAdapter::IsDetected()) - m_adapter_status->SetLabelText(_("Adapter Detected")); - else - m_adapter_status->SetLabelText(_("Adapter Not Detected")); - Core::PauseAndLock(false, unpause); -#endif -} - wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer() { wxStaticText* wiimote_label[4]; @@ -502,30 +446,35 @@ void ControllerConfigDiag::OnGameCubePortChanged(wxCommandEvent& event) } else if (device_name == m_gc_pad_type_strs[2]) { - tempType = SIDEVICE_GC_STEERING; + tempType = SIDEVICE_WIIU_ADAPTER; gamecube_configure_bt[device_num]->Enable(); } else if (device_name == m_gc_pad_type_strs[3]) { - tempType = SIDEVICE_DANCEMAT; + tempType = SIDEVICE_GC_STEERING; gamecube_configure_bt[device_num]->Enable(); } else if (device_name == m_gc_pad_type_strs[4]) { - tempType = SIDEVICE_GC_TARUKONGA; + tempType = SIDEVICE_DANCEMAT; gamecube_configure_bt[device_num]->Enable(); } else if (device_name == m_gc_pad_type_strs[5]) + { + tempType = SIDEVICE_GC_TARUKONGA; + gamecube_configure_bt[device_num]->Enable(); + } + else if (device_name == m_gc_pad_type_strs[6]) { tempType = SIDEVICE_GC_GBA; gamecube_configure_bt[device_num]->Disable(); } - else if (device_name == m_gc_pad_type_strs[6]) + else if (device_name == m_gc_pad_type_strs[7]) { tempType = SIDEVICE_GC_KEYBOARD; gamecube_configure_bt[device_num]->Enable(); } - else if (device_name == m_gc_pad_type_strs[7]) + else if (device_name == m_gc_pad_type_strs[8]) { tempType = SIDEVICE_AM_BASEBOARD; gamecube_configure_bt[device_num]->Enable(); @@ -538,6 +487,13 @@ void ControllerConfigDiag::OnGameCubePortChanged(wxCommandEvent& event) SConfig::GetInstance().m_SIDevice[device_num] = tempType; +#if defined(__LIBUSB__) || defined (_WIN32) + if (GCAdapter::UseAdapter()) + GCAdapter::StartScanThread(); + else + GCAdapter::StopScanThread(); +#endif + if (Core::IsRunning()) SerialInterface::ChangeDevice(tempType, device_num); } @@ -555,6 +511,11 @@ void ControllerConfigDiag::OnGameCubeConfigButton(wxCommandEvent& event) InputConfigDialog m_ConfigFrame(this, *key_plugin, _("GameCube Controller Configuration"), port_num); m_ConfigFrame.ShowModal(); } + else if (SConfig::GetInstance().m_SIDevice[port_num] == SIDEVICE_WIIU_ADAPTER) + { + GCAdapterConfigDiag m_ConfigFramg(this, _("Wii U Gamecube Controller Adapter Configuration"), port_num); + m_ConfigFramg.ShowModal(); + } else { InputConfigDialog m_ConfigFrame(this, *pad_plugin, _("GameCube Controller Configuration"), port_num); @@ -563,10 +524,3 @@ void ControllerConfigDiag::OnGameCubeConfigButton(wxCommandEvent& event) HotkeyManagerEmu::Enable(true); } - -ControllerConfigDiag::~ControllerConfigDiag() -{ -#if defined(__LIBUSB__) || defined (_WIN32) - SI_GCAdapter::SetAdapterCallback(nullptr); -#endif -} diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.h b/Source/Core/DolphinWX/ControllerConfigDiag.h index 7bfc76bca7..8646396b2b 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.h +++ b/Source/Core/DolphinWX/ControllerConfigDiag.h @@ -21,7 +21,6 @@ class ControllerConfigDiag : public wxDialog { public: ControllerConfigDiag(wxWindow* const parent); - ~ControllerConfigDiag(); private: void RefreshRealWiimotes(wxCommandEvent& event); @@ -70,23 +69,6 @@ private: event.Skip(); } - void OnGameCubeAdapter(wxCommandEvent& event) - { - SConfig::GetInstance().m_GameCubeAdapter = event.IsChecked(); -#ifdef __LIBUSB__ - if (event.IsChecked()) - SI_GCAdapter::StartScanThread(); - else - SI_GCAdapter::StopScanThread(); -#endif - event.Skip(); - } - void OnAdapterRumble(wxCommandEvent& event) - { - SConfig::GetInstance().m_AdapterRumble = event.IsChecked(); - } - - wxStaticBoxSizer* CreateGamecubeSizer(); wxStaticBoxSizer* CreateWiimoteConfigSizer(); wxStaticBoxSizer* CreateBalanceBoardSizer(); @@ -96,17 +78,14 @@ private: void Cancel(wxCommandEvent& event); void OnGameCubePortChanged(wxCommandEvent& event); void OnGameCubeConfigButton(wxCommandEvent& event); - void ScheduleAdapterUpdate(); - void UpdateAdapter(wxCommandEvent& ev); std::map m_gc_port_choice_ids; std::map m_gc_port_config_ids; - std::array m_gc_pad_type_strs; + std::array m_gc_pad_type_strs; std::map m_wiimote_index_from_ctrl_id; unsigned int m_orig_wiimote_sources[MAX_BBMOTES]; - wxStaticText* m_adapter_status; wxButton* wiimote_configure_bt[MAX_WIIMOTES]; wxButton* gamecube_configure_bt[4]; std::map m_wiimote_index_from_conf_bt_id; diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index b4818cf162..13882b44a4 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -58,6 +58,7 @@ + @@ -113,6 +114,7 @@ + @@ -246,4 +248,4 @@ - \ No newline at end of file + diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters index 87fb5df32a..5534ec41f8 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters @@ -178,6 +178,9 @@ GUI\Config + + GUI\Config + GUI\Config @@ -339,6 +342,9 @@ GUI\Config + + GUI\Config + GUI\Config @@ -369,4 +375,4 @@ - \ No newline at end of file + diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index b6b12bcfdb..d357952f4f 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -8,15 +8,17 @@ #include "Common/Flag.h" #include "Common/Thread.h" +#include "Common/Logging/Log.h" #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreTiming.h" #include "Core/HW/SI.h" -#include "Core/HW/SI_GCAdapter.h" #include "Core/HW/SystemTimers.h" + +#include "InputCommon/GCAdapter.h" #include "InputCommon/GCPadStatus.h" -namespace SI_GCAdapter +namespace GCAdapter { enum ControllerTypes { @@ -158,13 +160,16 @@ void Init() } else { - if (SConfig::GetInstance().m_GameCubeAdapter) + if (UseAdapter()) StartScanThread(); } } void StartScanThread() { + if (s_adapter_detect_thread_running.IsSet()) + return; + s_adapter_detect_thread_running.Set(true); s_adapter_detect_thread = std::thread(ScanThreadFunc); } @@ -351,7 +356,11 @@ void Reset() void Input(int chan, GCPadStatus* pad) { - if (!SConfig::GetInstance().m_GameCubeAdapter) + bool use_adapter = SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[1] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[2] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[3] == SIDEVICE_WIIU_ADAPTER; + if (!use_adapter) return; if (s_handle == nullptr || !s_detected) @@ -371,15 +380,19 @@ void Input(int chan, GCPadStatus* pad) } else { + bool get_origin = false; 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)]); + get_origin = true; + } s_controller_type[chan] = type; + memset(pad, 0, sizeof(*pad)); if (s_controller_type[chan] != CONTROLLER_NONE) { - memset(pad, 0, sizeof(*pad)); u8 b1 = controller_payload_copy[1 + (9 * chan) + 1]; u8 b2 = controller_payload_copy[1 + (9 * chan) + 2]; @@ -398,6 +411,8 @@ void Input(int chan, GCPadStatus* pad) if (b2 & (1 << 2)) pad->button |= PAD_TRIGGER_R; if (b2 & (1 << 3)) pad->button |= PAD_TRIGGER_L; + if (get_origin) pad->button |= PAD_GET_ORIGIN; + 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]; @@ -405,12 +420,29 @@ void Input(int chan, GCPadStatus* pad) pad->triggerLeft = controller_payload_copy[1 + (9 * chan) + 7]; pad->triggerRight = controller_payload_copy[1 + (9 * chan) + 8]; } + else + { + pad->button = PAD_ERR_STATUS; + } } } +bool DeviceConnected(int chan) +{ + return s_controller_type[chan] != CONTROLLER_NONE; +} + +bool UseAdapter() +{ + return SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[1] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[2] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[3] == SIDEVICE_WIIU_ADAPTER; +} + void ResetRumble() { - if (!SConfig::GetInstance().m_GameCubeAdapter) + if (!UseAdapter()) return; if (s_handle == nullptr || !s_detected) return; @@ -427,7 +459,7 @@ void ResetRumble() void Output(int chan, u8 rumble_command) { - if (s_handle == nullptr || !SConfig::GetInstance().m_GameCubeAdapter || !SConfig::GetInstance().m_AdapterRumble) + if (s_handle == nullptr || !UseAdapter() || !SConfig::GetInstance().m_AdapterRumble) return; // Skip over rumble commands if it has not changed or the controller is wireless @@ -458,4 +490,4 @@ bool IsDriverDetected() return !s_libusb_driver_not_supported; } -} // end of namespace SI_GCAdapter +} // end of namespace GCAdapter diff --git a/Source/Core/InputCommon/GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h index 13deb8b536..c8091291ff 100644 --- a/Source/Core/InputCommon/GCAdapter.h +++ b/Source/Core/InputCommon/GCAdapter.h @@ -8,7 +8,7 @@ struct GCPadStatus; -namespace SI_GCAdapter +namespace GCAdapter { void Init(); @@ -23,5 +23,7 @@ void Input(int chan, GCPadStatus* pad); void Output(int chan, u8 rumble_command); bool IsDetected(); bool IsDriverDetected(); +bool DeviceConnected(int chan); +bool UseAdapter(); -} // end of namespace SI_GCAdapter +} // end of namespace GCAdapter From 1dcc199a63bf8bd72a76b14352263ab6768e21ba Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 31 Dec 2015 11:23:04 -0600 Subject: [PATCH 4/7] Fix GCPad recalibration shortcut. Dolphin has supported the recalibration shortcut (X+Y+Start) for quite a long while. So if someont's axises are terrible, you could easily recalibrate. Games even get the initial calibration upon boot(Most of the time). While changing over the GCAdapter code, I was testing to make sure the reset and calibration shortcuts still worked, turns out they didn't work at all. Looking in to the problem, we capture the combination properly, and we wait three seconds until we actually fire that off recalibration. The problem is for Nintendo's SDK to properly handle recalibrating, we need to send back data saying that it needs to recalibrate. On hardware this is done as part of the 64bits of data the controller sends back to us. On holding of the controller, bit 61 of the return value is set, which the Nintendo SDK catches, and then signals immediately afterwards a CMD_ORIGIN command in order to recalibrate the controller. We were outright ignoring this bit, so the library wasn't ever recalibrating. I suspect in the past the class itself used to use the calibration data to to offset the data, but somewhere along the lines it got munged out of existence. The Gamecube adapter does this shortcut in a bit of a unique way, instead of sending the command and having the library support it and what have you. Once holding the shortcut for the amount of time, the adapter reports back that the controller has actually been disconnected. Then when you let go of the combination, the adapter states that a new device has been connected to that port, and the recalibration happens because a new device is "connected." This fixes controller calibration for both emulated GC controllers and also the Wii Gamecube Adapter. --- Source/Core/Core/ConfigManager.cpp | 2 ++ Source/Core/Core/ConfigManager.h | 1 + Source/Core/Core/HW/SI_DeviceGCAdapter.cpp | 9 +++++++++ Source/Core/Core/HW/SI_DeviceGCAdapter.h | 2 +- Source/Core/Core/HW/SI_DeviceGCController.cpp | 14 +++++++++++-- Source/Core/Core/HW/SI_DeviceGCController.h | 20 ++++++++----------- .../DolphinWX/Config/GCAdapterConfigDiag.cpp | 5 +++++ .../DolphinWX/Config/GCAdapterConfigDiag.h | 5 +++++ 8 files changed, 43 insertions(+), 15 deletions(-) diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 5e9901f5d8..47c789ec43 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -255,6 +255,7 @@ void SConfig::SaveCoreSettings(IniFile& ini) { core->Set(StringFromFormat("SIDevice%i", i), m_SIDevice[i]); core->Set(StringFromFormat("AdapterRumble%i", i), m_AdapterRumble[i]); + core->Set(StringFromFormat("SimulateKonga%i", i), m_AdapterKonga[i]); } core->Set("WiiSDCard", m_WiiSDCard); core->Set("WiiKeyboard", m_WiiKeyboard); @@ -509,6 +510,7 @@ void SConfig::LoadCoreSettings(IniFile& ini) { core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE); core->Get(StringFromFormat("AdapterRumble%i", i), &m_AdapterRumble[i], true); + core->Get(StringFromFormat("SimulateKonga%i", i), &m_AdapterKonga[i], false); } core->Get("WiiSDCard", &m_WiiSDCard, false); core->Get("WiiKeyboard", &m_WiiKeyboard, false); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index 880e93bc8a..7325c27da9 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -266,6 +266,7 @@ struct SConfig : NonCopyable // Input settings bool m_BackgroundInput; bool m_AdapterRumble[4]; + bool m_AdapterKonga[4]; SysConf* m_SYSCONF; diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp index 70215aa6a8..23ce9aac0c 100644 --- a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp @@ -4,9 +4,18 @@ #include "Common/MsgHandler.h" #include "Common/Logging/Log.h" +#include "Core/ConfigManager.h" #include "Core/Movie.h" #include "Core/HW/SI_DeviceGCAdapter.h" +CSIDevice_GCAdapter::CSIDevice_GCAdapter(SIDevices device, int _iDeviceNumber) + : CSIDevice_GCController(device, _iDeviceNumber) +{ + // get the correct pad number that should rumble locally when using netplay + const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); + m_simulate_konga = SConfig::GetInstance().m_AdapterKonga[numPAD]; +} + GCPadStatus CSIDevice_GCAdapter::GetPadStatus() { GCPadStatus PadStatus; diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.h b/Source/Core/Core/HW/SI_DeviceGCAdapter.h index 05c73253fc..e171e3a5a0 100644 --- a/Source/Core/Core/HW/SI_DeviceGCAdapter.h +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.h @@ -12,7 +12,7 @@ class CSIDevice_GCAdapter : public CSIDevice_GCController { public: - CSIDevice_GCAdapter(SIDevices device, int _iDeviceNumber) : CSIDevice_GCController(device, _iDeviceNumber) {} + CSIDevice_GCAdapter(SIDevices device, int _iDeviceNumber); GCPadStatus GetPadStatus() override; int RunBuffer(u8* _pBuffer, int _iLength) override; diff --git a/Source/Core/Core/HW/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI_DeviceGCController.cpp index 3b2a191b2e..cf6eb50ff5 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCController.cpp @@ -160,6 +160,8 @@ GCPadStatus CSIDevice_GCController::GetPadStatus() bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) { GCPadStatus PadStatus = GetPadStatus(); + if (HandleButtonCombos(PadStatus) == COMBO_ORIGIN) + PadStatus.button |= PAD_GET_ORIGIN; _Hi = MapPadStatus(PadStatus); @@ -208,7 +210,12 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) _Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits } - HandleButtonCombos(PadStatus); + // Unset all bits except those that represent + // A, B, X, Y, Start and the error bits, as they + // are not used. + if (m_simulate_konga) + _Hi &= ~0x20FFFFFF; + return true; } @@ -222,7 +229,7 @@ u32 CSIDevice_GCController::MapPadStatus(const GCPadStatus& pad_status) return _Hi; } -void CSIDevice_GCController::HandleButtonCombos(const GCPadStatus& pad_status) +CSIDevice_GCController::EButtonCombo CSIDevice_GCController::HandleButtonCombos(const GCPadStatus& pad_status) { // Keep track of the special button combos (embedded in controller hardware... :( ) EButtonCombo tempCombo; @@ -255,8 +262,11 @@ void CSIDevice_GCController::HandleButtonCombos(const GCPadStatus& pad_status) m_Origin.uTrigger_R = pad_status.triggerRight; } m_LastButtonCombo = COMBO_NONE; + return tempCombo; } } + + return COMBO_NONE; } // SendCommand diff --git a/Source/Core/Core/HW/SI_DeviceGCController.h b/Source/Core/Core/HW/SI_DeviceGCController.h index 855ae89127..ca772131dc 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.h +++ b/Source/Core/Core/HW/SI_DeviceGCController.h @@ -79,6 +79,9 @@ protected: // Type of button combo from the last/current poll EButtonCombo m_LastButtonCombo; + // Set this if we want to simulate the "TaruKonga" DK Bongo controller + bool m_simulate_konga = false; + public: // Constructor @@ -98,14 +101,15 @@ public: virtual GCPadStatus GetPadStatus(); virtual u32 MapPadStatus(const GCPadStatus& pad_status); - virtual void HandleButtonCombos(const GCPadStatus& pad_status); + virtual EButtonCombo HandleButtonCombos(const GCPadStatus& pad_status); // Send and Receive pad input from network static bool NetPlay_GetInput(u8 numPAD, GCPadStatus* status); static u8 NetPlay_InGamePadToLocalPad(u8 numPAD); -private: +protected: void Calibrate(); + void HandleMoviePadStatus(GCPadStatus* PadStatus); }; @@ -113,16 +117,8 @@ private: class CSIDevice_TaruKonga : public CSIDevice_GCController { public: - CSIDevice_TaruKonga(SIDevices device, int _iDeviceNumber) : CSIDevice_GCController(device, _iDeviceNumber) { } - - bool GetData(u32& _Hi, u32& _Low) override + CSIDevice_TaruKonga(SIDevices device, int _iDeviceNumber) : CSIDevice_GCController(device, _iDeviceNumber) { - CSIDevice_GCController::GetData(_Hi, _Low); - - // Unset all bits except those that represent - // A, B, X, Y, Start and the error bits, as they - // are not used. - _Hi &= ~0x20FFFFFF; - return true; + m_simulate_konga = true; } }; diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp index 21d64a686d..f72ad9d992 100644 --- a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp @@ -24,6 +24,10 @@ GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& gamecube_rumble->SetValue(SConfig::GetInstance().m_AdapterRumble[m_pad_id]); gamecube_rumble->Bind(wxEVT_CHECKBOX, &GCAdapterConfigDiag::OnAdapterRumble, this); + wxCheckBox* const gamecube_konga = new wxCheckBox(this, wxID_ANY, _("Simulate DK TaruKonga")); + gamecube_konga->SetValue(SConfig::GetInstance().m_AdapterKonga[m_pad_id]); + gamecube_konga->Bind(wxEVT_CHECKBOX, &GCAdapterConfigDiag::OnAdapterKonga, this); + m_adapter_status = new wxStaticText(this, wxID_ANY, _("Adapter Not Detected")); #if defined(__LIBUSB__) || defined (_WIN32) @@ -44,6 +48,7 @@ GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& szr->Add(m_adapter_status, 0, wxEXPAND); szr->Add(gamecube_rumble, 0, wxEXPAND); + szr->Add(gamecube_konga, 0, wxEXPAND); szr->Add(CreateButtonSizer(wxOK | wxNO_DEFAULT), 0, wxEXPAND|wxALL, 5); SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED); diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h index fa7bf471d8..4c86f55a2e 100644 --- a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.h @@ -32,4 +32,9 @@ private: { SConfig::GetInstance().m_AdapterRumble[m_pad_id] = event.IsChecked(); } + + void OnAdapterKonga(wxCommandEvent& event) + { + SConfig::GetInstance().m_AdapterKonga[m_pad_id] = event.IsChecked(); + } }; From af6a5ddafe69a7ba36080cc164318f56a2ebc7f6 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 6 Jan 2016 00:35:56 -0600 Subject: [PATCH 5/7] Fixup typo in GCAdapter --- Source/Core/InputCommon/GCAdapter.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index d357952f4f..c3aea3dc4f 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -356,11 +356,7 @@ void Reset() void Input(int chan, GCPadStatus* pad) { - bool use_adapter = SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_WIIU_ADAPTER || - SConfig::GetInstance().m_SIDevice[1] == SIDEVICE_WIIU_ADAPTER || - SConfig::GetInstance().m_SIDevice[2] == SIDEVICE_WIIU_ADAPTER || - SConfig::GetInstance().m_SIDevice[3] == SIDEVICE_WIIU_ADAPTER; - if (!use_adapter) + if (!UseAdapter()) return; if (s_handle == nullptr || !s_detected) @@ -459,7 +455,7 @@ void ResetRumble() void Output(int chan, u8 rumble_command) { - if (s_handle == nullptr || !UseAdapter() || !SConfig::GetInstance().m_AdapterRumble) + if (s_handle == nullptr || !UseAdapter() || !SConfig::GetInstance().m_AdapterRumble[chan]) return; // Skip over rumble commands if it has not changed or the controller is wireless From 6e503bebc43e17418d88261568a15cfc75757a17 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 6 Jan 2016 00:57:08 -0600 Subject: [PATCH 6/7] Add a stubbed GCAdapter namespace. This cleans up a bunch of #ifdef checks in places. --- Source/Core/Core/HW/SI_DeviceGCAdapter.cpp | 6 ----- .../DolphinWX/Config/GCAdapterConfigDiag.cpp | 6 ----- .../Core/DolphinWX/ControllerConfigDiag.cpp | 2 -- Source/Core/InputCommon/CMakeLists.txt | 2 ++ Source/Core/InputCommon/GCAdapter.cpp | 21 ++++++----------- Source/Core/InputCommon/GCAdapter.h | 7 +++++- Source/Core/InputCommon/GCAdapter_Null.cpp | 23 +++++++++++++++++++ Source/Core/UICommon/UICommon.cpp | 4 ---- 8 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 Source/Core/InputCommon/GCAdapter_Null.cpp diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp index 23ce9aac0c..0f2c55ca5d 100644 --- a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp @@ -21,9 +21,7 @@ GCPadStatus CSIDevice_GCAdapter::GetPadStatus() GCPadStatus PadStatus; memset(&PadStatus, 0, sizeof(PadStatus)); -#if defined(__LIBUSB__) || defined (_WIN32) GCAdapter::Input(ISIDevice::m_iDeviceNumber, &PadStatus); -#endif HandleMoviePadStatus(&PadStatus); @@ -38,11 +36,9 @@ int CSIDevice_GCAdapter::RunBuffer(u8* _pBuffer, int _iLength) // Read the command EBufferCommands command = static_cast(_pBuffer[3]); -#if defined(__LIBUSB__) || defined (_WIN32) // get the correct pad number that should rumble locally when using netplay const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); if (!GCAdapter::DeviceConnected(numPAD)) -#endif { reinterpret_cast(_pBuffer)[0] = SI_NONE; return 4; @@ -122,7 +118,6 @@ void CSIDevice_GCAdapter::SendCommand(u32 _Cmd, u8 _Poll) case CMD_WRITE: { -#if defined(__LIBUSB__) || defined (_WIN32) unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard unsigned int uStrength = command.Parameter2; @@ -136,7 +131,6 @@ void CSIDevice_GCAdapter::SendCommand(u32 _Cmd, u8 _Poll) else GCAdapter::Output(numPAD, 0); } -#endif if (!_Poll) { m_Mode = command.Parameter2; diff --git a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp index f72ad9d992..06ef12dd80 100644 --- a/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp +++ b/Source/Core/DolphinWX/Config/GCAdapterConfigDiag.cpp @@ -30,7 +30,6 @@ GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& m_adapter_status = new wxStaticText(this, wxID_ANY, _("Adapter Not Detected")); -#if defined(__LIBUSB__) || defined (_WIN32) if (!GCAdapter::IsDetected()) { if (!GCAdapter::IsDriverDetected()) @@ -44,7 +43,6 @@ GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& m_adapter_status->SetLabelText(_("Adapter Detected")); } GCAdapter::SetAdapterCallback(std::bind(&GCAdapterConfigDiag::ScheduleAdapterUpdate, this)); -#endif szr->Add(m_adapter_status, 0, wxEXPAND); szr->Add(gamecube_rumble, 0, wxEXPAND); @@ -65,19 +63,15 @@ void GCAdapterConfigDiag::ScheduleAdapterUpdate() void GCAdapterConfigDiag::UpdateAdapter(wxCommandEvent& ev) { -#if defined(__LIBUSB__) || defined (_WIN32) bool unpause = Core::PauseAndLock(true); if (GCAdapter::IsDetected()) m_adapter_status->SetLabelText(_("Adapter Detected")); else m_adapter_status->SetLabelText(_("Adapter Not Detected")); Core::PauseAndLock(false, unpause); -#endif } GCAdapterConfigDiag::~GCAdapterConfigDiag() { -#if defined(__LIBUSB__) || defined (_WIN32) GCAdapter::SetAdapterCallback(nullptr); -#endif } diff --git a/Source/Core/DolphinWX/ControllerConfigDiag.cpp b/Source/Core/DolphinWX/ControllerConfigDiag.cpp index 1e736ce56b..8bc510f7a5 100644 --- a/Source/Core/DolphinWX/ControllerConfigDiag.cpp +++ b/Source/Core/DolphinWX/ControllerConfigDiag.cpp @@ -487,12 +487,10 @@ void ControllerConfigDiag::OnGameCubePortChanged(wxCommandEvent& event) SConfig::GetInstance().m_SIDevice[device_num] = tempType; -#if defined(__LIBUSB__) || defined (_WIN32) if (GCAdapter::UseAdapter()) GCAdapter::StartScanThread(); else GCAdapter::StopScanThread(); -#endif if (Core::IsRunning()) SerialInterface::ChangeDevice(tempType, device_num); diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 254dffce10..57484db14b 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -37,6 +37,8 @@ endif() if(LIBUSB_FOUND) set(SRCS ${SRCS} GCAdapter.cpp) +else() + set(SRCS ${SRCS} GCAdapter_Null.cpp) endif(LIBUSB_FOUND) if(LIBEVDEV_FOUND AND LIBUDEV_FOUND) diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp index c3aea3dc4f..b5dc395b49 100644 --- a/Source/Core/InputCommon/GCAdapter.cpp +++ b/Source/Core/InputCommon/GCAdapter.cpp @@ -20,19 +20,12 @@ namespace GCAdapter { -enum ControllerTypes -{ - CONTROLLER_NONE = 0, - CONTROLLER_WIRED = 1, - CONTROLLER_WIRELESS = 2 -}; - static bool CheckDeviceAccess(libusb_device* device); static void AddGCAdapter(libusb_device* device); static bool s_detected = false; 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_type[MAX_SI_CHANNELS] = { ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE }; static u8 s_controller_rumble[4]; static std::mutex s_mutex; @@ -189,7 +182,7 @@ void Setup() for (int i = 0; i < MAX_SI_CHANNELS; i++) { - s_controller_type[i] = CONTROLLER_NONE; + s_controller_type[i] = ControllerTypes::CONTROLLER_NONE; s_controller_rumble[i] = 0; } @@ -339,7 +332,7 @@ void Reset() } for (int i = 0; i < MAX_SI_CHANNELS; i++) - s_controller_type[i] = CONTROLLER_NONE; + s_controller_type[i] = ControllerTypes::CONTROLLER_NONE; s_detected = false; @@ -378,7 +371,7 @@ void Input(int chan, GCPadStatus* pad) { bool get_origin = false; u8 type = controller_payload_copy[1 + (9 * chan)] >> 4; - if (type != CONTROLLER_NONE && s_controller_type[chan] == CONTROLLER_NONE) + if (type != ControllerTypes::CONTROLLER_NONE && s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE) { NOTICE_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload_copy[1 + (9 * chan)]); get_origin = true; @@ -387,7 +380,7 @@ void Input(int chan, GCPadStatus* pad) s_controller_type[chan] = type; memset(pad, 0, sizeof(*pad)); - if (s_controller_type[chan] != CONTROLLER_NONE) + if (s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE) { u8 b1 = controller_payload_copy[1 + (9 * chan) + 1]; u8 b2 = controller_payload_copy[1 + (9 * chan) + 2]; @@ -425,7 +418,7 @@ void Input(int chan, GCPadStatus* pad) bool DeviceConnected(int chan) { - return s_controller_type[chan] != CONTROLLER_NONE; + return s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE; } bool UseAdapter() @@ -459,7 +452,7 @@ void Output(int chan, u8 rumble_command) return; // Skip over rumble commands if it has not changed or the controller is wireless - if (rumble_command != s_controller_rumble[chan] && s_controller_type[chan] != CONTROLLER_WIRELESS) + if (rumble_command != s_controller_rumble[chan] && s_controller_type[chan] != ControllerTypes::CONTROLLER_WIRELESS) { s_controller_rumble[chan] = rumble_command; diff --git a/Source/Core/InputCommon/GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h index c8091291ff..5af8f7b915 100644 --- a/Source/Core/InputCommon/GCAdapter.h +++ b/Source/Core/InputCommon/GCAdapter.h @@ -10,7 +10,12 @@ struct GCPadStatus; namespace GCAdapter { - +enum ControllerTypes +{ + CONTROLLER_NONE = 0, + CONTROLLER_WIRED = 1, + CONTROLLER_WIRELESS = 2 +}; void Init(); void Reset(); void ResetRumble(); diff --git a/Source/Core/InputCommon/GCAdapter_Null.cpp b/Source/Core/InputCommon/GCAdapter_Null.cpp new file mode 100644 index 0000000000..0936eb33f1 --- /dev/null +++ b/Source/Core/InputCommon/GCAdapter_Null.cpp @@ -0,0 +1,23 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "InputCommon/GCAdapter.h" +namespace GCAdapter +{ +void Init() {} +void Reset() {} +void ResetRumble() {} +void Setup() {} +void Shutdown() {} +void SetAdapterCallback(std::function func) {} +void StartScanThread() {} +void StopScanThread() {} +void Input(int chan, GCPadStatus* pad) {} +void Output(int chan, u8 rumble_command) {} +bool IsDetected() { return false; } +bool IsDriverDetected() { return false; } +bool DeviceConnected(int chan) { return false; } +bool UseAdapter() { return false; } + +} // end of namespace GCAdapter diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 8a4e76c535..10e00584a2 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -28,9 +28,7 @@ void Init() SConfig::Init(); VideoBackend::PopulateList(); WiimoteReal::LoadSettings(); -#if defined(__LIBUSB__) || defined (_WIN32) GCAdapter::Init(); -#endif VideoBackend::ActivateBackend(SConfig::GetInstance().m_strVideoBackend); SetEnableAlert(SConfig::GetInstance().bUsePanicHandlers); @@ -38,9 +36,7 @@ void Init() void Shutdown() { -#if defined(__LIBUSB__) || defined (_WIN32) GCAdapter::Shutdown(); -#endif WiimoteReal::Shutdown(); VideoBackend::ClearList(); SConfig::Shutdown(); From e62503c873833b33c63585c6f0810b824e5c6a6b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 6 Jan 2016 01:00:02 -0600 Subject: [PATCH 7/7] [Android] Add support for the Wii U Gamecube adapter under Android. No way to properly enable it from an end user perspective yet. Doesn't require root. This same sort of system can be used for the Dolphinbar in the future for real wiimote support. --- .../dolphinemu/utils/Java_GCAdapter.java | 91 +++++ Source/Core/InputCommon/CMakeLists.txt | 6 +- Source/Core/InputCommon/GCAdapter_Android.cpp | 353 ++++++++++++++++++ 3 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java create mode 100644 Source/Core/InputCommon/GCAdapter_Android.cpp diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java new file mode 100644 index 0000000000..51d00ad348 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Java_GCAdapter.java @@ -0,0 +1,91 @@ +package org.dolphinemu.dolphinemu.utils; + +import android.app.Activity; +import android.hardware.usb.UsbConfiguration; +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbInterface; +import android.hardware.usb.UsbManager; + +import java.util.HashMap; +import java.util.Iterator; + +public class Java_GCAdapter { + public static UsbManager manager; + public static Activity our_activity; + static byte[] controller_payload = new byte[37]; + static byte HasRead; + + static UsbDeviceConnection usb_con; + static UsbInterface usb_intf; + static UsbEndpoint usb_in; + static UsbEndpoint usb_out; + + public static void Shutdown() + { + usb_con.close(); + } + public static int GetFD() { return usb_con.getFileDescriptor(); } + + public static boolean QueryAdapter() + { + HashMap devices = manager.getDeviceList(); + Iterator it = devices.entrySet().iterator(); + while (it.hasNext()) + { + HashMap.Entry pair = (HashMap.Entry) it.next(); + UsbDevice dev = (UsbDevice) pair.getValue(); + if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) + if (manager.hasPermission(dev)) + return true; + } + return false; + } + + public static void InitAdapter() + { + byte[] init = { 0x13 }; + usb_con.bulkTransfer(usb_in, init, init.length, 0); + } + + public static int Input() { + int read = usb_con.bulkTransfer(usb_in, controller_payload, controller_payload.length, 16); + return read; + } + + public static int Output(byte[] rumble) { + int size = usb_con.bulkTransfer(usb_out, rumble, 5, 16); + return size; + } + + public static void OpenAdapter() + { + HashMap devices = manager.getDeviceList(); + Iterator it = devices.entrySet().iterator(); + while (it.hasNext()) + { + HashMap.Entry pair = (HashMap.Entry)it.next(); + UsbDevice dev = (UsbDevice)pair.getValue(); + if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e) { + if (manager.hasPermission(dev)) + { + usb_con = manager.openDevice(dev); + UsbConfiguration conf = dev.getConfiguration(0); + usb_intf = conf.getInterface(0); + usb_con.claimInterface(usb_intf, true); + for (int i = 0; i < usb_intf.getEndpointCount(); ++i) + if (usb_intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) + usb_in = usb_intf.getEndpoint(i); + else + usb_out = usb_intf.getEndpoint(i); + + InitAdapter(); + return; + } + } + + } + } +} diff --git a/Source/Core/InputCommon/CMakeLists.txt b/Source/Core/InputCommon/CMakeLists.txt index 57484db14b..01eef4532c 100644 --- a/Source/Core/InputCommon/CMakeLists.txt +++ b/Source/Core/InputCommon/CMakeLists.txt @@ -31,12 +31,14 @@ elseif(X11_FOUND) endif() set(LIBS ${LIBS} ${X11_LIBRARIES} ${XINPUT2_LIBRARIES}) elseif(ANDROID) - set(SRCS ${SRCS} - ControllerInterface/Android/Android.cpp) + set(SRCS ${SRCS} + ControllerInterface/Android/Android.cpp) endif() if(LIBUSB_FOUND) set(SRCS ${SRCS} GCAdapter.cpp) +elseif(ANDROID) + set(SRCS ${SRCS} GCAdapter_Android.cpp) else() set(SRCS ${SRCS} GCAdapter_Null.cpp) endif(LIBUSB_FOUND) diff --git a/Source/Core/InputCommon/GCAdapter_Android.cpp b/Source/Core/InputCommon/GCAdapter_Android.cpp new file mode 100644 index 0000000000..6e638e2a72 --- /dev/null +++ b/Source/Core/InputCommon/GCAdapter_Android.cpp @@ -0,0 +1,353 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include + +#include "Common/Event.h" +#include "Common/Flag.h" +#include "Common/Thread.h" +#include "Common/Logging/Log.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/HW/SI.h" +#include "Core/HW/SystemTimers.h" + +#include "InputCommon/GCAdapter.h" +#include "InputCommon/GCPadStatus.h" + +// Global java_vm class +extern JavaVM* g_java_vm; + +namespace GCAdapter +{ +// Java classes +static jclass s_adapter_class; + +static bool s_detected = false; +static int s_fd = 0; +static u8 s_controller_type[MAX_SI_CHANNELS] = { ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE, ControllerTypes::CONTROLLER_NONE }; +static u8 s_controller_rumble[4]; + +// Input handling +static std::mutex s_read_mutex; +static u8 s_controller_payload[37]; +static int s_controller_payload_size = 0; + +// Output handling +static std::mutex s_write_mutex; +static u8 s_controller_write_payload[5]; + +// Adapter running thread +static std::thread s_read_adapter_thread; +static Common::Flag s_read_adapter_thread_running; + +static std::thread s_write_adapter_thread; +static Common::Flag s_write_adapter_thread_running; +static Common::Event s_write_happened; + +// Adapter scanning thread +static std::thread s_adapter_detect_thread; +static Common::Flag s_adapter_detect_thread_running; + +static u64 s_last_init = 0; + +static void ScanThreadFunc() +{ + Common::SetCurrentThreadName("GC Adapter Scanning Thread"); + NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread started"); + + JNIEnv* env; + g_java_vm->AttachCurrentThread(&env, NULL); + + jmethodID queryadapter_func = env->GetStaticMethodID(s_adapter_class, "QueryAdapter", "()Z"); + + while (s_adapter_detect_thread_running.IsSet()) + { + if (!s_detected && UseAdapter() && + env->CallStaticBooleanMethod(s_adapter_class, queryadapter_func)) + Setup(); + Common::SleepCurrentThread(1000); + } + g_java_vm->DetachCurrentThread(); + + NOTICE_LOG(SERIALINTERFACE, "GC Adapter scanning thread stopped"); +} + +static void Read() +{ + Common::SetCurrentThreadName("GC Adapter Read Thread"); + NOTICE_LOG(SERIALINTERFACE, "GC Adapter read thread started"); + + bool first_read = true; + JNIEnv* env; + g_java_vm->AttachCurrentThread(&env, NULL); + + jfieldID payload_field = env->GetStaticFieldID(s_adapter_class, "controller_payload", "[B"); + jobject payload_object = env->GetStaticObjectField(s_adapter_class, payload_field); + jbyteArray* java_controller_payload = reinterpret_cast(&payload_object); + + // Get function pointers + jmethodID getfd_func = env->GetStaticMethodID(s_adapter_class, "GetFD", "()I"); + jmethodID input_func = env->GetStaticMethodID(s_adapter_class, "Input", "()I"); + jmethodID openadapter_func = env->GetStaticMethodID(s_adapter_class, "OpenAdapter", "()V"); + + env->CallStaticVoidMethod(s_adapter_class, openadapter_func); + + // Reset rumble once on initial reading + ResetRumble(); + + while (s_read_adapter_thread_running.IsSet()) + { + s_controller_payload_size = env->CallStaticIntMethod(s_adapter_class, input_func); + + jbyte* java_data = env->GetByteArrayElements(*java_controller_payload, nullptr); + { + std::lock_guard lk(s_read_mutex); + memcpy(s_controller_payload, java_data, 0x37); + } + env->ReleaseByteArrayElements(*java_controller_payload, java_data, 0); + + if (first_read) + { + first_read = false; + s_fd = env->CallStaticIntMethod(s_adapter_class, getfd_func); + } + + Common::YieldCPU(); + } + + g_java_vm->DetachCurrentThread(); + + NOTICE_LOG(SERIALINTERFACE, "GC Adapter read thread stopped"); +} + +static void Write() +{ + Common::SetCurrentThreadName("GC Adapter Write Thread"); + NOTICE_LOG(SERIALINTERFACE, "GC Adapter write thread started"); + + JNIEnv* env; + g_java_vm->AttachCurrentThread(&env, NULL); + jmethodID output_func = env->GetStaticMethodID(s_adapter_class, "Output", "([B)I"); + + while (s_write_adapter_thread_running.IsSet()) + { + jbyteArray jrumble_array = env->NewByteArray(5); + jbyte* jrumble = env->GetByteArrayElements(jrumble_array, NULL); + + s_write_happened.Wait(); + { + std::lock_guard lk(s_write_mutex); + memcpy(jrumble, s_controller_write_payload, 5); + } + + env->ReleaseByteArrayElements(jrumble_array, jrumble, 0); + int size = env->CallStaticIntMethod(s_adapter_class, output_func, jrumble_array); + // Netplay sends invalid data which results in size = 0x00. Ignore it. + if (size != 0x05 && size != 0x00) + { + ERROR_LOG(SERIALINTERFACE, "error writing rumble (size: %d)", size); + Reset(); + } + + Common::YieldCPU(); + } + + g_java_vm->DetachCurrentThread(); + + NOTICE_LOG(SERIALINTERFACE, "GC Adapter write thread stopped"); +} + +void Init() +{ + if (s_fd) + return; + + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + if ((CoreTiming::GetTicks() - s_last_init) < SystemTimers::GetTicksPerSecond()) + return; + + s_last_init = CoreTiming::GetTicks(); + } + + JNIEnv* env; + g_java_vm->AttachCurrentThread(&env, NULL); + + jclass adapter_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Java_GCAdapter"); + s_adapter_class = reinterpret_cast(env->NewGlobalRef(adapter_class)); + + if (UseAdapter()) + StartScanThread(); +} + +void Setup() +{ + s_read_adapter_thread_running.Set(true); + s_read_adapter_thread = std::thread(Read); + + s_write_adapter_thread_running.Set(true); + s_write_adapter_thread = std::thread(Write); + + s_detected = true; +} + +void Reset() +{ + if (!s_detected) + return; + + if (s_read_adapter_thread_running.TestAndClear()) + s_read_adapter_thread.join(); + + if (s_write_adapter_thread_running.TestAndClear()) + { + s_write_happened.Set(); // Kick the waiting event + s_write_adapter_thread.join(); + } + + for (int i = 0; i < MAX_SI_CHANNELS; i++) + s_controller_type[i] = ControllerTypes::CONTROLLER_NONE; + + s_detected = false; + s_fd = 0; + NOTICE_LOG(SERIALINTERFACE, "GC Adapter detached"); +} + +void Shutdown() +{ + StopScanThread(); + Reset(); +} + +void StartScanThread() +{ + if (s_adapter_detect_thread_running.IsSet()) + return; + + s_adapter_detect_thread_running.Set(true); + s_adapter_detect_thread = std::thread(ScanThreadFunc); +} + +void StopScanThread() +{ + if (s_adapter_detect_thread_running.TestAndClear()) + s_adapter_detect_thread.join(); +} + +void Input(int chan, GCPadStatus* pad) +{ + if (!UseAdapter() || !s_detected || !s_fd) + return; + + u8 controller_payload_copy[37]; + + { + std::lock_guard lk(s_read_mutex); + std::copy(std::begin(s_controller_payload), std::end(s_controller_payload), std::begin(controller_payload_copy)); + } + + if (s_controller_payload_size != sizeof(controller_payload_copy)) + { + ERROR_LOG(SERIALINTERFACE, "error reading payload (size: %d, type: %02x)", s_controller_payload_size, controller_payload_copy[0]); + Reset(); + } + else + { + bool get_origin = false; + u8 type = controller_payload_copy[1 + (9 * chan)] >> 4; + if (type != ControllerTypes::CONTROLLER_NONE && s_controller_type[chan] == ControllerTypes::CONTROLLER_NONE) + { + ERROR_LOG(SERIALINTERFACE, "New device connected to Port %d of Type: %02x", chan + 1, controller_payload_copy[1 + (9 * chan)]); + get_origin = true; + } + + s_controller_type[chan] = type; + + memset(pad, 0, sizeof(*pad)); + if (s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE) + { + u8 b1 = controller_payload_copy[1 + (9 * chan) + 1]; + u8 b2 = controller_payload_copy[1 + (9 * chan) + 2]; + + if (b1 & (1 << 0)) pad->button |= PAD_BUTTON_A; + if (b1 & (1 << 1)) pad->button |= PAD_BUTTON_B; + if (b1 & (1 << 2)) pad->button |= PAD_BUTTON_X; + if (b1 & (1 << 3)) pad->button |= PAD_BUTTON_Y; + + if (b1 & (1 << 4)) pad->button |= PAD_BUTTON_LEFT; + if (b1 & (1 << 5)) pad->button |= PAD_BUTTON_RIGHT; + if (b1 & (1 << 6)) pad->button |= PAD_BUTTON_DOWN; + if (b1 & (1 << 7)) pad->button |= PAD_BUTTON_UP; + + if (b2 & (1 << 0)) pad->button |= PAD_BUTTON_START; + if (b2 & (1 << 1)) pad->button |= PAD_TRIGGER_Z; + if (b2 & (1 << 2)) pad->button |= PAD_TRIGGER_R; + if (b2 & (1 << 3)) pad->button |= PAD_TRIGGER_L; + + if (get_origin) pad->button |= PAD_GET_ORIGIN; + + 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]; + } + else + { + pad->button = PAD_ERR_STATUS; + } + } +} + +void Output(int chan, u8 rumble_command) +{ + if (!UseAdapter() || !s_detected || !s_fd) + return; + + // Skip over rumble commands if it has not changed or the controller is wireless + if (rumble_command != s_controller_rumble[chan] && s_controller_type[chan] != ControllerTypes::CONTROLLER_WIRELESS) + { + s_controller_rumble[chan] = rumble_command; + unsigned char rumble[5] = { 0x11, s_controller_rumble[0], s_controller_rumble[1], s_controller_rumble[2], s_controller_rumble[3] }; + { + std::lock_guard lk(s_write_mutex); + memcpy(s_controller_write_payload, rumble, 5); + } + s_write_happened.Set(); + } +} + +bool IsDetected() { return s_detected; } +bool IsDriverDetected() { return true; } +bool DeviceConnected(int chan) +{ + return s_controller_type[chan] != ControllerTypes::CONTROLLER_NONE; +} + +bool UseAdapter() +{ + return SConfig::GetInstance().m_SIDevice[0] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[1] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[2] == SIDEVICE_WIIU_ADAPTER || + SConfig::GetInstance().m_SIDevice[3] == SIDEVICE_WIIU_ADAPTER; +} + +void ResetRumble() +{ + unsigned char rumble[5] = {0x11, 0, 0, 0, 0}; + { + std::lock_guard lk(s_read_mutex); + memcpy(s_controller_write_payload, rumble, 5); + } + s_write_happened.Set(); +} + +void SetAdapterCallback(std::function func) { } + +} // end of namespace GCAdapter