Skip to content

Commit

Permalink
Better support for secondary stick in DirectInput driver
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed Aug 26, 2023
1 parent 02382ed commit afd78ea
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 2 deletions.
3 changes: 2 additions & 1 deletion include/allegro5/internal/aintern_wjoydxnu.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,14 @@ typedef struct
int num_sliders; TCHAR name_slider[MAX_SLIDERS][NAME_LEN];
int num_povs; TCHAR name_pov[MAX_POVS][NAME_LEN];
int num_buttons; TCHAR name_button[MAX_BUTTONS][NAME_LEN];
DWORD secondary_stick_axis_one, secondary_stick_axis_two;
} CAPS_AND_NAMES;


/* map a DirectInput axis to an Allegro (stick,axis) pair */
typedef struct
{
int stick, axis;
int stick, axis, j;
} AXIS_MAPPING;


Expand Down
47 changes: 46 additions & 1 deletion src/win/wjoydxnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
#include <mmsystem.h>
#include <process.h>
#include <dinput.h>
#include <utility>

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

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

CAPS_AND_NAMES *can = (CAPS_AND_NAMES *)pvRef;
DWORD j = 0;

if (GUIDTYPE_EQ(__al_GUID_XAxis)) {
can->have_x = true;
Expand All @@ -515,18 +518,22 @@ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO
else if (GUIDTYPE_EQ(__al_GUID_ZAxis)) {
can->have_z = true;
_tcsncpy(can->name_z, lpddoi->tszName, NAME_LEN);
j = DIJOFS_Z;
}
else if (GUIDTYPE_EQ(__al_GUID_RxAxis)) {
can->have_rx = true;
_tcsncpy(can->name_rx, lpddoi->tszName, NAME_LEN);
j = DIJOFS_RX;
}
else if (GUIDTYPE_EQ(__al_GUID_RyAxis)) {
can->have_ry = true;
_tcsncpy(can->name_ry, lpddoi->tszName, NAME_LEN);
j = DIJOFS_RY;
}
else if (GUIDTYPE_EQ(__al_GUID_RzAxis)) {
can->have_rz = true;
_tcsncpy(can->name_rz, lpddoi->tszName, NAME_LEN);
j = DIJOFS_RZ;
}
else if (GUIDTYPE_EQ(__al_GUID_Slider)) {
if (can->num_sliders < MAX_SLIDERS) {
Expand All @@ -550,6 +557,38 @@ static BOOL CALLBACK object_enum_callback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVO
}
}

// The first two axis (not X or Y) are stored and used as the secondary stick.
// The order of the enumeration is assumed to give us the X followed by the Y axis. However,
// an override is provided in the case that the second axis seen here is for Z, in which case that
// will be used as the X axis. This is to fit behaviors seen on specific controllers:
// - PS4 DualShock
// - Stadia
// ...it may be that using `Z` really is common for some input devices.
//
// Solution came from https://www.gamedev.net/forums/topic/613913-directinput-identifying-second-thumbstick/
if (j)
{
if (can->secondary_stick_axis_one == 0)
{
can->secondary_stick_axis_one = j;
_tcsncpy(can->name_rx, lpddoi->tszName, NAME_LEN);
}
else if (can->secondary_stick_axis_two == 0)
{
can->secondary_stick_axis_two = j;
_tcsncpy(can->name_ry, lpddoi->tszName, NAME_LEN);

if (j == DIJOFS_Z)
{
std::swap(can->secondary_stick_axis_one, can->secondary_stick_axis_two);
std::swap(can->name_rx, can->name_ry);
}

can->have_rx = true;
can->have_ry = true;
}
}

return DIENUM_CONTINUE;

#undef GUIDTYPE_EQ
Expand Down Expand Up @@ -640,6 +679,7 @@ static void fill_joystick_info_using_caps_and_names(ALLEGRO_JOYSTICK_DIRECTX *jo
info->stick[N_STICK].axis[N_AXIS].name = ADD_STRING(can->name_rx, default_name_rx);
joy->rx_mapping.stick = N_STICK;
joy->rx_mapping.axis = N_AXIS;
joy->rx_mapping.j = can->secondary_stick_axis_one;
N_AXIS++;
}

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

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

if (dwOfs == DIJOFS_X)
if (joy->rx_mapping.j && joy->rx_mapping.j == dwOfs)
handle_axis_event(joy, &joy->rx_mapping, dwData);
else if (joy->ry_mapping.j && joy->ry_mapping.j == dwOfs)
handle_axis_event(joy, &joy->ry_mapping, dwData);
else if (dwOfs == DIJOFS_X)
handle_axis_event(joy, &joy->x_mapping, dwData);
else if (dwOfs == DIJOFS_Y)
handle_axis_event(joy, &joy->y_mapping, dwData);
Expand Down

0 comments on commit afd78ea

Please sign in to comment.