GameCubeAdapter: Add suppport for all rumble modes

This adds support for all 3 of the gamecube controller's rumble modes
Rumble: 1
Stop: 0
StopHard: 2
This is useful for applications that need the full range of support
This also adds a hint to control rumble behavior, defaults 0 to maintain compatibility
This commit is contained in:
Phillip Stephens 2022-02-22 00:41:15 -08:00 committed by Sam Lantinga
parent b946e31ec8
commit 94d43186f2
2 changed files with 41 additions and 2 deletions

View File

@ -625,6 +625,21 @@ extern "C" {
*/
#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
/**
* \brief A variable controlling whether "low_frequency_rumble" and "high_frequency_rumble" is used to implement
* the GameCube controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2)
* this is useful for applications that need full compatibility for things like ADSR envelopes.
* Stop is implemented by setting "low_frequency_rumble" to "0" and "high_frequency_rumble" ">0"
* Rumble is both at any arbitrary value,
* StopHard is implemented by setting both "low_frequency_rumble" and "high_frequency_rumble" to "0"
*
* This variable can be set to the following values:
* "0" - Normal rumble behavior is behavior is used (default)
* "1" - Proper GameCube controller rumble behavior is used
*
*/
#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE"
/**
* \brief A variable controlling whether Switch Joy-Cons should be treated the same as Switch Pro Controllers when using the HIDAPI driver.
*

View File

@ -53,6 +53,7 @@ typedef struct {
/* Without this variable, hid_write starts to lag a TON */
SDL_bool rumbleUpdate;
SDL_bool m_bUseButtonLabels;
SDL_bool useRumbleBrake;
} SDL_DriverGameCube_Context;
static SDL_bool
@ -92,6 +93,14 @@ static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata,
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
}
static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
if (hint) {
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
ctx->useRumbleBrake = SDL_GetStringBoolean(hint, SDL_FALSE);
}
}
static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
{
if (!ctx->m_bUseButtonLabels) {
@ -142,6 +151,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
ctx->joysticks[2] = -1;
ctx->joysticks[3] = -1;
ctx->rumble[0] = rumbleMagic;
ctx->useRumbleBrake = SDL_FALSE;
if (device->vendor_id != USB_VENDOR_NINTENDO) {
ctx->pc_mode = SDL_TRUE;
@ -195,6 +205,8 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
}
}
SDL_AddHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
@ -439,12 +451,22 @@ HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
if (joystick->instance_id == ctx->joysticks[i]) {
if (ctx->wireless[i]) {
return SDL_SetError("Ninteno GameCube WaveBird controllers do not support rumble");
return SDL_SetError("Nintendo GameCube WaveBird controllers do not support rumble");
}
if (!ctx->rumbleAllowed[i]) {
return SDL_SetError("Second USB cable for WUP-028 not connected");
}
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
if (ctx->useRumbleBrake) {
if (low_frequency_rumble == 0 && high_frequency_rumble > 0) {
val = 0; /* if only low is 0 we want to do a regular stop*/
} else if (low_frequency_rumble == 0 && high_frequency_rumble == 0) {
val = 2; /* if both frequencies are 0 we want to do a hard stop */
} else {
val = 1; /* normal rumble */
}
} else {
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
}
if (val != ctx->rumble[i + 1]) {
ctx->rumble[i + 1] = val;
ctx->rumbleUpdate = SDL_TRUE;
@ -522,6 +544,8 @@ HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
SDL_GameControllerButtonReportingHintChanged, ctx);
SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
SDL_LockMutex(device->dev_lock);
{