mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-07-15 13:40:35 +00:00
n3ds: Treat the d-pad as a hat switch at the SDL_Joystick level.
Reference Issue #14830.
This commit is contained in:
committed by
Sam Lantinga
parent
82141a2439
commit
fb3afd33e4
@@ -877,7 +877,7 @@ static const char *s_GamepadMappings[] = {
|
||||
"0000000050535669746120436f6e7400,PSVita Controller,crc:d598,a:b2,b:b1,back:b10,dpdown:b6,dpleft:b7,dpright:b9,dpup:b8,leftshoulder:b4,leftstick:b14,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,",
|
||||
#endif
|
||||
#ifdef SDL_JOYSTICK_N3DS
|
||||
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b11,y:b10,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||
"000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b1,b:b0,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b11,rightx:a2,righty:a3,start:b3,x:b7,y:b6,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
#define NB_BUTTONS 23
|
||||
#define NB_BUTTONS 23 // physical buttons on the device (although we treat four of these, the dpad, as a hat switch).
|
||||
#define N3DS_HAT_MASK 0xF0 // 0xF0==d-pad bits, which we handle elsewhere, so mask them out here.
|
||||
|
||||
/*
|
||||
N3DS sticks values are roughly within +/-160
|
||||
@@ -54,8 +55,9 @@ static inline int Correct_Axis_Y(int Y) {
|
||||
return Correct_Axis_X(-Y);
|
||||
}
|
||||
|
||||
static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick);
|
||||
static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick);
|
||||
static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_state, u32 current_state);
|
||||
static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_state, u32 current_state);
|
||||
static void UpdateN3DSHat(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_down_state, u32 current_down_state, u32 previous_up_state, u32 current_up_state);
|
||||
static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick);
|
||||
static void UpdateN3DSCStick(Uint64 timestamp, SDL_Joystick *joystick);
|
||||
|
||||
@@ -89,9 +91,9 @@ static SDL_JoystickID N3DS_JoystickGetDeviceInstanceID(int device_index)
|
||||
|
||||
static bool N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||
{
|
||||
joystick->nbuttons = NB_BUTTONS;
|
||||
joystick->nbuttons = NB_BUTTONS - 4; // -4 for the dpad (which we treat as a hat).
|
||||
joystick->naxes = 4;
|
||||
joystick->nhats = 0;
|
||||
joystick->nhats = 1; // treat the dpad as a hat.
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -103,46 +105,85 @@ static bool N3DS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool enabled)
|
||||
|
||||
static void N3DS_JoystickUpdate(SDL_Joystick *joystick)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
static u32 previous_down_state = 0;
|
||||
static u32 previous_up_state = 0;
|
||||
const Uint64 timestamp = SDL_GetTicksNS();
|
||||
const u32 current_down_state = hidKeysDown();
|
||||
const u32 current_up_state = hidKeysUp();
|
||||
|
||||
UpdateN3DSPressedButtons(timestamp, joystick);
|
||||
UpdateN3DSReleasedButtons(timestamp, joystick);
|
||||
UpdateN3DSPressedButtons(timestamp, joystick, previous_down_state, current_down_state);
|
||||
UpdateN3DSReleasedButtons(timestamp, joystick, previous_up_state, current_up_state);
|
||||
UpdateN3DSHat(timestamp, joystick, previous_down_state, current_down_state, previous_up_state, current_up_state);
|
||||
UpdateN3DSCircle(timestamp, joystick);
|
||||
UpdateN3DSCStick(timestamp, joystick);
|
||||
|
||||
previous_down_state = current_down_state;
|
||||
previous_up_state = current_up_state;
|
||||
}
|
||||
|
||||
static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick)
|
||||
static void UpdateN3DSPressedButtons(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_state, u32 current_state)
|
||||
{
|
||||
static u32 previous_state = 0;
|
||||
u32 updated_down;
|
||||
u32 current_state = hidKeysDown();
|
||||
updated_down = previous_state ^ current_state;
|
||||
const u32 updated_down = (previous_state ^ current_state) & ~N3DS_HAT_MASK;
|
||||
if (updated_down) {
|
||||
for (Uint8 i = 0; i < joystick->nbuttons; i++) {
|
||||
if (current_state & BIT(i) & updated_down) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, i, true);
|
||||
Uint8 buttonidx = 0;
|
||||
Uint8 i = 0;
|
||||
while (i < joystick->nbuttons) {
|
||||
if ((buttonidx < 4) || (buttonidx > 7)) { // skip dpad (we treat it as a hat).
|
||||
if (current_state & BIT(buttonidx) & updated_down) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, i, true);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
buttonidx++;
|
||||
}
|
||||
}
|
||||
previous_state = current_state;
|
||||
}
|
||||
|
||||
static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick)
|
||||
static void UpdateN3DSReleasedButtons(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_state, u32 current_state)
|
||||
{
|
||||
static u32 previous_state = 0;
|
||||
u32 updated_up;
|
||||
u32 current_state = hidKeysUp();
|
||||
updated_up = previous_state ^ current_state;
|
||||
const u32 updated_up = (previous_state ^ current_state) & ~N3DS_HAT_MASK;
|
||||
if (updated_up) {
|
||||
for (Uint8 i = 0; i < joystick->nbuttons; i++) {
|
||||
if (current_state & BIT(i) & updated_up) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, i, false);
|
||||
}
|
||||
Uint8 buttonidx = 0;
|
||||
Uint8 i = 0;
|
||||
while (i < joystick->nbuttons) {
|
||||
if ((buttonidx < 4) || (buttonidx > 7)) { // skip dpad (we treat it as a hat).
|
||||
if (current_state & BIT(buttonidx) & updated_up) {
|
||||
SDL_SendJoystickButton(timestamp, joystick, i, false);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
buttonidx++;
|
||||
}
|
||||
}
|
||||
previous_state = current_state;
|
||||
}
|
||||
|
||||
static void UpdateN3DSHat(Uint64 timestamp, SDL_Joystick *joystick, u32 previous_down_state, u32 current_down_state, u32 previous_up_state, u32 current_up_state)
|
||||
{
|
||||
// The 3DS dpad looks like 4 buttons at this level, but we treat it as a hat switch, so apps that are talking to SDL_Joystick can hope to do basic directional things without a configuration step.
|
||||
// (but they should _really_ be using the gamepad API.)
|
||||
const u32 updated_hat = (((previous_up_state ^ current_up_state) | (previous_down_state ^ current_down_state)) & N3DS_HAT_MASK); // did bits 4 through 7 change?
|
||||
if (updated_hat) {
|
||||
Uint8 hat = SDL_HAT_CENTERED;
|
||||
|
||||
#define HATSTATE(n3dsbit, sdlenum) if (current_down_state & BIT(n3dsbit)) { hat |= SDL_HAT_##sdlenum; }
|
||||
HATSTATE(4, RIGHT);
|
||||
HATSTATE(5, LEFT);
|
||||
HATSTATE(6, UP);
|
||||
HATSTATE(7, DOWN);
|
||||
#undef HATSTATE
|
||||
|
||||
// this is a physical d-pad on the device, so it probably _can't_ send opposing buttons at the same time, but just in case, cancel them out.
|
||||
if ((hat & (SDL_HAT_UP|SDL_HAT_DOWN)) == (SDL_HAT_UP|SDL_HAT_DOWN)) {
|
||||
hat &= ~(SDL_HAT_UP|SDL_HAT_DOWN);
|
||||
}
|
||||
if ((hat & (SDL_HAT_LEFT|SDL_HAT_RIGHT)) == (SDL_HAT_LEFT|SDL_HAT_RIGHT)) {
|
||||
hat &= ~(SDL_HAT_LEFT|SDL_HAT_RIGHT);
|
||||
}
|
||||
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void UpdateN3DSCircle(Uint64 timestamp, SDL_Joystick *joystick)
|
||||
{
|
||||
static circlePosition previous_state = { 0, 0 };
|
||||
@@ -194,19 +235,19 @@ static bool N3DS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
|
||||
*out = (SDL_GamepadMapping){
|
||||
.a = { EMappingKind_Button, 0 },
|
||||
.b = { EMappingKind_Button, 1 },
|
||||
.x = { EMappingKind_Button, 10 },
|
||||
.y = { EMappingKind_Button, 11 },
|
||||
.x = { EMappingKind_Button, 6 },
|
||||
.y = { EMappingKind_Button, 7 },
|
||||
.back = { EMappingKind_Button, 2 },
|
||||
.guide = { EMappingKind_None, 255 },
|
||||
.start = { EMappingKind_Button, 3 },
|
||||
.leftstick = { EMappingKind_None, 255 },
|
||||
.rightstick = { EMappingKind_None, 255 },
|
||||
.leftshoulder = { EMappingKind_Button, 9 },
|
||||
.rightshoulder = { EMappingKind_Button, 8 },
|
||||
.dpup = { EMappingKind_Button, 6 },
|
||||
.dpdown = { EMappingKind_Button, 7 },
|
||||
.dpleft = { EMappingKind_Button, 5 },
|
||||
.dpright = { EMappingKind_Button, 4 },
|
||||
.leftshoulder = { EMappingKind_Button, 5 },
|
||||
.rightshoulder = { EMappingKind_Button, 4 },
|
||||
.dpup = { EMappingKind_Hat, SDL_HAT_UP },
|
||||
.dpdown = { EMappingKind_Hat, SDL_HAT_DOWN },
|
||||
.dpleft = { EMappingKind_Hat, SDL_HAT_LEFT },
|
||||
.dpright = { EMappingKind_Hat, SDL_HAT_RIGHT },
|
||||
.misc1 = { EMappingKind_None, 255 },
|
||||
.right_paddle1 = { EMappingKind_None, 255 },
|
||||
.left_paddle1 = { EMappingKind_None, 255 },
|
||||
@@ -216,8 +257,8 @@ static bool N3DS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping
|
||||
.lefty = { EMappingKind_Axis, 1 },
|
||||
.rightx = { EMappingKind_Axis, 2 },
|
||||
.righty = { EMappingKind_Axis, 3 },
|
||||
.lefttrigger = { EMappingKind_Button, 14 },
|
||||
.righttrigger = { EMappingKind_Button, 15 },
|
||||
.lefttrigger = { EMappingKind_Button, 10 },
|
||||
.righttrigger = { EMappingKind_Button, 11 },
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user