Skip to content

Commit

Permalink
Minor modifications to how devices and their capabilities are present…
Browse files Browse the repository at this point in the history
…ed to applications. This is intended to improve compatibility and is based on studying real DirectInput behavior.
  • Loading branch information
samuelgr committed Jan 29, 2022
1 parent 7d83b2c commit 993502c
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Include/Xidi/ApiDirectInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ enum class ECharMode
#define DINPUT_VER_MIN 0x0800
#define DINPUT_VER_MAX 0x08ff

#define DINPUT_DEVTYPE_XINPUT_GAMEPAD DI8DEVTYPE_GAMEPAD
#define DINPUT_DEVTYPE_XINPUT_GAMEPAD ((DI8DEVTYPE_GAMEPAD) | ((DI8DEVTYPEGAMEPAD_STANDARD) << 8))

typedef IDirectInput8 EarliestIDirectInput;
typedef IDirectInput8 LatestIDirectInput;
Expand Down
8 changes: 7 additions & 1 deletion Include/Xidi/VirtualController.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ namespace Xidi
/// Default value for an axis deadzone property. No deadzone region is defined by default.
static constexpr uint32_t kAxisDeadzoneDefault = kAxisDeadzoneMin;

/// Default lower-bound value for the range property, based on tests with real DirectInput hardware.
static constexpr int32_t kRangeMinDefault = 0;

/// Default upper-bound value for the range property, based on tests with real DirectInput hardware.
static constexpr int32_t kRangeMaxDefault = 65535;

/// Minimum allowed value for an axis saturation property, per DirectInput documentation.
static constexpr uint32_t kAxisSaturationMin = 0;

Expand Down Expand Up @@ -212,7 +218,7 @@ namespace Xidi
constexpr inline SAxisProperties(void)
{
SetDeadzone(kAxisDeadzoneDefault);
SetRange(kAnalogValueMin, kAnalogValueMax);
SetRange(kRangeMinDefault, kRangeMaxDefault);
SetSaturation(kAxisSaturationDefault);
}

Expand Down
14 changes: 11 additions & 3 deletions Source/Test/Case/VirtualControllerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ namespace XidiTest
};

VirtualController controller(kControllerIndex, kTestMapper);
controller.SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);

for (int i = 0; i < _countof(kExpectedStates); ++i)
{
controller.RefreshState(kPhysicalStates[i]);
Expand All @@ -279,6 +281,8 @@ namespace XidiTest
};

VirtualController controller(kControllerIndex, kTestMapper);
controller.SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);

for (const auto& expectedState : kExpectedStates)
{
controller.RefreshState(kPhysicalState);
Expand Down Expand Up @@ -322,6 +326,8 @@ namespace XidiTest
};

VirtualController controller(kControllerIndex, kTestMapper);
controller.SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);

for (int i = 0; i < _countof(kExpectedStates); ++i)
{
controller.RefreshState(kPhysicalStates[i]);
Expand Down Expand Up @@ -490,7 +496,7 @@ namespace XidiTest
if ((int)kTestRangeAxis == i)
TEST_ASSERT(kTestRangeValue == controller.GetAxisRange((EAxis)i));
else
TEST_ASSERT(std::make_pair(Controller::kAnalogValueMin, Controller::kAnalogValueMax) == controller.GetAxisRange((EAxis)i));
TEST_ASSERT(std::make_pair(VirtualController::kRangeMinDefault, VirtualController::kRangeMaxDefault) == controller.GetAxisRange((EAxis)i));
}

TEST_ASSERT(true == controller.SetAllAxisRange(kTestRangeValue.first, kTestRangeValue.second));
Expand All @@ -509,12 +515,12 @@ namespace XidiTest
TEST_ASSERT(false == controller.SetAxisRange(kTestRangeAxis, kTestRangeValue.first, kTestRangeValue.second));

