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