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