for (int i = 0; i < (int)EAxis::Count; ++i)
TEST_ASSERT(std::make_pair(Controller::kAnalogValueMin, Controller::kAnalogValueMax) == controller.GetAxisRange((EAxis)i));
TEST_ASSERT(std::make_pair(VirtualController::kRangeMinDefault, VirtualController::kRangeMaxDefault) == controller.GetAxisRange((EAxis)i));

TEST_ASSERT(false == controller.SetAllAxisRange(kTestRangeValue.first, kTestRangeValue.second));

for (int i = 0; i < (int)EAxis::Count; ++i)
TEST_ASSERT(std::make_pair(Controller::kAnalogValueMin, Controller::kAnalogValueMax) == controller.GetAxisRange((EAxis)i));
TEST_ASSERT(std::make_pair(VirtualController::kRangeMinDefault, VirtualController::kRangeMaxDefault) == controller.GetAxisRange((EAxis)i));
}

// Valid saturation value set on a single axis and then on all axes.
Expand Down Expand Up @@ -652,6 +658,7 @@ namespace XidiTest
for (unsigned int i = 1; i <= _countof(kPhysicalStates); ++i)
{
VirtualController controller(kControllerIndex, kTestMapper);
controller.SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);
controller.SetEventBufferCapacity(kEventBufferCapacity);

uint32_t lastEventCount = controller.GetEventBufferCount();
Expand Down Expand Up @@ -706,6 +713,7 @@ namespace XidiTest
for (unsigned int i = 1; i <= _countof(kPhysicalStates); ++i)
{
VirtualController controller(kControllerIndex, kTestMapper);
controller.SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);
controller.SetEventBufferCapacity(kEventBufferCapacity);
controller.EventFilterRemoveElement({.type = EElementType::Axis, .axis = EAxis::X});
controller.EventFilterRemoveElement({.type = EElementType::Axis, .axis = EAxis::Y});
Expand Down
4 changes: 3 additions & 1 deletion Source/Test/Case/VirtualDirectInputDeviceTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ namespace XidiTest
/// @return Smart pointer to the new virtual controller object.
static inline std::unique_ptr<VirtualController> CreateTestVirtualController(const Mapper& mapper = kTestMapper)
{
return std::make_unique<VirtualController>(kTestControllerIdentifier, mapper);
std::unique_ptr<VirtualController> testVirtualController = std::make_unique<VirtualController>(kTestControllerIdentifier, mapper);
testVirtualController->SetAllAxisRange(Controller::kAnalogValueMin, Controller::kAnalogValueMax);
return testVirtualController;
}


Expand Down
12 changes: 8 additions & 4 deletions Source/VirtualDirectInputDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,12 @@ namespace Xidi

if (objectInfo->dwSize > sizeof(DirectInputDeviceType<charMode>::DeviceObjectInstanceCompatType))
{
objectInfo->dwFFMaxForce = (DWORD)Controller::ForceFeedback::kEffectForceMagnitudeMaximum;
objectInfo->dwFFForceResolution = 1;
// Maximum force is supposedly measured in Newtons. This value is taken from a Logitech RumblePad 2.
objectInfo->dwFFMaxForce = 10;

// Supported force range follows the DirectInput allowed range.
// A difference of 1 probably will not be noticeable to a user, but nevertheless that resolution is supported.
objectInfo->dwFFForceResolution = (DWORD)Controller::ForceFeedback::kEffectForceMagnitudeMaximum;
}
}
break;
Expand Down Expand Up @@ -1218,8 +1222,8 @@ namespace Xidi
{
case (sizeof(DIDEVCAPS)):
// Hardware information, only present in the latest version of the structure.
lpDIDevCaps->dwFirmwareRevision = 0;
lpDIDevCaps->dwHardwareRevision = 0;
lpDIDevCaps->dwFirmwareRevision = 1;
lpDIDevCaps->dwHardwareRevision = 1;

// Force feedback information, only present in the latest version of the structure.
if (true == kForceFeedbackIsSupported)
Expand Down

0 comments on commit 993502c

Please sign in to comment.