]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/gamepad.cpp
Fixed controller profile system.
[virtualjaguar] / src / gui / gamepad.cpp
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
30 Gamepad::Gamepad(void)//: numJoysticks(0)
31 {
32         AllocateJoysticks();
33 }
34
35
36 Gamepad::~Gamepad(void)
37 {
38         DeallocateJoysticks();
39 }
40
41
42 void 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         }
69
70         WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks, (numJoysticks == 1 ? "" : "s"));
71 #if 0
72 for(int i=0; i<numJoysticks; i++)
73         printf("GAMEPAD::AllocateJoysticks: stick #%i = %s\n", i, padName[i]);
74 #endif
75 }
76
77
78 void Gamepad::DeallocateJoysticks(void)
79 {
80         for(int i=0; i<numJoysticks; i++)
81                 SDL_JoystickClose(pad[i]);
82 }
83
84
85 const char * Gamepad::GetJoystickName(int joystickID)
86 {
87         // Sanity check
88         if (joystickID >= 8)
89                 return NULL;
90
91 //printf("GAMEPAD: Getting name (%s) for joystick #%i...\n", padName[joystickID], joystickID);
92         return padName[joystickID];
93 }
94
95
96 bool Gamepad::GetState(int joystickID, int buttonID)
97 {
98         uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
99
100         if (buttonID & JOY_BUTTON)
101         {
102                 // Handle SDL button
103                 int buttonNum = (buttonID & JOY_BUTTON_MASK);
104                 return button[joystickID][buttonNum];
105         }
106         else if (buttonID & JOY_HAT)
107         {
108                 // Handle SDL hats
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);
112         }
113         else if (buttonID & JOY_AXIS)
114         {
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);
118
119                 if (axis[joystickID][axisNum] != 0)
120                 {
121                         if ((axis[joystickID][axisNum] > 32000) && (direction == 0))
122 //{
123 //printf("Axis + hit!\n");
124                                 return true;
125 //}
126
127                         if ((axis[joystickID][axisNum] < -32000) && (direction == 1))
128 //{
129 //printf("Axis - hit!\n");
130                                 return true;
131 //}
132                 }
133         }
134
135         // Default == failure
136         return false;
137 }
138
139
140 //UNUSED
141 int Gamepad::CheckButtonPressed(void)
142 {
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 };
146
147         // Return single button ID being pressed (if any)
148         for(int i=0; i<numJoysticks; i++)
149         {
150                 for(int j=0; j<numButtons[i]; j++)
151                 {
152                         if (button[i][j])
153                                 return (JOY_BUTTON | j);
154                 }
155
156                 for(int j=0; j<numHats[i]; j++)
157                 {
158                         if (hat[i][j])
159                                 return (JOY_HAT | hatNum[hat[i][j]]);
160                 }
161
162                 for(int j=0; j<numAxes[i]; j++)
163                 {
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);
168
169 //                      if (axis[i][j] < 0)
170                         if (axis[i][j] < -32000)
171                                 return (JOY_AXIS | (j << 1) | 1);
172                 }
173         }
174
175         return -1;
176 }
177
178
179 // UNUSED
180 int Gamepad::GetButtonID(void)
181 {
182         // Return single button ID being pressed (if any)
183         return -1;
184 }
185
186
187 // UNUSED
188 int Gamepad::GetJoystickID(void)
189 {
190         // Return joystick ID of button being pressed (if any)
191         return -1;
192 }
193
194
195 void Gamepad::Update(void)
196 {
197 //      SDL_PollEvent(&event);
198         SDL_JoystickUpdate();
199
200         for(int i=0; i<numJoysticks; i++)
201         {
202                 for(int j=0; j<numButtons[i]; j++)
203                         button[i][j] = SDL_JoystickGetButton(pad[i], j);
204
205                 for(int j=0; j<numHats[i]; j++)
206                         hat[i][j] = SDL_JoystickGetHat(pad[i], j);
207
208                 for(int j=0; j<numAxes[i]; j++)
209                         axis[i][j] = SDL_JoystickGetAxis(pad[i], j);
210         }
211 }
212
213
214 // However, SDL 2 *does* support hot-plugging! :-D
215 #if 0
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)
220 {
221         int currentNumJoysticks = SDL_NumJoysticks();
222
223         // Check to see if the # of joysticks reported by SDL changed
224         if (currentNumJoysticks == numJoysticks)
225                 return;
226
227         // Either one or more joysticks were plugged in, or removed. Fix up our
228         // internal states to reflect this.
229
230         
231 }
232 #endif
233