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