switch: implement rumble with native API
This commit is contained in:
parent
bc70d9118d
commit
19bb4a6e5d
|
@ -1037,7 +1037,10 @@ else()
|
|||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
core/linux/libnx_vmem.cpp
|
||||
shell/switch/stubs.c
|
||||
shell/switch/context_switch.S)
|
||||
shell/switch/context_switch.S
|
||||
shell/switch/nswitch.h
|
||||
shell/switch/switch_gamepad.h
|
||||
shell/switch/ucontext.h)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#endif
|
||||
#ifdef __SWITCH__
|
||||
#include "nswitch.h"
|
||||
#include "switch_gamepad.h"
|
||||
#endif
|
||||
|
||||
static SDL_Window* window = NULL;
|
||||
|
@ -51,7 +52,7 @@ static struct SDLDeInit
|
|||
}
|
||||
|
||||
bool initialized = false;
|
||||
} sqlDeinit;
|
||||
} sdlDeInit;
|
||||
|
||||
static void sdl_open_joystick(int index)
|
||||
{
|
||||
|
@ -63,7 +64,11 @@ static void sdl_open_joystick(int index)
|
|||
return;
|
||||
}
|
||||
try {
|
||||
#ifdef __SWITCH__
|
||||
std::shared_ptr<SDLGamepad> gamepad = std::make_shared<SwitchGamepad>(index < MAPLE_PORTS ? index : -1, index, pJoystick);
|
||||
#else
|
||||
std::shared_ptr<SDLGamepad> gamepad = std::make_shared<SDLGamepad>(index < MAPLE_PORTS ? index : -1, index, pJoystick);
|
||||
#endif
|
||||
SDLGamepad::AddSDLGamepad(gamepad);
|
||||
} catch (const FlycastException& e) {
|
||||
}
|
||||
|
@ -189,7 +194,7 @@ void input_sdl_init()
|
|||
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
die("SDL: error initializing Joystick subsystem");
|
||||
}
|
||||
sqlDeinit.initialized = true;
|
||||
sdlDeInit.initialized = true;
|
||||
|
||||
SDL_SetRelativeMouseMode(SDL_FALSE);
|
||||
|
||||
|
@ -720,7 +725,7 @@ void sdl_window_create()
|
|||
SDL_Vulkan_LoadLibrary("libvulkan.dylib");
|
||||
#endif
|
||||
}
|
||||
sqlDeinit.initialized = true;
|
||||
sdlDeInit.initialized = true;
|
||||
initRenderApi();
|
||||
// ImGui copy & paste
|
||||
ImGui::GetIO().GetClipboardTextFn = getClipboardText;
|
||||
|
|
|
@ -410,11 +410,13 @@ public:
|
|||
pair.second->update_rumble();
|
||||
}
|
||||
|
||||
protected:
|
||||
double vib_stop_time = 0;
|
||||
SDL_JoystickID sdl_joystick_instance;
|
||||
|
||||
private:
|
||||
SDL_Joystick* sdl_joystick;
|
||||
SDL_JoystickID sdl_joystick_instance;
|
||||
float vib_inclination = 0;
|
||||
double vib_stop_time = 0;
|
||||
SDL_GameController *sdl_controller = nullptr;
|
||||
static std::map<SDL_JoystickID, std::shared_ptr<SDLGamepad>> sdl_gamepads;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
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 = os_GetSeconds() + duration_ms / 1000.0;
|
||||
else
|
||||
vib_stop_time = 0.0;
|
||||
}
|
||||
|
||||
void update_rumble() override
|
||||
{
|
||||
if (!rumbleEnabled || vib_stop_time == 0.0)
|
||||
return;
|
||||
int rem_time = (vib_stop_time - os_GetSeconds()) * 1000;
|
||||
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.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];
|
||||
};
|
Loading…
Reference in New Issue