rnd-20020323-2-src
[rocksndiamonds.git] / src / libgame / joystick.c
1 /***********************************************************
2 * Artsoft Retro-Game Library                               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * joystick.c                                               *
12 ***********************************************************/
13
14 #if defined(PLATFORM_FREEBSD)
15 #include <machine/joystick.h>
16 #endif
17
18 #include "joystick.h"
19 #include "misc.h"
20
21
22 #define TRANSLATE_JOYSYMBOL_TO_JOYNAME  0
23 #define TRANSLATE_JOYNAME_TO_JOYSYMBOL  1
24
25 #if 0
26 static int joystick_device = 0;
27 char *joystick_device_name[MAX_PLAYERS] =
28 {
29   DEV_JOYSTICK_0,
30   DEV_JOYSTICK_1,
31   DEV_JOYSTICK_2,
32   DEV_JOYSTICK_3
33 };
34 #endif
35
36
37 void translate_joyname(int *joysymbol, char **name, int mode)
38 {
39   static struct
40   {
41     int joysymbol;
42     char *name;
43   } translate_joy[] =
44   {
45     { JOY_LEFT,         "joystick_left" },
46     { JOY_RIGHT,        "joystick_right" },
47     { JOY_UP,           "joystick_up" },
48     { JOY_DOWN,         "joystick_down" },
49     { JOY_BUTTON_1,     "joystick_button_1" },
50     { JOY_BUTTON_2,     "joystick_button_2" },
51   };
52
53   int i;
54
55   if (mode == TRANSLATE_JOYSYMBOL_TO_JOYNAME)
56   {
57     *name = "[undefined]";
58
59     for (i=0; i<6; i++)
60     {
61       if (*joysymbol == translate_joy[i].joysymbol)
62       {
63         *name = translate_joy[i].name;
64         break;
65       }
66     }
67   }
68   else if (mode == TRANSLATE_JOYNAME_TO_JOYSYMBOL)
69   {
70     *joysymbol = 0;
71
72     for (i=0; i<6; i++)
73     {
74       if (strcmp(*name, translate_joy[i].name) == 0)
75       {
76         *joysymbol = translate_joy[i].joysymbol;
77         break;
78       }
79     }
80   }
81 }
82
83 char *getJoyNameFromJoySymbol(int joysymbol)
84 {
85   char *name;
86
87   translate_joyname(&joysymbol, &name, TRANSLATE_JOYSYMBOL_TO_JOYNAME);
88   return name;
89 }
90
91 int getJoySymbolFromJoyName(char *name)
92 {
93   int joysymbol;
94
95   translate_joyname(&joysymbol, &name, TRANSLATE_JOYNAME_TO_JOYSYMBOL);
96   return joysymbol;
97 }
98
99 int getJoystickNrFromDeviceName(char *device_name)
100 {
101   char c;
102   int joystick_nr = 0;
103
104   if (device_name == NULL || device_name[0] == '\0')
105     return 0;
106
107   c = device_name[strlen(device_name) - 1];
108
109   if (c >= '0' && c <= '9')
110     joystick_nr = (int)(c - '0');
111
112   if (joystick_nr < 0 || joystick_nr >= MAX_PLAYERS)
113     joystick_nr = 0;
114
115   return joystick_nr;
116 }
117
118 char *getDeviceNameFromJoystickNr(int joystick_nr)
119 {
120   static char *joystick_device_name[MAX_PLAYERS] =
121   {
122     DEV_JOYSTICK_0,
123     DEV_JOYSTICK_1,
124     DEV_JOYSTICK_2,
125     DEV_JOYSTICK_3
126   };
127
128   return (joystick_nr >= 0 && joystick_nr <= 3 ?
129           joystick_device_name[joystick_nr] : "");
130 }
131
132 #if !defined(PLATFORM_MSDOS)
133 static int JoystickPosition(int middle, int margin, int actual)
134 {
135   long range, pos;
136   int percentage;
137
138   if (margin < middle && actual > middle)
139     return 0;
140   if (margin > middle && actual < middle)
141     return 0;
142
143   range = ABS(margin - middle);
144   pos = ABS(actual - middle);
145   percentage = (int)(pos * 100 / range);
146
147   if (percentage > 100)
148     percentage = 100;
149
150   return percentage;
151 }
152 #endif
153
154 #if defined(TARGET_SDL)
155
156 static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
157 static int sdl_js_axis[MAX_PLAYERS][2]   = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
158 static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
159
160 SDL_Joystick *Get_SDL_Joystick(int nr)
161 {
162   return sdl_joystick[nr];
163 }
164
165 boolean Open_SDL_Joystick(int nr)
166 {
167   if (nr < 0 || nr > MAX_PLAYERS)
168     return FALSE;
169
170   return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
171 }
172
173 void Close_SDL_Joystick(int nr)
174 {
175   if (nr < 0 || nr > MAX_PLAYERS)
176     return;
177
178   SDL_JoystickClose(sdl_joystick[nr]);
179 }
180
181 boolean Check_SDL_JoystickOpened(int nr)
182 {
183   if (nr < 0 || nr > MAX_PLAYERS)
184     return FALSE;
185
186   return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
187 }
188
189 void HandleJoystickEvent(Event *event)
190 {
191   switch(event->type)
192   {
193     case SDL_JOYAXISMOTION:
194       if (event->jaxis.axis < 2)
195       {
196         sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
197
198 #if 0
199         printf("js_%d %s-axis: %d\n",
200                event->jaxis.which,
201                (event->jaxis.axis == 0 ? "x" : "y"),
202                event->jaxis.value);
203 #endif
204       }
205       break;
206
207     case SDL_JOYBUTTONDOWN:
208       if (event->jbutton.button < 2)
209       {
210         sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
211
212 #if 0
213         printf("js_%d button %d: pressed\n",
214                event->jbutton.which,
215                event->jbutton.button);
216 #endif
217       }
218       break;
219
220     case SDL_JOYBUTTONUP:
221       if (event->jbutton.button < 2)
222       {
223         sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
224
225 #if 0
226         printf("js_%d button %d: released\n",
227                event->jbutton.which,
228                event->jbutton.button);
229 #endif
230       }
231       break;
232
233     default:
234       break;
235   }
236 }
237
238 int Get_SDL_Joystick_Axis(int nr, int axis)
239 {
240   if (nr < 0 || nr > MAX_PLAYERS)
241     return 0;
242
243   if (axis < 0 || axis > 1)
244     return 0;
245
246   return sdl_js_axis[nr][axis];
247 }
248
249 void CheckJoystickData()
250 {
251 }
252
253 int Joystick(int player_nr)
254 {
255 #if 0
256   int joystick_nr = stored_player[player_nr].joystick_fd;
257 #else
258   int joystick_nr = joystick.fd[player_nr];
259 #endif
260   int js_x,js_y, js_b1,js_b2;
261   int left, right, up, down;
262   int result = 0;
263
264   if (joystick.status != JOYSTICK_ACTIVATED)
265     return 0;
266
267   if (!setup.input[player_nr].use_joystick ||
268       !Check_SDL_JoystickOpened(joystick_nr))
269     return 0;
270
271   js_x  = sdl_js_axis[joystick_nr][0];
272   js_y  = sdl_js_axis[joystick_nr][1];
273
274   js_b1 = sdl_js_button[joystick_nr][0];
275   js_b2 = sdl_js_button[joystick_nr][1];
276
277
278
279 #if 0
280   printf("JOYSTICK %d: js_x == %d, js_y == %d, js_b1 == %d, js_b2 == %d\n",
281          joystick_nr, js_x, js_y, js_b1, js_b2);
282 #endif
283
284
285
286   left  = JoystickPosition(setup.input[player_nr].joy.xmiddle,
287                            setup.input[player_nr].joy.xleft,  js_x);
288   right = JoystickPosition(setup.input[player_nr].joy.xmiddle,
289                            setup.input[player_nr].joy.xright, js_x);
290   up    = JoystickPosition(setup.input[player_nr].joy.ymiddle,
291                            setup.input[player_nr].joy.yupper, js_y);
292   down  = JoystickPosition(setup.input[player_nr].joy.ymiddle,
293                            setup.input[player_nr].joy.ylower, js_y);
294
295   if (left > JOYSTICK_PERCENT)
296     result |= JOY_LEFT;
297   else if (right > JOYSTICK_PERCENT)
298     result |= JOY_RIGHT;
299   if (up > JOYSTICK_PERCENT)
300     result |= JOY_UP;
301   else if (down > JOYSTICK_PERCENT)
302     result |= JOY_DOWN;
303
304   if (js_b1)
305     result |= JOY_BUTTON_1;
306   if (js_b2)
307     result |= JOY_BUTTON_2;
308
309
310
311 #if 0
312   printf("result == 0x%08x\n", result);
313 #endif
314
315
316
317   return result;
318 }
319
320 #else /* !TARGET_SDL */
321
322 void CheckJoystickData()
323 {
324   int i;
325   int distance = 100;
326
327   for(i=0; i<MAX_PLAYERS; i++)
328   {
329     if (setup.input[i].joy.xmiddle <= distance)
330       setup.input[i].joy.xmiddle = distance;
331     if (setup.input[i].joy.ymiddle <= distance)
332       setup.input[i].joy.ymiddle = distance;
333
334     if (setup.input[i].joy.xleft >= setup.input[i].joy.xmiddle)
335       setup.input[i].joy.xleft = setup.input[i].joy.xmiddle - distance;
336     if (setup.input[i].joy.xright <= setup.input[i].joy.xmiddle)
337       setup.input[i].joy.xright = setup.input[i].joy.xmiddle + distance;
338
339     if (setup.input[i].joy.yupper >= setup.input[i].joy.ymiddle)
340       setup.input[i].joy.yupper = setup.input[i].joy.ymiddle - distance;
341     if (setup.input[i].joy.ylower <= setup.input[i].joy.ymiddle)
342       setup.input[i].joy.ylower = setup.input[i].joy.ymiddle + distance;
343   }
344 }
345
346 #if defined(PLATFORM_UNIX)
347 int Joystick(int player_nr)
348 {
349 #if defined(PLATFORM_FREEBSD)
350   struct joystick joy_ctrl;
351 #else
352   struct joystick_control
353   {
354     int buttons;
355     int x;
356     int y;
357   } joy_ctrl;
358 #endif
359
360 #if 0
361   int joystick_fd = stored_player[player_nr].joystick_fd;
362 #else
363   int joystick_fd = joystick.fd[player_nr];
364 #endif
365   int js_x,js_y, js_b1,js_b2;
366   int left, right, up, down;
367   int result = 0;
368
369   if (joystick.status != JOYSTICK_ACTIVATED)
370     return 0;
371
372   if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
373     return 0;
374
375   if (read(joystick_fd, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
376   {
377     Error(ERR_WARN, "cannot read joystick device '%s'",
378           setup.input[player_nr].joy.device_name);
379     joystick.status = JOYSTICK_NOT_AVAILABLE;
380     return 0;
381   }
382
383   js_x  = joy_ctrl.x;
384   js_y  = joy_ctrl.y;
385
386 #if defined(PLATFORM_FREEBSD)
387   js_b1 = joy_ctrl.b1;
388   js_b2 = joy_ctrl.b2;
389 #else
390   js_b1 = joy_ctrl.buttons & 1;
391   js_b2 = joy_ctrl.buttons & 2;
392 #endif
393
394   left  = JoystickPosition(setup.input[player_nr].joy.xmiddle,
395                            setup.input[player_nr].joy.xleft,  js_x);
396   right = JoystickPosition(setup.input[player_nr].joy.xmiddle,
397                            setup.input[player_nr].joy.xright, js_x);
398   up    = JoystickPosition(setup.input[player_nr].joy.ymiddle,
399                            setup.input[player_nr].joy.yupper, js_y);
400   down  = JoystickPosition(setup.input[player_nr].joy.ymiddle,
401                            setup.input[player_nr].joy.ylower, js_y);
402
403   if (left > JOYSTICK_PERCENT)
404     result |= JOY_LEFT;
405   else if (right > JOYSTICK_PERCENT)
406     result |= JOY_RIGHT;
407   if (up > JOYSTICK_PERCENT)
408     result |= JOY_UP;
409   else if (down > JOYSTICK_PERCENT)
410     result |= JOY_DOWN;
411
412   if (js_b1)
413     result |= JOY_BUTTON_1;
414   if (js_b2)
415     result |= JOY_BUTTON_2;
416
417   return result;
418 }
419
420 #else /* PLATFORM_MSDOS */
421
422 /* allegro global variables for joystick control */
423 extern int num_joysticks;
424 extern JOYSTICK_INFO joy[];
425
426 int Joystick(int player_nr)
427 {
428 #if 0
429   int joystick_nr = stored_player[player_nr].joystick_fd;
430 #else
431   int joystick_nr = joystick.fd[player_nr];
432 #endif
433   int result = 0;
434
435   if (joystick.status != JOYSTICK_ACTIVATED)
436     return 0;
437
438   if (joystick_nr < 0)
439     return 0;
440
441   /* the allegro global variable 'num_joysticks' contains the number
442      of joysticks found at initialization under MS-DOS / Windows */
443
444 #if 0
445   if (joystick_nr >= num_joysticks || !setup.input[player_nr].use_joystick)
446     return 0;
447 #else
448
449 #if 1
450   /*
451   if (joystick_nr >= num_joysticks ||
452       (game_status == PLAYING && !setup.input[player_nr].use_joystick))
453     return 0;
454   */
455
456   if (joystick_nr >= num_joysticks || !setup.input[player_nr].use_joystick)
457     return 0;
458
459 #else
460   if (joystick_nr >= num_joysticks)
461     return 0;
462 #endif
463
464 #endif
465
466   poll_joystick();
467
468   if (joy[joystick_nr].stick[0].axis[0].d1)
469     result |= JOY_LEFT;
470   else if (joy[joystick_nr].stick[0].axis[0].d2)
471     result |= JOY_RIGHT;
472   if (joy[joystick_nr].stick[0].axis[1].d1)
473     result |= JOY_UP;
474   else if (joy[joystick_nr].stick[0].axis[1].d2)
475     result |= JOY_DOWN;
476
477   if (joy[joystick_nr].button[0].b)
478     result |= JOY_BUTTON_1;
479   if (joy[joystick_nr].button[1].b)
480     result |= JOY_BUTTON_2;
481
482   return result;
483 }
484 #endif /* PLATFORM_MSDOS */
485
486 #endif /* !TARGET_SDL */
487
488 int JoystickButton(int player_nr)
489 {
490   static int last_joy_button[MAX_PLAYERS] = { 0, 0, 0, 0 };
491   int joy_button = (Joystick(player_nr) & JOY_BUTTON);
492   int result;
493
494   if (joy_button)
495   {
496     if (last_joy_button[player_nr])
497       result = JOY_BUTTON_PRESSED;
498     else
499       result = JOY_BUTTON_NEW_PRESSED;
500   }
501   else
502   {
503     if (last_joy_button[player_nr])
504       result = JOY_BUTTON_NEW_RELEASED;
505     else
506       result = JOY_BUTTON_NOT_PRESSED;
507   }
508
509   last_joy_button[player_nr] = joy_button;
510   return result;
511 }
512
513 int AnyJoystick()
514 {
515   int i;
516   int result = 0;
517
518   for (i=0; i<MAX_PLAYERS; i++)
519   {
520
521     /*
522     if (!setup.input[i].use_joystick)
523       continue;
524       */
525
526
527     result |= Joystick(i);
528   }
529
530   return result;
531 }
532
533 int AnyJoystickButton()
534 {
535   int i;
536   int result;
537
538   for (i=0; i<MAX_PLAYERS; i++)
539   {
540
541     /*
542     if (!setup.input[i].use_joystick)
543       continue;
544       */
545
546     /*
547     result |= JoystickButton(i);
548     */
549
550     result = JoystickButton(i);
551     if (result != JOY_BUTTON_NOT_PRESSED)
552       break;
553   }
554
555   return result;
556 }
557
558 void DeactivateJoystickForCalibration()
559 {
560   /* Temporarily deactivate joystick. This is needed for calibration
561      screens, where the player has to select a joystick device that
562      should be calibrated. If there is a totally uncalibrated joystick
563      active, it may be impossible (due to messed up input from joystick)
564      to select the joystick device to calibrate even when trying to use
565      the mouse or keyboard to select the device. */
566
567   if (joystick.status & JOYSTICK_AVAILABLE)
568     joystick.status &= ~JOYSTICK_ACTIVE;
569 }
570
571 void ActivateJoystickIfAvailable()
572 {
573   /* reactivate temporarily deactivated joystick */
574
575   if (joystick.status & JOYSTICK_AVAILABLE)
576     joystick.status |= JOYSTICK_ACTIVE;
577 }