Lilypad/DualShock3.cpp (255 lines of code) (raw):

#include "Global.h" #include "InputManager.h" #include <xinput.h> typedef struct { float SCP_UP; float SCP_RIGHT; float SCP_DOWN; float SCP_LEFT; float SCP_LX; float SCP_LY; float SCP_L1; float SCP_L2; float SCP_L3; float SCP_RX; float SCP_RY; float SCP_R1; float SCP_R2; float SCP_R3; float SCP_T; float SCP_C; float SCP_X; float SCP_S; float SCP_SELECT; float SCP_START; float SCP_PS; } SCP_EXTN; typedef void (CALLBACK *_XInputEnable)(BOOL enable); typedef DWORD(CALLBACK *_XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState); typedef DWORD(CALLBACK *_XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration); typedef DWORD(CALLBACK *_XInputGetExtended)(DWORD dwUserIndex, SCP_EXTN* pPressure); static _XInputEnable pXInputEnable = 0; static _XInputGetState pXInputGetState = 0; static _XInputSetState pXInputSetState = 0; static _XInputGetExtended pXInputGetExtended = 0; static int xInputActiveCount = 0; __forceinline int FloatToValue(float f) { return (int)(f * ((float)(FULLY_DOWN))); } class DualShock3Device : public Device { protected: // Cached last vibration values by pad and motor. // Need this, as only one value is changed at a time. int ps2Vibration[2][4][2]; // Minor optimization - cache last set vibration values // When there's no change, no need to do anything. XINPUT_VIBRATION xInputVibration; public: int index; DualShock3Device(int index, wchar_t *name) : Device(DS3, OTHER, name) { memset(ps2Vibration, 0, sizeof(ps2Vibration)); memset(&xInputVibration, 0, sizeof(xInputVibration)); this->index = index; for (int i = 0; i < 12; i++) { AddPhysicalControl(PRESSURE_BTN, i, 0); } for (int i = 12; i < 16; i++) { AddPhysicalControl(PSHBTN, i, 0); } for (int i = 16; i < 20; i++) { AddPhysicalControl(ABSAXIS, i, 0); } AddPhysicalControl(PSHBTN, 20, 0); AddFFAxis(L"Slow Motor", 0); AddFFAxis(L"Fast Motor", 1); AddFFEffectType(L"Constant Effect", L"Constant", EFFECT_CONSTANT); } wchar_t *GetPhysicalControlName(PhysicalControl *control) { const static wchar_t *names[] = { L"Up", L"Right", L"Down", L"Left", L"Triangle", L"Circle", L"Cross", L"Square", L"L1", L"L2", L"R1", L"R2", L"L3", L"R3", L"Select", L"Start", L"L-Stick X", L"L-Stick Y", L"R-Stick X", L"R-Stick Y", L"PS", }; unsigned int i = (unsigned int)(control - physicalControls); if (i < 21) return (wchar_t*)names[i]; return Device::GetPhysicalControlName(control); } int Activate(InitInfo *initInfo) { if (active) Deactivate(); if (!xInputActiveCount) pXInputEnable(1); xInputActiveCount++; active = 1; AllocState(); return 1; } int Update() { if (!active) return 0; SCP_EXTN extn; if (pXInputGetExtended(index, &extn) != ERROR_SUCCESS) { Deactivate(); return 0; } physicalControlState[0] = FloatToValue(extn.SCP_UP); physicalControlState[1] = FloatToValue(extn.SCP_RIGHT); physicalControlState[2] = FloatToValue(extn.SCP_DOWN); physicalControlState[3] = FloatToValue(extn.SCP_LEFT); physicalControlState[4] = FloatToValue(extn.SCP_T); physicalControlState[5] = FloatToValue(extn.SCP_C); physicalControlState[6] = FloatToValue(extn.SCP_X); physicalControlState[7] = FloatToValue(extn.SCP_S); physicalControlState[8] = FloatToValue(extn.SCP_L1); physicalControlState[9] = FloatToValue(extn.SCP_L2); physicalControlState[10] = FloatToValue(extn.SCP_R1); physicalControlState[11] = FloatToValue(extn.SCP_R2); physicalControlState[12] = FloatToValue(extn.SCP_L3); physicalControlState[13] = FloatToValue(extn.SCP_R3); physicalControlState[14] = FloatToValue(extn.SCP_SELECT); physicalControlState[15] = FloatToValue(extn.SCP_START); physicalControlState[16] = FloatToValue(extn.SCP_LX); physicalControlState[17] = FloatToValue(extn.SCP_LY); physicalControlState[18] = FloatToValue(extn.SCP_RX); physicalControlState[19] = FloatToValue(extn.SCP_RY); physicalControlState[20] = FloatToValue(extn.SCP_PS); return 1; } void SetEffects(unsigned char port, unsigned int slot, unsigned char motor, unsigned char force) { int newVibration[2] = { 0, 0 }; ps2Vibration[port][slot][motor] = force; for (int p = 0; p < 2; p++) { for (int s = 0; s < 4; s++) { for (int i = 0; i < pads[p][s].numFFBindings; i++) { ForceFeedbackBinding *ffb = &pads[p][s].ffBindings[i]; newVibration[0] += (int)((ffb->axes[0].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); newVibration[1] += (int)((ffb->axes[1].force * (__int64)ps2Vibration[p][s][ffb->motor]) / 255); } } } newVibration[0] = abs(newVibration[0]); if (newVibration[0] > 65535) newVibration[0] = 65535; newVibration[1] = abs(newVibration[1]); if (newVibration[1] > 65535) newVibration[1] = 65535; if (newVibration[0] != xInputVibration.wLeftMotorSpeed || newVibration[1] != xInputVibration.wRightMotorSpeed) { XINPUT_VIBRATION newv = { newVibration[0], newVibration[1] }; if (pXInputSetState(index, &newv) == ERROR_SUCCESS) { xInputVibration = newv; } } } void SetEffect(ForceFeedbackBinding *binding, unsigned char force) { PadBindings pBackup = pads[0][0]; pads[0][0].ffBindings = binding; pads[0][0].numFFBindings = 1; SetEffects(0, 0, binding->motor, force); pads[0][0] = pBackup; } void Deactivate() { memset(&xInputVibration, 0, sizeof(xInputVibration)); memset(ps2Vibration, 0, sizeof(ps2Vibration)); pXInputSetState(index, &xInputVibration); FreeState(); if (active) { if (!--xInputActiveCount) { pXInputEnable(0); } active = 0; } } ~DualShock3Device() { } }; void EnumDualShock3s() { wchar_t name[30]; XINPUT_STATE state; SCP_EXTN extn; if (!pXInputSetState) { if (pXInputGetExtended) return; HMODULE hMod = 0; if (hMod = LoadLibraryW(L"XInput1_3.dll")) { if ((pXInputEnable = (_XInputEnable)GetProcAddress(hMod, "XInputEnable")) && (pXInputGetState = (_XInputGetState)GetProcAddress(hMod, "XInputGetState")) && (pXInputSetState = (_XInputSetState)GetProcAddress(hMod, "XInputSetState"))) { pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended"); } } if (!pXInputGetExtended) { pXInputGetExtended = (_XInputGetExtended)-1; return; } } pXInputEnable(1); for (int index = 0; index < 4; index++) { if (pXInputGetState(index, &state) == ERROR_SUCCESS && pXInputGetExtended(index, &extn) == ERROR_SUCCESS) { wsprintfW(name, L"DualShock 3 #%i", index + 1); dm->AddDevice(new DualShock3Device(index, name)); } } pXInputEnable(0); } int DualShock3Possible() { int retVal = 0; HMODULE hMod = 0; if (hMod = LoadLibraryW(L"XInput1_3.dll")) { _XInputGetExtended pXInputGetExtended = 0; if (pXInputGetExtended = (_XInputGetExtended)GetProcAddress(hMod, "XInputGetExtended")) { SCP_EXTN extn; for (int index = 0; index < 4; index++) { if (pXInputGetExtended(index, &extn) == ERROR_SUCCESS) { retVal = 1; break; } } } FreeLibrary(hMod); } return retVal; } void UninitLibUsb() { return; }