Subversion Repositories Kolibri OS

Rev

Rev 8557 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8557 maxcodehac 1
//
2
//	ID Engine
3
//	ID_IN.c - Input Manager
4
//	v1.0d1
5
//	By Jason Blochowiak
6
//
7
 
8
//
9
//	This module handles dealing with the various input devices
10
//
11
//	Depends on: Memory Mgr (for demo recording), Sound Mgr (for timing stuff),
12
//				User Mgr (for command line parms)
13
//
14
//	Globals:
15
//		LastScan - The keyboard scan code of the last key pressed
16
//		LastASCII - The ASCII value of the last key pressed
17
//	DEBUG - there are more globals
18
//
19
 
20
#include "wl_def.h"
21
 
22
 
23
/*
24
=============================================================================
25
 
26
					GLOBAL VARIABLES
27
 
28
=============================================================================
29
*/
30
 
31
 
32
//
33
// configuration variables
34
//
35
boolean MousePresent;
36
boolean forcegrabmouse;
37
 
38
 
39
// 	Global variables
40
volatile boolean    Keyboard[SDLK_LAST];
41
volatile boolean	Paused;
42
volatile char		LastASCII;
43
volatile ScanCode	LastScan;
44
 
45
//KeyboardDef	KbdDefs = {0x1d,0x38,0x47,0x48,0x49,0x4b,0x4d,0x4f,0x50,0x51};
46
static KeyboardDef KbdDefs = {
47
    sc_Control,             // button0
48
    sc_Alt,                 // button1
49
    sc_Home,                // upleft
50
    sc_UpArrow,             // up
51
    sc_PgUp,                // upright
52
    sc_LeftArrow,           // left
53
    sc_RightArrow,          // right
54
    sc_End,                 // downleft
55
    sc_DownArrow,           // down
56
    sc_PgDn                 // downright
57
};
58
 
59
static SDL_Joystick *Joystick;
60
int JoyNumButtons;
61
static int JoyNumHats;
62
 
63
static bool GrabInput = false;
64
static bool NeedRestore = false;
65
 
66
/*
67
=============================================================================
68
 
69
					LOCAL VARIABLES
70
 
71
=============================================================================
72
*/
73
byte        ASCIINames[] =		// Unshifted ASCII for scan codes       // TODO: keypad
74
{
75
//	 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
76
 
77
 
78
	' ',0  ,0  ,0  ,0  ,0  ,0  ,39 ,0  ,0  ,'*','+',',','-','.','/',	// 2
79
	'0','1','2','3','4','5','6','7','8','9',0  ,';',0  ,'=',0  ,0  ,	// 3
80
	'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',	// 4
81
	'p','q','r','s','t','u','v','w','x','y','z','[',92 ,']',0  ,0  ,	// 5
82
 
83
 
84
};
85
byte ShiftNames[] =		// Shifted ASCII for scan codes
86
{
87
//	 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
88
 
89
 
90
	' ',0  ,0  ,0  ,0  ,0  ,0  ,34 ,0  ,0  ,'*','+','<','_','>','?',	// 2
91
	')','!','@','#','$','%','^','&','*','(',0  ,':',0  ,'+',0  ,0  ,	// 3
92
	'~','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',	// 4
93
	'P','Q','R','S','T','U','V','W','X','Y','Z','{','|','}',0  ,0  ,	// 5
94
 
95
 
96
};
97
byte SpecialNames[] =	// ASCII for 0xe0 prefixed codes
98
{
99
//	 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
100
 
101
 
102
 
103
 
104
 
105
 
106
 
107
 
108
};
109
 
110
 
111
static	boolean		IN_Started;
112
 
113
static	Direction	DirTable[] =		// Quick lookup for total direction
114
{
115
    dir_NorthWest,	dir_North,	dir_NorthEast,
116
    dir_West,		dir_None,	dir_East,
117
    dir_SouthWest,	dir_South,	dir_SouthEast
118
};
119
 
120
 
121
///////////////////////////////////////////////////////////////////////////
122
//
123
//	INL_GetMouseButtons() - Gets the status of the mouse buttons from the
124
//		mouse driver
125
//
126
///////////////////////////////////////////////////////////////////////////
127
static int
128
INL_GetMouseButtons(void)
129
{
130
    int buttons = SDL_GetMouseState(NULL, NULL);
131
    int middlePressed = buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE);
132
    int rightPressed = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
