]> Shamusworld >> Repos - virtualjaguar/blob - src/gui/gamepad.cpp
Fixed updated joystick handling, first major stab at gamepad profiles.
[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*/ const char * Gamepad::padName[8];
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                 padName[i] = SDL_JoystickName(i);
55                 numButtons[i] = numHats[i] = numAxes[i] = 0;
56
57                 if (pad[i])
58                 {
59                         numButtons[i] = SDL_JoystickNumButtons(pad[i]);
60                         numHats[i] = SDL_JoystickNumHats(pad[i]);
61                         numAxes[i] = SDL_JoystickNumAxes(pad[i]);
62                 }
63         }
64
65         WriteLog("Gamepad: Found %u joystick%s.\n", numJoysticks, (numJoysticks == 1 ? "" : "s"));
66 }
67
68
69 void Gamepad::DeallocateJoysticks(void)
70 {
71         for(int i=0; i<numJoysticks; i++)
72                 SDL_JoystickClose(pad[i]);
73 }
74
75
76 const char * Gamepad::GetJoystickName(int joystickID)
77 {
78         // Sanity check
79         if (joystickID >= 8)
80                 return NULL;
81
82         return padName[joystickID];
83 }
84
85
86 bool Gamepad::GetState(int joystickID, int buttonID)
87 {
88         uint8_t hatMask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
89
90         if (buttonID & JOY_BUTTON)
91         {
92                 // Handle SDL button
93                 int buttonNum = (buttonID & JOY_BUTTON_MASK);
94                 return button[joystickID][buttonNum];
95         }
96         else if (buttonID & JOY_HAT)
97         {
98                 // Handle SDL hats
99                 int hatNumber = (buttonID & JOY_HATNUM_MASK) >> 3;
100                 uint8_t hatDirection = hatMask[buttonID & JOY_HATBUT_MASK];
101                 return (hat[joystickID][hatNumber] & hatDirection ? true : false);
102         }
103         else if (buttonID & JOY_AXIS)
104         {
105                 int axisNum = (buttonID & JOY_AXISNUM_MASK) >> 1;
106                 int direction = (buttonID & JOY_AXISDIR_MASK);
107 //printf("Checking pad #%u axis %u: axis = %i, direction = %u\n", joystickID, axisNum, axis[joystickID][axisNum], direction);
108
109                 if (axis[joystickID][axisNum] != 0)
110                 {
111                         if ((axis[joystickID][axisNum] > 32000) && (direction == 0))
112 //{
113 //printf("Axis + hit!\n");
114                                 return true;
115 //}
116
117                         if ((axis[joystickID][axisNum] < -32000) && (direction == 1))
118 //{
119 //printf("Axis - hit!\n");
120                                 return true;
121 //}
122                 }
123         }
124
125         // Default == failure
126         return false;
127 }
128
129
130 int Gamepad::CheckButtonPressed(void)
131 {
132         // This translates the hat direction to a mask index.
133         int hatNum[16] = { -1, 0, 1, -1, 2, -1, -1, -1,
134                 3, -1, -1, -1, -1, -1, -1, -1 };
135
136         // Return single button ID being pressed (if any)
137         for(int i=0; i<numJoysticks; i++)
138         {
139                 for(int j=0; j<numButtons[i]; j++)
140                 {
141                         if (button[i][j])
142                                 return (JOY_BUTTON | j);
143                 }
144
145                 for(int j=0; j<numHats[i]; j++)
146                 {
147                         if (hat[i][j])
148                                 return (JOY_HAT | hatNum[hat[i][j]]);
149                 }
150
151                 for(int j=0; j<numAxes[i]; j++)
152                 {
153                         // We encode these as axis # (in bits 1-15), up or down in bit 0.
154 //                      if (axis[i][j] > 0)
155                         if (axis[i][j] > 32000)
156                                 return (JOY_AXIS | (j << 1) | 0);
157
158 //                      if (axis[i][j] < 0)
159                         if (axis[i][j] < -32000)
160                                 return (JOY_AXIS | (j << 1) | 1);
161                 }
162         }
163
164         return -1;
165 }
166
167
168 int Gamepad::GetButtonID(void)
169 {
170         // Return single button ID being pressed (if any)
171         return -1;
172 }
173
174
175 int Gamepad::GetJoystickID(void)
176 {
177         // Return joystick ID of button being pressed (if any)
178         return -1;
179 }
180
181
182 void Gamepad::Update(void)
183 {
184 //      SDL_PollEvent(&event);
185         SDL_JoystickUpdate();
186
187         for(int i=0; i<numJoysticks; i++)
188         {
189                 for(int j=0; j<numButtons[i]; j++)
190                         button[i][j] = SDL_JoystickGetButton(pad[i], j);
191
192                 for(int j=0; j<numHats[i]; j++)
193                         hat[i][j] = SDL_JoystickGetHat(pad[i], j);
194
195                 for(int j=0; j<numAxes[i]; j++)
196                         axis[i][j] = SDL_JoystickGetAxis(pad[i], j);
197         }
198 }
199
200
201 #if 0
202 // Need to test this. It may be that the only time joysticks are detected is
203 // when the program is first run. That would suck.
204 // Well, it turns out that SDL doesn't do hot plugging. :-(
205 void Gamepad::CheckConsistency(void)
206 {
207         int currentNumJoysticks = SDL_NumJoysticks();
208
209         // Check to see if the # of joysticks reported by SDL changed
210         if (currentNumJoysticks == numJoysticks)
211                 return;
212
213         // Either one or more joysticks were plugged in, or removed. Fix up our
214         // internal states to reflect this.
215
216         
217 }
218 #endif
219