1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: in_alleg.cpp 3694 2008-06-15 00:09:53Z dj_jl $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
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 //**	Input modue for Allegro library. Used only in Linux (in Windows I
27 //**  don't use Allegro, in DOS keyboard and mouse are handled directly).
28 //**
29 //**************************************************************************
30 
31 // HEADER FILES ------------------------------------------------------------
32 
33 #include <allegro.h>
34 #include "gamedefs.h"
35 
36 // MACROS ------------------------------------------------------------------
37 
38 #define KBDQUESIZE			32
39 
40 // TYPES -------------------------------------------------------------------
41 
42 class VAllegroInputDevice : public VInputDevice
43 {
44 public:
45 	VAllegroInputDevice();
46 	~VAllegroInputDevice();
47 
48 	void ReadInput();
49 
50 private:
51 	bool				keyboard_started;
52 
53 	bool				mouse_started;
54 	int					old_mouse_x;
55 	int					old_mouse_y;
56 	int					old_mouse_z;
57 	int					old_z_delta;
58 	int 				lastbuttons;
59 
60 	bool				joystick_started;
61 	int					joy_oldx;
62 	int					joy_oldy;
63 	int					joy_oldb[MAX_JOYSTICK_BUTTONS];
64 
65 	static const vuint8	scantokey[KEY_MAX];
66 
67 	void StartupKeyboard();
68 	void ReadKeyboard();
69 	void ShutdownKeyboard();
70 
71 	void StartupMouse();
72 	void ReadMouse();
73 	void ShutdownMouse();
74 
75 	void StartupJoystick();
76 	void ReadJoystick();
77 	void ShutdownJoystick();
78 };
79 
80 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
81 
82 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
83 
84 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
85 
86 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
87 
88 // PUBLIC DATA DEFINITIONS -------------------------------------------------
89 
90 // PRIVATE DATA DEFINITIONS ------------------------------------------------
91 
92 static vuint8				keyboardque[KBDQUESIZE];
93 static int 					kbdtail = 0;
94 static int					kbdhead = 0;
95 
96 const vuint8				VAllegroInputDevice::scantokey[KEY_MAX] =
97 {
98 	0,
99 	'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
100 	'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
101 	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
102 	K_PAD0, K_PAD1, K_PAD2, K_PAD3, K_PAD4,
103 	K_PAD5, K_PAD6, K_PAD7, K_PAD8, K_PAD9,
104 	K_F1, K_F2, K_F3, K_F4, K_F5, K_F6,
105 	K_F7, K_F8, K_F9, K_F10, K_F11, K_F12,
106 	K_ESCAPE, '`', '-', '=', K_BACKSPACE, K_TAB,
107 	'[', ']', K_ENTER, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
108 	K_INSERT, K_DELETE, K_HOME, K_END, K_PAGEUP, K_PAGEDOWN,
109 	K_LEFTARROW, K_RIGHTARROW, K_UPARROW, K_DOWNARROW,
110 	K_PADDIVIDE, K_PADMULTIPLE, K_PADMINUS, K_PADPLUS,
111 	K_PADDOT, K_PADENTER, K_PRINTSCRN, K_PAUSE,
112 	K_ABNT_C1, K_YEN, K_KANA, K_CONVERT, K_NOCONVERT,
113 	K_AT, K_CIRCUMFLEX, K_COLON2, K_KANJI,
114 	K_LSHIFT, K_RSHIFT, K_LCTRL, K_RCTRL, K_LALT, K_RALT,
115 	K_LWIN, K_RWIN, K_MENU, K_SCROLLLOCK, K_NUMLOCK, K_CAPSLOCK
116 };
117 
118 static VCvarI				m_filter("m_filter", "1", CVAR_Archive);
119 
120 // CODE --------------------------------------------------------------------
121 
122 //==========================================================================
123 //
124 //	VAllegroInputDevice::VAllegroInputDevice
125 //
126 //==========================================================================
127 
VAllegroInputDevice()128 VAllegroInputDevice::VAllegroInputDevice()
129 : keyboard_started(false)
130 , mouse_started(false)
131 , old_mouse_x(0)
132 , old_mouse_y(0)
133 , old_mouse_z(0)
134 , old_z_delta(0)
135 , lastbuttons(0)
136 , joystick_started(false)
137 , joy_oldx(0)
138 , joy_oldy(0)
139 {
140 	guard(VAllegroInputDevice::VAllegroInputDevice);
141 	StartupKeyboard();
142 	StartupMouse();
143 	StartupJoystick();
144 	unguard;
145 }
146 
147 //==========================================================================
148 //
149 //	VAllegroInputDevice::~VAllegroInputDevice
150 //
151 //==========================================================================
152 
~VAllegroInputDevice()153 VAllegroInputDevice::~VAllegroInputDevice()
154 {
155 	guard(VAllegroInputDevice::~VAllegroInputDevice);
156 	ShutdownJoystick();
157 	ShutdownMouse();
158 	ShutdownKeyboard();
159 	unguard;
160 }
161 
162 //==========================================================================
163 //
164 //  VAllegroInputDevice::ReadInput
165 //
166 //	Reads input from the input devices.
167 //
168 //==========================================================================
169 
ReadInput()170 void VAllegroInputDevice::ReadInput()
171 {
172 	guard(VAllegroInputDevice::ReadInput);
173 	ReadKeyboard();
174 	ReadMouse();
175 	ReadJoystick();
176 	unguard;
177 }
178 
179 //**************************************************************************
180 //**
181 //**	KEYBOARD
182 //**
183 //**************************************************************************
184 
185 //==========================================================================
186 //
187 //  KeyboardHandler
188 //
189 // 	Keyboard interrupt handler
190 //
191 //==========================================================================
192 
KeyboardHandler(int key)193 static void KeyboardHandler(int key)
194 {
195 	keyboardque[kbdhead & (KBDQUESIZE - 1)] = key;
196 	kbdhead++;
197 }
END_OF_FUNCTION(KeyboardHandler)198 END_OF_FUNCTION(KeyboardHandler)
199 
200 //==========================================================================
201 //
202 //	VAllegroInputDevice::StartupKeyboard
203 //
204 //	Installs the keyboard handler.
205 //
206 //==========================================================================
207 
208 void VAllegroInputDevice::StartupKeyboard()
209 {
210 	guard(VAllegroInputDevice::StartupKeyboard);
211 	LOCK_FUNCTION((void*)KeyboardHandler);
212 	LOCK_DATA(keyboardque, sizeof(keyboardque));
213 	LOCK_VARIABLE(kbdhead);
214 
215 	if (install_keyboard())
216 	{
217 		Sys_Error("Failed to initialise keyboard");
218 	}
219 	keyboard_lowlevel_callback = KeyboardHandler;
220 	keyboard_started = true;
221 	unguard;
222 }
223 
224 //==========================================================================
225 //
226 //  VAllegroInputDevice::ReadKeyboard
227 //
228 //==========================================================================
229 
ReadKeyboard()230 void VAllegroInputDevice::ReadKeyboard()
231 {
232 	guard(VAllegroInputDevice::ReadKeyboard);
233 	unsigned char 	ch;
234 
235 	if (!keyboard_started)
236 		return;
237 
238 	while (kbdtail < kbdhead)
239 	{
240 		ch = keyboardque[kbdtail & (KBDQUESIZE - 1)];
241 		kbdtail++;
242 
243 		GInput->KeyEvent(scantokey[ch & 0x7f], !(ch & 0x80));
244 	}
245 	unguard;
246 }
247 
248 //==========================================================================
249 //
250 //  VAllegroInputDevice::ShutdownKeyboard
251 //
252 // 	Removes the keyboard handler.
253 //
254 //==========================================================================
255 
ShutdownKeyboard()256 void VAllegroInputDevice::ShutdownKeyboard()
257 {
258 	guard(VAllegroInputDevice::ShutdownKeyboard);
259 	if (keyboard_started)
260 	{
261 		remove_keyboard();
262 	}
263 	unguard;
264 }
265 
266 //**************************************************************************
267 //**
268 //**	MOUSE
269 //**
270 //**************************************************************************
271 
272 //==========================================================================
273 //
274 //	VAllegroInputDevice::StartupMouse
275 //
276 //	Initialises mouse
277 //
278 //==========================================================================
279 
StartupMouse()280 void VAllegroInputDevice::StartupMouse()
281 {
282 	guard(VAllegroInputDevice::StartupMouse);
283 	int		buts;
284 
285 	if (GArgs.CheckParm("-nomouse"))
286 		return;
287 
288 	buts = install_mouse();
289 	if (buts == -1)
290 	{
291 		return;
292 	}
293 	mouse_started = true;
294 	unguard;
295 }
296 
297 //==========================================================================
298 //
299 //	VAllegroInputDevice::ReadMouse
300 //
301 // 	Reads mouse.
302 //
303 //==========================================================================
304 
ReadMouse()305 void VAllegroInputDevice::ReadMouse()
306 {
307 	guard(VAllegroInputDevice::ReadMouse);
308 	int			i;
309 	event_t 	event;
310 	int 		xmickeys;
311 	int			ymickeys;
312 	int			mouse_x;
313 	int			mouse_y;
314 	int			buttons;
315 
316 	if (!mouse_started)
317 		return;
318 
319 	poll_mouse();
320 	get_mouse_mickeys(&xmickeys, &ymickeys);
321 	int Wheel = mouse_z;
322 	buttons = mouse_b;
323 
324 	if (m_filter == 2)
325 	{
326 		mouse_x = (xmickeys + old_mouse_x) / 2;
327 		mouse_y = (ymickeys + old_mouse_y) / 2;
328 		old_mouse_x = mouse_x;
329 		old_mouse_y = mouse_y;
330 	}
331 	else if (m_filter == 1)
332 	{
333 		mouse_x = (xmickeys + old_mouse_x) / 2;
334 		mouse_y = (ymickeys + old_mouse_y) / 2;
335 		old_mouse_x = xmickeys;
336 		old_mouse_y = ymickeys;
337 	}
338 	else
339 	{
340 		mouse_x = xmickeys;
341 		mouse_y = ymickeys;
342 		old_mouse_x = 0;
343 		old_mouse_y = 0;
344 	}
345 
346 	if (mouse_x || mouse_y)
347 	{
348 		event.type  = ev_mouse;
349 		event.data1 = 0;
350 		event.data2 = mouse_x;
351 		event.data3 = -mouse_y;
352 
353 		GInput->PostEvent(&event);
354 	}
355 	for (i = 0; i < 3; i++)
356 	{
357 		if ((buttons ^ lastbuttons) & (1 << i))
358 		{
359 			GInput->KeyEvent(K_MOUSE1 + i, buttons & (1 << i));
360 		}
361 	}
362 	lastbuttons = buttons;
363 
364 	//	Handle mouse wheel.
365 	int ZDelta = Wheel - old_mouse_z;
366 	if (ZDelta > 0 || old_mouse_z > 0)
367 	{
368 		GInput->KeyEvent(K_MWHEELUP, ZDelta > 0);
369 	}
370 	if (ZDelta < 0 || old_mouse_z < 0)
371 	{
372 		GInput->KeyEvent(K_MWHEELDOWN, ZDelta < 0);
373 	}
374 	old_mouse_z = Wheel;
375 	old_z_delta = ZDelta;
376 	unguard;
377 }
378 
379 //==========================================================================
380 //
381 //	VAllegroInputDevice::ShutdownMouse
382 //
383 //==========================================================================
384 
ShutdownMouse()385 void VAllegroInputDevice::ShutdownMouse()
386 {
387 	guard(VAllegroInputDevice::ShutdownMouse);
388 	if (!mouse_started)
389 		return;
390 	remove_mouse();
391 	unguard;
392 }
393 
394 //**************************************************************************
395 //**
396 //**	JOYSTICK
397 //**
398 //**************************************************************************
399 
400 //==========================================================================
401 //
402 //	VAllegroInputDevice::StartupJoystick
403 //
404 //	Initialises joystick
405 //
406 //==========================================================================
407 
StartupJoystick()408 void VAllegroInputDevice::StartupJoystick()
409 {
410 	guard(VAllegroInputDevice::StartupJoystick);
411 	if (GArgs.CheckParm("-nojoy"))
412 		return;
413 
414 	//	Detect the joystick type
415 	if (install_joystick(JOY_TYPE_AUTODETECT))
416 	{
417 		Sys_Error("Error initialising joystick\n%s\n", allegro_error);
418 	}
419 
420 	//	Make sure that we really do have a joystick
421 	if (!num_joysticks)
422 	{
423 		return;
424 	}
425 
426 	//	When initialising joystick, it must be centred, so we have to remove
427 	// it, give a message to centre joystick, wait for keypress and then
428 	// reinitialise it.
429 	if (joy[0].flags & JOYFLAG_CALIBRATE)
430 	{
431 		remove_joystick();
432 
433 		printf("CENTRE the joystick and press a key:\n");
434 		GInput->ReadKey();
435 
436 		// Initialise the joystick driver
437 		if (install_joystick(JOY_TYPE_AUTODETECT))
438 		{
439 			Sys_Error("Error initialising joystick\n%s\n", allegro_error);
440 		}
441 	}
442 
443 	//	Calibrate joystick
444 	while (joy[0].flags & JOYFLAG_CALIBRATE)
445 	{
446 		printf("%s and press a key:\n", calibrate_joystick_name(0));
447 		GInput->ReadKey();
448 
449 		if (calibrate_joystick(0))
450 		{
451 			Sys_Error("Error calibrating joystick!\n");
452 		}
453 	}
454 
455 	joystick_started = true;
456 	memset(joy_oldb, 0, sizeof(joy_oldb));
457 	unguard;
458 }
459 
460 //==========================================================================
461 //
462 //	VAllegroInputDevice::ReadJoystick
463 //
464 //==========================================================================
465 
ReadJoystick()466 void VAllegroInputDevice::ReadJoystick()
467 {
468 	guard(VAllegroInputDevice::ReadJoystick);
469 	int			i;
470 	event_t		event;
471 
472 	if (!joystick_started)
473 		return;
474 
475 	poll_joystick();
476 
477 	if ((joy_oldx != joy_x) || (joy_oldy != joy_y))
478 	{
479 		event.type = ev_joystick;
480 		event.data1 = 0;
481 		event.data2 = (abs(joy_x) < 4)? 0 : joy_x;
482 		event.data3 = (abs(joy_y) < 4)? 0 : joy_y;
483 		GInput->PostEvent(&event);
484 
485 		joy_oldx = joy_x;
486 		joy_oldy = joy_y;
487 	}
488 	for (i = 0; i < joy[0].num_buttons; i++)
489 	{
490 		if (joy[0].button[i].b != joy_oldb[i])
491 		{
492 			GInput->KeyEvent(K_JOY1 + i, joy[0].button[i].b);
493 			joy_oldb[i] = joy[0].button[i].b;
494 		}
495 	}
496 	unguard;
497 }
498 
499 //==========================================================================
500 //
501 //	VAllegroInputDevice::ShutdownJoystick
502 //
503 //==========================================================================
504 
ShutdownJoystick()505 void VAllegroInputDevice::ShutdownJoystick()
506 {
507 	guard(VAllegroInputDevice::ShutdownJoystick);
508 	if (joystick_started)
509 	{
510 		remove_joystick();
511 	}
512 	unguard;
513 }
514 
515 //==========================================================================
516 //
517 //  VInputDevice::CreateDevice
518 //
519 //==========================================================================
520 
CreateDevice()521 VInputDevice* VInputDevice::CreateDevice()
522 {
523 	return new VAllegroInputDevice();
524 }
525