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"
19 static int Joy_inited = 0;
20 int Dead_zone_size = 10;
21 int Joy_sensitivity = 9;
23 static int Joy_last_x_reading = 0;
24 static int Joy_last_y_reading = 0;
26 typedef struct joy_button_info {
27 int actual_state; // Set if the button is physically down
28 int state; // Set when the button goes from up to down, cleared on down to up. Different than actual_state after a flush.
32 uint last_down_check; // timestamp in milliseconds of last
35 static Joy_info joystick;
38 static SDL_JoystickID joy_id = -1;
40 joy_button_info joy_buttons[JOY_TOTAL_BUTTONS];
58 if (SDL_JoystickGetAttached(sdljoy)) {
59 SDL_JoystickClose(sdljoy);
64 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
75 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) {
79 tmp = joy_buttons[btn].state;
84 int joy_down_count(int btn, int reset_count)
92 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) {
96 tmp = joy_buttons[btn].down_count;
98 joy_buttons[btn].down_count = 0;
104 float joy_down_time(int btn)
107 unsigned int now, delta;
114 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) {
118 bi = &joy_buttons[btn];
120 now = timer_get_milliseconds();
121 delta = now - bi->last_down_check;
123 if ( (now - bi->last_down_check) > 0)
124 rval = i2fl((now - bi->down_time)) / delta;
129 bi->last_down_check = now;
139 void joy_mark_button(int btn, int state)
148 if ( (btn < 0) || (btn >= JOY_TOTAL_BUTTONS)) {
152 bi = &joy_buttons[btn];
159 bi->down_time = timer_get_milliseconds();
161 // toggle off other positions if hat
162 if (btn >= JOY_HATBACK) {
163 for (i = JOY_HATBACK; i < (JOY_HATBACK+JOY_NUM_HAT_POS); i++) {
165 joy_buttons[i].state = 0;
175 // special hat handling - make sure all hat pos are off
176 if (btn == JOY_HATBACK) {
177 for (i = JOY_HATBACK; i < (JOY_HATBACK+JOY_NUM_HAT_POS); i++) {
178 joy_buttons[i].state = 0;
193 for ( i = 0; i < JOY_TOTAL_BUTTONS; i++) {
194 bi = &joy_buttons[i];
199 bi->last_down_check = timer_get_milliseconds();
203 int joy_get_unscaled_reading(int axn)
211 if (axn >= joystick.num_axes) {
215 int raw = joystick.axis_current[axn];
217 rng = joystick.axis_max[axn] - joystick.axis_min[axn];
218 raw -= joystick.axis_min[axn]; // adjust for linear range starting at 0
226 return (int) ((unsigned int) raw * (unsigned int) F1_0 / (unsigned int) rng); // convert to 0 - F1_0 range.
229 // --------------------------------------------------------------
230 // joy_get_scaled_reading()
232 // input: raw => the raw value for an axis position
233 // axn => axis number, numbered starting at 0
235 // return: joy_get_scaled_reading will return a value that represents
236 // the joystick pos from -1 to +1 for the specified axis number 'axn', and
237 // the raw value 'raw'
239 int joy_get_scaled_reading(int axn)
241 int x, d, dead_zone, rng, raw;
242 float percent, sensitivity_percent, non_sensitivity_percent;
248 if (axn >= joystick.num_axes) {
252 raw = joystick.axis_current[axn] - joystick.axis_center[axn];
254 dead_zone = (joystick.axis_max[axn] - joystick.axis_min[axn]) * Dead_zone_size / 100;
256 if (raw < -dead_zone) {
257 rng = joystick.axis_center[axn] - joystick.axis_min[axn] - dead_zone;
258 d = -raw - dead_zone;
260 } else if (raw > dead_zone) {
261 rng = joystick.axis_max[axn] - joystick.axis_center[axn] - dead_zone;
271 SDL_assert(Joy_sensitivity >= 0 && Joy_sensitivity <= 9);
273 // compute percentages as a range between 0 and 1
274 sensitivity_percent = (float) Joy_sensitivity / 9.0f;
275 non_sensitivity_percent = (float) (9 - Joy_sensitivity) / 9.0f;
277 // find percent of max axis is at
278 percent = (float) d / (float) rng;
280 // work sensitivity on axis value
281 percent = (percent * sensitivity_percent + percent * percent * percent * percent * percent * non_sensitivity_percent);
283 x = (int) ((float) F1_0 * percent);
285 //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));
294 // --------------------------------------------------------------
297 // input: x => OUTPUT PARAMETER: x-axis position of stick (-1 to 1)
298 // y => OUTPUT PARAMETER: y-axis position of stick (-1 to 1)
299 // z => OUTPUT PARAMETER: z-axis (throttle) position of stick (-1 to 1)
300 // r => OUTPUT PARAMETER: rudder position of stick (-1 to 1)
302 // return: success => 1
305 int joy_get_pos(int *x, int *y, int *z, int *rx)
316 // joy_get_scaled_reading will return a value represents the joystick
318 if (x && joystick.num_axes > 0) {
319 *x = joy_get_scaled_reading(0);
320 Joy_last_x_reading = *x;
323 if (y && joystick.num_axes > 1) {
324 *y = joy_get_scaled_reading(1);
325 Joy_last_y_reading = *y;
328 if (z && joystick.num_axes > 2) {
329 *z = joy_get_unscaled_reading(2);
332 if (rx && joystick.num_axes > 3) {
333 *rx = joy_get_scaled_reading(3);
342 const char *ptr = NULL;
349 mprintf(("Initializing Joystick...\n"));
351 if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
352 mprintf((" Could not initialize joystick subsystem\n\n"));
356 num_sticks = SDL_NumJoysticks();
358 if (num_sticks < 1) {
359 mprintf((" No joysticks found\n\n"));
365 ptr = os_config_read_string("Controls", "CurrentJoystick", NULL);
367 if ( ptr && SDL_strlen(ptr) ) {
368 for (i = 0; i < num_sticks; i++) {
369 const char *jname = SDL_JoystickNameForIndex(i);
371 if ( jname && !SDL_strcasecmp(ptr, jname) ) {
378 sdljoy = SDL_JoystickOpen(Cur_joystick);
380 if (sdljoy == NULL) {
381 mprintf((" Unable to init joystick %d (%s)\n\n", Cur_joystick, SDL_JoystickNameForIndex(Cur_joystick)));
385 mprintf((" Name : %s\n", SDL_JoystickName(sdljoy)));
386 mprintf((" Axes : %d\n", SDL_JoystickNumAxes(sdljoy)));
387 mprintf((" Buttons : %d\n", SDL_JoystickNumButtons(sdljoy)));
388 mprintf((" Hats : %d\n", SDL_JoystickNumHats(sdljoy)));
389 mprintf((" Haptic : %s\n", SDL_JoystickIsHaptic(sdljoy) ? "Yes" : "No"));
397 joy_id = SDL_JoystickInstanceID(sdljoy);
399 joystick.num_axes = SDL_JoystickNumAxes(sdljoy);
403 // Fake a calibration
406 for (i = 0; i < JOY_NUM_AXES; i++) {
407 joystick.axis_min[i] = 0;
408 joystick.axis_max[i] = 65536;
409 joystick.axis_current[i] = joystick.axis_center[i];
415 void joy_reinit(int with_index)
418 const char *ptr = NULL;
426 // close out what we have already opened...
431 if (SDL_JoystickGetAttached(sdljoy)) {
432 SDL_JoystickClose(sdljoy);
437 // attempt to get a new joystick to use...
438 mprintf(("Re-Initializing Joystick...\n"));
440 num_sticks = SDL_NumJoysticks();
442 if (num_sticks < 1) {
443 mprintf((" No joysticks found\n\n"));
447 if ( (with_index >= 0) && (with_index < num_sticks) ) {
448 Cur_joystick = with_index;
452 ptr = os_config_read_string("Controls", "CurrentJoystick", NULL);
454 if ( ptr && SDL_strlen(ptr) ) {
455 for (i = 0; i < num_sticks; i++) {
456 const char *jname = SDL_JoystickNameForIndex(i);
458 if ( jname && !SDL_strcasecmp(ptr, jname) ) {
466 sdljoy = SDL_JoystickOpen(Cur_joystick);
468 if (sdljoy == NULL) {
469 mprintf((" Unable to init joystick %d (%s)\n\n", Cur_joystick, SDL_JoystickNameForIndex(Cur_joystick)));
473 mprintf((" Name : %s\n", SDL_JoystickName(sdljoy)));
474 mprintf((" Axes : %d\n", SDL_JoystickNumAxes(sdljoy)));
475 mprintf((" Buttons : %d\n", SDL_JoystickNumButtons(sdljoy)));
476 mprintf((" Hats : %d\n", SDL_JoystickNumHats(sdljoy)));
477 mprintf((" Haptic : %s\n", SDL_JoystickIsHaptic(sdljoy) ? "Yes" : "No"));
483 joy_id = SDL_JoystickInstanceID(sdljoy);
485 joystick.num_axes = SDL_JoystickNumAxes(sdljoy);
489 // Fake a calibration
492 for (i = 0; i < JOY_NUM_AXES; i++) {
493 joystick.axis_min[i] = 0;
494 joystick.axis_max[i] = 65536;
495 joystick.axis_current[i] = joystick.axis_center[i];
505 for (int i = 0; i < JOY_NUM_AXES; i++) {
506 if (i < joystick.num_axes) {
507 joystick.axis_center[i] = SDL_JoystickGetAxis(sdljoy, i) + 32768;
509 joystick.axis_center[i] = 32768;
514 int joystick_read_raw_axis(int num_axes, int *axis)
522 for (i = 0; i < num_axes; i++) {
523 if (i < joystick.num_axes) {
524 axis[i] = joystick.axis_current[i];
533 bool joy_axis_valid(int axis)
535 return (axis < joystick.num_axes);
538 void joystick_update_axis(int axis, int value)
540 if (axis < JOY_NUM_AXES) {
541 joystick.axis_current[axis] = value + 32768;