1 //**************************************************************************
2 //**
3 //**    ##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**    ##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**     ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**     ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**      ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**       #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**    $Id: in_sdl.cpp 3483 2008-04-10 18:03:34Z dj_jl $
11 //**
12 //**    Copyright (C) 1999-2002 J306nis Legzdi267375
13 //**
14 //**    This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**    This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include <SDL.h>
29 #include "gamedefs.h"
30 
31 // MACROS ------------------------------------------------------------------
32 
33 #ifndef MAX_JOYSTICK_BUTTONS
34 #define MAX_JOYSTICK_BUTTONS 100
35 #endif
36 
37 // TYPES -------------------------------------------------------------------
38 
39 class VSdlInputDevice : public VInputDevice
40 {
41 public:
42 	VSdlInputDevice();
43 	~VSdlInputDevice();
44 
45 	void ReadInput();
46 
47 private:
48 	int				mouse;
49 
50 	int				mouse_oldx;
51 	int				mouse_oldy;
52 
53 	SDL_Joystick*	joystick;
54 	bool			joystick_started;
55 	int				joy_num_buttons;
56 	int				joy_x;
57 	int				joy_y;
58 	int				joy_newb[MAX_JOYSTICK_BUTTONS];
59 	int				joy_oldx;
60 	int				joy_oldy;
61 	int				joy_oldb[MAX_JOYSTICK_BUTTONS];
62 
63 	static const vuint8		sym2key[SDLK_LAST];
64 
65 	void StartupJoystick();
66 	void PostJoystick();
67 };
68 
69 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
70 
71 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
72 
73 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
74 
75 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
76 
77 // PUBLIC DATA DEFINITIONS -------------------------------------------------
78 
79 static VCvarI m_filter("m_filter", "1", CVAR_Archive);
80 
81 // PRIVATE DATA DEFINITIONS ------------------------------------------------
82 
83 // tested with SDL 1.2.2
84 const vuint8 VSdlInputDevice::sym2key[SDLK_LAST] =
85 {
86 	//0,
87 	0,
88 	//1,  2,  3,  4,  5,  6,  7,  8,            9,     10, 11, 12, 13,      14, 15, 16,
89 	0,  0,  0,  0,  0,  0,  0,  K_BACKSPACE,  K_TAB, 0, 0, 0, K_ENTER, 0, 0, 0,
90 	//17, 18, 19,      20, 21, 22, 23, 24, 25, 26, 27,       28, 29, 30, 31, 32,
91 	0, 0, K_PAUSE, 0, 0, 0, 0, 0, 0, 0, K_ESCAPE, 0, 0, 0, 0, ' ',
92 	//33, 34, 35, 36, 37, 38, 39,   40, 41, 42, 43, 44,  45,  46,  47,  48,
93 	0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, ',', '-', '.', '/', '0',
94 	//49,  50,  51,  52,  53,  54,  55,  56,  57,  58, 59,  60, 61,  62, 63, 64,
95 	'1', '2', '3', '4', '5', '6', '7', '8', '9', 0, ';', 0, '=', 0, 0, 0,
96 	//65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
97 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98 	//81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,  92, 93,  94, 95, 96,
99 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '[', '\\', ']', 0, 0, '`',
100 	//97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
101 	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
102 	//113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,      128,
103 	'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 0, 0, 0, 0, K_DELETE, 0,
104 	//129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
105 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
106 	//145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
107 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
108 	//161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
109 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
110 	//177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
111 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
112 	//193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
113 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
114 	//209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
115 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
116 	//225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
117 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
118 	//241,242,243,244,245,246,247,248,
119 	0,0,0,0,0,0,0,0,
120 	//249,250,251,252,253,254,255, 256,
121 	0,0,0,0,0,0,0, K_PAD0,
122 	//257,    258,    259,    260,    261,    262,    263,    264,
123 	K_PAD1, K_PAD2, K_PAD3, K_PAD4, K_PAD5, K_PAD6, K_PAD7, K_PAD8,
124 	//265,    266,      267,         268,           269,        270,       271,        272,
125 	K_PAD9, K_PADDOT, K_PADDIVIDE, K_PADMULTIPLE, K_PADMINUS, K_PADPLUS, K_PADENTER, '=',
126 	//273,       274,         275,          276,         277,      278,    279,   280,
127 	K_UPARROW, K_DOWNARROW, K_RIGHTARROW, K_LEFTARROW, K_INSERT, K_HOME, K_END, K_PAGEUP,
128 	//281,        282,  283,  284,  285,  286,  287,  288,
129 	K_PAGEDOWN, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6, K_F7,
130 	//289,  290,  291,   292,   293,   294, 295, 296, 297, 298, 299, 300,       301,        302,          303,      304,
131 	K_F8, K_F9, K_F10, K_F11, K_F12, 0,   0,   0,   0,   0,   0,   K_NUMLOCK, K_CAPSLOCK, K_SCROLLLOCK, K_RSHIFT, K_LSHIFT,
132 	//305,     306,     307,    308,    309, 310, 311,    312,    313, 314, 315, 316,         317, 318,     319,    320,
133 	K_RCTRL, K_LCTRL, K_RALT, K_LALT, 0,   0,   K_LWIN, K_RWIN, 0,   0,   0,   K_PRINTSCRN, 0,   K_PAUSE, K_MENU, 0,
134 	//321
135 	0
136 };
137 
138 // CODE --------------------------------------------------------------------
139 
140 //==========================================================================
141 //
142 //	VSdlInputDevice::VSdlInputDevice
143 //
144 //==========================================================================
145 
VSdlInputDevice()146 VSdlInputDevice::VSdlInputDevice()
147 : mouse(0)
148 , mouse_oldx(0)
149 , mouse_oldy(0)
150 , joystick(NULL)
151 , joystick_started(false)
152 , joy_num_buttons(0)
153 , joy_x(0)
154 , joy_y(0)
155 , joy_oldx(0)
156 , joy_oldy(0)
157 {
158 	guard(VSdlInputDevice::VSdlInputDevice);
159 	// always off
160 	SDL_ShowCursor(0);
161 	// mouse and keyboard are setup using SDL's video interface
162 	mouse = 1;
163 	if (GArgs.CheckParm("-nomouse"))
164 	{
165 		SDL_EventState(SDL_MOUSEMOTION,     SDL_IGNORE);
166 		SDL_EventState(SDL_MOUSEBUTTONDOWN, SDL_IGNORE);
167 		SDL_EventState(SDL_MOUSEBUTTONUP,   SDL_IGNORE);
168 		mouse = 0;
169 	}
170 	else
171 	{
172 		// ignore mouse motion events in any case...
173 		SDL_EventState(SDL_MOUSEMOTION,     SDL_IGNORE);
174 		mouse_oldx = ScreenWidth / 2;
175 		mouse_oldy = ScreenHeight / 2;
176 		SDL_WarpMouse(mouse_oldx, mouse_oldy);
177 	}
178 
179 	//	Initialise joystick
180 	StartupJoystick();
181 	unguard;
182 }
183 
184 //==========================================================================
185 //
186 //	VSdlInputDevice::~VSdlInputDevice
187 //
188 //==========================================================================
189 
~VSdlInputDevice()190 VSdlInputDevice::~VSdlInputDevice()
191 {
192 	guard(VSdlInputDevice::~VSdlInputDevice);
193 	// on
194 	SDL_ShowCursor(1);
195 	if (joystick_started)
196 	{
197 		SDL_JoystickClose(joystick);
198 		SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
199 	}
200 	unguard;
201 }
202 
203 //==========================================================================
204 //
205 //  VSdlInputDevice::ReadInput
206 //
207 //	Reads input from the input devices.
208 //
209 //==========================================================================
210 
ReadInput()211 void VSdlInputDevice::ReadInput()
212 {
213 	guard(VSdlInputDevice::ReadInput);
214 	SDL_Event ev;
215 	event_t vev;
216 	//int rel_x;
217 	//int rel_y;
218 	int mouse_x;
219 	int mouse_y;
220 	int normal_value;
221 
222 	SDL_PumpEvents();
223 	while (SDL_PollEvent(&ev))
224 	{
225 		switch (ev.type)
226 		{
227 		case SDL_KEYDOWN:
228 		case SDL_KEYUP:
229 			if (sym2key[ev.key.keysym.sym])
230 			{
231 				GInput->KeyEvent(sym2key[ev.key.keysym.sym],
232 					(ev.key.state == SDL_PRESSED) ? 1 : 0);
233 			}
234 			break;
235 #if 0
236 		case SDL_MOUSEMOTION:
237 			vev.type = ev_mouse;
238 			vev.data1 = 0;
239 			vev.data2 = ev.motion.xrel;
240 			vev.data3 = ev.motion.yrel;
241 			GInput->PostEvent(&vev);
242 			break;
243 #endif /* 0 */
244 		case SDL_MOUSEBUTTONDOWN:
245 		case SDL_MOUSEBUTTONUP:
246 			vev.type = (ev.button.state == SDL_PRESSED) ? ev_keydown : ev_keyup;
247 			if (ev.button.button == SDL_BUTTON_LEFT)
248 				vev.data1 = K_MOUSE1;
249 			else if (ev.button.button == SDL_BUTTON_RIGHT)
250 				vev.data1 = K_MOUSE2;
251 			else if (ev.button.button == SDL_BUTTON_MIDDLE)
252 				vev.data1 = K_MOUSE3;
253 			else if (ev.button.button == SDL_BUTTON_WHEELUP)
254 				vev.data1 = K_MWHEELUP;
255 			else if (ev.button.button == SDL_BUTTON_WHEELDOWN)
256 				vev.data1 = K_MWHEELDOWN;
257 			else
258 				break;
259 			vev.data2 = 0;
260 			vev.data3 = 0;
261 			GInput->PostEvent(&vev);
262 			break;
263 		case SDL_JOYAXISMOTION:
264 			normal_value = ev.jaxis.value * 127 / 32767;
265 			if (ev.jaxis.axis == 0)
266 				joy_x = normal_value;
267 			else if (ev.jaxis.axis == 1)
268 				joy_y = normal_value;
269 			break;
270 		case SDL_JOYBALLMOTION:
271 			break;
272 		case SDL_JOYHATMOTION:
273 			break;
274 		case SDL_JOYBUTTONDOWN:
275 			joy_newb[ev.jbutton.button] = 1;
276 			break;
277 		case SDL_JOYBUTTONUP:
278 			joy_newb[ev.jbutton.button] = 0;
279 			break;
280 		default:
281 			break;
282 		}
283 	}
284 
285 	//	Read mouse separately
286 	if (mouse)
287 	{
288 		SDL_GetMouseState(&mouse_x, &mouse_y);
289 		vev.type = ev_mouse;
290 		vev.data1 = 0;
291 		vev.data2 = mouse_x - ScreenWidth / 2;
292 		vev.data3 = ScreenHeight / 2 - mouse_y;
293 		GInput->PostEvent(&vev);
294 		SDL_WarpMouse(ScreenWidth / 2, ScreenHeight / 2);
295 #if 0
296 		SDL_GetRelativeMouseState(&rel_x, &rel_y);
297 		vev.type = ev_mouse;
298 		vev.data1 = 0;
299 		vev.data2 = rel_x;
300 		vev.data3 = rel_y;
301 		GInput->PostEvent(&vev);
302 #endif
303 	}
304 
305 	PostJoystick();
306 
307 	unguard;
308 }
309 
310 //**************************************************************************
311 //**
312 //**	JOYSTICK
313 //**
314 //**************************************************************************
315 
316 //==========================================================================
317 //
318 //	VSdlInputDevice::StartupJoystick
319 //
320 //	Initialises joystick
321 //
322 //==========================================================================
323 
StartupJoystick()324 void VSdlInputDevice::StartupJoystick()
325 {
326 	guard(VSdlInputDevice::StartupJoystick);
327 	if (GArgs.CheckParm("-nojoy"))
328 		return;
329 
330 	if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
331 	{
332 		GCon->Log(NAME_Init, "sdl init joystick failed.");
333 		return;
334 	}
335 //	else
336 //	{
337 //		SDL_JoystickEventState(SDL_IGNORE);
338 //		// we are on our own now...
339 //	}
340 	joystick = SDL_JoystickOpen(0);
341 	if (!joystick)
342 		return;
343 
344 	joy_num_buttons = SDL_JoystickNumButtons(joystick);
345 	joystick_started = true;
346 	memset(joy_oldb, 0, sizeof(joy_oldb));
347 	memset(joy_newb, 0, sizeof(joy_newb));
348 	unguard;
349 }
350 
351 //==========================================================================
352 //
353 //  VSdlInputDevice::PostJoystick
354 //
355 //==========================================================================
356 
PostJoystick()357 void VSdlInputDevice::PostJoystick()
358 {
359 	guard(VSdlInputDevice::PostJoystick);
360 	int		i;
361 	event_t event;
362 
363 	if (!joystick_started)
364 		return;
365 
366 	if ((joy_oldx != joy_x) || (joy_oldy != joy_y))
367 	{
368 		event.type = ev_joystick;
369 		event.data1 = 0;
370 		event.data2 = joy_x;
371 		event.data3 = joy_y;
372 		GInput->PostEvent(&event);
373 
374 		joy_oldx = joy_x;
375 		joy_oldy = joy_y;
376 	}
377 
378 	for (i = 0; i < joy_num_buttons; i++)
379 	{
380 		if (joy_newb[i] != joy_oldb[i])
381 		{
382 			GInput->KeyEvent(K_JOY1 + i, joy_newb[i]);
383 			joy_oldb[i] = joy_newb[i];
384 		}
385 	}
386 	unguard;
387 }
388 
389 //**************************************************************************
390 //**
391 //**    INPUT
392 //**
393 //**************************************************************************
394 
395 //==========================================================================
396 //
397 //  VInputDevice::CreateDevice
398 //
399 //==========================================================================
400 
CreateDevice()401 VInputDevice* VInputDevice::CreateDevice()
402 {
403 	return new VSdlInputDevice();
404 }
405