]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/joy.c
remove rcs tags
[btb/d2x.git] / arch / sdl / joy.c
1 /*
2  *
3  * SDL joystick support
4  *
5  *
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <conf.h>
10 #endif
11
12 #include <string.h>   // for memset
13 #include <SDL.h>
14
15 #include "joy.h"
16 #include "error.h"
17 #include "timer.h"
18 #include "console.h"
19 #include "event.h"
20 #include "text.h"
21 #include "u_mem.h"
22
23 #define MAX_JOYSTICKS 16
24
25 #define MAX_AXES_PER_JOYSTICK 8
26 #define MAX_BUTTONS_PER_JOYSTICK 16
27 #define MAX_HATS_PER_JOYSTICK 4
28
29 extern char *joybutton_text[]; //from kconfig.c
30 extern char *joyaxis_text[]; //from kconfig.c
31
32 char joy_present = 0;
33 int num_joysticks = 0;
34
35 int joy_deadzone = 0;
36
37 int joy_num_axes = 0;
38
39 struct joybutton {
40         int state;
41         int last_state;
42         fix time_went_down;
43         int num_downs;
44         int num_ups;
45 };
46
47 struct joyaxis {
48         int             value;
49         int             min_val;
50         int             center_val;
51         int             max_val;
52 };
53
54 /* This struct is a "virtual" joystick, which includes all the axes
55  * and buttons of every joystick found.
56  */
57 static struct joyinfo {
58         int n_axes;
59         int n_buttons;
60         struct joyaxis axes[JOY_MAX_AXES];
61         struct joybutton buttons[JOY_MAX_BUTTONS];
62 } Joystick;
63
64 /* This struct is an array, with one entry for each physical joystick
65  * found.
66  */
67 static struct {
68         SDL_Joystick *handle;
69         int n_axes;
70         int n_buttons;
71         int n_hats;
72         int hat_map[MAX_HATS_PER_JOYSTICK];  //Note: Descent expects hats to be buttons, so these are indices into Joystick.buttons
73         int axis_map[MAX_AXES_PER_JOYSTICK];
74         int button_map[MAX_BUTTONS_PER_JOYSTICK];
75 } SDL_Joysticks[MAX_JOYSTICKS];
76
77 void joy_button_handler(SDL_JoyButtonEvent *jbe)
78 {
79         int button;
80
81         button = SDL_Joysticks[jbe->which].button_map[jbe->button];
82
83         Joystick.buttons[button].state = jbe->state;
84
85         switch (jbe->type) {
86         case SDL_JOYBUTTONDOWN:
87                 Joystick.buttons[button].time_went_down
88                         = timer_get_fixed_seconds();
89                 Joystick.buttons[button].num_downs++;
90                 break;
91         case SDL_JOYBUTTONUP:
92                 Joystick.buttons[button].num_ups++;
93                 break;
94         }
95 }
96
97 void joy_hat_handler(SDL_JoyHatEvent *jhe)
98 {
99         int hat = SDL_Joysticks[jhe->which].hat_map[jhe->hat];
100         int hbi;
101
102         //Save last state of the hat-button
103         Joystick.buttons[hat  ].last_state = Joystick.buttons[hat  ].state;
104         Joystick.buttons[hat+1].last_state = Joystick.buttons[hat+1].state;
105         Joystick.buttons[hat+2].last_state = Joystick.buttons[hat+2].state;
106         Joystick.buttons[hat+3].last_state = Joystick.buttons[hat+3].state;
107
108         //get current state of the hat-button
109         Joystick.buttons[hat  ].state = ((jhe->value & SDL_HAT_UP)>0);
110         Joystick.buttons[hat+1].state = ((jhe->value & SDL_HAT_RIGHT)>0);
111         Joystick.buttons[hat+2].state = ((jhe->value & SDL_HAT_DOWN)>0);
112         Joystick.buttons[hat+3].state = ((jhe->value & SDL_HAT_LEFT)>0);
113
114         //determine if a hat-button up or down event based on state and last_state
115         for(hbi=0;hbi<4;hbi++)
116         {
117                 if(     !Joystick.buttons[hat+hbi].last_state && Joystick.buttons[hat+hbi].state) //last_state up, current state down
118                 {
119                         Joystick.buttons[hat+hbi].time_went_down
120                                 = timer_get_fixed_seconds();
121                         Joystick.buttons[hat+hbi].num_downs++;
122                 }
123                 else if(Joystick.buttons[hat+hbi].last_state && !Joystick.buttons[hat+hbi].state)  //last_state down, current state up
124                 {
125                         Joystick.buttons[hat+hbi].num_ups++;
126                 }
127         }
128 }
129
130 void joy_axis_handler(SDL_JoyAxisEvent *jae)
131 {
132         int axis;
133
134         axis = SDL_Joysticks[jae->which].axis_map[jae->axis];
135         
136         Joystick.axes[axis].value = jae->value;
137 }
138
139
140 /* ----------------------------------------------- */
141
142 int joy_init()
143 {
144         int i,j,n;
145         char temp[10];
146
147         if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
148                 con_printf(CON_VERBOSE, "sdl-joystick: initialisation failed: %s.",SDL_GetError());
149                 return 0;
150         }
151
152         memset(&Joystick,0,sizeof(Joystick));
153         memset(joyaxis_text, 0, JOY_MAX_AXES * sizeof(char *));
154         memset(joybutton_text, 0, JOY_MAX_BUTTONS * sizeof(char *));
155
156         n = SDL_NumJoysticks();
157
158         con_printf(CON_VERBOSE, "sdl-joystick: found %d joysticks\n", n);
159         for (i = 0; i < n; i++) {
160                 con_printf(CON_VERBOSE, "sdl-joystick %d: %s\n", i, SDL_JoystickName(i));
161                 SDL_Joysticks[num_joysticks].handle = SDL_JoystickOpen(i);
162                 if (SDL_Joysticks[num_joysticks].handle) {
163                         joy_present = 1;
164
165                         SDL_Joysticks[num_joysticks].n_axes
166                                 = SDL_JoystickNumAxes(SDL_Joysticks[num_joysticks].handle);
167                         if(SDL_Joysticks[num_joysticks].n_axes > MAX_AXES_PER_JOYSTICK)
168                         {
169                                 Warning("sdl-joystick: found %d axes, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_axes, MAX_AXES_PER_JOYSTICK);
170                                 SDL_Joysticks[num_joysticks].n_axes = MAX_AXES_PER_JOYSTICK;
171                         }
172
173                         SDL_Joysticks[num_joysticks].n_buttons
174                                 = SDL_JoystickNumButtons(SDL_Joysticks[num_joysticks].handle);
175                         if(SDL_Joysticks[num_joysticks].n_buttons > MAX_BUTTONS_PER_JOYSTICK)
176                         {
177                                 Warning("sdl-joystick: found %d buttons, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_buttons, MAX_BUTTONS_PER_JOYSTICK);
178                                 SDL_Joysticks[num_joysticks].n_buttons = MAX_BUTTONS_PER_JOYSTICK;
179                         }
180
181                         SDL_Joysticks[num_joysticks].n_hats
182                                 = SDL_JoystickNumHats(SDL_Joysticks[num_joysticks].handle);
183                         if(SDL_Joysticks[num_joysticks].n_hats > MAX_HATS_PER_JOYSTICK)
184                         {
185                                 Warning("sdl-joystick: found %d hats, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_hats, MAX_HATS_PER_JOYSTICK);
186                                 SDL_Joysticks[num_joysticks].n_hats = MAX_HATS_PER_JOYSTICK;
187                         }
188
189                         con_printf(CON_VERBOSE, "sdl-joystick: %d axes\n", SDL_Joysticks[num_joysticks].n_axes);
190                         con_printf(CON_VERBOSE, "sdl-joystick: %d buttons\n", SDL_Joysticks[num_joysticks].n_buttons);
191                         con_printf(CON_VERBOSE, "sdl-joystick: %d hats\n", SDL_Joysticks[num_joysticks].n_hats);
192
193                         for (j=0; j < SDL_Joysticks[num_joysticks].n_axes; j++)
194                         {
195                                 sprintf(temp, "J%d A%d", i + 1, j + 1);
196                                 joyaxis_text[Joystick.n_axes] = d_strdup(temp);
197                                 SDL_Joysticks[num_joysticks].axis_map[j] = Joystick.n_axes++;
198                         }
199                         for (j=0; j < SDL_Joysticks[num_joysticks].n_buttons; j++)
200                         {
201                                 sprintf(temp, "J%d B%d", i + 1, j + 1);
202                                 joybutton_text[Joystick.n_buttons] = d_strdup(temp);
203                                 SDL_Joysticks[num_joysticks].button_map[j] = Joystick.n_buttons++;
204                         }
205                         for (j=0; j < SDL_Joysticks[num_joysticks].n_hats; j++)
206                         {
207                                 SDL_Joysticks[num_joysticks].hat_map[j] = Joystick.n_buttons;
208                                 //a hat counts as four buttons
209                                 sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0202);
210                                 joybutton_text[Joystick.n_buttons++] = d_strdup(temp);
211                                 sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0177);
212                                 joybutton_text[Joystick.n_buttons++] = d_strdup(temp);
213                                 sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0200);
214                                 joybutton_text[Joystick.n_buttons++] = d_strdup(temp);
215                                 sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0201);
216                                 joybutton_text[Joystick.n_buttons++] = d_strdup(temp);
217                         }
218
219                         num_joysticks++;
220                 }
221                 else
222                         con_printf(CON_VERBOSE, "sdl-joystick: initialization failed!\n");
223
224                 con_printf(CON_VERBOSE, "sdl-joystick: %d axes (total)\n", Joystick.n_axes);
225                 con_printf(CON_VERBOSE, "sdl-joystick: %d buttons (total)\n", Joystick.n_buttons);
226         }
227
228         joy_num_axes = Joystick.n_axes;
229         atexit(joy_close);
230
231         return joy_present;
232 }
233
234 void joy_close()
235 {
236         while (num_joysticks)
237                 SDL_JoystickClose(SDL_Joysticks[--num_joysticks].handle);
238         while (Joystick.n_axes--)
239                 d_free(joyaxis_text[Joystick.n_axes]);
240         while (Joystick.n_buttons--)
241                 d_free(joybutton_text[Joystick.n_buttons]);
242 }
243
244 void joy_get_pos(int *x, int *y)
245 {
246         int axis[JOY_MAX_AXES];
247
248         if (!num_joysticks) {
249                 *x=*y=0;
250                 return;
251         }
252
253         joystick_read_raw_axis (JOY_ALL_AXIS, axis);
254
255         *x = joy_get_scaled_reading( axis[0], 0 );
256         *y = joy_get_scaled_reading( axis[1], 1 );
257 }
258
259 int joy_get_btns()
260 {
261 #if 0 // This is never used?
262         int i, buttons = 0;
263         for (i=0; i++; i<buttons) {
264                 switch (Joystick.buttons[i].state) {
265                 case SDL_PRESSED:
266                         buttons |= 1<<i;
267                         break;
268                 case SDL_RELEASED:
269                         break;
270                 }
271         }
272         return buttons;
273 #else
274         return 0;
275 #endif
276 }
277
278 int joy_get_button_down_cnt( int btn )
279 {
280         int num_downs;
281
282         if (!num_joysticks)
283                 return 0;
284
285         event_poll();
286
287         num_downs = Joystick.buttons[btn].num_downs;
288         Joystick.buttons[btn].num_downs = 0;
289
290         return num_downs;
291 }
292
293 fix joy_get_button_down_time(int btn)
294 {
295         fix time = F0_0;
296
297         if (!num_joysticks)
298                 return 0;
299
300         event_poll();
301
302         switch (Joystick.buttons[btn].state) {
303         case SDL_PRESSED:
304                 time = timer_get_fixed_seconds() - Joystick.buttons[btn].time_went_down;
305                 Joystick.buttons[btn].time_went_down = timer_get_fixed_seconds();
306                 break;
307         case SDL_RELEASED:
308                 time = 0;
309                 break;
310         }
311
312         return time;
313 }
314
315 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
316 {
317         int i;
318         ubyte channel_masks = 0;
319         
320         if (!num_joysticks)
321                 return 0;
322
323         event_poll();
324
325         for (i = 0; i < Joystick.n_axes; i++)
326         {
327                 if ((axis[i] = Joystick.axes[i].value))
328                         channel_masks |= 1 << i;
329         }
330
331         return channel_masks;
332 }
333
334 void joy_flush()
335 {
336         int i;
337
338         if (!num_joysticks)
339                 return;
340
341         for (i = 0; i < Joystick.n_buttons; i++) {
342                 Joystick.buttons[i].time_went_down = 0;
343                 Joystick.buttons[i].num_downs = 0;
344         }
345         
346 }
347
348 int joy_get_button_state( int btn )
349 {
350         if (!num_joysticks)
351                 return 0;
352
353         if(btn >= Joystick.n_buttons)
354                 return 0;
355
356         event_poll();
357
358         return Joystick.buttons[btn].state;
359 }
360
361 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
362 {
363         int i;
364
365         for (i = 0; i < Joystick.n_axes; i++)
366         {
367                 axis_center[i] = Joystick.axes[i].center_val;
368                 axis_min[i] = Joystick.axes[i].min_val;
369                 axis_max[i] = Joystick.axes[i].max_val;
370         }
371 }
372
373 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
374 {
375         int i;
376
377         for (i = 0; i < Joystick.n_axes; i++)
378         {
379                 Joystick.axes[i].center_val = axis_center[i];
380                 Joystick.axes[i].min_val = axis_min[i];
381                 Joystick.axes[i].max_val = axis_max[i];
382         }
383 }
384
385 int joy_get_scaled_reading( int raw, int axis_num )
386 {
387 #if 1
388         return raw/256;
389 #else
390         int d, x;
391
392         raw -= Joystick.axes[axis_num].center_val;
393         
394         if (raw < 0)
395                 d = Joystick.axes[axis_num].center_val - Joystick.axes[axis_num].min_val;
396         else if (raw > 0)
397                 d = Joystick.axes[axis_num].max_val - Joystick.axes[axis_num].center_val;
398         else
399                 d = 0;
400         
401         if (d)
402                 x = ((raw << 7) / d);
403         else
404                 x = 0;
405         
406         if ( x < -128 )
407                 x = -128;
408         if ( x > 127 )
409                 x = 127;
410         
411         d =  (joy_deadzone) * 6;
412         if ((x > (-1*d)) && (x < d))
413                 x = 0;
414         
415         return x;
416 #endif
417 }
418
419 void joy_set_slow_reading( int flag )
420 {
421 }