Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
joystick.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2016 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #include "xep128.h"
20 #include "joystick.h"
21 #include "input.h"
22 #include "dave.h"
23 
24 #include <SDL.h>
25 
26 
27 #define MAX_JOYSTICKS 10
28 #define EPJOY_DISABLED -2
29 #define EPJOY_KP -1
30 
31 //#define USE_NEW_CFG
32 
33 
34 static struct {
35  SDL_Joystick *joy;
36  SDL_Haptic *haptic;
37  int sdl_index;
38  int rumble;
41  int num_of_axes_orig; // before abstraction of hats as axes ...
46  const char *name;
47  SDL_JoystickGUID guid;
48  char guid_str[40];
49  int cfg_updated; // used by configurator
50 } joysticks[MAX_JOYSTICKS];
51 static struct {
52  int id; // Joystick ID (in joysticks array), use -1 for numeric keypad, or -2 for disable!, for vals < 0, all other options here ARE NOT used at all!
55  int activated; // used by configurator
56 } epjoys[3]; // emulation details for the two external joysticks of Enterprise (note: we have 0,1 on EP they're named as 1,2!) index 2 is for internal joystick emu ...
57 static int joy_to_init = 1;
58 static const char unknown_joystick_name[] = "Unknown joystick";
59 
60 
61 #define BIT_TO_SET(storage,mask) (storage) |= mask
62 #define BIT_TO_RESET(storage,mask) (storage) &= (4294967295U - mask)
63 
64 #define AXIS_LIMIT_HIGH 20000
65 #define AXIS_LIMIT_LOW 10000
66 
67 
68 #ifdef USE_NEW_CFG
69 static const char joy_cfg_file_header[] =
70  "# Joystick configuration file. Updated by Xep128 every time if new joystick is detected." NL
71  "# You should not change anything, just write extra options after the * and # lines for" NL
72  "# the given joystick or controller you would like to use." NL
73  "# A line starting with '*' marks configuration for the given joystick/controller till" NL
74  "# the next '* line or to the end of the file, if the last one. New models are added" NL
75  "# automatically to this file, if Xep128 detects one." NL
76  "# The syntax is quite strict, you should not use extra spaces or tabs." NL
77  "# Basically you may want to add '1v=8' like options (one per line) to the given place." NL
78  "# In the example, the first number ('1') means the EP joystick number (1 or 2)," NL
79  "# 'v' or 'h' to select axis number as v(ertical) or h(orizonal) control." NL
80  "# The other options are 'a', 'b', 'c' meaning (max of three) buttons (however most EP" NL
81  "# softwares use only one fire ('a'). Here, the number after the '=' sign is button" NL
82  "# number on your joystick/controller to assign (not axis number as with 'v' and 'h')." NL
83  "# Uppercase versions of 'v', 'h', 'a', 'b', 'c' are for selecting an alternative" NL
84  "# controller if you have more than one attached, then the second one is tried to be" NL
85  "# used (ie, with two X-Box controllers connected, you can have one for joy-1 and" NL
86  "# one for joy-2, since the configuration marks per model, and you have two of the" NL
87  "# same models of controller in this case). However, if only one controller of the" NL
88  "# type is detected, upper cased options treated as lower case, possible overwriting" NL
89  "# the functionality! Confusing? Indeed. But it's hard to deal with hot-pluggable system" NL
90  "# having options for possible unknown mappings, with the possibility to use two identical" NL
91  "# models but also different ones, etc ... Also please note, that meaning of axis and button" NL
92  "# numbers varies among operating systems and even with driver versions sometimes :-(" NL NL;
93 
94 static const char joy_cfg_file_name[] = "@joysticks.cfg";
95 static const char joy_cfg_syntax_error[] = "Syntax error (line %d) in joystick configuration file:\n%s";
96 #endif
97 
98 
99 
100 static void joy_clear_assignments ( void )
101 {
102  int a;
103  for (a = 0; a < 2; a++) {
104  epjoys[a].id = EPJOY_KP;
105  epjoys[a].button_masks[0] = epjoys[a].button_masks[1] = epjoys[a].button_masks[2] = 0;
106  epjoys[a].v_axis_mask = epjoys[a].h_axis_mask = 0;
107  epjoys[a].activated = 0;
108  }
109 }
110 
111 
112 
113 #ifdef USE_NEW_CFG
114 /* This function re-scans configuration file, and even updating it, if new device found by GUID
115 Emulation assignment has been re-set, and re-done according to the configuration file.
116 Should be called at new joystick device attached event, after joystick struct has been set properly. */
117 static void use_and_update_config_file ( void )
118 {
119  char path[PATH_MAX + 1];
120  int had_cfg, a;
121  FILE *f = open_emu_file(joy_cfg_file_name, "r", path);
122  // Reset assignments
123  joy_clear_assignments();
124  // Parse configuration file, if we have any ...
125  if (f) {
126  char line[256];
127  int lineno = 0;
128  int fnum = 0; // number of valid items in found[]
129  int found[MAX_JOYSTICKS]; // joysticks indices found for the given controller GUID
130  while (fgets(line, sizeof line, f)) {
131  lineno++;
132  if (line[0] == '*') {
133  for (fnum = 0, a = 0; a < MAX_JOYSTICKS; a++)
134  if (joysticks[a].joy && !strncmp(joysticks[a].guid_str, line + 1, strlen(joysticks[a].guid_str))) {
135  joysticks[a].cfg_updated = 1;
136  found[fnum++] = a;
137  }
138  } else if (line[0] == '+') {
139  char *p = strchr(line, '=');
140  if (p >= line + 3 && (line[1] == '1' || line[1] == '2')) {
141  Uint32 param = atoi(p + 1) & 31; // parameter as integer after the '=' sign
142  int jnum = line[1] - '1';
143  if (!fnum)
144  continue;
145  epjoys[jnum].id = found[0];
146  switch (line[2]) {
147  case 'v':
148  epjoys[jnum].v_axis_mask = 1U << param;
149  break;
150  case 'h':
151  epjoys[jnum].h_axis_mask = 1U << param;
152  break;
153  case 'a':
154  case 'b':
155  case 'c':
156  epjoys[jnum].button_masks[line[2] - 'a'] = 1U << param;
157  break;
158  default:
159  ERROR_WINDOW(joy_cfg_syntax_error, lineno, path);
160  break;
161  }
162  } else
163  ERROR_WINDOW(joy_cfg_syntax_error, lineno, path);
164  } else if (line[0] != '#' && line[0] > 32)
165  ERROR_WINDOW(joy_cfg_syntax_error, lineno, path);
166  }
167  fclose(f);
168  had_cfg = 1;
169  } else
170  had_cfg = 0;
171  // Now, append joy cfg file with "new" joysticks not found in cfg file yet (or the cfg file has to be created ...)
172  f = open_emu_file(joy_cfg_file_name, "a", path);
173  if (f) {
174  if (!had_cfg)
175  fprintf(f, "%s", joy_cfg_file_header);
176  for (a = 0; a < MAX_JOYSTICKS; a++)
177  if (joysticks[a].joy && !joysticks[a].cfg_updated) {
178  had_cfg = 2;
179  fprintf(f,
180  NL "*%s" NL
181  "# Name: \"%s\"" NL
182  "# Axes = %d, buttons = %d, hats = %d (mapped - if any - as two virtual axes from %d per hats)" NL,
183  joysticks[a].guid_str, joysticks[a].name,
184  joysticks[a].num_of_axes, joysticks[a].num_of_buttons, joysticks[a].num_of_hats,
185  joysticks[a].num_of_axes_orig
186  );
187  }
188  fclose(f);
189  if (had_cfg == 2)
190  INFO_WINDOW("Joystick configuration file has been created/appended with new joystick\n%s", path);
191  } else
192  ERROR_WINDOW("Cannot create/append joystick configuration file:\n%s", path);
193  /* TODO: if we have joysticks found but no assignment is done, let's assign "something" at least :) */
194 }
195 #endif
196 
197 
198 
199 /* virtual is zero for "real" axes,
200  for hat->axis abstraction, axes will mean the hat number, and virtual must be 1 or 2 for the two
201  "axes" of the hat */
202 static void set_axis_state ( int joy_id, Uint32 axis, int value, int virtual )
203 {
204  Uint32 axis_mask, oldp, oldn;
205  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].joy || axis >= (virtual ? joysticks[joy_id].num_of_axes : joysticks[joy_id].num_of_axes_orig))
206  return;
207  if (virtual)
208  axis = joysticks[joy_id].num_of_axes_orig + axis * 2 + virtual - 1;
209  axis_mask = 1U << axis;
210  oldp = joysticks[joy_id].axisp;
211  oldn = joysticks[joy_id].axisn;
212  if (value > AXIS_LIMIT_HIGH) {
213  BIT_TO_SET (joysticks[joy_id].axisp, axis_mask);
214  BIT_TO_RESET(joysticks[joy_id].axisn, axis_mask);
215  } else if (value < AXIS_LIMIT_LOW && value > -AXIS_LIMIT_LOW) {
216  BIT_TO_RESET(joysticks[joy_id].axisp, axis_mask);
217  BIT_TO_RESET(joysticks[joy_id].axisn, axis_mask);
218  } else if (value < -AXIS_LIMIT_HIGH) {
219  BIT_TO_RESET(joysticks[joy_id].axisp, axis_mask);
220  BIT_TO_SET (joysticks[joy_id].axisn, axis_mask);
221  }
222  if (show_keys && (oldp != joysticks[joy_id].axisp || oldn != joysticks[joy_id].axisn))
223  OSD("PC joystick #%d axis %d [%c %c]\nmask=%X value=%d virtual=%c",
224  joy_id,
225  axis,
226  (joysticks[joy_id].axisn & axis_mask) ? '-' : ' ',
227  (joysticks[joy_id].axisp & axis_mask) ? '+' : ' ',
228  axis_mask,
229  value,
230  virtual ? 'Y' : 'N'
231  );
232 }
233 
234 
235 
236 static void set_button_state ( int joy_id, Uint32 button, int value )
237 {
238  Uint32 button_mask, old;
239  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].joy || button >= joysticks[joy_id].num_of_buttons)
240  return;
241  button_mask = 1U << button;
242  old = joysticks[joy_id].button;
243  if (value)
244  BIT_TO_SET(joysticks[joy_id].button, button_mask);
245  else
246  BIT_TO_RESET(joysticks[joy_id].button, button_mask);
247  if (show_keys && old != joysticks[joy_id].button)
248  OSD("PC joystick #%d button %d\n%s", joy_id, button, value ? "pressed" : "released");
249 }
250 
251 
252 
253 static void set_hat_state ( int joy_id, Uint32 hat, int value )
254 {
255  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].joy || hat >= joysticks[joy_id].num_of_hats)
256  return;
257  // we emulate hats as two axes after placed the "normal axes", we signal set_axis_state() about this with the third parameter being non-zero
258  if (value & SDL_HAT_UP)
259  set_axis_state(joy_id, hat, -32000, 1);
260  else if (value & SDL_HAT_DOWN)
261  set_axis_state(joy_id, hat, 32000, 1);
262  else
263  set_axis_state(joy_id, hat, 0, 1);
264  if (value & SDL_HAT_LEFT)
265  set_axis_state(joy_id, hat, -32000, 2);
266  else if (value & SDL_HAT_RIGHT)
267  set_axis_state(joy_id, hat, 32000, 2);
268  else
269  set_axis_state(joy_id, hat, 0, 2);
270 }
271 
272 
273 
274 static void joy_sync ( int joy_id )
275 {
276  int a;
277  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].joy)
278  return;
279  joysticks[joy_id].button = joysticks[joy_id].axisp = joysticks[joy_id].axisn = 0;
280  for (a = 0; a < 32; a++) {
281  if (a < joysticks[joy_id].num_of_axes_orig)
282  set_axis_state(joy_id, a, SDL_JoystickGetAxis(joysticks[joy_id].joy, a), 0);
283  if (a < joysticks[joy_id].num_of_buttons)
284  set_button_state(joy_id, a, SDL_JoystickGetButton(joysticks[joy_id].joy, a));
285  if (a < joysticks[joy_id].num_of_hats)
286  set_hat_state(joy_id, a, SDL_JoystickGetHat(joysticks[joy_id].joy, a));
287  }
288 }
289 
290 
291 
292 static void joy_detach ( int joy_id )
293 {
294  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].joy)
295  return;
296  DEBUG("JOY: device removed #%d" NL,
297  joy_id
298  );
299  if (joysticks[joy_id].haptic)
300  SDL_HapticClose(joysticks[joy_id].haptic);
301  SDL_JoystickClose(joysticks[joy_id].joy);
302  joysticks[joy_id].joy = NULL;
303  joysticks[joy_id].haptic = NULL;
304  OSD("Joy detached #%d", joy_id);
305  joysticks[joy_id].button = joysticks[joy_id].axisp = joysticks[joy_id].axisn = 0; // don't leave state in a "stucked" situation!
306 }
307 
308 
309 
310 static void joy_rumble ( int joy_id, Uint32 len, int always )
311 {
312  if (joy_id >= MAX_JOYSTICKS || !joysticks[joy_id].haptic || !joysticks[joy_id].rumble)
313  return;
314  if (always || joysticks[joy_id].rumble == 1) {
315  SDL_HapticRumblePlay(joysticks[joy_id].haptic, 1.0, len);
316  joysticks[joy_id].rumble = 2;
317  }
318 }
319 
320 
321 
322 static void joy_attach ( int joy_id )
323 {
324  SDL_Joystick *joy;
325  if (joy_id >= MAX_JOYSTICKS)
326  return;
327  if (joysticks[joy_id].joy) // already attached joystick?
328  return;
329  joysticks[joy_id].joy = joy = SDL_JoystickOpen(joy_id);
330  if (!joy)
331  return;
332  joysticks[joy_id].haptic = SDL_HapticOpenFromJoystick(joy);
333  if (joysticks[joy_id].haptic)
334  joysticks[joy_id].rumble = SDL_HapticRumbleInit(joysticks[joy_id].haptic) ? 0 : 1;
335  else
336  joysticks[joy_id].rumble = 0; // rumble is not supported
337  joysticks[joy_id].sdl_index = joy_id;
338  joysticks[joy_id].num_of_buttons = SDL_JoystickNumButtons(joy);
339  joysticks[joy_id].num_of_axes = SDL_JoystickNumAxes(joy);
340  joysticks[joy_id].num_of_hats = SDL_JoystickNumHats(joy);
341  joysticks[joy_id].name = SDL_JoystickName(joy);
342  if (!joysticks[joy_id].name)
343  joysticks[joy_id].name = unknown_joystick_name;
344  joysticks[joy_id].guid = SDL_JoystickGetGUID(joy);
345  SDL_JoystickGetGUIDString(
346  joysticks[joy_id].guid,
347  joysticks[joy_id].guid_str,
348  40
349  );
350  if (joysticks[joy_id].num_of_buttons > 32)
351  joysticks[joy_id].num_of_buttons = 32;
352  if (joysticks[joy_id].num_of_axes > 32)
353  joysticks[joy_id].num_of_axes = 32;
354  if (joysticks[joy_id].num_of_hats > 32)
355  joysticks[joy_id].num_of_hats = 32;
356  if (joysticks[joy_id].num_of_axes + (joysticks[joy_id].num_of_hats * 2) > 32) {
357  if (joysticks[joy_id].num_of_hats > 4)
358  joysticks[joy_id].num_of_hats = 4;
359  }
360  if (joysticks[joy_id].num_of_axes + (joysticks[joy_id].num_of_hats * 2) > 32) {
361  joysticks[joy_id].num_of_axes = 32 - (joysticks[joy_id].num_of_hats * 2);
362  }
363  joy_sync(joy_id);
364  DEBUGPRINT("JOY: new device added #%d \"%s\" axes=%d buttons=%d (balls=%d) hats=%d guid=%s" NL,
365  joy_id,
366  joysticks[joy_id].name,
367  joysticks[joy_id].num_of_axes,
368  joysticks[joy_id].num_of_buttons,
369  SDL_JoystickNumBalls(joy),
370  joysticks[joy_id].num_of_hats,
371  joysticks[joy_id].guid_str
372  );
373  OSD("Joy attached:\n#%d %s", joy_id, joysticks[joy_id].name);
374  joysticks[joy_id].num_of_axes_orig = joysticks[joy_id].num_of_axes;
375  joysticks[joy_id].num_of_axes += joysticks[joy_id].num_of_hats * 2;
376 #ifdef USE_NEW_CFG
377  use_and_update_config_file();
378 #endif
379 }
380 
381 
382 
383 void joy_sdl_event ( SDL_Event *e )
384 {
385  if (joy_to_init) {
386  int a;
387  for (a = 0; a < MAX_JOYSTICKS; a++) {
388  joysticks[a].joy = NULL;
389  joysticks[a].haptic = NULL;
390  joysticks[a].button = joysticks[a].axisp = joysticks[a].axisn = 0;
391  joysticks[a].cfg_updated = 0;
392  }
393  joy_clear_assignments();
394 #ifndef USE_NEW_CFG
395  for (a = 0; a < 2; a++) {
396  epjoys[a].id = 0; // assigned to SDL joystick #0
397  epjoys[a].button_masks[0] = 1;
398  epjoys[a].button_masks[1] = 0;
399  epjoys[a].button_masks[2] = 0;
400  epjoys[a].v_axis_mask = 2;
401  epjoys[a].h_axis_mask = 1;
402  }
403 #endif
404  SDL_GameControllerEventState(SDL_DISABLE);
405  SDL_JoystickEventState(SDL_ENABLE);
406  joy_to_init = 0;
407  }
408  if (e) switch (e->type) {
409  case SDL_JOYAXISMOTION: // joystick axis motion
410  set_axis_state(e->jaxis.which, e->jaxis.axis, e->jaxis.value, 0);
411  break;
412  case SDL_JOYBUTTONDOWN:
413  case SDL_JOYBUTTONUP:
414  set_button_state(e->jbutton.which, e->jbutton.button, e->jbutton.state);
415  break;
416  case SDL_JOYDEVICEADDED:
417  joy_attach(e->jdevice.which);
418  break;
419  case SDL_JOYDEVICEREMOVED:
420  joy_detach(e->jdevice.which);
421  break;
422  case SDL_JOYHATMOTION:
423  set_hat_state(e->jhat.which, e->jhat.hat, e->jhat.value);
424  break;
425  }
426 }
427 
428 
429 
430 /* The SCAN function called from input.c
431  num is the Enterprise (!) external joystick number, 0 or 1 (beware, on EP it's called 1 or 2)
432  dir is the direction / button to scan, see JOY_SCAN_* defines in the header file.
433  The return value is '0' for inactive and '1' for active (well, or any non-zero value) for a given scan, warning, it's the
434  opposite behaviour as you can see on EP HW level!
435  DO NOT call this function with other num than 0, 1! (2 is reserved for internal joy emu, but it's not handled by this func!)
436 */
437 int joystick_scan ( int num, int dir )
438 {
439  if (num != 0 && num != 1)
440  return 0;
441  switch (epjoys[num].id) {
442  case EPJOY_KP:
443  return !(kbd_matrix[10] & (1 << dir)); // keyboard-matrix row #10 (not a real EP one!) is used to maintain status of numeric keypad joy emu keys ...
444  case EPJOY_DISABLED:
445  return 0; // disabled, always zero answer
446  default:
447  // hack: give priority to the numeric keypad ;-)
448  if (!(kbd_matrix[10] & (1 << dir)))
449  return 1;
450  joy_rumble(epjoys[num].id, 200, 0);
451  switch (dir) {
452  case JOY_SCAN_FIRE1:
453  return joysticks[epjoys[num].id].button & epjoys[num].button_masks[0];
454  case JOY_SCAN_UP:
455  return joysticks[epjoys[num].id].axisn & epjoys[num].v_axis_mask;
456  case JOY_SCAN_DOWN:
457  return joysticks[epjoys[num].id].axisp & epjoys[num].v_axis_mask;
458  case JOY_SCAN_LEFT:
459  return joysticks[epjoys[num].id].axisn & epjoys[num].h_axis_mask;
460  case JOY_SCAN_RIGHT:
461  return joysticks[epjoys[num].id].axisp & epjoys[num].h_axis_mask;
462  case JOY_SCAN_FIRE2:
463  return joysticks[epjoys[num].id].button & epjoys[num].button_masks[1];
464  case JOY_SCAN_FIRE3:
465  return joysticks[epjoys[num].id].button & epjoys[num].button_masks[2];
466  }
467  }
468  return 0; // unknown?!
469 }
guid
SDL_JoystickGUID guid
Definition: joystick.c:47
AXIS_LIMIT_LOW
#define AXIS_LIMIT_LOW
Definition: joystick.c:65
num_of_axes_orig
int num_of_axes_orig
Definition: joystick.c:41
JOY_SCAN_RIGHT
#define JOY_SCAN_RIGHT
Definition: input_devices.h:28
BIT_TO_SET
#define BIT_TO_SET(storage, mask)
Definition: joystick.c:61
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
rumble
int rumble
Definition: joystick.c:38
JOY_SCAN_UP
#define JOY_SCAN_UP
Definition: input_devices.h:25
dave.h
id
int id
Definition: joystick.c:52
Uint32
uint32_t Uint32
Definition: fat32.c:49
MAX_JOYSTICKS
#define MAX_JOYSTICKS
Definition: joystick.c:27
activated
int activated
Definition: joystick.c:55
EPJOY_KP
#define EPJOY_KP
Definition: joystick.c:29
joy_sdl_event
void joy_sdl_event(SDL_Event *e)
Definition: joystick.c:383
joystick.h
open_emu_file
FILE * open_emu_file(const char *name, const char *mode, char *pathbuffer)
Definition: configuration.c:109
JOY_SCAN_FIRE2
#define JOY_SCAN_FIRE2
Definition: input_devices.h:29
cfg_updated
int cfg_updated
Definition: joystick.c:49
JOY_SCAN_LEFT
#define JOY_SCAN_LEFT
Definition: input_devices.h:27
joystick_scan
int joystick_scan(int num, int dir)
Definition: joystick.c:437
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
AXIS_LIMIT_HIGH
#define AXIS_LIMIT_HIGH
Definition: joystick.c:64
dir
DIR * dir
Definition: cpmfs.c:46
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
BIT_TO_RESET
#define BIT_TO_RESET(storage, mask)
Definition: joystick.c:62
NL
#define NL
Definition: fat32.c:37
axisp
Uint32 axisp
Definition: joystick.c:44
num_of_hats
int num_of_hats
Definition: joystick.c:42
num_of_buttons
int num_of_buttons
Definition: joystick.c:39
xep128.h
EPJOY_DISABLED
#define EPJOY_DISABLED
Definition: joystick.c:28
JOY_SCAN_FIRE3
#define JOY_SCAN_FIRE3
Definition: input_devices.h:30
JOY_SCAN_DOWN
#define JOY_SCAN_DOWN
Definition: input_devices.h:26
kbd_matrix
Uint8 kbd_matrix[16]
Definition: dave.c:30
guid_str
char guid_str[40]
Definition: joystick.c:48
v_axis_mask
Uint32 v_axis_mask
Definition: joystick.c:54
show_keys
int show_keys
Definition: input_devices.c:39
OSD
#define OSD(...)
Definition: xep128.h:100
JOY_SCAN_FIRE1
#define JOY_SCAN_FIRE1
Definition: input_devices.h:24
value
int value
Definition: dma65.c:90
found
char found[8+3+1]
Definition: cpmfs.c:36
haptic
SDL_Haptic * haptic
Definition: joystick.c:36
name
const char * name
Definition: joystick.c:46
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
h_axis_mask
Uint32 h_axis_mask
Definition: joystick.c:54
num_of_axes
int num_of_axes
Definition: joystick.c:40
button
Uint32 button
Definition: joystick.c:43
joy
SDL_Joystick * joy
Definition: joystick.c:35
button_masks
Uint32 button_masks[3]
Definition: joystick.c:53
input.h
axisn
Uint32 axisn
Definition: joystick.c:45
sdl_index
int sdl_index
Definition: joystick.c:37