rlm@1: //#define USE_GETASYNCKEYSTATE_FOR_KEYBOARD rlm@1: rlm@1: #include "stdafx.h" rlm@1: rlm@1: #define DIRECTINPUT_VERSION 0x0500 rlm@1: #include "dinput.h" rlm@1: rlm@1: #include "resource.h" rlm@1: #include "Input.h" rlm@1: #include "Reg.h" rlm@1: #include "WinResUtil.h" rlm@1: rlm@1: // master keyboard translation table rlm@1: static const struct { rlm@1: int dik; rlm@1: int vk; rlm@1: int ascii; rlm@1: } win_key_trans_table[] = { rlm@1: // dinput key virtual key ascii rlm@1: { DIK_ESCAPE, VK_ESCAPE, 27 }, rlm@1: { DIK_1, '1', '1' }, rlm@1: { DIK_2, '2', '2' }, rlm@1: { DIK_3, '3', '3' }, rlm@1: { DIK_4, '4', '4' }, rlm@1: { DIK_5, '5', '5' }, rlm@1: { DIK_6, '6', '6' }, rlm@1: { DIK_7, '7', '7' }, rlm@1: { DIK_8, '8', '8' }, rlm@1: { DIK_9, '9', '9' }, rlm@1: { DIK_0, '0', '0' }, rlm@1: { DIK_MINUS, VK_OEM_MINUS, '-' }, rlm@1: { DIK_EQUALS, VK_OEM_PLUS, '=' }, rlm@1: { DIK_BACK, VK_BACK, 8 }, rlm@1: { DIK_TAB, VK_TAB, 9 }, rlm@1: { DIK_Q, 'Q', 'Q' }, rlm@1: { DIK_W, 'W', 'W' }, rlm@1: { DIK_E, 'E', 'E' }, rlm@1: { DIK_R, 'R', 'R' }, rlm@1: { DIK_T, 'T', 'T' }, rlm@1: { DIK_Y, 'Y', 'Y' }, rlm@1: { DIK_U, 'U', 'U' }, rlm@1: { DIK_I, 'I', 'I' }, rlm@1: { DIK_O, 'O', 'O' }, rlm@1: { DIK_P, 'P', 'P' }, rlm@1: { DIK_LBRACKET, VK_OEM_4, '[' }, rlm@1: { DIK_RBRACKET, VK_OEM_6, ']' }, rlm@1: { DIK_RETURN, VK_RETURN, 13 }, rlm@1: { DIK_LCONTROL, VK_LCONTROL, 0 }, rlm@1: { DIK_A, 'A', 'A' }, rlm@1: { DIK_S, 'S', 'S' }, rlm@1: { DIK_D, 'D', 'D' }, rlm@1: { DIK_F, 'F', 'F' }, rlm@1: { DIK_G, 'G', 'G' }, rlm@1: { DIK_H, 'H', 'H' }, rlm@1: { DIK_J, 'J', 'J' }, rlm@1: { DIK_K, 'K', 'K' }, rlm@1: { DIK_L, 'L', 'L' }, rlm@1: { DIK_SEMICOLON, VK_OEM_1, ';' }, rlm@1: { DIK_APOSTROPHE, VK_OEM_7, '\'' }, rlm@1: { DIK_GRAVE, VK_OEM_3, '`' }, rlm@1: { DIK_LSHIFT, VK_LSHIFT, 0 }, rlm@1: { DIK_BACKSLASH, VK_OEM_5, '\\' }, rlm@1: { DIK_Z, 'Z', 'Z' }, rlm@1: { DIK_X, 'X', 'X' }, rlm@1: { DIK_C, 'C', 'C' }, rlm@1: { DIK_V, 'V', 'V' }, rlm@1: { DIK_B, 'B', 'B' }, rlm@1: { DIK_N, 'N', 'N' }, rlm@1: { DIK_M, 'M', 'M' }, rlm@1: { DIK_COMMA, VK_OEM_COMMA, ',' }, rlm@1: { DIK_PERIOD, VK_OEM_PERIOD, '.' }, rlm@1: { DIK_SLASH, VK_OEM_2, '/' }, rlm@1: { DIK_RSHIFT, VK_RSHIFT, 0 }, rlm@1: { DIK_MULTIPLY, VK_MULTIPLY, '*' }, rlm@1: { DIK_LMENU, VK_LMENU, 0 }, rlm@1: { DIK_SPACE, VK_SPACE, ' ' }, rlm@1: { DIK_CAPITAL, VK_CAPITAL, 0 }, rlm@1: { DIK_F1, VK_F1, 0 }, rlm@1: { DIK_F2, VK_F2, 0 }, rlm@1: { DIK_F3, VK_F3, 0 }, rlm@1: { DIK_F4, VK_F4, 0 }, rlm@1: { DIK_F5, VK_F5, 0 }, rlm@1: { DIK_F6, VK_F6, 0 }, rlm@1: { DIK_F7, VK_F7, 0 }, rlm@1: { DIK_F8, VK_F8, 0 }, rlm@1: { DIK_F9, VK_F9, 0 }, rlm@1: { DIK_F10, VK_F10, 0 }, rlm@1: { DIK_NUMLOCK, VK_NUMLOCK, 0 }, rlm@1: { DIK_SCROLL, VK_SCROLL, 0 }, rlm@1: { DIK_NUMPAD7, VK_NUMPAD7, 0 }, rlm@1: { DIK_NUMPAD8, VK_NUMPAD8, 0 }, rlm@1: { DIK_NUMPAD9, VK_NUMPAD9, 0 }, rlm@1: { DIK_SUBTRACT, VK_SUBTRACT, 0 }, rlm@1: { DIK_NUMPAD4, VK_NUMPAD4, 0 }, rlm@1: { DIK_NUMPAD5, VK_NUMPAD5, 0 }, rlm@1: { DIK_NUMPAD6, VK_NUMPAD6, 0 }, rlm@1: { DIK_ADD, VK_ADD, 0 }, rlm@1: { DIK_NUMPAD1, VK_NUMPAD1, 0 }, rlm@1: { DIK_NUMPAD2, VK_NUMPAD2, 0 }, rlm@1: { DIK_NUMPAD3, VK_NUMPAD3, 0 }, rlm@1: { DIK_NUMPAD0, VK_NUMPAD0, 0 }, rlm@1: { DIK_DECIMAL, VK_DECIMAL, 0 }, rlm@1: { DIK_F11, VK_F11, 0 }, rlm@1: { DIK_F12, VK_F12, 0 }, rlm@1: { DIK_F13, VK_F13, 0 }, rlm@1: { DIK_F14, VK_F14, 0 }, rlm@1: { DIK_F15, VK_F15, 0 }, rlm@1: { DIK_NUMPADENTER, VK_RETURN, 0 }, rlm@1: { DIK_RCONTROL, VK_RCONTROL, 0 }, rlm@1: { DIK_DIVIDE, VK_DIVIDE, 0 }, rlm@1: { DIK_SYSRQ, 0, 0 }, rlm@1: { DIK_RMENU, VK_RMENU, 0 }, rlm@1: { DIK_HOME, VK_HOME, 0 }, rlm@1: { DIK_UP, VK_UP, 0 }, rlm@1: { DIK_PRIOR, VK_PRIOR, 0 }, rlm@1: { DIK_LEFT, VK_LEFT, 0 }, rlm@1: { DIK_RIGHT, VK_RIGHT, 0 }, rlm@1: { DIK_END, VK_END, 0 }, rlm@1: { DIK_DOWN, VK_DOWN, 0 }, rlm@1: { DIK_NEXT, VK_NEXT, 0 }, rlm@1: { DIK_INSERT, VK_INSERT, 0 }, rlm@1: { DIK_DELETE, VK_DELETE, 0 }, rlm@1: { DIK_LWIN, VK_LWIN, 0 }, rlm@1: { DIK_RWIN, VK_RWIN, 0 }, rlm@1: { DIK_APPS, VK_APPS, 0 }, rlm@1: { DIK_PAUSE, VK_PAUSE, 0 }, rlm@1: { 0, VK_CANCEL, 0 }, rlm@1: rlm@1: // New keys introduced in Windows 2000. These have no MAME codes to rlm@1: // preserve compatibility with old config files that may refer to them rlm@1: // as e.g. FORWARD instead of e.g. KEYCODE_WEBFORWARD. They need table rlm@1: // entries anyway because otherwise they aren't recognized when rlm@1: // GetAsyncKeyState polling is used (as happens currently when MAME is rlm@1: // paused). Some codes are missing because the mapping to vkey codes rlm@1: // isn't clear, and MapVirtualKey is no help. rlm@1: rlm@1: { DIK_MUTE, VK_VOLUME_MUTE, 0 }, rlm@1: { DIK_VOLUMEDOWN, VK_VOLUME_DOWN, 0 }, rlm@1: { DIK_VOLUMEUP, VK_VOLUME_UP, 0 }, rlm@1: { DIK_WEBHOME, VK_BROWSER_HOME, 0 }, rlm@1: { DIK_WEBSEARCH, VK_BROWSER_SEARCH, 0 }, rlm@1: { DIK_WEBFAVORITES, VK_BROWSER_FAVORITES, 0 }, rlm@1: { DIK_WEBREFRESH, VK_BROWSER_REFRESH, 0 }, rlm@1: { DIK_WEBSTOP, VK_BROWSER_STOP, 0 }, rlm@1: { DIK_WEBFORWARD, VK_BROWSER_FORWARD, 0 }, rlm@1: { DIK_WEBBACK, VK_BROWSER_BACK, 0 }, rlm@1: { DIK_MAIL, VK_LAUNCH_MAIL, 0 }, rlm@1: { DIK_MEDIASELECT, VK_LAUNCH_MEDIA_SELECT, 0 }, rlm@1: }; rlm@1: rlm@1: extern void directXMessage(const char *); rlm@1: extern void winlog(const char *msg, ...); rlm@1: rlm@1: #define POV_UP 1 rlm@1: #define POV_DOWN 2 rlm@1: #define POV_RIGHT 4 rlm@1: #define POV_LEFT 8 rlm@1: rlm@1: class DirectInput : public Input rlm@1: { rlm@1: private: rlm@1: HINSTANCE dinputDLL; rlm@1: public: rlm@1: virtual void checkDevices(); rlm@1: DirectInput(); rlm@1: virtual ~DirectInput(); rlm@1: rlm@1: virtual bool initialize(); rlm@1: virtual bool readDevices(); rlm@1: virtual u32 readDevice(int which, bool sensor); rlm@1: virtual CString getKeyName(LONG_PTR key); rlm@1: virtual void checkKeys(); rlm@1: virtual void activate(); rlm@1: virtual void loadSettings(); rlm@1: virtual void saveSettings(); rlm@1: }; rlm@1: rlm@1: struct deviceInfo rlm@1: { rlm@1: LPDIRECTINPUTDEVICE device; rlm@1: BOOL isPolled; rlm@1: int nButtons; rlm@1: int nAxes; rlm@1: int nPovs; rlm@1: BOOL first; rlm@1: struct rlm@1: { rlm@1: DWORD offset; rlm@1: LONG center; rlm@1: LONG negative; rlm@1: LONG positive; rlm@1: } axis[8]; rlm@1: int needed; rlm@1: union rlm@1: { rlm@1: UCHAR data[256]; rlm@1: DIJOYSTATE state; rlm@1: }; rlm@1: }; rlm@1: rlm@1: static deviceInfo * currentDevice = NULL; rlm@1: static int numDevices = 1; rlm@1: static deviceInfo * pDevices = NULL; rlm@1: static LPDIRECTINPUT pDirectInput = NULL; rlm@1: static int joyDebug = 0; rlm@1: static int axisNumber = 0; rlm@1: rlm@1: USHORT joypad[4][13] = { rlm@1: { rlm@1: DIK_LEFT, DIK_RIGHT, rlm@1: DIK_UP, DIK_DOWN, rlm@1: DIK_Z, DIK_X, rlm@1: DIK_RETURN, DIK_BACK, rlm@1: DIK_A, DIK_S, rlm@1: DIK_SPACE, DIK_F12, rlm@1: DIK_C rlm@1: }, rlm@1: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, rlm@1: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, rlm@1: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } rlm@1: }; rlm@1: rlm@1: USHORT motion[4] = { rlm@1: DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2 rlm@1: }; rlm@1: rlm@1: static int winReadKey(char *name, int num) rlm@1: { rlm@1: char buffer[80]; rlm@1: rlm@1: sprintf(buffer, "Joy%d_%s", num, name); rlm@1: rlm@1: return regQueryDwordValue(buffer, (DWORD)-1); rlm@1: } rlm@1: rlm@1: void winReadKeys() rlm@1: { rlm@1: int key = -1; rlm@1: rlm@1: for (int i = 0; i < 4; i++) rlm@1: { rlm@1: key = winReadKey("Left", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_LEFT] = key; rlm@1: key = winReadKey("Right", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_RIGHT] = key; rlm@1: key = winReadKey("Up", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_UP] = key; rlm@1: key = winReadKey("Down", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_DOWN] = key; rlm@1: key = winReadKey("A", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_A] = key; rlm@1: key = winReadKey("B", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_B] = key; rlm@1: key = winReadKey("L", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_L] = key; rlm@1: key = winReadKey("R", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_R] = key; rlm@1: key = winReadKey("Start", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_START] = key; rlm@1: key = winReadKey("Select", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_SELECT] = key; rlm@1: key = winReadKey("Speed", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_SPEED] = key; rlm@1: key = winReadKey("Capture", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_CAPTURE] = key; rlm@1: key = winReadKey("GS", i); rlm@1: if (key != -1) rlm@1: joypad[i][KEY_BUTTON_GS] = key; rlm@1: } rlm@1: key = regQueryDwordValue("Motion_Left", (DWORD)-1); rlm@1: if (key != -1) rlm@1: motion[KEY_LEFT] = key; rlm@1: key = regQueryDwordValue("Motion_Right", (DWORD)-1); rlm@1: if (key != -1) rlm@1: motion[KEY_RIGHT] = key; rlm@1: key = regQueryDwordValue("Motion_Up", (DWORD)-1); rlm@1: if (key != -1) rlm@1: motion[KEY_UP] = key; rlm@1: key = regQueryDwordValue("Motion_Down", (DWORD)-1); rlm@1: if (key != -1) rlm@1: motion[KEY_DOWN] = key; rlm@1: } rlm@1: rlm@1: static void winSaveKey(char *name, int num, USHORT value) rlm@1: { rlm@1: char buffer[80]; rlm@1: rlm@1: sprintf(buffer, "Joy%d_%s", num, name); rlm@1: rlm@1: regSetDwordValue(buffer, value); rlm@1: } rlm@1: rlm@1: void winSaveKeys() rlm@1: { rlm@1: for (int i = 0; i < 4; i++) rlm@1: { rlm@1: winSaveKey("Left", i, joypad[i][KEY_LEFT]); rlm@1: winSaveKey("Right", i, joypad[i][KEY_RIGHT]); rlm@1: winSaveKey("Up", i, joypad[i][KEY_UP]); rlm@1: winSaveKey("Speed", i, joypad[i][KEY_BUTTON_SPEED]); rlm@1: winSaveKey("Capture", i, joypad[i][KEY_BUTTON_CAPTURE]); rlm@1: winSaveKey("GS", i, joypad[i][KEY_BUTTON_GS]); rlm@1: winSaveKey("Down", i, joypad[i][KEY_DOWN]); rlm@1: winSaveKey("A", i, joypad[i][KEY_BUTTON_A]); rlm@1: winSaveKey("B", i, joypad[i][KEY_BUTTON_B]); rlm@1: winSaveKey("L", i, joypad[i][KEY_BUTTON_L]); rlm@1: winSaveKey("R", i, joypad[i][KEY_BUTTON_R]); rlm@1: winSaveKey("Start", i, joypad[i][KEY_BUTTON_START]); rlm@1: winSaveKey("Select", i, joypad[i][KEY_BUTTON_SELECT]); rlm@1: } rlm@1: regSetDwordValue("joyVersion", 1); rlm@1: rlm@1: regSetDwordValue("Motion_Left", rlm@1: motion[KEY_LEFT]); rlm@1: regSetDwordValue("Motion_Right", rlm@1: motion[KEY_RIGHT]); rlm@1: regSetDwordValue("Motion_Up", rlm@1: motion[KEY_UP]); rlm@1: regSetDwordValue("Motion_Down", rlm@1: motion[KEY_DOWN]); rlm@1: } rlm@1: rlm@1: static BOOL CALLBACK EnumAxesCallback(const DIDEVICEOBJECTINSTANCE*pdidoi, rlm@1: VOID*pContext) rlm@1: { rlm@1: DIPROPRANGE diprg; rlm@1: diprg.diph.dwSize = sizeof(DIPROPRANGE); rlm@1: diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); rlm@1: diprg.diph.dwHow = DIPH_BYOFFSET; rlm@1: diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis rlm@1: rlm@1: diprg.lMin = -32768; rlm@1: diprg.lMax = 32767; rlm@1: // try to set the range rlm@1: if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) rlm@1: { rlm@1: // Get the range for the axis rlm@1: if (FAILED(currentDevice->device-> rlm@1: GetProperty(DIPROP_RANGE, &diprg.diph))) rlm@1: { rlm@1: return DIENUM_STOP; rlm@1: } rlm@1: } rlm@1: rlm@1: DIPROPDWORD didz; rlm@1: rlm@1: didz.diph.dwSize = sizeof(didz); rlm@1: didz.diph.dwHeaderSize = sizeof(DIPROPHEADER); rlm@1: didz.diph.dwHow = DIPH_BYOFFSET; rlm@1: didz.diph.dwObj = pdidoi->dwOfs; rlm@1: rlm@1: didz.dwData = 5000; rlm@1: rlm@1: currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph); rlm@1: rlm@1: LONG center = (diprg.lMin + diprg.lMax)/2; rlm@1: LONG threshold = (diprg.lMax - center)/2; rlm@1: rlm@1: // only 8 axis supported rlm@1: if (axisNumber < 8) rlm@1: { rlm@1: currentDevice->axis[axisNumber].center = center; rlm@1: currentDevice->axis[axisNumber].negative = center - threshold; rlm@1: currentDevice->axis[axisNumber].positive = center + threshold; rlm@1: currentDevice->axis[axisNumber].offset = pdidoi->dwOfs; rlm@1: } rlm@1: axisNumber++; rlm@1: return DIENUM_CONTINUE; rlm@1: } rlm@1: rlm@1: static BOOL CALLBACK EnumPovsCallback(const DIDEVICEOBJECTINSTANCE*pdidoi, rlm@1: VOID*pContext) rlm@1: { rlm@1: return DIENUM_CONTINUE; rlm@1: } rlm@1: rlm@1: static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst, rlm@1: LPVOID lpvContext) rlm@1: { rlm@1: ZeroMemory(&pDevices[numDevices], sizeof(deviceInfo)); rlm@1: rlm@1: HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance, rlm@1: &pDevices[numDevices].device, rlm@1: NULL); rlm@1: rlm@1: if (hRet != DI_OK) rlm@1: return DIENUM_STOP; rlm@1: rlm@1: DIDEVCAPS caps; rlm@1: caps.dwSize = sizeof(DIDEVCAPS); rlm@1: rlm@1: hRet = pDevices[numDevices].device->GetCapabilities(&caps); rlm@1: rlm@1: if (hRet == DI_OK) rlm@1: { rlm@1: if (caps.dwFlags & DIDC_POLLEDDATAFORMAT || rlm@1: caps.dwFlags & DIDC_POLLEDDEVICE) rlm@1: pDevices[numDevices].isPolled = TRUE; rlm@1: rlm@1: pDevices[numDevices].nButtons = caps.dwButtons; rlm@1: pDevices[numDevices].nAxes = caps.dwAxes; rlm@1: pDevices[numDevices].nPovs = caps.dwPOVs; rlm@1: rlm@1: for (int i = 0; i < 6; i++) rlm@1: { rlm@1: pDevices[numDevices].axis[i].center = 0x8000; rlm@1: pDevices[numDevices].axis[i].negative = 0x4000; rlm@1: pDevices[numDevices].axis[i].positive = 0xc000; rlm@1: } rlm@1: } rlm@1: else if (joyDebug) rlm@1: winlog("Failed to get device capabilities %08x\n", hRet); rlm@1: rlm@1: if (joyDebug) rlm@1: { rlm@1: // don't translate. debug only rlm@1: winlog("******************************\n"); rlm@1: winlog("Joystick %2d name : %s\n", numDevices, pInst->tszProductName); rlm@1: } rlm@1: rlm@1: numDevices++; rlm@1: rlm@1: return DIENUM_CONTINUE; rlm@1: } rlm@1: rlm@1: BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst, rlm@1: LPVOID lpvContext) rlm@1: { rlm@1: numDevices++; rlm@1: rlm@1: return DIENUM_CONTINUE; rlm@1: } rlm@1: rlm@1: static int getPovState(DWORD value) rlm@1: { rlm@1: int state = 0; rlm@1: if (LOWORD(value) != 0xFFFF) rlm@1: { rlm@1: if (value < 9000 || value > 27000) rlm@1: state |= POV_UP; rlm@1: if (value > 0 && value < 18000) rlm@1: state |= POV_RIGHT; rlm@1: if (value > 9000 && value < 27000) rlm@1: state |= POV_DOWN; rlm@1: if (value > 18000) rlm@1: state |= POV_LEFT; rlm@1: } rlm@1: return state; rlm@1: } rlm@1: rlm@1: static void checkKeys() rlm@1: { rlm@1: LONG_PTR dev = 0; rlm@1: int i; rlm@1: rlm@1: for (i = 0; i < numDevices; i++) rlm@1: pDevices[i].needed = 0; rlm@1: rlm@1: for (i = 0; i < 4; i++) rlm@1: { rlm@1: dev = joypad[i][KEY_LEFT] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_LEFT] = DIK_LEFT; rlm@1: rlm@1: dev = joypad[i][KEY_RIGHT] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_RIGHT] = DIK_RIGHT; rlm@1: rlm@1: dev = joypad[i][KEY_UP] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_UP] = DIK_UP; rlm@1: rlm@1: dev = joypad[i][KEY_DOWN] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_DOWN] = DIK_DOWN; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_A] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_A] = DIK_Z; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_B] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_B] = DIK_X; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_L] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_L] = DIK_A; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_R] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_R] = DIK_S; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_START] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_START] = DIK_RETURN; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_SELECT] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_SELECT] = DIK_BACK; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_SPEED] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_SPEED] = DIK_SPACE; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_CAPTURE] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_CAPTURE] = DIK_F12; rlm@1: rlm@1: dev = joypad[i][KEY_BUTTON_GS] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: joypad[i][KEY_BUTTON_GS] = DIK_C; rlm@1: } rlm@1: rlm@1: dev = motion[KEY_UP] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: motion[KEY_UP] = DIK_NUMPAD8; rlm@1: rlm@1: dev = motion[KEY_DOWN] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: motion[KEY_DOWN] = DIK_NUMPAD2; rlm@1: rlm@1: dev = motion[KEY_LEFT] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: motion[KEY_LEFT] = DIK_NUMPAD4; rlm@1: rlm@1: dev = motion[KEY_RIGHT] >> 8; rlm@1: if (dev < numDevices && dev >= 0) rlm@1: pDevices[dev].needed = 1; rlm@1: else rlm@1: motion[KEY_RIGHT] = DIK_NUMPAD6; rlm@1: } rlm@1: rlm@1: #define KEYDOWN(buffer, key) (buffer[key] & 0x80) rlm@1: rlm@1: static bool IsKeyDownAsync (WORD KeyIdent) rlm@1: { rlm@1: //if (KeyIdent == 0 || KeyIdent == VK_ESCAPE) // if it's the 'disabled' key, it's never pressed rlm@1: // return false; rlm@1: rlm@1: //if (!GUI.BackgroundInput && GUI.hWnd != GetForegroundWindow()) rlm@1: // return false; rlm@1: rlm@1: // the pause key is special, need this to catch all presses of it rlm@1: // Both GetKeyState and GetAsyncKeyState cannot catch it anyway, rlm@1: // so this should be handled in WM_KEYDOWN message. rlm@1: if (KeyIdent == VK_PAUSE) rlm@1: { rlm@1: return false; rlm@1: // if(GetAsyncKeyState(VK_PAUSE)) // not &'ing this with 0x8000 is intentional and necessary rlm@1: // return true; rlm@1: } rlm@1: rlm@1: if (KeyIdent == VK_CAPITAL || KeyIdent == VK_NUMLOCK || KeyIdent == VK_SCROLL) rlm@1: return ((GetKeyState(KeyIdent) & 0x01) != 0); rlm@1: else rlm@1: return ((GetAsyncKeyState(KeyIdent) & 0x8000) != 0); rlm@1: //return ((GetKeyState (KeyIdent) & 0x80) != 0); rlm@1: } rlm@1: rlm@1: static bool readKeyboard() rlm@1: { rlm@1: #ifndef USE_GETASYNCKEYSTATE_FOR_KEYBOARD rlm@1: if (pDevices[0].needed) rlm@1: { rlm@1: HRESULT hret = pDevices[0].device-> rlm@1: GetDeviceState(256, rlm@1: (LPVOID)pDevices[0].data); rlm@1: rlm@1: if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) rlm@1: { rlm@1: hret = pDevices[0].device->Acquire(); rlm@1: if (hret != DI_OK) rlm@1: return false; rlm@1: hret = pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data); rlm@1: } rlm@1: rlm@1: return hret == DI_OK; rlm@1: } rlm@1: #else rlm@1: for (int i = 0; i < sizeof(win_key_trans_table)/sizeof(win_key_trans_table[0]); i++) { rlm@1: pDevices[0].data[win_key_trans_table[i].dik] = IsKeyDownAsync(win_key_trans_table[i].vk) ? 0x80 : 0; rlm@1: } rlm@1: #endif rlm@1: return true; rlm@1: } rlm@1: rlm@1: static bool readJoystick(int joy) rlm@1: { rlm@1: if (pDevices[joy].needed) rlm@1: { rlm@1: if (pDevices[joy].isPolled) rlm@1: ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); rlm@1: rlm@1: HRESULT hret = pDevices[joy].device-> rlm@1: GetDeviceState(sizeof(DIJOYSTATE), rlm@1: (LPVOID)&pDevices[joy].state); rlm@1: rlm@1: if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) rlm@1: { rlm@1: hret = pDevices[joy].device->Acquire(); rlm@1: rlm@1: if (hret == DI_OK) rlm@1: { rlm@1: if (pDevices[joy].isPolled) rlm@1: ((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll(); rlm@1: rlm@1: hret = pDevices[joy].device-> rlm@1: GetDeviceState(sizeof(DIJOYSTATE), rlm@1: (LPVOID)&pDevices[joy].state); rlm@1: } rlm@1: } rlm@1: rlm@1: return hret == DI_OK; rlm@1: } rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: static void checkKeyboard() rlm@1: { rlm@1: // mham fix. Patch #1378104 rlm@1: UCHAR keystate[256]; rlm@1: HRESULT hret = pDevices[0].device->Acquire(); rlm@1: rlm@1: if (pDevices[0].first) rlm@1: { rlm@1: pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data); rlm@1: pDevices[0].first = FALSE; rlm@1: return; rlm@1: } rlm@1: rlm@1: hret = pDevices[0].device-> rlm@1: GetDeviceState(256, (LPVOID)keystate); rlm@1: rlm@1: if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) rlm@1: { rlm@1: return; rlm@1: } rlm@1: rlm@1: if (hret == DI_OK) rlm@1: { rlm@1: for (int i = 0; i < 256; i++) rlm@1: { rlm@1: if (keystate[i] == pDevices[0].data[i]) rlm@1: continue; rlm@1: if (KEYDOWN(keystate, i)) rlm@1: { rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, 0, i); rlm@1: break; rlm@1: } rlm@1: } rlm@1: } rlm@1: memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256); rlm@1: } rlm@1: rlm@1: static void checkJoypads() rlm@1: { rlm@1: DIDEVICEOBJECTINSTANCE di; rlm@1: rlm@1: ZeroMemory(&di, sizeof(DIDEVICEOBJECTINSTANCE)); rlm@1: rlm@1: di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); rlm@1: rlm@1: int i = 0; rlm@1: rlm@1: DIJOYSTATE joystick; rlm@1: rlm@1: for (i = 1; i < numDevices; i++) rlm@1: { rlm@1: HRESULT hret = pDevices[i].device->Acquire(); rlm@1: rlm@1: if (pDevices[i].isPolled) rlm@1: ((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll(); rlm@1: rlm@1: hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick); rlm@1: rlm@1: int j; rlm@1: rlm@1: if (pDevices[i].first) rlm@1: { rlm@1: memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); rlm@1: pDevices[i].first = FALSE; rlm@1: continue; rlm@1: } rlm@1: rlm@1: for (j = 0; j < pDevices[i].nButtons; j++) rlm@1: { rlm@1: if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j]) rlm@1: & joystick.rgbButtons[j]) & 0x80) rlm@1: { rlm@1: HWND focus = GetFocus(); rlm@1: rlm@1: SendMessage(focus, JOYCONFIG_MESSAGE, i, j+128); rlm@1: } rlm@1: } rlm@1: rlm@1: for (j = 0; j < pDevices[i].nAxes && j < 8; j++) rlm@1: { rlm@1: LONG value = pDevices[i].axis[j].center; rlm@1: LONG old = 0; rlm@1: switch (pDevices[i].axis[j].offset) rlm@1: { rlm@1: case DIJOFS_X: rlm@1: value = joystick.lX; rlm@1: old = pDevices[i].state.lX; rlm@1: break; rlm@1: case DIJOFS_Y: rlm@1: value = joystick.lY; rlm@1: old = pDevices[i].state.lY; rlm@1: break; rlm@1: case DIJOFS_Z: rlm@1: value = joystick.lZ; rlm@1: old = pDevices[i].state.lZ; rlm@1: break; rlm@1: case DIJOFS_RX: rlm@1: value = joystick.lRx; rlm@1: old = pDevices[i].state.lRx; rlm@1: break; rlm@1: case DIJOFS_RY: rlm@1: value = joystick.lRy; rlm@1: old = pDevices[i].state.lRy; rlm@1: break; rlm@1: case DIJOFS_RZ: rlm@1: value = joystick.lRz; rlm@1: old = pDevices[i].state.lRz; rlm@1: break; rlm@1: case DIJOFS_SLIDER(0): rlm@1: value = joystick.rglSlider[0]; rlm@1: old = pDevices[i].state.rglSlider[0]; rlm@1: break; rlm@1: case DIJOFS_SLIDER(1): rlm@1: value = joystick.rglSlider[1]; rlm@1: old = pDevices[i].state.rglSlider[1]; rlm@1: break; rlm@1: } rlm@1: if (value != old) rlm@1: { rlm@1: if (value < pDevices[i].axis[j].negative) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)); rlm@1: else if (value > pDevices[i].axis[j].positive) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1); rlm@1: } rlm@1: } rlm@1: rlm@1: for (j = 0; j < 4 && j < pDevices[i].nPovs; j++) rlm@1: { rlm@1: if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) rlm@1: { rlm@1: int state = getPovState(joystick.rgdwPOV[j]); rlm@1: rlm@1: if (state & POV_UP) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20); rlm@1: else if (state & POV_DOWN) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21); rlm@1: else if (state & POV_RIGHT) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22); rlm@1: else if (state & POV_LEFT) rlm@1: SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23); rlm@1: } rlm@1: } rlm@1: rlm@1: memcpy(&pDevices[i].state, &joystick, sizeof(joystick)); rlm@1: } rlm@1: } rlm@1: rlm@1: BOOL checkKey(LONG_PTR key) rlm@1: { rlm@1: LONG_PTR dev = (key >> 8); rlm@1: rlm@1: LONG_PTR k = (key & 255); rlm@1: rlm@1: if (dev == 0) rlm@1: { rlm@1: return KEYDOWN(pDevices[0].data, k); rlm@1: } rlm@1: else if (dev >= numDevices) rlm@1: { rlm@1: return FALSE; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (k < 16) rlm@1: { rlm@1: LONG_PTR axis = k >> 1; rlm@1: LONG value = pDevices[dev].axis[axis].center; rlm@1: switch (pDevices[dev].axis[axis].offset) rlm@1: { rlm@1: case DIJOFS_X: rlm@1: value = pDevices[dev].state.lX; rlm@1: break; rlm@1: case DIJOFS_Y: rlm@1: value = pDevices[dev].state.lY; rlm@1: break; rlm@1: case DIJOFS_Z: rlm@1: value = pDevices[dev].state.lZ; rlm@1: break; rlm@1: case DIJOFS_RX: rlm@1: value = pDevices[dev].state.lRx; rlm@1: break; rlm@1: case DIJOFS_RY: rlm@1: value = pDevices[dev].state.lRy; rlm@1: break; rlm@1: case DIJOFS_RZ: rlm@1: value = pDevices[dev].state.lRz; rlm@1: break; rlm@1: case DIJOFS_SLIDER(0): rlm@1: value = pDevices[dev].state.rglSlider[0]; rlm@1: break; rlm@1: case DIJOFS_SLIDER(1): rlm@1: value = pDevices[dev].state.rglSlider[1]; rlm@1: break; rlm@1: } rlm@1: rlm@1: if (k & 1) rlm@1: return value > pDevices[dev].axis[axis].positive; rlm@1: return value < pDevices[dev].axis[axis].negative; rlm@1: } rlm@1: else if (k < 48) rlm@1: { rlm@1: LONG_PTR hat = (k >> 2) & 3; rlm@1: int state = getPovState(pDevices[dev].state.rgdwPOV[hat]); rlm@1: BOOL res = FALSE; rlm@1: switch (k & 3) rlm@1: { rlm@1: case 0: rlm@1: res = state & POV_UP; rlm@1: break; rlm@1: case 1: rlm@1: res = state & POV_DOWN; rlm@1: break; rlm@1: case 2: rlm@1: res = state & POV_RIGHT; rlm@1: break; rlm@1: case 3: rlm@1: res = state & POV_LEFT; rlm@1: break; rlm@1: } rlm@1: return res; rlm@1: } rlm@1: else if (k >= 128) rlm@1: { rlm@1: return pDevices[dev].state.rgbButtons[k-128] & 0x80; rlm@1: } rlm@1: } rlm@1: rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: DirectInput::DirectInput() rlm@1: { rlm@1: dinputDLL = NULL; rlm@1: } rlm@1: rlm@1: DirectInput::~DirectInput() rlm@1: { rlm@1: saveSettings(); rlm@1: if (pDirectInput != NULL) rlm@1: { rlm@1: if (pDevices) rlm@1: { rlm@1: for (int i = 0; i < numDevices; i++) rlm@1: { rlm@1: if (pDevices[i].device) rlm@1: { rlm@1: pDevices[i].device->Unacquire(); rlm@1: pDevices[i].device->Release(); rlm@1: pDevices[i].device = NULL; rlm@1: } rlm@1: } rlm@1: free(pDevices); rlm@1: pDevices = NULL; rlm@1: } rlm@1: rlm@1: pDirectInput->Release(); rlm@1: pDirectInput = NULL; rlm@1: } rlm@1: rlm@1: if (dinputDLL) rlm@1: { rlm@1: /**/ ::FreeLibrary(dinputDLL); rlm@1: dinputDLL = NULL; rlm@1: } rlm@1: } rlm@1: rlm@1: bool DirectInput::initialize() rlm@1: { rlm@1: joyDebug = GetPrivateProfileInt("config", rlm@1: "joyDebug", rlm@1: 0, rlm@1: "VBA.ini"); rlm@1: dinputDLL = /**/ ::LoadLibrary("DINPUT.DLL"); rlm@1: HRESULT (WINAPI *DInputCreate)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *); rlm@1: if (dinputDLL != NULL) rlm@1: { rlm@1: DInputCreate = (HRESULT (WINAPI *)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *)) rlm@1: GetProcAddress(dinputDLL, "DirectInputCreateA"); rlm@1: rlm@1: if (DInputCreate == NULL) rlm@1: { rlm@1: directXMessage("DirectInputCreateA"); rlm@1: return false; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: directXMessage("DINPUT.DLL"); rlm@1: return false; rlm@1: } rlm@1: rlm@1: HRESULT hret = DInputCreate(AfxGetInstanceHandle(), rlm@1: DIRECTINPUT_VERSION, rlm@1: &pDirectInput, rlm@1: NULL); rlm@1: if (hret != DI_OK) rlm@1: { rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_CREATE), hret); rlm@1: return false; rlm@1: } rlm@1: rlm@1: hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK, rlm@1: DIEnumDevicesCallback2, rlm@1: NULL, rlm@1: DIEDFL_ATTACHEDONLY); rlm@1: rlm@1: pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo)); rlm@1: rlm@1: hret = pDirectInput->CreateDevice(GUID_SysKeyboard, &pDevices[0].device, NULL); rlm@1: pDevices[0].isPolled = false; rlm@1: pDevices[0].needed = true; rlm@1: pDevices[0].first = true; rlm@1: rlm@1: if (hret != DI_OK) rlm@1: { rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_CREATEDEVICE), hret); rlm@1: return false; rlm@1: } rlm@1: rlm@1: numDevices = 1; rlm@1: rlm@1: hret = pDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK, rlm@1: DIEnumDevicesCallback, rlm@1: NULL, rlm@1: DIEDFL_ATTACHEDONLY); rlm@1: rlm@1: // hret = pDevices[0].device->SetCooperativeLevel(hWindow, rlm@1: // DISCL_FOREGROUND| rlm@1: // DISCL_NONEXCLUSIVE); rlm@1: rlm@1: if (hret != DI_OK) rlm@1: { rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_LEVEL), hret); rlm@1: return false; rlm@1: } rlm@1: rlm@1: hret = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard); rlm@1: rlm@1: if (hret != DI_OK) rlm@1: { rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DATAFORMAT), hret); rlm@1: return false; rlm@1: } rlm@1: rlm@1: for (int i = 1; i < numDevices; i++) rlm@1: { rlm@1: pDevices[i].device->SetDataFormat(&c_dfDIJoystick); rlm@1: pDevices[i].needed = false; rlm@1: pDevices[i].first = true; rlm@1: currentDevice = &pDevices[i]; rlm@1: axisNumber = 0; rlm@1: currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS); rlm@1: currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV); rlm@1: if (joyDebug) rlm@1: { rlm@1: // don't translate. debug only rlm@1: winlog("Joystick %2d polled : %d\n", i, currentDevice->isPolled); rlm@1: winlog("Joystick %2d buttons : %d\n", i, currentDevice->nButtons); rlm@1: winlog("Joystick %2d povs : %d\n", i, currentDevice->nPovs); rlm@1: winlog("Joystick %2d axes : %d\n", i, currentDevice->nAxes); rlm@1: for (int j = 0; j < currentDevice->nAxes; j++) rlm@1: { rlm@1: winlog("Axis %2d offset : %08lx\n", j, currentDevice->axis[j]. rlm@1: offset); rlm@1: winlog("Axis %2d center : %08lx\n", j, currentDevice->axis[j]. rlm@1: center); rlm@1: winlog("Axis %2d negative : %08lx\n", j, currentDevice->axis[j]. rlm@1: negative); rlm@1: winlog("Axis %2d positive : %08lx\n", j, currentDevice->axis[j]. rlm@1: positive); rlm@1: } rlm@1: } rlm@1: rlm@1: currentDevice = NULL; rlm@1: } rlm@1: rlm@1: for (int i = 0; i < numDevices; i++) rlm@1: pDevices[i].device->Acquire(); rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool DirectInput::readDevices() rlm@1: { rlm@1: bool ok = true; rlm@1: for (int i = 0; i < numDevices; i++) rlm@1: { rlm@1: if (pDevices[i].needed) rlm@1: { rlm@1: ok = (i > 0 ? readJoystick(i) : readKeyboard()) || ok; rlm@1: } rlm@1: } rlm@1: return ok; rlm@1: } rlm@1: rlm@1: bool inputActive = true; // used to disable all input when the window is inactive rlm@1: rlm@1: u32 DirectInput::readDevice(int i, bool sensor) rlm@1: { rlm@1: // this old hack is evil rlm@1: extern int systemGetDefaultJoypad(); rlm@1: extern int32 gbSgbMode, gbSgbMultiplayer; rlm@1: if (!(gbSgbMode && gbSgbMultiplayer)) rlm@1: i = systemGetDefaultJoypad(); rlm@1: rlm@1: u32 res = 0; rlm@1: rlm@1: // manual input rlm@1: if (inputActive) rlm@1: { rlm@1: if (checkKey(joypad[i][KEY_BUTTON_A])) rlm@1: res |= BUTTON_MASK_A; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_B])) rlm@1: res |= BUTTON_MASK_B; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_SELECT])) rlm@1: res |= BUTTON_MASK_SELECT; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_START])) rlm@1: res |= BUTTON_MASK_START; rlm@1: if (checkKey(joypad[i][KEY_RIGHT])) rlm@1: res |= BUTTON_MASK_RIGHT; rlm@1: if (checkKey(joypad[i][KEY_LEFT])) rlm@1: res |= BUTTON_MASK_LEFT; rlm@1: if (checkKey(joypad[i][KEY_UP])) rlm@1: res |= BUTTON_MASK_UP; rlm@1: if (checkKey(joypad[i][KEY_DOWN])) rlm@1: res |= BUTTON_MASK_DOWN; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_R])) rlm@1: res |= BUTTON_MASK_R; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_L])) rlm@1: res |= BUTTON_MASK_L; rlm@1: rlm@1: // unused rlm@1: if (checkKey(motion[KEY_LEFT])) rlm@1: res |= BUTTON_MASK_LEFT_MOTION; rlm@1: else if (checkKey(motion[KEY_RIGHT])) rlm@1: res |= BUTTON_MASK_RIGHT_MOTION; rlm@1: if (checkKey(motion[KEY_UP])) rlm@1: res |= BUTTON_MASK_UP_MOTION; rlm@1: else if (checkKey(motion[KEY_DOWN])) rlm@1: res |= BUTTON_MASK_DOWN_MOTION; rlm@1: } rlm@1: rlm@1: u32 hackedButtons = 0; rlm@1: if (inputActive) rlm@1: { rlm@1: // the "non-button" buttons (what a hack!) rlm@1: if (checkKey(joypad[i][KEY_BUTTON_SPEED])) rlm@1: hackedButtons |= BUTTON_MASK_SPEED; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_CAPTURE])) rlm@1: hackedButtons |= BUTTON_MASK_CAPTURE; rlm@1: if (checkKey(joypad[i][KEY_BUTTON_GS])) rlm@1: hackedButtons |= BUTTON_MASK_GAMESHARK; rlm@1: } rlm@1: rlm@1: extern bool systemIsSpedUp(); rlm@1: if (systemIsSpedUp()) rlm@1: hackedButtons |= BUTTON_MASK_SPEED; rlm@1: rlm@1: return res | hackedButtons; rlm@1: } rlm@1: rlm@1: CString DirectInput::getKeyName(LONG_PTR key) rlm@1: { rlm@1: LONG_PTR d = (key >> 8); rlm@1: LONG_PTR k = key & 255; rlm@1: rlm@1: DIDEVICEOBJECTINSTANCE di; rlm@1: rlm@1: ZeroMemory(&di, sizeof(DIDEVICEOBJECTINSTANCE)); rlm@1: rlm@1: di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); rlm@1: rlm@1: CString winBuffer = winResLoadString(IDS_ERROR); rlm@1: rlm@1: if (d == 0) rlm@1: { rlm@1: pDevices[0].device->GetObjectInfo(&di, (DWORD)key, DIPH_BYOFFSET); rlm@1: winBuffer = di.tszName; rlm@1: } rlm@1: else if (d < numDevices) rlm@1: { rlm@1: if (k < 16) rlm@1: { rlm@1: if (k < 4) rlm@1: { rlm@1: switch (k) rlm@1: { rlm@1: case 0: rlm@1: winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d); rlm@1: break; rlm@1: case 1: rlm@1: winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d); rlm@1: break; rlm@1: case 2: rlm@1: winBuffer.Format(winResLoadString(IDS_JOY_UP), d); rlm@1: break; rlm@1: case 3: rlm@1: winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d); rlm@1: break; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: pDevices[d].device->GetObjectInfo(&di, rlm@1: pDevices[d].axis[k>>1].offset, rlm@1: DIPH_BYOFFSET); rlm@1: if (k & 1) rlm@1: winBuffer.Format("Joy %d %s +", d, di.tszName); rlm@1: else rlm@1: winBuffer.Format("Joy %d %s -", d, di.tszName); rlm@1: } rlm@1: } rlm@1: else if (k < 48) rlm@1: { rlm@1: LONG_PTR hat = (k >> 2) & 3; rlm@1: pDevices[d].device->GetObjectInfo(&di, rlm@1: (DWORD)DIJOFS_POV(hat), rlm@1: DIPH_BYOFFSET); rlm@1: char * dir = "up"; rlm@1: LONG_PTR dd = k & 3; rlm@1: if (dd == 1) rlm@1: dir = "down"; rlm@1: else if (dd == 2) rlm@1: dir = "right"; rlm@1: else if (dd == 3) rlm@1: dir = "left"; rlm@1: winBuffer.Format("Joy %d %s %s", d, di.tszName, dir); rlm@1: } rlm@1: else rlm@1: { rlm@1: pDevices[d].device->GetObjectInfo(&di, rlm@1: (DWORD)DIJOFS_BUTTON(k-128), rlm@1: DIPH_BYOFFSET); rlm@1: winBuffer.Format(winResLoadString(IDS_JOY_BUTTON), d, di.tszName); rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: // Joystick isn't plugged in. We can't decipher k, so just show its value. rlm@1: winBuffer.Format("Joy %d (%d)", d, k); rlm@1: } rlm@1: rlm@1: return winBuffer; rlm@1: } rlm@1: rlm@1: void DirectInput::checkKeys() rlm@1: { rlm@1: ::checkKeys(); rlm@1: } rlm@1: rlm@1: Input *newDirectInput() rlm@1: { rlm@1: return new DirectInput; rlm@1: } rlm@1: rlm@1: void DirectInput::checkDevices() rlm@1: { rlm@1: checkJoypads(); rlm@1: checkKeyboard(); rlm@1: } rlm@1: rlm@1: void DirectInput::activate() rlm@1: { rlm@1: for (int i = 0; i < numDevices; i++) rlm@1: { rlm@1: if (pDevices != NULL && pDevices[i].device != NULL) rlm@1: pDevices[i].device->Acquire(); rlm@1: } rlm@1: } rlm@1: rlm@1: void DirectInput::loadSettings() rlm@1: { rlm@1: winReadKeys(); rlm@1: } rlm@1: rlm@1: void DirectInput::saveSettings() rlm@1: { rlm@1: winSaveKeys(); rlm@1: } rlm@1: