Handle number of M68K cycles used when tracing in debugger mode
[clinton/Virtual-Jaguar-Rx.git] / src / gui / gamepad.cpp
CommitLineData
cf76e892
JPM
1//
2// gamepad.cpp - Host joystick handling (using SDL)
3//
4// by James Hammons
5// (C) 2013 Underground Software
6//
7// JLH = James Hammons <jlhamm@acm.org>
8//
9// Who When What
10// --- ---------- ------------------------------------------------------------
11// JLH 01/05/2013 Created this file
12//
13
14#include "gamepad.h"
15#include "log.h"
16
17
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];
28
29
30Gamepad::Gamepad(void)//: numJoysticks(0)
31{
32 AllocateJoysticks();
33}
34
35
36Gamepad::~Gamepad(void)
37{
38 DeallocateJoysticks();
39}
40
41
42void Gamepad::AllocateJoysticks(void)
43{
44// DeallocateJoysticks();
45 numJoysticks = SDL_NumJoysticks();
46
47 // Sanity check
48 if (numJoysticks > 8)
49 numJoysticks = 8;
50
51 for(int i=0; i<numJoysticks; i++)
52 {
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
60
61 if (pad[i])
62 {
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]);
67
68 // Ick, kludges already!!!
69 if (strcmp(padName[i], "Sony PLAYSTATION(R)3 Controller") == 0)
70 {
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
73 numAxes[i] = 8;
74 WriteLog("Gamepad: Blacklisting PS3 controller axes 8 on up...\n");
75 }
76 }
77 }
78
79 WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks, (numJoysticks == 1 ? "" : "s"));
80#if 0
81for(int i=0; i<numJoysticks; i++)
82 printf("GAMEPAD::AllocateJoysticks: stick #%i = %s\n", i, padName[i]);
83#endif
84}
85
86
87void Gamepad::DeallocateJoysticks(void)
88{
89 for(int i=0; i<numJoysticks; i++)
90 SDL_JoystickClose(pad[i]);
91}
92
93
94const char * Gamepad::GetJoystickName(int joystickID)
95{
96 // Sanity check
97 if (joystickID >= 8)
98 return NULL;
99
100//printf("GAMEPAD: Getting name (%s) for joystick #%i...\n", padName[joystickID], joystickID);
101 return padName[joystickID];
102}
103
104
105bool Gamepad::GetState(int joystickID, int buttonID)
106{
107 uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
108
109 if (buttonID & JOY_BUTTON)
110 {
111 // Handle SDL button
112 int buttonNum = (buttonID & JOY_BUTTON_MASK);
113 return button[joystickID][buttonNum];
114 }
115 else if (buttonID & JOY_HAT)
116 {
117 // Handle SDL hats
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);
121 }
122 else if (buttonID & JOY_AXIS)
123 {
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);
127
128 if (axis[joystickID][axisNum] != 0)
129 {
130 if ((axis[joystickID][axisNum] > 32000) && (direction == 0))
131//{
132//printf("Axis + hit!\n");
133 return true;
134//}
135
136 if ((axis[joystickID][axisNum] < -32000) && (direction == 1))
137//{
138//printf("Axis - hit!\n");
139 return true;
140//}
141 }
142 }
143
144 // Default == failure
145 return false;
146}
147
148
149int Gamepad::CheckButtonPressed(void)
150{
151 DumpJoystickStatesToLog();
152
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 };
156
157 // Return single button ID being pressed (if any)
158 for(int i=0; i<numJoysticks; i++)
159 {
160 for(int j=0; j<numButtons[i]; j++)
161 {
162 if (button[i][j])
163 return (JOY_BUTTON | j);
164 }
165
166 for(int j=0; j<numHats[i]; j++)
167 {
168 if (hat[i][j])
169 return (JOY_HAT | hatNum[hat[i][j]]);
170 }
171
172 for(int j=0; j<numAxes[i]; j++)
173 {
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);
178
179// if (axis[i][j] < 0)
180 if (axis[i][j] < -32000)
181 return (JOY_AXIS | (j << 1) | 1);
182 }
183 }
184
185 return -1;
186}
187
188
189// UNUSED
190int Gamepad::GetButtonID(void)
191{
192 // Return single button ID being pressed (if any)
193 return -1;
194}
195
196
197// UNUSED
198int Gamepad::GetJoystickID(void)
199{
200 // Return joystick ID of button being pressed (if any)
201 return -1;
202}
203
204
205void Gamepad::Update(void)
206{
207// SDL_PollEvent(&event);
208 SDL_JoystickUpdate();
209
210 for(int i=0; i<numJoysticks; i++)
211 {
212 for(int j=0; j<numButtons[i]; j++)
213 button[i][j] = SDL_JoystickGetButton(pad[i], j);
214
215 for(int j=0; j<numHats[i]; j++)
216 hat[i][j] = SDL_JoystickGetHat(pad[i], j);
217
218 for(int j=0; j<numAxes[i]; j++)
219 axis[i][j] = SDL_JoystickGetAxis(pad[i], j);
220 }
221}
222
223
224void Gamepad::DumpJoystickStatesToLog(void)
225{
226 bool pressed = false;
227
228 for(int i=0; i<numJoysticks; i++)
229 {
230 for(int j=0; j<numButtons[i]; j++)
231 {
232 if (button[i][j])
233 {
234 pressed = true;
235 break;
236 break;
237 }
238 }
239
240 for(int j=0; j<numHats[i]; j++)
241 {
242 if (hat[i][j])
243 {
244 pressed = true;
245 break;
246 break;
247 }
248 }
249
250 for(int j=0; j<numAxes[i]; j++)
251 {
252 // We encode these as axis # (in bits 1-15), up or down in bit 0.
253 if (axis[i][j] > 32000)
254 {
255 pressed = true;
256 break;
257 break;
258 }
259
260 if (axis[i][j] < -32000)
261 {
262 pressed = true;
263 break;
264 break;
265 }
266 }
267 }
268
269 if (!pressed)
270 return;
271
272 WriteLog("Gamepad: CheckButtonPressed...\n");
273
274 for(int i=0; i<numJoysticks; i++)
275 {
276 for(int j=0; j<numButtons[i]; j++)
277 {
278 if (button[i][j])
279 WriteLog("Gamepad: Pad #%i, button %i down...\n", i, j);
280 }
281
282 for(int j=0; j<numHats[i]; j++)
283 {
284 if (hat[i][j])
285 WriteLog("Gamepad: Pad #%i, hat %i pushed...\n", i, j);
286 }
287
288 for(int j=0; j<numAxes[i]; j++)
289 {
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);
293
294 if (axis[i][j] < -32000)
295 WriteLog("Gamepad: Pad #%i, axis %i pushed up...\n", i, j);
296 }
297 }
298}
299
300
301// However, SDL 2 *does* support hot-plugging! :-D
302#if 0
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. :-(
306void Gamepad::CheckConsistency(void)
307{
308 int currentNumJoysticks = SDL_NumJoysticks();
309
310 // Check to see if the # of joysticks reported by SDL changed
311 if (currentNumJoysticks == numJoysticks)
312 return;
313
314 // Either one or more joysticks were plugged in, or removed. Fix up our
315 // internal states to reflect this.
316
317
318}
319#endif
320