Mercurial > vba-clojure
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_KEYBOARD3 #include "stdafx.h"5 #define DIRECTINPUT_VERSION 0x05006 #include "dinput.h"8 #include "resource.h"9 #include "Input.h"10 #include "Reg.h"11 #include "WinResUtil.h"13 // master keyboard translation table14 static const struct {15 int dik;16 int vk;17 int ascii;18 } win_key_trans_table[] = {19 // dinput key virtual key ascii20 { 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 to130 // preserve compatibility with old config files that may refer to them131 // as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table132 // entries anyway because otherwise they aren't recognized when133 // GetAsyncKeyState polling is used (as happens currently when MAME is134 // paused). Some codes are missing because the mapping to vkey codes135 // 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 1155 #define POV_DOWN 2156 #define POV_RIGHT 4157 #define POV_LEFT 8159 class DirectInput : public Input160 {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 deviceInfo179 {180 LPDIRECTINPUTDEVICE device;181 BOOL isPolled;182 int nButtons;183 int nAxes;184 int nPovs;185 BOOL first;186 struct187 {188 DWORD offset;189 LONG center;190 LONG negative;191 LONG positive;192 } axis[8];193 int needed;194 union195 {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_C217 },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_NUMPAD2225 };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 axis344 diprg.lMin = -32768;345 diprg.lMax = 32767;346 // try to set the range347 if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph)))348 {349 // Get the range for the axis350 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 supported372 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 only429 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 else477 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 else483 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 else489 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 else495 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 else501 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 else507 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 else513 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 else519 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 else525 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 else531 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 else537 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 else543 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 else549 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 else556 motion[KEY_UP] = DIK_NUMPAD8;558 dev = motion[KEY_DOWN] >> 8;559 if (dev < numDevices && dev >= 0)560 pDevices[dev].needed = 1;561 else562 motion[KEY_DOWN] = DIK_NUMPAD2;564 dev = motion[KEY_LEFT] >> 8;565 if (dev < numDevices && dev >= 0)566 pDevices[dev].needed = 1;567 else568 motion[KEY_LEFT] = DIK_NUMPAD4;570 dev = motion[KEY_RIGHT] >> 8;571 if (dev < numDevices && dev >= 0)572 pDevices[dev].needed = 1;573 else574 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 pressed582 // 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 it588 // 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 necessary594 // return true;595 }597 if (KeyIdent == VK_CAPITAL || KeyIdent == VK_NUMLOCK || KeyIdent == VK_SCROLL)598 return ((GetKeyState(KeyIdent) & 0x01) != 0);599 else600 return ((GetAsyncKeyState(KeyIdent) & 0x8000) != 0);601 //return ((GetKeyState (KeyIdent) & 0x80) != 0);602 }604 static bool readKeyboard()605 {606 #ifndef USE_GETASYNCKEYSTATE_FOR_KEYBOARD607 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 #else624 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 #endif628 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 #1378104666 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 else825 {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 else949 {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)1002 {1003 // errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret);1004 return false;1005 }1007 for (int i = 1; i < numDevices; i++)1008 {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)1017 {1018 // don't translate. debug only1019 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++)1024 {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);1033 }1034 }1036 currentDevice = NULL;1037 }1039 for (int i = 0; i < numDevices; i++)1040 pDevices[i].device->Acquire();1042 return true;1043 }1045 bool DirectInput::readDevices()1046 {1047 bool ok = true;1048 for (int i = 0; i < numDevices; i++)1049 {1050 if (pDevices[i].needed)1051 {1052 ok = (i > 0 ? readJoystick(i) : readKeyboard()) || ok;1053 }1054 }1055 return ok;1056 }1058 bool inputActive = true; // used to disable all input when the window is inactive1060 u32 DirectInput::readDevice(int i, bool sensor)1061 {1062 // this old hack is evil1063 extern int systemGetDefaultJoypad();1064 extern int32 gbSgbMode, gbSgbMultiplayer;1065 if (!(gbSgbMode && gbSgbMultiplayer))1066 i = systemGetDefaultJoypad();1068 u32 res = 0;1070 // manual input1071 if (inputActive)1072 {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 // unused1095 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;1103 }1105 u32 hackedButtons = 0;1106 if (inputActive)1107 {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;1115 }1117 extern bool systemIsSpedUp();1118 if (systemIsSpedUp())1119 hackedButtons |= BUTTON_MASK_SPEED;1121 return res | hackedButtons;1122 }1124 CString DirectInput::getKeyName(LONG_PTR key)1125 {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)1138 {1139 pDevices[0].device->GetObjectInfo(&di, (DWORD)key, DIPH_BYOFFSET);1140 winBuffer = di.tszName;1141 }1142 else if (d < numDevices)1143 {1144 if (k < 16)1145 {1146 if (k < 4)1147 {1148 switch (k)1149 {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;1162 }1163 }1164 else1165 {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 else1172 winBuffer.Format("Joy %d %s -", d, di.tszName);1173 }1174 }1175 else if (k < 48)1176 {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);1190 }1191 else1192 {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);1197 }1198 }1199 else1200 {1201 // Joystick isn't plugged in. We can't decipher k, so just show its value.1202 winBuffer.Format("Joy %d (%d)", d, k);1203 }1205 return winBuffer;1206 }1208 void DirectInput::checkKeys()1209 {1210 ::checkKeys();1211 }1213 Input *newDirectInput()1214 {1215 return new DirectInput;1216 }1218 void DirectInput::checkDevices()1219 {1220 checkJoypads();1221 checkKeyboard();1222 }1224 void DirectInput::activate()1225 {1226 for (int i = 0; i < numDevices; i++)1227 {1228 if (pDevices != NULL && pDevices[i].device != NULL)1229 pDevices[i].device->Acquire();1230 }1231 }1233 void DirectInput::loadSettings()1234 {1235 winReadKeys();1236 }1238 void DirectInput::saveSettings()1239 {1240 winSaveKeys();1241 }