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