]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/joy.c
do away with Joystick.buttons
[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 #include "key.h"
23
24 #define MAX_JOYSTICKS 16
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 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 joyaxis {
40         int             value;
41         int             min_val;
42         int             center_val;
43         int             max_val;
44 };
45
46 /* This struct is a "virtual" joystick, which includes all the axes
47  * and buttons of every joystick found.
48  */
49 static struct joyinfo {
50         int n_axes;
51         int n_buttons;
52         struct joyaxis axes[JOY_MAX_AXES];
53 } Joystick;
54
55 /* This struct is an array, with one entry for each physical joystick
56  * found.
57  */
58 static struct {
59         SDL_Joystick *handle;
60         int n_axes;
61         int n_buttons;
62         int n_hats;
63         int hat_map[MAX_HATS_PER_JOYSTICK];  //Note: Descent expects hats to be buttons, so these are indices into Joystick.buttons
64         int axis_map[MAX_AXES_PER_JOYSTICK];
65         int button_map[MAX_BUTTONS_PER_JOYSTICK];
66 } SDL_Joysticks[MAX_JOYSTICKS];
67
68 void joy_button_handler(SDL_JoyButtonEvent *jbe)
69 {
70         int button;
71
72         button = SDL_Joysticks[jbe->which].button_map[jbe->button];
73
74         vkey_handler(KEY_JB1 + button, jbe->state == SDL_PRESSED);
75 }
76
77 void joy_hat_handler(SDL_JoyHatEvent *jhe)
78 {
79         int hat = SDL_Joysticks[jhe->which].hat_map[jhe->hat];
80
81         vkey_handler(KEY_JB1 + hat + 0, (jhe->value & SDL_HAT_UP   ) > 0);
82         vkey_handler(KEY_JB1 + hat + 1, (jhe->value & SDL_HAT_RIGHT) > 0);
83         vkey_handler(KEY_JB1 + hat + 2, (jhe->value & SDL_HAT_DOWN ) > 0);
84         vkey_handler(KEY_JB1 + hat + 3, (jhe->value & SDL_HAT_LEFT ) > 0);
85 }
86
87 void joy_axis_handler(SDL_JoyAxisEvent *jae)
88 {
89         int axis;
90
91         axis = SDL_Joysticks[jae->which].axis_map[jae->axis];
92         
93         Joystick.axes[axis].value = jae->value;
94 }
95
96
97 /* ----------------------------------------------- */
98
99 int joy_init()
100 {
101         int i,j,n;
102         char temp[10];
103
104         if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
105                 con_printf(CON_VERBOSE, "sdl-joystick: initialisation failed: %s.",SDL_GetError());
106                 return 0;
107         }
108
109         memset(&Joystick,0,sizeof(Joystick));
110         memset(joyaxis_text, 0, JOY_MAX_AXES * sizeof(char *));
111
112         n = SDL_NumJoysticks();
113
114         con_printf(CON_VERBOSE, "sdl-joystick: found %d joysticks\n", n);
115         for (i = 0; i < n; i++) {
116                 con_printf(CON_VERBOSE, "sdl-joystick %d: %s\n", i, SDL_JoystickName(i));
117                 SDL_Joysticks[num_joysticks].handle = SDL_JoystickOpen(i);
118                 if (SDL_Joysticks[num_joysticks].handle) {
119                         joy_present = 1;
120
121                         SDL_Joysticks[num_joysticks].n_axes
122                                 = SDL_JoystickNumAxes(SDL_Joysticks[num_joysticks].handle);
123                         if(SDL_Joysticks[num_joysticks].n_axes > MAX_AXES_PER_JOYSTICK)
124                         {
125                                 Warning("sdl-joystick: found %d axes, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_axes, MAX_AXES_PER_JOYSTICK);
126                                 SDL_Joysticks[num_joysticks].n_axes = MAX_AXES_PER_JOYSTICK;
127                         }
128
129                         SDL_Joysticks[num_joysticks].n_buttons
130                                 = SDL_JoystickNumButtons(SDL_Joysticks[num_joysticks].handle);
131                         if(SDL_Joysticks[num_joysticks].n_buttons > MAX_BUTTONS_PER_JOYSTICK)
132                         {
133                                 Warning("sdl-joystick: found %d buttons, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_buttons, MAX_BUTTONS_PER_JOYSTICK);
134                                 SDL_Joysticks[num_joysticks].n_buttons = MAX_BUTTONS_PER_JOYSTICK;
135                         }
136
137                         SDL_Joysticks[num_joysticks].n_hats
138                                 = SDL_JoystickNumHats(SDL_Joysticks[num_joysticks].handle);
139                         if(SDL_Joysticks[num_joysticks].n_hats > MAX_HATS_PER_JOYSTICK)
140                         {
141                                 Warning("sdl-joystick: found %d hats, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_hats, MAX_HATS_PER_JOYSTICK);
142                                 SDL_Joysticks[num_joysticks].n_hats = MAX_HATS_PER_JOYSTICK;
143                         }
144
145                         con_printf(CON_VERBOSE, "sdl-joystick: %d axes\n", SDL_Joysticks[num_joysticks].n_axes);
146                         con_printf(CON_VERBOSE, "sdl-joystick: %d buttons\n", SDL_Joysticks[num_joysticks].n_buttons);
147                         con_printf(CON_VERBOSE, "sdl-joystick: %d hats\n", SDL_Joysticks[num_joysticks].n_hats);
148
149                         for (j=0; j < SDL_Joysticks[num_joysticks].n_axes; j++)
150                         {
151                                 sprintf(temp, "J%d A%d", i + 1, j + 1);
152                                 joyaxis_text[Joystick.n_axes] = d_strdup(temp);
153                                 SDL_Joysticks[num_joysticks].axis_map[j] = Joystick.n_axes++;
154                         }
155                         for (j=0; j < SDL_Joysticks[num_joysticks].n_buttons; j++)
156                         {
157                                 sprintf(temp, "J%dB%d", i + 1, j + 1);
158                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
159                                 SDL_Joysticks[num_joysticks].button_map[j] = Joystick.n_buttons++;
160                         }
161                         for (j=0; j < SDL_Joysticks[num_joysticks].n_hats; j++)
162                         {
163                                 SDL_Joysticks[num_joysticks].hat_map[j] = Joystick.n_buttons;
164                                 //a hat counts as four buttons
165
166                                 sprintf(temp, "J%dH%dUP", i + 1, j + 1);
167                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
168                                 Joystick.n_buttons++;
169
170                                 sprintf(temp, "J%dH%dRIGHT", i + 1, j + 1);
171                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
172                                 Joystick.n_buttons++;
173
174                                 sprintf(temp, "J%dH%dDOWN", i + 1, j + 1);
175                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
176                                 Joystick.n_buttons++;
177
178                                 sprintf(temp, "J%dH%dLEFT", i + 1, j + 1);
179                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
180                                 Joystick.n_buttons++;
181                         }
182
183                         num_joysticks++;
184                 }
185                 else
186                         con_printf(CON_VERBOSE, "sdl-joystick: initialization failed!\n");
187
188                 con_printf(CON_VERBOSE, "sdl-joystick: %d axes (total)\n", Joystick.n_axes);
189                 con_printf(CON_VERBOSE, "sdl-joystick: %d buttons (total)\n", Joystick.n_buttons);
190         }
191
192         joy_num_axes = Joystick.n_axes;
193         atexit(joy_close);
194
195         return joy_present;
196 }
197
198 void joy_close()
199 {
200         while (num_joysticks)
201                 SDL_JoystickClose(SDL_Joysticks[--num_joysticks].handle);
202         while (Joystick.n_axes--)
203                 d_free(joyaxis_text[Joystick.n_axes]);
204         while (Joystick.n_buttons--)
205                 d_free(key_text[KEY_JB1 + Joystick.n_buttons]);
206 }
207
208 void joy_get_pos(int *x, int *y)
209 {
210         int axis[JOY_MAX_AXES];
211
212         if (!num_joysticks) {
213                 *x=*y=0;
214                 return;
215         }
216
217         joystick_read_raw_axis (JOY_ALL_AXIS, axis);
218
219         *x = joy_get_scaled_reading( axis[0], 0 );
220         *y = joy_get_scaled_reading( axis[1], 1 );
221 }
222
223 int joy_get_btns()
224 {
225 #if 0 // This is never used?
226         int i, buttons = 0;
227         for (i=0; i++; i<buttons) {
228                 switch (keyd_pressed[KEY_JB1 + i]) {
229                 case 1:
230                         buttons |= 1<<i;
231                         break;
232                 case 0:
233                         break;
234                 }
235         }
236         return buttons;
237 #else
238         return 0;
239 #endif
240 }
241
242
243 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
244 {
245         int i;
246         ubyte channel_masks = 0;
247         
248         if (!num_joysticks)
249                 return 0;
250
251         event_poll();
252
253         for (i = 0; i < Joystick.n_axes; i++)
254         {
255                 if ((axis[i] = Joystick.axes[i].value))
256                         channel_masks |= 1 << i;
257         }
258
259         return channel_masks;
260 }
261
262 void joy_flush()
263 {
264         if (!num_joysticks)
265                 return;
266 }
267
268 int joy_get_button_state( int btn )
269 {
270         if (!num_joysticks)
271                 return 0;
272
273         if(btn >= Joystick.n_buttons)
274                 return 0;
275
276         event_poll();
277
278         return keyd_pressed[KEY_JB1 + btn];
279 }
280
281 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
282 {
283         int i;
284
285         for (i = 0; i < Joystick.n_axes; i++)
286         {
287                 axis_center[i] = Joystick.axes[i].center_val;
288                 axis_min[i] = Joystick.axes[i].min_val;
289                 axis_max[i] = Joystick.axes[i].max_val;
290         }
291 }
292
293 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
294 {
295         int i;
296
297         for (i = 0; i < Joystick.n_axes; i++)
298         {
299                 Joystick.axes[i].center_val = axis_center[i];
300                 Joystick.axes[i].min_val = axis_min[i];
301                 Joystick.axes[i].max_val = axis_max[i];
302         }
303 }
304
305 int joy_get_scaled_reading( int raw, int axis_num )
306 {
307 #if 1
308         return raw/256;
309 #else
310         int d, x;
311
312         raw -= Joystick.axes[axis_num].center_val;
313         
314         if (raw < 0)
315                 d = Joystick.axes[axis_num].center_val - Joystick.axes[axis_num].min_val;
316         else if (raw > 0)
317                 d = Joystick.axes[axis_num].max_val - Joystick.axes[axis_num].center_val;
318         else
319                 d = 0;
320         
321         if (d)
322                 x = ((raw << 7) / d);
323         else
324                 x = 0;
325         
326         if ( x < -128 )
327                 x = -128;
328         if ( x > 127 )
329                 x = 127;
330         
331         d =  (joy_deadzone) * 6;
332         if ((x > (-1*d)) && (x < d))
333                 x = 0;
334         
335         return x;
336 #endif
337 }
338
339 void joy_set_slow_reading( int flag )
340 {
341 }