mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	First implementation of controller rumble
This commit is contained in:
		
							parent
							
								
									a8be822e8e
								
							
						
					
					
						commit
						ab88c2f611
					
				| @ -33,6 +33,9 @@ public: | ||||
|     virtual bool GetAnalogDirectionStatus(AnalogDirection direction) const { | ||||
|         return {}; | ||||
|     } | ||||
|     virtual bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const { | ||||
|         return {}; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| /// An abstract class template for a factory that can create input devices.
 | ||||
|  | ||||
| @ -609,20 +609,31 @@ void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | ||||
| void Controller_NPad::VibrateController(const std::vector<u32>& controllers, | ||||
|                                         const std::vector<Vibration>& vibrations) { | ||||
|     LOG_DEBUG(Service_HID, "(STUBBED) called"); | ||||
|     LOG_TRACE(Service_HID, "called"); | ||||
| 
 | ||||
|     if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { | ||||
|         return; | ||||
|     } | ||||
|     for (std::size_t i = 0; i < controller_ids.size(); i++) { | ||||
|         std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i)); | ||||
|         if (connected_controllers[controller_pos].is_connected) { | ||||
|             // TODO(ogniK): Vibrate the physical controller
 | ||||
|     bool success = true; | ||||
|     for (std::size_t i = 0; i < controllers.size(); ++i) { | ||||
|         if (!connected_controllers[i].is_connected) { | ||||
|             continue; | ||||
|         } | ||||
|         using namespace Settings::NativeButton; | ||||
|         const auto& button_state = buttons[i]; | ||||
|         if (button_state[A - BUTTON_HID_BEGIN]) { | ||||
|             if (button_state[A - BUTTON_HID_BEGIN]->SetRumblePlay( | ||||
|                     vibrations[0].amp_high, vibrations[0].amp_low, vibrations[0].freq_high, | ||||
|                     vibrations[0].freq_low)) { | ||||
|                 success = false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     last_processed_vibration = vibrations.back(); | ||||
|     if (success) { | ||||
|         last_processed_vibration = vibrations.back(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | ||||
|  | ||||
| @ -121,7 +121,7 @@ public: | ||||
| 
 | ||||
|     void SetNpadMode(u32 npad_id, NPadAssignments assignment_mode); | ||||
| 
 | ||||
|     void VibrateController(const std::vector<u32>& controller_ids, | ||||
|     void VibrateController(const std::vector<u32>& controllers, | ||||
|                            const std::vector<Vibration>& vibrations); | ||||
| 
 | ||||
|     Vibration GetLastVibration() const; | ||||
|  | ||||
| @ -802,18 +802,18 @@ void Hid::EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { | ||||
| 
 | ||||
| void Hid::SendVibrationValue(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto controller_id{rp.Pop<u32>()}; | ||||
|     const auto controller{rp.Pop<u32>()}; | ||||
|     const auto vibration_values{rp.PopRaw<Controller_NPad::Vibration>()}; | ||||
|     const auto applet_resource_user_id{rp.Pop<u64>()}; | ||||
| 
 | ||||
|     LOG_DEBUG(Service_HID, "called, controller_id={}, applet_resource_user_id={}", controller_id, | ||||
|     LOG_DEBUG(Service_HID, "called, controller={}, applet_resource_user_id={}", controller, | ||||
|               applet_resource_user_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| 
 | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .VibrateController({controller_id}, {vibration_values}); | ||||
|         .VibrateController({controller}, {vibration_values}); | ||||
| } | ||||
| 
 | ||||
| void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { | ||||
| @ -831,8 +831,6 @@ void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) { | ||||
| 
 | ||||
|     std::memcpy(controller_list.data(), controllers.data(), controllers.size()); | ||||
|     std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); | ||||
|     std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(), | ||||
|                    [](u32 controller_id) { return controller_id - 3; }); | ||||
| 
 | ||||
|     applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||||
|         .VibrateController(controller_list, vibration_list); | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <atomic> | ||||
| #include <chrono> | ||||
| #include <cmath> | ||||
| #include <functional> | ||||
| #include <mutex> | ||||
| @ -78,6 +79,33 @@ public: | ||||
|         return state.axes.at(axis) / (32767.0f * range); | ||||
|     } | ||||
| 
 | ||||
|     bool RumblePlay(f32 amp_low, f32 amp_high, int time) { | ||||
|         const u16 raw_amp_low = static_cast<u16>(amp_low * 0xFFFF); | ||||
|         const u16 raw_amp_high = static_cast<u16>(amp_high * 0xFFFF); | ||||
|         // Lower drastically the number of state changes
 | ||||
|         if (raw_amp_low >> 11 == last_state_rumble_low >> 11 && | ||||
|             raw_amp_high >> 11 == last_state_rumble_high >> 11) { | ||||
|             if (raw_amp_low + raw_amp_high != 0 || | ||||
|                 last_state_rumble_low + last_state_rumble_high == 0) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|         // Don't change state if last vibration was < 20ms
 | ||||
|         const auto now = std::chrono::system_clock::now(); | ||||
|         if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_vibration) < | ||||
|             std::chrono::milliseconds(20)) { | ||||
|             return raw_amp_low + raw_amp_high == 0; | ||||
|         } | ||||
| 
 | ||||
|         last_vibration = now; | ||||
|         last_state_rumble_low = raw_amp_low; | ||||
|         last_state_rumble_high = raw_amp_high; | ||||
|         if (sdl_joystick) { | ||||
|             SDL_JoystickRumble(sdl_joystick.get(), raw_amp_low, raw_amp_high, time); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     std::tuple<float, float> GetAnalog(int axis_x, int axis_y, float range) const { | ||||
|         float x = GetAxis(axis_x, range); | ||||
|         float y = GetAxis(axis_y, range); | ||||
| @ -139,6 +167,9 @@ private: | ||||
|     } state; | ||||
|     std::string guid; | ||||
|     int port; | ||||
|     u16 last_state_rumble_high; | ||||
|     u16 last_state_rumble_low; | ||||
|     std::chrono::time_point<std::chrono::system_clock> last_vibration; | ||||
|     std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; | ||||
|     std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | ||||
|     mutable std::mutex mutex; | ||||
| @ -207,7 +238,7 @@ void SDLState::InitJoystick(int joystick_index) { | ||||
|         sdl_gamecontroller = SDL_GameControllerOpen(joystick_index); | ||||
|     } | ||||
|     if (!sdl_joystick) { | ||||
|         LOG_ERROR(Input, "failed to open joystick {}", joystick_index); | ||||
|         LOG_ERROR(Input, "Failed to open joystick {}", joystick_index); | ||||
|         return; | ||||
|     } | ||||
|     const std::string guid = GetGUID(sdl_joystick); | ||||
| @ -303,6 +334,12 @@ public: | ||||
|         return joystick->GetButton(button); | ||||
|     } | ||||
| 
 | ||||
|     bool SetRumblePlay(f32 amp_high, f32 amp_low, f32 freq_high, f32 freq_low) const override { | ||||
|         const f32 new_amp_low = pow(amp_low, 0.5f) * (3.0f - 2.0f * pow(amp_low, 0.15f)); | ||||
|         const f32 new_amp_high = pow(amp_high, 0.5f) * (3.0f - 2.0f * pow(amp_high, 0.15f)); | ||||
|         return joystick->RumblePlay(new_amp_low, new_amp_high, 250); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     std::shared_ptr<SDLJoystick> joystick; | ||||
|     int button; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 german
						german