Skip to content

Commit 7751f41

Browse files
SonickidnextgenSonickidnextgen
authored andcommitted
vJoy functionality: Button remapping, POV HAT support, etc.
1 parent 5ac5e2c commit 7751f41

7 files changed

Lines changed: 459 additions & 118 deletions

File tree

IOSync/IOSync.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<ClInclude Include="src\application\application_exceptions.h" />
4848
<ClInclude Include="src\devices\gamepad.h" />
4949
<ClInclude Include="src\devices\native\winnt\Real_XInput_Wrapper.h" />
50+
<ClInclude Include="src\devices\native\winnt\vJoyDriver.h" />
5051
<ClInclude Include="src\iosync_application_exceptions.h" />
5152
<ClInclude Include="src\devices\devices.h" />
5253
<ClInclude Include="src\devices\keyboard.h" />

IOSync/IOSync.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@
167167
<ClInclude Include="src\names.h">
168168
<Filter>Header Files</Filter>
169169
</ClInclude>
170+
<ClInclude Include="src\devices\native\winnt\vJoyDriver.h">
171+
<Filter>Header Files\devices\native\winnt</Filter>
172+
</ClInclude>
170173
</ItemGroup>
171174
<ItemGroup>
172175
<ResourceCompile Include="Icon.rc">

IOSync/src/devices/gamepad.cpp

Lines changed: 133 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
#include "../application/application.h"
77
#include "../names.h"
88

9-
// Standard library:
10-
#include <cmath>
11-
129
// Namespace(s):
1310
namespace iosync
1411
{
@@ -120,7 +117,7 @@ namespace iosync
120117
#endif
121118

122119
#ifdef GAMEPAD_VJOY_ENABLED
123-
gamepad::vJoyDriverState gamepad::vJoyInfo = gamepad::VJOY_UNDEFINED;
120+
vJoy::vJoyDriver gamepad::vJoyInfo = { vJoy::vJoyDriver::VJOY_UNDEFINED };
124121
#endif
125122

126123
// Functions:
@@ -181,123 +178,188 @@ namespace iosync
181178
}
182179

183180
#ifdef GAMEPAD_VJOY_ENABLED
184-
gamepad::vJoyDriverState gamepad::__winnt__vJoy__init()
181+
vJoy::vJoyDriver::vJoyDriverState gamepad::__winnt__vJoy__init()
185182
{
186-
vJoyInfo = ((vJoyEnabled() == TRUE) ? VJOY_ENABLED : VJOY_DISABLED);
183+
// Namespace(s):
184+
using namespace vJoy;
185+
186+
vJoyInfo.state = ((vJoyEnabled() == TRUE) ? vJoyDriver::VJOY_ENABLED : vJoyDriver::VJOY_DISABLED);
187187

188-
if (vJoyInfo == VJOY_ENABLED)
188+
if (vJoyInfo.state == vJoyDriver::VJOY_ENABLED)
189189
{
190190
WORD DLLVer, driverVer;
191191

192192
if (!DriverMatch(&DLLVer, &driverVer))
193193
{
194-
vJoyInfo = VJOY_DISABLED;
194+
vJoyInfo.state = vJoyDriver::VJOY_DISABLED;
195195
}
196196
}
197197

198-
return vJoyInfo;
198+
return vJoyInfo.state;
199+
}
200+
201+
vJoy::vJoyDriver::vJoyDriverState gamepad::__winnt__vJoy__deinit()
202+
{
203+
// Namespace(s):
204+
using namespace vJoy;
205+
206+
if (vJoyInfo.state == vJoyDriver::VJOY_ENABLED)
207+
{
208+
// Nothing so far.
209+
210+
vJoyInfo.state = vJoyDriver::VJOY_DISABLED;
211+
}
212+
213+
return vJoyInfo.state;
199214
}
200215

201216
VjdStat gamepad::__winnt__vJoy__getStatus(const gamepadID internal_identifier)
202217
{
203218
return GetVJDStatus(__winnt__vJoy__vDevice(internal_identifier));
204219
}
205220

206-
LONG gamepad::__winnt__vJoy__capAxis(const UINT vJoyDevice, const LONG value, const UINT axis)
221+
LONG gamepad::__winnt__vJoy__capAxis(const UINT vJoyID, const LONG value, const UINT axis, const UINT maximum_value)
207222
{
208223
#ifdef GAMEPAD_VJOY_SAFE
209-
LONG axis_min, axis_max;
224+
auto& device = vJoyInfo.getDevice(vJoyID);
225+
auto axisInfo = device.getAxis(axis)->second;
226+
auto axis_mid = ((axisInfo.max - axisInfo.min) / 2);
210227

211-
GetVJDAxisMin(vJoyDevice, axis, &axis_min);
212-
GetVJDAxisMax(vJoyDevice, axis, &axis_max);
228+
//return axis_mid + value;
229+
//return axis_mid + max(axis_min, min(value, axis_max));
230+
231+
auto scalar = max(axis_mid / maximum_value, 1);
213232

214-
return max(axis_min, min(value, axis_max));
233+
return max(axisInfo.min, min((LONG)(axis_mid + (value * scalar)), axisInfo.max));
215234
#else
216235
return value;
217236
#endif
218237
}
219238

