merged in Yannick's fixes.
[AROS-Contrib.git] / SDL / SDL_main / src / joystick / aros / SDL_sysjoystick.c
blob71720a764b92fcd300124c75c7967bdf948c018d
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2004 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 Sam Lantinga
20 slouken@libsdl.org
22 20040518 SDL_SYS_JoystickOpen() function fixed
23 SetJoyPortAttrs() function added to initialize port
25 20040515 SDL_SYS_JoystickInit() function fixed
26 SDL_SYS_JoystickName() function fixed
27 SDL_SYS_JoystickQuit() function fixed
28 joystick max number (2) removed
29 PrivateJoyAxis 2nd parameters inverted!
31 20040505 "inline" include replaced with "proto"
33 20040501 LowlevelBase static declaration removed
34 Debug lines added
38 /* This is the system specific header for the SDL joystick API */
40 #include <stdio.h> /* For the definition of NULL */
42 #include <libraries/lowlevel.h>
43 //#define NO_LOWLEVEL_EXT
44 #ifndef NO_LOWLEVEL_EXT
45 #include <libraries/lowlevel_ext.h>
46 #endif
47 #include <proto/exec.h>
48 #include <proto/lowlevel.h>
49 #include <proto/graphics.h>
50 #include "../../main/aros/mydebug.h"
53 extern struct ExecBase *SysBase;
54 extern struct GfxBase *GfxBase;
57 #include <stdlib.h>
59 #include "SDL_events.h"
60 #include "SDL_error.h"
61 #include "SDL_joystick.h"
62 #include "../SDL_sysjoystick.h"
63 #include "../SDL_joystick_c.h"
65 /* The maximum number of joysticks we'll detect */
66 #define MAX_JOYSTICKS 4 /* lowlevel.library is limited to 4 ports */
68 /* Directions/Axis differences */
69 #define MOS_PLUS 32767 /* was 127, changed by Henes (20040801) */
70 #define MOS_MINUS -32768 /* was -127 */
72 #ifndef JP_TYPE_ANALOGUE
73 #define JP_TYPE_ANALOGUE (14<<28) /* port has analogue joystick */
74 #define JP_XAXIS_MASK (255<<0) /* horizontal position */
75 #define JP_YAXIS_MASK (255<<8) /* vertical position */
76 #define JP_ANALOGUE_PORT_MAGIC (1<<16) /* port offset to force analogue readout */
77 #endif
79 /* Function to scan the system for joysticks.
80 * This function should set SDL_numjoysticks to the number of available
81 * joysticks. Joystick 0 should be the system default joystick.
82 * It should return 0, or -1 on an unrecoverable fatal error.
85 struct Library *LowLevelBase = NULL;
87 unsigned long joybut[] =
89 JPF_BUTTON_RED,
90 JPF_BUTTON_BLUE,
91 JPF_BUTTON_YELLOW,
92 JPF_BUTTON_GREEN,
93 JPF_BUTTON_PLAY,
94 JPF_BUTTON_FORWARD,
95 JPF_BUTTON_REVERSE
97 JPF_JOY_UP,
98 JPF_JOY_DOWN,
99 JPF_JOY_LEFT,
100 JPF_JOY_RIGHT
104 struct joystick_hwdata
106 ULONG joystate;
107 #ifndef NO_LOWLEVEL_EXT
108 ULONG joystate_ext;
109 ULONG supports_analog;
110 #endif
113 /* lowlevel portNumber 0 <-> 1 */
114 static int PortIndex(int index)
116 switch(index)
118 case 0:
119 return 1;
120 break;
122 case 1:
123 return 0;
124 break;
126 default:
127 break;
130 return index;
133 int SDL_SYS_JoystickInit(void)
135 int numjoysticks = 0;
136 unsigned long joyflag = 0L;
138 D(bug("SDL_SYS_JoystickInit()\n"));
140 if(!LowLevelBase)
142 if((LowLevelBase = OpenLibrary("lowlevel.library",37)))
144 numjoysticks = 0;
145 while(numjoysticks < MAX_JOYSTICKS)
147 joyflag = ReadJoyPort(PortIndex(numjoysticks));
149 if((joyflag&JP_TYPE_MASK) == JP_TYPE_NOTAVAIL)
151 break;
154 numjoysticks++;
157 return numjoysticks;
159 else
161 /* failed to open lowlevel.library! */
162 SDL_SetError("Unable to open lowlevel.library");
163 return 0;
166 else
168 return SDL_numjoysticks;
172 /* Function to get the device-dependent name of a joystick */
173 const char *SDL_SYS_JoystickName(int index)
175 static char name[64];
176 unsigned long joyflag = 0L;
178 D(bug("SDL_SYS_JoystickName()\n"));
180 if(LowLevelBase)
182 memset(name, 0, sizeof(name));
184 index = PortIndex(index);
186 joyflag = ReadJoyPort(index);
188 if((joyflag&JP_TYPE_MASK) == JP_TYPE_NOTAVAIL)
190 SDL_SetError("No joystick available with that index");
192 return NULL;
195 if((joyflag&JP_TYPE_MASK) == JP_TYPE_GAMECTLR) sprintf(name, "Port %d is a Game Controller", index);
196 if((joyflag&JP_TYPE_MASK) == JP_TYPE_MOUSE) sprintf(name, "Port %d is a Mouse", index);
197 if((joyflag&JP_TYPE_MASK) == JP_TYPE_JOYSTK) sprintf(name, "Port %d is a Joystick", index);
198 if((joyflag&JP_TYPE_MASK) == JP_TYPE_UNKNOWN) sprintf(name, "Port %d is an unknown device", index);
200 return name;
202 else
204 SDL_SetError("No joystick available with that index");
206 return NULL;
210 /* Function to open a joystick for use.
211 The joystick to open is specified by the index field of the joystick.
212 This should fill the nbuttons and naxes fields of the joystick structure.
213 It returns 0, or -1 if there is an error.
216 int SDL_SYS_JoystickOpen(SDL_Joystick *joystick)
218 unsigned long temp = 0L;
220 D(bug("SDL_SYS_JoystickOpen()"));
221 D(bug("Opening joystick %ld\n", joystick->index));
223 if(!LowLevelBase)
225 if(SDL_SYS_JoystickInit() < 1)
227 SDL_SetError("Initialize Joysticks first!");
228 return -1;
232 /* if(!(joystick->hwdata=malloc(sizeof(struct joystick_hwdata)))) */
233 joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
234 if ( joystick->hwdata == NULL )
236 SDL_OutOfMemory();
238 return -1;
240 memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
242 SetJoyPortAttrs(PortIndex(joystick->index), SJA_Type, SJA_TYPE_GAMECTLR, TAG_END);
244 temp = ReadJoyPort(PortIndex(joystick->index));
246 if((temp & JP_TYPE_MASK)==JP_TYPE_GAMECTLR)
248 joystick->nbuttons = 7;
249 joystick->nhats = 1;
251 else if((temp & JP_TYPE_MASK) == JP_TYPE_JOYSTK)
253 joystick->nbuttons = 3;
254 joystick->nhats = 1;
256 else if((temp & JP_TYPE_MASK) == JP_TYPE_MOUSE)
258 joystick->nbuttons = 3;
259 joystick->nhats = 0;
261 else if((temp & JP_TYPE_MASK) == JP_TYPE_UNKNOWN)
263 joystick->nbuttons = 3;
264 joystick->nhats = 1;
266 else if((temp & JP_TYPE_MASK) == JP_TYPE_NOTAVAIL)
268 joystick->nbuttons = 0;
269 joystick->nhats = 0;
272 joystick->nballs = 0;
273 joystick->naxes = 2; /* FIXME: even for JP_TYPE_NOTAVAIL ? */
274 joystick->hwdata->joystate = 0L;
275 #ifndef NO_LOWLEVEL_EXT
276 joystick->hwdata->joystate_ext = 0L;
278 if (LowLevelBase->lib_Version > 50 || (LowLevelBase->lib_Version >= 50 && LowLevelBase->lib_Revision >= 17))
279 joystick->hwdata->supports_analog = 1;
280 #endif
282 return 0;
285 /* Function to update the state of a joystick - called as a device poll.
286 * This function shouldn't update the joystick structure directly,
287 * but instead should call SDL_PrivateJoystick*() to deliver events
288 * and update joystick device state.
290 void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
292 ULONG data;
293 #ifndef NO_LOWLEVEL_EXT
294 ULONG data_ext;
295 #endif
296 int i;
298 D(bug("SDL_SYS_JoystickUpdate()\n"));
300 if(!LowLevelBase)
302 if(SDL_SYS_JoystickInit() < 1)
304 SDL_SetError("Initialize Joysticks first!");
306 return;
310 data = ReadJoyPort(PortIndex(joystick->index));
311 #ifndef NO_LOWLEVEL_EXT
312 if (joystick->hwdata->supports_analog)
313 data_ext = ReadJoyPort(PortIndex(joystick->index) + JP_ANALOGUE_PORT_MAGIC);
314 #endif
316 /* only send an event when something changed */
318 /* hats */
319 if((joystick->hwdata->joystate & JP_DIRECTION_MASK) != (data & JP_DIRECTION_MASK))
321 if(joystick->nhats)
323 Uint8 value_hat = SDL_HAT_CENTERED;
325 if(data & JPF_JOY_DOWN)
327 value_hat |= SDL_HAT_DOWN;
329 else if(data & JPF_JOY_UP)
331 value_hat |= SDL_HAT_UP;
334 if(data & JPF_JOY_LEFT)
336 value_hat |= SDL_HAT_LEFT;
338 else if(data & JPF_JOY_RIGHT)
340 value_hat |= SDL_HAT_RIGHT;
343 SDL_PrivateJoystickHat(joystick, 0, value_hat);
347 /* axes */
348 #ifndef NO_LOWLEVEL_EXT
349 if (joystick->hwdata->supports_analog && data_ext & JP_TYPE_ANALOGUE)
351 if((joystick->hwdata->joystate_ext & JP_XAXIS_MASK) != (data_ext & JP_XAXIS_MASK))
353 Sint16 value;
355 value = (data_ext & JP_XAXIS_MASK) * 2*32767 / 255 - 32767;
356 SDL_PrivateJoystickAxis(joystick, 0, value);
359 if((joystick->hwdata->joystate_ext & JP_YAXIS_MASK) != (data_ext & JP_YAXIS_MASK))
361 Sint16 value;
363 value = ((data_ext & JP_YAXIS_MASK)>>8) * 2*32767 / 255 - 32767;
364 SDL_PrivateJoystickAxis(joystick, 1, value);
367 else
368 #endif
370 if((joystick->hwdata->joystate & (JPF_JOY_DOWN|JPF_JOY_UP)) != (data & (JPF_JOY_DOWN|JPF_JOY_UP)))
372 Sint16 value;
374 /* UP and DOWN direction */
375 if(data & JPF_JOY_DOWN)
377 value = MOS_PLUS;
379 else if(data & JPF_JOY_UP)
381 value = MOS_MINUS;
383 else
385 value = 0;
388 SDL_PrivateJoystickAxis(joystick, 1, value);
391 if((joystick->hwdata->joystate & (JPF_JOY_LEFT|JPF_JOY_RIGHT)) != (data & (JPF_JOY_LEFT|JPF_JOY_RIGHT)))
393 Sint16 value;
395 /* LEFT and RIGHT direction */
396 if(data & JPF_JOY_LEFT)
398 value = MOS_MINUS;
400 else if(data & JPF_JOY_RIGHT)
402 value = MOS_PLUS;
404 else
406 value = 0;
409 SDL_PrivateJoystickAxis(joystick, 0, value);
413 /* Joy buttons */
414 for(i = 0; i < joystick->nbuttons; i++)
416 if( (data & joybut[i]) )
418 if(i == 1)
420 #warning WTF?
421 data &= ~(joybut[2]);
424 if(!(joystick->hwdata->joystate & joybut[i]))
426 SDL_PrivateJoystickButton(joystick, i, SDL_PRESSED);
429 else if(joystick->hwdata->joystate & joybut[i])
431 SDL_PrivateJoystickButton(joystick, i, SDL_RELEASED);
435 joystick->hwdata->joystate = data;
436 #ifndef NO_LOWLEVEL_EXT
437 joystick->hwdata->joystate_ext = data_ext;
438 #endif
441 /* Function to close a joystick after use */
442 void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
444 D(bug("SDL_SYS_JoystickClose()\n"));
446 if(LowLevelBase) /* ne to reinitialize */
448 SetJoyPortAttrs(PortIndex(joystick->index), SJA_Type, SJA_TYPE_AUTOSENSE, TAG_END);
451 if(joystick->hwdata)
453 free(joystick->hwdata);
456 return;
459 /* Function to perform any system-specific joystick related cleanup */
460 void SDL_SYS_JoystickQuit(void)
462 D(bug("SDL_SYS_JoystickQuit()\n"));
464 if(LowLevelBase)
466 CloseLibrary(LowLevelBase);
467 LowLevelBase = NULL;
468 SDL_numjoysticks = 0;
471 return;