foxygit / doom Log in
commit 13f76d361a18e4b0f083ce1cca4c1d05fd9435bb
Author:     Michael Day <contact@michaelcday.com>
AuthorDate: Sun Aug 6 23:33:24 2023 -0400
Commit:     Turo Lamminen <turol@users.noreply.github.com>
CommitDate: Wed Aug 23 11:42:50 2023 +0300

    Show real button names for popular gamepads
---
 src/i_joystick.c          |   5 +
 src/m_config.c            |   6 +
 src/setup/joystick.c      |   6 +
 src/setup/joystick.h      |   1 +
 src/setup/txt_joybinput.c | 282 +++++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 299 insertions(+), 1 deletion(-)

diff --git a/src/i_joystick.c b/src/i_joystick.c
index eb471750..f2b6e6f9 100644
--- a/src/i_joystick.c
+++ b/src/i_joystick.c
@@ -49,6 +49,9 @@ static int usejoystick = 0;
 // Use SDL_gamecontroller interface for the selected device
 static int use_gamepad = 0;

+// SDL_GameControllerType of gamepad
+static int gamepad_type = 0;
+
 // SDL GUID and index of the joystick to use.
 static char *joystick_guid = "";
 static int joystick_index = -1;
@@ -194,6 +197,7 @@ void I_InitGamepad(void)
     }

     joystick_index = index;
