From 3c5094eec05835df467dd08195271b76c71e89dd Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Tue, 30 Nov 2021 05:49:07 +0100 Subject: [PATCH] early-access version 2258 --- README.md | 2 +- src/core/hid/emulated_console.h | 28 +-- src/core/hid/emulated_controller.h | 58 +++--- src/core/hid/emulated_devices.h | 40 ++-- src/core/hid/hid_core.cpp | 26 +++ src/core/hid/hid_core.h | 6 + src/core/hid/hid_types.h | 2 + src/core/hid/input_converter.h | 23 +-- src/core/hid/input_interpreter.cpp | 16 +- src/core/hid/input_interpreter.h | 2 +- src/core/hle/service/hid/controllers/npad.cpp | 8 +- src/core/hle/service/hid/controllers/npad.h | 4 +- src/core/memory/cheat_engine.cpp | 3 +- src/input_common/drivers/sdl_driver.cpp | 3 +- src/yuzu/CMakeLists.txt | 4 +- src/yuzu/applets/qt_controller.cpp | 23 +-- src/yuzu/applets/qt_controller.h | 8 +- src/yuzu/applets/qt_profile_select.cpp | 1 + src/yuzu/applets/qt_profile_select.h | 6 +- .../configuration/configure_input_player.cpp | 32 ++-- src/yuzu/game_list.cpp | 1 + src/yuzu/game_list.h | 2 +- src/yuzu/util/controller_navigation.cpp | 177 ++++++++++++++++++ src/yuzu/util/controller_navigation.h | 48 +++++ 24 files changed, 387 insertions(+), 136 deletions(-) create mode 100755 src/yuzu/util/controller_navigation.cpp create mode 100755 src/yuzu/util/controller_navigation.h diff --git a/README.md b/README.md index 0231c8a24..c3c985c52 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2256. +This is the source code for early-access 2258. ## Legal Notice diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h index 25c183eee..bb3d7ab90 100755 --- a/src/core/hid/emulated_console.h +++ b/src/core/hid/emulated_console.h @@ -78,9 +78,9 @@ struct ConsoleUpdateCallback { class EmulatedConsole { public: /** - * Contains all input data related to the console like motion and touch input + * Contains all input data within the emulated switch console tablet such as touch and motion */ - EmulatedConsole(); + explicit EmulatedConsole(); ~EmulatedConsole(); YUZU_NON_COPYABLE(EmulatedConsole); @@ -89,14 +89,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated console into configuring mode + * This prevents the modification of the HID state of the emulated console by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated console into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated console is on configuring mode + /// Returns true if the emulated console is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -116,7 +118,7 @@ public: /** * Updates the current mapped motion device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetMotionParam(Common::ParamPackage param); @@ -134,14 +136,14 @@ public: /** * Adds a callback to the list of events - * @param ConsoleUpdateCallback that will be triggered + * @param update_callback A ConsoleUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(ConsoleUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -151,20 +153,20 @@ private: /** * Updates the motion status of the console - * @param A CallbackStatus containing gyro and accelerometer data + * @param callback A CallbackStatus containing gyro and accelerometer data */ void SetMotion(Common::Input::CallbackStatus callback); /** * Updates the touch status of the console - * @param callback: A CallbackStatus containing the touch position - * @param index: Finger ID to be updated + * @param callback A CallbackStatus containing the touch position + * @param index Finger ID to be updated */ void SetTouch(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the console status - * @param Input type of the event to trigger + * @param type Input type of the event to trigger */ void TriggerOnChange(ConsoleTriggerType type); diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 2c5d51bc8..5887e3e38 100755 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -132,8 +132,8 @@ struct ControllerUpdateCallback { class EmulatedController { public: /** - * Contains all input data related to this controller. Like buttons, joysticks, motion. - * @param Npad id type for this specific controller + * Contains all input data (buttons, joysticks, vibration, and motion) within this controller. + * @param npad_id_type npad id type for this specific controller */ explicit EmulatedController(NpadIdType npad_id_type_); ~EmulatedController(); @@ -155,7 +155,7 @@ public: /** * Gets the NpadStyleIndex for this controller - * @param If true tmp_npad_type will be returned + * @param get_temporary_value If true tmp_npad_type will be returned * @return NpadStyleIndex set on the controller */ NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const; @@ -168,7 +168,7 @@ public: /** * Is the emulated connected - * @param If true tmp_is_connected will be returned + * @param get_temporary_value If true tmp_is_connected will be returned * @return true if the controller has the connected status */ bool IsConnected(bool get_temporary_value = false) const; @@ -179,14 +179,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated controller into configuring mode + * This prevents the modification of the HID state of the emulated controller by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated controller into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated device is on configuring mode + /// Returns true if the emulated controller is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -215,19 +217,19 @@ public: /** * Updates the current mapped button device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetButtonParam(std::size_t index, Common::ParamPackage param); /** * Updates the current mapped stick device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetStickParam(std::size_t index, Common::ParamPackage param); /** * Updates the current mapped motion device - * @param ParamPackage with controller data to be mapped + * @param param ParamPackage with controller data to be mapped */ void SetMotionParam(std::size_t index, Common::ParamPackage param); @@ -270,13 +272,13 @@ public: /// Returns the latest battery status from the controller BatteryLevelState GetBattery() const; - /* + /** * Sends a specific vibration to the output device * @return returns true if vibration had no errors */ bool SetVibration(std::size_t device_index, VibrationValue vibration); - /* + /** * Sends a small vibration to the output device * @return returns true if SetVibration was successfull */ @@ -290,14 +292,14 @@ public: /** * Adds a callback to the list of events - * @param ConsoleUpdateCallback that will be triggered + * @param update_callback A ConsoleUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(ControllerUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -310,43 +312,43 @@ private: /** * Updates the button status of the controller - * @param callback: A CallbackStatus containing the button status - * @param index: Button ID of the to be updated + * @param callback A CallbackStatus containing the button status + * @param index Button ID of the to be updated */ void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the analog stick status of the controller - * @param callback: A CallbackStatus containing the analog stick status - * @param index: stick ID of the to be updated + * @param callback A CallbackStatus containing the analog stick status + * @param index stick ID of the to be updated */ void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the trigger status of the controller - * @param callback: A CallbackStatus containing the trigger status - * @param index: trigger ID of the to be updated + * @param callback A CallbackStatus containing the trigger status + * @param index trigger ID of the to be updated */ void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid); /** * Updates the motion status of the controller - * @param callback: A CallbackStatus containing gyro and accelerometer data - * @param index: motion ID of the to be updated + * @param callback A CallbackStatus containing gyro and accelerometer data + * @param index motion ID of the to be updated */ void SetMotion(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the battery status of the controller - * @param callback: A CallbackStatus containing the battery status - * @param index: Button ID of the to be updated + * @param callback A CallbackStatus containing the battery status + * @param index Button ID of the to be updated */ void SetBattery(Common::Input::CallbackStatus callback, std::size_t index); /** * Triggers a callback that something has changed on the controller status - * @param type: Input type of the event to trigger - * @param is_service_update: indicates if this event should be sended to only services + * @param type Input type of the event to trigger + * @param is_service_update indicates if this event should only be sent to HID services */ void TriggerOnChange(ControllerTriggerType type, bool is_service_update); @@ -357,7 +359,7 @@ private: f32 motion_sensitivity{0.01f}; bool force_update_motion{false}; - // Temporary values to avoid doing changes while the controller is on configuration mode + // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; bool tmp_is_connected{false}; diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 05a945d08..c72327681 100755 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h @@ -75,9 +75,9 @@ class EmulatedDevices { public: /** * Contains all input data related to external devices that aren't necesarily a controller - * like keyboard and mouse + * This includes devices such as the keyboard or mouse */ - EmulatedDevices(); + explicit EmulatedDevices(); ~EmulatedDevices(); YUZU_NON_COPYABLE(EmulatedDevices); @@ -86,14 +86,16 @@ public: /// Removes all callbacks created from input devices void UnloadInput(); - /// Sets the emulated console into configuring mode. Locking all HID service events from being - /// moddified + /** + * Sets the emulated devices into configuring mode + * This prevents the modification of the HID state of the emulated devices by input commands + */ void EnableConfiguration(); - /// Returns the emulated console to the normal behaivour + /// Returns the emulated devices into normal mode, allowing the modification of the HID state void DisableConfiguration(); - /// Returns true if the emulated device is on configuring mode + /// Returns true if the emulated device is in configuring mode bool IsConfiguring() const; /// Reload all input devices @@ -134,14 +136,14 @@ public: /** * Adds a callback to the list of events - * @param InterfaceUpdateCallback that will be triggered + * @param update_callback InterfaceUpdateCallback that will be triggered * @return an unique key corresponding to the callback index in the list */ int SetCallback(InterfaceUpdateCallback update_callback); /** * Removes a callback from the list stopping any future events to this object - * @param Key corresponding to the callback index in the list + * @param key Key corresponding to the callback index in the list */ void DeleteCallback(int key); @@ -151,42 +153,42 @@ private: /** * Updates the touch status of the keyboard device - * @param callback: A CallbackStatus containing the key status - * @param index: key ID to be updated + * @param callback A CallbackStatus containing the key status + * @param index key ID to be updated */ void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the keyboard status of the keyboard device - * @param callback: A CallbackStatus containing the modifier key status - * @param index: modifier key ID to be updated + * @param callback A CallbackStatus containing the modifier key status + * @param index modifier key ID to be updated */ void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse button status of the mouse device - * @param callback: A CallbackStatus containing the button status - * @param index: Button ID to be updated + * @param callback A CallbackStatus containing the button status + * @param index Button ID to be updated */ void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse wheel status of the mouse device - * @param callback: A CallbackStatus containing the wheel status - * @param index: wheel ID to be updated + * @param callback A CallbackStatus containing the wheel status + * @param index wheel ID to be updated */ void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index); /** * Updates the mouse position status of the mouse device - * @param callback: A CallbackStatus containing the position status - * @param index: stick ID to be updated + * @param callback A CallbackStatus containing the position status + * @param index stick ID to be updated */ void SetMouseStick(Common::Input::CallbackStatus callback); /** * Triggers a callback that something has changed on the device status - * @param Input type of the event to trigger + * @param type Input type of the event to trigger */ void TriggerOnChange(DeviceTriggerType type); diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp index 741a69c3c..946adde00 100755 --- a/src/core/hid/hid_core.cpp +++ b/src/core/hid/hid_core.cpp @@ -135,6 +135,32 @@ NpadIdType HIDCore::GetFirstNpadId() const { return NpadIdType::Player1; } +void HIDCore::EnableAllControllerConfiguration() { + player_1->EnableConfiguration(); + player_2->EnableConfiguration(); + player_3->EnableConfiguration(); + player_4->EnableConfiguration(); + player_5->EnableConfiguration(); + player_6->EnableConfiguration(); + player_7->EnableConfiguration(); + player_8->EnableConfiguration(); + other->EnableConfiguration(); + handheld->EnableConfiguration(); +} + +void HIDCore::DisableAllControllerConfiguration() { + player_1->DisableConfiguration(); + player_2->DisableConfiguration(); + player_3->DisableConfiguration(); + player_4->DisableConfiguration(); + player_5->DisableConfiguration(); + player_6->DisableConfiguration(); + player_7->DisableConfiguration(); + player_8->DisableConfiguration(); + other->DisableConfiguration(); + handheld->DisableConfiguration(); +} + void HIDCore::ReloadInputDevices() { player_1->ReloadFromSettings(); player_2->ReloadFromSettings(); diff --git a/src/core/hid/hid_core.h b/src/core/hid/hid_core.h index 609f40f3b..140a0e962 100755 --- a/src/core/hid/hid_core.h +++ b/src/core/hid/hid_core.h @@ -45,6 +45,12 @@ public: /// Returns the first connected npad id NpadIdType GetFirstNpadId() const; + /// Sets all emulated controllers into configuring mode. + void EnableAllControllerConfiguration(); + + /// Sets all emulated controllers into normal mode. + void DisableAllControllerConfiguration(); + /// Reloads all input devices from settings void ReloadInputDevices(); diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index acf54e233..780659b86 100755 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -63,6 +63,8 @@ enum class NpadButton : u64 { LagonCUp = 1ULL << 32, LagonCRight = 1ULL << 33, LagonCDown = 1ULL << 34, + + All = 0xFFFFFFFFFFFFFFFFULL, }; DECLARE_ENUM_FLAG_OPERATORS(NpadButton); diff --git a/src/core/hid/input_converter.h b/src/core/hid/input_converter.h index 1492489d7..d24582226 100755 --- a/src/core/hid/input_converter.h +++ b/src/core/hid/input_converter.h @@ -21,7 +21,7 @@ namespace Core::HID { /** * Converts raw input data into a valid battery status. * - * @param Supported callbacks: Analog, Battery, Trigger. + * @param callback Supported callbacks: Analog, Battery, Trigger. * @return A valid BatteryStatus object. */ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback); @@ -29,7 +29,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta /** * Converts raw input data into a valid button status. Applies invert properties to the output. * - * @param Supported callbacks: Analog, Button, Trigger. + * @param callback Supported callbacks: Analog, Button, Trigger. * @return A valid TouchStatus object. */ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback); @@ -37,7 +37,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu /** * Converts raw input data into a valid motion status. * - * @param Supported callbacks: Motion. + * @param callback Supported callbacks: Motion. * @return A valid TouchStatus object. */ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback); @@ -46,7 +46,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu * Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert * properties to the output. * - * @param Supported callbacks: Stick. + * @param callback Supported callbacks: Stick. * @return A valid StickStatus object. */ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback); @@ -54,7 +54,7 @@ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& /** * Converts raw input data into a valid touch status. * - * @param Supported callbacks: Touch. + * @param callback Supported callbacks: Touch. * @return A valid TouchStatus object. */ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback); @@ -63,7 +63,7 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& * Converts raw input data into a valid trigger status. Applies offset, deadzone, range and * invert properties to the output. Button status uses the threshold property if necessary. * - * @param Supported callbacks: Analog, Button, Trigger. + * @param callback Supported callbacks: Analog, Button, Trigger. * @return A valid TriggerStatus object. */ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback); @@ -72,22 +72,23 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta * Converts raw input data into a valid analog status. Applies offset, deadzone, range and * invert properties to the output. * - * @param Supported callbacks: Analog. + * @param callback Supported callbacks: Analog. * @return A valid AnalogStatus object. */ Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback); /** * Converts raw analog data into a valid analog value - * @param An analog object containing raw data and properties, bool that determines if the value - * needs to be clamped between -1.0f and 1.0f. + * @param analog An analog object containing raw data and properties + * @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f. */ void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value); /** * Converts raw stick data into a valid stick value - * @param Two analog objects containing raw data and properties, bool that determines if the value - * needs to be clamped into the unit circle. + * @param analog_x raw analog data and properties for the x-axis + * @param analog_y raw analog data and properties for the y-axis + * @param clamp_value bool that determines if the value needs to be clamped into the unit circle. */ void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y, bool clamp_value); diff --git a/src/core/hid/input_interpreter.cpp b/src/core/hid/input_interpreter.cpp index 870422d82..2dbda8814 100755 --- a/src/core/hid/input_interpreter.cpp +++ b/src/core/hid/input_interpreter.cpp @@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system) InputInterpreter::~InputInterpreter() = default; void InputInterpreter::PollInput() { - const u64 button_state = npad.GetAndResetPressState(); + const auto button_state = npad.GetAndResetPressState(); previous_index = current_index; current_index = (current_index + 1) % button_states.size(); @@ -32,30 +32,30 @@ void InputInterpreter::ResetButtonStates() { previous_index = 0; current_index = 0; - button_states[0] = 0xFFFFFFFFFFFFFFFF; + button_states[0] = Core::HID::NpadButton::All; for (std::size_t i = 1; i < button_states.size(); ++i) { - button_states[i] = 0; + button_states[i] = Core::HID::NpadButton::None; } } bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const { - return (button_states[current_index] & static_cast(button)) != 0; + return True(button_states[current_index] & button); } bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const { - const bool current_press = (button_states[current_index] & static_cast(button)) != 0; - const bool previous_press = (button_states[previous_index] & static_cast(button)) != 0; + const bool current_press = True(button_states[current_index] & button); + const bool previous_press = True(button_states[previous_index] & button); return current_press && !previous_press; } bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const { - u64 held_buttons{button_states[0]}; + Core::HID::NpadButton held_buttons{button_states[0]}; for (std::size_t i = 1; i < button_states.size(); ++i) { held_buttons &= button_states[i]; } - return (held_buttons & static_cast(button)) != 0; + return True(held_buttons & button); } diff --git a/src/core/hid/input_interpreter.h b/src/core/hid/input_interpreter.h index 1c2e02142..70c34d474 100755 --- a/src/core/hid/input_interpreter.h +++ b/src/core/hid/input_interpreter.h @@ -105,7 +105,7 @@ private: Service::HID::Controller_NPad& npad; /// Stores 9 consecutive button states polled from HID. - std::array button_states{}; + std::array button_states{}; std::size_t previous_index{}; std::size_t current_index{}; diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 04b3a68c3..6916930f7 100755 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -510,7 +510,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* libnx_state.r_stick = pad_state.r_stick; npad.system_ext_lifo.WriteNextEntry(pad_state); - press_state |= static_cast(pad_state.npad_buttons.raw); + press_state |= static_cast(pad_state.npad_buttons.raw); std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), &controller.shared_memory_entry, sizeof(NpadInternalState)); @@ -635,7 +635,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing // This buffer only is updated on handheld on HW npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); } else { - // Hanheld doesn't update this buffer on HW + // Handheld doesn't update this buffer on HW npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); } @@ -1149,8 +1149,8 @@ void Controller_NPad::ClearAllControllers() { } } -u32 Controller_NPad::GetAndResetPressState() { - return press_state.exchange(0); +Core::HID::NpadButton Controller_NPad::GetAndResetPressState() { + return static_cast(press_state.exchange(0)); } bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const { diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9fa113bb6..de5fa5a64 100755 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -179,7 +179,7 @@ public: // Logical OR for all buttons presses on all controllers // Specifically for cheat engine and other features. - u32 GetAndResetPressState(); + Core::HID::NpadButton GetAndResetPressState(); static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle); @@ -503,7 +503,7 @@ private: NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id); const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const; - std::atomic press_state{}; + std::atomic press_state{}; std::array controller_data{}; KernelHelpers::ServiceContext& service_context; diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 20f0e90f5..12446c9ac 100755 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp @@ -19,7 +19,6 @@ namespace Core::Memory { namespace { constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; -constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) { auto end_index = start_index; @@ -61,7 +60,7 @@ u64 StandardVmCallbacks::HidKeysDown() { applet_resource ->GetController(Service::HID::HidController::NPad) .GetAndResetPressState(); - return press_state & KEYPAD_BITMASK; + return static_cast(press_state & HID::NpadButton::All); } void StandardVmCallbacks::DebugLog(u8 id, u64 value) { diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 90128b6cf..1052ed394 100755 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -388,8 +388,6 @@ void SDLDriver::CloseJoysticks() { } SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engine_) { - Common::SetCurrentThreadName("yuzu:input:SDL"); - if (!Settings::values.enable_raw_input) { // Disable raw input. When enabled this setting causes SDL to die when a web applet opens SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, "0"); @@ -422,6 +420,7 @@ SDLDriver::SDLDriver(const std::string& input_engine_) : InputEngine(input_engin initialized = true; if (start_thread) { poll_thread = std::thread([this] { + Common::SetCurrentThreadName("yuzu:input:SDL"); using namespace std::chrono_literals; while (initialized) { SDL_PumpEvents(); diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 2572d3825..732e8c276 100755 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -126,8 +126,6 @@ add_executable(yuzu configuration/configure_web.ui configuration/input_profiles.cpp configuration/input_profiles.h - controller_navigation.cpp - controller_navigation.h debugger/console.cpp debugger/console.h debugger/controller.cpp @@ -154,6 +152,8 @@ add_executable(yuzu main.ui uisettings.cpp uisettings.h + util/controller_navigation.cpp + util/controller_navigation.h util/limitable_input_dialog.cpp util/limitable_input_dialog.h util/overlay_dialog.cpp diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index cf1f1cda6..c5685db2e 100755 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -139,7 +139,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( DisableUnsupportedPlayers(); for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { - system.HIDCore().GetEmulatedControllerByIndex(player_index)->EnableConfiguration(); SetEmulatedControllers(player_index); } @@ -201,23 +200,10 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QtControllerSelectorDialog::ApplyConfiguration); - controller_navigation = new ControllerNavigation(system.HIDCore(), this); - connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, - [this](Qt::Key key) { - if (!this->isActiveWindow()) { - return; - } - QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); - QCoreApplication::postEvent(this, event); - }); - // Enhancement: Check if the parameters have already been met before disconnecting controllers. // If all the parameters are met AND only allows a single player, // stop the constructor here as we do not need to continue. if (CheckIfParametersMet() && parameters.enable_single_mode) { - for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { - system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration(); - } return; } @@ -232,8 +218,8 @@ QtControllerSelectorDialog::QtControllerSelectorDialog( } QtControllerSelectorDialog::~QtControllerSelectorDialog() { - controller_navigation->UnloadController(); -}; + system.HIDCore().DisableAllControllerConfiguration(); +} int QtControllerSelectorDialog::exec() { if (parameters_met && parameters.enable_single_mode) { @@ -249,12 +235,11 @@ void QtControllerSelectorDialog::ApplyConfiguration() { Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); - for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { - system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration(); - } } void QtControllerSelectorDialog::LoadConfiguration() { + system.HIDCore().EnableAllControllerConfiguration(); + const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h index 5e99499e5..7ab9ced3d 100755 --- a/src/yuzu/applets/qt_controller.h +++ b/src/yuzu/applets/qt_controller.h @@ -7,9 +7,7 @@ #include #include #include -#include "core/core.h" #include "core/frontend/applets/controller.h" -#include "yuzu/controller_navigation.h" class GMainWindow; class QCheckBox; @@ -33,8 +31,9 @@ class System; } namespace Core::HID { +class HIDCore; enum class NpadStyleIndex : u8; -} +} // namespace Core::HID class QtControllerSelectorDialog final : public QDialog { Q_OBJECT @@ -149,9 +148,6 @@ private: // Checkboxes representing the "Connected Controllers". std::array connected_controller_checkboxes; - - // QObject for navigating the UI with a controller - ControllerNavigation* controller_navigation = nullptr; }; class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet { diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index de8bda293..7b19f1f8d 100755 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp @@ -17,6 +17,7 @@ #include "core/hle/lock.h" #include "yuzu/applets/qt_profile_select.h" #include "yuzu/main.h" +#include "yuzu/util/controller_navigation.h" namespace { QString FormatUserEntryText(const QString& username, Common::UUID uuid) { diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h index 200a1c47a..56496ed31 100755 --- a/src/yuzu/applets/qt_profile_select.h +++ b/src/yuzu/applets/qt_profile_select.h @@ -10,8 +10,8 @@ #include #include "core/frontend/applets/profile_select.h" #include "core/hle/service/acc/profile_manager.h" -#include "yuzu/controller_navigation.h" +class ControllerNavigation; class GMainWindow; class QDialogButtonBox; class QGraphicsScene; @@ -21,6 +21,10 @@ class QStandardItem; class QStandardItemModel; class QVBoxLayout; +namespace Core::HID { +class HIDCore; +} // namespace Core::HID + class QtProfileSelectionDialog final : public QDialog { Q_OBJECT diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 16284d5a6..34099bc83 100755 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -246,15 +246,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->EnableConfiguration(); - emulated_controller_hanheld->SaveCurrentConfig(); - emulated_controller_hanheld->EnableConfiguration(); - if (emulated_controller_hanheld->IsConnected(true)) { + emulated_controller_handheld->SaveCurrentConfig(); + emulated_controller_handheld->EnableConfiguration(); + if (emulated_controller_handheld->IsConnected(true)) { emulated_controller_p1->Disconnect(); - emulated_controller = emulated_controller_hanheld; + emulated_controller = emulated_controller_handheld; } else { emulated_controller = emulated_controller_p1; } @@ -590,19 +590,19 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); bool is_connected = emulated_controller->IsConnected(true); emulated_controller_p1->SetNpadStyleIndex(type); - emulated_controller_hanheld->SetNpadStyleIndex(type); + emulated_controller_handheld->SetNpadStyleIndex(type); if (is_connected) { if (type == Core::HID::NpadStyleIndex::Handheld) { emulated_controller_p1->Disconnect(); - emulated_controller_hanheld->Connect(); - emulated_controller = emulated_controller_hanheld; + emulated_controller_handheld->Connect(); + emulated_controller = emulated_controller_handheld; } else { - emulated_controller_hanheld->Disconnect(); + emulated_controller_handheld->Disconnect(); emulated_controller_p1->Connect(); emulated_controller = emulated_controller_p1; } @@ -650,10 +650,10 @@ ConfigureInputPlayer::~ConfigureInputPlayer() { if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->DisableConfiguration(); - emulated_controller_hanheld->DisableConfiguration(); + emulated_controller_handheld->DisableConfiguration(); } else { emulated_controller->DisableConfiguration(); } @@ -663,14 +663,14 @@ void ConfigureInputPlayer::ApplyConfiguration() { if (player_index == 0) { auto* emulated_controller_p1 = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); - auto* emulated_controller_hanheld = + auto* emulated_controller_handheld = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); emulated_controller_p1->DisableConfiguration(); emulated_controller_p1->SaveCurrentConfig(); emulated_controller_p1->EnableConfiguration(); - emulated_controller_hanheld->DisableConfiguration(); - emulated_controller_hanheld->SaveCurrentConfig(); - emulated_controller_hanheld->EnableConfiguration(); + emulated_controller_handheld->DisableConfiguration(); + emulated_controller_handheld->SaveCurrentConfig(); + emulated_controller_handheld->EnableConfiguration(); return; } emulated_controller->DisableConfiguration(); diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 3183b4df3..1a5e41588 100755 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -26,6 +26,7 @@ #include "yuzu/game_list_worker.h" #include "yuzu/main.h" #include "yuzu/uisettings.h" +#include "yuzu/util/controller_navigation.h" GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) : QObject(parent), gamelist{gamelist} {} diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index e673f9121..a94ea1477 100755 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -23,8 +23,8 @@ #include "common/common_types.h" #include "uisettings.h" #include "yuzu/compatibility_list.h" -#include "yuzu/controller_navigation.h" +class ControllerNavigation; class GameListWorker; class GameListSearchField; class GameListDir; diff --git a/src/yuzu/util/controller_navigation.cpp b/src/yuzu/util/controller_navigation.cpp new file mode 100755 index 000000000..86fb28b9f --- /dev/null +++ b/src/yuzu/util/controller_navigation.cpp @@ -0,0 +1,177 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#include "common/settings_input.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "yuzu/util/controller_navigation.h" + +ControllerNavigation::ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent) { + player1_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); + handheld_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); + Core::HID::ControllerUpdateCallback engine_callback{ + .on_change = [this](Core::HID::ControllerTriggerType type) { ControllerUpdateEvent(type); }, + .is_npad_service = false, + }; + player1_callback_key = player1_controller->SetCallback(engine_callback); + handheld_callback_key = handheld_controller->SetCallback(engine_callback); + is_controller_set = true; +} + +ControllerNavigation::~ControllerNavigation() { + UnloadController(); +} + +void ControllerNavigation::UnloadController() { + if (is_controller_set) { + player1_controller->DeleteCallback(player1_callback_key); + handheld_controller->DeleteCallback(handheld_callback_key); + is_controller_set = false; + } +} + +void ControllerNavigation::TriggerButton(Settings::NativeButton::Values native_button, + Qt::Key key) { + if (button_values[native_button].value && !button_values[native_button].locked) { + emit TriggerKeyboardEvent(key); + } +} + +void ControllerNavigation::ControllerUpdateEvent(Core::HID::ControllerTriggerType type) { + std::lock_guard lock{mutex}; + if (type == Core::HID::ControllerTriggerType::Button) { + ControllerUpdateButton(); + return; + } + + if (type == Core::HID::ControllerTriggerType::Stick) { + ControllerUpdateStick(); + return; + } +} + +void ControllerNavigation::ControllerUpdateButton() { + const auto controller_type = player1_controller->GetNpadStyleIndex(); + const auto& player1_buttons = player1_controller->GetButtonsValues(); + const auto& handheld_buttons = handheld_controller->GetButtonsValues(); + + for (std::size_t i = 0; i < player1_buttons.size(); ++i) { + const bool button = player1_buttons[i].value || handheld_buttons[i].value; + // Trigger only once + button_values[i].locked = button == button_values[i].value; + button_values[i].value = button; + } + + switch (controller_type) { + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::GameCube: + TriggerButton(Settings::NativeButton::A, Qt::Key_Enter); + TriggerButton(Settings::NativeButton::B, Qt::Key_Escape); + TriggerButton(Settings::NativeButton::DDown, Qt::Key_Down); + TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Left); + TriggerButton(Settings::NativeButton::DRight, Qt::Key_Right); + TriggerButton(Settings::NativeButton::DUp, Qt::Key_Up); + break; + case Core::HID::NpadStyleIndex::JoyconLeft: + TriggerButton(Settings::NativeButton::DDown, Qt::Key_Enter); + TriggerButton(Settings::NativeButton::DLeft, Qt::Key_Escape); + break; + case Core::HID::NpadStyleIndex::JoyconRight: + TriggerButton(Settings::NativeButton::X, Qt::Key_Enter); + TriggerButton(Settings::NativeButton::A, Qt::Key_Escape); + break; + default: + break; + } +} + +void ControllerNavigation::ControllerUpdateStick() { + const auto controller_type = player1_controller->GetNpadStyleIndex(); + const auto& player1_sticks = player1_controller->GetSticksValues(); + const auto& handheld_sticks = player1_controller->GetSticksValues(); + bool update = false; + + for (std::size_t i = 0; i < player1_sticks.size(); ++i) { + const Common::Input::StickStatus stick{ + .left = player1_sticks[i].left || handheld_sticks[i].left, + .right = player1_sticks[i].right || handheld_sticks[i].right, + .up = player1_sticks[i].up || handheld_sticks[i].up, + .down = player1_sticks[i].down || handheld_sticks[i].down, + }; + // Trigger only once + if (stick.down != stick_values[i].down || stick.left != stick_values[i].left || + stick.right != stick_values[i].right || stick.up != stick_values[i].up) { + update = true; + } + stick_values[i] = stick; + } + + if (!update) { + return; + } + + switch (controller_type) { + case Core::HID::NpadStyleIndex::ProController: + case Core::HID::NpadStyleIndex::JoyconDual: + case Core::HID::NpadStyleIndex::Handheld: + case Core::HID::NpadStyleIndex::GameCube: + if (stick_values[Settings::NativeAnalog::LStick].down) { + emit TriggerKeyboardEvent(Qt::Key_Down); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].left) { + emit TriggerKeyboardEvent(Qt::Key_Left); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].right) { + emit TriggerKeyboardEvent(Qt::Key_Right); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].up) { + emit TriggerKeyboardEvent(Qt::Key_Up); + return; + } + break; + case Core::HID::NpadStyleIndex::JoyconLeft: + if (stick_values[Settings::NativeAnalog::LStick].left) { + emit TriggerKeyboardEvent(Qt::Key_Down); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].up) { + emit TriggerKeyboardEvent(Qt::Key_Left); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].down) { + emit TriggerKeyboardEvent(Qt::Key_Right); + return; + } + if (stick_values[Settings::NativeAnalog::LStick].right) { + emit TriggerKeyboardEvent(Qt::Key_Up); + return; + } + break; + case Core::HID::NpadStyleIndex::JoyconRight: + if (stick_values[Settings::NativeAnalog::RStick].right) { + emit TriggerKeyboardEvent(Qt::Key_Down); + return; + } + if (stick_values[Settings::NativeAnalog::RStick].down) { + emit TriggerKeyboardEvent(Qt::Key_Left); + return; + } + if (stick_values[Settings::NativeAnalog::RStick].up) { + emit TriggerKeyboardEvent(Qt::Key_Right); + return; + } + if (stick_values[Settings::NativeAnalog::RStick].left) { + emit TriggerKeyboardEvent(Qt::Key_Up); + return; + } + break; + default: + break; + } +} diff --git a/src/yuzu/util/controller_navigation.h b/src/yuzu/util/controller_navigation.h new file mode 100755 index 000000000..b8f33967a --- /dev/null +++ b/src/yuzu/util/controller_navigation.h @@ -0,0 +1,48 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included + +#pragma once + +#include +#include + +#include "common/input.h" +#include "common/settings.h" +#include "core/hid/emulated_controller.h" + +namespace Core::HID { +class HIDCore; +} // namespace Core::HID + +class ControllerNavigation : public QObject { + Q_OBJECT + +public: + explicit ControllerNavigation(Core::HID::HIDCore& hid_core, QWidget* parent = nullptr); + ~ControllerNavigation(); + + /// Disables events from the emulated controller + void UnloadController(); + +signals: + void TriggerKeyboardEvent(Qt::Key key); + +private: + void TriggerButton(Settings::NativeButton::Values native_button, Qt::Key key); + void ControllerUpdateEvent(Core::HID::ControllerTriggerType type); + + void ControllerUpdateButton(); + + void ControllerUpdateStick(); + + Core::HID::ButtonValues button_values{}; + Core::HID::SticksValues stick_values{}; + + int player1_callback_key{}; + int handheld_callback_key{}; + bool is_controller_set{}; + mutable std::mutex mutex; + Core::HID::EmulatedController* player1_controller; + Core::HID::EmulatedController* handheld_controller; +};