1 /* $Id: joy.c,v 1.12 2003/04/12 00:11:46 btb Exp $ */
2 /*
3  *
4  * SDL joystick support
5  *
6  *
7  */
8 
9 #ifdef HAVE_CONFIG_H
10 #include <conf.h>
11 #endif
12 
13 #include <string.h>   // for memset
14 #include <SDL.h>
15 
16 #include "joy.h"
17 #include "error.h"
18 #include "timer.h"
19 #include "console.h"
20 #include "event.h"
21 #include "text.h"
22 
23 #define MAX_JOYSTICKS 16
24 #define MAX_AXES 32
25 
26 #define MAX_AXES_PER_JOYSTICK 8
27 #define MAX_BUTTONS_PER_JOYSTICK 16
28 #define MAX_HATS_PER_JOYSTICK 4
29 
30 extern int joybutton_text[]; //from kconfig.c
31 
32 char joy_present = 0;
33 int num_joysticks = 0;
34 
35 int joy_deadzone = 0;
36 
37 struct joybutton {
38 	int state;
39 	int last_state;
40 	fix time_went_down;
41 	int num_downs;
42 	int num_ups;
43 };
44 
45 struct joyaxis {
46 	int		value;
47 	int		min_val;
48 	int		center_val;
49 	int		max_val;
50 };
51 
52 static struct joyinfo {
53 	int n_axes;
54 	int n_buttons;
55 	struct joyaxis axes[MAX_AXES];
56 	struct joybutton buttons[MAX_BUTTONS];
57 } Joystick;
58 
59 static struct {
60 	SDL_Joystick *handle;
61 	int n_axes;
62 	int n_buttons;
63 	int n_hats;
64 	int hat_map[MAX_HATS_PER_JOYSTICK];  //Note: Descent expects hats to be buttons, so these are indices into Joystick.buttons
65 	int axis_map[MAX_AXES_PER_JOYSTICK];
66 	int button_map[MAX_BUTTONS_PER_JOYSTICK];
67 } SDL_Joysticks[MAX_JOYSTICKS];
68 
joy_button_handler(SDL_JoyButtonEvent * jbe)69 void joy_button_handler(SDL_JoyButtonEvent *jbe)
70 {
71 	int button;
72 
73 	button = SDL_Joysticks[jbe->which].button_map[jbe->button];
74 
75 	Joystick.buttons[button].state = jbe->state;
76 
77 	switch (jbe->type) {
78 	case SDL_JOYBUTTONDOWN:
79 		Joystick.buttons[button].time_went_down
80 			= timer_get_fixed_seconds();
81 		Joystick.buttons[button].num_downs++;
82 		break;
83 	case SDL_JOYBUTTONUP:
84 		Joystick.buttons[button].num_ups++;
85 		break;
86 	}
87 }
88 
joy_hat_handler(SDL_JoyHatEvent * jhe)89 void joy_hat_handler(SDL_JoyHatEvent *jhe)
90 {
91 	int hat = SDL_Joysticks[jhe->which].hat_map[jhe->hat];
92 	int hbi;
93 
94 	//Save last state of the hat-button
95 	Joystick.buttons[hat  ].last_state = Joystick.buttons[hat  ].state;
96 	Joystick.buttons[hat+1].last_state = Joystick.buttons[hat+1].state;
97 	Joystick.buttons[hat+2].last_state = Joystick.buttons[hat+2].state;
98 	Joystick.buttons[hat+3].last_state = Joystick.buttons[hat+3].state;
99 
100 	//get current state of the hat-button
101 	Joystick.buttons[hat  ].state = ((jhe->value & SDL_HAT_UP)>0);
102 	Joystick.buttons[hat+1].state = ((jhe->value & SDL_HAT_RIGHT)>0);
103 	Joystick.buttons[hat+2].state = ((jhe->value & SDL_HAT_DOWN)>0);
104 	Joystick.buttons[hat+3].state = ((jhe->value & SDL_HAT_LEFT)>0);
105 
106 	//determine if a hat-button up or down event based on state and last_state
107 	for(hbi=0;hbi<4;hbi++)
108 	{
109 		if(	!Joystick.buttons[hat+hbi].last_state && Joystick.buttons[hat+hbi].state) //last_state up, current state down
110 		{
111 			Joystick.buttons[hat+hbi].time_went_down
112 				= timer_get_fixed_seconds();
113 			Joystick.buttons[hat+hbi].num_downs++;
114 		}
115 		else if(Joystick.buttons[hat+hbi].last_state && !Joystick.buttons[hat+hbi].state)  //last_state down, current state up
116 		{
117 			Joystick.buttons[hat+hbi].num_ups++;
118 		}
119 	}
120 }
121 
joy_axis_handler(SDL_JoyAxisEvent * jae)122 void joy_axis_handler(SDL_JoyAxisEvent *jae)
123 {
124 	int axis;
125 
126 	axis = SDL_Joysticks[jae->which].axis_map[jae->axis];
127 
128 	Joystick.axes[axis].value = jae->value;
129 }
130 
131 
132 /* ----------------------------------------------- */
133 
joy_init()134 int joy_init()
135 {
136 	int i,j,n;
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 
145 	n = SDL_NumJoysticks();
146 
147 	con_printf(CON_VERBOSE, "sdl-joystick: found %d joysticks\n", n);
148 	for (i = 0; i < n; i++) {
149 		con_printf(CON_VERBOSE, "sdl-joystick %d: %s\n", i, SDL_JoystickName(i));
150 		SDL_Joysticks[num_joysticks].handle = SDL_JoystickOpen(i);
151 		if (SDL_Joysticks[num_joysticks].handle) {
152 			joy_present = 1;
153 
154 			SDL_Joysticks[num_joysticks].n_axes
155 				= SDL_JoystickNumAxes(SDL_Joysticks[num_joysticks].handle);
156 			if(SDL_Joysticks[num_joysticks].n_axes > MAX_AXES_PER_JOYSTICK)
157 			{
158 				Warning("sdl-joystick: found %d axes, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_axes, MAX_AXES_PER_JOYSTICK);
159 				SDL_Joysticks[num_joysticks].n_axes = MAX_AXES_PER_JOYSTICK;
160 			}
161 
162 			SDL_Joysticks[num_joysticks].n_buttons
163 				= SDL_JoystickNumButtons(SDL_Joysticks[num_joysticks].handle);
164 			if(SDL_Joysticks[num_joysticks].n_buttons > MAX_BUTTONS_PER_JOYSTICK)
165 			{
166 				Warning("sdl-joystick: found %d buttons, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_buttons, MAX_BUTTONS_PER_JOYSTICK);
167 				SDL_Joysticks[num_joysticks].n_buttons = MAX_BUTTONS_PER_JOYSTICK;
168 			}
169 
170 			SDL_Joysticks[num_joysticks].n_hats
171 				= SDL_JoystickNumHats(SDL_Joysticks[num_joysticks].handle);
172 			if(SDL_Joysticks[num_joysticks].n_hats > MAX_HATS_PER_JOYSTICK)
173 			{
174 				Warning("sdl-joystick: found %d hats, only %d supported.  Game may be unstable.\n", SDL_Joysticks[num_joysticks].n_hats, MAX_HATS_PER_JOYSTICK);
175 				SDL_Joysticks[num_joysticks].n_hats = MAX_HATS_PER_JOYSTICK;
176 			}
177 
178 			con_printf(CON_VERBOSE, "sdl-joystick: %d axes\n", SDL_Joysticks[num_joysticks].n_axes);
179 			con_printf(CON_VERBOSE, "sdl-joystick: %d buttons\n", SDL_Joysticks[num_joysticks].n_buttons);
180 			con_printf(CON_VERBOSE, "sdl-joystick: %d hats\n", SDL_Joysticks[num_joysticks].n_hats);
181 
182 			for (j=0; j < SDL_Joysticks[num_joysticks].n_axes; j++)
183 				SDL_Joysticks[num_joysticks].axis_map[j] = Joystick.n_axes++;
184 			for (j=0; j < SDL_Joysticks[num_joysticks].n_buttons; j++)
185 				SDL_Joysticks[num_joysticks].button_map[j] = Joystick.n_buttons++;
186 			for (j=0; j < SDL_Joysticks[num_joysticks].n_hats; j++)
187 			{
188 				SDL_Joysticks[num_joysticks].hat_map[j] = Joystick.n_buttons;
189 				//a hat counts as four buttons
190 				joybutton_text[Joystick.n_buttons++] = j?TNUM_HAT2_U:TNUM_HAT_U;
191 				joybutton_text[Joystick.n_buttons++] = j?TNUM_HAT2_R:TNUM_HAT_R;
192 				joybutton_text[Joystick.n_buttons++] = j?TNUM_HAT2_D:TNUM_HAT_D;
193 				joybutton_text[Joystick.n_buttons++] = j?TNUM_HAT2_L:TNUM_HAT_L;
194 			}
195 
196 			num_joysticks++;
197 		}
198 		else
199 			con_printf(CON_VERBOSE, "sdl-joystick: initialization failed!\n");
200 
201 		con_printf(CON_VERBOSE, "sdl-joystick: %d axes (total)\n", Joystick.n_axes);
202 		con_printf(CON_VERBOSE, "sdl-joystick: %d buttons (total)\n", Joystick.n_buttons);
203 	}
204 
205 	return joy_present;
206 }
207 
joy_close()208 void joy_close()
209 {
210 	while (num_joysticks)
211 		SDL_JoystickClose(SDL_Joysticks[--num_joysticks].handle);
212 }
213 
joy_get_pos(int * x,int * y)214 void joy_get_pos(int *x, int *y)
215 {
216 	int axis[MAX_AXES];
217 
218 	if (!num_joysticks) {
219 		*x=*y=0;
220 		return;
221 	}
222 
223 	joystick_read_raw_axis (JOY_ALL_AXIS, axis);
224 
225 	*x = joy_get_scaled_reading( axis[0], 0 );
226 	*y = joy_get_scaled_reading( axis[1], 1 );
227 }
228 
joy_get_btns()229 int joy_get_btns()
230 {
231 #if 0 // This is never used?
232 	int i, buttons = 0;
233 	for (i=0; i++; i<buttons) {
234 		switch (Joystick.buttons[i].state) {
235 		case SDL_PRESSED:
236 			buttons |= 1<<i;
237 			break;
238 		case SDL_RELEASED:
239 			break;
240 		}
241 	}
242 	return buttons;
243 #else
244 	return 0;
245 #endif
246 }
247 
joy_get_button_down_cnt(int btn)248 int joy_get_button_down_cnt( int btn )
249 {
250 	int num_downs;
251 
252 	if (!num_joysticks)
253 		return 0;
254 
255 	event_poll();
256 
257 	num_downs = Joystick.buttons[btn].num_downs;
258 	Joystick.buttons[btn].num_downs = 0;
259 
260 	return num_downs;
261 }
262 
joy_get_button_down_time(int btn)263 fix joy_get_button_down_time(int btn)
264 {
265 	fix time = F0_0;
266 
267 	if (!num_joysticks)
268 		return 0;
269 
270 	event_poll();
271 
272 	switch (Joystick.buttons[btn].state) {
273 	case SDL_PRESSED:
274 		time = timer_get_fixed_seconds() - Joystick.buttons[btn].time_went_down;
275 		Joystick.buttons[btn].time_went_down = timer_get_fixed_seconds();
276 		break;
277 	case SDL_RELEASED:
278 		time = 0;
279 		break;
280 	}
281 
282 	return time;
283 }
284 
joystick_read_raw_axis(ubyte mask,int * axis)285 ubyte joystick_read_raw_axis( ubyte mask, int * axis )
286 {
287 	int i;
288 
289 	if (!num_joysticks)
290 		return 0;
291 
292 	event_poll();
293 
294 	for (i = 0; i <= JOY_NUM_AXES; i++) {
295 		axis[i] = Joystick.axes[i].value;
296 	}
297 
298 	return 0;
299 }
300 
joy_flush()301 void joy_flush()
302 {
303 	int i;
304 
305 	if (!num_joysticks)
306 		return;
307 
308 	for (i = 0; i < Joystick.n_buttons; i++) {
309 		Joystick.buttons[i].time_went_down = 0;
310 		Joystick.buttons[i].num_downs = 0;
311 	}
312 
313 }
314 
joy_get_button_state(int btn)315 int joy_get_button_state( int btn )
316 {
317 	if (!num_joysticks)
318 		return 0;
319 
320 	if(btn >= Joystick.n_buttons)
321 		return 0;
322 
323 	event_poll();
324 
325 	return Joystick.buttons[btn].state;
326 }
327 
joy_get_cal_vals(int * axis_min,int * axis_center,int * axis_max)328 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max)
329 {
330 	int i;
331 
332 	for (i = 0; i < JOY_NUM_AXES; i++) {
333 		axis_center[i] = Joystick.axes[i].center_val;
334 		axis_min[i] = Joystick.axes[i].min_val;
335 		axis_max[i] = Joystick.axes[i].max_val;
336 	}
337 }
338 
joy_set_cal_vals(int * axis_min,int * axis_center,int * axis_max)339 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
340 {
341 	int i;
342 
343 	for (i = 0; i < JOY_NUM_AXES; i++) {
344 		Joystick.axes[i].center_val = axis_center[i];
345 		Joystick.axes[i].min_val = axis_min[i];
346 		Joystick.axes[i].max_val = axis_max[i];
347 	}
348 }
349 
joy_get_scaled_reading(int raw,int axis_num)350 int joy_get_scaled_reading( int raw, int axis_num )
351 {
352 #if 1
353 	return raw/256;
354 #else
355 	int d, x;
356 
357 	raw -= Joystick.axes[axis_num].center_val;
358 
359 	if (raw < 0)
360 		d = Joystick.axes[axis_num].center_val - Joystick.axes[axis_num].min_val;
361 	else if (raw > 0)
362 		d = Joystick.axes[axis_num].max_val - Joystick.axes[axis_num].center_val;
363 	else
364 		d = 0;
365 
366 	if (d)
367 		x = ((raw << 7) / d);
368 	else
369 		x = 0;
370 
371 	if ( x < -128 )
372 		x = -128;
373 	if ( x > 127 )
374 		x = 127;
375 
376 	d =  (joy_deadzone) * 6;
377 	if ((x > (-1*d)) && (x < d))
378 		x = 0;
379 
380 	return x;
381 #endif
382 }
383 
joy_set_slow_reading(int flag)384 void joy_set_slow_reading( int flag )
385 {
386 }
387