annotate src/win32/DirectInput.cpp @ 5:8fe0c57e53d2

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