view src/win32/DirectInput.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 //#define USE_GETASYNCKEYSTATE_FOR_KEYBOARD
3 #include "stdafx.h"
5 #define DIRECTINPUT_VERSION 0x0500
6 #include "dinput.h"
8 #include "resource.h"
9 #include "Input.h"
10 #include "Reg.h"
11 #include "WinResUtil.h"
13 // master keyboard translation table
14 static const struct {
15 int dik;
16 int vk;
17 int ascii;
18 } win_key_trans_table[] = {
19 // dinput key virtual key ascii
20 { DIK_ESCAPE, VK_ESCAPE, 27 },
21 { DIK_1, '1', '1' },
22 { DIK_2, '2', '2' },
23 { DIK_3, '3', '3' },
24 { DIK_4, '4', '4' },
25 { DIK_5, '5', '5' },
26 { DIK_6, '6', '6' },
27 { DIK_7, '7', '7' },
28 { DIK_8, '8', '8' },
29 { DIK_9, '9', '9' },
30 { DIK_0, '0', '0' },
31 { DIK_MINUS, VK_OEM_MINUS, '-' },
32 { DIK_EQUALS, VK_OEM_PLUS, '=' },
33 { DIK_BACK, VK_BACK, 8 },
34 { DIK_TAB, VK_TAB, 9 },
35 { DIK_Q, 'Q', 'Q' },
36 { DIK_W, 'W', 'W' },
37 { DIK_E, 'E', 'E' },
38 { DIK_R, 'R', 'R' },
39 { DIK_T, 'T', 'T' },
40 { DIK_Y, 'Y', 'Y' },
41 { DIK_U, 'U', 'U' },
42 { DIK_I, 'I', 'I' },
43 { DIK_O, 'O', 'O' },
44 { DIK_P, 'P', 'P' },
45 { DIK_LBRACKET, VK_OEM_4, '[' },
46 { DIK_RBRACKET, VK_OEM_6, ']' },
47 { DIK_RETURN, VK_RETURN, 13 },
48 { DIK_LCONTROL, VK_LCONTROL, 0 },
49 { DIK_A, 'A', 'A' },
50 { DIK_S, 'S', 'S' },
51 { DIK_D, 'D', 'D' },
52 { DIK_F, 'F', 'F' },
53 { DIK_G, 'G', 'G' },
54 { DIK_H, 'H', 'H' },
55 { DIK_J, 'J', 'J' },
56 { DIK_K, 'K', 'K' },
57 { DIK_L, 'L', 'L' },
58 { DIK_SEMICOLON, VK_OEM_1, ';' },
59 { DIK_APOSTROPHE, VK_OEM_7, '\'' },
60 { DIK_GRAVE, VK_OEM_3, '`' },
61 { DIK_LSHIFT, VK_LSHIFT, 0 },
62 { DIK_BACKSLASH, VK_OEM_5, '\\' },
63 { DIK_Z, 'Z', 'Z' },
64 { DIK_X, 'X', 'X' },
65 { DIK_C, 'C', 'C' },
66 { DIK_V, 'V', 'V' },
67 { DIK_B, 'B', 'B' },
68 { DIK_N, 'N', 'N' },
69 { DIK_M, 'M', 'M' },
70 { DIK_COMMA, VK_OEM_COMMA, ',' },
71 { DIK_PERIOD, VK_OEM_PERIOD, '.' },
72 { DIK_SLASH, VK_OEM_2, '/' },
73 { DIK_RSHIFT, VK_RSHIFT, 0 },
74 { DIK_MULTIPLY, VK_MULTIPLY, '*' },
75 { DIK_LMENU, VK_LMENU, 0 },
76 { DIK_SPACE, VK_SPACE, ' ' },
77 { DIK_CAPITAL, VK_CAPITAL, 0 },
78 { DIK_F1, VK_F1, 0 },
79 { DIK_F2, VK_F2, 0 },
80 { DIK_F3, VK_F3, 0 },
81 { DIK_F4, VK_F4, 0 },
82 { DIK_F5, VK_F5, 0 },
83 { DIK_F6, VK_F6, 0 },
84 { DIK_F7, VK_F7, 0 },
85 { DIK_F8, VK_F8, 0 },
86 { DIK_F9, VK_F9, 0 },
87 { DIK_F10, VK_F10, 0 },
88 { DIK_NUMLOCK, VK_NUMLOCK, 0 },
89 { DIK_SCROLL, VK_SCROLL, 0 },
90 { DIK_NUMPAD7, VK_NUMPAD7, 0 },
91 { DIK_NUMPAD8, VK_NUMPAD8, 0 },
92 { DIK_NUMPAD9, VK_NUMPAD9, 0 },
93 { DIK_SUBTRACT, VK_SUBTRACT, 0 },
94 { DIK_NUMPAD4, VK_NUMPAD4, 0 },
95 { DIK_NUMPAD5, VK_NUMPAD5, 0 },
96 { DIK_NUMPAD6, VK_NUMPAD6, 0 },
97 { DIK_ADD, VK_ADD, 0 },
98 { DIK_NUMPAD1, VK_NUMPAD1, 0 },
99 { DIK_NUMPAD2, VK_NUMPAD2, 0 },
100 { DIK_NUMPAD3, VK_NUMPAD3, 0 },
101 { DIK_NUMPAD0, VK_NUMPAD0, 0 },
102 { DIK_DECIMAL, VK_DECIMAL, 0 },
103 { DIK_F11, VK_F11, 0 },
104 { DIK_F12, VK_F12, 0 },
105 { DIK_F13, VK_F13, 0 },
106 { DIK_F14, VK_F14, 0 },
107 { DIK_F15, VK_F15, 0 },
108 { DIK_NUMPADENTER, VK_RETURN, 0 },
109 { DIK_RCONTROL, VK_RCONTROL, 0 },
110 { DIK_DIVIDE, VK_DIVIDE, 0 },
111 { DIK_SYSRQ, 0, 0 },
112 { DIK_RMENU, VK_RMENU, 0 },
113 { DIK_HOME, VK_HOME, 0 },
114 { DIK_UP, VK_UP, 0 },
115 { DIK_PRIOR, VK_PRIOR, 0 },
116 { DIK_LEFT, VK_LEFT, 0 },
117 { DIK_RIGHT, VK_RIGHT, 0 },
118 { DIK_END, VK_END, 0 },
119 { DIK_DOWN, VK_DOWN, 0 },
120 { DIK_NEXT, VK_NEXT, 0 },
121 { DIK_INSERT, VK_INSERT, 0 },
122 { DIK_DELETE, VK_DELETE, 0 },
123 { DIK_LWIN, VK_LWIN, 0 },
124 { DIK_RWIN, VK_RWIN, 0 },
125 { DIK_APPS, VK_APPS, 0 },
126 { DIK_PAUSE, VK_PAUSE, 0 },
127 { 0, VK_CANCEL, 0 },
129 // New keys introduced in Windows 2000. These have no MAME codes to
130 // preserve compatibility with old config files that may refer to them
131 // as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table
132 // entries anyway because otherwise they aren't recognized when
133 // GetAsyncKeyState polling is used (as happens currently when MAME is
134 // paused). Some codes are missing because the mapping to vkey codes
135 // isn't clear, and MapVirtualKey is no help.
137 { DIK_MUTE, VK_VOLUME_MUTE, 0 },
138 { DIK_VOLUMEDOWN, VK_VOLUME_DOWN, 0 },
139 { DIK_VOLUMEUP, VK_VOLUME_UP, 0 },
140 { DIK_WEBHOME, VK_BROWSER_HOME, 0 },
141 { DIK_WEBSEARCH, VK_BROWSER_SEARCH, 0 },
142 { DIK_WEBFAVORITES, VK_BROWSER_FAVORITES, 0 },
143 { DIK_WEBREFRESH, VK_BROWSER_REFRESH, 0 },
144 { DIK_WEBSTOP, VK_BROWSER_STOP, 0 },
145 { DIK_WEBFORWARD, VK_BROWSER_FORWARD, 0 },
146 { DIK_WEBBACK, VK_BROWSER_BACK, 0 },
147 { DIK_MAIL, VK_LAUNCH_MAIL, 0 },
148 { DIK_MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0 },
149 };
151 extern void directXMessage(const char *);
152 extern void winlog(const char *msg, ...);
154 #define POV_UP 1
155 #define POV_DOWN 2
156 #define POV_RIGHT 4
157 #define POV_LEFT 8
159 class DirectInput : public Input
160 {
161 private:
162 HINSTANCE dinputDLL;
163 public:
164 virtual void checkDevices();
165 DirectInput();
166 virtual ~DirectInput();
168 virtual bool initialize();
169 virtual bool readDevices();
170 virtual u32 readDevice(int which, bool sensor);
171 virtual CString getKeyName(LONG_PTR key);
172 virtual void checkKeys();
173 virtual void activate();
174 virtual void loadSettings();
175 virtual void saveSettings();
176 };
178 struct deviceInfo
179 {
180 LPDIRECTINPUTDEVICE device;
181 BOOL isPolled;
182 int nButtons;
183 int nAxes;
184 int nPovs;
185 BOOL first;
186 struct
187 {
188 DWORD offset;
189 LONG center;
190 LONG negative;
191 LONG positive;
192 } axis[8];
193 int needed;
194 union
195 {
196 UCHAR data[256];
197 DIJOYSTATE state;
198 };
199 };
201 static deviceInfo * currentDevice = NULL;
202 static int numDevices = 1;
203 static deviceInfo * pDevices = NULL;
204 static LPDIRECTINPUT pDirectInput = NULL;
205 static int joyDebug = 0;
206 static int axisNumber = 0;
208 USHORT joypad[4][13] = {
209 {
210 DIK_LEFT, DIK_RIGHT,
211 DIK_UP, DIK_DOWN,
212 DIK_Z, DIK_X,
213 DIK_RETURN, DIK_BACK,
214 DIK_A, DIK_S,
215 DIK_SPACE, DIK_F12,
216 DIK_C
217 },
218 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
219 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
220 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
221 };
223 USHORT motion[4] = {
224 DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2
225 };
227 static int winReadKey(char *name, int num)
228 {
229 char buffer[80];
231 sprintf(buffer, "Joy%d_%s", num, name);
233 return regQueryDwordValue(buffer, (DWORD)-1);
234 }
236 void winReadKeys()
237 {
238 int key = -1;
240 for (int i = 0; i < 4; i++)
241 {
242 key = winReadKey("Left", i);
243 if (key != -1)
244 joypad[i][KEY_LEFT] = key;
245 key = winReadKey("Right", i);
246 if (key != -1)
247 joypad[i][KEY_RIGHT] = key;
248 key = winReadKey("Up", i);
249 if (key != -1)
250 joypad[i][KEY_UP] = key;
251 key = winReadKey("Down", i);
252 if (key != -1)
253 joypad[i][KEY_DOWN] = key;
254 key = winReadKey("A", i);
255 if (key != -1)
256 joypad[i][KEY_BUTTON_A] = key;
257 key = winReadKey("B", i);
258 if (key != -1)
259 joypad[i][KEY_BUTTON_B] = key;
260 key = winReadKey("L", i);
261 if (key != -1)
262 joypad[i][KEY_BUTTON_L] = key;
263 key = winReadKey("R", i);
264 if (key != -1)
265 joypad[i][KEY_BUTTON_R] = key;
266 key = winReadKey("Start", i);
267 if (key != -1)
268 joypad[i][KEY_BUTTON_START] = key;
269 key = winReadKey("Select", i);
270 if (key != -1)
271 joypad[i][KEY_BUTTON_SELECT] = key;
272 key = winReadKey("Speed", i);
273 if (key != -1)
274 joypad[i][KEY_BUTTON_SPEED] = key;
275 key = winReadKey("Capture", i);
276 if (key != -1)
277 joypad[i][KEY_BUTTON_CAPTURE] = key;
278 key = winReadKey("GS", i);
279 if (key != -1)
280 joypad[i][KEY_BUTTON_GS] = key;
281 }
282 key = regQueryDwordValue("Motion_Left", (DWORD)-1);
283 if (key != -1)
284 motion[KEY_LEFT] = key;
285 key = regQueryDwordValue("Motion_Right", (DWORD)-1);
286 if (key != -1)
287 motion[KEY_RIGHT] = key;
288 key = regQueryDwordValue("Motion_Up", (DWORD)-1);
289 if (key != -1)
290 motion[KEY_UP] = key;
291 key = regQueryDwordValue("Motion_Down", (DWORD)-1);
292 if (key != -1)
293 motion[KEY_DOWN] = key;
294 }
296 static void winSaveKey(char *name, int num, USHORT value)
297 {
298 char buffer[80];
300 sprintf(buffer, "Joy%d_%s", num, name);
302 regSetDwordValue(buffer, value);
303 }
305 void winSaveKeys()
306 {
307 for (int i = 0; i < 4; i++)
308 {
309 winSaveKey("Left", i, joypad[i][KEY_LEFT]);
310 winSaveKey("Right", i, joypad[i][KEY_RIGHT]);
311 winSaveKey("Up", i, joypad[i][KEY_UP]);
312 winSaveKey("Speed", i, joypad[i][KEY_BUTTON_SPEED]);
313 winSaveKey("Capture", i, joypad[i][KEY_BUTTON_CAPTURE]);
314 winSaveKey("GS", i, joypad[i][KEY_BUTTON_GS]);
315 winSaveKey("Down", i, joypad[i][KEY_DOWN]);
316 winSaveKey("A", i, joypad[i][KEY_BUTTON_A]);
317 winSaveKey("B", i, joypad[i][KEY_BUTTON_B]);
318 winSaveKey("L", i, joypad[i][KEY_BUTTON_L]);
319 winSaveKey("R", i, joypad[i][KEY_BUTTON_R]);
320 winSaveKey("Start", i, joypad[i][KEY_BUTTON_START]);
321 winSaveKey("Select", i, joypad[i][KEY_BUTTON_SELECT]);
322 }
323 regSetDwordValue("joyVersion", 1);
325 regSetDwordValue("Motion_Left",
326 motion[KEY_LEFT]);
327 regSetDwordValue("Motion_Right",
328 motion[KEY_RIGHT]);
329 regSetDwordValue("Motion_Up",
330 motion[KEY_UP]);
331 regSetDwordValue("Motion_Down",
332 motion[KEY_DOWN]);
333 }
335 static BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE*pdidoi,
336 VOID*pContext)
337 {
338 DIPROPRANGE diprg;
339 diprg.diph.dwSize = sizeof(DIPROPRANGE);
340 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
341 diprg.diph.dwHow = DIPH_BYOFFSET;
342 diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
344 diprg.lMin = -32768;
345 diprg.lMax = 32767;
346 // try to set the range
347 if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph)))
348 {
349 // Get the range for the axis
350 if (FAILED(currentDevice->device->
351 GetProperty(DIPROP_RANGE, &diprg.diph)))
352 {
353 return DIENUM_STOP;
354 }
355 }
357 DIPROPDWORD didz;
359 didz.diph.dwSize = sizeof(didz);
360 didz.diph.dwHeaderSize = sizeof(DIPROPHEADER);
361 didz.diph.dwHow = DIPH_BYOFFSET;
362 didz.diph.dwObj = pdidoi->dwOfs;
364 didz.dwData = 5000;
366 currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph);
368 LONG center = (diprg.lMin + diprg.lMax)/2;
369 LONG threshold = (diprg.lMax - center)/2;
371 // only 8 axis supported
372 if (axisNumber < 8)
373 {
374 currentDevice->axis[axisNumber].center = center;
375 currentDevice->axis[axisNumber].negative = center - threshold;
376 currentDevice->axis[axisNumber].positive = center + threshold;
377 currentDevice->axis[axisNumber].offset = pdidoi->dwOfs;
378 }
379 axisNumber++;
380 return DIENUM_CONTINUE;
381 }
383 static BOOL CALLBACK EnumPovsCallback(const DIDEVICEOBJECTINSTANCE*pdidoi,
384 VOID*pContext)
385 {
386 return DIENUM_CONTINUE;
387 }
389 static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst,
390 LPVOID lpvContext)
391 {
392 ZeroMemory(&pDevices[numDevices], sizeof(deviceInfo));
394 HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance,
395 &pDevices[numDevices].device,
396 NULL);
398 if (hRet != DI_OK)
399 return DIENUM_STOP;
401 DIDEVCAPS caps;
402 caps.dwSize = sizeof(DIDEVCAPS);
404 hRet = pDevices[numDevices].device->GetCapabilities(&caps);
406 if (hRet == DI_OK)
407 {
408 if (caps.dwFlags & DIDC_POLLEDDATAFORMAT ||
409 caps.dwFlags & DIDC_POLLEDDEVICE)
410 pDevices[numDevices].isPolled = TRUE;
412 pDevices[numDevices].nButtons = caps.dwButtons;
413 pDevices[numDevices].nAxes = caps.dwAxes;
414 pDevices[numDevices].nPovs = caps.dwPOVs;
416 for (int i = 0; i < 6; i++)
417 {
418 pDevices[numDevices].axis[i].center = 0x8000;
419 pDevices[numDevices].axis[i].negative = 0x4000;
420 pDevices[numDevices].axis[i].positive = 0xc000;
421 }
422 }
423 else if (joyDebug)
424 winlog("Failed to get device capabilities %08x\n", hRet);
426 if (joyDebug)
427 {
428 // don't translate. debug only
429 winlog("******************************\n");
430 winlog("Joystick %2d name : %s\n", numDevices, pInst->tszProductName);
431 }
433 numDevices++;
435 return DIENUM_CONTINUE;
436 }
438 BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst,
439 LPVOID lpvContext)
440 {
441 numDevices++;
443 return DIENUM_CONTINUE;
444 }
446 static int getPovState(DWORD value)
447 {
448 int state = 0;
449 if (LOWORD(value) != 0xFFFF)
450 {
451 if (value < 9000 || value > 27000)
452 state |= POV_UP;
453 if (value > 0 && value < 18000)
454 state |= POV_RIGHT;
455 if (value > 9000 && value < 27000)
456 state |= POV_DOWN;
457 if (value > 18000)
458 state |= POV_LEFT;
459 }
460 return state;
461 }
463 static void checkKeys()
464 {
465 LONG_PTR dev = 0;
466 int i;
468 for (i = 0; i < numDevices; i++)
469 pDevices[i].needed = 0;
471 for (i = 0; i < 4; i++)
472 {
473 dev = joypad[i][KEY_LEFT] >> 8;
474 if (dev < numDevices && dev >= 0)
475 pDevices[dev].needed = 1;
476 else
477 joypad[i][KEY_LEFT] = DIK_LEFT;
479 dev = joypad[i][KEY_RIGHT] >> 8;
480 if (dev < numDevices && dev >= 0)
481 pDevices[dev].needed = 1;
482 else
483 joypad[i][KEY_RIGHT] = DIK_RIGHT;
485 dev = joypad[i][KEY_UP] >> 8;
486 if (dev < numDevices && dev >= 0)
487 pDevices[dev].needed = 1;
488 else
489 joypad[i][KEY_UP] = DIK_UP;
491 dev = joypad[i][KEY_DOWN] >> 8;
492 if (dev < numDevices && dev >= 0)
493 pDevices[dev].needed = 1;
494 else
495 joypad[i][KEY_DOWN] = DIK_DOWN;
497 dev = joypad[i][KEY_BUTTON_A] >> 8;
498 if (dev < numDevices && dev >= 0)
499 pDevices[dev].needed = 1;
500 else
501 joypad[i][KEY_BUTTON_A] = DIK_Z;
503 dev = joypad[i][KEY_BUTTON_B] >> 8;
504 if (dev < numDevices && dev >= 0)
505 pDevices[dev].needed = 1;
506 else
507 joypad[i][KEY_BUTTON_B] = DIK_X;
509 dev = joypad[i][KEY_BUTTON_L] >> 8;
510 if (dev < numDevices && dev >= 0)
511 pDevices[dev].needed = 1;
512 else
513 joypad[i][KEY_BUTTON_L] = DIK_A;
515 dev = joypad[i][KEY_BUTTON_R] >> 8;
516 if (dev < numDevices && dev >= 0)
517 pDevices[dev].needed = 1;
518 else
519 joypad[i][KEY_BUTTON_R] = DIK_S;
521 dev = joypad[i][KEY_BUTTON_START] >> 8;
522 if (dev < numDevices && dev >= 0)
523 pDevices[dev].needed = 1;
524 else
525 joypad[i][KEY_BUTTON_START] = DIK_RETURN;
527 dev = joypad[i][KEY_BUTTON_SELECT] >> 8;
528 if (dev < numDevices && dev >= 0)
529 pDevices[dev].needed = 1;
530 else
531 joypad[i][KEY_BUTTON_SELECT] = DIK_BACK;
533 dev = joypad[i][KEY_BUTTON_SPEED] >> 8;
534 if (dev < numDevices && dev >= 0)
535 pDevices[dev].needed = 1;
536 else
537 joypad[i][KEY_BUTTON_SPEED] = DIK_SPACE;
539 dev = joypad[i][KEY_BUTTON_CAPTURE] >> 8;
540 if (dev < numDevices && dev >= 0)
541 pDevices[dev].needed = 1;
542 else
543 joypad[i][KEY_BUTTON_CAPTURE] = DIK_F12;
545 dev = joypad[i][KEY_BUTTON_GS] >> 8;
546 if (dev < numDevices && dev >= 0)
547 pDevices[dev].needed = 1;
548 else
549 joypad[i][KEY_BUTTON_GS] = DIK_C;
550 }
552 dev = motion[KEY_UP] >> 8;
553 if (dev < numDevices && dev >= 0)
554 pDevices[dev].needed = 1;
555 else
556 motion[KEY_UP] = DIK_NUMPAD8;
558 dev = motion[KEY_DOWN] >> 8;
559 if (dev < numDevices && dev >= 0)
560 pDevices[dev].needed = 1;
561 else
562 motion[KEY_DOWN] = DIK_NUMPAD2;
564 dev = motion[KEY_LEFT] >> 8;
565 if (dev < numDevices && dev >= 0)
566 pDevices[dev].needed = 1;
567 else
568 motion[KEY_LEFT] = DIK_NUMPAD4;
570 dev = motion[KEY_RIGHT] >> 8;
571 if (dev < numDevices && dev >= 0)
572 pDevices[dev].needed = 1;
573 else
574 motion[KEY_RIGHT] = DIK_NUMPAD6;
575 }
577 #define KEYDOWN(buffer, key) (buffer[key] & 0x80)
579 static bool IsKeyDownAsync (WORD KeyIdent)
580 {
581 //if (KeyIdent == 0 || KeyIdent == VK_ESCAPE) // if it's the 'disabled' key, it's never pressed
582 // return false;
584 //if (!GUI.BackgroundInput && GUI.hWnd != GetForegroundWindow())
585 // return false;
587 // the pause key is special, need this to catch all presses of it
588 // Both GetKeyState and GetAsyncKeyState cannot catch it anyway,
589 // so this should be handled in WM_KEYDOWN message.
590 if (KeyIdent == VK_PAUSE)
591 {
592 return false;
593 // if(GetAsyncKeyState(VK_PAUSE)) // not &'ing this with 0x8000 is intentional and necessary
594 // return true;
595 }
597 if (KeyIdent == VK_CAPITAL || KeyIdent == VK_NUMLOCK || KeyIdent == VK_SCROLL)
598 return ((GetKeyState(KeyIdent) & 0x01) != 0);
599 else
600 return ((GetAsyncKeyState(KeyIdent) & 0x8000) != 0);
601 //return ((GetKeyState (KeyIdent) & 0x80) != 0);
602 }
604 static bool readKeyboard()
605 {
606 #ifndef USE_GETASYNCKEYSTATE_FOR_KEYBOARD
607 if (pDevices[0].needed)
608 {
609 HRESULT hret = pDevices[0].device->
610 GetDeviceState(256,
611 (LPVOID)pDevices[0].data);
613 if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED)
614 {
615 hret = pDevices[0].device->Acquire();
616 if (hret != DI_OK)
617 return false;
618 hret = pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data);
619 }
621 return hret == DI_OK;
622 }
623 #else
624 for (int i = 0; i < sizeof(win_key_trans_table)/sizeof(win_key_trans_table[0]); i++) {
625 pDevices[0].data[win_key_trans_table[i].dik] = IsKeyDownAsync(win_key_trans_table[i].vk) ? 0x80 : 0;
626 }
627 #endif
628 return true;
629 }
631 static bool readJoystick(int joy)
632 {
633 if (pDevices[joy].needed)
634 {
635 if (pDevices[joy].isPolled)
636 ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
638 HRESULT hret = pDevices[joy].device->
639 GetDeviceState(sizeof(DIJOYSTATE),
640 (LPVOID)&pDevices[joy].state);
642 if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED)
643 {
644 hret = pDevices[joy].device->Acquire();
646 if (hret == DI_OK)
647 {
648 if (pDevices[joy].isPolled)
649 ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
651 hret = pDevices[joy].device->
652 GetDeviceState(sizeof(DIJOYSTATE),
653 (LPVOID)&pDevices[joy].state);
654 }
655 }
657 return hret == DI_OK;
658 }
660 return true;
661 }
663 static void checkKeyboard()
664 {
665 // mham fix. Patch #1378104
666 UCHAR keystate[256];
667 HRESULT hret = pDevices[0].device->Acquire();
669 if (pDevices[0].first)
670 {
671 pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data);
672 pDevices[0].first = FALSE;
673 return;
674 }
676 hret = pDevices[0].device->
677 GetDeviceState(256, (LPVOID)keystate);
679 if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED)
680 {
681 return;
682 }
684 if (hret == DI_OK)
685 {
686 for (int i = 0; i < 256; i++)
687 {
688 if (keystate[i] == pDevices[0].data[i])
689 continue;
690 if (KEYDOWN(keystate, i))
691 {
692 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, 0, i);
693 break;
694 }
695 }
696 }
697 memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256);
698 }
700 static void checkJoypads()
701 {
702 DIDEVICEOBJECTINSTANCE di;
704 ZeroMemory(&di, sizeof(DIDEVICEOBJECTINSTANCE));
706 di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
708 int i = 0;
710 DIJOYSTATE joystick;
712 for (i = 1; i < numDevices; i++)
713 {
714 HRESULT hret = pDevices[i].device->Acquire();
716 if (pDevices[i].isPolled)
717 ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll();
719 hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick);
721 int j;
723 if (pDevices[i].first)
724 {
725 memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
726 pDevices[i].first = FALSE;
727 continue;
728 }
730 for (j = 0; j < pDevices[i].nButtons; j++)
731 {
732 if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j])
733 & joystick.rgbButtons[j]) & 0x80)
734 {
735 HWND focus = GetFocus();
737 SendMessage(focus, JOYCONFIG_MESSAGE, i, j+128);
738 }
739 }
741 for (j = 0; j < pDevices[i].nAxes && j < 8; j++)
742 {
743 LONG value = pDevices[i].axis[j].center;
744 LONG old = 0;
745 switch (pDevices[i].axis[j].offset)
746 {
747 case DIJOFS_X:
748 value = joystick.lX;
749 old = pDevices[i].state.lX;
750 break;
751 case DIJOFS_Y:
752 value = joystick.lY;
753 old = pDevices[i].state.lY;
754 break;
755 case DIJOFS_Z:
756 value = joystick.lZ;
757 old = pDevices[i].state.lZ;
758 break;
759 case DIJOFS_RX:
760 value = joystick.lRx;
761 old = pDevices[i].state.lRx;
762 break;
763 case DIJOFS_RY:
764 value = joystick.lRy;
765 old = pDevices[i].state.lRy;
766 break;
767 case DIJOFS_RZ:
768 value = joystick.lRz;
769 old = pDevices[i].state.lRz;
770 break;
771 case DIJOFS_SLIDER(0):
772 value = joystick.rglSlider[0];
773 old = pDevices[i].state.rglSlider[0];
774 break;
775 case DIJOFS_SLIDER(1):
776 value = joystick.rglSlider[1];
777 old = pDevices[i].state.rglSlider[1];
778 break;
779 }
780 if (value != old)
781 {
782 if (value < pDevices[i].axis[j].negative)
783 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1));
784 else if (value > pDevices[i].axis[j].positive)
785 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1);
786 }
787 }
789 for (j = 0; j < 4 && j < pDevices[i].nPovs; j++)
790 {
791 if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j]))
792 {
793 int state = getPovState(joystick.rgdwPOV[j]);
795 if (state & POV_UP)
796 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20);
797 else if (state & POV_DOWN)
798 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21);
799 else if (state & POV_RIGHT)
800 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22);
801 else if (state & POV_LEFT)
802 SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23);
803 }
804 }
806 memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
807 }
808 }
810 BOOL checkKey(LONG_PTR key)
811 {
812 LONG_PTR dev = (key >> 8);
814 LONG_PTR k = (key & 255);
816 if (dev == 0)
817 {
818 return KEYDOWN(pDevices[0].data, k);
819 }
820 else if (dev >= numDevices)
821 {
822 return FALSE;
823 }
824 else
825 {
826 if (k < 16)
827 {
828 LONG_PTR axis = k >> 1;
829 LONG value = pDevices[dev].axis[axis].center;
830 switch (pDevices[dev].axis[axis].offset)
831 {
832 case DIJOFS_X:
833 value = pDevices[dev].state.lX;
834 break;
835 case DIJOFS_Y:
836 value = pDevices[dev].state.lY;
837 break;
838 case DIJOFS_Z:
839 value = pDevices[dev].state.lZ;
840 break;
841 case DIJOFS_RX:
842 value = pDevices[dev].state.lRx;
843 break;
844 case DIJOFS_RY:
845 value = pDevices[dev].state.lRy;
846 break;
847 case DIJOFS_RZ:
848 value = pDevices[dev].state.lRz;
849 break;
850 case DIJOFS_SLIDER(0):
851 value = pDevices[dev].state.rglSlider[0];
852 break;
853 case DIJOFS_SLIDER(1):
854 value = pDevices[dev].state.rglSlider[1];
855 break;
856 }
858 if (k & 1)
859 return value > pDevices[dev].axis[axis].positive;
860 return value < pDevices[dev].axis[axis].negative;
861 }
862 else if (k < 48)
863 {
864 LONG_PTR hat = (k >> 2) & 3;
865 int state = getPovState(pDevices[dev].state.rgdwPOV[hat]);
866 BOOL res = FALSE;
867 switch (k & 3)
868 {
869 case 0:
870 res = state & POV_UP;
871 break;
872 case 1:
873 res = state & POV_DOWN;
874 break;
875 case 2:
876 res = state & POV_RIGHT;
877 break;
878 case 3:
879 res = state & POV_LEFT;
880 break;
881 }
882 return res;
883 }
884 else if (k >= 128)
885 {
886 return pDevices[dev].state.rgbButtons[k-128] & 0x80;
887 }
888 }
890 return FALSE;
891 }
893 DirectInput::DirectInput()
894 {
895 dinputDLL = NULL;
896 }
898 DirectInput::~DirectInput()
899 {
900 saveSettings();
901 if (pDirectInput != NULL)
902 {
903 if (pDevices)
904 {
905 for (int i = 0; i < numDevices; i++)
906 {
907 if (pDevices[i].device)
908 {
909 pDevices[i].device->Unacquire();
910 pDevices[i].device->Release();
911 pDevices[i].device = NULL;
912 }
913 }
914 free(pDevices);
915 pDevices = NULL;
916 }
918 pDirectInput->Release();
919 pDirectInput = NULL;
920 }
922 if (dinputDLL)
923 {
924 /**/ ::FreeLibrary(dinputDLL);
925 dinputDLL = NULL;
926 }
927 }
929 bool DirectInput::initialize()
930 {
931 joyDebug = GetPrivateProfileInt("config",
932 "joyDebug",
933 0,
934 "VBA.ini");
935 dinputDLL = /**/ ::LoadLibrary("DINPUT.DLL");
936 HRESULT (WINAPI *DInputCreate)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *);
937 if (dinputDLL != NULL)
938 {
939 DInputCreate = (HRESULT (WINAPI *)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *))
940 GetProcAddress(dinputDLL, "DirectInputCreateA");
942 if (DInputCreate == NULL)
943 {
944 directXMessage("DirectInputCreateA");
945 return false;
946 }
947 }
948 else
949 {
950 directXMessage("DINPUT.DLL");
951 return false;
952 }
954 HRESULT hret = DInputCreate(AfxGetInstanceHandle(),
955 DIRECTINPUT_VERSION,
956 &pDirectInput,
957 NULL);
958 if (hret != DI_OK)
959 {
960 // errorMessage(myLoadString(IDS_ERROR_DISP_CREATE), hret);
961 return false;
962 }
964 hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
965 DIEnumDevicesCallback2,
966 NULL,
967 DIEDFL_ATTACHEDONLY);
969 pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo));
971 hret = pDirectInput->CreateDevice(GUID_SysKeyboard, &pDevices[0].device, NULL);
972 pDevices[0].isPolled = false;
973 pDevices[0].needed = true;
974 pDevices[0].first = true;
976 if (hret != DI_OK)
977 {
978 // errorMessage(myLoadString(IDS_ERROR_DISP_CREATEDEVICE), hret);
979 return false;
980 }
982 numDevices = 1;
984 hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK,
985 DIEnumDevicesCallback,
986 NULL,
987 DIEDFL_ATTACHEDONLY);
989 // hret = pDevices[0].device->SetCooperativeLevel(hWindow,
990 // DISCL_FOREGROUND|
991 // DISCL_NONEXCLUSIVE);
993 if (hret != DI_OK)
994 {
995 // errorMessage(myLoadString(IDS_ERROR_DISP_LEVEL), hret);
996 return false;
997 }
999 hret = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard);
1001 if (hret != DI_OK)
1003 // errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret);
1004 return false;
1007 for (int i = 1; i < numDevices; i++)
1009 pDevices[i].device->SetDataFormat(&c_dfDIJoystick);
1010 pDevices[i].needed = false;
1011 pDevices[i].first = true;
1012 currentDevice = &pDevices[i];
1013 axisNumber = 0;
1014 currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS);
1015 currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV);
1016 if (joyDebug)
1018 // don't translate. debug only
1019 winlog("Joystick %2d polled : %d\n", i, currentDevice->isPolled);
1020 winlog("Joystick %2d buttons : %d\n", i, currentDevice->nButtons);
1021 winlog("Joystick %2d povs : %d\n", i, currentDevice->nPovs);
1022 winlog("Joystick %2d axes : %d\n", i, currentDevice->nAxes);
1023 for (int j = 0; j < currentDevice->nAxes; j++)
1025 winlog("Axis %2d offset : %08lx\n", j, currentDevice->axis[j].
1026 offset);
1027 winlog("Axis %2d center : %08lx\n", j, currentDevice->axis[j].
1028 center);
1029 winlog("Axis %2d negative : %08lx\n", j, currentDevice->axis[j].
1030 negative);
1031 winlog("Axis %2d positive : %08lx\n", j, currentDevice->axis[j].
1032 positive);
1036 currentDevice = NULL;
1039 for (int i = 0; i < numDevices; i++)
1040 pDevices[i].device->Acquire();
1042 return true;
1045 bool DirectInput::readDevices()
1047 bool ok = true;
1048 for (int i = 0; i < numDevices; i++)
1050 if (pDevices[i].needed)
1052 ok = (i > 0 ? readJoystick(i) : readKeyboard()) || ok;
1055 return ok;
1058 bool inputActive = true; // used to disable all input when the window is inactive
1060 u32 DirectInput::readDevice(int i, bool sensor)
1062 // this old hack is evil
1063 extern int systemGetDefaultJoypad();
1064 extern int32 gbSgbMode, gbSgbMultiplayer;
1065 if (!(gbSgbMode && gbSgbMultiplayer))
1066 i = systemGetDefaultJoypad();
1068 u32 res = 0;
1070 // manual input
1071 if (inputActive)
1073 if (checkKey(joypad[i][KEY_BUTTON_A]))
1074 res |= BUTTON_MASK_A;
1075 if (checkKey(joypad[i][KEY_BUTTON_B]))
1076 res |= BUTTON_MASK_B;
1077 if (checkKey(joypad[i][KEY_BUTTON_SELECT]))
1078 res |= BUTTON_MASK_SELECT;
1079 if (checkKey(joypad[i][KEY_BUTTON_START]))
1080 res |= BUTTON_MASK_START;
1081 if (checkKey(joypad[i][KEY_RIGHT]))
1082 res |= BUTTON_MASK_RIGHT;
1083 if (checkKey(joypad[i][KEY_LEFT]))
1084 res |= BUTTON_MASK_LEFT;
1085 if (checkKey(joypad[i][KEY_UP]))
1086 res |= BUTTON_MASK_UP;
1087 if (checkKey(joypad[i][KEY_DOWN]))
1088 res |= BUTTON_MASK_DOWN;
1089 if (checkKey(joypad[i][KEY_BUTTON_R]))
1090 res |= BUTTON_MASK_R;
1091 if (checkKey(joypad[i][KEY_BUTTON_L]))
1092 res |= BUTTON_MASK_L;
1094 // unused
1095 if (checkKey(motion[KEY_LEFT]))
1096 res |= BUTTON_MASK_LEFT_MOTION;
1097 else if (checkKey(motion[KEY_RIGHT]))
1098 res |= BUTTON_MASK_RIGHT_MOTION;
1099 if (checkKey(motion[KEY_UP]))
1100 res |= BUTTON_MASK_UP_MOTION;
1101 else if (checkKey(motion[KEY_DOWN]))
1102 res |= BUTTON_MASK_DOWN_MOTION;
1105 u32 hackedButtons = 0;
1106 if (inputActive)
1108 // the "non-button" buttons (what a hack!)
1109 if (checkKey(joypad[i][KEY_BUTTON_SPEED]))
1110 hackedButtons |= BUTTON_MASK_SPEED;
1111 if (checkKey(joypad[i][KEY_BUTTON_CAPTURE]))
1112 hackedButtons |= BUTTON_MASK_CAPTURE;
1113 if (checkKey(joypad[i][KEY_BUTTON_GS]))
1114 hackedButtons |= BUTTON_MASK_GAMESHARK;
1117 extern bool systemIsSpedUp();
1118 if (systemIsSpedUp())
1119 hackedButtons |= BUTTON_MASK_SPEED;
1121 return res | hackedButtons;
1124 CString DirectInput::getKeyName(LONG_PTR key)
1126 LONG_PTR d = (key >> 8);
1127 LONG_PTR k = key & 255;
1129 DIDEVICEOBJECTINSTANCE di;
1131 ZeroMemory(&di, sizeof(DIDEVICEOBJECTINSTANCE));
1133 di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
1135 CString winBuffer = winResLoadString(IDS_ERROR);
1137 if (d == 0)
1139 pDevices[0].device->GetObjectInfo(&di, (DWORD)key, DIPH_BYOFFSET);
1140 winBuffer = di.tszName;
1142 else if (d < numDevices)
1144 if (k < 16)
1146 if (k < 4)
1148 switch (k)
1150 case 0:
1151 winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d);
1152 break;
1153 case 1:
1154 winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d);
1155 break;
1156 case 2:
1157 winBuffer.Format(winResLoadString(IDS_JOY_UP), d);
1158 break;
1159 case 3:
1160 winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d);
1161 break;
1164 else
1166 pDevices[d].device->GetObjectInfo(&di,
1167 pDevices[d].axis[k>>1].offset,
1168 DIPH_BYOFFSET);
1169 if (k & 1)
1170 winBuffer.Format("Joy %d %s +", d, di.tszName);
1171 else
1172 winBuffer.Format("Joy %d %s -", d, di.tszName);
1175 else if (k < 48)
1177 LONG_PTR hat = (k >> 2) & 3;
1178 pDevices[d].device->GetObjectInfo(&di,
1179 (DWORD)DIJOFS_POV(hat),
1180 DIPH_BYOFFSET);
1181 char * dir = "up";
1182 LONG_PTR dd = k & 3;
1183 if (dd == 1)
1184 dir = "down";
1185 else if (dd == 2)
1186 dir = "right";
1187 else if (dd == 3)
1188 dir = "left";
1189 winBuffer.Format("Joy %d %s %s", d, di.tszName, dir);
1191 else
1193 pDevices[d].device->GetObjectInfo(&di,
1194 (DWORD)DIJOFS_BUTTON(k-128),
1195 DIPH_BYOFFSET);
1196 winBuffer.Format(winResLoadString(IDS_JOY_BUTTON), d, di.tszName);
1199 else
1201 // Joystick isn't plugged in. We can't decipher k, so just show its value.
1202 winBuffer.Format("Joy %d (%d)", d, k);
1205 return winBuffer;
1208 void DirectInput::checkKeys()
1210 ::checkKeys();
1213 Input *newDirectInput()
1215 return new DirectInput;
1218 void DirectInput::checkDevices()
1220 checkJoypads();
1221 checkKeyboard();
1224 void DirectInput::activate()
1226 for (int i = 0; i < numDevices; i++)
1228 if (pDevices != NULL && pDevices[i].device != NULL)
1229 pDevices[i].device->Acquire();
1233 void DirectInput::loadSettings()
1235 winReadKeys();
1238 void DirectInput::saveSettings()
1240 winSaveKeys();