src/joystick/win32/SDL_dxjoystick.c
author Bob Pendleton <bob@pendleton.com>
Fri, 09 Jan 2009 20:43:30 +0000
changeset 3011 8f4ed5ec2b06
parent 2859 99210400e8b9
child 3013 8cc00819c8d6
permissions -rw-r--r--
I ran a global "make indent" it modified the following files.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2009 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #ifdef SDL_JOYSTICK_DINPUT
    25 
    26 /* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
    27  * A. Formiga's WINMM driver. 
    28  *
    29  * Hats and sliders are completely untested; the app I'm writing this for mostly
    30  * doesn't use them and I don't own any joysticks with them. 
    31  *
    32  * We don't bother to use event notification here.  It doesn't seem to work
    33  * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
    34  * let it return 0 events. */
    35 
    36 #include "SDL_error.h"
    37 #include "SDL_events.h"
    38 #include "SDL_joystick.h"
    39 #include "../SDL_sysjoystick.h"
    40 #include "../SDL_joystick_c.h"
    41 #define INITGUID                /* Only set here, if set twice will cause mingw32 to break. */
    42 #include "SDL_dxjoystick_c.h"
    43 
    44 
    45 #ifndef DIDFT_OPTIONAL
    46 #define DIDFT_OPTIONAL		0x80000000
    47 #endif
    48 
    49 
    50 #define INPUT_QSIZE	32      /* Buffer up to 32 input messages */
    51 #define MAX_JOYSTICKS	8
    52 #define AXIS_MIN	-32768  /* minimum value for axis coordinate */
    53 #define AXIS_MAX	32767   /* maximum value for axis coordinate */
    54 #define JOY_AXIS_THRESHOLD	(((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
    55 
    56 /* external variables referenced. */
    57 extern HWND SDL_HelperWindow;
    58 
    59 
    60 /* local variables */
    61 static LPDIRECTINPUT dinput = NULL;
    62 extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
    63                                        LPDIRECTINPUT * ppDI,
    64                                        LPUNKNOWN punkOuter);
    65 static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS];    /* array to hold joystick ID values */
    66 static int SYS_NumJoysticks;
    67 static HINSTANCE DInputDLL = NULL;
    68 
    69 
    70 /* local prototypes */
    71 static void SetDIerror(const char *function, HRESULT code);
    72 static BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE *
    73                                            pdidInstance, VOID * pContext);
    74 static BOOL CALLBACK EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev,
    75                                             LPVOID pvRef);
    76 static Uint8 TranslatePOV(DWORD value);
    77 static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis,
    78                                        Sint16 value);
    79 static int SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat,
    80                                       Uint8 value);
    81 static int SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick,
    82                                          Uint8 button, Uint8 state);
    83 
    84 /* Taken from Wine - Thanks! */
    85 DIOBJECTDATAFORMAT dfDIJoystick2[] = {
    86     {&GUID_XAxis, DIJOFS_X, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    87      0},
    88     {&GUID_YAxis, DIJOFS_Y, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    89      0},
    90     {&GUID_ZAxis, DIJOFS_Z, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    91      0},
    92     {&GUID_RxAxis, DIJOFS_RX, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    93      0},
    94     {&GUID_RyAxis, DIJOFS_RY, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    95      0},
    96     {&GUID_RzAxis, DIJOFS_RZ, DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE,
    97      0},
    98     {&GUID_Slider, DIJOFS_SLIDER(0),
    99      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   100     {&GUID_Slider, DIJOFS_SLIDER(1),
   101      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   102     {&GUID_POV, DIJOFS_POV(0), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE,
   103      0},
   104     {&GUID_POV, DIJOFS_POV(1), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE,
   105      0},
   106     {&GUID_POV, DIJOFS_POV(2), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE,
   107      0},
   108     {&GUID_POV, DIJOFS_POV(3), DIDFT_OPTIONAL | DIDFT_POV | DIDFT_ANYINSTANCE,
   109      0},
   110     {NULL, DIJOFS_BUTTON(0),
   111      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   112     {NULL, DIJOFS_BUTTON(1),
   113      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   114     {NULL, DIJOFS_BUTTON(2),
   115      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   116     {NULL, DIJOFS_BUTTON(3),
   117      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   118     {NULL, DIJOFS_BUTTON(4),
   119      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   120     {NULL, DIJOFS_BUTTON(5),
   121      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   122     {NULL, DIJOFS_BUTTON(6),
   123      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   124     {NULL, DIJOFS_BUTTON(7),
   125      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   126     {NULL, DIJOFS_BUTTON(8),
   127      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   128     {NULL, DIJOFS_BUTTON(9),
   129      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   130     {NULL, DIJOFS_BUTTON(10),
   131      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   132     {NULL, DIJOFS_BUTTON(11),
   133      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   134     {NULL, DIJOFS_BUTTON(12),
   135      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   136     {NULL, DIJOFS_BUTTON(13),
   137      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   138     {NULL, DIJOFS_BUTTON(14),
   139      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   140     {NULL, DIJOFS_BUTTON(15),
   141      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   142     {NULL, DIJOFS_BUTTON(16),
   143      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   144     {NULL, DIJOFS_BUTTON(17),
   145      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   146     {NULL, DIJOFS_BUTTON(18),
   147      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   148     {NULL, DIJOFS_BUTTON(19),
   149      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   150     {NULL, DIJOFS_BUTTON(20),
   151      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   152     {NULL, DIJOFS_BUTTON(21),
   153      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   154     {NULL, DIJOFS_BUTTON(22),
   155      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   156     {NULL, DIJOFS_BUTTON(23),
   157      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   158     {NULL, DIJOFS_BUTTON(24),
   159      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   160     {NULL, DIJOFS_BUTTON(25),
   161      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   162     {NULL, DIJOFS_BUTTON(26),
   163      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   164     {NULL, DIJOFS_BUTTON(27),
   165      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   166     {NULL, DIJOFS_BUTTON(28),
   167      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   168     {NULL, DIJOFS_BUTTON(29),
   169      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   170     {NULL, DIJOFS_BUTTON(30),
   171      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   172     {NULL, DIJOFS_BUTTON(31),
   173      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   174     {NULL, DIJOFS_BUTTON(32),
   175      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   176     {NULL, DIJOFS_BUTTON(33),
   177      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   178     {NULL, DIJOFS_BUTTON(34),
   179      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   180     {NULL, DIJOFS_BUTTON(35),
   181      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   182     {NULL, DIJOFS_BUTTON(36),
   183      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   184     {NULL, DIJOFS_BUTTON(37),
   185      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   186     {NULL, DIJOFS_BUTTON(38),
   187      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   188     {NULL, DIJOFS_BUTTON(39),
   189      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   190     {NULL, DIJOFS_BUTTON(40),
   191      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   192     {NULL, DIJOFS_BUTTON(41),
   193      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   194     {NULL, DIJOFS_BUTTON(42),
   195      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   196     {NULL, DIJOFS_BUTTON(43),
   197      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   198     {NULL, DIJOFS_BUTTON(44),
   199      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   200     {NULL, DIJOFS_BUTTON(45),
   201      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   202     {NULL, DIJOFS_BUTTON(46),
   203      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   204     {NULL, DIJOFS_BUTTON(47),
   205      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   206     {NULL, DIJOFS_BUTTON(48),
   207      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   208     {NULL, DIJOFS_BUTTON(49),
   209      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   210     {NULL, DIJOFS_BUTTON(50),
   211      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   212     {NULL, DIJOFS_BUTTON(51),
   213      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   214     {NULL, DIJOFS_BUTTON(52),
   215      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   216     {NULL, DIJOFS_BUTTON(53),
   217      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   218     {NULL, DIJOFS_BUTTON(54),
   219      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   220     {NULL, DIJOFS_BUTTON(55),
   221      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   222     {NULL, DIJOFS_BUTTON(56),
   223      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   224     {NULL, DIJOFS_BUTTON(57),
   225      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   226     {NULL, DIJOFS_BUTTON(58),
   227      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   228     {NULL, DIJOFS_BUTTON(59),
   229      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   230     {NULL, DIJOFS_BUTTON(60),
   231      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   232     {NULL, DIJOFS_BUTTON(61),
   233      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   234     {NULL, DIJOFS_BUTTON(62),
   235      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   236     {NULL, DIJOFS_BUTTON(63),
   237      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   238     {NULL, DIJOFS_BUTTON(64),
   239      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   240     {NULL, DIJOFS_BUTTON(65),
   241      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   242     {NULL, DIJOFS_BUTTON(66),
   243      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   244     {NULL, DIJOFS_BUTTON(67),
   245      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   246     {NULL, DIJOFS_BUTTON(68),
   247      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   248     {NULL, DIJOFS_BUTTON(69),
   249      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   250     {NULL, DIJOFS_BUTTON(70),
   251      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   252     {NULL, DIJOFS_BUTTON(71),
   253      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   254     {NULL, DIJOFS_BUTTON(72),
   255      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   256     {NULL, DIJOFS_BUTTON(73),
   257      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   258     {NULL, DIJOFS_BUTTON(74),
   259      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   260     {NULL, DIJOFS_BUTTON(75),
   261      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   262     {NULL, DIJOFS_BUTTON(76),
   263      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   264     {NULL, DIJOFS_BUTTON(77),
   265      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   266     {NULL, DIJOFS_BUTTON(78),
   267      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   268     {NULL, DIJOFS_BUTTON(79),
   269      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   270     {NULL, DIJOFS_BUTTON(80),
   271      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   272     {NULL, DIJOFS_BUTTON(81),
   273      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   274     {NULL, DIJOFS_BUTTON(82),
   275      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   276     {NULL, DIJOFS_BUTTON(83),
   277      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   278     {NULL, DIJOFS_BUTTON(84),
   279      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   280     {NULL, DIJOFS_BUTTON(85),
   281      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   282     {NULL, DIJOFS_BUTTON(86),
   283      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   284     {NULL, DIJOFS_BUTTON(87),
   285      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   286     {NULL, DIJOFS_BUTTON(88),
   287      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   288     {NULL, DIJOFS_BUTTON(89),
   289      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   290     {NULL, DIJOFS_BUTTON(90),
   291      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   292     {NULL, DIJOFS_BUTTON(91),
   293      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   294     {NULL, DIJOFS_BUTTON(92),
   295      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   296     {NULL, DIJOFS_BUTTON(93),
   297      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   298     {NULL, DIJOFS_BUTTON(94),
   299      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   300     {NULL, DIJOFS_BUTTON(95),
   301      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   302     {NULL, DIJOFS_BUTTON(96),
   303      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   304     {NULL, DIJOFS_BUTTON(97),
   305      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   306     {NULL, DIJOFS_BUTTON(98),
   307      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   308     {NULL, DIJOFS_BUTTON(99),
   309      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   310     {NULL, DIJOFS_BUTTON(100),
   311      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   312     {NULL, DIJOFS_BUTTON(101),
   313      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   314     {NULL, DIJOFS_BUTTON(102),
   315      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   316     {NULL, DIJOFS_BUTTON(103),
   317      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   318     {NULL, DIJOFS_BUTTON(104),
   319      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   320     {NULL, DIJOFS_BUTTON(105),
   321      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   322     {NULL, DIJOFS_BUTTON(106),
   323      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   324     {NULL, DIJOFS_BUTTON(107),
   325      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   326     {NULL, DIJOFS_BUTTON(108),
   327      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   328     {NULL, DIJOFS_BUTTON(109),
   329      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   330     {NULL, DIJOFS_BUTTON(110),
   331      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   332     {NULL, DIJOFS_BUTTON(111),
   333      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   334     {NULL, DIJOFS_BUTTON(112),
   335      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   336     {NULL, DIJOFS_BUTTON(113),
   337      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   338     {NULL, DIJOFS_BUTTON(114),
   339      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   340     {NULL, DIJOFS_BUTTON(115),
   341      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   342     {NULL, DIJOFS_BUTTON(116),
   343      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   344     {NULL, DIJOFS_BUTTON(117),
   345      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   346     {NULL, DIJOFS_BUTTON(118),
   347      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   348     {NULL, DIJOFS_BUTTON(119),
   349      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   350     {NULL, DIJOFS_BUTTON(120),
   351      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   352     {NULL, DIJOFS_BUTTON(121),
   353      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   354     {NULL, DIJOFS_BUTTON(122),
   355      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   356     {NULL, DIJOFS_BUTTON(123),
   357      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   358     {NULL, DIJOFS_BUTTON(124),
   359      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   360     {NULL, DIJOFS_BUTTON(125),
   361      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   362     {NULL, DIJOFS_BUTTON(126),
   363      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   364     {NULL, DIJOFS_BUTTON(127),
   365      DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_ANYINSTANCE, 0},
   366     {&GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lVX),
   367      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   368     {&GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lVY),
   369      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   370     {&GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lVZ),
   371      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   372     {&GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lVRx),
   373      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   374     {&GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lVRy),
   375      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   376     {&GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lVRz),
   377      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   378     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[0]),
   379      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   380     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglVSlider[1]),
   381      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   382     {&GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lAX),
   383      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   384     {&GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lAY),
   385      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   386     {&GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lAZ),
   387      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   388     {&GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lARx),
   389      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   390     {&GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lARy),
   391      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   392     {&GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lARz),
   393      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   394     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[0]),
   395      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   396     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglASlider[1]),
   397      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   398     {&GUID_XAxis, FIELD_OFFSET(DIJOYSTATE2, lFX),
   399      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   400     {&GUID_YAxis, FIELD_OFFSET(DIJOYSTATE2, lFY),
   401      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   402     {&GUID_ZAxis, FIELD_OFFSET(DIJOYSTATE2, lFZ),
   403      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   404     {&GUID_RxAxis, FIELD_OFFSET(DIJOYSTATE2, lFRx),
   405      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   406     {&GUID_RyAxis, FIELD_OFFSET(DIJOYSTATE2, lFRy),
   407      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   408     {&GUID_RzAxis, FIELD_OFFSET(DIJOYSTATE2, lFRz),
   409      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   410     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[0]),
   411      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   412     {&GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]),
   413      DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0},
   414 };
   415 
   416 const DIDATAFORMAT c_dfDIJoystick2 = {
   417     sizeof(DIDATAFORMAT),
   418     sizeof(DIOBJECTDATAFORMAT),
   419     DIDF_ABSAXIS,
   420     sizeof(DIJOYSTATE2),
   421     SDL_arraysize(dfDIJoystick2),
   422     dfDIJoystick2
   423 };
   424 
   425 
   426 /* Convert a DirectInput return code to a text message */
   427 static void
   428 SetDIerror(const char *function, HRESULT code)
   429 {
   430     /*
   431        SDL_SetError("%s() [%s]: %s", function,
   432        DXGetErrorString9A(code), DXGetErrorDescription9A(code));
   433      */
   434     SDL_SetError("%s() DirectX error %d", function, code);
   435 }
   436 
   437 
   438 /* Function to scan the system for joysticks.
   439  * This function should set SDL_numjoysticks to the number of available
   440  * joysticks.  Joystick 0 should be the system default joystick.
   441  * It should return 0, or -1 on an unrecoverable fatal error.
   442  */
   443 int
   444 SDL_SYS_JoystickInit(void)
   445 {
   446     HRESULT result;
   447     HINSTANCE instance;
   448 
   449     SYS_NumJoysticks = 0;
   450 
   451     result = CoInitialize(NULL);
   452     if (FAILED(result)) {
   453         SetDIerror("CoInitialize", result);
   454         return (-1);
   455     }
   456 
   457     result = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER,
   458                               &IID_IDirectInput, (LPVOID) & dinput);
   459 
   460     if (FAILED(result)) {
   461         SetDIerror("CoCreateInstance", result);
   462         return (-1);
   463     }
   464 
   465     /* Because we used CoCreateInstance, we need to Initialize it, first. */
   466     instance = GetModuleHandle(NULL);
   467     if (instance == NULL) {
   468         SDL_SetError("GetModuleHandle() failed with error code %d.",
   469                      GetLastError());
   470         return (-1);
   471     }
   472     result = IDirectInput_Initialize(dinput, instance, DIRECTINPUT_VERSION);
   473 
   474     if (FAILED(result)) {
   475         SetDIerror("IDirectInput::Initialize", result);
   476         return (-1);
   477     }
   478 
   479     /* Look for joysticks, wheels, head trackers, gamepads, etc.. */
   480     result = IDirectInput_EnumDevices(dinput,
   481                                       DIDEVTYPE_JOYSTICK,
   482                                       EnumJoysticksCallback,
   483                                       NULL, DIEDFL_ATTACHEDONLY);
   484 
   485     return SYS_NumJoysticks;
   486 }
   487 
   488 static BOOL CALLBACK
   489 EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
   490 {
   491     SDL_memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
   492                sizeof(DIDEVICEINSTANCE));
   493     SYS_NumJoysticks++;
   494 
   495     if (SYS_NumJoysticks >= MAX_JOYSTICKS)
   496         return DIENUM_STOP;
   497 
   498     return DIENUM_CONTINUE;
   499 }
   500 
   501 /* Function to get the device-dependent name of a joystick */
   502 const char *
   503 SDL_SYS_JoystickName(int index)
   504 {
   505         /***-> test for invalid index ? */
   506     return (SYS_Joystick[index].tszProductName);
   507 }
   508 
   509 /* Function to open a joystick for use.
   510    The joystick to open is specified by the index field of the joystick.
   511    This should fill the nbuttons and naxes fields of the joystick structure.
   512    It returns 0, or -1 if there is an error.
   513  */
   514 int
   515 SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
   516 {
   517     HRESULT result;
   518     LPDIRECTINPUTDEVICE device;
   519     DIPROPDWORD dipdw;
   520 
   521     SDL_memset(&dipdw, 0, sizeof(DIPROPDWORD));
   522     dipdw.diph.dwSize = sizeof(DIPROPDWORD);
   523     dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
   524 
   525 
   526     /* allocate memory for system specific hardware data */
   527     joystick->hwdata =
   528         (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
   529     if (joystick->hwdata == NULL) {
   530         SDL_OutOfMemory();
   531         return (-1);
   532     }
   533     SDL_memset(joystick->hwdata, 0, sizeof(struct joystick_hwdata));
   534     joystick->hwdata->buffered = 1;
   535     joystick->hwdata->Capabilities.dwSize = sizeof(DIDEVCAPS);
   536 
   537     result =
   538         IDirectInput_CreateDevice(dinput,
   539                                   &SYS_Joystick[joystick->index].guidInstance,
   540                                   &device, NULL);
   541     if (FAILED(result)) {
   542         SetDIerror("IDirectInput::CreateDevice", result);
   543         return (-1);
   544     }
   545 
   546     /* Now get the IDirectInputDevice2 interface, instead. */
   547     result = IDirectInputDevice_QueryInterface(device,
   548                                                &IID_IDirectInputDevice2,
   549                                                (LPVOID *) & joystick->hwdata->
   550                                                InputDevice);
   551     /* We are done with this object.  Use the stored one from now on. */
   552     IDirectInputDevice_Release(device);
   553 
   554     if (FAILED(result)) {
   555         SetDIerror("IDirectInputDevice::QueryInterface", result);
   556         return (-1);
   557     }
   558 
   559     /* Aquire shared access. Exclusive access is required for forces,
   560      * though. */
   561     result =
   562         IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->InputDevice,
   563                                                 SDL_HelperWindow,
   564                                                 DISCL_EXCLUSIVE |
   565                                                 DISCL_BACKGROUND);
   566     if (FAILED(result)) {
   567         SetDIerror("IDirectInputDevice2::SetCooperativeLevel", result);
   568         return (-1);
   569     }
   570 
   571     /* Use the extended data structure: DIJOYSTATE2. */
   572     result =
   573         IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
   574                                           &c_dfDIJoystick2);
   575     if (FAILED(result)) {
   576         SetDIerror("IDirectInputDevice2::SetDataFormat", result);
   577         return (-1);
   578     }
   579 
   580     /* Get device capabilities */
   581     result =
   582         IDirectInputDevice2_GetCapabilities(joystick->hwdata->InputDevice,
   583                                             &joystick->hwdata->Capabilities);
   584 
   585     if (FAILED(result)) {
   586         SetDIerror("IDirectInputDevice2::GetCapabilities", result);
   587         return (-1);
   588     }
   589 
   590     /* Force capable? */
   591     if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
   592 
   593         result = IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
   594 
   595         if (FAILED(result)) {
   596             SetDIerror("IDirectInputDevice2::Acquire", result);
   597             return (-1);
   598         }
   599 
   600         /* reset all accuators. */
   601         result =
   602             IDirectInputDevice2_SendForceFeedbackCommand(joystick->
   603                                                          hwdata->InputDevice,
   604                                                          DISFFC_RESET);
   605 
   606         if (FAILED(result)) {
   607             SetDIerror("IDirectInputDevice2::SendForceFeedbackCommand",
   608                        result);
   609             return (-1);
   610         }
   611 
   612         result = IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
   613 
   614         if (FAILED(result)) {
   615             SetDIerror("IDirectInputDevice2::Unacquire", result);
   616             return (-1);
   617         }
   618 
   619         /* Turn on auto-centering for a ForceFeedback device (until told
   620          * otherwise). */
   621         dipdw.diph.dwObj = 0;
   622         dipdw.diph.dwHow = DIPH_DEVICE;
   623         dipdw.dwData = DIPROPAUTOCENTER_ON;
   624 
   625         result =
   626             IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
   627                                             DIPROP_AUTOCENTER, &dipdw.diph);
   628 
   629         if (FAILED(result)) {
   630             SetDIerror("IDirectInputDevice2::SetProperty", result);
   631             return (-1);
   632         }
   633     }
   634 
   635     /* What buttons and axes does it have? */
   636     IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
   637                                     EnumDevObjectsCallback, joystick,
   638                                     DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
   639 
   640     dipdw.diph.dwObj = 0;
   641     dipdw.diph.dwHow = DIPH_DEVICE;
   642     dipdw.dwData = INPUT_QSIZE;
   643 
   644     /* Set the buffer size */
   645     result =
   646         IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
   647                                         DIPROP_BUFFERSIZE, &dipdw.diph);
   648 
   649     if (result == DI_POLLEDDEVICE) {
   650         /* This device doesn't support buffering, so we're forced
   651          * to use less reliable polling. */
   652         joystick->hwdata->buffered = 0;
   653     } else if (FAILED(result)) {
   654         SetDIerror("IDirectInputDevice2::SetProperty", result);
   655         return (-1);
   656     }
   657 
   658     return (0);
   659 }
   660 
   661 static BOOL CALLBACK
   662 EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
   663 {
   664     SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
   665     HRESULT result;
   666     input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
   667 
   668     in->ofs = dev->dwOfs;
   669 
   670     if (dev->dwType & DIDFT_BUTTON) {
   671         in->type = BUTTON;
   672         in->num = joystick->nbuttons;
   673         joystick->nbuttons++;
   674     } else if (dev->dwType & DIDFT_POV) {
   675         in->type = HAT;
   676         in->num = joystick->nhats;
   677         joystick->nhats++;
   678     } else if (dev->dwType & DIDFT_AXIS) {
   679         DIPROPRANGE diprg;
   680         DIPROPDWORD dilong;
   681 
   682         in->type = AXIS;
   683         in->num = joystick->naxes;
   684 
   685         diprg.diph.dwSize = sizeof(diprg);
   686         diprg.diph.dwHeaderSize = sizeof(diprg.diph);
   687         diprg.diph.dwObj = dev->dwOfs;
   688         diprg.diph.dwHow = DIPH_BYOFFSET;
   689         diprg.lMin = AXIS_MIN;
   690         diprg.lMax = AXIS_MAX;
   691 
   692         result =
   693             IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
   694                                             DIPROP_RANGE, &diprg.diph);
   695         if (FAILED(result)) {
   696             return DIENUM_CONTINUE;     /* don't use this axis */
   697         }
   698 
   699         /* Set dead zone to 0. */
   700         dilong.diph.dwSize = sizeof(dilong);
   701         dilong.diph.dwHeaderSize = sizeof(dilong.diph);
   702         dilong.diph.dwObj = dev->dwOfs;
   703         dilong.diph.dwHow = DIPH_BYOFFSET;
   704         dilong.dwData = 0;
   705         result =
   706             IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
   707                                             DIPROP_DEADZONE, &dilong.diph);
   708         if (FAILED(result)) {
   709             return DIENUM_CONTINUE;     /* don't use this axis */
   710         }
   711 
   712         joystick->naxes++;
   713     } else {
   714         /* not supported at this time */
   715         return DIENUM_CONTINUE;
   716     }
   717 
   718     joystick->hwdata->NumInputs++;
   719 
   720     if (joystick->hwdata->NumInputs == MAX_INPUTS) {
   721         return DIENUM_STOP;     /* too many */
   722     }
   723 
   724     return DIENUM_CONTINUE;
   725 }
   726 
   727 /* Function to update the state of a joystick - called as a device poll.
   728  * This function shouldn't update the joystick structure directly,
   729  * but instead should call SDL_PrivateJoystick*() to deliver events
   730  * and update joystick device state.
   731  */
   732 void
   733 SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
   734 {
   735     DIJOYSTATE2 state;
   736     HRESULT result;
   737     int i;
   738 
   739     result =
   740         IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
   741                                            sizeof(DIJOYSTATE2), &state);
   742     if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
   743         IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
   744         result =
   745             IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
   746                                                sizeof(DIJOYSTATE2), &state);
   747     }
   748 
   749     /* Set each known axis, button and POV. */
   750     for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
   751         const input_t *in = &joystick->hwdata->Inputs[i];
   752 
   753         switch (in->type) {
   754         case AXIS:
   755             switch (in->ofs) {
   756             case DIJOFS_X:
   757                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   758                                             (Sint16) state.lX);
   759                 break;
   760             case DIJOFS_Y:
   761                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   762                                             (Sint16) state.lY);
   763                 break;
   764             case DIJOFS_Z:
   765                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   766                                             (Sint16) state.lZ);
   767                 break;
   768             case DIJOFS_RX:
   769                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   770                                             (Sint16) state.lRx);
   771                 break;
   772             case DIJOFS_RY:
   773                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   774                                             (Sint16) state.lRy);
   775                 break;
   776             case DIJOFS_RZ:
   777                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   778                                             (Sint16) state.lRz);
   779                 break;
   780             case DIJOFS_SLIDER(0):
   781                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   782                                             (Sint16) state.rglSlider[0]);
   783                 break;
   784             case DIJOFS_SLIDER(1):
   785                 SDL_PrivateJoystickAxis_Int(joystick, in->num,
   786                                             (Sint16) state.rglSlider[1]);
   787                 break;
   788             }
   789 
   790             break;
   791 
   792         case BUTTON:
   793             SDL_PrivateJoystickButton_Int(joystick, in->num,
   794                                           (Uint8) (state.rgbButtons[in->ofs -
   795                                                                     DIJOFS_BUTTON0]
   796                                                    ? SDL_PRESSED :
   797                                                    SDL_RELEASED));
   798             break;
   799         case HAT:
   800             {
   801                 Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs -
   802                                                        DIJOFS_POV(0)]);
   803                 SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
   804                 break;
   805             }
   806         }
   807     }
   808 }
   809 
   810 void
   811 SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
   812 {
   813     int i;
   814     HRESULT result;
   815     DWORD numevents;
   816     DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
   817 
   818     numevents = INPUT_QSIZE;
   819     result =
   820         IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
   821                                           sizeof(DIDEVICEOBJECTDATA), evtbuf,
   822                                           &numevents, 0);
   823     if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
   824         IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
   825         result =
   826             IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
   827                                               sizeof(DIDEVICEOBJECTDATA),
   828                                               evtbuf, &numevents, 0);
   829     }
   830 
   831     /* Handle the events or punt */
   832     if (FAILED(result))
   833         return;
   834 
   835     for (i = 0; i < (int) numevents; ++i) {
   836         int j;
   837 
   838         for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
   839             const input_t *in = &joystick->hwdata->Inputs[j];
   840 
   841             if (evtbuf[i].dwOfs != in->ofs)
   842                 continue;
   843 
   844             switch (in->type) {
   845             case AXIS:
   846                 SDL_PrivateJoystickAxis(joystick, in->num,
   847                                         (Sint16) evtbuf[i].dwData);
   848                 break;
   849             case BUTTON:
   850                 SDL_PrivateJoystickButton(joystick, in->num,
   851                                           (Uint8) (evtbuf[i].dwData ?
   852                                                    SDL_PRESSED :
   853                                                    SDL_RELEASED));
   854                 break;
   855             case HAT:
   856                 {
   857                     Uint8 pos = TranslatePOV(evtbuf[i].dwData);
   858                     SDL_PrivateJoystickHat(joystick, in->num, pos);
   859                 }
   860             }
   861         }
   862     }
   863 }
   864 
   865 
   866 static Uint8
   867 TranslatePOV(DWORD value)
   868 {
   869     const int HAT_VALS[] = {
   870         SDL_HAT_UP,
   871         SDL_HAT_UP | SDL_HAT_RIGHT,
   872         SDL_HAT_RIGHT,
   873         SDL_HAT_DOWN | SDL_HAT_RIGHT,
   874         SDL_HAT_DOWN,
   875         SDL_HAT_DOWN | SDL_HAT_LEFT,
   876         SDL_HAT_LEFT,
   877         SDL_HAT_UP | SDL_HAT_LEFT
   878     };
   879 
   880     if (LOWORD(value) == 0xFFFF)
   881         return SDL_HAT_CENTERED;
   882 
   883     /* Round the value up: */
   884     value += 4500 / 2;
   885     value %= 36000;
   886     value /= 4500;
   887 
   888     if (value >= 8)
   889         return SDL_HAT_CENTERED;        /* shouldn't happen */
   890 
   891     return HAT_VALS[value];
   892 }
   893 
   894 /* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to
   895  * do it. */
   896 static int
   897 SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
   898 {
   899     if (joystick->axes[axis] != value)
   900         return SDL_PrivateJoystickAxis(joystick, axis, value);
   901     return 0;
   902 }
   903 
   904 static int
   905 SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
   906 {
   907     if (joystick->hats[hat] != value)
   908         return SDL_PrivateJoystickHat(joystick, hat, value);
   909     return 0;
   910 }
   911 
   912 static int
   913 SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick, Uint8 button,
   914                               Uint8 state)
   915 {
   916     if (joystick->buttons[button] != state)
   917         return SDL_PrivateJoystickButton(joystick, button, state);
   918     return 0;
   919 }
   920 
   921 void
   922 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   923 {
   924     HRESULT result;
   925 
   926     result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
   927     if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
   928         IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
   929         IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
   930     }
   931 
   932     if (joystick->hwdata->buffered)
   933         SDL_SYS_JoystickUpdate_Buffered(joystick);
   934     else
   935         SDL_SYS_JoystickUpdate_Polled(joystick);
   936 }
   937 
   938 /* Function to close a joystick after use */
   939 void
   940 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   941 {
   942     IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
   943     IDirectInputDevice2_Release(joystick->hwdata->InputDevice);
   944 
   945     if (joystick->hwdata != NULL) {
   946         /* free system specific hardware data */
   947         SDL_free(joystick->hwdata);
   948     }
   949 }
   950 
   951 /* Function to perform any system-specific joystick related cleanup */
   952 void
   953 SDL_SYS_JoystickQuit(void)
   954 {
   955     IDirectInput_Release(dinput);
   956     dinput = NULL;
   957 }
   958 
   959 #endif /* SDL_JOYSTICK_DINPUT */
   960 /* vi: set ts=4 sw=4 expandtab: */