+    gamepad_type = SDL_GameControllerTypeForIndex(index);

     if (strcmp(joystick_guid, ""))
     {
@@ -633,6 +637,7 @@ void I_BindJoystickVariables(void)

     M_BindIntVariable("use_joystick",          &usejoystick);
     M_BindIntVariable("use_gamepad",           &use_gamepad);
+    M_BindIntVariable("gamepad_type",          &gamepad_type);
     M_BindStringVariable("joystick_guid",      &joystick_guid);
     M_BindIntVariable("joystick_index",        &joystick_index);
     M_BindIntVariable("joystick_x_axis",       &joystick_x_axis);
diff --git a/src/m_config.c b/src/m_config.c
index c38d5989..109601b0 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -1376,6 +1376,12 @@ static default_t extra_defaults_list[] =

     CONFIG_VARIABLE_INT(use_gamepad),

+    //!
+    // Stores the SDL_GameControllerType of the last configured gamepad.
+    //
+
+    CONFIG_VARIABLE_INT(gamepad_type),
+
     //!
     // Joystick virtual button to make the player strafe left.
     //
diff --git a/src/setup/joystick.c b/src/setup/joystick.c
index 72886d59..dd24448c 100644
--- a/src/setup/joystick.c
+++ b/src/setup/joystick.c
@@ -599,6 +599,9 @@ static const known_joystick_t known_joysticks[] =
 // Use SDL_GameController interface
 int use_gamepad = 0;

+// SDL_GameControllerType of gamepad
+int gamepad_type = 0;
+
 // Based on Unity Doom mapping
 static const joystick_config_t modern_gamepad[] =
 {
@@ -980,6 +983,7 @@ static int CalibrationEventCallback(SDL_Event *event, void *user_data)
     {
         usejoystick = 1;
         use_gamepad = 1;
+        gamepad_type = SDL_GameControllerTypeForIndex(joystick_index);
         LoadConfigurationSet(empty_defaults);
         GetGamepadDefaultConfig();
         TXT_CloseWindow(calibration_window);
@@ -990,6 +994,7 @@ static int CalibrationEventCallback(SDL_Event *event, void *user_data)
     // In the first "center" stage, we're just trying to work out which
     // joystick is being configured and which button the user is pressing.
     usejoystick = 1;
+    gamepad_type = SDL_CONTROLLER_TYPE_UNKNOWN;
     calibrate_button = event->jbutton.button;

     // If the joystick is a known one, auto-load default
@@ -1205,6 +1210,7 @@ void BindJoystickVariables(void)

     M_BindIntVariable("use_joystick",           &usejoystick);
     M_BindIntVariable("use_gamepad",            &use_gamepad);
+    M_BindIntVariable("gamepad_type",           &gamepad_type);
     M_BindStringVariable("joystick_guid",       &joystick_guid);
     M_BindIntVariable("joystick_index",         &joystick_index);
     M_BindIntVariable("joystick_x_axis",        &joystick_x_axis);
diff --git a/src/setup/joystick.h b/src/setup/joystick.h
index 3a9d1705..dd17b7d9 100644
--- a/src/setup/joystick.h
+++ b/src/setup/joystick.h
@@ -22,6 +22,7 @@
 extern int joystick_index;
 extern int joystick_physical_buttons[NUM_VIRTUAL_BUTTONS];
 extern int use_gamepad;
+extern int gamepad_type;


 void ConfigJoystick(void *widget, void *user_data);
diff --git a/src/setup/txt_joybinput.c b/src/setup/txt_joybinput.c
index ca469731..6321a066 100644
--- a/src/setup/txt_joybinput.c
+++ b/src/setup/txt_joybinput.c
@@ -60,6 +60,199 @@ static int *all_joystick_buttons[NUM_VIRTUAL_BUTTONS] =
     &joybautomap,
 };

+// For indirection so that we're not dependent on item ordering in the
+// SDL_GameControllerButton enum.
+static const int gamepad_buttons[GAMEPAD_BUTTON_MAX] =
+{
+   SDL_CONTROLLER_BUTTON_A,
+   SDL_CONTROLLER_BUTTON_B,
+   SDL_CONTROLLER_BUTTON_X,
+   SDL_CONTROLLER_BUTTON_Y,
+   SDL_CONTROLLER_BUTTON_BACK,
+   SDL_CONTROLLER_BUTTON_GUIDE,
+   SDL_CONTROLLER_BUTTON_START,
+   SDL_CONTROLLER_BUTTON_LEFTSTICK,
+   SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+   SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+   SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+   SDL_CONTROLLER_BUTTON_DPAD_UP,
+   SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+   SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+   SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+   SDL_CONTROLLER_BUTTON_MISC1,
+   SDL_CONTROLLER_BUTTON_PADDLE1,
+   SDL_CONTROLLER_BUTTON_PADDLE2,
+   SDL_CONTROLLER_BUTTON_PADDLE3,
+   SDL_CONTROLLER_BUTTON_PADDLE4,
+   SDL_CONTROLLER_BUTTON_TOUCHPAD,
+   GAMEPAD_BUTTON_TRIGGERLEFT,
+   GAMEPAD_BUTTON_TRIGGERRIGHT,
+};
+
+// Items in the following button lists are ordered according to gamepad_buttons
+// above.
+static const char *xbox360_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "A",
+    "B",
+    "X",
+    "Y",
+    "BACK",
+    "GUIDE",
+    "START",
+    "LSB",
+    "RSB",
+    "LB",
+    "RB",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "LT",
+    "RT",
+};
+
+static const char *xboxone_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "A",
+    "B",
+    "X",
+    "Y",
+    "VIEW",
+    "XBOX",
+    "MENU",
+    "LSB",
+    "RSB",
+    "LB",
+    "RB",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "PROFILE",
+    "P1",
+    "P2",
+    "P3",
+    "P4",
+    "",
+    "LT",
+    "RT",
+};
+
+static const char *ps3_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "X",
+    "CIRCLE",
+    "SQUARE",
+    "TRIANGLE",
+    "SELECT",
+    "PS",
+    "START",
+    "L3",
+    "R3",
+    "L1",
+    "R1",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "L2",
+    "R2",
+};
+
+static const char *ps4_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "X",
+    "CIRCLE",
+    "SQUARE",
+    "TRIANGLE",
+    "SHARE",
+    "PS",
+    "OPTIONS",
+    "L3",
+    "R3",
+    "L1",
+    "R1",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "TOUCH",
+    "L2",
+    "R2",
+};
+
+static const char *ps5_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "X",
+    "CIRCLE",
+    "SQUARE",
+    "TRIANGLE",
+    "SHARE",
+    "PS",
+    "OPTIONS",
+    "L3",
+    "R3",
+    "L1",
+    "R1",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "MUTE",
+    "",
+    "",
+    "",
+    "",
+    "TOUCH",
+    "L2",
+    "R2",
+};
+
+static const char *switchpro_buttons[GAMEPAD_BUTTON_MAX] =
+{
+    "B",
+    "A",
+    "Y",
+    "X",
+    "MINUS",
+    "HOME",
+    "PLUS",
+    "LSB",
+    "RSB",
+    "L",
+    "R",
+    "DPAD U",
+    "DPAD D",
+    "DPAD L",
+    "DPAD R",
+    "CAPTURE",
+    "",
+    "",
+    "",
+    "",
+    "",
+    "ZL",
+    "ZR",
+};
+
 static int PhysicalForVirtualButton(int vbutton)
 {
     if (vbutton < NUM_VIRTUAL_BUTTONS)
@@ -381,6 +574,93 @@ static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input))
     }
 }

