From 68b32846b85d19a77de9ccc2399d69a0c74f9188 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 15 Jan 2012 15:48:27 -0500 Subject: [PATCH] Fixed bug 1371 - DX joystick axis ordering fix Alex Nankervis 2012-01-15 11:19:45 PST DirectX joysticks can enumerate their axis out of order. This results in some joysticks having vertical/horizontal swapped, for example (vertical axis gets assigned to axis0). Joysticks that I've tested with this problem: XBOX 360 controller, Logitech Extreme 3D Pro. Attached is a diff that fixes this by sorting the DX joystick objects by their data offsets into the DX data structs. This puts the joystick objects into a standard ordering (X axis -> axis0, Y axis -> axis1, and so on). --- src/joystick/windows/SDL_dxjoystick.c | 54 +++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/joystick/windows/SDL_dxjoystick.c b/src/joystick/windows/SDL_dxjoystick.c index a59af75fd..d73f66416 100755 --- a/src/joystick/windows/SDL_dxjoystick.c +++ b/src/joystick/windows/SDL_dxjoystick.c @@ -74,6 +74,7 @@ static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext); static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef); +static void SortDevObjects(SDL_Joystick *joystick); static Uint8 TranslatePOV(DWORD value); static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value); @@ -483,6 +484,10 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick) EnumDevObjectsCallback, joystick, DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); + /* Reorder the input objects. Some devices do not report the X axis as + * the first axis, for example. */ + SortDevObjects(joystick); + dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; dipdw.dwData = INPUT_QSIZE; @@ -504,6 +509,55 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick) return (0); } +/* Sort using the data offset into the DInput struct. + * This gives a reasonable ordering for the inputs. */ +static int +SortDevFunc(const void *a, const void *b) +{ + const input_t *inputA = (const input_t*)a; + const input_t *inputB = (const input_t*)b; + + if (inputA->ofs < inputB->ofs) + return -1; + if (inputA->ofs > inputB->ofs) + return 1; + return 0; +} + +/* Sort the input objects and recalculate the indices for each input. */ +static void +SortDevObjects(SDL_Joystick *joystick) +{ + input_t *inputs = joystick->hwdata->Inputs; + int nButtons = 0; + int nHats = 0; + int nAxis = 0; + int n; + + SDL_qsort(inputs, joystick->hwdata->NumInputs, sizeof(input_t), SortDevFunc); + + for (n = 0; n < joystick->hwdata->NumInputs; n++) + { + switch (inputs[n].type) + { + case BUTTON: + inputs[n].num = nButtons; + nButtons++; + break; + + case HAT: + inputs[n].num = nHats; + nHats++; + break; + + case AXIS: + inputs[n].num = nAxis; + nAxis++; + break; + } + } +} + static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) {