]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/joy.c
Rename include/error.h to include/dxxerror.h
[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 "dxxerror.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 "inferno.h"
24
25
26 #define MAX_JOYSTICKS 9 // don't want text descriptions going into double digits
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", CVAR_ARCHIVE },
82         { "joy_advaxisy", "2", CVAR_ARCHIVE },
83         { "joy_advaxisz", "0", CVAR_ARCHIVE },
84         { "joy_advaxisr", "0", CVAR_ARCHIVE },
85         { "joy_advaxisu", "0", CVAR_ARCHIVE },
86         { "joy_advaxisv", "0", CVAR_ARCHIVE },
87 };
88
89 cvar_t joy_invert[] = {
90         { "joy_invertx", "0", CVAR_ARCHIVE },
91         { "joy_inverty", "0", CVAR_ARCHIVE },
92         { "joy_invertz", "0", CVAR_ARCHIVE },
93         { "joy_invertr", "0", CVAR_ARCHIVE },
94         { "joy_invertu", "0", CVAR_ARCHIVE },
95         { "joy_invertv", "0", CVAR_ARCHIVE },
96 };
97
98
99 void joy_button_handler(SDL_JoyButtonEvent *jbe)
100 {
101         int button;
102
103         button = SDL_Joysticks[jbe->which].button_map[jbe->button];
104
105         vkey_handler(KEY_JB1 + button, jbe->state == SDL_PRESSED);
106 }
107
108 void joy_hat_handler(SDL_JoyHatEvent *jhe)
109 {
110         int hat = SDL_Joysticks[jhe->which].hat_map[jhe->hat];
111         int state_up    = (jhe->value & SDL_HAT_UP   ) != 0;
112         int state_right = (jhe->value & SDL_HAT_RIGHT) != 0;
113         int state_down  = (jhe->value & SDL_HAT_DOWN ) != 0;
114         int state_left  = (jhe->value & SDL_HAT_LEFT ) != 0;
115         int old_state_up    = keyd_pressed[KEY_JB1 + hat + 0];
116         int old_state_right = keyd_pressed[KEY_JB1 + hat + 1];
117         int old_state_down  = keyd_pressed[KEY_JB1 + hat + 2];
118         int old_state_left  = keyd_pressed[KEY_JB1 + hat + 3];
119
120         if (state_up    != old_state_up   ) vkey_handler(KEY_JB1 + hat + 0, state_up   );
121         if (state_right != old_state_right) vkey_handler(KEY_JB1 + hat + 1, state_right);
122         if (state_down  != old_state_down ) vkey_handler(KEY_JB1 + hat + 2, state_down );
123         if (state_left  != old_state_left ) vkey_handler(KEY_JB1 + hat + 3, state_left );
124 }
125
126 void joy_axis_handler(SDL_JoyAxisEvent *jae)
127 {
128         int axis;
129
130         axis = SDL_Joysticks[jae->which].axis_map[jae->axis];
131         
132         Joystick.axes[axis].value = jae->value;
133 }
134
135
136 /* ----------------------------------------------- */
137
138 int joy_init()
139 {
140         int i,j,n;
141         char temp[10];
142
143         if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
144                 con_printf(CON_VERBOSE, "sdl-joystick: initialisation failed: %s.",SDL_GetError());
145                 return 0;
146         }
147
148         memset(&Joystick,0,sizeof(Joystick));
149         memset(joyaxis_text, 0, JOY_MAX_AXES * sizeof(char *));
150
151         for (i = 0; i < 6; i++) {
152                 cvar_registervariable(&joy_advaxes[i]);
153                 cvar_registervariable(&joy_invert[i]);
154         }
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%dB%d", i + 1, j + 1);
202                                 key_text[KEY_JB1 + 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
210                                 sprintf(temp, "J%dH%dUP", i + 1, j + 1);
211                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
212                                 Joystick.n_buttons++;
213
214                                 sprintf(temp, "J%dH%dRIGHT", i + 1, j + 1);
215                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
216                                 Joystick.n_buttons++;
217
218                                 sprintf(temp, "J%dH%dDOWN", i + 1, j + 1);
219                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
220                                 Joystick.n_buttons++;
221
222                                 sprintf(temp, "J%dH%dLEFT", i + 1, j + 1);
223                                 key_text[KEY_JB1 + Joystick.n_buttons] = d_strdup(temp);
224                                 Joystick.n_buttons++;
225                         }
226
227                         num_joysticks++;
228                 }
229                 else
230                         con_printf(CON_VERBOSE, "sdl-joystick: initialization failed!\n");
231
232                 con_printf(CON_VERBOSE, "sdl-joystick: %d axes (total)\n", Joystick.n_axes);
233                 con_printf(CON_VERBOSE, "sdl-joystick: %d buttons (total)\n", Joystick.n_buttons);
234         }
235
236         joy_num_axes = Joystick.n_axes;
237         atexit(joy_close);
238
239         return joy_present;
240 }
241
242 void joy_close()
243 {
244         while (num_joysticks)
245                 SDL_JoystickClose(SDL_Joysticks[--num_joysticks].handle);
246         while (Joystick.n_axes--)
247                 d_free(joyaxis_text[Joystick.n_axes]);
248         while (Joystick.n_buttons--)
249                 d_free(key_text[KEY_JB1 + Joystick.n_buttons]);
250 }
251
252 void joy_get_pos(int *x, int *y)
253 {
254         int axis[JOY_MAX_AXES];
255
256         if (!num_joysticks) {
257                 *x=*y=0;
258                 return;
259         }
260
261         joystick_read_raw_axis (JOY_ALL_AXIS, axis);
262
263         *x = joy_get_scaled_reading( axis[0], 0 );
264         *y = joy_get_scaled_reading( axis[1], 1 );
265 }
266
267 int joy_get_btns()
268 {
269 #if 0 // This is never used?
270         int i, buttons = 0;
271         for (i=0; i++; i<buttons) {
272                 switch (keyd_pressed[KEY_JB1 + i]) {
273                 case 1:
274                         buttons |= 1<<i;
275                         break;
276                 case 0:
277                         break;
278                 }
279         }
280         return buttons;
281 #else
282         return 0;
283 #endif
284 }
285
286
287 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
288 {
289         int i;
290         ubyte channel_masks = 0;
291         
292         if (!num_joysticks)
293                 return 0;
294
295         event_poll();
296
297         for (i = 0; i < Joystick.n_axes; i++)
298         {
299                 if ((axis[i] = Joystick.axes[i].value))
300                         channel_masks |= 1 << i;
301         }
302
303         return channel_masks;
304 }
305
306 void joy_flush()
307 {
308         if (!num_joysticks)
309                 return;
310 }
311
312 int joy_get_button_state( int btn )
313 {
314         if (!num_joysticks)
315                 return 0;
316
317         if(btn >= Joystick.n_buttons)
318                 return 0;
319
320         event_poll();
321
322         return keyd_pressed[KEY_JB1 + btn];
323 }
324
325 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
326 {
327         int i;
328
329         for (i = 0; i < Joystick.n_axes; i++)
330         {
331                 axis_center[i] = Joystick.axes[i].center_val;
332                 axis_min[i] = Joystick.axes[i].min_val;
333                 axis_max[i] = Joystick.axes[i].max_val;
334         }
335 }
336
337 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
338 {
339         int i;
340
341         for (i = 0; i < Joystick.n_axes; i++)
342         {
343                 Joystick.axes[i].center_val = axis_center[i];
344                 Joystick.axes[i].min_val = axis_min[i];
345                 Joystick.axes[i].max_val = axis_max[i];
346         }
347 }
348
349 int joy_get_scaled_reading( int raw, int axis_num )
350 {
351 #if 1
352         return raw/256;
353 #else
354         int d, x;
355
356         raw -= Joystick.axes[axis_num].center_val;
357         
358         if (raw < 0)
359                 d = Joystick.axes[axis_num].center_val - Joystick.axes[axis_num].min_val;
360         else if (raw > 0)
361                 d = Joystick.axes[axis_num].max_val - Joystick.axes[axis_num].center_val;
362         else
363                 d = 0;
364         
365         if (d)
366                 x = ((raw << 7) / d);
367         else
368                 x = 0;
369         
370         if ( x < -128 )
371                 x = -128;
372         if ( x > 127 )
373                 x = 127;
374         
375         d =  (joy_deadzone) * 6;
376         if ((x > (-1*d)) && (x < d))
377                 x = 0;
378         
379         return x;
380 #endif
381 }
382
383 void joy_set_slow_reading( int flag )
384 {
385 }