220-
void gamepad::__winnt__vJoy__transferAxis(const UINT vJoyDevice, const gamepadState& state, JOYSTICK_POSITION& vState, const UINT axis)
239+
void gamepad::__winnt__vJoy__transferAxis(const UINT vJoyID, const gamepadState& state, JOYSTICK_POSITION& vState, const UINT axis)
221240
{
222241
switch (axis)
223242
{
224243
case HID_USAGE_X:
225-
vState.wAxisX = __winnt__vJoy__capAxis(vJoyDevice, state.native.Gamepad.sThumbLX, axis);
244+
vState.wAxisX = __winnt__vJoy__capAxis(vJoyID, state.native.Gamepad.sThumbLX, axis);
226245

227246
break;
228247
case HID_USAGE_Y:
229-
vState.wAxisX = __winnt__vJoy__capAxis(vJoyDevice, state.native.Gamepad.sThumbLY, axis);
248+
vState.wAxisY = __winnt__vJoy__capAxis(vJoyID, -state.native.Gamepad.sThumbLY, axis);
230249

231250
break;
232251
case HID_USAGE_Z:
233-
vState.wAxisZ = __winnt__vJoy__capAxis(vJoyDevice, state.native.Gamepad.bRightTrigger-state.native.Gamepad.bLeftTrigger, axis);
252+
{
253+
LONG m = vJoyInfo.getDevice(vJoyID).axisMax(axis);
254+
255+
m = ((m+1)/2);
256+
//m = m+1;
257+
258+
auto value = m;
259+
260+
int scalar = max(m / (UCHAR_MAX), 1);
261+
262+
if (state.native.Gamepad.bRightTrigger != 0)
263+
value += ((state.native.Gamepad.bRightTrigger * scalar) + scalar);
264+
265+
if (state.native.Gamepad.bLeftTrigger != 0)
266+
value -= ((state.native.Gamepad.bLeftTrigger * scalar) + scalar);
267+
268+
vState.wAxisZ = value;
269+
//vState.wAxisZ = __winnt__vJoy__capAxis(vJoyID, value, axis);
270+
}
234271

235272
break;
236273
case HID_USAGE_RX:
237-
vState.wAxisXRot = __winnt__vJoy__capAxis(vJoyDevice, state.native.Gamepad.sThumbRX, axis);
274+
vState.wAxisXRot = __winnt__vJoy__capAxis(vJoyID, state.native.Gamepad.sThumbRX, axis);
238275

239276
break;
240277
case HID_USAGE_RY:
241-
vState.wAxisYRot = __winnt__vJoy__capAxis(vJoyDevice, state.native.Gamepad.sThumbRY, axis);
278+
vState.wAxisYRot = __winnt__vJoy__capAxis(vJoyID, -state.native.Gamepad.sThumbRY, axis);
242279

243280
break;
244-
case HID_USAGE_RZ:
245-
vState.wAxisZRot = __winnt__vJoy__capAxis(vJoyDevice, -(state.native.Gamepad.bRightTrigger-state.native.Gamepad.bLeftTrigger), axis);
281+
case HID_USAGE_POV:
282+
{
283+
// Local variable(s):
284+
285+
// Get a reference to the vJoy-device.
286+
auto& device = vJoyInfo.getDevice(vJoyID);
287+
288+
// Check the POV mode:
289+
if (device.contPOVNumber > 0)
290+
{
291+
if ((state.native.Gamepad.wButtons & gamepadState::padMask) > 0)
292+
{
293+
vState.bHats = (((int)joyHat(state))*100);
294+
}
295+
else
296+
{
297+
// Disable the HAT.
298+
vState.bHats = 36001;
299+
}
300+
}
301+
else
302+
{
303+
vState.bHats = 4;
304+
305+
if (state.native.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
306+
vState.bHats = 1;
307+
else if (state.native.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
308+
vState.bHats = 3;
309+
else if (state.native.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
310+
vState.bHats = 2;
311+
else if (state.native.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
312+
vState.bHats = 0;
313+
}
314+
}
246315

247316
break;
248317
}
249318

250319
return;
251320
}
252321

253-
void gamepad::__winnt__vJoy__autoTransferAxis(const UINT vJoyDevice, const gamepadState& state, JOYSTICK_POSITION& vState, const UINT axis)
322+
void gamepad::__winnt__vJoy__autoTransferAxis(const UINT vJoyID, const gamepadState& state, JOYSTICK_POSITION& vState, const UINT axis)
254323
{
255-
if (GetVJDAxisExist(vJoyDevice, axis))
324+
// Local variable(s):
325+
auto& device = vJoyInfo.getDevice(vJoyID);
326+
327+
if (device.hasAxis(axis))
256328
{
257-
__winnt__vJoy__transferAxis(vJoyDevice, state, vState, axis);
329+
__winnt__vJoy__transferAxis(vJoyID, state, vState, axis);
258330
}
259331

260332
return;
261333
}
262334

263-
void gamepad::__winnt__vJoy__simulateState(const gamepadState& state, const UINT vJoyDevice, const VjdStat status)
335+
void gamepad::__winnt__vJoy__simulateState(const gamepadState& state, const UINT vJoyID, const VjdStat status)
264336
{
265-
if (status == VJD_STAT_FREE)
266-
{
267-
// Acquire control over the device:
268-
if (!AcquireVJD(vJoyDevice))
269-
return;
270-
}
271-
272-
ResetVJD(vJoyDevice);
337+
//ResetVJD(vJoyID);
273338

339+
// Local variable(s):
274340
JOYSTICK_POSITION vState;
275341

276342
ZeroVar(vState);
277343

278-
vState.bDevice = vJoyDevice;
344+
vState.bDevice = vJoyID;
279345

280346
// Automatically transfer the axes to the output-state:
281-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_X);
282-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_Y);
347+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_X);
348+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_Y);
283349

284-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_RX);
285-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_RY);
350+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_RX);
351+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_RY);
286352

