95 lines
3.1 KiB
C++
95 lines
3.1 KiB
C++
/*
|
|
Copyright 2024 flyinghead
|
|
|
|
This file is part of Flycast.
|
|
|
|
Flycast is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Flycast is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
#include "sdl/sdl_gamepad.h"
|
|
#include "nswitch.h"
|
|
|
|
//
|
|
// SDL 2.0.14-4 rumble doesn't seem to work
|
|
// so this class implements rumble using the native API.
|
|
//
|
|
class SwitchGamepad : public SDLGamepad
|
|
{
|
|
public:
|
|
SwitchGamepad(int maple_port, int joystick_idx, SDL_Joystick* sdl_joystick)
|
|
: SDLGamepad(maple_port, joystick_idx, sdl_joystick)
|
|
{
|
|
// A dual joycon controller has 2 vibration devices (left and right joycons)
|
|
// Joystick 0 is either HidNpadIdType_Handheld or HidNpadIdType_No1 depending on the joycon configuration
|
|
Result rc = hidInitializeVibrationDevices(vibDeviceHandlesNoN, 2, (HidNpadIdType)(HidNpadIdType_No1 + joystick_idx),
|
|
HidNpadStyleTag_NpadJoyDual);
|
|
if (R_FAILED(rc))
|
|
WARN_LOG(INPUT, "hidInitializeVibrationDevices(No%d) failed %x", joystick_idx + 1, rc);
|
|
if (joystick_idx == 0)
|
|
{
|
|
padInitializeDefault(&pad);
|
|
rc = hidInitializeVibrationDevices(vibDeviceHandlesHandHeld, 2, HidNpadIdType_Handheld, HidNpadStyleTag_NpadHandheld);
|
|
if (R_FAILED(rc))
|
|
WARN_LOG(INPUT, "hidInitializeVibrationDevices(handHeld) failed %x", rc);
|
|
}
|
|
}
|
|
|
|
void rumble(float power, float inclination, u32 duration_ms) override
|
|
{
|
|
if (!rumbleEnabled)
|
|
return;
|
|
|
|
power = std::min(power / std::pow(1.06f, 100.f - rumblePower), 1.f);
|
|
float freq = 160.f + inclination * 100.f;
|
|
HidVibrationValue vibValues[2]{};
|
|
vibValues[0].amp_low = power;
|
|
vibValues[0].freq_low = freq;
|
|
vibValues[0].amp_high = power;
|
|
vibValues[0].freq_high = freq;
|
|
memcpy(&vibValues[1], &vibValues[0], sizeof(HidVibrationValue));
|
|
hidSendVibrationValues(getDeviceHandle(), vibValues, 2);
|
|
if (power != 0.f)
|
|
vib_stop_time = getTimeMs() + duration_ms;
|
|
else
|
|
vib_stop_time = 0;
|
|
}
|
|
|
|
void update_rumble() override
|
|
{
|
|
if (!rumbleEnabled || vib_stop_time == 0.0)
|
|
return;
|
|
int rem_time = vib_stop_time - getTimeMs();
|
|
if (rem_time <= 0)
|
|
{
|
|
HidVibrationValue vibValues[2]{};
|
|
vibValues[0].freq_low = vibValues[1].freq_low = 160.f;
|
|
vibValues[0].freq_high = vibValues[1].freq_high = 320.f;
|
|
hidSendVibrationValues(getDeviceHandle(), vibValues, 2);
|
|
vib_stop_time = 0;
|
|
}
|
|
}
|
|
|
|
private:
|
|
HidVibrationDeviceHandle *getDeviceHandle()
|
|
{
|
|
if (sdl_joystick_instance != 0)
|
|
return vibDeviceHandlesNoN;
|
|
padUpdate(&pad);
|
|
return padIsHandheld(&pad) ? vibDeviceHandlesHandHeld : vibDeviceHandlesNoN;
|
|
}
|
|
|
|
PadState pad;
|
|
HidVibrationDeviceHandle vibDeviceHandlesHandHeld[2];
|
|
HidVibrationDeviceHandle vibDeviceHandlesNoN[2];
|
|
};
|