Mercurial > sdl-ios-xcode
annotate src/joystick/os2/SDL_sysjoystick.c @ 4384:6800e2560310 SDL-1.2
Fixed bugs #882 and 865, re-opening bug #634
Ronald Lamprecht to SDL
Hi,
Sam Lantinga wrote:
The problem with that fix is that it breaks IME events again. Maybe
we can handle keyboard events differently to prevent this issue?
Spending an hour reading MSDN, analysing SDL and another hour testing the reality on XP I am really wondering how patch r4990 could have ever worked in any situation. It's main effect is to break the unicode translation and causing spurious activation events!
Why does TranslateMessage(&msg) nothing useful? Simply because it does not affect "msg" at all! All keyboard events are dispatched without the slightest change (see MSDN). TranslateMessage() just appends additional WM_CHAR, WM_DEADCHAR, WM_SYSCHAR, WM_SYSDEADCHAR event messages to the queue. But I could not find any SDL event handling routine that catches these events and transforms them to proper SDL keyevents while eliminating the corresponding WM_KEYDOWN, etc. events. Thus any IME input like the '@' generated by "Alt + 6(Numpad) + 4(Numpad)" is simply lost.
But the situation is even worse! Up to r4990 the TranslateKey()/ToUnicode() calls did evaluate dead keys and did deliver proper key events for subsequent key strokes like '´' + 'e' resulting in 'é'. ToUnicode() needs proper key state informations to be able to handle these substitutions. But unfortunatly TranslateMessage() needs the same state information and eats it up while generating the WM_CHAR messages :-( Thus the current 1.2.14 breakes the partial IME support of previous releases, too.
The key state race condition between ToUnicode() and TranslateMessage() requires to avoid any ToUnicode() usage for receiving proper WM_CHAR, etc. messages generated by TranslateMessage(). (Yes - the '@' and 'é' appear as WM_CHAR messages when unicode is switched off).
The spurious SDL activation events are *not* caused by additional WM_ACTIVATE Windows messages! Besides DIB_HandleMessage() SDL_PrivateAppActive() is called by another source which I am not yet aware of - any hints?
Thus I do strongly recommend the deletion of the TranslateMessage(&msg) call as a quick fix.
A proper support of unicode and IME requires a clean SDL keyboard input concept first. Which SDL keyboards events should be transmitted to the app when the user presses '´' + 'e' ? Within the current unicode handling the first key stroke is hidden. Even though ToUnicode() delivers the proper key SDL does ignore it in TranslateKey(). Just the composed key event is transmitted to the app. That is what you expect for text input, but the app can no longer use keys like '^' as a key button because it will never receive a key event for it!
With a given concept it seems to be necessary to regenerate SDL key events out of the WM_CHAR, etc. events and to drop all related direct WM_KEYDOWN, etc. events while the remaining basic WM_KEYDOWN, etc. events would still have to result in SDL key events.
Anyway the source of the spurious WM_ACTIVATE should be located to avoid future trouble.
Greets,
Ronald
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 17 Nov 2009 04:59:13 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
1190 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
1190 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
1190 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
1190 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
13 Lesser General Public License for more details. |
1190 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1190
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
1190 | 18 |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
22 #include "SDL_config.h" |
1190 | 23 |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1442
diff
changeset
|
24 #ifdef SDL_JOYSTICK_OS2 |
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1442
diff
changeset
|
25 |
1190 | 26 /* OS/2 Joystick driver, contributed by Daniel Caetano */ |
27 | |
28 #include <mem.h> | |
29 | |
30 #define INCL_DOSDEVICES | |
31 #define INCL_DOSDEVIOCTL | |
32 #define INCL_DOSMEMMGR | |
33 #include <os2.h> | |
34 #include "joyos2.h" | |
35 | |
36 #include "SDL_joystick.h" | |
1442
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
37 #include "SDL_events.h" |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
38 #include "../SDL_sysjoystick.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
39 #include "../SDL_joystick_c.h" |
1190 | 40 |
41 HFILE hJoyPort = NULL; /* Joystick GAME$ Port Address */ | |
42 #define MAX_JOYSTICKS 2 /* Maximum of two joysticks */ | |
43 #define MAX_AXES 4 /* each joystick can have up to 4 axes */ | |
44 #define MAX_BUTTONS 8 /* 8 buttons */ | |
45 #define MAX_HATS 0 /* 0 hats - OS/2 doesn't support it */ | |
46 #define MAX_BALLS 0 /* and 0 balls - OS/2 doesn't support it */ | |
47 #define AXIS_MIN -32768 /* minimum value for axes coordinate */ | |
48 #define AXIS_MAX 32767 /* maximum value for axes coordinate */ | |
49 #define MAX_JOYNAME 128 /* Joystick name may have 128 characters */ | |
50 /* limit axes to 256 possible positions to filter out noise */ | |
51 #define JOY_AXIS_THRESHOLD (((AXIS_MAX)-(AXIS_MIN))/256) | |
52 /* Calc Button Flag for buttons A to D */ | |
53 #define JOY_BUTTON_FLAG(n) (1<<n) | |
54 | |
55 /* Joystick data... hold information about detected devices */ | |
1442
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
56 typedef struct SYS_JoyData_s |
1190 | 57 { |
58 Sint8 id; // Device ID | |
59 char szDeviceName[MAX_JOYNAME]; // Device Name | |
60 char axes; // Number of axes | |
61 char buttons; // Number of buttons | |
62 char hats; // Number of buttons | |
63 char balls; // Number of buttons | |
64 int axes_min[MAX_AXES]; // minimum callibration value for axes | |
65 int axes_med[MAX_AXES]; // medium callibration value for axes | |
66 int axes_max[MAX_AXES]; // maximum callibration value for axes | |
67 int buttoncalc[4]; // Used for buttons 5, 6, 7 and 8. | |
1442
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
68 } SYS_JoyData_t, *SYS_JoyData_p; |
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
69 |
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
70 SYS_JoyData_t SYS_JoyData[MAX_JOYSTICKS]; |
1190 | 71 |
72 | |
73 /* Structure used to convert data from OS/2 driver format to SDL format */ | |
74 struct joystick_hwdata | |
75 { | |
76 Sint8 id; | |
77 struct _transaxes | |
78 { | |
79 int offset; /* Center Offset */ | |
80 float scale1; /* Center to left/up Scale */ | |
81 float scale2; /* Center to right/down Scale */ | |
82 } transaxes[MAX_AXES]; | |
83 }; | |
84 | |
85 /* Structure used to get values from Joystick Environment Variable */ | |
86 struct _joycfg | |
87 { | |
88 char name[MAX_JOYNAME]; | |
89 unsigned int axes; | |
90 unsigned int buttons; | |
91 unsigned int hats; | |
92 unsigned int balls; | |
93 }; | |
94 | |
95 /* OS/2 Implementation Function Prototypes */ | |
96 APIRET joyPortOpen(HFILE * hGame); | |
97 void joyPortClose(HFILE * hGame); | |
98 int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars); | |
99 int joyGetEnv(struct _joycfg * joydata); | |
100 | |
101 | |
102 | |
103 /************************************************************************/ | |
104 /* Function to scan the system for joysticks. */ | |
105 /* This function should set SDL_numjoysticks to the number of available */ | |
106 /* joysticks. Joystick 0 should be the system default joystick. */ | |
107 /* It should return 0, or -1 on an unrecoverable fatal error. */ | |
108 /************************************************************************/ | |
109 int SDL_SYS_JoystickInit(void) | |
110 { | |
111 APIRET rc; /* Generic OS/2 return code */ | |
112 GAME_PORT_STRUCT stJoyStatus; /* Joystick Status Structure */ | |
113 GAME_PARM_STRUCT stGameParms; /* Joystick Parameter Structure */ | |
114 GAME_CALIB_STRUCT stGameCalib; /* Calibration Struct */ | |
115 ULONG ulDataLen; /* Size of data */ | |
116 ULONG ulLastTick; /* Tick Counter for timing operations */ | |
117 Uint8 maxdevs; /* Maximum number of devices */ | |
118 Uint8 numdevs; /* Number of present devices */ | |
119 Uint8 maxbut; /* Maximum number of buttons... */ | |
120 Uint8 i; /* Temporary Count Vars */ | |
121 Uint8 ucNewJoystickMask; /* Mask for Joystick Detection */ | |
122 struct _joycfg joycfg; /* Joy Configuration from envvar */ | |
123 | |
124 | |
125 /* Get Max Number of Devices */ | |
126 rc = joyPortOpen(&hJoyPort); /* Open GAME$ port */ | |
127 if (rc != 0) return 0; /* Cannot open... report no joystick */ | |
128 ulDataLen = sizeof(stGameParms); | |
129 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_PARMS, | |
130 NULL, 0, NULL, &stGameParms, ulDataLen, &ulDataLen); /* Ask device info */ | |
131 if (rc != 0) | |
132 { | |
133 joyPortClose(&hJoyPort); | |
134 SDL_SetError("Could not read joystick port."); | |
135 return -1; | |
136 } | |
137 if (stGameParms.useA != 0) maxdevs++; | |
138 if (stGameParms.useB != 0) maxdevs++; | |
139 if ( maxdevs > MAX_JOYSTICKS ) maxdevs = MAX_JOYSTICKS; | |
140 | |
141 /* Defines min/max axes values (callibration) */ | |
142 ulDataLen = sizeof(stGameCalib); | |
143 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_CALIB, | |
144 NULL, 0, NULL, &stGameCalib, ulDataLen, &ulDataLen); | |
145 if (rc != 0) | |
146 { | |
147 joyPortClose(&hJoyPort); | |
148 SDL_SetError("Could not read callibration data."); | |
149 return -1; | |
150 } | |
151 | |
152 /* Determine how many joysticks are active */ | |
153 numdevs = 0; /* Points no device */ | |
154 ucNewJoystickMask = 0x0F; /* read all 4 joystick axis */ | |
155 ulDataLen = sizeof(ucNewJoystickMask); | |
156 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_RESET, | |
157 &ucNewJoystickMask, ulDataLen, &ulDataLen, NULL, 0, NULL); | |
158 if (rc == 0) | |
159 { | |
160 ulDataLen = sizeof(stJoyStatus); | |
161 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET, | |
162 NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen); | |
163 if (rc != 0) | |
164 { | |
165 joyPortClose(&hJoyPort); | |
166 SDL_SetError("Could not call joystick port."); | |
167 return -1; | |
168 } | |
169 ulLastTick = stJoyStatus.ulJs_Ticks; | |
170 while (stJoyStatus.ulJs_Ticks == ulLastTick) | |
171 { | |
172 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_PORT_GET, | |
173 NULL, 0, NULL, &stJoyStatus, ulDataLen, &ulDataLen); | |
174 } | |
175 if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) numdevs++; | |
176 if (((stJoyStatus.ucJs_JoyStickMask >> 2) & 0x03) > 0) numdevs++; | |
177 } | |
178 | |
179 if (numdevs>maxdevs) numdevs=maxdevs; | |
180 | |
181 /* If *any* joystick was detected... Let's configure SDL for them */ | |
182 if (numdevs > 0) | |
183 { | |
184 /* Verify if it is a "user defined" joystick */ | |
185 if (joyGetEnv(&joycfg)) | |
186 { | |
187 GAME_3POS_STRUCT * axis[4]; | |
188 axis[0] = &stGameCalib.Ax; | |
189 axis[1] = &stGameCalib.Ay; | |
190 axis[2] = &stGameCalib.Bx; | |
191 axis[3] = &stGameCalib.By; | |
192 /* Say it has one device only (user defined is always one device only) */ | |
193 numdevs = 1; | |
194 /* Define Device 0 as... */ | |
195 SYS_JoyData[0].id=0; | |
196 /* Define Number of Axes... up to 4 */ | |
197 if (joycfg.axes>MAX_AXES) joycfg.axes = MAX_AXES; | |
198 SYS_JoyData[0].axes = joycfg.axes; | |
199 /* Define number of buttons... 8 if 2 axes, 6 if 3 axes and 4 if 4 axes */ | |
200 maxbut = MAX_BUTTONS; | |
201 if (joycfg.axes>2) maxbut-=((joycfg.axes-2)<<1); /* MAX_BUTTONS - 2*(axes-2) */ | |
202 if (joycfg.buttons > maxbut) joycfg.buttons = maxbut; | |
203 SYS_JoyData[0].buttons = joycfg.buttons; | |
204 /* Define number of hats */ | |
205 if (joycfg.hats > MAX_HATS) joycfg.hats = MAX_HATS; | |
206 SYS_JoyData[0].hats = joycfg.hats; | |
207 /* Define number of balls */ | |
208 if (joycfg.balls > MAX_BALLS) joycfg.balls = MAX_BALLS; | |
209 SYS_JoyData[0].balls = joycfg.balls; | |
210 /* Initialize Axes Callibration Values */ | |
211 for (i=0; i<joycfg.axes; i++) | |
212 { | |
213 SYS_JoyData[0].axes_min[i] = axis[i]->lower; | |
214 SYS_JoyData[0].axes_med[i] = axis[i]->centre; | |
215 SYS_JoyData[0].axes_max[i] = axis[i]->upper; | |
216 } | |
217 /* Initialize Buttons 5 to 8 structures */ | |
218 if (joycfg.buttons>=5) SYS_JoyData[0].buttoncalc[0]=((axis[2]->lower+axis[3]->centre)>>1); | |
219 if (joycfg.buttons>=6) SYS_JoyData[0].buttoncalc[1]=((axis[3]->lower+axis[3]->centre)>>1); | |
220 if (joycfg.buttons>=7) SYS_JoyData[0].buttoncalc[2]=((axis[2]->upper+axis[3]->centre)>>1); | |
221 if (joycfg.buttons>=8) SYS_JoyData[0].buttoncalc[3]=((axis[3]->upper+axis[3]->centre)>>1); | |
222 /* Intialize Joystick Name */ | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1375
diff
changeset
|
223 SDL_strlcpy (SYS_JoyData[0].szDeviceName,joycfg.name, SDL_arraysize(SYS_JoyData[0].szDeviceName)); |
1190 | 224 } |
225 /* Default Init ... autoconfig */ | |
226 else | |
227 { | |
228 /* if two devices were detected... configure as Joy1 4 axis and Joy2 2 axis */ | |
229 if (numdevs==2) | |
230 { | |
231 /* Define Device 0 as 4 axes, 4 buttons */ | |
232 SYS_JoyData[0].id=0; | |
233 SYS_JoyData[0].axes = 4; | |
234 SYS_JoyData[0].buttons = 4; | |
235 SYS_JoyData[0].hats = 0; | |
236 SYS_JoyData[0].balls = 0; | |
237 SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower; | |
238 SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre; | |
239 SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper; | |
240 SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower; | |
241 SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre; | |
242 SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper; | |
243 SYS_JoyData[0].axes_min[2] = stGameCalib.Bx.lower; | |
244 SYS_JoyData[0].axes_med[2] = stGameCalib.Bx.centre; | |
245 SYS_JoyData[0].axes_max[2] = stGameCalib.Bx.upper; | |
246 SYS_JoyData[0].axes_min[3] = stGameCalib.By.lower; | |
247 SYS_JoyData[0].axes_med[3] = stGameCalib.By.centre; | |
248 SYS_JoyData[0].axes_max[3] = stGameCalib.By.upper; | |
249 /* Define Device 1 as 2 axes, 2 buttons */ | |
250 SYS_JoyData[1].id=1; | |
251 SYS_JoyData[1].axes = 2; | |
252 SYS_JoyData[1].buttons = 2; | |
253 SYS_JoyData[1].hats = 0; | |
254 SYS_JoyData[1].balls = 0; | |
255 SYS_JoyData[1].axes_min[0] = stGameCalib.Bx.lower; | |
256 SYS_JoyData[1].axes_med[0] = stGameCalib.Bx.centre; | |
257 SYS_JoyData[1].axes_max[0] = stGameCalib.Bx.upper; | |
258 SYS_JoyData[1].axes_min[1] = stGameCalib.By.lower; | |
259 SYS_JoyData[1].axes_med[1] = stGameCalib.By.centre; | |
260 SYS_JoyData[1].axes_max[1] = stGameCalib.By.upper; | |
261 } | |
262 /* One joystick only? */ | |
263 else | |
264 { | |
265 /* If it is joystick A... */ | |
266 if ((stJoyStatus.ucJs_JoyStickMask & 0x03) > 0) | |
267 { | |
268 /* Define Device 0 as 2 axes, 4 buttons */ | |
269 SYS_JoyData[0].id=0; | |
270 SYS_JoyData[0].axes = 2; | |
271 SYS_JoyData[0].buttons = 4; | |
272 SYS_JoyData[0].hats = 0; | |
273 SYS_JoyData[0].balls = 0; | |
274 SYS_JoyData[0].axes_min[0] = stGameCalib.Ax.lower; | |
275 SYS_JoyData[0].axes_med[0] = stGameCalib.Ax.centre; | |
276 SYS_JoyData[0].axes_max[0] = stGameCalib.Ax.upper; | |
277 SYS_JoyData[0].axes_min[1] = stGameCalib.Ay.lower; | |
278 SYS_JoyData[0].axes_med[1] = stGameCalib.Ay.centre; | |
279 SYS_JoyData[0].axes_max[1] = stGameCalib.Ay.upper; | |
280 } | |
281 /* If not, it is joystick B */ | |
282 else | |
283 { | |
284 /* Define Device 1 as 2 axes, 2 buttons */ | |
285 SYS_JoyData[0].id=1; | |
286 SYS_JoyData[0].axes = 2; | |
287 SYS_JoyData[0].buttons = 2; | |
288 SYS_JoyData[0].hats = 0; | |
289 SYS_JoyData[0].balls = 0; | |
290 SYS_JoyData[0].axes_min[0] = stGameCalib.Bx.lower; | |
291 SYS_JoyData[0].axes_med[0] = stGameCalib.Bx.centre; | |
292 SYS_JoyData[0].axes_max[0] = stGameCalib.Bx.upper; | |
293 SYS_JoyData[0].axes_min[1] = stGameCalib.By.lower; | |
294 SYS_JoyData[0].axes_med[1] = stGameCalib.By.centre; | |
295 SYS_JoyData[0].axes_max[1] = stGameCalib.By.upper; | |
296 } | |
297 } | |
298 /* Hack to define Joystick Port Names */ | |
299 if ( numdevs > maxdevs ) numdevs = maxdevs; | |
1442
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
300 for (i=0; i<numdevs; i++) |
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
301 SDL_snprintf (SYS_JoyData[i].szDeviceName, SDL_arraysize(SYS_JoyData[i].szDeviceName), "Default Joystick %c", 'A'+SYS_JoyData[i].id); |
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
302 |
e3242177fe4a
Updated OS/2 build, yay!
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
303 } |
1190 | 304 } |
305 /* Return the number of devices found */ | |
306 return(numdevs); | |
307 } | |
308 | |
309 | |
310 /***********************************************************/ | |
311 /* Function to get the device-dependent name of a joystick */ | |
312 /***********************************************************/ | |
313 const char *SDL_SYS_JoystickName(int index) | |
314 { | |
315 /* No need to verify if device exists, already done in upper layer */ | |
316 return(SYS_JoyData[index].szDeviceName); | |
317 } | |
318 | |
319 | |
320 | |
321 /******************************************************************************/ | |
322 /* Function to open a joystick for use. */ | |
323 /* The joystick to open is specified by the index field of the joystick. */ | |
324 /* This should fill the nbuttons and naxes fields of the joystick structure. */ | |
325 /* It returns 0, or -1 if there is an error. */ | |
326 /******************************************************************************/ | |
327 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) | |
328 { | |
329 int index; /* Index shortcut for index in joystick structure */ | |
330 int i; /* Generic Counter */ | |
331 | |
332 /* allocate memory for system specific hardware data */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
333 joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(*joystick->hwdata)); |
1190 | 334 if (joystick->hwdata == NULL) |
335 { | |
336 SDL_OutOfMemory(); | |
337 return(-1); | |
338 } | |
339 /* Reset Hardware Data */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
340 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); |
1190 | 341 |
342 /* ShortCut Pointer */ | |
343 index = joystick->index; | |
344 /* Define offsets and scales for all axes */ | |
345 joystick->hwdata->id = SYS_JoyData[index].id; | |
346 for ( i = 0; i < MAX_AXES; ++i ) | |
347 { | |
348 if ( (i<2) || i < SYS_JoyData[index].axes ) | |
349 { | |
350 joystick->hwdata->transaxes[i].offset = ((AXIS_MAX + AXIS_MIN)>>1) - SYS_JoyData[index].axes_med[i]; | |
351 //joystick->hwdata->transaxes[i].scale = (float)((AXIS_MAX - AXIS_MIN)/(SYS_JoyData[index].axes_max[i]-SYS_JoyData[index].axes_min[i])); | |
352 joystick->hwdata->transaxes[i].scale1 = (float)abs((AXIS_MIN/SYS_JoyData[index].axes_min[i])); | |
353 joystick->hwdata->transaxes[i].scale2 = (float)abs((AXIS_MAX/SYS_JoyData[index].axes_max[i])); | |
354 } | |
355 else | |
356 { | |
357 joystick->hwdata->transaxes[i].offset = 0; | |
358 //joystick->hwdata->transaxes[i].scale = 1.0; /* Just in case */ | |
359 joystick->hwdata->transaxes[i].scale1 = 1.0; /* Just in case */ | |
360 joystick->hwdata->transaxes[i].scale2 = 1.0; /* Just in case */ | |
361 } | |
362 } | |
363 | |
364 /* fill nbuttons, naxes, and nhats fields */ | |
365 joystick->nbuttons = SYS_JoyData[index].buttons; | |
366 joystick->naxes = SYS_JoyData[index].axes; | |
367 /* joystick->nhats = SYS_JoyData[index].hats; */ | |
368 joystick->nhats = 0; /* No support for hats at this time */ | |
369 /* joystick->nballs = SYS_JoyData[index].balls; */ | |
370 joystick->nballs = 0; /* No support for balls at this time */ | |
371 return 0; | |
372 } | |
373 | |
374 | |
375 | |
376 /***************************************************************************/ | |
377 /* Function to update the state of a joystick - called as a device poll. */ | |
378 /* This function shouldn't update the joystick structure directly, */ | |
379 /* but instead should call SDL_PrivateJoystick*() to deliver events */ | |
380 /* and update joystick device state. */ | |
381 /***************************************************************************/ | |
382 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) | |
383 { | |
384 APIRET rc; /* Generic OS/2 return code */ | |
385 int index; /* index shortcurt to joystick index */ | |
386 int i; /* Generic counter */ | |
387 int normbut; /* Number of buttons reported by joystick */ | |
388 int corr; /* Correction for button names */ | |
389 Sint16 value, change; /* Values used to update axis values */ | |
390 struct _transaxes *transaxes; /* Shortcut for Correction structure */ | |
391 Uint32 pos[MAX_AXES]; /* Vector to inform the Axis status */ | |
392 ULONG ulDataLen; /* Size of data */ | |
393 GAME_STATUS_STRUCT stGameStatus; /* Joystick Status Structure */ | |
394 | |
395 ulDataLen = sizeof(stGameStatus); | |
396 rc = DosDevIOCtl(hJoyPort, IOCTL_CAT_USER, GAME_GET_STATUS, | |
397 NULL, 0, NULL, &stGameStatus, ulDataLen, &ulDataLen); | |
398 if (rc != 0) | |
399 { | |
400 SDL_SetError("Could not read joystick status."); | |
401 return; /* Could not read data */ | |
402 } | |
403 | |
404 /* Shortcut pointer */ | |
405 index = joystick->index; | |
406 /* joystick motion events */ | |
407 | |
408 if (SYS_JoyData[index].id == 0) | |
409 { | |
410 pos[0] = stGameStatus.curdata.A.x; | |
411 pos[1] = stGameStatus.curdata.A.y; | |
412 if (SYS_JoyData[index].axes >= 3) pos[2] = stGameStatus.curdata.B.x; | |
413 else pos[2]=0; | |
414 if (SYS_JoyData[index].axes >= 4) pos[3] = stGameStatus.curdata.B.y; | |
415 else pos[3]=0; | |
416 pos[4]=0; /* OS/2 basic drivers do not support more than 4 axes joysticks */ | |
417 pos[5]=0; | |
418 } | |
419 else if (SYS_JoyData[index].id == 1) | |
420 { | |
421 pos[0] = stGameStatus.curdata.B.x; | |
422 pos[1] = stGameStatus.curdata.B.y; | |
423 pos[2]=0; | |
424 pos[3]=0; | |
425 pos[4]=0; | |
426 pos[5]=0; | |
427 } | |
428 | |
429 /* Corrects the movements using the callibration */ | |
430 transaxes = joystick->hwdata->transaxes; | |
431 for (i = 0; i < joystick->naxes; i++) | |
432 { | |
433 value = pos[i] + transaxes[i].offset; | |
434 if (value<0) | |
435 { | |
436 value*=transaxes[i].scale1; | |
437 if (value>0) value = AXIS_MIN; | |
438 } | |
439 else | |
440 { | |
441 value*=transaxes[i].scale2; | |
442 if (value<0) value = AXIS_MAX; | |
443 } | |
444 change = (value - joystick->axes[i]); | |
445 if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) | |
446 { | |
447 SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); | |
448 } | |
449 } | |
450 | |
451 /* joystick button A to D events */ | |
452 if (SYS_JoyData[index].id == 1) corr = 2; | |
453 else corr = 0; | |
454 normbut=4; /* Number of normal buttons */ | |
455 if (joystick->nbuttons<normbut) normbut = joystick->nbuttons; | |
456 for ( i = corr; (i-corr) < normbut; ++i ) | |
457 { | |
458 /* | |
459 Button A: 1110 0000 | |
460 Button B: 1101 0000 | |
461 Button C: 1011 0000 | |
462 Button D: 0111 0000 | |
463 */ | |
464 if ( (~stGameStatus.curdata.butMask)>>4 & JOY_BUTTON_FLAG(i) ) | |
465 { | |
466 if ( ! joystick->buttons[i-corr] ) | |
467 { | |
468 SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_PRESSED); | |
469 } | |
470 } | |
471 else | |
472 { | |
473 if ( joystick->buttons[i-corr] ) | |
474 { | |
475 SDL_PrivateJoystickButton(joystick, (Uint8)(i-corr), SDL_RELEASED); | |
476 } | |
477 } | |
478 } | |
479 | |
480 /* Joystick button E to H buttons */ | |
481 /* | |
482 Button E: Axis 2 X Left | |
483 Button F: Axis 2 Y Up | |
484 Button G: Axis 2 X Right | |
485 Button H: Axis 2 Y Down | |
486 */ | |
487 if (joystick->nbuttons>=5) | |
488 { | |
489 if (stGameStatus.curdata.B.x < SYS_JoyData[index].buttoncalc[0]) SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_PRESSED); | |
490 else SDL_PrivateJoystickButton(joystick, (Uint8)4, SDL_RELEASED); | |
491 } | |
492 if (joystick->nbuttons>=6) | |
493 { | |
494 if (stGameStatus.curdata.B.y < SYS_JoyData[index].buttoncalc[1]) SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_PRESSED); | |
495 else SDL_PrivateJoystickButton(joystick, (Uint8)5, SDL_RELEASED); | |
496 } | |
497 if (joystick->nbuttons>=7) | |
498 { | |
499 if (stGameStatus.curdata.B.x > SYS_JoyData[index].buttoncalc[2]) SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_PRESSED); | |
500 else SDL_PrivateJoystickButton(joystick, (Uint8)6, SDL_RELEASED); | |
501 } | |
502 if (joystick->nbuttons>=8) | |
503 { | |
504 if (stGameStatus.curdata.B.y > SYS_JoyData[index].buttoncalc[3]) SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_PRESSED); | |
505 else SDL_PrivateJoystickButton(joystick, (Uint8)7, SDL_RELEASED); | |
506 } | |
507 | |
508 /* joystick hat events */ | |
509 /* Not Supported under OS/2 */ | |
510 /* joystick ball events */ | |
511 /* Not Supported under OS/2 */ | |
512 } | |
513 | |
514 | |
515 | |
516 /******************************************/ | |
517 /* Function to close a joystick after use */ | |
518 /******************************************/ | |
519 void SDL_SYS_JoystickClose(SDL_Joystick *joystick) | |
520 { | |
521 if (joystick->hwdata != NULL) | |
522 { | |
523 /* free system specific hardware data */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
524 SDL_free(joystick->hwdata); |
1190 | 525 } |
526 } | |
527 | |
528 | |
529 | |
530 /********************************************************************/ | |
531 /* Function to perform any system-specific joystick related cleanup */ | |
532 /********************************************************************/ | |
533 void SDL_SYS_JoystickQuit(void) | |
534 { | |
535 joyPortClose(&hJoyPort); | |
536 } | |
537 | |
538 | |
539 | |
540 /************************/ | |
541 /************************/ | |
542 /* OS/2 Implementations */ | |
543 /************************/ | |
544 /************************/ | |
545 | |
546 | |
547 /*****************************************/ | |
548 /* Open Joystick Port, if not opened yet */ | |
549 /*****************************************/ | |
550 APIRET joyPortOpen(HFILE * hGame) | |
551 { | |
552 APIRET rc; /* Generic Return Code */ | |
553 ULONG ulAction; /* ? */ | |
554 ULONG ulVersion; /* Version of joystick driver */ | |
555 ULONG ulDataLen; /* Size of version data */ | |
556 | |
557 /* Verifies if joyport is not already open... */ | |
558 if (*hGame != NULL) return 0; | |
559 /* Open GAME$ for read */ | |
560 rc = DosOpen((PSZ)GAMEPDDNAME, hGame, &ulAction, 0, FILE_READONLY, | |
561 FILE_OPEN, OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, NULL); | |
562 if (rc != 0) | |
563 { | |
564 SDL_SetError("Could not open Joystick Port."); | |
565 return -1; | |
566 } | |
567 | |
568 /* Get Joystick Driver Version... must be 2.0 or higher */ | |
569 ulVersion = 0; | |
570 ulDataLen = sizeof(ulVersion); | |
571 rc = DosDevIOCtl( *hGame, IOCTL_CAT_USER, GAME_GET_VERSION, | |
572 NULL, 0, NULL, &ulVersion, ulDataLen, &ulDataLen); | |
573 if (rc != 0) | |
574 { | |
575 joyPortClose(hGame); | |
576 SDL_SetError("Could not get Joystick Driver version."); | |
577 return -1; | |
578 } | |
579 if (ulVersion < GAME_VERSION) | |
580 { | |
581 joyPortClose(hGame); | |
582 SDL_SetError("Driver too old. At least IBM driver version 2.0 required."); | |
583 return -1; | |
584 } | |
585 return 0; | |
586 } | |
587 | |
588 | |
589 | |
590 /****************************/ | |
591 /* Close JoyPort, if opened */ | |
592 /****************************/ | |
593 void joyPortClose(HFILE * hGame) | |
594 { | |
595 if (*hGame != NULL) DosClose(*hGame); | |
596 *hGame = NULL; | |
597 } | |
598 | |
599 | |
600 | |
601 /***************************/ | |
602 /* Get SDL Joystick EnvVar */ | |
603 /***************************/ | |
604 int joyGetEnv(struct _joycfg * joydata) | |
605 { | |
606 char *joyenv; /* Pointer to tested character */ | |
607 char tempnumber[5]; /* Temporary place to put numeric texts */ | |
608 | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
609 joyenv = SDL_getenv("SDL_OS2_JOYSTICK"); |
1190 | 610 if (joyenv == NULL) return 0; |
611 /* Joystick Environment is defined! */ | |
612 while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ | |
613 /* If the string name starts with '... get if fully */ | |
614 if (*joyenv=='\'') joyenv+=joyGetData(++joyenv,joydata->name,'\'',sizeof(joydata->name)); | |
615 /* If not, get it until the next space */ | |
616 else if (*joyenv=='\"') joyenv+=joyGetData(++joyenv,joydata->name,'\"',sizeof(joydata->name)); | |
617 else joyenv+=joyGetData(joyenv,joydata->name,' ',sizeof(joydata->name)); | |
618 /* Now get the number of axes */ | |
619 while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ | |
620 joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); | |
621 joydata->axes = atoi(tempnumber); | |
622 /* Now get the number of buttons */ | |
623 while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ | |
624 joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); | |
625 joydata->buttons = atoi(tempnumber); | |
626 /* Now get the number of hats */ | |
627 while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ | |
628 joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); | |
629 joydata->hats = atoi(tempnumber); | |
630 /* Now get the number of balls */ | |
631 while (*joyenv==' ' && *joyenv!=0) joyenv++; /* jump spaces... */ | |
632 joyenv+=joyGetData(joyenv,tempnumber,' ',sizeof(tempnumber)); | |
633 joydata->balls = atoi(tempnumber); | |
634 return 1; | |
635 } | |
636 | |
637 | |
638 | |
639 /************************************************************************/ | |
640 /* Get a text from in the string starting in joyenv until it finds */ | |
641 /* the stopchar or maxchars is reached. The result is placed in name. */ | |
642 /************************************************************************/ | |
643 int joyGetData(char *joyenv, char *name, char stopchar, size_t maxchars) | |
644 { | |
645 char *nameptr; /* Pointer to the selected character */ | |
646 int chcnt=0; /* Count how many characters where copied */ | |
647 | |
648 nameptr=name; | |
649 while (*joyenv!=stopchar && *joyenv!=0) | |
650 { | |
651 if (nameptr<(name+(maxchars-1))) | |
652 { | |
653 *nameptr = *joyenv; /* Only copy if smaller than maximum */ | |
654 nameptr++; | |
655 } | |
656 chcnt++; | |
657 joyenv++; | |
658 } | |
659 if (*joyenv==stopchar) | |
660 { | |
661 joyenv++; /* Jump stopchar */ | |
662 chcnt++; | |
663 } | |
664 *nameptr = 0; /* Mark last byte */ | |
665 return chcnt; | |
666 } | |
667 | |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1442
diff
changeset
|
668 #endif /* SDL_JOYSTICK_OS2 */ |