2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
14 #include "osregistry.h"
18 static int Joy_inited = 0;
19 int joy_num_sticks = 0;
20 int Dead_zone_size = 10;
21 int Cur_joystick = -1;
22 int Joy_sensitivity = 9;
24 int joy_pollrate = 1000 / 18; // poll at 18Hz
26 static int Joy_last_x_reading = 0;
27 static int Joy_last_y_reading = 0;
29 typedef struct joy_button_info {
30 int actual_state; // Set if the button is physically down
31 int state; // Set when the button goes from up to down, cleared on down to up. Different than actual_state after a flush.
35 uint last_down_check; // timestamp in milliseconds of last
40 int JOYSTICKID1 = 0; // DDOI - temporary
41 static SDL_Joystick *sdljoy;
43 joy_button_info joy_buttons[JOY_TOTAL_BUTTONS];
55 SDL_JoystickClose(sdljoy);
58 SDL_QuitSubSystem (SDL_INIT_JOYSTICK);
61 void joy_get_caps (int max)
66 for (j=0; j < JOY_NUM_AXES; j++)
67 joystick.axis_valid[j] = 0;
69 for (j=JOYSTICKID1; j<JOYSTICKID1+max; j++) {
70 joy = SDL_JoystickOpen (j);
73 nprintf (("JOYSTICK", "Joystick #%d: %s\n", j - JOYSTICKID1 + 1, SDL_JoystickName(j)));
74 if (j == Cur_joystick) {
75 for (int i = 0; i < SDL_JoystickNumAxes(joy); i++)
77 joystick.axis_valid[i] = 1;
80 SDL_JoystickClose (joy);
89 if ( joy_num_sticks < 1 ) return 0;
90 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS )) return 0;
92 tmp = joy_buttons[btn].state;
97 int joy_down_count(int btn, int reset_count)
101 if ( joy_num_sticks < 1 ) return 0;
102 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) return 0;
104 tmp = joy_buttons[btn].down_count;
106 joy_buttons[btn].down_count = 0;
112 float joy_down_time(int btn)
118 if ( joy_num_sticks < 1 ) return 0.0f;
119 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) return 0.0f;
120 bi = &joy_buttons[btn];
122 now = timer_get_milliseconds();
124 if ( bi->down_time == 0 && joy_down(btn) ) {
125 bi->down_time += joy_pollrate;
128 if ( (now - bi->last_down_check) > 0)
129 rval = i2fl(bi->down_time) / (now - bi->last_down_check);
134 bi->last_down_check = now;
149 if ( joy_num_sticks < 1 ) return;
151 for ( i = 0; i < JOY_TOTAL_BUTTONS; i++) {
152 bi = &joy_buttons[i];
157 bi->last_down_check = timer_get_milliseconds();
161 int joy_get_unscaled_reading(int raw, int axn)
165 // Make sure it's calibrated properly.
166 if (joystick.axis_center[axn] - joystick.axis_min[axn] < 5)
169 if (joystick.axis_max[axn] - joystick.axis_center[axn] < 5)
172 rng = joystick.axis_max[axn] - joystick.axis_min[axn];
173 raw -= joystick.axis_min[axn]; // adjust for linear range starting at 0
181 return (int) ((unsigned int) raw * (unsigned int) F1_0 / (unsigned int) rng); // convert to 0 - F1_0 range.
184 // --------------------------------------------------------------
185 // joy_get_scaled_reading()
187 // input: raw => the raw value for an axis position
188 // axn => axis number, numbered starting at 0
190 // return: joy_get_scaled_reading will return a value that represents
191 // the joystick pos from -1 to +1 for the specified axis number 'axn', and
192 // the raw value 'raw'
194 int joy_get_scaled_reading(int raw, int axn)
196 int x, d, dead_zone, rng;
197 float percent, sensitivity_percent, non_sensitivity_percent;
199 // Make sure it's calibrated properly.
200 if (joystick.axis_center[axn] - joystick.axis_min[axn] < 5)
203 if (joystick.axis_max[axn] - joystick.axis_center[axn] < 5)
206 raw -= joystick.axis_center[axn];
208 dead_zone = (joystick.axis_max[axn] - joystick.axis_min[axn]) * Dead_zone_size / 100;
210 if (raw < -dead_zone) {
211 rng = joystick.axis_center[axn] - joystick.axis_min[axn] - dead_zone;
212 d = -raw - dead_zone;
214 } else if (raw > dead_zone) {
215 rng = joystick.axis_max[axn] - joystick.axis_center[axn] - dead_zone;
224 Assert(Joy_sensitivity >= 0 && Joy_sensitivity <= 9);
226 // compute percentages as a range between 0 and 1
227 sensitivity_percent = (float) Joy_sensitivity / 9.0f;
228 non_sensitivity_percent = (float) (9 - Joy_sensitivity) / 9.0f;
230 // find percent of max axis is at
231 percent = (float) d / (float) rng;
233 // work sensitivity on axis value
234 percent = (percent * sensitivity_percent + percent * percent * percent * percent * percent * non_sensitivity_percent);
236 x = (int) ((float) F1_0 * percent);
238 //nprintf(("AI", "d=%6i, sens=%3i, percent=%6.3f, val=%6i, ratio=%6.3f\n", d, Joy_sensitivity, percent, (raw<0) ? -x : x, (float) d/x));
246 // --------------------------------------------------------------
249 // input: x => OUTPUT PARAMETER: x-axis position of stick (-1 to 1)
250 // y => OUTPUT PARAMETER: y-axis position of stick (-1 to 1)
251 // z => OUTPUT PARAMETER: z-axis (throttle) position of stick (-1 to 1)
252 // r => OUTPUT PARAMETER: rudder position of stick (-1 to 1)
254 // return: success => 1
257 int joy_get_pos(int *x, int *y, int *z, int *rx)
259 int axis[JOY_NUM_AXES];
266 if (joy_num_sticks < 1) return 0;
268 joystick_read_raw_axis( 6, axis );
270 // joy_get_scaled_reading will return a value represents the joystick pos from -1 to +1
271 if (x && joystick.axis_valid[0])
272 *x = joy_get_scaled_reading(axis[0], 0);
273 if (y && joystick.axis_valid[1])
274 *y = joy_get_scaled_reading(axis[1], 1);
275 if (z && joystick.axis_valid[2])
276 *z = joy_get_unscaled_reading(axis[2], 2);
277 if (rx && joystick.axis_valid[3])
278 *rx = joy_get_scaled_reading(axis[3], 3);
281 Joy_last_x_reading = *x;
284 Joy_last_y_reading = *y;
289 void joy_process(int time_delta)
298 int buttons = SDL_JoystickNumButtons(sdljoy);
299 int hat = SDL_JoystickGetHat(sdljoy, 0);
301 for (i=0; i < JOY_TOTAL_BUTTONS; i++) {
304 if (i < JOY_NUM_BUTTONS) {
306 state = SDL_JoystickGetButton(sdljoy, i);
311 state = (hat & SDL_HAT_DOWN) ? 1 : 0;
314 state = (hat & SDL_HAT_UP) ? 1 : 0;
317 state = (hat & SDL_HAT_LEFT) ? 1 : 0;
320 state = (hat & SDL_HAT_RIGHT) ? 1 : 0;
327 if (state != joy_buttons[i].actual_state) {
328 // Button position physically changed.
329 joy_buttons[i].actual_state = state;
332 // went from up to down
333 joy_buttons[i].down_count++;
334 joy_buttons[i].down_time = 0;
336 joy_buttons[i].state = 1;
338 // went from down to up
339 if ( joy_buttons[i].state ) {
340 joy_buttons[i].up_count++;
343 joy_buttons[i].state = 0;
346 // Didn't move... increment time down if down.
347 if (joy_buttons[i].state) {
348 //joy_buttons[i].down_time += joy_pollrate;
349 joy_buttons[i].down_time += time_delta;
362 if (SDL_InitSubSystem (SDL_INIT_JOYSTICK)<0)
364 mprintf(("Could not initialize joystick\n"));
369 n = SDL_NumJoysticks ();
371 Cur_joystick = os_config_read_uint (NULL, "CurrentJoystick", JOYSTICKID1);
376 mprintf(("No joysticks found\n"));
380 sdljoy = SDL_JoystickOpen(Cur_joystick);
381 if (sdljoy == NULL) {
382 mprintf(("Unable to init joystick %d\n", Cur_joystick));
389 // Fake a calibration
390 if (joy_num_sticks > 0) {
392 for (i=0; i<4; i++) {
393 joystick.axis_center[i] = 32768;
394 joystick.axis_min[i] = 0;
395 joystick.axis_max[i] = 65536;
399 return joy_num_sticks;
404 joystick_read_raw_axis( 2, joystick.axis_center );
407 int joystick_read_raw_axis(int num_axes, int *axis)
415 num = SDL_JoystickNumAxes(sdljoy);
417 for (i = 0; i < num_axes; i++) {
419 axis[i] = SDL_JoystickGetAxis(sdljoy, i) + 32768;
428 void joy_ff_adjust_handling(int speed)
433 void joy_ff_afterburn_off()
438 void joy_ff_afterburn_on()
443 void joy_ff_deathroll()
453 void joy_ff_explode()
458 void joy_ff_fly_by(int mag)
463 void joy_ff_mission_init(vector v)
468 void joy_ff_play_dir_effect(float x, float y)
473 void joy_ff_play_primary_shoot(int gain)
478 void joy_ff_play_reload_effect()
483 void joy_ff_play_secondary_shoot(int gain)
488 void joy_ff_play_vector_effect(vector *v, float scaler)
493 void joy_ff_stop_effects()
495 joy_ff_afterburn_off();