133
    buttons &= ~(SDL_BUTTON(SDL_BUTTON_MIDDLE) | SDL_BUTTON(SDL_BUTTON_RIGHT));
134
    if(middlePressed) buttons |= 1 << 2;
135
    if(rightPressed) buttons |= 1 << 1;
136
 
137
    return buttons;
138
}
139
 
140
///////////////////////////////////////////////////////////////////////////
141
//
142
//	IN_GetJoyDelta() - Returns the relative movement of the specified
143
//		joystick (from +/-127)
144
//
145
///////////////////////////////////////////////////////////////////////////
146
void IN_GetJoyDelta(int *dx,int *dy)
147
{
148
    if(!Joystick)
149
    {
150
        *dx = *dy = 0;
151
        return;
152
    }
153
 
154
    SDL_JoystickUpdate();
155
#ifdef _arch_dreamcast
156
    int x = 0;
157
    int y = 0;
158
#else
159
    int x = SDL_JoystickGetAxis(Joystick, 0) >> 8;
160
    int y = SDL_JoystickGetAxis(Joystick, 1) >> 8;
161
#endif
162
 
163
    if(param_joystickhat != -1)
164
    {
165
        uint8_t hatState = SDL_JoystickGetHat(Joystick, param_joystickhat);
166
        if(hatState & SDL_HAT_RIGHT)
167
            x += 127;
168
        else if(hatState & SDL_HAT_LEFT)
169
            x -= 127;
170
        if(hatState & SDL_HAT_DOWN)
171
            y += 127;
172
        else if(hatState & SDL_HAT_UP)
173
            y -= 127;
174
 
175
        if(x < -128) x = -128;
176
        else if(x > 127) x = 127;
177
 
178
        if(y < -128) y = -128;
179
        else if(y > 127) y = 127;
180
    }
181
 
182
    *dx = x;
183
    *dy = y;
184
}
185
 
186
///////////////////////////////////////////////////////////////////////////
187
//
188
//	IN_GetJoyFineDelta() - Returns the relative movement of the specified
189
//		joystick without dividing the results by 256 (from +/-127)
190
//
191
///////////////////////////////////////////////////////////////////////////
192
void IN_GetJoyFineDelta(int *dx, int *dy)
193
{
194
    if(!Joystick)
195
    {
196
        *dx = 0;
197
        *dy = 0;
198
        return;
199
    }
200
 
201
    SDL_JoystickUpdate();
202
    int x = SDL_JoystickGetAxis(Joystick, 0);
203
    int y = SDL_JoystickGetAxis(Joystick, 1);
204
 
205
    if(x < -128) x = -128;
206
    else if(x > 127) x = 127;
207
 
208
    if(y < -128) y = -128;
209
    else if(y > 127) y = 127;
210
 
211
    *dx = x;
212
    *dy = y;
213
}
214
 
215
/*
216
===================
217
=
218
= IN_JoyButtons
219
=
220
===================
221
*/
222
 
223
int IN_JoyButtons()
224
{
225
    if(!Joystick) return 0;
226
 
227
    SDL_JoystickUpdate();
228
 
229
    int res = 0;
230
    for(int i = 0; i < JoyNumButtons && i < 32; i++)
231
        res |= SDL_JoystickGetButton(Joystick, i) << i;
232
    return res;
233
}
234
 
235
boolean IN_JoyPresent()
236
{
237
    return Joystick != NULL;
238
}
239
 
