0966b94934ed68b664acdd71cbc8af2213d09d02
[rocksndiamonds.git] / src / libgame / joystick.c
1 /***********************************************************
2 * Artsoft Retro-Game Library                               *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 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 /* ========================================================================= */
23 /* platform independent joystick functions                                   */
24 /* ========================================================================= */
25
26 #define TRANSLATE_JOYSYMBOL_TO_JOYNAME  0
27 #define TRANSLATE_JOYNAME_TO_JOYSYMBOL  1
28
29 void translate_joyname(int *joysymbol, char **name, int mode)
30 {
31   static struct
32   {
33     int joysymbol;
34     char *name;
35   } translate_joy[] =
36   {
37     { JOY_LEFT,         "joystick_left" },
38     { JOY_RIGHT,        "joystick_right" },
39     { JOY_UP,           "joystick_up" },
40     { JOY_DOWN,         "joystick_down" },
41     { JOY_BUTTON_1,     "joystick_button_1" },
42     { JOY_BUTTON_2,     "joystick_button_2" },
43   };
44
45   int i;
46
47   if (mode == TRANSLATE_JOYSYMBOL_TO_JOYNAME)
48   {
49     *name = "[undefined]";
50
51     for (i = 0; i < 6; i++)
52     {
53       if (*joysymbol == translate_joy[i].joysymbol)
54       {
55         *name = translate_joy[i].name;
56         break;
57       }
58     }
59   }
60   else if (mode == TRANSLATE_JOYNAME_TO_JOYSYMBOL)
61   {
62     *joysymbol = 0;
63
64     for (i = 0; i < 6; i++)
65     {
66       if (strEqual(*name, translate_joy[i].name))
67       {
68         *joysymbol = translate_joy[i].joysymbol;
69         break;
70       }
71     }
72   }
73 }
74
75 char *getJoyNameFromJoySymbol(int joysymbol)
76 {
77   char *name;
78
79   translate_joyname(&joysymbol, &name, TRANSLATE_JOYSYMBOL_TO_JOYNAME);
80   return name;
81 }
82
83 int getJoySymbolFromJoyName(char *name)
84 {
85   int joysymbol;
86
87   translate_joyname(&joysymbol, &name, TRANSLATE_JOYNAME_TO_JOYSYMBOL);
88   return joysymbol;
89 }
90
91 int getJoystickNrFromDeviceName(char *device_name)
92 {
93   char c;
94   int joystick_nr = 0;
95
96   if (device_name == NULL || device_name[0] == '\0')
97     return 0;
98
99   c = device_name[strlen(device_name) - 1];
100
101   if (c >= '0' && c <= '9')
102     joystick_nr = (int)(c - '0');
103
104   if (joystick_nr < 0 || joystick_nr >= MAX_PLAYERS)
105     joystick_nr = 0;
106
107   return joystick_nr;
108 }
109
110 char *getDeviceNameFromJoystickNr(int joystick_nr)
111 {
112   static char *joystick_device_name[MAX_PLAYERS] =
113   {
114     DEV_JOYSTICK_0,
115     DEV_JOYSTICK_1,
116     DEV_JOYSTICK_2,
117     DEV_JOYSTICK_3
118   };
119
120   return (joystick_nr >= 0 && joystick_nr <= 3 ?
121           joystick_device_name[joystick_nr] : "");
122 }
123
124 static int JoystickPositionPercent(int center, int border, int actual)
125 {
126   int range, position;
127   int percent;
128
129   if (border < center && actual > center)
130     return 0;
131   if (border > center && actual < center)
132     return 0;
133
134   range = ABS(border - center);
135   position = ABS(actual - center);
136
137   percent = (int)(position * 100 / range);
138
139   if (percent > 100)
140     percent = 100;
141
142   return percent;
143 }
144
145 void CheckJoystickData()
146 {
147   int i;
148   int distance = 100;
149
150   for (i = 0; i < MAX_PLAYERS; i++)
151   {
152     if (setup.input[i].joy.xleft >= setup.input[i].joy.xmiddle)
153       setup.input[i].joy.xleft = setup.input[i].joy.xmiddle - distance;
154     if (setup.input[i].joy.xright <= setup.input[i].joy.xmiddle)
155       setup.input[i].joy.xright = setup.input[i].joy.xmiddle + distance;
156
157     if (setup.input[i].joy.yupper >= setup.input[i].joy.ymiddle)
158       setup.input[i].joy.yupper = setup.input[i].joy.ymiddle - distance;
159     if (setup.input[i].joy.ylower <= setup.input[i].joy.ymiddle)
160       setup.input[i].joy.ylower = setup.input[i].joy.ymiddle + distance;
161   }
162 }
163
164 int Joystick(int player_nr)
165 {
166   int joystick_fd = joystick.fd[player_nr];
167   int js_x, js_y;
168   boolean js_b1, js_b2;
169   int left, right, up, down;
170   int result = JOY_NO_ACTION;
171
172   if (joystick.status != JOYSTICK_ACTIVATED)
173     return JOY_NO_ACTION;
174
175   if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
176     return JOY_NO_ACTION;
177
178   if (!ReadJoystick(joystick_fd, &js_x, &js_y, &js_b1, &js_b2))
179   {
180     Error(ERR_WARN, "cannot read joystick device '%s'",
181           setup.input[player_nr].joy.device_name);
182
183     joystick.status = JOYSTICK_NOT_AVAILABLE;
184     return JOY_NO_ACTION;
185   }
186
187   left  = JoystickPositionPercent(setup.input[player_nr].joy.xmiddle,
188                                   setup.input[player_nr].joy.xleft,  js_x);
189   right = JoystickPositionPercent(setup.input[player_nr].joy.xmiddle,
190                                   setup.input[player_nr].joy.xright, js_x);
191   up    = JoystickPositionPercent(setup.input[player_nr].joy.ymiddle,
192                                   setup.input[player_nr].joy.yupper, js_y);
193   down  = JoystickPositionPercent(setup.input[player_nr].joy.ymiddle,
194                                   setup.input[player_nr].joy.ylower, js_y);
195
196   if (left > JOYSTICK_PERCENT)
197     result |= JOY_LEFT;
198   else if (right > JOYSTICK_PERCENT)
199     result |= JOY_RIGHT;
200   if (up > JOYSTICK_PERCENT)
201     result |= JOY_UP;
202   else if (down > JOYSTICK_PERCENT)
203     result |= JOY_DOWN;
204
205   if (js_b1)
206     result |= JOY_BUTTON_1;
207   if (js_b2)
208     result |= JOY_BUTTON_2;
209
210   return result;
211 }
212
213 int JoystickButton(int player_nr)
214 {
215   static int last_joy_button[MAX_PLAYERS] = { 0, 0, 0, 0 };
216   int joy_button = (Joystick(player_nr) & JOY_BUTTON);
217   int result;
218
219   if (joy_button)
220   {
221     if (last_joy_button[player_nr])
222       result = JOY_BUTTON_PRESSED;
223     else
224       result = JOY_BUTTON_NEW_PRESSED;
225   }
226   else
227   {
228     if (last_joy_button[player_nr])
229       result = JOY_BUTTON_NEW_RELEASED;
230     else
231       result = JOY_BUTTON_NOT_PRESSED;
232   }
233
234   last_joy_button[player_nr] = joy_button;
235   return result;
236 }
237
238 int AnyJoystick()
239 {
240   int i;
241   int result = 0;
242
243   for (i = 0; i < MAX_PLAYERS; i++)
244     result |= Joystick(i);
245
246   return result;
247 }
248
249 int AnyJoystickButton()
250 {
251   int i;
252   int result = JOY_BUTTON_NOT_PRESSED;
253
254   for (i = 0; i < MAX_PLAYERS; i++)
255   {
256     result = JoystickButton(i);
257     if (result != JOY_BUTTON_NOT_PRESSED)
258       break;
259   }
260
261   return result;
262 }
263
264 void DeactivateJoystick()
265 {
266   /* Temporarily deactivate joystick. This is needed for calibration
267      screens, where the player has to select a joystick device that
268      should be calibrated. If there is a totally uncalibrated joystick
269      active, it may be impossible (due to messed up input from joystick)
270      to select the joystick device to calibrate even when trying to use
271      the mouse or keyboard to select the device. */
272
273   if (joystick.status & JOYSTICK_AVAILABLE)
274     joystick.status &= ~JOYSTICK_ACTIVE;
275 }
276
277 void ActivateJoystick()
278 {
279   /* reactivate temporarily deactivated joystick */
280
281   if (joystick.status & JOYSTICK_AVAILABLE)
282     joystick.status |= JOYSTICK_ACTIVE;
283 }