From dfa77e92078d911f99d7425e9c08af7e63ffd1fa Mon Sep 17 00:00:00 2001 From: Nik Henson Date: Tue, 1 Nov 2011 23:24:37 +0000 Subject: [PATCH] Added support for joystick sliders to input system. Added extra debugging output to calibration input detection routine (activated by pressing Shift). --- Src/Inputs/InputSystem.cpp | 152 +++++++++++++++++--------- Src/Inputs/InputSystem.h | 20 +++- Src/OSD/SDL/SDLInputSystem.cpp | 1 - Src/OSD/Windows/DirectInputSystem.cpp | 71 ++++++++---- 4 files changed, 171 insertions(+), 73 deletions(-) diff --git a/Src/Inputs/InputSystem.cpp b/Src/Inputs/InputSystem.cpp index ab345ea..27564e1 100644 --- a/Src/Inputs/InputSystem.cpp +++ b/Src/Inputs/InputSystem.cpp @@ -201,7 +201,7 @@ const char *CInputSystem::s_validKeyNames[] = MousePartsStruct CInputSystem::s_mseParts[] = { - // X Axis (Axis 0) + // X Axis (Axis 1) { "XAXIS", MouseXAxis }, { "XAXIS_INV", MouseXAxisInv }, { "XAXIS_POS", MouseXAxisPos }, @@ -213,7 +213,7 @@ MousePartsStruct CInputSystem::s_mseParts[] = { "AXIS1_POS", MouseXAxisPos }, { "AXIS1_NEG", MouseXAxisNeg }, - // Y Axis (Axis 1) + // Y Axis (Axis 2) { "YAXIS", MouseYAxis }, { "YAXIS_INV", MouseYAxisInv }, { "YAXIS_POS", MouseYAxisPos }, @@ -225,7 +225,7 @@ MousePartsStruct CInputSystem::s_mseParts[] = { "AXIS2_POS", MouseYAxisPos }, { "AXIS2_NEG", MouseYAxisNeg }, - // Z/Wheel Axis (Axis 2) + // Z/Wheel Axis (Axis 3) { "ZAXIS", MouseZAxis }, { "ZAXIS_INV", MouseZAxisInv }, { "ZAXIS_POS", MouseZAxisPos }, @@ -237,7 +237,7 @@ MousePartsStruct CInputSystem::s_mseParts[] = { "AXIS3_POS", MouseZAxisPos }, { "AXIS3_NEG", MouseZAxisNeg }, - // Left/Middle/Right Buttons (Buttons 0-2) + // Left/Middle/Right Buttons (Buttons 1-3) { "LEFT_BUTTON", MouseButtonLeft }, { "BUTTON1", MouseButtonLeft }, { "MIDDLE_BUTTON", MouseButtonMiddle }, @@ -245,7 +245,7 @@ MousePartsStruct CInputSystem::s_mseParts[] = { "RIGHT_BUTTON", MouseButtonRight }, { "BUTTON3", MouseButtonRight }, - // Extra Buttons (Buttons 3 & 4) + // Extra Buttons (Buttons 4 & 5) { "BUTTONX1", MouseButtonX1 }, { "BUTTON4", MouseButtonX1 }, { "BUTTONX2", MouseButtonX2 }, @@ -257,7 +257,7 @@ MousePartsStruct CInputSystem::s_mseParts[] = JoyPartsStruct CInputSystem::s_joyParts[] = { - // X-Axis (Axis 0) + // X-Axis (Axis 1) { "XAXIS", JoyXAxis }, { "XAXIS_INV", JoyXAxisInv }, { "XAXIS_POS", JoyXAxisPos }, @@ -269,7 +269,7 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS1_POS", JoyXAxisPos }, { "AXIS1_NEG", JoyXAxisNeg }, - // Y-Axis (Axis 1) + // Y-Axis (Axis 2) { "YAXIS", JoyYAxis }, { "YAXIS_INV", JoyYAxisInv }, { "YAXIS_POS", JoyYAxisPos }, @@ -281,7 +281,7 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS2_POS", JoyYAxisPos }, { "AXIS2_NEG", JoyYAxisNeg }, - // Z-Axis (Axis 2) + // Z-Axis (Axis 3) { "ZAXIS", JoyZAxis }, { "ZAXIS_INV", JoyZAxisInv }, { "ZAXIS_POS", JoyZAxisPos }, @@ -291,7 +291,7 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS3_POS", JoyZAxisPos }, { "AXIS3_NEG", JoyZAxisNeg }, - // RX-Axis (Axis 3) + // RX-Axis (Axis 4) { "RXAXIS", JoyRXAxis }, { "RXAXIS_INV", JoyRXAxisInv }, { "RXAXIS_POS", JoyRXAxisPos }, @@ -301,7 +301,7 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS4_POS", JoyRXAxisPos }, { "AXIS4_NEG", JoyRXAxisNeg }, - // RY-Axis (Axis 4) + // RY-Axis (Axis 5) { "RYAXIS", JoyRYAxis }, { "RYAXIS_INV", JoyRYAxisInv }, { "RYAXIS_POS", JoyRYAxisPos }, @@ -311,7 +311,7 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS5_POS", JoyRYAxisPos }, { "AXIS5_NEG", JoyRYAxisNeg }, - // RZ-Axis (Axis 5) + // RZ-Axis (Axis 6) { "RZAXIS", JoyRZAxis }, { "RZAXIS_INV", JoyRZAxisInv }, { "RZAXIS_POS", JoyRZAxisPos }, @@ -321,31 +321,51 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { "AXIS6_POS", JoyRZAxisPos }, { "AXIS6_NEG", JoyRZAxisNeg }, - // POV Hat 0 + // Slider 1 (Axis 7) + { "SLIDER1", JoyS1Axis }, + { "SLIDER1_INV", JoyS1AxisInv }, + { "SLIDER1_POS", JoyS1AxisPos }, + { "SLIDER1_NEG", JoyS1AxisNeg }, + { "AXIS7", JoyS1Axis }, + { "AXIS7_INV", JoyS1AxisInv }, + { "AXIS7_POS", JoyS1AxisPos }, + { "AXIS7_NEG", JoyS1AxisNeg }, + + // Slider 2 (Axis 8) + { "SLIDER2", JoyS1Axis }, + { "SLIDER2_INV", JoyS1AxisInv }, + { "SLIDER2_POS", JoyS1AxisPos }, + { "SLIDER2_NEG", JoyS1AxisNeg }, + { "AXIS8", JoyS1Axis }, + { "AXIS8_INV", JoyS1AxisInv }, + { "AXIS8_POS", JoyS1AxisPos }, + { "AXIS8_NEG", JoyS1AxisNeg }, + + // POV Hat 1 { "POV1_UP", JoyPOV0Up }, { "POV1_DOWN", JoyPOV0Down }, { "POV1_LEFT", JoyPOV0Left }, { "POV1_RIGHT", JoyPOV0Right }, - // POV Hat 1 + // POV Hat 2 { "POV2_UP", JoyPOV1Up }, { "POV2_DOWN", JoyPOV1Down }, { "POV2_LEFT", JoyPOV1Left }, { "POV2_RIGHT", JoyPOV1Right }, - // POV Hat 2 + // POV Hat 3 { "POV3_UP", JoyPOV2Up }, { "POV3_DOWN", JoyPOV2Down }, { "POV3_LEFT", JoyPOV2Left }, { "POV3_RIGHT", JoyPOV2Right }, - // POV Hat 3 + // POV Hat 4 { "POV4_UP", JoyPOV3Up }, { "POV4_DOWN", JoyPOV3Down }, { "POV4_LEFT", JoyPOV3Left }, { "POV4_RIGHT", JoyPOV3Right }, - // Buttons 0-31 + // Buttons 1-32 { "BUTTON1", JoyButton0 }, { "BUTTON2", JoyButton1 }, { "BUTTON3", JoyButton2 }, @@ -383,11 +403,13 @@ JoyPartsStruct CInputSystem::s_joyParts[] = { NULL, JoyUnknown } }; -const char *CInputSystem::s_axisNames[] = { "X", "Y", "Z", "RX", "RY", "RZ" }; +const char *CInputSystem::s_axisIds[] = { "X", "Y", "Z", "RX", "RY", "RZ", "S1", "S2" }; + +const char *CInputSystem::s_axisNames[] = { "X-Axis", "Y-Axis", "Z-Axis", "RX-Axis", "RY-Axis", "RZ-Axis", "Slider1", "Slider2" }; const char *CInputSystem::GetDefaultAxisName(int axisNum) { - return (axisNum >= 0 && axisNum < 6 ? s_axisNames[axisNum] : ""); + return (axisNum >= 0 && axisNum < NUM_JOY_AXES ? s_axisNames[axisNum] : ""); } CInputSystem::CInputSystem(const char *systemName) : @@ -1039,8 +1061,8 @@ CInputSource *CInputSystem::ParseSingleSource(string str) void CInputSystem::PrintKeySettings(int kbdNum, KeySettings *settings) { - printf(" Sensitivity = %d %%\n", settings->sensitivity); - printf(" Decay Speed = %d %%\n", settings->decaySpeed); + printf(" Sensitivity = %u %%\n", settings->sensitivity); + printf(" Decay Speed = %u %%\n", settings->decaySpeed); } KeySettings *CInputSystem::ReadKeySettings(CINIFile *ini, const char *section, int kbdNum) @@ -1079,10 +1101,7 @@ void CInputSystem::WriteKeySettings(CINIFile *ini, const char *section, KeySetti void CInputSystem::PrintMouseSettings(int mseNum, MouseSettings *settings) { for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++) - { - const char *axisName = s_axisNames[axisNum]; - printf(" %s-Axis Dead Zone = %d %%\n", axisName, settings->deadZones[axisNum]); - } + printf(" %-7s Dead Zone = %u %%\n", s_axisNames[axisNum], settings->deadZones[axisNum]); } MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *section, int mseNum) @@ -1098,10 +1117,7 @@ MouseSettings *CInputSystem::ReadMouseSettings(CINIFile *ini, const char *sectio baseKey.append(IntToString(mseNum + 1)); bool read = false; for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++) - { - const char *axisName = s_axisNames[axisNum]; - read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY; - } + read |= ini->Get(section, baseKey + s_axisIds[axisNum] + "DeadZone", settings->deadZones[axisNum]) == OKAY; if (read) return settings; delete settings; @@ -1119,9 +1135,8 @@ void CInputSystem::WriteMouseSettings(CINIFile *ini, const char *section, MouseS baseKey.append(IntToString(settings->mseNum + 1)); for (int axisNum = 0; axisNum < NUM_MOUSE_AXES; axisNum++) { - const char *axisName = s_axisNames[axisNum]; if (settings->deadZones[axisNum] != common->deadZones[axisNum]) - ini->Set(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]); + ini->Set(section, baseKey + s_axisIds[axisNum] + "DeadZone", settings->deadZones[axisNum]); } } @@ -1133,11 +1148,11 @@ void CInputSystem::PrintJoySettings(int joyNum, JoySettings *settings) if (joyDetails && !joyDetails->hasAxis[axisNum]) continue; const char *axisName = s_axisNames[axisNum]; - printf(" %-2s-Axis Min Value = %d\n", axisName, settings->axisMinVals[axisNum]); - printf(" %-2s-Axis Center/Off Value = %d\n", axisName, settings->axisOffVals[axisNum]); - printf(" %-2s-Axis Max Value = %d\n", axisName, settings->axisMaxVals[axisNum]); - printf(" %-2s-Axis Dead Zone = %d %%\n", axisName, settings->deadZones[axisNum]); - printf(" %-2s-Axis Saturation = %d %%\n", axisName, settings->saturations[axisNum]); + printf(" %-7s Min Value = %d\n", axisName, settings->axisMinVals[axisNum]); + printf(" %-7s Center/Off Value = %d\n", axisName, settings->axisOffVals[axisNum]); + printf(" %-7s Max Value = %d\n", axisName, settings->axisMaxVals[axisNum]); + printf(" %-7s Dead Zone = %u %%\n", axisName, settings->deadZones[axisNum]); + printf(" %-7s Saturation = %u %%\n", axisName, settings->saturations[axisNum]); } } @@ -1155,12 +1170,12 @@ JoySettings *CInputSystem::ReadJoySettings(CINIFile *ini, const char *section, i bool read = false; for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++) { - const char *axisName = s_axisNames[axisNum]; - read |= ini->Get(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]) == OKAY; - read |= ini->Get(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]) == OKAY; - read |= ini->Get(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]) == OKAY; - read |= ini->Get(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]) == OKAY; - read |= ini->Get(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]) == OKAY; + const char *axisId = s_axisIds[axisNum]; + read |= ini->Get(section, baseKey + axisId + "MinVal", settings->axisMinVals[axisNum]) == OKAY; + read |= ini->Get(section, baseKey + axisId + "OffVal", settings->axisOffVals[axisNum]) == OKAY; + read |= ini->Get(section, baseKey + axisId + "MaxVal", settings->axisMaxVals[axisNum]) == OKAY; + read |= ini->Get(section, baseKey + axisId + "DeadZone", settings->deadZones[axisNum]) == OKAY; + read |= ini->Get(section, baseKey + axisId + "Saturation", settings->saturations[axisNum]) == OKAY; } if (read) return settings; @@ -1179,17 +1194,17 @@ void CInputSystem::WriteJoySettings(CINIFile *ini, const char *section, JoySetti baseKey.append(IntToString(settings->joyNum + 1)); for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++) { - const char *axisName = s_axisNames[axisNum]; + const char *axisId = s_axisIds[axisNum]; if (settings->axisMinVals[axisNum] != common->axisMinVals[axisNum]) - ini->Set(section, baseKey + axisName + "MinVal", settings->axisMinVals[axisNum]); + ini->Set(section, baseKey + axisId + "MinVal", settings->axisMinVals[axisNum]); if (settings->axisOffVals[axisNum] != common->axisOffVals[axisNum]) - ini->Set(section, baseKey + axisName + "OffVal", settings->axisOffVals[axisNum]); + ini->Set(section, baseKey + axisId + "OffVal", settings->axisOffVals[axisNum]); if (settings->axisMaxVals[axisNum] != common->axisMaxVals[axisNum]) - ini->Set(section, baseKey + axisName + "MaxVal", settings->axisMaxVals[axisNum]); + ini->Set(section, baseKey + axisId + "MaxVal", settings->axisMaxVals[axisNum]); if (settings->deadZones[axisNum] != common->deadZones[axisNum]) - ini->Set(section, baseKey + axisName + "DeadZone", settings->deadZones[axisNum]); + ini->Set(section, baseKey + axisId + "DeadZone", settings->deadZones[axisNum]); if (settings->saturations[axisNum] != common->saturations[axisNum]) - ini->Set(section, baseKey + axisName + "Saturation", settings->saturations[axisNum]); + ini->Set(section, baseKey + axisId + "Saturation", settings->saturations[axisNum]); } } @@ -1285,7 +1300,7 @@ EMousePart CInputSystem::GetMouseButton(int butNum) bool CInputSystem::IsAxis(EJoyPart joyPart) { - return joyPart >= JoyXAxis && joyPart <= JoyRZAxisNeg; + return joyPart >= JoyXAxis && joyPart <= JoyS2AxisNeg; } bool CInputSystem::IsFullAxis(EJoyPart joyPart) @@ -1293,6 +1308,11 @@ bool CInputSystem::IsFullAxis(EJoyPart joyPart) return IsAxis(joyPart) && (((joyPart - JoyXAxis) % 4) == AXIS_FULL || ((joyPart - JoyXAxis) % 4) == AXIS_INVERTED); } +bool CInputSystem::IsSliderAxis(EJoyPart joyPart) +{ + return joyPart >= JoyS1Axis && joyPart <= JoyS2AxisNeg; +} + bool CInputSystem::GetAxisDetails(EJoyPart joyPart, int &axisNum, int &axisDir) { if (!IsAxis(joyPart)) @@ -1754,6 +1774,8 @@ void CInputSystem::UngrabMouse() SetMouseVisibility(true); } +#include + bool CInputSystem::SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd) { const JoyDetails *joyDetails = GetJoyDetails(joyNum); @@ -1775,10 +1797,13 @@ bool CInputSystem::DetectJoystickAxis(unsigned joyNum, unsigned &axisNum, const bool cancelled = false; CInputSource *escape = ParseSource(escapeMapping); CInputSource *confirm = ParseSource(confirmMapping); + CInputSource *output = ParseSource("KEY_SHIFT"); if (escape) escape->Acquire(); if (confirm) confirm->Acquire(); + if (output) + output->Acquire(); printf("Move axis around and then press Return (or press Esc to cancel): "); fflush(stdout); // required on terminals that use buffering @@ -1786,6 +1811,7 @@ bool CInputSystem::DetectJoystickAxis(unsigned joyNum, unsigned &axisNum, const unsigned maxRange; unsigned maxAxisNum; + bool firstOut = true; int minVals[NUM_JOY_AXES]; int maxVals[NUM_JOY_AXES]; for (unsigned loopAxisNum = 0; loopAxisNum < NUM_JOY_AXES; loopAxisNum++) @@ -1836,6 +1862,23 @@ bool CInputSystem::DetectJoystickAxis(unsigned joyNum, unsigned &axisNum, const maxVals[loopAxisNum] = max(joyVal, maxVals[loopAxisNum]); } + // Check if output source is triggered, and if so output value for debugging + if (output && output->IsActive()) + { + if (firstOut) + puts(""); + printf(" ["); + for (unsigned loopAxisNum = 0; loopAxisNum < NUM_JOY_AXES; loopAxisNum++) + { + int joyVal = GetJoyAxisValue(joyNum, loopAxisNum); + if (loopAxisNum > 0) + printf(", "); + printf("%s: %d", s_axisIds[loopAxisNum], joyVal); + } + puts("]"); + firstOut = false; + } + // Don't poll continuously Wait(1000/60); } @@ -1872,6 +1915,8 @@ Finish: escape->Release(); if (confirm) confirm->Release(); + if (output) + output->Release(); return !cancelled; } @@ -1920,6 +1965,8 @@ Repeat: puts(" - for a horizontal joystick axis, push it all the way to the right."); if (axisNum == AXIS_Y || axisNum == AXIS_RY || axisNum == AXIS_Z || axisNum == AXIS_RZ) puts(" - for a vertical joystick axis, push it all the way downwards."); + if (axisNum == AXIS_S1 || axisNum == AXIS_S2) + puts(" - for a joystick slider, push it all the way to its extreme."); puts(" - for a steering wheel, turn it all the way to the right."); puts(" - for a pedal, press it all the way to the floor."); break; @@ -1930,6 +1977,8 @@ Repeat: puts(" - for a horizontal joystick axis, push it all the way to the left."); if (axisNum == AXIS_Y || axisNum == AXIS_RY || axisNum == AXIS_Z || axisNum == AXIS_RZ) puts(" - for a vertical joystick axis, push it all the way updwards."); + if (axisNum == AXIS_S1 || axisNum == AXIS_S2) + puts(" - for a joystick slider, return it to its off position."); puts(" - for a steering wheel, turn it all the way to the left."); puts(" - for a pedal, let go of the pedal completely. If there is another pedal"); puts(" that shares the same axis then press that one all the way to the floor."); @@ -1937,7 +1986,10 @@ Repeat: case 2: puts("Step 3:"); puts(" Return axis to its central/'off' position and hold, ie:"); - puts(" - for a joystick axis, let it return to the middle."); + if (axisNum == AXIS_X || axisNum == AXIS_RX || axisNum == AXIS_Y || axisNum == AXIS_RY || axisNum == AXIS_Z || axisNum == AXIS_RZ) + puts(" - for a joystick axis, let it return to the middle."); + else if (axisNum == AXIS_S1 || axisNum == AXIS_S2) + puts(" - for a joystick slider, keep it at its off position."); puts(" - for a steering weel, turn it back to the center."); puts(" - for a pedal, let go of pedal completely. Likewise for any other pedal"); puts(" that shares the same axis."); @@ -2046,7 +2098,7 @@ Repeat: printf(" Min Value = %d\n", negVal); printf(" Center/Off Value = %d\n", offVal); printf(" Max Value = %d\n", posVal); - printf(" Dead Zone = %d %%\n", deadZone); + printf(" Dead Zone = %u %%\n", deadZone); printf("\nAccept these settings: y/n? "); fflush(stdout); // required on terminals that use buffering diff --git a/Src/Inputs/InputSystem.h b/Src/Inputs/InputSystem.h index f6fa612..5b23cdc 100644 --- a/Src/Inputs/InputSystem.h +++ b/Src/Inputs/InputSystem.h @@ -73,7 +73,7 @@ class CINIFile; #define NUM_MOUSE_AXES 3 #define NUM_MOUSE_BUTTONS 5 #define NUM_JOY_PARTS ((int)JoyButton31 + 1) -#define NUM_JOY_AXES 6 +#define NUM_JOY_AXES 8 #define NUM_JOY_POVS 4 #define NUM_JOY_BUTTONS 32 @@ -84,6 +84,8 @@ class CINIFile; #define AXIS_RX 3 #define AXIS_RY 4 #define AXIS_RZ 5 +#define AXIS_S1 6 +#define AXIS_S2 7 // Axis directions #define AXIS_FULL 0 @@ -152,6 +154,14 @@ enum EJoyPart JoyRZAxisInv, JoyRZAxisPos, JoyRZAxisNeg, + JoyS1Axis, + JoyS1AxisInv, + JoyS1AxisPos, + JoyS1AxisNeg, + JoyS2Axis, + JoyS2AxisInv, + JoyS2AxisPos, + JoyS2AxisNeg, JoyPOV0Up, JoyPOV0Down, JoyPOV0Left, @@ -322,7 +332,8 @@ private: // Lookup table for translating joystick mapping strings to their respective joystick parts static JoyPartsStruct s_joyParts[]; - // Names of axes + // Ids and names of axes + static const char *s_axisIds[]; static const char *s_axisNames[]; // Number of keyboards, mice and joysticks @@ -570,6 +581,11 @@ protected: */ bool IsFullAxis(EJoyPart joyPart); + /* + * Returns true if the given EJoyPart represents a slider axis, eg JoyS1Axis. + */ + bool IsSliderAxis(EJoyPart joyPart); + /* * Returns true if joystick part represents an axis and sets axisPart and axisDir as follows: * axisNum will be the axis number (AXIS_X, AXIS_Y, AXIS_Z, AXIS_RX, AXIS_RY or AXIS_RZ) diff --git a/Src/OSD/SDL/SDLInputSystem.cpp b/Src/OSD/SDL/SDLInputSystem.cpp index f4f9d30..0807a34 100644 --- a/Src/OSD/SDL/SDLInputSystem.cpp +++ b/Src/OSD/SDL/SDLInputSystem.cpp @@ -217,7 +217,6 @@ void CSDLInputSystem::OpenJoysticks() joyDetails.axisHasFF[axisNum] = false; // SDL 1.2 does not support force feedback char *axisName = joyDetails.axisName[axisNum]; strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); // SDL 1.2 does not support axis names - strcat(axisName, "-Axis"); } joyDetails.numPOVs = SDL_JoystickNumHats(joystick); joyDetails.numButtons = SDL_JoystickNumButtons(joystick); diff --git a/Src/OSD/Windows/DirectInputSystem.cpp b/Src/OSD/Windows/DirectInputSystem.cpp index 7ffb825..85d8d1c 100644 --- a/Src/OSD/Windows/DirectInputSystem.cpp +++ b/Src/OSD/Windows/DirectInputSystem.cpp @@ -293,8 +293,9 @@ struct DIEnumDevsContext static BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context) { - // Keep track of all joystick device GUIDs DIEnumDevsContext *diDevsContext = (DIEnumDevsContext*)context; + + // Keep track of all joystick device GUIDs DIJoyInfo info; memset(&info, 0, sizeof(DIJoyInfo)); info.guid = instance->guidInstance; @@ -304,16 +305,22 @@ static BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID return DIENUM_CONTINUE; } -struct DIEnumAxesContext +struct DIEnumObjsContext { JoyDetails *joyDetails; + unsigned sliderCount; bool enumError; }; -static BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID context) +static BOOL CALLBACK DI8EnumObjectsCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID context) { - // Work out which axis is currently being enumerated from the GUID - DIEnumAxesContext *diAxesContext = (DIEnumAxesContext*)context; + DIEnumObjsContext *diObjsContext = (DIEnumObjsContext*)context; + + // Get data format for object + int objNum = DIDFT_GETINSTANCE(instance->dwType); + DIOBJECTDATAFORMAT fmt = c_dfDIJoystick2.rgodf[objNum]; + + // Work out which axis or slider is currently being enumerated from the GUID int axisNum; if (instance->guidType == GUID_XAxis) axisNum = AXIS_X; else if (instance->guidType == GUID_YAxis) axisNum = AXIS_Y; @@ -321,12 +328,24 @@ static BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPV else if (instance->guidType == GUID_RxAxis) axisNum = AXIS_RX; else if (instance->guidType == GUID_RyAxis) axisNum = AXIS_RY; else if (instance->guidType == GUID_RzAxis) axisNum = AXIS_RZ; - else + else if (instance->guidType == GUID_Slider) { - // If couldn't match GUID (which, according to MSDN, is an optional attribute), then flag error and try matching using a different method - diAxesContext->enumError = true; + // Work out which slider from count + switch (diObjsContext->sliderCount++) + { + case 0: axisNum = AXIS_S1; break; + case 1: axisNum = AXIS_S2; break; + default: + // If couldn't match then ignore slider + return DIENUM_CONTINUE; + } + } + else if (instance->dwType & DIDFT_AXIS) + { + // If is an axis but couldn't match GUID above (which, according to MSDN, is an optional attribute), then flag error and try matching via offset int objNum = DIDFT_GETINSTANCE(instance->dwType); DIOBJECTDATAFORMAT fmt = c_dfDIJoystick2.rgodf[objNum]; + diObjsContext->enumError = true; switch (fmt.dwOfs) { case DIJOFS_X: axisNum = AXIS_X; break; @@ -340,11 +359,16 @@ static BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPV return DIENUM_CONTINUE; } } + else + { + // Ignore all other types of object + return DIENUM_CONTINUE; + } - // If axis overlaps with a previous ones, flag error - JoyDetails *joyDetails = diAxesContext->joyDetails; + // If axis overlaps with a previous one, flag error + JoyDetails *joyDetails = diObjsContext->joyDetails; if (joyDetails->hasAxis[axisNum]) - diAxesContext->enumError = true; + diObjsContext->enumError = true; // Record fact that axis is present and also whether it has force feedback available joyDetails->hasAxis[axisNum] = true; @@ -353,7 +377,7 @@ static BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPV // Get axis name from DirectInput and store that too char *axisName = joyDetails->axisName[axisNum]; strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); - strcat(axisName, "-Axis ("); + strcat(axisName, " ("); strncat(axisName, instance->tszName, MAX_NAME_LENGTH - strlen(axisName) - 1); strcat(axisName, ")"); @@ -1050,12 +1074,16 @@ void CDirectInputSystem::OpenJoysticks() joyDetails.hasAxis[AXIS_RX] = true; joyDetails.hasAxis[AXIS_RY] = true; joyDetails.hasAxis[AXIS_RZ] = true; + joyDetails.hasAxis[AXIS_S1] = false; + joyDetails.hasAxis[AXIS_S2] = false; joyDetails.axisHasFF[AXIS_X] = true; // Force feedback simulated on left and right sticks joyDetails.axisHasFF[AXIS_Y] = true; joyDetails.axisHasFF[AXIS_Z] = false; joyDetails.axisHasFF[AXIS_RX] = true; joyDetails.axisHasFF[AXIS_RY] = true; joyDetails.axisHasFF[AXIS_RZ] = false; + joyDetails.axisHasFF[AXIS_S1] = false; + joyDetails.axisHasFF[AXIS_S2] = false; // Keep track of XInput device number it->xInputNum = xNum++; @@ -1109,10 +1137,10 @@ void CDirectInputSystem::OpenJoysticks() joyDetails.numButtons = devCaps.dwButtons; // Enumerate axes - DIEnumAxesContext diAxesContext; - diAxesContext.joyDetails = &joyDetails; - diAxesContext.enumError = false; - if (FAILED(hr = joystick->EnumObjects(DI8EnumAxesCallback, &diAxesContext, DIDFT_AXIS))) + DIEnumObjsContext diObjsContext; + memset(&diObjsContext, 0, sizeof(DIEnumObjsContext)); + diObjsContext.joyDetails = &joyDetails; + if (FAILED(hr = joystick->EnumObjects(DI8EnumObjectsCallback, &diObjsContext, DIDFT_ALL))) { ErrorLog("Unable to enumerate axes of DirectInput joystick %d (error %d) - skipping joystick.\n", joyNum, hr); @@ -1121,7 +1149,7 @@ void CDirectInputSystem::OpenJoysticks() } // If enumeration failed for some reason then include all possible joystick axes so that no axis is left off due to error - if (diAxesContext.enumError) + if (diObjsContext.enumError) { for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++) { @@ -1131,7 +1159,6 @@ void CDirectInputSystem::OpenJoysticks() joyDetails.axisHasFF[axisNum] = false; char *axisName = joyDetails.axisName[axisNum]; strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); - strcat(axisName, "-Axis"); } } } @@ -1379,6 +1406,8 @@ HRESULT CDirectInputSystem::CreateJoystickEffect(LPDIRECTINPUTDEVICE8 joystick, case AXIS_RX: axisOfs = DIJOFS_RX; break; case AXIS_RY: axisOfs = DIJOFS_RY; break; case AXIS_RZ: axisOfs = DIJOFS_RZ; break; + case AXIS_S1: axisOfs = DIJOFS_SLIDER(0); break; + case AXIS_S2: axisOfs = DIJOFS_SLIDER(1); break; default: return E_FAIL; } @@ -1428,7 +1457,7 @@ HRESULT CDirectInputSystem::CreateJoystickEffect(LPDIRECTINPUTDEVICE8 joystick, dic.lNegativeCoefficient = 0; dic.dwPositiveSaturation = DI_FFNOMINALMAX; dic.dwNegativeSaturation = DI_FFNOMINALMAX; - dic.lDeadBand = (LONG)(0.05 * DI_FFNOMINALMAX); // 5% deadband + dic.lDeadBand = (LONG)(0.05 * DI_FFNOMINALMAX); // 5% deadband eff.cbTypeSpecificParams = sizeof(DICONDITION); eff.lpvTypeSpecificParams = &dic; @@ -1670,6 +1699,8 @@ int CDirectInputSystem::GetJoyAxisValue(int joyNum, int axisNum) case AXIS_RX: return (int)m_diJoyStates[joyNum].lRx; case AXIS_RY: return (int)m_diJoyStates[joyNum].lRy; case AXIS_RZ: return (int)m_diJoyStates[joyNum].lRz; + case AXIS_S1: return (int)m_diJoyStates[joyNum].rglSlider[0]; + case AXIS_S2: return (int)m_diJoyStates[joyNum].rglSlider[1]; default: return 0; } } @@ -1831,7 +1862,7 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF lFFMag = (LONG)(-ffCmd.force * (float)(g_Config.dInputConstForceLeftMax * DI_EFFECTS_SCALE)); // Invert sign for DirectInput effect dicf.lMagnitude = min(lFFMag, DI_EFFECTS_MAX); } - + eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); eff.lpvTypeSpecificParams = &dicf; break;