1 /*****************************************************************************\
2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3 This file is licensed under the Snes9x License.
4 For further information, consult the LICENSE file in the root directory.
5 \*****************************************************************************/
6
7 #include <fcntl.h>
8
9 #include "gtk_s9xcore.h"
10 #include "gtk_s9x.h"
11 #include "gtk_config.h"
12 #include "gtk_control.h"
13 #include "gtk_file.h"
14
15 const BindingLink b_links[] =
16 {
17 /* Joypad-specific bindings. "Joypad# " will be prepended */
18 { "b_up", "Up" },
19 { "b_down", "Down" },
20 { "b_left", "Left" },
21 { "b_right", "Right" },
22 { "b_start", "Start" },
23 { "b_select", "Select" },
24 { "b_a", "A" },
25 { "b_b", "B" },
26 { "b_x", "X" },
27 { "b_y", "Y" },
28 { "b_l", "L" },
29 { "b_r", "R" },
30 { "b_a_turbo", "Turbo A" },
31 { "b_b_turbo", "Turbo B" },
32 { "b_x_turbo", "Turbo X" },
33 { "b_y_turbo", "Turbo Y" },
34 { "b_l_turbo", "Turbo L" },
35 { "b_r_turbo", "Turbo R" },
36 { "b_a_sticky", "Sticky A" },
37 { "b_b_sticky", "Sticky B" },
38 { "b_x_sticky", "Sticky X" },
39 { "b_y_sticky", "Sticky Y" },
40 { "b_l_sticky", "Sticky L" },
41 { "b_r_sticky", "Sticky R" },
42
43 /* Emulator based bindings */
44 { "b_open_rom", "GTK_open_rom" },
45 { "b_enable_turbo", "EmuTurbo" },
46 { "b_toggle_turbo", "ToggleEmuTurbo" },
47 { "b_pause", "GTK_pause" },
48 { "b_decrease_frame_rate", "DecFrameRate" },
49 { "b_increase_frame_rate", "IncFrameRate" },
50 { "b_decrease_frame_time", "DecFrameTime" },
51 { "b_increase_frame_time", "IncFrameTime" },
52 { "b_hardware_reset", "Reset" },
53 { "b_soft_reset", "SoftReset" },
54 { "b_quit", "GTK_quit" },
55 { "b_bg_layer_0", "ToggleBG0" },
56 { "b_bg_layer_1", "ToggleBG1" },
57 { "b_bg_layer_2", "ToggleBG2" },
58 { "b_bg_layer_3", "ToggleBG3" },
59 { "b_sprites", "ToggleSprites" },
60 { "b_bg_layering_hack", "BGLayeringHack" },
61 { "b_screenshot", "Screenshot" },
62 { "b_fullscreen", "GTK_fullscreen" },
63 { "b_state_save_current", "GTK_state_save_current" },
64 { "b_state_load_current", "GTK_state_load_current" },
65 { "b_state_increment_save","GTK_state_increment_save" },
66 { "b_state_decrement_load","GTK_state_decrement_load" },
67 { "b_state_increment", "GTK_state_increment" },
68 { "b_state_decrement", "GTK_state_decrement" },
69 { "b_save_0", "QuickSave000" },
70 { "b_save_1", "QuickSave001" },
71 { "b_save_2", "QuickSave002" },
72 { "b_save_3", "QuickSave003" },
73 { "b_save_4", "QuickSave004" },
74 { "b_save_5", "QuickSave005" },
75 { "b_save_6", "QuickSave006" },
76 { "b_save_7", "QuickSave007" },
77 { "b_save_8", "QuickSave008" },
78 { "b_save_9", "QuickSave009" },
79 { "b_load_0", "QuickLoad000" },
80 { "b_load_1", "QuickLoad001" },
81 { "b_load_2", "QuickLoad002" },
82 { "b_load_3", "QuickLoad003" },
83 { "b_load_4", "QuickLoad004" },
84 { "b_load_5", "QuickLoad005" },
85 { "b_load_6", "QuickLoad006" },
86 { "b_load_7", "QuickLoad007" },
87 { "b_load_8", "QuickLoad008" },
88 { "b_load_9", "QuickLoad009" },
89 { "b_sound_channel_0", "SoundChannel0" },
90 { "b_sound_channel_1", "SoundChannel1" },
91 { "b_sound_channel_2", "SoundChannel2" },
92 { "b_sound_channel_3", "SoundChannel3" },
93 { "b_sound_channel_4", "SoundChannel4" },
94 { "b_sound_channel_5", "SoundChannel5" },
95 { "b_sound_channel_6", "SoundChannel6" },
96 { "b_sound_channel_7", "SoundChannel7" },
97 { "b_all_sound_channels", "SoundChannelsOn" },
98 { "b_save_spc", "GTK_save_spc" },
99 { "b_begin_recording_movie", "BeginRecordingMovie" },
100 { "b_stop_recording_movie", "EndRecordingMovie" },
101 { "b_load_movie", "LoadMovie" },
102 { "b_seek_to_frame", "GTK_seek_to_frame" },
103 { "b_swap_controllers", "GTK_swap_controllers" },
104 { "b_rewind", "GTK_rewind" },
105 { "b_grab_mouse", "GTK_grab_mouse" },
106
107 { NULL, NULL }
108 };
109
110 /* Where the page breaks occur in the preferences pane */
111 const int b_breaks[] =
112 {
113 12, /* End of main buttons */
114 24, /* End of turbo/sticky buttons */
115 35, /* End of base emulator buttons */
116 43, /* End of Graphic options */
117 69, /* End of save/load states */
118 78, /* End of sound buttons */
119 86, /* End of miscellaneous buttons */
120 -1
121 };
122
123 static int joystick_lock = 0;
124
S9xPollButton(uint32 id,bool * pressed)125 bool S9xPollButton (uint32 id, bool *pressed)
126 {
127 return true;
128 }
129
S9xPollAxis(uint32 id,int16 * value)130 bool S9xPollAxis (uint32 id, int16 *value)
131 {
132 return true;
133 }
134
S9xPollPointer(uint32 id,int16 * x,int16 * y)135 bool S9xPollPointer (uint32 id, int16 *x, int16 *y)
136 {
137 *x = top_level->snes_mouse_x;
138 *y = top_level->snes_mouse_y;
139
140 return true;
141 }
142
S9xIsMousePluggedIn()143 bool S9xIsMousePluggedIn ()
144 {
145 enum controllers ctl;
146 int8 id1, id2, id3, id4;
147
148 for (int i = 0; i <= 1; i++)
149 {
150 S9xGetController (i, &ctl, &id1, &id2, &id3, &id4);
151 if (ctl == CTL_MOUSE || ctl == CTL_SUPERSCOPE)
152 return true;
153 }
154
155 return false;
156 }
157
S9xGrabJoysticks()158 bool S9xGrabJoysticks ()
159 {
160 if (joystick_lock)
161 return false;
162
163 joystick_lock++;
164
165 return true;
166 }
167
S9xReleaseJoysticks()168 void S9xReleaseJoysticks ()
169 {
170 joystick_lock--;
171 }
172
swap_controllers_1_2()173 static void swap_controllers_1_2 ()
174 {
175 JoypadBinding interrim;
176
177 interrim = gui_config->pad[0];
178 gui_config->pad[0] = gui_config->pad[1];
179 gui_config->pad[1] = interrim;
180
181 gui_config->rebind_keys ();
182 }
183
change_slot(int difference)184 static void change_slot (int difference)
185 {
186 static char buf[256];
187
188 gui_config->current_save_slot += difference;
189 gui_config->current_save_slot %= 1000;
190 if (gui_config->current_save_slot < 0)
191 gui_config->current_save_slot += 1000;
192 if (!gui_config->rom_loaded)
193 return;
194
195 snprintf (buf, 256, "State Slot: %d", gui_config->current_save_slot);
196 S9xSetInfoString (buf);
197 GFX.InfoStringTimeout = 60;
198 }
199
S9xHandlePortCommand(s9xcommand_t cmd,int16 data1,int16 data2)200 void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2)
201 {
202 static bool quit_binding_down = false;
203
204 if (data1 == true)
205 {
206 if (cmd.port[0] == PORT_QUIT)
207 quit_binding_down = true;
208 else if (cmd.port[0] == PORT_REWIND)
209 Settings.Rewinding = true;
210 }
211
212 if (data1 == false) /* Release */
213 {
214 if (cmd.port[0] != PORT_QUIT)
215 {
216 quit_binding_down = false;
217 }
218
219 if (cmd.port[0] == PORT_COMMAND_FULLSCREEN)
220 {
221 top_level->toggle_fullscreen_mode ();
222 }
223
224 else if (cmd.port[0] == PORT_COMMAND_SAVE_SPC)
225 {
226 top_level->save_spc_dialog ();
227 }
228
229 else if (cmd.port[0] == PORT_OPEN_ROM)
230 {
231 top_level->open_rom_dialog ();
232 }
233
234 else if (cmd.port[0] == PORT_PAUSE)
235 {
236 if (!(top_level->user_pause))
237 top_level->pause_from_user ();
238 else
239 top_level->unpause_from_user ();
240 }
241
242 else if (cmd.port[0] == PORT_REWIND)
243 {
244 Settings.Rewinding = false;
245 }
246
247 else if (cmd.port[0] == PORT_SEEK_TO_FRAME)
248 {
249 top_level->movie_seek_dialog ();
250 }
251
252 else if (cmd.port[0] == PORT_SWAP_CONTROLLERS)
253 {
254 swap_controllers_1_2 ();
255 }
256
257 else if (cmd.port[0] == PORT_QUIT)
258 {
259 if (quit_binding_down)
260 S9xExit ();
261 }
262
263 else if (cmd.port[0] >= PORT_QUICKLOAD0 && cmd.port[0] <= PORT_QUICKLOAD9)
264 {
265 S9xQuickLoadSlot (cmd.port[0] - PORT_QUICKLOAD0);
266 }
267
268 else if (cmd.port[0] == PORT_SAVESLOT)
269 {
270 S9xQuickSaveSlot (gui_config->current_save_slot);
271 }
272
273 else if (cmd.port[0] == PORT_LOADSLOT)
274 {
275 S9xQuickLoadSlot (gui_config->current_save_slot);
276 }
277
278 else if (cmd.port[0] == PORT_INCREMENTSAVESLOT)
279 {
280 change_slot (1);
281 S9xQuickSaveSlot (gui_config->current_save_slot);
282 }
283
284 else if (cmd.port[0] == PORT_DECREMENTLOADSLOT)
285 {
286 change_slot (-1);
287 S9xQuickLoadSlot (gui_config->current_save_slot);
288 }
289
290 else if (cmd.port[0] == PORT_INCREMENTSLOT)
291 {
292 change_slot (1);
293 }
294
295 else if (cmd.port[0] == PORT_DECREMENTSLOT)
296 {
297 change_slot (-1);
298 }
299
300 else if (cmd.port[0] == PORT_GRABMOUSE)
301 {
302 top_level->toggle_grab_mouse ();
303 }
304 }
305 }
306
S9xGetBindingByName(const char * name)307 Binding S9xGetBindingByName (const char *name)
308 {
309 for (int i = 0; i < NUM_EMU_LINKS; i++)
310 {
311 if (!strcasecmp (b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name))
312 {
313 return gui_config->shortcut[i];
314 }
315 }
316
317 return Binding ();
318 }
319
S9xGetPortCommandT(const char * name)320 s9xcommand_t S9xGetPortCommandT (const char *name)
321 {
322 s9xcommand_t cmd;
323
324 cmd.type = S9xButtonPort;
325 cmd.multi_press = 0;
326 cmd.button_norpt = 0;
327 cmd.port[0] = 0;
328 cmd.port[1] = 0;
329 cmd.port[2] = 0;
330 cmd.port[3] = 0;
331
332 if (!strcasecmp (name, "GTK_fullscreen"))
333 {
334 cmd.port[0] = PORT_COMMAND_FULLSCREEN;
335 }
336
337 else if (!strcasecmp (name, "GTK_save_spc"))
338 {
339 cmd.port[0] = PORT_COMMAND_SAVE_SPC;
340 }
341
342 else if (!strcasecmp (name, "GTK_open_rom"))
343 {
344 cmd.port[0] = PORT_OPEN_ROM;
345 }
346
347 else if (!strcasecmp (name, "GTK_pause"))
348 {
349 cmd.port[0] = PORT_PAUSE;
350 }
351
352 else if (!strcasecmp (name, "GTK_seek_to_frame"))
353 {
354 cmd.port[0] = PORT_SEEK_TO_FRAME;
355 }
356
357 else if (!strcasecmp (name, "GTK_quit"))
358 {
359 cmd.port[0] = PORT_QUIT;
360 }
361
362 else if (!strcasecmp (name, "GTK_swap_controllers"))
363 {
364 cmd.port[0] = PORT_SWAP_CONTROLLERS;
365 }
366
367 else if (!strcasecmp (name, "GTK_rewind"))
368 {
369 cmd.port[0] = PORT_REWIND;
370 }
371
372 else if (strstr (name, "QuickLoad000"))
373 {
374 cmd.port[0] = PORT_QUICKLOAD0;
375 }
376
377 else if (strstr (name, "QuickLoad001"))
378 {
379 cmd.port[0] = PORT_QUICKLOAD1;
380 }
381
382 else if (strstr (name, "QuickLoad002"))
383 {
384 cmd.port[0] = PORT_QUICKLOAD2;
385 }
386
387 else if (strstr (name, "QuickLoad003"))
388 {
389 cmd.port[0] = PORT_QUICKLOAD3;
390 }
391
392 else if (strstr (name, "QuickLoad004"))
393 {
394 cmd.port[0] = PORT_QUICKLOAD4;
395 }
396
397 else if (strstr (name, "QuickLoad005"))
398 {
399 cmd.port[0] = PORT_QUICKLOAD5;
400 }
401
402 else if (strstr (name, "QuickLoad006"))
403 {
404 cmd.port[0] = PORT_QUICKLOAD6;
405 }
406
407 else if (strstr (name, "QuickLoad007"))
408 {
409 cmd.port[0] = PORT_QUICKLOAD7;
410 }
411
412 else if (strstr (name, "QuickLoad008"))
413 {
414 cmd.port[0] = PORT_QUICKLOAD8;
415 }
416
417 else if (strstr (name, "QuickLoad009"))
418 {
419 cmd.port[0] = PORT_QUICKLOAD9;
420 }
421
422 else if (strstr (name, "GTK_state_save_current"))
423 {
424 cmd.port[0] = PORT_SAVESLOT;
425 }
426
427 else if (strstr (name, "GTK_state_load_current"))
428 {
429 cmd.port[0] = PORT_LOADSLOT;
430 }
431
432 else if (strstr (name, "GTK_state_increment_save"))
433 {
434 cmd.port[0] = PORT_INCREMENTSAVESLOT;
435 }
436
437 else if (strstr (name, "GTK_state_decrement_load"))
438 {
439 cmd.port[0] = PORT_DECREMENTLOADSLOT;
440 }
441
442 else if (strstr (name, "GTK_state_increment"))
443 {
444 cmd.port[0] = PORT_INCREMENTSLOT;
445 }
446
447 else if (strstr (name, "GTK_state_decrement"))
448 {
449 cmd.port[0] = PORT_DECREMENTSLOT;
450 }
451
452 else if (strstr (name, "GTK_grab_mouse"))
453 {
454 cmd.port[0] = PORT_GRABMOUSE;
455 }
456
457
458 else
459 {
460 cmd = S9xGetCommandT (name);
461 }
462
463 return cmd;
464 }
465
S9xProcessEvents(bool8 block)466 void S9xProcessEvents (bool8 block)
467 {
468 JoyEvent event;
469 Binding binding;
470
471 if (S9xGrabJoysticks ())
472 {
473 for (int i = 0; gui_config->joystick[i]; i++)
474 {
475 while (gui_config->joystick[i]->get_event (&event))
476 {
477 binding = Binding (i, event.parameter, 0);
478 S9xReportButton (binding.hex (), event.state == JOY_PRESSED ? 1 : 0);
479 gui_config->screensaver_needs_reset = true;
480 }
481 }
482
483 S9xReleaseJoysticks ();
484 }
485 }
486
poll_joystick_events()487 static void poll_joystick_events ()
488 {
489 SDL_Event event;
490
491 while (SDL_PollEvent (&event))
492 {
493 if (event.type == SDL_JOYAXISMOTION)
494 {
495 gui_config->joystick[event.jaxis.which]->handle_event (&event);
496 }
497
498 else if (event.type == SDL_JOYHATMOTION)
499 {
500 gui_config->joystick[event.jhat.which]->handle_event (&event);
501 }
502
503 else if (event.type == SDL_JOYBUTTONUP ||
504 event.type == SDL_JOYBUTTONDOWN)
505 {
506 gui_config->joystick[event.jbutton.which]->handle_event (&event);
507 }
508 }
509 }
510
S9xInitInputDevices()511 void S9xInitInputDevices ()
512 {
513 SDL_Init (SDL_INIT_JOYSTICK);
514
515 for (int i = 0; ; i++)
516 {
517 gui_config->joystick = (JoyDevice **)
518 realloc (gui_config->joystick,
519 sizeof (JoyDevice *) * (i + 1));
520
521 gui_config->joystick[i] = new JoyDevice (i);
522
523 if (!gui_config->joystick[i]->enabled)
524 {
525 delete gui_config->joystick[i];
526 gui_config->joystick[i] = NULL;
527 break;
528 }
529 else
530 {
531 gui_config->joystick[i]->joynum = i;
532 }
533 }
534
535 //First plug in both, they'll change later as needed
536 S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0);
537 S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0);
538 }
539
S9xDeinitInputDevices()540 void S9xDeinitInputDevices ()
541 {
542 for (int i = 0; gui_config->joystick[i] != NULL; i++)
543 {
544 delete gui_config->joystick[i];
545 }
546
547 free (gui_config->joystick);
548
549 SDL_Quit ();
550 }
551
JoyDevice(unsigned int device_num)552 JoyDevice::JoyDevice (unsigned int device_num)
553 {
554 enabled = false;
555 axis = NULL;
556 filedes = NULL;
557 mode = JOY_MODE_INDIVIDUAL;
558
559 if ((int) device_num >= SDL_NumJoysticks ())
560 return;
561
562 filedes = SDL_JoystickOpen (device_num);
563
564 if (!filedes)
565 return;
566
567 enabled = true;
568
569 num_axes = SDL_JoystickNumAxes (filedes);
570 num_hats = SDL_JoystickNumHats (filedes);
571 axis = new int[num_axes];
572 hat = new int[num_hats];
573 calibration = new Calibration[num_axes];
574
575 for (int i = 0; i < num_axes; i++)
576 {
577 calibration[i].min = -32767;
578 calibration[i].max = 32767;
579 calibration[i].center = 0;
580 }
581
582 printf ("Joystick %d, %s:\n %d axes, %d buttons, %d hats\n",
583 device_num + 1,
584 SDL_JoystickName (filedes),
585 SDL_JoystickNumButtons (filedes),
586 num_axes,
587 num_hats);
588
589 memset (axis, 0, sizeof (int) * num_axes);
590 }
591
~JoyDevice()592 JoyDevice::~JoyDevice ()
593 {
594 if (enabled)
595 {
596 SDL_JoystickClose (filedes);
597 delete[] axis;
598 delete[] hat;
599 delete[] calibration;
600 }
601
602 enabled = false;
603 }
604
add_event(unsigned int parameter,unsigned int state)605 void JoyDevice::add_event (unsigned int parameter, unsigned int state)
606 {
607 JoyEvent event = { parameter, state };
608
609 queue.push (event);
610 }
611
register_centers()612 void JoyDevice::register_centers ()
613 {
614 for (int i = 0; i < num_axes; i++)
615 {
616 calibration[i].center = SDL_JoystickGetAxis (filedes, i);
617
618 /* Snap centers to specific target points */
619 if (calibration[i].center < -24576)
620 calibration[i].center = -32768;
621 else if (calibration[i].center < -8192)
622 calibration[i].center = -16384;
623 else if (calibration[i].center < 8192)
624 calibration[i].center = 0;
625 else if (calibration[i].center < 24576)
626 calibration[i].center = 16383;
627 else
628 calibration[i].center = 32767;
629 }
630 }
631
handle_event(SDL_Event * event)632 void JoyDevice::handle_event (SDL_Event *event)
633 {
634 if (event->type == SDL_JOYAXISMOTION)
635 {
636 int cal_min = calibration[event->jaxis.axis].min;
637 int cal_max = calibration[event->jaxis.axis].max;
638 int cal_cen = calibration[event->jaxis.axis].center;
639 int t = gui_config->joystick_threshold;
640 int ax_min = (cal_min - cal_cen) * t / 100 + cal_cen;
641 int ax_max = (cal_max - cal_cen) * t / 100 + cal_cen;
642
643 if (mode == JOY_MODE_INDIVIDUAL)
644 {
645 for (int i = 0; i < NUM_JOYPADS; i++)
646 {
647 Binding *pad = (Binding *) &(gui_config->pad[i]);
648
649 for (int j = 0; j < NUM_JOYPAD_LINKS; j++)
650 {
651 if (pad[j].get_axis () == event->jaxis.axis &&
652 pad[j].get_device () == (unsigned int) (joynum + 1))
653 {
654 t = pad[j].get_threshold ();
655
656 if (pad[j].is_positive ())
657 {
658 ax_max = (cal_max - cal_cen) * t / 100 + cal_cen;
659 }
660 else if (pad[j].is_negative ())
661 {
662 ax_min = (cal_min - cal_cen) * t / 100 + cal_cen;
663 }
664 }
665 }
666 }
667
668 for (int i = 0; i < NUM_EMU_LINKS; i++)
669 {
670 if (gui_config->shortcut[i].get_axis () == event->jaxis.axis &&
671 gui_config->shortcut[i].get_device () ==
672 (unsigned int) (joynum + 1))
673 {
674 t = gui_config->shortcut[i].get_threshold ();
675 if (gui_config->shortcut[i].is_positive ())
676 {
677 ax_max = (cal_max - cal_cen) * t / 100 + cal_cen;
678 }
679 else if (gui_config->shortcut[i].is_negative ())
680 {
681 ax_min = (cal_min - cal_cen) * t / 100 + cal_cen;
682 }
683 }
684 }
685 }
686 else if (mode == JOY_MODE_CALIBRATE)
687 {
688 if (event->jaxis.value < calibration[event->jaxis.axis].min)
689 calibration[event->jaxis.axis].min = event->jaxis.value;
690 if (event->jaxis.value > calibration[event->jaxis.axis].max)
691 calibration[event->jaxis.axis].min = event->jaxis.value;
692 }
693
694 /* Sanity Check */
695 if (ax_min >= cal_cen)
696 ax_min = cal_cen - 1;
697 if (ax_max <= cal_cen)
698 ax_max = cal_cen + 1;
699
700 if (event->jaxis.value <= ax_min &&
701 axis[event->jaxis.axis] > ax_min)
702 {
703 add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 1);
704 }
705
706 if (event->jaxis.value > ax_min &&
707 axis[event->jaxis.axis] <= ax_min)
708 {
709 add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 0);
710 }
711
712 if (event->jaxis.value >= ax_max &&
713 axis[event->jaxis.axis] < ax_max)
714 {
715 add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 1);
716 }
717
718 if (event->jaxis.value < ax_max &&
719 axis[event->jaxis.axis] >= ax_max)
720 {
721 add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 0);
722 }
723
724 axis[event->jaxis.axis] = event->jaxis.value;
725
726 }
727
728 else if (event->type == SDL_JOYBUTTONUP ||
729 event->type == SDL_JOYBUTTONDOWN)
730 {
731 add_event (event->jbutton.button,
732 event->jbutton.state == SDL_PRESSED ? 1 : 0);
733 }
734
735 else if (event->type == SDL_JOYHATMOTION)
736 {
737 if ((event->jhat.value & SDL_HAT_UP) &&
738 !(hat[event->jhat.hat] & SDL_HAT_UP))
739 {
740 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 1);
741 }
742
743 if (!(event->jhat.value & SDL_HAT_UP) &&
744 (hat[event->jhat.hat] & SDL_HAT_UP))
745 {
746 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 0);
747 }
748
749 if ((event->jhat.value & SDL_HAT_DOWN) &&
750 !(hat[event->jhat.hat] & SDL_HAT_DOWN))
751 {
752 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 1);
753 }
754
755 if (!(event->jhat.value & SDL_HAT_DOWN) &&
756 (hat[event->jhat.hat] & SDL_HAT_DOWN))
757 {
758 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 0);
759 }
760
761 if ((event->jhat.value & SDL_HAT_LEFT) &&
762 !(hat[event->jhat.hat] & SDL_HAT_LEFT))
763 {
764 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 1);
765 }
766
767 if (!(event->jhat.value & SDL_HAT_LEFT) &&
768 (hat[event->jhat.hat] & SDL_HAT_LEFT))
769 {
770 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 0);
771 }
772
773 if ((event->jhat.value & SDL_HAT_RIGHT) &&
774 !(hat[event->jhat.hat] & SDL_HAT_RIGHT))
775 {
776 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 1);
777 }
778
779 if (!(event->jhat.value & SDL_HAT_RIGHT) &&
780 (hat[event->jhat.hat] & SDL_HAT_RIGHT))
781 {
782 add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 0);
783 }
784
785 hat[event->jhat.hat] = event->jhat.value;
786 }
787 }
788
get_event(JoyEvent * event)789 int JoyDevice::get_event (JoyEvent *event)
790 {
791 poll_events ();
792
793 if (queue.empty ())
794 return 0;
795
796 event->parameter = queue.front ().parameter;
797 event->state = queue.front ().state;
798
799 queue.pop ();
800
801 return 1;
802 }
803
poll_events()804 void JoyDevice::poll_events ()
805 {
806 poll_joystick_events ();
807 }
808
flush()809 void JoyDevice::flush ()
810 {
811 SDL_Event event;
812
813 while (SDL_PollEvent (&event))
814 {
815 }
816
817 while (!queue.empty ())
818 queue.pop ();
819 }
820