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