Skip to content

Commit bddb437

Browse files
committed
Improvement: external pedals support and fixes
1 parent 4b08dbb commit bddb437

File tree

5 files changed

+114
-24
lines changed

5 files changed

+114
-24
lines changed

README.RU.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
[![RU](https://user-images.githubusercontent.com/9499881/27683795-5b0fbac6-5cd8-11e7-929c-057833e01fb1.png)](https://github.com/r57zone/DSAdvance/blob/master/README.RU.md)
33

44
# DSAdvance
5-
Продвинутая эмуляция Xbox геймпада для Sony DualSense, DualShock 4, Nintendo Pro контроллера или Joycon-ов. Поддерживается прицеливание и вождение наклонами геймпада, а также эмуляция стиков на тачпаде. Работает на базе драйвера [ViGEm](https://github.com/ViGEm).
5+
Продвинутая эмуляция Xbox геймпада для Sony DualSense, DualShock 4, Nintendo Pro контроллера или Joycon-ов. Поддерживается прицеливание и вождение наклонами геймпада, эмуляция стиков на тачпаде, а также [внешние педали](https://github.com/r57zone/XboxExternalPedals). Работает на базе драйвера [ViGEm](https://github.com/ViGEm).
66

77
[![](https://user-images.githubusercontent.com/9499881/164945071-5b9f86dd-c396-45a5-817b-fc7068450f02.gif)](https://youtu.be/gkyqO_HuPnk)
88
[![](https://user-images.githubusercontent.com/9499881/164945073-cfa1bfb7-cb82-4714-b2ad-7ecd84a5bcfc.gif)](https://youtu.be/gkyqO_HuPnk)
@@ -26,6 +26,9 @@
2626

2727
По умолчанию кнопка микрофона делает скринщот `Win+Alt+PrtScr` (для DualShock 4 включаем `PSMultiKey` и нажимаем `PS + X`). Изменив параметр `MicCustomKey` на [нужный код кнопки](https://github.com/r57zone/Half-Life-Alyx-novr/blob/master/BINDINGS.md#codes), будет производится её нажатие.
2828

29+
30+
Для подключения внешних педалей измените номер COM-порта, изменив параметр `COMPort`, в разделе `ExternalPedals`.
31+
2932
## Настройка
3033
1. Установить [ViGEmBus](https://github.com/ViGEm/ViGEmBus/releases).
3134
2. Установить Microsoft Visual C++ Redistributable 2017 или новее.

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
– Other languages / Другие языки
44

55
# DSAdvance
6-
Advanced Xbox gamepad emulation for Sony DualSense, DualShock 4, Nintendo Pro controller or Joy-cons. Supports aiming and driving by tilting the gamepad, as well as emulation of sticks on the touchpad. Works based on the driver [ViGEm](https://github.com/ViGEm).
6+
Advanced Xbox gamepad emulation for Sony DualSense, DualShock 4, Nintendo Pro controller or Joy-cons. Supports aiming and driving by tilting the gamepad, stick emulation on the touchpad, and [external pedals](https://github.com/r57zone/XboxExternalPedals). Works based on the driver [ViGEm](https://github.com/ViGEm).
77

88
[![](https://user-images.githubusercontent.com/9499881/164945071-5b9f86dd-c396-45a5-817b-fc7068450f02.gif)](https://youtu.be/gkyqO_HuPnk)
99
[![](https://user-images.githubusercontent.com/9499881/164945073-cfa1bfb7-cb82-4714-b2ad-7ecd84a5bcfc.gif)](https://youtu.be/gkyqO_HuPnk)
@@ -24,6 +24,9 @@ By default, the `PS` button opens the "Xbox Game Bar" (by pressing `Win+G`). By
2424

2525
By default, the microphone button takes a screenshot of `Win+Alt+PrtScr` (for DualShock 4 enable `PSMultiKey` and press `PS + X`). By changing the `MicCustomKey` parameter to the [desired button code](https://github.com/r57zone/Half-Life-Alyx-novr/blob/master/BINDINGS.md#codes), it will be pressed.
2626

27+
28+
To connect external pedals, change the COM port number by changing the `COMPort` parameter in the `ExternalPedals` section.
29+
2730
## Setup
2831
1. Install [ViGEmBus](https://github.com/ViGEm/ViGEmBus/releases).
2932
2. Install Microsoft Visual C++ Redistributable 2017 or newer.

Source/DSAdvance/DSAdvance.cpp

Lines changed: 97 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,35 @@
1010
#include "JoyShockLibrary\JoyShockLibrary.h"
1111
#include "hidapi.h"
1212
#include "DSAdvance.h"
13+
#include <thread>
1314

1415
Gamepad CurGamepad;
1516
InputOutState GamepadOutState;
1617

18+
bool ExternalPedalsConnected = false;
19+
HANDLE hSerial;
20+
std::thread *pArduinoReadThread = NULL;
21+
float PedalsValues[2];
22+
23+
void ArduinoRead()
24+
{
25+
DWORD bytesRead;
26+
27+
while (ExternalPedalsConnected) {
28+
ReadFile(hSerial, &PedalsValues, sizeof(PedalsValues), &bytesRead, 0);
29+
30+
if (PedalsValues[0] > 1.0 || PedalsValues[0] < 0 || PedalsValues[1] > 1.0 || PedalsValues[1] < 0)
31+
{
32+
PedalsValues[0] = 0;
33+
PedalsValues[1] = 0;
34+
35+
PurgeComm(hSerial, PURGE_TXCLEAR | PURGE_RXCLEAR);
36+
}
37+
38+
if (bytesRead == 0) Sleep(1);
39+
}
40+
}
41+
1742
void GamepadSetState(InputOutState OutState)
1843
{
1944
if (CurGamepad.HidHandle != NULL) {
@@ -190,14 +215,14 @@ double RadToDeg(double Rad)
190215
return Rad / 3.14159265358979323846 * 180.0;
191216
}
192217

193-
double OffsetYPR(float f, float f2)
218+
double OffsetYPR(float Angle1, float Angle2)
194219
{
195-
f -= f2;
196-
if (f < -180)
197-
f += 360;
198-
else if (f > 180)
199-
f -= 360;
200-
return f;
220+
Angle1 -= Angle2;
221+
if (Angle1 < -180)
222+
Angle1 += 360;
223+
else if (Angle1 > 180)
224+
Angle1 -= 360;
225+
return Angle1;
201226
}
202227

203228
static std::mutex m;
@@ -217,13 +242,14 @@ VOID CALLBACK notification(
217242
m.unlock();
218243
}
219244

220-
float DeadZoneAxis(float StickAxis, float DeadZoneValue)
245+
float DeadZoneAxis(float StickAxis, float DeadZoneValue) // Possibly wrong
221246
{
222247
if (StickAxis > 0) {
223248
StickAxis -= DeadZoneValue;
224249
if (StickAxis < 0)
225250
StickAxis = 0;
226-
} else if (StickAxis < 0) {
251+
}
252+
else if (StickAxis < 0) {
227253
StickAxis += DeadZoneValue;
228254
if (StickAxis > 0)
229255
StickAxis = 0;
@@ -271,7 +297,7 @@ SHORT ToLeftStick(double Value, float WheelAngle)
271297
return LeftAxisX;
272298
}
273299

274-
void DefMainText(int ControllerCount, int EmuMode, int AimMode, bool ChangeModesWithoutPress, bool ShowBatteryStatus) {
300+
void DefMainText(int ControllerCount, int EmuMode, int AimMode, bool ChangeModesWithoutPress, bool ShowBatteryStatus, bool ExternalPedals) {
275301
system("cls");
276302
if (ControllerCount < 1)
277303
printf("\n Connect DualSense, DualShock 4, Pro controller or Joycons and reset.");
@@ -280,7 +306,7 @@ void DefMainText(int ControllerCount, int EmuMode, int AimMode, bool ChangeModes
280306
if (ControllerCount > 0 && ShowBatteryStatus && CurGamepad.ControllerType == SONY_DUALSENSE) {
281307
printf(" Gamepad mode:");
282308
if (CurGamepad.USBConnection) printf(" wired"); else printf(" wireless (not recomended for gyro aiming)");
283-
printf(", battery charge: %d\%%", CurGamepad.BatteryLevel);
309+
printf(", battery charge: %d\%%.", CurGamepad.BatteryLevel);
284310
if (CurGamepad.BatteryMode == 0x2)
285311
printf(" (charging)", CurGamepad.BatteryLevel);
286312
printf("\n");
@@ -294,6 +320,9 @@ void DefMainText(int ControllerCount, int EmuMode, int AimMode, bool ChangeModes
294320
printf(" Emulation: -");
295321
printf(", press \"ALT\" + \"Q\" to switch.\n");
296322

323+
if (ExternalPedals)
324+
printf(" External pedals connected.\n");
325+
297326
if (AimMode == 1) printf(" AIM mode = mouse"); else printf(" AIM mode = mouse-joystick");
298327
printf(", press \"ALT\" + \"A\" to switch.\n");
299328

@@ -305,7 +334,7 @@ void DefMainText(int ControllerCount, int EmuMode, int AimMode, bool ChangeModes
305334

306335
int main(int argc, char **argv)
307336
{
308-
SetConsoleTitle("DSAdvance 0.6.3");
337+
SetConsoleTitle("DSAdvance 0.7");
309338
// Config parameters
310339
CIniReader IniFile("Config.ini");
311340

@@ -333,7 +362,7 @@ int main(int argc, char **argv)
333362
bool ChangeModesWithoutPress = IniFile.ReadBoolean("Gamepad", "ChangeModesWithoutPress", false);
334363

335364
bool AimMode = IniFile.ReadBoolean("Motion", "AimMode", false);
336-
float MotionWheelAngle = IniFile.ReadFloat("Motion", "WheelAngle", 75);
365+
float MotionWheelAngle = IniFile.ReadFloat("Motion", "WheelAngle", 150) / 2.0f;
337366
float MotionSensX = IniFile.ReadFloat("Motion", "MouseSensX", 3) / 10.0f;;
338367
float MotionSensY = IniFile.ReadFloat("Motion", "MouseSensY", 3) / 10.0f;;
339368
float JoySensX = IniFile.ReadFloat("Motion", "JoySensX", 3);
@@ -342,6 +371,35 @@ int main(int argc, char **argv)
342371
bool PSMultiKey = !IniFile.ReadBoolean("Gamepad", "PSMultiKey", false);
343372
int MicCustomKey = IniFile.ReadInteger("Gamepad", "MicCustomKey", 0);
344373

374+
int ExternalPedalsCOMPort = IniFile.ReadInteger("ExternalPedals", "COMPort", 0);
375+
if (ExternalPedalsCOMPort != 0) {
376+
char sPortName[32];
377+
sprintf_s(sPortName, "\\\\.\\COM%d", ExternalPedalsCOMPort);
378+
379+
hSerial = ::CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
380+
381+
if (hSerial != INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_NOT_FOUND) {
382+
383+
DCB dcbSerialParams = { 0 };
384+
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
385+
386+
if (GetCommState(hSerial, &dcbSerialParams))
387+
{
388+
dcbSerialParams.BaudRate = CBR_115200;
389+
dcbSerialParams.ByteSize = 8;
390+
dcbSerialParams.StopBits = ONESTOPBIT;
391+
dcbSerialParams.Parity = NOPARITY;
392+
393+
if (SetCommState(hSerial, &dcbSerialParams))
394+
{
395+
ExternalPedalsConnected = true;
396+
PurgeComm(hSerial, PURGE_TXCLEAR | PURGE_RXCLEAR);
397+
pArduinoReadThread = new std::thread(ArduinoRead);
398+
}
399+
}
400+
}
401+
}
402+
345403
GamepadSearch();
346404
GamepadOutState.PlayersCount = 0;
347405
GamepadOutState.LEDBlue = 255;
@@ -361,7 +419,7 @@ int main(int argc, char **argv)
361419
int deviceID[4];
362420
JslGetConnectedDeviceHandles(deviceID, controllersCount);
363421

364-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
422+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
365423

366424
JOY_SHOCK_STATE InputState;
367425
MOTION_STATE MotionState;
@@ -384,7 +442,7 @@ int main(int argc, char **argv)
384442
if (((GetAsyncKeyState(VK_MENU) & 0x8000) != 0) && (GetAsyncKeyState(VK_F9) & 0x8000) != 0 && SkipPollCount == 0)
385443
{
386444
DeadZoneMode = !DeadZoneMode;
387-
if (DeadZoneMode == false) DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
445+
if (DeadZoneMode == false) DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
388446
SkipPollCount = SkipPollTimeOut;
389447
}
390448

@@ -400,12 +458,12 @@ int main(int argc, char **argv)
400458
controllersCount = JslConnectDevices();
401459
JslGetConnectedDeviceHandles(deviceID, controllersCount);
402460
//if (CurGamepad.HidHandle != NULL)
403-
//hid_close(CurGamepad.HidHandle); // conflict with jsl?
461+
//hid_close(CurGamepad.HidHandle); // conflict with Jsl?
404462
GamepadSearch();
405463
GamepadSetState(GamepadOutState);
406464
BTReset = false;
407465
SkipPollCount = SkipPollTimeOut;
408-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
466+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
409467
}
410468

411469
if ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0 && (GetAsyncKeyState('Q') & 0x8000) != 0 && SkipPollCount == 0) // Disable Xbox controller emulation for games that support DualSense, DualShock, Nintendo controllers or enable only driving & mouse aiming
@@ -421,21 +479,21 @@ int main(int argc, char **argv)
421479
ret = vigem_target_x360_register_notification(client, x360, &notification, nullptr);
422480
}
423481

424-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
482+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
425483
SkipPollCount = SkipPollTimeOut;
426484
}
427485

428486
if ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0 && (GetAsyncKeyState('A') & 0x8000) != 0 && SkipPollCount == 0)
429487
{
430488
AimMode = !AimMode;
431-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
489+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
432490
SkipPollCount = SkipPollTimeOut;
433491
}
434492

435493
if ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0 && (GetAsyncKeyState('W') & 0x8000) != 0 && SkipPollCount == 0)
436494
{
437495
ChangeModesWithoutPress = !ChangeModesWithoutPress;
438-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false);
496+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected);
439497
SkipPollCount = SkipPollTimeOut;
440498
}
441499

@@ -480,7 +538,7 @@ int main(int argc, char **argv)
480538
GamepadOutState.LEDBlue = 255; GamepadOutState.LEDRed = 0; GamepadOutState.LEDGreen = 0;
481539
// Show battery level
482540
GetBatteryInfo(); BackOutStateCounter = 40; GamepadOutState.PlayersCount = CurGamepad.LEDBatteryLevel; GamepadSetState(GamepadOutState); // JslSetPlayerNumber(deviceID[0], 5);
483-
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, true);
541+
DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, true, ExternalPedalsConnected);
484542
if (ResetOnDefaultMode && SkipPollCount == 0) { SkipPollCount = SkipPollTimeOut; BTReset = true; }
485543
} else { // Touch sticks mode
486544
GamepadMode = TouchpadSticksMode;
@@ -516,6 +574,15 @@ int main(int argc, char **argv)
516574

517575
report.bLeftTrigger = InputState.lTrigger * 255;
518576
report.bRightTrigger = InputState.rTrigger * 255;
577+
578+
if (ExternalPedalsConnected) {
579+
if (InputState.lTrigger == 0)
580+
report.bLeftTrigger = PedalsValues[0] * 255;
581+
if (InputState.rTrigger == 0)
582+
report.bRightTrigger = PedalsValues[1] * 255;
583+
}
584+
585+
519586
if (JslGetControllerType(deviceID[0]) == JS_TYPE_DS || JslGetControllerType(deviceID[0]) == JS_TYPE_DS4) {
520587
report.wButtons |= InputState.buttons & JSMASK_SHARE ? XINPUT_GAMEPAD_BACK : 0;
521588
report.wButtons |= InputState.buttons & JSMASK_OPTIONS ? XINPUT_GAMEPAD_START : 0;
@@ -650,7 +717,7 @@ int main(int argc, char **argv)
650717
}
651718

652719
// Battery level display
653-
if (BackOutStateCounter > 0) { if (BackOutStateCounter == 1) { GamepadOutState.PlayersCount = 0; GamepadSetState(GamepadOutState); DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false); } BackOutStateCounter--; }
720+
if (BackOutStateCounter > 0) { if (BackOutStateCounter == 1) { GamepadOutState.PlayersCount = 0; GamepadSetState(GamepadOutState); DefMainText(controllersCount, XboxGamepadEmuMode, AimMode, ChangeModesWithoutPress, false, ExternalPedalsConnected); } BackOutStateCounter--; }
654721

655722
if (SkipPollCount > 0) SkipPollCount--;
656723
Sleep(SleepTimeOut);
@@ -660,6 +727,14 @@ int main(int argc, char **argv)
660727
if (CurGamepad.HidHandle != NULL)
661728
hid_close(CurGamepad.HidHandle);
662729

730+
if (ExternalPedalsConnected) {
731+
ExternalPedalsConnected = false;
732+
pArduinoReadThread->join();
733+
delete pArduinoReadThread;
734+
pArduinoReadThread = nullptr;
735+
CloseHandle(hSerial);
736+
}
737+
663738
vigem_target_x360_unregister_notification(x360);
664739
vigem_target_remove(client, x360);
665740
vigem_target_free(x360);

Source/DSAdvance/DSAdvance.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,15 @@ struct TouchpadTouch {
7676
float LastAxisX = 0, LastAxisY = 0;
7777
};
7878

79+
//struct _AppStatus {
80+
// int ControllerCount;
81+
// int EmuMode = true;
82+
// int AimMode = false;
83+
// bool ChangeModesWithoutPress = false;
84+
// bool ShowBatteryStatus = false;
85+
// bool ExternalPedals = false;
86+
//};
87+
7988
// https://github.com/JibbSmart/JoyShockLibrary/blob/master/JoyShockLibrary/JoyShock.cpp
8089
uint32_t crc_table[256] = {
8190
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
File renamed without changes.

0 commit comments

Comments
 (0)