240
static void processEvent(SDL_Event *event)
241
{
242
    switch (event->type)
243
    {
244
        // exit if the window is closed
245
        case SDL_QUIT:
246
            Quit(NULL);
247
 
248
        // check for keypresses
249
        case SDL_KEYDOWN:
250
        {
251
            if(event->key.keysym.sym==SDLK_SCROLLOCK || event->key.keysym.sym==SDLK_F12)
252
            {
253
                GrabInput = !GrabInput;
254
                SDL_WM_GrabInput(GrabInput ? SDL_GRAB_ON : SDL_GRAB_OFF);
255
                return;
256
            }
257
 
258
            LastScan = event->key.keysym.sym;
259
            SDLMod mod = SDL_GetModState();
260
            if(Keyboard[sc_Alt])
261
            {
262
                if(LastScan==SDLK_F4)
263
                    Quit(NULL);
264
            }
265
 
266
            if(LastScan == SDLK_KP_ENTER) LastScan = SDLK_RETURN;
267
            else if(LastScan == SDLK_RSHIFT) LastScan = SDLK_LSHIFT;
268
            else if(LastScan == SDLK_RALT) LastScan = SDLK_LALT;
269
            else if(LastScan == SDLK_RCTRL) LastScan = SDLK_LCTRL;
270
            else
271
            {
272
                if((mod & KMOD_NUM) == 0)
273
                {
274
                    switch(LastScan)
275
                    {
276
                        case SDLK_KP2: LastScan = SDLK_DOWN; break;
277
                        case SDLK_KP4: LastScan = SDLK_LEFT; break;
278
                        case SDLK_KP6: LastScan = SDLK_RIGHT; break;
279
                        case SDLK_KP8: LastScan = SDLK_UP; break;
280
                    }
281
                }
282
            }
283
 
284
            int sym = LastScan;
285
            if(sym >= 'a' && sym <= 'z')
286
                sym -= 32;  // convert to uppercase
287
 
288
            if(mod & (KMOD_SHIFT | KMOD_CAPS))
289
            {
290
                if(sym < lengthof(ShiftNames) && ShiftNames[sym])
291
                    LastASCII = ShiftNames[sym];
292
            }
293
            else
294
            {
295
                if(sym < lengthof(ASCIINames) && ASCIINames[sym])
296
                    LastASCII = ASCIINames[sym];
297
            }
298
            if(LastScan
299
                Keyboard[LastScan] = 1;
300
            if(LastScan == SDLK_PAUSE)
301
                Paused = true;
302
            break;
303
		}
304
 
305
        case SDL_KEYUP:
306
        {
307
            int key = event->key.keysym.sym;
308
            if(key == SDLK_KP_ENTER) key = SDLK_RETURN;
309
            else if(key == SDLK_RSHIFT) key = SDLK_LSHIFT;
310
            else if(key == SDLK_RALT) key = SDLK_LALT;
311
            else if(key == SDLK_RCTRL) key = SDLK_LCTRL;
312
            else
313
            {
314
                if((SDL_GetModState() & KMOD_NUM) == 0)
315
                {
316
                    switch(key)
317
                    {
318
                        case SDLK_KP2: key = SDLK_DOWN; break;
319
                        case SDLK_KP4: key = SDLK_LEFT; break;
320
                        case SDLK_KP6: key = SDLK_RIGHT; break;
321
                        case SDLK_KP8: key = SDLK_UP; break;
322
                    }
323
                }
324
            }
325
 
326
            if(key
327
                Keyboard[key] = 0;
328
            break;
329
        }
330
 
331
        case SDL_ACTIVEEVENT:
332
        {
333
            if(fullscreen && (event->active.state & SDL_APPACTIVE) != 0)
334
            {
335
                if(event->active.gain)
336
                {
337
                    if(NeedRestore)
338
                    {
339
                        FreeLatchMem();
340
                        LoadLatchMem();
341
                    }
342
 
343
                    NeedRestore = false;
344
                }
345
                else NeedRestore = true;
346
            }
347
        }
348
 
349
#if defined(GP2X)
350
        case SDL_JOYBUTTONDOWN:
351
            GP2X_ButtonDown(event->jbutton.button);
352
            break;
353
 
354
        case SDL_JOYBUTTONUP:
355
            GP2X_ButtonUp(event->jbutton.button);
356
            break;
357
#endif
358
    }
359
}
360
 
361
void IN_WaitAndProcessEvents()
362
{
363
    SDL_Event event;
364
    if(!SDL_WaitEvent(&event)) return;
365
    do
366
    {
367
        processEvent(&event);
368
    }
369
    while(SDL_PollEvent(&event));
370
}
371
 
372
void IN_ProcessEvents()
373
{
374
    SDL_Event event;
375
 
376
    while (SDL_PollEvent(&event))
377
    {
378
        processEvent(&event);
379
    }
380
}
381
 
382
 
383
///////////////////////////////////////////////////////////////////////////
384
//
385
//	IN_Startup() - Starts up the Input Mgr
386
//
387
///////////////////////////////////////////////////////////////////////////
388
void
389
IN_Startup(void)
390
{
391
	if (IN_Started)
392
		return;
393
 
394
    IN_ClearKeysDown();
395
 
396
    if(param_joystickindex >= 0 && param_joystickindex < SDL_NumJoysticks())
397
    {
398
        Joystick = SDL_JoystickOpen(param_joystickindex);
399
        if(Joystick)
400
        {
401
            JoyNumButtons = SDL_JoystickNumButtons(Joystick);
402
            if(JoyNumButtons > 32) JoyNumButtons = 32;      // only up to 32 buttons are supported
403
            JoyNumHats = SDL_JoystickNumHats(Joystick);
404
            if(param_joystickhat < -1 || param_joystickhat >= JoyNumHats)
405
                Quit("The joystickhat param must be between 0 and %i!", JoyNumHats - 1);
406
        }
407
    }
408
 
409
    SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
410
 
411
    if(fullscreen || forcegrabmouse)
412
    {
413
        GrabInput = true;
414
        SDL_WM_GrabInput(SDL_GRAB_ON);
415
    }
416
 
417
    // I didn't find a way to ask libSDL whether a mouse is present, yet...
418
#if defined(GP2X)
419
    MousePresent = false;
420
#elif defined(_arch_dreamcast)
421
    MousePresent = DC_MousePresent();
422
#else
423
    MousePresent = true;
424
#endif
425
 
426
    IN_Started = true;
427
}
428
 
429
///////////////////////////////////////////////////////////////////////////
430
//
431
//	IN_Shutdown() - Shuts down the Input Mgr
432
//
433
///////////////////////////////////////////////////////////////////////////
434
void
435
IN_Shutdown(void)
436
{
437
	if (!IN_Started)
438
		return;
439
 
440
    if(Joystick)
441
        SDL_JoystickClose(Joystick);
442
 
443
	IN_Started = false;
444
}
445
 
446
///////////////////////////////////////////////////////////////////////////
447
//
448
//	IN_ClearKeysDown() - Clears the keyboard array
449
//
450
///////////////////////////////////////////////////////////////////////////
451
void
452
IN_ClearKeysDown(void)
453
{
454
	LastScan = sc_None;
455
	LastASCII = key_None;
456
	memset ((void *) Keyboard,0,sizeof(Keyboard));
457
}
458
 
459
 
460
///////////////////////////////////////////////////////////////////////////
461
//
462
//	IN_ReadControl() - Reads the device associated with the specified
463
//		player and fills in the control info struct
464
//
465
///////////////////////////////////////////////////////////////////////////
466
void
467
IN_ReadControl(int player,ControlInfo *info)
468
{
469
	word		buttons;
470
	int			dx,dy;
471
	Motion		mx,my;
472
 
473
	dx = dy = 0;
474
	mx = my = motion_None;
475
	buttons = 0;
476
 
477
	IN_ProcessEvents();
478
 
479
    if (Keyboard[KbdDefs.upleft])
480
        mx = motion_Left,my = motion_Up;
481
    else if (Keyboard[KbdDefs.upright])
482
        mx = motion_Right,my = motion_Up;
483
    else if (Keyboard[KbdDefs.downleft])
484
        mx = motion_Left,my = motion_Down;
485
    else if (Keyboard[KbdDefs.downright])
486
        mx = motion_Right,my = motion_Down;
487
 
488
    if (Keyboard[KbdDefs.up])
489
        my = motion_Up;
490
    else if (Keyboard[KbdDefs.down])
491
        my = motion_Down;
492
 
493
    if (Keyboard[KbdDefs.left])
494
        mx = motion_Left;
495
    else if (Keyboard[KbdDefs.right])
496
        mx = motion_Right;
497
 
498
    if (Keyboard[KbdDefs.button0])
499
        buttons += 1 << 0;
500
    if (Keyboard[KbdDefs.button1])
501
        buttons += 1 << 1;
502
 
503
	dx = mx * 127;
504
	dy = my * 127;
505
 
506
	info->x = dx;
507
	info->xaxis = mx;
508
	info->y = dy;
509
	info->yaxis = my;
510
	info->button0 = (buttons & (1 << 0)) != 0;
511
	info->button1 = (buttons & (1 << 1)) != 0;
512
	info->button2 = (buttons & (1 << 2)) != 0;
513
	info->button3 = (buttons & (1 << 3)) != 0;
514
	info->dir = DirTable[((my + 1) * 3) + (mx + 1)];
515
}
516
 
517
///////////////////////////////////////////////////////////////////////////
518
//
519
//	IN_WaitForKey() - Waits for a scan code, then clears LastScan and
520
//		returns the scan code
521
//
522
///////////////////////////////////////////////////////////////////////////
523
ScanCode
524
IN_WaitForKey(void)
525
{
526
	ScanCode	result;
527
 
528
	while ((result = LastScan)==0)
529
		IN_WaitAndProcessEvents();
530
	LastScan = 0;
531
	return(result);
532
}
533
 
534
///////////////////////////////////////////////////////////////////////////
535
//
536
//	IN_WaitForASCII() - Waits for an ASCII char, then clears LastASCII and
537
//		returns the ASCII value
538
//
539
///////////////////////////////////////////////////////////////////////////
540
char
541
IN_WaitForASCII(void)
542
{
543
	char		result;
544
 
545
	while ((result = LastASCII)==0)
546
		IN_WaitAndProcessEvents();
547
	LastASCII = '\0';
548
	return(result);
549
}
550
 
551
///////////////////////////////////////////////////////////////////////////
552
//
553
//	IN_Ack() - waits for a button or key press.  If a button is down, upon
554
// calling, it must be released for it to be recognized
555
//
556
///////////////////////////////////////////////////////////////////////////
557
 
558
boolean	btnstate[NUMBUTTONS];
559
 
560
void IN_StartAck(void)
561
{
562
    IN_ProcessEvents();
563
//
564
// get initial state of everything
565
//
566
	IN_ClearKeysDown();
567
	memset(btnstate, 0, sizeof(btnstate));
568
 
569
	int buttons = IN_JoyButtons() << 4;
570
 
571
	if(MousePresent)
572
		buttons |= IN_MouseButtons();
573
 
574
	for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1)
575
		if(buttons & 1)
576
			btnstate[i] = true;
577
}
578
 
579
 
580
boolean IN_CheckAck (void)
581
{
582
    IN_ProcessEvents();
583
//
584
// see if something has been pressed
585
//
586
	if(LastScan)
587
		return true;
588
 
589
	int buttons = IN_JoyButtons() << 4;
590
 
591
	if(MousePresent)
592
		buttons |= IN_MouseButtons();
593
 
594
	for(int i = 0; i < NUMBUTTONS; i++, buttons >>= 1)
595
	{
596
		if(buttons & 1)
597
		{
598
			if(!btnstate[i])
599
            {
600
                // Wait until button has been released
601
                do
602
                {
603
                    IN_WaitAndProcessEvents();
604
                    buttons = IN_JoyButtons() << 4;
605
 
606
                    if(MousePresent)
607
                        buttons |= IN_MouseButtons();
608
                }
609
                while(buttons & (1 << i));
610
 
611
				return true;
612
            }
613
		}
614
		else
615
			btnstate[i] = false;
616
	}
617
 
618
	return false;
619
}
620
 
621
 
622
void IN_Ack (void)
623
{
624
	IN_StartAck ();
625
 
626
    do
627
    {
628
        IN_WaitAndProcessEvents();
629
    }
630
	while(!IN_CheckAck ());
631
}
632
 
633
 
634
///////////////////////////////////////////////////////////////////////////
635
//
636
//	IN_UserInput() - Waits for the specified delay time (in ticks) or the
637
//		user pressing a key or a mouse button. If the clear flag is set, it
638
//		then either clears the key or waits for the user to let the mouse
639
//		button up.
640
//
641
///////////////////////////////////////////////////////////////////////////
642
boolean IN_UserInput(longword delay)
643
{
644
	longword	lasttime;
645
 
646
	lasttime = GetTimeCount();
647
	IN_StartAck ();
648
	do
649
	{
650
        IN_ProcessEvents();
651
		if (IN_CheckAck())
652
			return true;
9097 turbocat 653
        uSDL_Delay(5);
8557 maxcodehac 654
	} while (GetTimeCount() - lasttime < delay);
655
	return(false);
656
}
657
 
658
//===========================================================================
659
 
660
/*
661
===================
662
=
663
= IN_MouseButtons
664
=
665
===================
666
*/
667
int IN_MouseButtons (void)
668
{
669
	if (MousePresent)
670
		return INL_GetMouseButtons();
671
	else
672
		return 0;
673
}
674
 
675
bool IN_IsInputGrabbed()
676
{
677
    return GrabInput;
678
}
679
 
680
void IN_CenterMouse()
681
{
682
    SDL_WarpMouse(screenWidth / 2, screenHeight / 2);
683
}