2 // gamepad.cpp - Host joystick handling (using SDL)
5 // (C) 2013 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- ------------------------------------------------------------
11 // JLH 01/05/2013 Created this file
18 // Class member initialization
19 /*static*/ int Gamepad::numJoysticks
= 0;
20 /*static*/ SDL_Joystick
* Gamepad::pad
[8];
21 /*static*/ char Gamepad::padName
[8][128];
22 /*static*/ int Gamepad::numButtons
[8];
23 /*static*/ int Gamepad::numHats
[8];
24 /*static*/ int Gamepad::numAxes
[8];
25 /*static*/ bool Gamepad::button
[8][256];
26 /*static*/ uint8_t Gamepad::hat
[8][32];
27 /*static*/ int32_t Gamepad::axis
[8][32];
30 Gamepad::Gamepad(void)//: numJoysticks(0)
36 Gamepad::~Gamepad(void)
38 DeallocateJoysticks();
42 void Gamepad::AllocateJoysticks(void)
44 // DeallocateJoysticks();
45 numJoysticks
= SDL_NumJoysticks();
51 for(int i
=0; i
<numJoysticks
; i
++)
53 pad
[i
] = SDL_JoystickOpen(i
);
54 numButtons
[i
] = numHats
[i
] = numAxes
[i
] = 0;
55 // We need to copy the contents of this pointer, as SDL will change it
56 // willy nilly to suit itself
57 // padName[i] = SDL_JoystickName(i);
58 strncpy(padName
[i
], SDL_JoystickName(i
), 127);
59 padName
[i
][127] = 0; // Just in case name's length > 127
63 numButtons
[i
] = SDL_JoystickNumButtons(pad
[i
]);
64 numHats
[i
] = SDL_JoystickNumHats(pad
[i
]);
65 numAxes
[i
] = SDL_JoystickNumAxes(pad
[i
]);
66 WriteLog("Gamepad: Joystick #%i: %s\n", i
, padName
[i
]);
68 // Ick, kludges already!!!
69 if (strcmp(padName
[i
], "Sony PLAYSTATION(R)3 Controller") == 0)
71 // We do this because these axes stay stuck on -32767 (buttons)
72 // or start at 0 and stay stuck at -32767 (D-pad). :-P
74 WriteLog("Gamepad: Blacklisting PS3 controller axes 8 on up...\n");
79 WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks
, (numJoysticks
== 1 ? "" : "s"));
81 for(int i
=0; i
<numJoysticks
; i
++)
82 printf("GAMEPAD::AllocateJoysticks: stick #%i = %s\n", i
, padName
[i
]);
87 void Gamepad::DeallocateJoysticks(void)
89 for(int i
=0; i
<numJoysticks
; i
++)
90 SDL_JoystickClose(pad
[i
]);
94 const char * Gamepad::GetJoystickName(int joystickID
)
100 //printf("GAMEPAD: Getting name (%s) for joystick #%i...\n", padName[joystickID], joystickID);
101 return padName
[joystickID
];
105 bool Gamepad::GetState(int joystickID
, int buttonID
)
107 uint8_t hatMask
[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
109 if (buttonID
& JOY_BUTTON
)
112 int buttonNum
= (buttonID
& JOY_BUTTON_MASK
);
113 return button
[joystickID
][buttonNum
];
115 else if (buttonID
& JOY_HAT
)
118 int hatNumber
= (buttonID
& JOY_HATNUM_MASK
) >> 3;
119 uint8_t hatDirection
= hatMask
[buttonID
& JOY_HATBUT_MASK
];
120 return (hat
[joystickID
][hatNumber
] & hatDirection
? true : false);
122 else if (buttonID
& JOY_AXIS
)
124 int axisNum
= (buttonID
& JOY_AXISNUM_MASK
) >> 1;
125 int direction
= (buttonID
& JOY_AXISDIR_MASK
);
126 //printf("Checking pad #%u axis %u: axis = %i, direction = %u\n", joystickID, axisNum, axis[joystickID][axisNum], direction);
128 if (axis
[joystickID
][axisNum
] != 0)
130 if ((axis
[joystickID
][axisNum
] > 32000) && (direction
== 0))
132 //printf("Axis + hit!\n");
136 if ((axis
[joystickID
][axisNum
] < -32000) && (direction
== 1))
138 //printf("Axis - hit!\n");
144 // Default == failure
149 int Gamepad::CheckButtonPressed(void)
151 DumpJoystickStatesToLog();
153 // This translates the hat direction to a mask index.
154 int hatNum
[16] = { -1, 0, 1, -1, 2, -1, -1, -1,
155 3, -1, -1, -1, -1, -1, -1, -1 };
157 // Return single button ID being pressed (if any)
158 for(int i
=0; i
<numJoysticks
; i
++)
160 for(int j
=0; j
<numButtons
[i
]; j
++)
163 return (JOY_BUTTON
| j
);
166 for(int j
=0; j
<numHats
[i
]; j
++)
169 return (JOY_HAT
| hatNum
[hat
[i
][j
]]);
172 for(int j
=0; j
<numAxes
[i
]; j
++)
174 // We encode these as axis # (in bits 1-15), up or down in bit 0.
175 // if (axis[i][j] > 0)
176 if (axis
[i
][j
] > 32000)
177 return (JOY_AXIS
| (j
<< 1) | 0);
179 // if (axis[i][j] < 0)
180 if (axis
[i
][j
] < -32000)
181 return (JOY_AXIS
| (j
<< 1) | 1);
190 int Gamepad::GetButtonID(void)
192 // Return single button ID being pressed (if any)
198 int Gamepad::GetJoystickID(void)
200 // Return joystick ID of button being pressed (if any)
205 void Gamepad::Update(void)
207 // SDL_PollEvent(&event);
208 SDL_JoystickUpdate();
210 for(int i
=0; i
<numJoysticks
; i
++)
212 for(int j
=0; j
<numButtons
[i
]; j
++)
213 button
[i
][j
] = SDL_JoystickGetButton(pad
[i
], j
);
215 for(int j
=0; j
<numHats
[i
]; j
++)
216 hat
[i
][j
] = SDL_JoystickGetHat(pad
[i
], j
);
218 for(int j
=0; j
<numAxes
[i
]; j
++)
219 axis
[i
][j
] = SDL_JoystickGetAxis(pad
[i
], j
);
224 void Gamepad::DumpJoystickStatesToLog(void)
226 bool pressed
= false;
228 for(int i
=0; i
<numJoysticks
; i
++)
230 for(int j
=0; j
<numButtons
[i
]; j
++)
240 for(int j
=0; j
<numHats
[i
]; j
++)
250 for(int j
=0; j
<numAxes
[i
]; j
++)
252 // We encode these as axis # (in bits 1-15), up or down in bit 0.
253 if (axis
[i
][j
] > 32000)
260 if (axis
[i
][j
] < -32000)
272 WriteLog("Gamepad: CheckButtonPressed...\n");
274 for(int i
=0; i
<numJoysticks
; i
++)
276 for(int j
=0; j
<numButtons
[i
]; j
++)
279 WriteLog("Gamepad: Pad #%i, button %i down...\n", i
, j
);
282 for(int j
=0; j
<numHats
[i
]; j
++)
285 WriteLog("Gamepad: Pad #%i, hat %i pushed...\n", i
, j
);
288 for(int j
=0; j
<numAxes
[i
]; j
++)
290 // We encode these as axis # (in bits 1-15), up or down in bit 0.
291 if (axis
[i
][j
] > 32000)
292 WriteLog("Gamepad: Pad #%i, axis %i pushed down...\n", i
, j
);
294 if (axis
[i
][j
] < -32000)
295 WriteLog("Gamepad: Pad #%i, axis %i pushed up...\n", i
, j
);
301 // However, SDL 2 *does* support hot-plugging! :-D
303 // Need to test this. It may be that the only time joysticks are detected is
304 // when the program is first run. That would suck.
305 // Well, it turns out that SDL doesn't do hot plugging. :-(
306 void Gamepad::CheckConsistency(void)
308 int currentNumJoysticks
= SDL_NumJoysticks();
310 // Check to see if the # of joysticks reported by SDL changed
311 if (currentNumJoysticks
== numJoysticks
)
314 // Either one or more joysticks were plugged in, or removed. Fix up our
315 // internal states to reflect this.