1 /***************************************************************************
2 Joystick.cpp - description
3 -------------------
4 begin : Sat Feb 14 2004
5 copyright : (C) 2004 by upi
6 email : upi@feel
7 ***************************************************************************/
8
9
10 #include "SDL.h"
11 #include "Event.h"
12 #include "common.h"
13 #include "Joystick.h"
14
15 #include <string.h>
16
17 CJoystick g_oJoystick;
18
19
20
CJoystick()21 CJoystick::CJoystick()
22 {
23 m_iNumJoysticks = 0;
24 }
25
26
~CJoystick()27 CJoystick::~CJoystick()
28 {
29 }
30
31
InitJoystick()32 int InitJoystick()
33 {
34 return g_oJoystick.Init();
35 }
36
37
38
Init()39 int CJoystick::Init()
40 {
41 m_iNumJoysticks = 0;
42 int iResult = SDL_InitSubSystem(SDL_INIT_JOYSTICK);
43
44 if ( iResult < 0 )
45 {
46 debug( "CJoystick::Init() failed: %s\n", SDL_GetError() );
47 return 0;
48 }
49
50 int iNumJoysticks = SDL_NumJoysticks();
51 debug( "CJoystick::Init(): Number of joysticks is %d\n", iNumJoysticks );
52
53 int i;
54 for ( i=0; i<iNumJoysticks; ++i )
55 {
56 const char* poName = SDL_JoystickName(i);
57 debug( "CJoystick::Init(): Joystick #%d is '%s'\n", i, poName );
58
59 SDL_Joystick* poJoystick = SDL_JoystickOpen(i);
60 if ( NULL == poJoystick )
61 {
62 continue;
63 }
64
65 m_apoJoysticks[m_iNumJoysticks] = poJoystick;
66 m_apcJoystickNames[m_iNumJoysticks] = poName;
67 m_abWorkaround[m_iNumJoysticks] = false;
68 m_aiHorizontalAxis[m_iNumJoysticks] = 0;
69 m_aiVerticalAxis[m_iNumJoysticks] = 0;
70
71 debug( "CJoystick::Init(): Joystick #%d has %d axes, %d buttons, %d balls, %d hats\n",
72 i,
73 SDL_JoystickNumAxes( poJoystick ),
74 SDL_JoystickNumButtons( poJoystick ),
75 SDL_JoystickNumBalls( poJoystick ),
76 SDL_JoystickNumHats( poJoystick ) );
77
78 if ( strstr( poName, "SIGHT FIGHTER ACTION USB" ) )
79 {
80 m_abWorkaround[m_iNumJoysticks] = true;
81 debug( "CJoystick::Init(): Infuriatingly stupid joystick detected.\n" );
82 }
83 ++m_iNumJoysticks;
84 }
85
86 if ( m_iNumJoysticks )
87 {
88 SDL_JoystickEventState( SDL_ENABLE );
89 }
90
91 return m_iNumJoysticks;
92 }
93
94
95
GetJoystickName(int a_iJoystickNumber)96 const char* CJoystick::GetJoystickName( int a_iJoystickNumber )
97 {
98 if ( a_iJoystickNumber >= m_iNumJoysticks
99 || a_iJoystickNumber < 0 )
100 {
101 return NULL;
102 }
103
104 return m_apcJoystickNames[a_iJoystickNumber];
105 }
106
107
108
TranslateEvent(const SDL_Event * a_poInEvent,SMortalEvent * a_poOutEvent)109 bool CJoystick::TranslateEvent( const SDL_Event* a_poInEvent, SMortalEvent* a_poOutEvent )
110 {
111 a_poOutEvent->m_enType = Me_NOTHING;
112
113 switch ( a_poInEvent->type )
114 {
115 case SDL_JOYAXISMOTION:
116 {
117 int iJoyNumber = a_poInEvent->jaxis.which;
118 int iAxisNumber = a_poInEvent->jaxis.axis;
119 int iValue = a_poInEvent->jaxis.value;
120
121 if ( iAxisNumber > 1 )
122 {
123 // Only translate axis 0 and 1.
124 return false;
125 }
126
127 if ( m_abWorkaround[iJoyNumber] )
128 {
129 iValue = AxisWorkaround( a_poInEvent->jaxis );
130 debug( "Translated %d to %d\n", a_poInEvent->jaxis.value, iValue );
131 }
132
133 // Try the new value into motion.
134 int& riOldValue = iAxisNumber ? m_aiVerticalAxis[iJoyNumber] : m_aiHorizontalAxis[iJoyNumber];
135
136 if ( -1 == riOldValue )
137 {
138 if ( iValue < -3200 )
139 {
140 return false;
141 }
142 riOldValue = 0;
143 a_poOutEvent->m_enType = Me_PLAYERKEYUP;
144 a_poOutEvent->m_iPlayer = iJoyNumber;
145 a_poOutEvent->m_iKey = iAxisNumber ? Mk_UP : Mk_LEFT;
146 return true;
147 }
148
149 if ( 0 == riOldValue )
150 {
151 if ( iValue < -6400 )
152 {
153 riOldValue = -1;
154 a_poOutEvent->m_enType = Me_PLAYERKEYDOWN;
155 a_poOutEvent->m_iPlayer = iJoyNumber;
156 a_poOutEvent->m_iKey = iAxisNumber ? Mk_UP : Mk_LEFT;
157 return true;
158 }
159 if ( iValue > 6400 )
160 {
161 riOldValue = 1;
162 a_poOutEvent->m_enType = Me_PLAYERKEYDOWN;
163 a_poOutEvent->m_iPlayer = iJoyNumber;
164 a_poOutEvent->m_iKey = iAxisNumber ? Mk_DOWN : Mk_RIGHT;
165 return true;
166 }
167 return false;
168 }
169 if ( 1 == riOldValue )
170 {
171 if ( iValue > 3200 )
172 {
173 return false;
174 }
175 riOldValue = 0;
176 a_poOutEvent->m_enType = Me_PLAYERKEYUP;
177 a_poOutEvent->m_iPlayer = iJoyNumber;
178 a_poOutEvent->m_iKey = iAxisNumber ? Mk_DOWN : Mk_RIGHT;
179 return true;
180 }
181
182 riOldValue = 0;
183 return false;
184 }
185
186 case SDL_JOYBUTTONDOWN:
187 case SDL_JOYBUTTONUP:
188 {
189 int iJoyNumber = a_poInEvent->jbutton.which;
190 int iButton = a_poInEvent->jbutton.button;
191 int iPressed = a_poInEvent->jbutton.state == SDL_PRESSED;
192
193 debug( "Button down: joy %d, button %d, state %d\n", iJoyNumber, iButton, iPressed );
194
195 if ( iButton > 4 )
196 {
197 if ( iButton == SDL_JoystickNumButtons(m_apoJoysticks[iJoyNumber]) - 1
198 && iPressed )
199 {
200 a_poOutEvent->m_enType = Me_MENU;
201 return true;
202 }
203 return false;
204 }
205
206 if ( iJoyNumber > 1 )
207 {
208 return false;
209 }
210
211 a_poOutEvent->m_enType = iPressed ? Me_PLAYERKEYDOWN : Me_PLAYERKEYUP;
212 a_poOutEvent->m_iPlayer = iJoyNumber;
213 a_poOutEvent->m_iKey = iButton + 4;
214
215 return true;
216 }
217
218 case SDL_JOYBALLMOTION:
219 if( a_poInEvent->jball.ball == 0 )
220 {
221 // Nothing for now.
222 }
223 break;
224
225 case SDL_JOYHATMOTION:
226 if ( a_poInEvent->jhat.hat & SDL_HAT_UP )
227 {
228 // Nothing for now.
229 }
230 if ( a_poInEvent->jhat.hat & SDL_HAT_LEFT )
231 {
232 // Nothing for now.
233 }
234 if ( a_poInEvent->jhat.hat & SDL_HAT_RIGHTDOWN )
235 {
236 // Nothing for now.
237 }
238 break;
239
240 } // end of switch statement
241
242 return false;
243 }
244
245
AxisWorkaround(const SDL_JoyAxisEvent & a_roEvent)246 int CJoystick::AxisWorkaround( const SDL_JoyAxisEvent& a_roEvent )
247 {
248 if ( 0 == a_roEvent.value ) return -32768;
249 if ( 127 == a_roEvent.value ) return 0;
250 if ( -1 == a_roEvent.value ) return 32768;
251
252 return 0;
253 }
254
255
256
257