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
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
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>
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;
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 */
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
[] =
104 struct joystick_hwdata
107 #ifndef NO_LOWLEVEL_EXT
109 ULONG supports_analog
;
113 /* lowlevel portNumber 0 <-> 1 */
114 static int PortIndex(int index
)
133 int SDL_SYS_JoystickInit(void)
135 int numjoysticks
= 0;
136 unsigned long joyflag
= 0L;
138 D(bug("SDL_SYS_JoystickInit()\n"));
142 if((LowLevelBase
= OpenLibrary("lowlevel.library",37)))
145 while(numjoysticks
< MAX_JOYSTICKS
)
147 joyflag
= ReadJoyPort(PortIndex(numjoysticks
));
149 if((joyflag
&JP_TYPE_MASK
) == JP_TYPE_NOTAVAIL
)
161 /* failed to open lowlevel.library! */
162 SDL_SetError("Unable to open lowlevel.library");
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"));
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");
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
);
204 SDL_SetError("No joystick available with that index");
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
));
225 if(SDL_SYS_JoystickInit() < 1)
227 SDL_SetError("Initialize Joysticks first!");
232 /* if(!(joystick->hwdata=malloc(sizeof(struct joystick_hwdata)))) */
233 joystick
->hwdata
= (struct joystick_hwdata
*) malloc(sizeof(*joystick
->hwdata
));
234 if ( joystick
->hwdata
== NULL
)
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;
251 else if((temp
& JP_TYPE_MASK
) == JP_TYPE_JOYSTK
)
253 joystick
->nbuttons
= 3;
256 else if((temp
& JP_TYPE_MASK
) == JP_TYPE_MOUSE
)
258 joystick
->nbuttons
= 3;
261 else if((temp
& JP_TYPE_MASK
) == JP_TYPE_UNKNOWN
)
263 joystick
->nbuttons
= 3;
266 else if((temp
& JP_TYPE_MASK
) == JP_TYPE_NOTAVAIL
)
268 joystick
->nbuttons
= 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;
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
)
293 #ifndef NO_LOWLEVEL_EXT
298 D(bug("SDL_SYS_JoystickUpdate()\n"));
302 if(SDL_SYS_JoystickInit() < 1)
304 SDL_SetError("Initialize Joysticks first!");
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
);
316 /* only send an event when something changed */
319 if((joystick
->hwdata
->joystate
& JP_DIRECTION_MASK
) != (data
& JP_DIRECTION_MASK
))
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
);
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
))
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
))
363 value
= ((data_ext
& JP_YAXIS_MASK
)>>8) * 2*32767 / 255 - 32767;
364 SDL_PrivateJoystickAxis(joystick
, 1, value
);
370 if((joystick
->hwdata
->joystate
& (JPF_JOY_DOWN
|JPF_JOY_UP
)) != (data
& (JPF_JOY_DOWN
|JPF_JOY_UP
)))
374 /* UP and DOWN direction */
375 if(data
& JPF_JOY_DOWN
)
379 else if(data
& JPF_JOY_UP
)
388 SDL_PrivateJoystickAxis(joystick
, 1, value
);
391 if((joystick
->hwdata
->joystate
& (JPF_JOY_LEFT
|JPF_JOY_RIGHT
)) != (data
& (JPF_JOY_LEFT
|JPF_JOY_RIGHT
)))
395 /* LEFT and RIGHT direction */
396 if(data
& JPF_JOY_LEFT
)
400 else if(data
& JPF_JOY_RIGHT
)
409 SDL_PrivateJoystickAxis(joystick
, 0, value
);
414 for(i
= 0; i
< joystick
->nbuttons
; i
++)
416 if( (data
& joybut
[i
]) )
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
;
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
);
453 free(joystick
->hwdata
);
459 /* Function to perform any system-specific joystick related cleanup */
460 void SDL_SYS_JoystickQuit(void)
462 D(bug("SDL_SYS_JoystickQuit()\n"));
466 CloseLibrary(LowLevelBase
);
468 SDL_numjoysticks
= 0;