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]);
70 WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks, (numJoysticks == 1 ? "" : "s"));
72 for(int i=0; i<numJoysticks; i++)
73 printf("GAMEPAD::AllocateJoysticks: stick #%i = %s\n", i, padName[i]);
78 void Gamepad::DeallocateJoysticks(void)
80 for(int i=0; i<numJoysticks; i++)
81 SDL_JoystickClose(pad[i]);
85 const char * Gamepad::GetJoystickName(int joystickID)
91 //printf("GAMEPAD: Getting name (%s) for joystick #%i...\n", padName[joystickID], joystickID);
92 return padName[joystickID];
96 bool Gamepad::GetState(int joystickID, int buttonID)
98 uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
100 if (buttonID & JOY_BUTTON)
103 int buttonNum = (buttonID & JOY_BUTTON_MASK);
104 return button[joystickID][buttonNum];
106 else if (buttonID & JOY_HAT)
109 int hatNumber = (buttonID & JOY_HATNUM_MASK) >> 3;
110 uint8_t hatDirection = hatMask[buttonID & JOY_HATBUT_MASK];
111 return (hat[joystickID][hatNumber] & hatDirection ? true : false);
113 else if (buttonID & JOY_AXIS)
115 int axisNum = (buttonID & JOY_AXISNUM_MASK) >> 1;
116 int direction = (buttonID & JOY_AXISDIR_MASK);
117 //printf("Checking pad #%u axis %u: axis = %i, direction = %u\n", joystickID, axisNum, axis[joystickID][axisNum], direction);
119 if (axis[joystickID][axisNum] != 0)
121 if ((axis[joystickID][axisNum] > 32000) && (direction == 0))
123 //printf("Axis + hit!\n");
127 if ((axis[joystickID][axisNum] < -32000) && (direction == 1))
129 //printf("Axis - hit!\n");
135 // Default == failure
141 int Gamepad::CheckButtonPressed(void)
143 // This translates the hat direction to a mask index.
144 int hatNum[16] = { -1, 0, 1, -1, 2, -1, -1, -1,
145 3, -1, -1, -1, -1, -1, -1, -1 };
147 // Return single button ID being pressed (if any)
148 for(int i=0; i<numJoysticks; i++)
150 for(int j=0; j<numButtons[i]; j++)
153 return (JOY_BUTTON | j);
156 for(int j=0; j<numHats[i]; j++)
159 return (JOY_HAT | hatNum[hat[i][j]]);
162 for(int j=0; j<numAxes[i]; j++)
164 // We encode these as axis # (in bits 1-15), up or down in bit 0.
165 // if (axis[i][j] > 0)
166 if (axis[i][j] > 32000)
167 return (JOY_AXIS | (j << 1) | 0);
169 // if (axis[i][j] < 0)
170 if (axis[i][j] < -32000)
171 return (JOY_AXIS | (j << 1) | 1);
180 int Gamepad::GetButtonID(void)
182 // Return single button ID being pressed (if any)
188 int Gamepad::GetJoystickID(void)
190 // Return joystick ID of button being pressed (if any)
195 void Gamepad::Update(void)
197 // SDL_PollEvent(&event);
198 SDL_JoystickUpdate();
200 for(int i=0; i<numJoysticks; i++)
202 for(int j=0; j<numButtons[i]; j++)
203 button[i][j] = SDL_JoystickGetButton(pad[i], j);
205 for(int j=0; j<numHats[i]; j++)
206 hat[i][j] = SDL_JoystickGetHat(pad[i], j);
208 for(int j=0; j<numAxes[i]; j++)
209 axis[i][j] = SDL_JoystickGetAxis(pad[i], j);
214 // However, SDL 2 *does* support hot-plugging! :-D
216 // Need to test this. It may be that the only time joysticks are detected is
217 // when the program is first run. That would suck.
218 // Well, it turns out that SDL doesn't do hot plugging. :-(
219 void Gamepad::CheckConsistency(void)
221 int currentNumJoysticks = SDL_NumJoysticks();
223 // Check to see if the # of joysticks reported by SDL changed
224 if (currentNumJoysticks == numJoysticks)
227 // Either one or more joysticks were plugged in, or removed. Fix up our
228 // internal states to reflect this.