@@ -30,57 +30,22 @@ static void dinput_joypad_poll(void)
3030 int i ;
3131 for (i = 0 ; i < MAX_USERS ; i ++ )
3232 {
33- int j ;
3433 HRESULT ret ;
35- struct dinput_joypad_data * pad = & g_pads [i ];
36- if (!pad || !pad -> joypad )
34+ struct dinput_joypad_data * pad = & g_pads [i ];
35+
36+ if (!pad -> joypad )
3737 continue ;
3838
39- pad -> joy_state .lX = 0 ;
40- pad -> joy_state .lY = 0 ;
41- pad -> joy_state .lRx = 0 ;
42- pad -> joy_state .lRy = 0 ;
43- pad -> joy_state .lRz = 0 ;
44- pad -> joy_state .rglSlider [0 ] = 0 ;
45- pad -> joy_state .rglSlider [1 ] = 0 ;
46- pad -> joy_state .rgdwPOV [0 ] = 0 ;
47- pad -> joy_state .rgdwPOV [1 ] = 0 ;
48- pad -> joy_state .rgdwPOV [2 ] = 0 ;
49- pad -> joy_state .rgdwPOV [3 ] = 0 ;
50- for (j = 0 ; j < 128 ; j ++ )
51- pad -> joy_state .rgbButtons [j ] = 0 ;
52-
53- pad -> joy_state .lVX = 0 ;
54- pad -> joy_state .lVY = 0 ;
55- pad -> joy_state .lVZ = 0 ;
56- pad -> joy_state .lVRx = 0 ;
57- pad -> joy_state .lVRy = 0 ;
58- pad -> joy_state .lVRz = 0 ;
59- pad -> joy_state .rglVSlider [0 ] = 0 ;
60- pad -> joy_state .rglVSlider [1 ] = 0 ;
61- pad -> joy_state .lAX = 0 ;
62- pad -> joy_state .lAY = 0 ;
63- pad -> joy_state .lAZ = 0 ;
64- pad -> joy_state .lARx = 0 ;
65- pad -> joy_state .lARy = 0 ;
66- pad -> joy_state .lARz = 0 ;
67- pad -> joy_state .rglASlider [0 ] = 0 ;
68- pad -> joy_state .rglASlider [1 ] = 0 ;
69- pad -> joy_state .lFX = 0 ;
70- pad -> joy_state .lFY = 0 ;
71- pad -> joy_state .lFZ = 0 ;
72- pad -> joy_state .lFRx = 0 ;
73- pad -> joy_state .lFRy = 0 ;
74- pad -> joy_state .lFRz = 0 ;
75- pad -> joy_state .rglFSlider [0 ] = 0 ;
76- pad -> joy_state .rglFSlider [1 ] = 0 ;
77-
78- /* If this fails, something *really* bad must have happened. */
39+ /* Zero the entire state structure before polling.
40+ * This also correctly zeroes lZ, which the previous
41+ * field-by-field implementation accidentally omitted. */
42+ ZeroMemory (& pad -> joy_state , sizeof (pad -> joy_state ));
43+
44+ /* If Poll() fails, attempt to re-acquire and poll again.
45+ * If that also fails, skip this pad for this frame. */
7946 if (FAILED (IDirectInputDevice8_Poll (pad -> joypad )))
80- if (
81- FAILED (IDirectInputDevice8_Acquire (pad -> joypad ))
82- || FAILED (IDirectInputDevice8_Poll (pad -> joypad ))
83- )
47+ if ( FAILED (IDirectInputDevice8_Acquire (pad -> joypad ))
48+ || FAILED (IDirectInputDevice8_Poll (pad -> joypad )))
8449 continue ;
8550
8651 ret = IDirectInputDevice8_GetDeviceState (pad -> joypad ,
@@ -91,9 +56,52 @@ static void dinput_joypad_poll(void)
9156 }
9257}
9358
59+ /* ---------------------------------------------------------------------------
60+ * dinput_joypad_tchar_to_str
61+ *
62+ * Helper: safely converts a TCHAR string to a heap-allocated char* that
63+ * is valid in both ANSI and Unicode builds.
64+ *
65+ * Under ANSI builds (TCHAR == char) this is equivalent to strdup().
66+ * Under Unicode builds (TCHAR == wchar_t) the original code cast the
67+ * wide pointer directly to char*, silently producing garbage. We use
68+ * WideCharToMultiByte() instead.
69+ *
70+ * Returns NULL on allocation failure; the caller must free() the result.
71+ * --------------------------------------------------------------------------*/
72+ static char * dinput_joypad_tchar_to_str (const TCHAR * src )
73+ {
74+ #ifdef UNICODE
75+ int len ;
76+ char * out ;
77+
78+ if (!src )
79+ return NULL ;
80+
81+ /* Query required buffer size (includes NUL terminator). */
82+ len = WideCharToMultiByte (CP_UTF8 , 0 , src , -1 , NULL , 0 , NULL , NULL );
83+ if (len <= 0 )
84+ return NULL ;
85+
86+ out = (char * )malloc ((size_t )len );
87+ if (!out )
88+ return NULL ;
89+
90+ WideCharToMultiByte (CP_UTF8 , 0 , src , -1 , out , len , NULL , NULL );
91+ return out ;
92+ #else
93+ if (!src )
94+ return NULL ;
95+ return strdup (src );
96+ #endif
97+ }
98+
9499static BOOL CALLBACK enum_joypad_cb (const DIDEVICEINSTANCE * inst , void * p )
95100{
96101 LPDIRECTINPUTDEVICE8 * pad = NULL ;
102+
103+ (void )p ; /* unused */
104+
97105 if (g_joypad_cnt == MAX_USERS )
98106 return DIENUM_STOP ;
99107
@@ -108,32 +116,19 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
108116#endif
109117 return DIENUM_CONTINUE ;
110118
119+ /* Bug fixed: use the safe TCHAR helper instead of a raw cast that
120+ * would produce garbage under Unicode builds. */
111121 g_pads [g_joypad_cnt ].joy_name =
112- strdup (( const char * ) inst -> tszProductName );
122+ dinput_joypad_tchar_to_str ( inst -> tszProductName );
113123 g_pads [g_joypad_cnt ].joy_friendly_name =
114- strdup ((const char * )inst -> tszInstanceName );
115-
116- /* there may be more useful info in the GUID,
117- * so leave this here for a while */
118- #if 0
119- printf ("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}\n" ,
120- inst -> guidProduct .Data1 ,
121- inst -> guidProduct .Data2 ,
122- inst -> guidProduct .Data3 ,
123- inst -> guidProduct .Data4 [0 ],
124- inst -> guidProduct .Data4 [1 ],
125- inst -> guidProduct .Data4 [2 ],
126- inst -> guidProduct .Data4 [3 ],
127- inst -> guidProduct .Data4 [4 ],
128- inst -> guidProduct .Data4 [5 ],
129- inst -> guidProduct .Data4 [6 ],
130- inst -> guidProduct .Data4 [7 ]);
131- #endif
124+ dinput_joypad_tchar_to_str (inst -> tszInstanceName );
132125
133- g_pads [g_joypad_cnt ].vid = inst -> guidProduct .Data1 % 0x10000 ;
134- g_pads [g_joypad_cnt ].pid = inst -> guidProduct .Data1 / 0x10000 ;
126+ /* VID is in the low 16 bits of guidProduct.Data1,
127+ * PID is in the high 16 bits. */
128+ g_pads [g_joypad_cnt ].vid = (int32_t )(inst -> guidProduct .Data1 & 0xFFFFu );
129+ g_pads [g_joypad_cnt ].pid = (int32_t )(inst -> guidProduct .Data1 >> 16 );
135130
136- /* Set data format to simple joystick */
131+ /* Set data format to extended joystick state */
137132 IDirectInputDevice8_SetDataFormat (* pad , & c_dfDIJoystick2 );
138133 IDirectInputDevice8_SetCooperativeLevel (* pad ,
139134 (HWND )video_driver_window_get (),
@@ -159,21 +154,14 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
159154
160155static void * dinput_joypad_init (void * data )
161156{
162- int i ;
163-
164157 if (!dinput_init_context ())
165158 return NULL ;
166-
167- for (i = 0 ; i < MAX_USERS ; ++ i )
168- {
169- g_pads [i ].joy_name = NULL ;
170- g_pads [i ].joy_friendly_name = NULL ;
171- }
172-
159+ /* Zero the pad array; dinput_joypad_destroy() uses memset() on the same
160+ * region, so we stay consistent and avoid partial-initialisation bugs. */
161+ ZeroMemory (g_pads , sizeof (g_pads ));
173162 IDirectInput8_EnumDevices (g_dinput_ctx , DI8DEVCLASS_GAMECTRL ,
174163 enum_joypad_cb , NULL , DIEDFL_ATTACHEDONLY );
175-
176164 return (void * )-1 ;
177165}
178166
179- #endif
167+ #endif /* __DINPUT_JOYPAD_EXCL_INL_H */
0 commit comments