Skip to content

Commit afd78ea

Browse files
committed
Better support for secondary stick in DirectInput driver
1 parent 02382ed commit afd78ea

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

include/allegro5/internal/aintern_wjoydxnu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@ typedef struct
5151
int num_sliders; TCHAR name_slider[MAX_SLIDERS][NAME_LEN];
5252
int num_povs; TCHAR name_pov[MAX_POVS][NAME_LEN];
5353
int num_buttons; TCHAR name_button[MAX_BUTTONS][NAME_LEN];
54+
DWORD secondary_stick_axis_one, secondary_stick_axis_two;
5455
} CAPS_AND_NAMES;
5556

5657

5758
/* map a DirectInput axis to an Allegro (stick,axis) pair */
5859
typedef struct
5960
{
60-
int stick, axis;
61+
int stick, axis, j;
6162
} AXIS_MAPPING;
6263

6364

src/win/wjoydxnu.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include <mmsystem.h>
8080
#include <process.h>
8181
#include <dinput.h>
82+
#include <utility>
8283

8384
/* We need XInput detection if we actually compile the XInput driver in.
8485
*/
@@ -146,6 +147,7 @@ ALLEGRO_JOYSTICK_DRIVER _al_joydrv_directx =
146147
#define DEFINE_PRIVATE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
147148
static const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
148149

150+
DEFINE_PRIVATE_GUID(__al_GUID_None, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
149151
DEFINE_PRIVATE_GUID(__al_GUID_XAxis, 0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
150152
DEFINE_PRIVATE_GUID(__al_GUID_YAxis, 0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
151153
DEFINE_PRIVATE_GUID(__al_GUID_ZAxis, 0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
@@ -503,6 +505,7 @@ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO
503505
#define GUIDTYPE_EQ(x) GUID_EQUAL(lpddoi->guidType, x)
504506

505507
CAPS_AND_NAMES *can = (CAPS_AND_NAMES *)pvRef;
508+
DWORD j = 0;
506509

507510
if (GUIDTYPE_EQ(__al_GUID_XAxis)) {
508511
can->have_x = true;
@@ -515,18 +518,22 @@ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO
515518
else if (GUIDTYPE_EQ(__al_GUID_ZAxis)) {
516519
can->have_z = true;
517520
_tcsncpy(can->name_z, lpddoi->tszName, NAME_LEN);
521+
j = DIJOFS_Z;
518522
}
519523
else if (GUIDTYPE_EQ(__al_GUID_RxAxis)) {
520524
can->have_rx = true;
521525
_tcsncpy(can->name_rx, lpddoi->tszName, NAME_LEN);
526+
j = DIJOFS_RX;
522527
}
523528
else if (GUIDTYPE_EQ(__al_GUID_RyAxis)) {
524529
can->have_ry = true;
525530
_tcsncpy(can->name_ry, lpddoi->tszName, NAME_LEN);
531+
j = DIJOFS_RY;
526532
}
527533
else if (GUIDTYPE_EQ(__al_GUID_RzAxis)) {
528534
can->have_rz = true;
529535
_tcsncpy(can->name_rz, lpddoi->tszName, NAME_LEN);
536+
j = DIJOFS_RZ;
530537
}
531538
else if (GUIDTYPE_EQ(__al_GUID_Slider)) {
532539
if (can->num_sliders < MAX_SLIDERS) {
@@ -550,6 +557,38 @@ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO
550557
}
551558
}
552559

560+
// The first two axis (not X or Y) are stored and used as the secondary stick.
561+
// The order of the enumeration is assumed to give us the X followed by the Y axis. However,
562+
// an override is provided in the case that the second axis seen here is for Z, in which case that
563+
// will be used as the X axis. This is to fit behaviors seen on specific controllers:
564+
// - PS4 DualShock
565+
// - Stadia
566+
// ...it may be that using `Z` really is common for some input devices.
567+
//
568+
// Solution came from https://www.gamedev.net/forums/topic/613913-directinput-identifying-second-thumbstick/
569+
if (j)
570+
{
571+
if (can->secondary_stick_axis_one == 0)
572+
{
573+
can->secondary_stick_axis_one = j;
574+
_tcsncpy(can->name_rx, lpddoi->tszName, NAME_LEN);
575+
}
576+
else if (can->secondary_stick_axis_two == 0)
577+
{
578+
can->secondary_stick_axis_two = j;
579+
_tcsncpy(can->name_ry, lpddoi->tszName, NAME_LEN);
580+
581+
if (j == DIJOFS_Z)
582+
{
583+
std::swap(can->secondary_stick_axis_one, can->secondary_stick_axis_two);
584+
std::swap(can->name_rx, can->name_ry);
585+
}
586+
587+
can->have_rx = true;
588+
can->have_ry = true;
589+
}
590+
}
591+
553592
return DIENUM_CONTINUE;
554593

555594
#undef GUIDTYPE_EQ
@@ -640,6 +679,7 @@ static void fill_joystick_info_using_caps_and_names(ALLEGRO_JOYSTICK_DIRECTX *jo
640679
info->stick[N_STICK].axis[N_AXIS].name = ADD_STRING(can->name_rx, default_name_rx);
641680
joy->rx_mapping.stick = N_STICK;
642681
joy->rx_mapping.axis = N_AXIS;
682+
joy->rx_mapping.j = can->secondary_stick_axis_one;
643683
N_AXIS++;
644684
}
645685

@@ -648,6 +688,7 @@ static void fill_joystick_info_using_caps_and_names(ALLEGRO_JOYSTICK_DIRECTX *jo
648688
info->stick[N_STICK].axis[N_AXIS].name = ADD_STRING(can->name_ry, default_name_ry);
649689
joy->ry_mapping.stick = N_STICK;
650690
joy->ry_mapping.axis = N_AXIS;
691+
joy->ry_mapping.j = can->secondary_stick_axis_two;
651692
N_AXIS++;
652693
}
653694

@@ -1491,7 +1532,11 @@ static void update_joystick(ALLEGRO_JOYSTICK_DIRECTX *joy)
14911532
const int dwOfs = item->dwOfs;
14921533
const DWORD dwData = item->dwData;
14931534

1494-
if (dwOfs == DIJOFS_X)
1535+
if (joy->rx_mapping.j && joy->rx_mapping.j == dwOfs)
1536+
handle_axis_event(joy, &joy->rx_mapping, dwData);
1537+
else if (joy->ry_mapping.j && joy->ry_mapping.j == dwOfs)
1538+
handle_axis_event(joy, &joy->ry_mapping, dwData);
1539+
else if (dwOfs == DIJOFS_X)
14951540
handle_axis_event(joy, &joy->x_mapping, dwData);
14961541
else if (dwOfs == DIJOFS_Y)
14971542
handle_axis_event(joy, &joy->y_mapping, dwData);

0 commit comments

Comments
 (0)