Reinitialize gamepads command and fix EVDEV going bonkers on gamepad suddenly disconn...
[lsnes.git] / src / platform / win32mm / joystick.cpp
blob60dc94e31eab92dcc01c2fd99a00ecfeb8b6f09a
1 #include "core/command.hpp"
2 #include "core/framerate.hpp"
3 #include "core/keymapper.hpp"
4 #include "core/joystickapi.hpp"
5 #include "core/messages.hpp"
6 #include "core/window.hpp"
7 #include "library/minmax.hpp"
8 #include "library/string.hpp"
10 #include <windows.h>
11 #include <mmsystem.h>
12 #include <regstr.h>
13 #include <cstdlib>
14 #include <string>
15 #include <sstream>
16 #include <iostream>
17 #include <stdexcept>
18 #include <sys/time.h>
19 #include <unistd.h>
21 namespace
23 volatile bool quit_signaled;
24 volatile bool quit_ack;
25 std::map<unsigned, unsigned> idx_to_jid;
26 unsigned joysticks;
28 const char* buttonnames[] = {"Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7",
29 "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15",
30 "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23",
31 "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31",
32 "Button32"};
33 #define POLL_WAIT 20000
35 struct _joystick_driver drv = {
36 .init = []() -> void {
37 quit_signaled = false;
38 quit_ack = false;
39 unsigned max_joysticks = joyGetNumDevs();
40 if(!max_joysticks)
41 return; //No joystick support.
42 joysticks = max_joysticks;
43 for(unsigned i = 0; i < max_joysticks; i++) {
44 JOYINFOEX info;
45 JOYCAPS caps;
46 info.dwSize = sizeof(info);
47 info.dwFlags = JOY_RETURNALL;
48 if(joyGetPosEx(i, &info) != JOYERR_NOERROR)
49 continue; //Not usable.
50 if(joyGetDevCaps(i, &caps, sizeof(caps)) != JOYERR_NOERROR)
51 continue; //Not usable.
52 idx_to_jid[i] = lsnes_gamepads.add(caps.szPname);
53 gamepad::pad& ngp = lsnes_gamepads[idx_to_jid[i]];
54 if(caps.wCaps & JOYCAPS_HASPOV)
55 ngp.add_hat(0, "POV");
56 for(unsigned j = 0; j < caps.wNumButtons && j < 32; j++)
57 ngp.add_button(j, buttonnames[j]);
58 ngp.add_axis(0, caps.wXmin, caps.wXmax, false, "X");
59 ngp.add_axis(1, caps.wYmin, caps.wYmax, false, "Y");
60 if(caps.wCaps & JOYCAPS_HASZ) ngp.add_axis(2, caps.wZmin, caps.wZmax, false, "Z");
61 if(caps.wCaps & JOYCAPS_HASR) ngp.add_axis(3, caps.wRmin, caps.wRmax, false,
62 "Rudder");
63 if(caps.wCaps & JOYCAPS_HASU) ngp.add_axis(4, caps.wUmin, caps.wUmax, false, "U");
64 if(caps.wCaps & JOYCAPS_HASV) ngp.add_axis(5, caps.wVmin, caps.wVmax, false, "V");
65 messages << "Joystick #" << idx_to_jid[i] << " online: " << caps.szPname << std::endl;
67 quit_ack = quit_signaled = false;
69 .quit = []() -> void {
70 quit_signaled = true;
71 while(!quit_ack);
73 .thread_fn = []() -> void {
74 while(!quit_signaled) {
75 for(unsigned i = 0; i < joysticks; i++) {
76 JOYINFOEX info;
77 info.dwSize = sizeof(info);
78 info.dwFlags = JOY_RETURNALL;
79 if(joyGetPosEx(i, &info) != JOYERR_NOERROR)
80 continue; //Not usable.
81 lsnes_gamepads[idx_to_jid[i]].report_hat(0, info.dwPOV);
82 for(unsigned j = 0; j < 32; j++)
83 lsnes_gamepads[idx_to_jid[i]].report_button(j,
84 (info.dwButtons >> j) & 1);
85 lsnes_gamepads[idx_to_jid[i]].report_axis(0, info.dwXpos);
86 lsnes_gamepads[idx_to_jid[i]].report_axis(1, info.dwYpos);
87 lsnes_gamepads[idx_to_jid[i]].report_axis(2, info.dwZpos);
88 lsnes_gamepads[idx_to_jid[i]].report_axis(3, info.dwRpos);
89 lsnes_gamepads[idx_to_jid[i]].report_axis(4, info.dwUpos);
90 lsnes_gamepads[idx_to_jid[i]].report_axis(5, info.dwVpos);
92 usleep(POLL_WAIT);
94 quit_ack = true;
96 .signal = []() -> void {
97 quit_signaled = true;
98 while(!quit_ack);
100 .name = []() -> const char* { return "Win32mm joystick plugin"; }
102 struct joystick_driver _drv(drv);