287-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_Z);
288-
__winnt__vJoy__autoTransferAxis(vJoyDevice, state, vState, HID_USAGE_RZ);
353+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_POV);
354+
__winnt__vJoy__autoTransferAxis(vJoyID, state, vState, HID_USAGE_Z);
289355

290-
vState.lButtons = state.native.Gamepad.wButtons;
356+
vState.lButtons = (state.native.Gamepad.wButtons ^ (state.native.Gamepad.wButtons & gamepadState::padMask));
357+
vState.lButtons = ((((vState.lButtons >> 12) & SHRT_MAX) | (vState.lButtons ^ (vState.lButtons & gamepadState::faceMask))) & SHRT_MAX);
291358

292-
#ifdef GAMEPAD_VJOY_SAFE
293-
//vState.lButtons &= (int)pow(2, GetVJDButtonNumber(vJoyDevice));
294-
#endif
359+
//cout << "vState.lButtons: " << vState.lButtons << endl;
295360

296361
// Update the vJoy-device.
297-
UpdateVJD(vJoyDevice, &vState);
298-
299-
// Relinquish control over the device.
300-
RelinquishVJD(vJoyDevice);
362+
UpdateVJD(vJoyID, &vState);
301363

302364
return;
303365
}
@@ -307,30 +369,6 @@ namespace iosync
307369
void gamepad::simulateState(const gamepadState& state, const gamepadID localIdentifier)
308370
{
309371
#ifdef PLATFORM_WINDOWS
310-
#ifdef GAMEPAD_VJOY_ENABLED
311-
// Check the current state of vJoy:
312-
if (vJoyInfo == VJOY_ENABLED)
313-
{
314-
// Calculate the internal status.
315-
auto status = __winnt__vJoy__getStatus(localIdentifier);
316-
317-
switch (status)
318-
{
319-
case VJD_STAT_OWN:
320-
case VJD_STAT_FREE:
321-
__winnt__vJoy__simulateState(state, __winnt__vJoy__vDevice(localIdentifier), status);
322-
323-
break;
324-
case VJD_STAT_BUSY:
325-
break;
326-
case VJD_STAT_MISS:
327-
break;
328-
default:
329-
break;
330-
}
331-
}
332-
#endif
333-
334372
if (__winnt__sharedMemoryOpen())
335373
{
336374
return;
@@ -458,6 +496,28 @@ namespace iosync
458496
simulateState(state, localGamepadNumber);
459497

460498
#ifdef PLATFORM_WINDOWS
499+
#ifdef GAMEPAD_VJOY_ENABLED
500+
// Check the current state of vJoy:
501+
if (vJoyInfo.state == vJoy::vJoyDriver::VJOY_ENABLED)
502+
{
503+
// Calculate the internal status.
504+
switch (vJoy_status)
505+
{
506+
case VJD_STAT_OWN:
507+
case VJD_STAT_FREE:
508+
__winnt__vJoy__simulateState(state, __winnt__vJoy__vDevice(localGamepadNumber), vJoy_status);
509+
510+
break;
511+
case VJD_STAT_BUSY:
512+
break;
513+
case VJD_STAT_MISS:
514+
break;
515+
default:
516+
break;
517+
}
518+
}
519+
#endif
520+
461521
__winnt__lastPacketNumber = state.native.dwPacketNumber;
462522
#endif
463523

0 commit comments

Comments
 (0)