+static int GetGamepadButtonIndex(int button)
+{
+    int i;
+
+    for (i = 0; i < arrlen(gamepad_buttons); ++i)
+    {
+        if (button == gamepad_buttons[i])
+        {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static void GetGamepadButtonDescription(int vbutton, char *buf, size_t buf_len)
+{
+    int index;
+
+    index = GetGamepadButtonIndex(PhysicalForVirtualButton(vbutton));
+
+    if (index < 0)
+    {
+        M_StringCopy(buf, "(unknown)", buf_len);
+        return;
+    }
+
+    switch (gamepad_type)
+    {
+        case SDL_CONTROLLER_TYPE_XBOX360:
+            M_snprintf(buf, buf_len, "%s", xbox360_buttons[index]);
+            break;
+
+        case SDL_CONTROLLER_TYPE_XBOXONE:
+            M_snprintf(buf, buf_len, "%s", xboxone_buttons[index]);
+            break;
+
+        case SDL_CONTROLLER_TYPE_PS3:
+            M_snprintf(buf, buf_len, "%s", ps3_buttons[index]);
+            break;
+
+        case SDL_CONTROLLER_TYPE_PS4:
+            M_snprintf(buf, buf_len, "%s", ps4_buttons[index]);
+            break;
+
+        case SDL_CONTROLLER_TYPE_PS5:
+            M_snprintf(buf, buf_len, "%s", ps5_buttons[index]);
+            break;
+
+        case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
+            M_snprintf(buf, buf_len, "%s", switchpro_buttons[index]);
+            break;
+
+        default:
+            M_snprintf(buf, buf_len, "BUTTON #%i",
+                       PhysicalForVirtualButton(vbutton) + 1);
+            break;
+    }
+}
+
+static void TXT_GamepadInputDrawer(TXT_UNCAST_ARG(joystick_input))
+{
+    TXT_CAST_ARG(txt_joystick_input_t, joystick_input);
+    char buf[20]; // Need to fit "BUTTON #XX"
+    int i;
+
+    if (*joystick_input->variable < 0)
+    {
+        M_StringCopy(buf, "(none)", sizeof(buf));
+    }
+    else
+    {
+        GetGamepadButtonDescription(*joystick_input->variable, buf,
+                                    sizeof(buf));
+    }
+
+    TXT_SetWidgetBG(joystick_input);
+    TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+
+    TXT_DrawString(buf);
+
+    for (i = TXT_UTF8_Strlen(buf); i < JOYSTICK_INPUT_WIDTH; ++i)
+    {
+        TXT_DrawString(" ");
+    }
+}
+
 static void TXT_JoystickInputDestructor(TXT_UNCAST_ARG(joystick_input))
 {
 }
@@ -466,7 +746,7 @@ txt_widget_class_t txt_gamepad_input_class =
 {
     TXT_AlwaysSelectable,
     TXT_JoystickInputSizeCalc,
-    TXT_JoystickInputDrawer,
+    TXT_GamepadInputDrawer,
     TXT_GamepadInputKeyPress,
     TXT_JoystickInputDestructor,
     TXT_GamepadInputMousePress,