#include "ffeapi.h" #include "win32api.h" #include "ffecfg.h" #include #include #include #define DIRECTINPUT_VERSION 0x500 #include #define INITGUID #include #include static LPDIRECTINPUT pDInput = NULL; static LPDIRECTINPUTDEVICE pDIMouse = NULL; static LPDIRECTINPUTDEVICE pDIKeyb = NULL; static LPDIRECTINPUTDEVICE2 pDIJoy = NULL; static long xmick = 0; static long ymick = 0; static int mflags = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; static int sensitivity = 100; static int repeatrate = 50; static int repeatdelay = 300; static int joyXRem = 0; static int joyYRem = 0; static int joyXVal = 0; static int joyYVal = 0; static ULONG joyLastTime = 0; static int pJoyXTable[1024]; static int pJoyYTable[1024]; #include static FILE *pLog = NULL; void Win32InputReacquire (void) { if (pDIMouse) pDIMouse->Acquire(); if (pDIKeyb) pDIKeyb->Acquire(); if (pDIJoy) pDIJoy->Acquire(); } void Win32SetMouseExclusive (void) { mflags = DISCL_FOREGROUND | DISCL_EXCLUSIVE; if (pDIMouse) { pDIMouse->Unacquire(); pDIMouse->SetCooperativeLevel (Win32GetWnd(), mflags); pDIMouse->Acquire(); } } void Win32SetMouseNorm (void) { mflags = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE; if (pDIMouse) { pDIMouse->Unacquire(); pDIMouse->SetCooperativeLevel (Win32GetWnd(), mflags); pDIMouse->Acquire(); } } extern "C" long InputMouseReadButtons (void) { DIMOUSESTATE mstate; long buttons = 0; int rval; if (pDIMouse == NULL) return 0; rval = pDIMouse->GetDeviceState (sizeof(mstate), (void *)&mstate); if (rval != DI_OK) return 0; xmick += mstate.lX; ymick += mstate.lY; if (mstate.rgbButtons[0]) buttons |= 1; if (mstate.rgbButtons[1]) buttons |= 2; return buttons; } extern "C" void InputMouseReadMickeys (long *pXMick, long *pYMick) { DIMOUSESTATE mstate; if (pDIMouse == NULL) { *pXMick = 0; *pYMick = 0; return; } int rval = pDIMouse->GetDeviceState (sizeof(mstate), (void *)&mstate); if (rval != DI_OK) { *pXMick = 0; *pYMick = 0; return; } *pXMick = ((mstate.lX + xmick) * sensitivity) / 100; *pYMick = ((mstate.lY + ymick) * sensitivity) / 100; xmick = 0; ymick = 0; } unsigned char pKeybConvTable[256] = { 0, DIK_ESCAPE, DIK_1, DIK_2, DIK_3, DIK_4, DIK_5, DIK_6, DIK_7, DIK_8, DIK_9, DIK_0, DIK_MINUS, DIK_EQUALS, DIK_BACK, DIK_TAB, DIK_Q, DIK_W, DIK_E, DIK_R, DIK_T, DIK_Y, DIK_U, DIK_I, DIK_O, DIK_P, DIK_LBRACKET, DIK_RBRACKET, DIK_RETURN, DIK_LCONTROL, DIK_A, DIK_S, DIK_D, DIK_F, DIK_G, DIK_H, DIK_J, DIK_K, DIK_L, DIK_SEMICOLON, DIK_APOSTROPHE, DIK_GRAVE, DIK_LSHIFT, DIK_BACKSLASH, DIK_Z, DIK_X, DIK_C, DIK_V, DIK_B, DIK_N, DIK_M, DIK_COMMA, DIK_PERIOD, DIK_SLASH, DIK_RSHIFT, DIK_MULTIPLY, DIK_LMENU, DIK_SPACE, DIK_CAPITAL, DIK_F1, DIK_F2, DIK_F3, DIK_F4, DIK_F5, DIK_F6, DIK_F7, DIK_F8, DIK_F9, DIK_F10, DIK_NUMLOCK, DIK_SCROLL, DIK_NUMPAD7, DIK_NUMPAD8, DIK_NUMPAD9, DIK_SUBTRACT, DIK_NUMPAD4, DIK_NUMPAD5, DIK_NUMPAD6, DIK_ADD, DIK_NUMPAD1, DIK_NUMPAD2, DIK_NUMPAD3, DIK_NUMPAD0, DIK_DECIMAL, 0, 0, 0, DIK_F11, DIK_F12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60-0x67 0, 0, 0, 0, 0, 0, 0, 0, // 0x68-0x6f 0, 0, 0, 0, 0, 0, 0, 0, // 0x70-0x77 0, 0, 0, 0, 0, 0, 0, 0, // 0x78-0x7f 0, 0, 0, 0, 0, 0, 0, 0, // 0x80-0x87 0, 0, 0, 0, 0, 0, 0, 0, // 0x88-0x8f 0, 0, 0, 0, 0, 0, 0, 0, // 0x90-0x97 0, 0, 0, 0, DIK_NUMPADENTER, DIK_RCONTROL, 0, 0, // 0x98-0x9f 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0-0xa7 0, 0, 0, 0, 0, 0, 0, 0, // 0xa8-0xaf 0, 0, 0, 0, 0, DIK_DIVIDE, 0, DIK_SYSRQ, // 0xb0-0xb7 DIK_RMENU, 0, 0, 0, 0, 0, 0, 0, // 0xb8-0xbf 0, 0, 0, 0, 0, 0, 0, DIK_HOME, // 0xc0-0xc7 DIK_UP, DIK_PRIOR, 0, DIK_LEFT, 0, DIK_RIGHT, 0, DIK_END, // 0xc8-0xcf DIK_DOWN, DIK_NEXT, DIK_INSERT, DIK_DELETE, 0, 0, 0, 0, // 0xd0-0xd7 0, 0, 0, DIK_LWIN, DIK_RWIN, DIK_APPS, 0, 0, // 0xd8-0xdf 0, 0, 0, 0, 0, 0, 0, 0, // 0xe0-0xe7 0, 0, 0, 0, 0, 0, 0, 0, // 0xe8-0xef 0, 0, 0, 0, 0, 0, 0, 0, // 0xf0-0xf7 0, 0, 0, 0, 0, 0, 0, 0, // 0xf8-0xff }; static UCHAR pKeybStates[256]; static int keybLastKey = 0xff; static ULONG pKeybTimes[256]; void InputKeybReadStates (UCHAR *pKeys) { int i, rval; UCHAR pCur[256]; memset (pKeys, 0x80, 256); if (pDIKeyb == NULL) return; rval = pDIKeyb->GetDeviceState (256, (void *)pCur); if (rval != DI_OK) return; for (i=0; i<256; i++) { if (pCur[pKeybConvTable[i]] & 0x80) { if (pKeybStates[i] == 0x80) { // Initial press keybLastKey = i; pKeybStates[i] = 0; pKeybTimes[i] = TimerGetTimeStamp() + repeatdelay; } else if (pKeybStates[i] == 0) { // hold if (pKeybTimes[i] < TimerGetTimeStamp()) { pKeybStates[i] = 0xff; } } if (pKeybStates[i] == 0xff) { // Repeat if (pKeybTimes[i] < TimerGetTimeStamp()) { keybLastKey = i; pKeybTimes[i] += repeatrate; } } } else pKeybStates[i] = 0x80; } for (i=0; i<256; i++) { if (pKeybStates[i] == 0x80) pKeys[i] = 0x80; else pKeys[i] = 0x0; } } extern "C" long InputKeybGetLastKey (void) { return keybLastKey; } extern "C" void InputKeybSetLastKey (long key) { keybLastKey = key; } static BOOL CALLBACK JoyEnumFunc (LPCDIDEVICEINSTANCE lpddi, LPVOID pGuid) { *(GUID *)pGuid = lpddi->guidInstance; return DIENUM_STOP; } void InputInit (void) { int rval, i; CfgStruct cfg; GUID joyGuid; LPDIRECTINPUTDEVICE pDIJoy1; if (pDInput == NULL) { rval = DirectInputCreate (Win32GetInst(), DIRECTINPUT_VERSION, &pDInput, NULL); if (rval != DI_OK) return; } CfgOpen (&cfg, __CONFIGFILE__); CfgFindSection (&cfg, "MOUSE"); CfgGetKeyVal (&cfg, "sensitivity", &sensitivity); CfgFindSection (&cfg, "KEYBOARD"); CfgGetKeyVal (&cfg, "repeatrate", &repeatrate); CfgGetKeyVal (&cfg, "repeatdelay", &repeatdelay); CfgClose (&cfg); if (pDIMouse == NULL) { rval = pDInput->CreateDevice (GUID_SysMouse, &pDIMouse, NULL); if (rval != DI_OK) return; rval = pDIMouse->SetCooperativeLevel (Win32GetWnd(), mflags); rval = pDIMouse->SetDataFormat (&c_dfDIMouse); rval = pDIMouse->Acquire(); } if (pDIKeyb == NULL) { rval = pDInput->CreateDevice (GUID_SysKeyboard, &pDIKeyb, NULL); if (rval != DI_OK) return; rval = pDIKeyb->SetCooperativeLevel (Win32GetWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); rval = pDIKeyb->SetDataFormat (&c_dfDIKeyboard); rval = pDIKeyb->Acquire(); memset (pKeybStates, 0x80, 256); } int xexpi = 20, yexpi = 20; int xmax = 512, ymax = 512; int xdeadzone = 20, ydeadzone = 20; int xmaxzone = 20, ymaxzone = 20; int enabled = 0, pollfreq = 10; CfgOpen (&cfg, __CONFIGFILE__); CfgFindSection (&cfg, "JOYSTICK"); CfgGetKeyVal (&cfg, "enabled", &enabled); CfgGetKeyVal (&cfg, "pollfreq", &pollfreq); CfgGetKeyVal (&cfg, "xexp", &xexpi); CfgGetKeyVal (&cfg, "yexp", &yexpi); CfgGetKeyVal (&cfg, "xmax", &xmax); CfgGetKeyVal (&cfg, "ymax", &ymax); CfgGetKeyVal (&cfg, "xdeadzone", &xdeadzone); CfgGetKeyVal (&cfg, "ydeadzone", &ydeadzone); CfgGetKeyVal (&cfg, "xmaxzone", &xmaxzone); CfgGetKeyVal (&cfg, "ymaxzone", &ymaxzone); CfgClose (&cfg); if (enabled == 0) return; if (pDIJoy != NULL) return; rval = pDInput->EnumDevices (DIDEVTYPE_JOYSTICK, JoyEnumFunc, &joyGuid, DIEDFL_ATTACHEDONLY); if (rval != DI_OK) return; rval = pDInput->CreateDevice (joyGuid, &pDIJoy1, NULL); if (rval != DI_OK) return; rval = pDIJoy1->QueryInterface (IID_IDirectInputDevice2, (void **)&pDIJoy); if (rval != DI_OK) return; pDIJoy1->Release(); pDIJoy->SetCooperativeLevel (Win32GetWnd(), DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); pDIJoy->SetDataFormat (&c_dfDIJoystick); DIPROPRANGE dirn; DIPROPDWORD didw; dirn.diph.dwSize = sizeof(DIPROPRANGE); dirn.diph.dwHeaderSize = sizeof(DIPROPHEADER); dirn.diph.dwHow = DIPH_BYOFFSET; didw.diph.dwSize = sizeof(DIPROPDWORD); didw.diph.dwHeaderSize = sizeof(DIPROPHEADER); didw.diph.dwHow = DIPH_BYOFFSET; dirn.lMin = -512; dirn.lMax = +511; dirn.diph.dwObj = DIJOFS_X; pDIJoy->SetProperty (DIPROP_RANGE, &dirn.diph); didw.dwData = 0; pDIJoy->SetProperty (DIPROP_DEADZONE, &didw.diph); didw.dwData = 10000; pDIJoy->SetProperty (DIPROP_SATURATION, &didw.diph); dirn.diph.dwObj = DIJOFS_Y; pDIJoy->SetProperty (DIPROP_RANGE, &dirn.diph); didw.dwData = 0; pDIJoy->SetProperty (DIPROP_DEADZONE, &didw.diph); didw.dwData = 10000; pDIJoy->SetProperty (DIPROP_SATURATION, &didw.diph); pDIJoy->Acquire(); joyLastTime = TimerGetTimeStamp(); double xexp = (double)xexpi / 10.0; double yexp = (double)yexpi / 10.0; double xdiv = 512 - xdeadzone - xmaxzone; double ydiv = 512 - ydeadzone - ymaxzone; for (i=0; iUnacquire(); pDIMouse->Release(); pDIMouse = NULL; } if (pDIKeyb != NULL) { pDIKeyb->Unacquire(); pDIKeyb->Release(); pDIKeyb = NULL; } if (pDIJoy != NULL) { pDIJoy->Unacquire(); pDIJoy->Release(); pDIJoy = NULL; } if (pDInput != NULL) { pDInput->Release(); pDInput = NULL; } } extern "C" void InputJoyReadPos (long *pXPos, long *pYPos) { if (!pDIJoy) { *pXPos = *pYPos = 0; return; } DIJOYSTATE state; int xval, yval, rval; ULONG joyCurTime = TimerGetTimeStamp(); ULONG joyTickCount = (joyCurTime - joyLastTime) / 5; memset (&state, 0, sizeof(state)); pDIJoy->Poll(); rval = pDIJoy->GetDeviceState (sizeof(state), (void *)&state); if (rval != DI_OK) { *pXPos = *pYPos = 0; return; } xval = pJoyXTable[state.lX+512]; yval = pJoyYTable[state.lY+512]; if (xval == 0) joyXRem = 0; if (yval == 0) joyYRem = 0; xval = xval * joyTickCount + joyXRem; joyXRem = xval & 0x800000ff; if (joyXRem < 0) joyXRem |= 0xffffff00; xval = (xval - joyXRem) >> 8; yval = yval * joyTickCount + joyYRem; joyYRem = yval & 0x800000ff; if (joyYRem < 0) joyYRem |= 0xffffff00; yval = (yval - joyYRem) >> 8; joyLastTime = joyCurTime; *pXPos = xval; *pYPos = yval; } extern "C" long InputJoyReadButtons (void) { if (!pDIJoy) return 0; DIJOYSTATE state; int rval, buttons = 0; memset (&state, 0, sizeof(state)); rval = pDIJoy->GetDeviceState (sizeof(state), (void *)&state); if (rval != DI_OK) return 0; if (state.rgbButtons[0]) buttons |= 1; if (state.rgbButtons[1]) buttons |= 2; if (state.rgbButtons[2]) buttons |= 4; if (state.rgbButtons[3]) buttons |= 8; return buttons; }