diff --git a/HGInstaller64/HGInstaller64.cpp b/HGInstaller64/HGInstaller64.cpp
deleted file mode 100644
index c5e4557..0000000
Binary files a/HGInstaller64/HGInstaller64.cpp and /dev/null differ
diff --git a/HGInstaller64/HGInstaller64.vcxproj b/HGInstaller64/HGInstaller64.vcxproj
deleted file mode 100644
index 4cbe537..0000000
--- a/HGInstaller64/HGInstaller64.vcxproj
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 15.0
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}
- Win32Proj
- HGInstaller64
- 10.0
-
-
-
- Application
- true
- v142
- Unicode
-
-
- Application
- false
- v142
- true
- Unicode
-
-
- Application
- true
- v142
- Unicode
-
-
- Application
- false
- v142
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
- true
-
-
- false
-
-
- false
-
-
-
- Use
- Level3
- Disabled
- true
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
-
-
- Console
- true
- setupapi.lib;%(AdditionalDependencies)
- RequireAdministrator
-
-
-
-
- Use
- Level3
- Disabled
- true
- _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
-
-
- Console
- true
- setupapi.lib;%(AdditionalDependencies)
-
-
-
-
- Use
- Level3
- MaxSpeed
- true
- true
- true
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
-
-
- Console
- true
- true
- true
- setupapi.lib;%(AdditionalDependencies)
-
-
-
-
- Use
- Level3
- MaxSpeed
- true
- true
- true
- NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
-
-
- Console
- true
- true
- true
- setupapi.lib;%(AdditionalDependencies)
-
-
-
-
-
-
-
-
-
- Create
- Create
- Create
- Create
-
-
-
-
-
-
\ No newline at end of file
diff --git a/HGInstaller64/HGInstaller64.vcxproj.filters b/HGInstaller64/HGInstaller64.vcxproj.filters
deleted file mode 100644
index bcf616b..0000000
--- a/HGInstaller64/HGInstaller64.vcxproj.filters
+++ /dev/null
@@ -1,33 +0,0 @@
-п»ї
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
-
-
- Header Files
-
-
- Header Files
-
-
-
-
- Source Files
-
-
- Source Files
-
-
-
\ No newline at end of file
diff --git a/HGInstaller64/stdafx.cpp b/HGInstaller64/stdafx.cpp
deleted file mode 100644
index e994575..0000000
Binary files a/HGInstaller64/stdafx.cpp and /dev/null differ
diff --git a/HGInstaller64/stdafx.h b/HGInstaller64/stdafx.h
deleted file mode 100644
index a9a4557..0000000
Binary files a/HGInstaller64/stdafx.h and /dev/null differ
diff --git a/HGInstaller64/targetver.h b/HGInstaller64/targetver.h
deleted file mode 100644
index 567cd34..0000000
Binary files a/HGInstaller64/targetver.h and /dev/null differ
diff --git a/HidGuardian_signed_Win7-10_x86_x64_latest.zip b/HidGuardian_signed_Win7-10_x86_x64_latest.zip
deleted file mode 100644
index dbfa569..0000000
Binary files a/HidGuardian_signed_Win7-10_x86_x64_latest.zip and /dev/null differ
diff --git a/README.md b/README.md
index 928c719..4caaf91 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,6 @@
irFFB can feed the 360 Hz steering column torque data recently made available in iRacing telemetry to your wheel, upsample and apply low-latency digital filters to the standard (60 Hz) iRacing FFB output and modify the feedback via a number of effects based on live telemetry.
-It can also drive a 'Jetseat' and fans if you have them.
+This version is a stripped version of Rob C's. Where jetseat/hidguradian/fan has been taken out so its FFB only.
There's more detail in the wiki..
diff --git a/irFFB.sln b/irFFB.sln
index fc65b8e..faa1219 100644
--- a/irFFB.sln
+++ b/irFFB.sln
@@ -5,8 +5,6 @@ VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "irFFB", "irFFB\irFFB.vcxproj", "{8BC973E0-815D-4BA3-A461-E09201F29869}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HGInstaller64", "HGInstaller64\HGInstaller64.vcxproj", "{0F49720F-1BB0-4ECC-A255-3474201F8FC8}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -28,16 +26,6 @@ Global
{8BC973E0-815D-4BA3-A461-E09201F29869}.Release|x64.Build.0 = Release|x64
{8BC973E0-815D-4BA3-A461-E09201F29869}.Release|x86.ActiveCfg = Release|Win32
{8BC973E0-815D-4BA3-A461-E09201F29869}.Release|x86.Build.0 = Release|Win32
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|Win32.ActiveCfg = Debug|Win32
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|Win32.Build.0 = Debug|Win32
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|x64.ActiveCfg = Debug|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|x64.Build.0 = Debug|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|x86.ActiveCfg = Debug|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Debug|x86.Build.0 = Debug|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Release|Win32.ActiveCfg = Release|Win32
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Release|x64.ActiveCfg = Release|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Release|x64.Build.0 = Release|x64
- {0F49720F-1BB0-4ECC-A255-3474201F8FC8}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/irFFB/HGInstaller64.dat b/irFFB/HGInstaller64.dat
deleted file mode 100644
index f91790c..0000000
Binary files a/irFFB/HGInstaller64.dat and /dev/null differ
diff --git a/irFFB/IUberwoorf.h b/irFFB/IUberwoorf.h
deleted file mode 100644
index d22dbcd..0000000
--- a/irFFB/IUberwoorf.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef __IUBERURF_INTERFACE_DEFINED__
-#define __IUBERURF_INTERFACE_DEFINED__
-
-#include "unknwn.h"
-
-
-#define UW_STATUS_IN_USE 0 // Используется
-#define UW_STATUS_READY 1 // Подключена
-#define UW_STATUS_NOT_CONNECTED 2 // Не подключена
-#define UW_STATUS_TIMER_ERROR 3 // Ошибка создания таймера
-#define UW_STATUS_UNSUPPORTED_PROTOCOL 4 // Ошибка: устройство запрашивает длину протокола больше предусмотренной
-
-#define UW_SIT_LEFT 0x200 // Сиденье – слева
-#define UW_SIT_RIGHT 0x002 // Сиденье – справа
-#define UW_BACK_LOW_LEFT 0x400 // Низ спины – слева
-#define UW_BACK_LOW_RIGHT 0x004 // Низ спины – справа
-#define UW_BACK_MID_LEFT 0x800 // Середина спины – слева
-#define UW_BACK_MID_RIGHT 0x008 // Середина спины – справа
-#define UW_LEFT 0xE00 // Левая сторона накидки
-#define UW_RIGHT 0x00E // Правая сторона накидки
-#define UW_SIT 0x202 // Сиденье
-#define UW_BACK_LOW 0x404 // Низ спины
-#define UW_BACK_MID 0x808 // Середина спины
-#define UW_ALL_ZONES 0xE0E // Все зоны
-
-// FLE - FILE LOAD ERROR
-#define UW_FLE_NO_ERROR 0 // Нет ошибки загрузки эффекта из файла XML
-#define UW_FLE_XML 1 // Ошибка при загрузке эффекта из файла XML
-#define UW_FLE_FILE_OPEN 2 // Не удалось открыть файл
-#define UW_FLE_XML_PARSE 3 // Ошибка разбора XML
-#define UW_FLE_XML_ELEMENT_NAME 4 // Ошибка с именем элемента XML
-#define UW_FLE_XML_ELEMENT_VALUE 5 // Ошибка со значением элемента XML
-#define UW_FLE_XML_ATTRIBUTE 6 // Ошибка с атрибутом XML
-#define UW_FLE_XML_EMPTY_TAG 7 // Пустой тег
-#define UW_FLE_XML_CLOSING_TAG 8 // Не найден закрывающий тег
-#define UW_FLE_XML_TAG_DEFINITION 9 // Ошибка с оформлением тега
-#define UW_FLE_XML_COMMENT 10 // Ошибка с комментарием
-#define UW_FLE_XML_DECLARATION 11 // Ошибка с заголовком XML-документа
-#define UW_FLE_XML_EMPTY_DOCUMENT 12 // Пустой XML документ
-#define UW_FLE_XML_EOF_OR_NULL 13 // Ошибка конца файла или нулевого символа
-#define UW_FLE_XML_CDATA 14 // Ошибка секции CDATA
-
-#define UW_FLE_PATH_CHAR_CONVERSION 50 // Ошибка преобразования заданного пути к однобайтовой строке
-#define UW_FLE_ROOT 51 // Неверный корневой элемент (не 'uberwoorf_vibro_effect')
-#define UW_FLE_ZONES_MISSING 52 // Атрибут виброзон не найден
-#define UW_FLE_ZONES_INCORRECT 53 // Значение атрибута виброзон не распознано
-#define UW_FLE_VPOINT_INCORRECT 54 // Элемент точки вибрации не распознан
-#define UW_FLE_VPOINT_NOT_UNIQUE 55 // Элемент точки вибрации не уникален
-#define UW_FLE_AMPL_TIME_MISSING 56 // Атрибут амплитуды и/или времени не найден
-#define UW_FLE_AMPL_TIME_INCORRECT 57 // Значение атрибута амплитуды и/или времени не распознано
-#define UW_FLE_VPOINT_UNKNOWN_TAG 58 // Неизвестный тег в описании точки вибрации
-#define UW_FLE_VPOINT_MISSING 59 // Элемент одной из точек вибрации не найден
-#define UW_FLE_VIBRATION_UNKNOWN_TAG 60 // Неизвестный тег в описании вибрации
-#define UW_FLE_NO_VIBRATIONS 61 // Эффект не содержит вибраций
-#define UW_FLE_EFFECT_NOT_FOUND 62 // Эффект с таким дескриптором не найден
-#define UW_FLE_EFFECT_ZERO_LENGTH 63 // Эффект имеет нулевую длительность
-
-#define UW_VALIDATION_NO_ERROR 0 // Нет ошибки проверки вибрации
-#define UW_VALIDATION_FAILURE 80 // Ошибка (exception) в процессе проверки вибрации
-#define UW_VALIDATION_NO_ZONES 81 // Для вибрации не указано ни одной виброзоны
-#define UW_VALIDATION_ZERO_LENGTH 82 // Нулевая длительность вибрации
-#define UW_VALIDATION_LESS_THAN_2_POINTS_OR_1_INFINITE 83 // Должно быть минимум 2 точки вибрации, или 1 со временем бесконечность
-#define UW_VALIDATION_INFINITY_NOT_LAST_OR_SINGLE 84 // Бесконечность может быть последней или единственной засечкой времени
-#define UW_VALIDATION_INFINITY_AMPLITUDE_NOT_AS_PREVIOUS 85 // Если бесконечность есть, то амплитуда должна быть такой же, как на предыдущей засечке
-#define UW_VALIDATION_INFINITY_AMPLITUDE_ZERO 86 // Амплитуда у бесконечной вибрации нулевая
-#define UW_VALIDATION_NEXT_TIME_NOT_EQUAL_OR_MORE 87 // Последующая засечка должна быть равной предыдущей или больше ее
-#define UW_VALIDATION_THREE_OR_MORE_EQUAL_TIMES 88 // Не допускается подряд три и более одинаковых засечек времени
-#define UW_VALIDATION_TIME_OUT_OF_RANGE 89 // Время вне диапазона (0... 1 000 000 мс)
-
-#define UW_LANG_RUSSIAN 0x0419 // Код русского языка
-
-
-
-struct IUberwoorf : public IUnknown
-{
-public:
- virtual HRESULT STDMETHODCALLTYPE uwGetApiVersion(UINT *version) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetStatus(UINT *status) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetSerialNumber(char *serialBuffer, UINT serialBufferSize) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwOpen(UINT *status) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwReset() = 0;
- virtual HRESULT STDMETHODCALLTYPE uwSetGain(UINT gain) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwCreateEffect(UINT *effectHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwSetSimpleVibration(UINT effectHandle, UINT zones,
- UINT startDelay, UINT duration, BYTE amplitude, UINT *vibrationHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwSetVibration(UINT effectHandle, UINT zones,
- UINT *durations, BYTE *amplitudes, UINT count, UINT *vibrationHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwStartEffect(UINT effectHandle, UINT count) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwStopEffect(UINT effectHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwPauseEffect(UINT effectHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwResumeEffect(UINT effectHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwUpdateSimpleVibration(UINT effectHandle, UINT vibrationHandle,
- UINT zones, UINT startDelay, UINT duration, BYTE amplitude) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwUpdateVibration(UINT effectHandle, UINT vibrationHandle,
- UINT zones, UINT *durations, BYTE *amplitudes, UINT count) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwUpdateEffectAmplitudes(UINT effectHandle, UINT coefficient) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwDeleteEffectVibration(UINT vibrationHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwDeleteEffect(UINT effectHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwClose() = 0;
- virtual HRESULT STDMETHODCALLTYPE uwLoadEffectFromFile(UINT effectHandle,
- const wchar_t *effectFilePath, UINT *errorCode) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetEffectLength(UINT effectHandle, UINT *nonInifinitePartMs, bool *isInfinite) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwValidateVibration(UINT *validationResult, UINT zones, UINT count,
- UINT *durations, BYTE *amplitudes) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetErrorDescriptionByCode(UINT errorCode, UINT languageCode, wchar_t *errDescr) = 0;
-
- virtual HRESULT STDMETHODCALLTYPE uwGetEffectInfo(UINT effectHandle, UINT *gain, UINT *vibrationCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetEffectVibrations(UINT effectHandle, UINT *vibrationCount, UINT *vibrationHandles) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetVibrationInfo(UINT vibrationHandle, UINT *zones, UINT *vibrationPointCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetVibrationPoints(UINT vibrationHandle, UINT *vibrationPointCount, UINT *durationPoints, BYTE *amplitudes) = 0;
-
- virtual HRESULT STDMETHODCALLTYPE uwCloneEffect(UINT effectHandle, UINT *clonedEffectHandle) = 0;
-
- virtual HRESULT STDMETHODCALLTYPE uwSetEffectGain(UINT effectHandle, UINT effectGain) = 0;
-
- virtual HRESULT STDMETHODCALLTYPE uwSetVibrationEx(UINT effectHandle, UINT zones, UINT looped,
- UINT *durations, BYTE *amplitudes, UINT count, UINT *vibrationHandle) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwGetVibrationInfoEx(UINT vibrationHandle, UINT *zones, UINT *looped, UINT *vibrationPointCount) = 0;
- virtual HRESULT STDMETHODCALLTYPE uwLoadEffectFromString(UINT effectHandle, const char *content, UINT *errorCode) = 0;
-};
-
-// {0AC11AE4-C1F7-4fa8-B85B-3789EDAA583A}
-DEFINE_GUID(IID_IUberwoorf, 0xac11ae4, 0xc1f7, 0x4fa8, 0xb8, 0x5b, 0x37, 0x89, 0xed, 0xaa, 0x58, 0x3a);
-
-// {22420DBA-2927-4d71-B6B8-028982A62B72}
-DEFINE_GUID(CLSID_Uberwoorf, 0x22420dba, 0x2927, 0x4d71, 0xb6, 0xb8, 0x2, 0x89, 0x82, 0xa6, 0x2b, 0x72);
-
-
-#endif // __IUBERURF_INTERFACE_DEFINED__
-
-
-
diff --git a/irFFB/Resource.h b/irFFB/Resource.h
index 3e62833..86b1fae 100644
--- a/irFFB/Resource.h
+++ b/irFFB/Resource.h
@@ -7,18 +7,19 @@
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
+#define IDS_APP_TITLE_64 104
#define IDM_EXIT 105
#define IDI_IRFFB 107
#define IDI_SMALL 108
#define IDC_IRFFB 109
#define IDR_MAINFRAME 128
+#define IDC_SYSLINK1 1001
#define IDR_HIDG64 8192
#define ID_SETTINGS_JETSEAT 32774
#define ID_SETTINGS_FAN 32775
#define ID_SETTINGS_HIDGUARDIAN 32778
#define ID_SETTINGS_TRACTIONLOSS 32779
#define IDC_STATIC -1
-#define IDC_SYSLINK1 1001
// Next default values for new objects
//
diff --git a/irFFB/Settings.h b/irFFB/Settings.h
index c0c2fcb..dc6c995 100644
--- a/irFFB/Settings.h
+++ b/irFFB/Settings.h
@@ -35,6 +35,15 @@ class Settings {
sWins_t *getUndersteerWnd() { return understeerWnd; };
void setUndersteerOffsetWnd(sWins_t *);
sWins_t *getUndersteerOffsetWnd() { return understeerOffsetWnd; };
+
+ void setUndersteerYawRateMultWnd(sWins_t*);
+ sWins_t* getUndersteerYawRateMultWnd() { return understeerYawRateMultWnd; };
+ void setUndersteerlatAccelDivWnd(sWins_t*);
+ sWins_t* getUndersteerlatAccelDivWnd() { return understeerlatAccelDivWnd; };
+
+ void setOverlayTransparencyWnd(sWins_t*);
+ sWins_t* getOverlayTransparencyWnd() { return overlayTransparencyWnd; };
+
void setUse360Wnd(HWND);
HWND getUse360Wnd() { return use360Wnd; };
void setCarSpecificWnd(HWND);
@@ -47,6 +56,12 @@ class Settings {
HWND getStartMinimisedWnd() { return startMinimisedWnd; };
void setDebugWnd(HWND);
HWND getDebugWnd() { return debugWnd; };
+ void setAltTimerWnd(HWND);
+ HWND getAltTimerWnd() { return altTimerWnd; };
+ void setForceOverlayWnd(HWND);
+ HWND getForceOverlayWnd() { return forceOverlayWnd; };
+ void setOverlayMaxForceWnd(HWND);
+ HWND getOverlayMaxForceWnd() { return overlayMaxForceWnd; };
void clearFfbDevices();
void addFfbDevice(GUID dev, const wchar_t *);
@@ -72,6 +87,14 @@ class Settings {
float getUndersteerFactor() { return understeerFactor; };
bool setUndersteerOffset(float, HWND);
float getUndersteerOffset() { return understeerOffset; };
+ bool setUndersteerYawRateMult(float, HWND);
+ float getUndersteerYawRateMult() { return understeerYawRateMult; };
+ bool setUndersteerlatAccelDiv(float, HWND);
+ float getUndersteerlatAccelDiv() { return understeerlatAccelDiv; };
+ bool setOverlayTransparency(float, HWND);
+ float getOverlayTransparency() { return overlayTransparency; };
+ void enableOverlayTransparencyWnd();
+ void disableOverlayTransparencyWnd();
void setUse360ForDirect(bool);
bool getUse360ForDirect() { return use360ForDirect; };
void setUseCarSpecific(bool, char *);
@@ -82,8 +105,20 @@ class Settings {
bool getRunOnStartup() { return runOnStartup; };
void setStartMinimised(bool);
bool getStartMinimised() { return startMinimised; };
+ void setWindowPosX(int X) { windowPosX = X; };
+ int getWindowPosX(){ return windowPosX; };
+ void setWindowPosY(int Y) { windowPosY = Y; };
+ int getWindowPosY() { return windowPosY; };
+
void setDebug(bool);
bool getDebug() { return debug; };
+
+ void setUseAltTimer(bool);
+ bool getUseAltTimer() { return useAltTimer; };
+ void setShowForceOverlay(bool);
+ bool getShowForceOverlay() { return showForceOverlay; };
+
+
float getBumpsSetting();
int getMinForceSetting();
float getSopOffsetSetting();
@@ -95,23 +130,29 @@ class Settings {
void writeGenericSettings();
void readSettingsForCar(char *);
void writeSettingsForCar(char *);
- PWSTR getLogPath();
+ std::wstring getLogPath();
private:
- HWND devWnd, ffbWnd;
- sWins_t *minWnd, *maxWnd, *bumpsWnd, *dampingWnd, *sopWnd, *sopOffsetWnd, *understeerWnd, *understeerOffsetWnd;
- HWND use360Wnd, carSpecificWnd, reduceWhenParkedWnd;
+ HWND devWnd, ffbWnd, overlayMaxForceWnd;
+ sWins_t *minWnd, *maxWnd, *bumpsWnd, *dampingWnd, *sopWnd, *sopOffsetWnd,
+ *understeerWnd, *understeerOffsetWnd, *understeerYawRateMultWnd, *understeerlatAccelDivWnd,
+ *overlayTransparencyWnd;
+ HWND use360Wnd, carSpecificWnd, reduceWhenParkedWnd, altTimerWnd, forceOverlayWnd;
HWND runOnStartupWnd, startMinimisedWnd, debugWnd;
int ffbType, ffdeviceIdx, minForce, maxForce;
- float scaleFactor, bumpsFactor, dampingFactor, sopFactor, sopOffset, understeerFactor, understeerOffset;
- bool use360ForDirect, useCarSpecific, debug;
+ float scaleFactor, bumpsFactor, dampingFactor, sopFactor, sopOffset,
+ understeerFactor, understeerOffset, understeerYawRateMult, understeerlatAccelDiv,
+ overlayTransparency;
+ bool use360ForDirect, useCarSpecific, debug, useAltTimer, showForceOverlay;
bool reduceWhenParked, runOnStartup, startMinimised;
GUID devGuid = GUID_NULL, ffdevices[MAX_FFB_DEVICES];
wchar_t strbuf[64];
HANDLE debugHnd;
+ int windowPosX, windowPosY;
+
wchar_t *ffbTypeString(int);
- PWSTR getIniPath();
+ std::wstring getIniPath();
void writeWithNewline(std::ofstream &, char *);
};
\ No newline at end of file
diff --git a/irFFB/fan.cpp b/irFFB/fan.cpp
deleted file mode 100644
index 40447b1..0000000
--- a/irFFB/fan.cpp
+++ /dev/null
@@ -1,491 +0,0 @@
-#include
-
-#include "fan.h"
-
-Fan *Fan::instance = nullptr;
-
-Fan *Fan::init() {
- return new Fan();
-}
-
-Fan::Fan() {
-
- instance = this;
-
- if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED)))
- return;
-
- CoInitializeSecurity(
- NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
- );
-
- readSettings();
- enumSerialPorts();
-
-}
-
-ATOM Fan::registerClass(HINSTANCE hInstance) {
-
- WNDCLASSEXW wcex;
-
- wcex.cbSize = sizeof(WNDCLASSEX);
-
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = wndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = 0;
- wcex.lpszClassName = windowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
-
- return RegisterClassExW(&wcex);
-
-}
-
-void Fan::createWindow(HINSTANCE hInst) {
-
- if (!classIsRegistered) {
- registerClass(hInst);
- classIsRegistered = true;
- }
-
- mainWnd = CreateWindowW(
- windowClass, windowClass, WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
- CW_USEDEFAULT, CW_USEDEFAULT, 432, 380,
- NULL, NULL, hInst, NULL
- );
-
- if (!mainWnd)
- return;
-
- windSimFormatWnd = checkbox(mainWnd, L"Use WindSim format?", 40, 20);
- portWnd = combo(mainWnd, L"Fan controller port:", 40, 80);
-
- CreateWindowW(
- L"STATIC", L"Maximum car speed: (0 = auto)",
- WS_CHILD | WS_VISIBLE,
- 40, 160, 300, 20, mainWnd, NULL, hInst, NULL
- );
- maxSpeedWnd = CreateWindowEx(
- WS_EX_CLIENTEDGE, L"EDIT", L"0",
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_OVERLAPPED | ES_NUMBER,
- 52, 184, 188, 24, mainWnd, NULL, hInst, NULL
- );
- speedUnitsWnd = CreateWindowW(
- L"COMBOBOX", nullptr,
- CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_TABSTOP,
- 240, 184, 112, 200, mainWnd, nullptr, hInst, nullptr
- );
- SendMessage(speedUnitsWnd, CB_ADDSTRING, 0, LPARAM(unitStrings[MPH]));
- SendMessage(speedUnitsWnd, CB_ADDSTRING, 0, LPARAM(unitStrings[KPH]));
-
- manualWnd = slider(mainWnd, L"Manual fan speed:", 40, 234, L"0", L"100", false);
-
- setManualSpeed((int)manualSpeed);
- ShowWindow(mainWnd, SW_SHOWNORMAL);
- UpdateWindow(mainWnd);
- enumSerialPorts();
- readSettings();
-
- return;
-
-}
-
-LRESULT CALLBACK Fan::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-
- HWND wnd = (HWND)lParam;
-
- switch (message) {
-
- case WM_COMMAND: {
- int wmId = LOWORD(wParam);
- switch (wmId) {
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
- default:
- if (HIWORD(wParam) == CBN_SELCHANGE) {
- if (wnd == instance->portWnd) {
- int idx = (int)SendMessage(wnd, CB_GETCURSEL, 0, 0);
- if (idx >= 0 && idx < instance->numPorts) {
- instance->fanPort = instance->ports[idx].dev;
- instance->initFanPort();
- }
- }
- else if (wnd == instance->speedUnitsWnd) {
- instance->setSpeedUnits(SendMessage(wnd, CB_GETCURSEL, 0, 0));
- }
- }
- else if (HIWORD(wParam) == BN_CLICKED) {
- bool oldValue = SendMessage(wnd, BM_GETCHECK, 0, 0) == BST_CHECKED;
- if (wnd == instance->windSimFormatWnd)
- instance->setWindSimFormat(!oldValue);
- }
- break;
- }
- }
- break;
-
- case WM_HSCROLL: {
- if (wnd == instance->manualWnd->trackbar) {
- wchar_t strbuf[8];
- int spd = SendMessage(wnd, TBM_GETPOS, 0, 0);
- swprintf_s(strbuf, L"%d", spd);
- instance->setManualSpeed(spd);
- SendMessage(instance->manualWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
- }
- }
- break;
-
- case WM_EDIT_VALUE: {
- if (wnd == instance->manualWnd->value) {
- instance->setManualSpeed(wParam);
- SendMessage(instance->manualWnd->trackbar, TBM_SETPOS, true, wParam);
- }
- }
- break;
-
- case WM_CTLCOLORSTATIC: {
- SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
- return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
- }
- break;
-
- case WM_PAINT: {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- EndPaint(hWnd, &ps);
- }
- break;
-
- case WM_DESTROY: {
- wchar_t buf[16];
- SendMessage(instance->maxSpeedWnd, WM_GETTEXT, 16, LPARAM(buf));
- instance->setMaxSpeed(StrToInt(buf));
- instance->writeSettings();
- }
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
-
- }
-
- return 0;
-
-}
-
-void Fan::setSpeedUnits(int u) {
-
- if (u < 0 || u > 1)
- return;
-
- units = u;
- if (SendMessageW(instance->maxSpeedWnd, WM_GETTEXT, 16, LPARAM(strbuf)))
- maxSpeed = StrToInt(strbuf);
- setMaxSpeed(maxSpeed);
- SendMessage(speedUnitsWnd, CB_SETCURSEL, u, 0);
-
-}
-
-void Fan::setMaxSpeed(int s) {
-
- maxSpeed = s;
-
- if (s == 0) {
- maxSpeedMs = 53;
- goto UPDATE;
- }
-
- if (units == MPH)
- maxSpeedMs = (float)s / 2.237f;
- else
- maxSpeedMs = (float)s / 3.6f;
-
-UPDATE:
- _itow_s(s, strbuf, 10);
- SendMessage(maxSpeedWnd, WM_SETTEXT, 0, LPARAM(strbuf));
-
-}
-
-void Fan::setManualSpeed(int s) {
-
- SendMessage(manualWnd->trackbar, TBM_SETPOS, TRUE, s);
- swprintf_s(strbuf, L"%d", s);
- SendMessage(manualWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
- manualSpeed = (float)s;
- setSpeed(manualSpeed * maxSpeedMs / 100);
-
-}
-
-void Fan::setWindSimFormat(bool ws) {
-
- SendMessage(windSimFormatWnd, BM_SETCHECK, ws ? BST_CHECKED : BST_UNCHECKED, NULL);
- bool reInit = windSimFormat != ws;
- windSimFormat = ws;
- if (reInit)
- initFanPort();
-
-}
-
-void Fan::enumSerialPorts() {
-
- UINT portsSize = numPorts = 0;
-
- IWbemLocator *locator = NULL;
- if (
- FAILED(
- CoCreateInstance(
- CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
- IID_IWbemLocator, reinterpret_cast(&locator)
- )
- )
- ) {
- text(L"Failed to CoCreateInstance of WbemLocator");
- return;
- }
-
- IWbemServices *services = NULL;
- if (
- FAILED(
- locator->ConnectServer(
- _bstr_t("\\\\.\\root\\cimv2"), NULL, NULL, NULL, 0, NULL, NULL, &services
- )
- )
- ) {
- text(L"Failed to connect to cimv2 server");
- locator->Release();
- return;
- }
-
- IEnumWbemClassObject *classObject = NULL;
- HRESULT hr = services->ExecQuery(
- _bstr_t("WQL"), _bstr_t("SELECT * FROM Win32_SerialPort"),
- WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &classObject
- );
-
- if (FAILED(hr)) {
- _com_error err(hr);
- text(L"SerialPort query failed: %s", err.ErrorMessage());
- services->Release();
- locator->Release();
- return;
- }
-
- hr = WBEM_S_NO_ERROR;
-
- while (hr == WBEM_S_NO_ERROR) {
-
- ULONG num = 0;
- IWbemClassObject *obj[16];
-
- if (
- SUCCEEDED(
- classObject->Next(
- WBEM_INFINITE, 16, reinterpret_cast(obj), &num
- )
- )
- ) {
-
- UINT i = 0;
-
- if (num == 0)
- break;
-
- portsSize += sizeof(port) * num;
- ports = (port *)realloc(ports, portsSize);
-
- for (ULONG n = 0; n < num; n++) {
-
- VARIANT name;
- HRESULT hrGet = obj[n]->Get(L"DeviceID", 0, &name, NULL, NULL);
-
- if (
- SUCCEEDED(hrGet) && (name.vt == VT_BSTR) && (wcslen(name.bstrVal) > 3)
- ) {
-
- if (_wcsnicmp(name.bstrVal, L"COM", 3) != 0)
- continue;
-
- VARIANT fname;
- ports[numPorts + i].dev = (wchar_t *)malloc((lstrlen(name.bstrVal) + 5) * sizeof(wchar_t));
- lstrcpy(ports[numPorts + i].dev, L"\\\\.\\");
- lstrcat(ports[numPorts + i].dev, name.bstrVal);
- if (
- FAILED(obj[n]->Get(L"Name", 0, &fname, NULL, NULL)) ||
- fname.vt != VT_BSTR
- )
- ports[numPorts + i].name = StrDupW(name.bstrVal);
- else
- ports[numPorts + i].name = StrDupW(fname.bstrVal);
-
- SendMessage(
- portWnd, CB_ADDSTRING, 0,
- LPARAM(ports[numPorts + i].name)
- );
-
- if (fanPort != nullptr && _wcsnicmp(ports[numPorts + i].dev, fanPort, 128) == 0) {
- SendMessage((HWND)portWnd, CB_SETCURSEL, numPorts + i, 0);
- if (fanHandle == INVALID_HANDLE_VALUE)
- initFanPort();
- }
-
- i++;
-
- }
-
- obj[n]->Release();
-
- }
-
- numPorts += i;
-
- }
- }
-
- classObject->Release();
- services->Release();
- locator->Release();
-
-}
-
-void Fan::initFanPort() {
-
- if (fanPort == nullptr)
- return;
-
- wchar_t *settings = windSimFormat ? L"9600,n,8,1" : L"115200,n,8,1";
-
- if (fanHandle != INVALID_HANDLE_VALUE)
- CloseHandle(fanHandle);
-
- fanHandle = CreateFile(
- fanPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0
- );
-
- DCB dcb;
-
- memset(&dcb, 0, sizeof(dcb));
- dcb.DCBlength = sizeof(dcb);
- if (!BuildCommDCB(settings, &dcb)) {
- text(L"Error building fan control port parameters");
- CloseHandle(fanHandle);
- fanHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- dcb.fAbortOnError = FALSE;
-
- if (!SetCommState(fanHandle, &dcb)) {
- text(L"Error setting fan control port parameters");
- CloseHandle(fanHandle);
- fanHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- COMMTIMEOUTS timeouts;
- memset(&timeouts, 0, sizeof(timeouts));
- timeouts.WriteTotalTimeoutConstant = 10;
- SetCommTimeouts(fanHandle, &timeouts);
-
- text(L"Connected to fan control port");
-
-}
-
-void Fan::setSpeed(float speed) {
-
- if (fanHandle == INVALID_HANDLE_VALUE)
- return;
-
- if (maxSpeed == 0 && speed > maxSpeedMs)
- maxSpeedMs = speed;
-
- byte buf[4];
-
- speed *= 100 / maxSpeedMs;
- speed = minf(speed, 100.0f);
- speed *= windSimFormat ? 2.55f : 1.6f;
-
- int ispeed = (int)speed;
-
- buf[0] = (byte)(ispeed);
- DWORD written;
- DWORD toWrite = 1;
-
- if (windSimFormat) {
- buf[3] = buf[0];
- buf[0] = buf[2] = 255;
- buf[1] = 88;
- toWrite = 4;
- }
-
- COMSTAT comstat;
- DWORD errors;
-
- if (!WriteFile(fanHandle, buf, toWrite, &written, NULL))
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(fanHandle, &errors, &comstat);
-
-}
-
-void Fan::setManualSpeed() {
- setSpeed(manualSpeed * maxSpeedMs / 100);
-}
-
-void Fan::readSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
-
- if (fanPort != nullptr)
- delete[] fanPort;
-
- if (key == NULL) {
- setWindSimFormat(true);
- delete[] fanPort;
- fanPort = nullptr;
- setMaxSpeed(120);
- setSpeedUnits(MPH);
- return;
- }
-
- fanPort = new wchar_t[128];
- DWORD fanPortSize = 128 * sizeof(wchar_t);
-
- if (RegGetValueW(key, nullptr, L"fanPort", RRF_RT_REG_SZ, nullptr, fanPort, &fanPortSize)) {
- delete[] fanPort;
- fanPort = nullptr;
- }
-
- setWindSimFormat(Settings::getRegSetting(key, L"fanWindSimFormat", true));
- setMaxSpeed(Settings::getRegSetting(key, L"fanMaxSpeed", 120));
- setSpeedUnits(Settings::getRegSetting(key, L"fanMaxSpeedUnits", MPH));
-
- RegCloseKey(key);
-
-}
-
-void Fan::writeSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
- DWORD fanPortSz = 0;
-
- if (key == NULL)
- return;
-
- if (fanPort) {
- fanPortSz = (lstrlen(fanPort) + 1) * sizeof(wchar_t);
- RegSetValueEx(key, L"fanPort", 0, REG_SZ, (BYTE *)fanPort, fanPortSz);
- }
-
- Settings::setRegSetting(key, L"fanWindSimFormat", windSimFormat);
- Settings::setRegSetting(key, L"fanMaxSpeed", maxSpeed);
- Settings::setRegSetting(key, L"fanMaxSpeedUnits", units);
-
- RegCloseKey(key);
-
-}
\ No newline at end of file
diff --git a/irFFB/fan.h b/irFFB/fan.h
deleted file mode 100644
index e8d39ab..0000000
--- a/irFFB/fan.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include
-#include
-
-#include "stdafx.h"
-#include "irFFB.h"
-#include "Settings.h"
-
-typedef struct {
- wchar_t *name;
- wchar_t *dev;
-} port;
-
-#define MPH 0
-#define KPH 1
-
-class Fan {
-
- public:
- static Fan *init();
- void createWindow(HINSTANCE);
- void setSpeed(float);
- void setManualSpeed();
-
- private:
- Fan();
- ATOM registerClass(HINSTANCE);
- static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
- void enumSerialPorts();
- void initFanPort();
- void setSpeedUnits(int);
- void setMaxSpeed(int);
- void setManualSpeed(int);
- void setWindSimFormat(bool);
- void readSettings();
- void writeSettings();
-
- static Fan *instance;
-
- wchar_t *windowClass = L"Fan settings";
- wchar_t *unitStrings[2] = { L"mph", L"kph" };
- HWND mainWnd, portWnd, maxSpeedWnd, speedUnitsWnd, windSimFormatWnd;
- sWins_t *manualWnd;
- bool classIsRegistered = false, windSimFormat = true;
- float maxSpeedMs = 0, manualSpeed = 0;
- int numPorts = 0, maxSpeed = 0, units = MPH;
- wchar_t *fanPort = nullptr;
- port *ports = nullptr;
- HANDLE fanHandle = INVALID_HANDLE_VALUE;
- wchar_t strbuf[64];
-
-};
-
diff --git a/irFFB/hidguardian.cpp b/irFFB/hidguardian.cpp
deleted file mode 100644
index 2102d39..0000000
--- a/irFFB/hidguardian.cpp
+++ /dev/null
@@ -1,1743 +0,0 @@
-#include "hidguardian.h"
-
-HidGuardian *HidGuardian::instance = nullptr;
-SERVICE_STATUS_HANDLE HidGuardian::svcStatusHandle;
-SERVICE_STATUS HidGuardian::svcStatus;
-HANDLE HidGuardian::svcStopEvent;
-
-HidGuardian *HidGuardian::init(DWORD pid) {
- return new HidGuardian(pid);
-}
-
-HidGuardian::HidGuardian(DWORD pid) {
-
- instance = this;
- readSettings();
- refreshStatus();
- if (enabled && hgStatus == STATUS_ENABLED) {
- if (queryService() == SERVICE_STOPPED)
- startService();
- Sleep(500);
- whitelist(pid);
- }
-
-}
-
-ATOM HidGuardian::registerClass(HINSTANCE hInstance) {
-
- WNDCLASSEXW wcex;
-
- wcex.cbSize = sizeof(WNDCLASSEX);
-
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = wndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = 0;
- wcex.lpszClassName = windowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
-
- hInst = hInstance;
-
- return RegisterClassExW(&wcex);
-
-}
-
-void HidGuardian::createWindow(HINSTANCE hInst) {
-
- if (!classIsRegistered) {
- registerClass(hInst);
- classIsRegistered = true;
- }
-
- mainWnd = CreateWindowW(
- windowClass, windowClass, WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
- CW_USEDEFAULT, CW_USEDEFAULT, 400, 180,
- NULL, NULL, hInst, NULL
- );
-
- if (!mainWnd)
- return;
-
- statusWnd = CreateWindowW(
- L"STATIC", L"Status: not installed",
- WS_CHILD | WS_VISIBLE,
- 40, 30, 150, 40, mainWnd, NULL, hInst, NULL
- );
-
- svcWnd = CreateWindowW(
- L"STATIC", L"Service: not installed",
- WS_CHILD | WS_VISIBLE,
- 220, 30, 300, 40, mainWnd, NULL, hInst, NULL
- );
-
- installWnd = CreateWindowW(
- L"BUTTON", L"Install",
- WS_CHILD | WS_VISIBLE,
- 40, 70, 100, 30, mainWnd, NULL, hInst, NULL
- );
-
- enabledWnd = checkbox(mainWnd, L"Enable", 220, 56);
-
- ShowWindow(mainWnd, SW_SHOWNORMAL);
- UpdateWindow(mainWnd);
- refreshStatus();
- setSvcStatus(queryService());
- return;
-
-}
-
-LRESULT CALLBACK HidGuardian::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-
- switch (message) {
-
- case WM_COMMAND: {
- int wmId = LOWORD(wParam);
- switch (wmId) {
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
- default:
- if (HIWORD(wParam) == BN_CLICKED) {
- if ((HWND)lParam == instance->installWnd) {
- if (instance->hgStatus == STATUS_NOTINSTALLED)
- instance->install();
- else if (instance->serviceStatus == SERVICE_STOPPED)
- instance->repairService();
- }
- else if ((HWND)lParam == instance->enabledWnd) {
- bool oldValue = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
- instance->setEnabled(!oldValue);
- }
- }
- break;
- }
- }
- break;
-
- case WM_CTLCOLORSTATIC: {
- SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
- return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
- }
- break;
-
- case WM_PAINT: {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- EndPaint(hWnd, &ps);
- }
- break;
-
- case WM_DESTROY:
- instance->writeSettings();
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
-
- }
-
- return 0;
-
-}
-
-void HidGuardian::install() {
-
- BOOL wow64;
- wchar_t *infPath = nullptr;
-
- IsWow64Process(GetCurrentProcess(), &wow64);
-
- if (!isElevated()) {
- elevate(CMDLINE_HGINST);
- return;
- }
-
- if (hgStatus != STATUS_NOTINSTALLED) {
- text(L"HG: already installed");
- goto installSvc;
- }
-
- wchar_t *hidZip = download();
-
- if (hidZip == nullptr)
- return;
-
- wchar_t *hidFld = unzip(hidZip);
-
- if (hidFld == nullptr)
- goto cleanup;
-
- int infPathLen = wcslen(hidFld) + 64;
- infPath = new wchar_t[infPathLen];
- StringCchCopyW(infPath, infPathLen, hidFld);
- if (wow64)
- StringCchCatW(infPath, infPathLen, L"\\x64\\HidGuardian.inf");
- else
- StringCchCatW(infPath, infPathLen, L"\\x86\\HidGuardian.inf");
-
- if (!wow64) {
- text(L"HG: Installing...");
- if (!doInstall(infPath))
- goto del;
- else if (!updateDriver(infPath))
- goto del;
- }
- else {
-
- wchar_t *tmpFile = unpackInstaller64();
-
- if (tmpFile == nullptr)
- goto del;
-
- exInstaller64(tmpFile, infPath);
- DeleteFileW(tmpFile);
- delete[] tmpFile;
-
- }
-
- if (!installFilter())
- goto del;
-
- refreshStatus();
-
-installSvc:
- if (queryService() == -1)
- if (!installService()) {
- text(L"HG: Failed to install service");
- goto del;
- }
-
- setStatus(hgStatus);
-
-del:
- if (infPath != nullptr)
- delete[] infPath;
-cleanup:
- cleanupInstall();
-
-}
-
-bool HidGuardian::isEnabled() {
- return hgStatus == STATUS_ENABLED;
-}
-
-void HidGuardian::setDevice(WORD vid, WORD pid) {
-
- pipeMsg msg;
-
- currentVid = vid;
- currentPid = pid;
-
- if (hgStatus != STATUS_ENABLED)
- return;
-
- msg.cmd = HG_CMD_DEVICE_ADD;
- StringCchPrintf(msg.id.hwid, 32, HG_HWID_FMT, vid, pid);
- UINT resp = sendSvcMsg(&msg);
- if (resp == HG_SVC_RET_SUCCESS)
- text(L"HG: *** Dev change - unplug/replug or reboot ***");
- else if (resp == HG_SVC_RET_ERROR)
- text(L"HG: Failed to set device");
-
-}
-
-void HidGuardian::removeDevice(WORD vid, WORD pid, bool warn) {
-
- pipeMsg msg;
-
- if (hgStatus != STATUS_ENABLED)
- return;
-
- msg.cmd = HG_CMD_DEVICE_DEL;
- StringCchPrintf(msg.id.hwid, 32, HG_HWID_FMT, vid, pid);
- if (sendSvcMsg(&msg) == HG_SVC_RET_ERROR) {
- text(L"HG: Failed to remove device");
- return;
- }
- if (warn)
- text(L"HG: *** Dev unmasked - unplug/replug or reboot ***");
-
-}
-
-void HidGuardian::whitelist(DWORD pid) {
-
- pipeMsg msg;
-
- if (hgStatus != STATUS_ENABLED || serviceStatus != SERVICE_RUNNING)
- return;
-
- msg.cmd = HG_CMD_WHITELIST_ADD;
- msg.id.pid = pid;
- if (sendSvcMsg(&msg) == HG_SVC_RET_ERROR)
- text(L"HG: Failed to add to whitelist");
-
-}
-
-void HidGuardian::unWhitelist(DWORD pid) {
-
- pipeMsg msg;
-
- msg.cmd = HG_CMD_WHITELIST_DEL;
- msg.id.pid = pid;
- sendSvcMsg(&msg);
-
-}
-
-void HidGuardian::stop(DWORD pid) {
- unWhitelist(pid);
- stopService();
-}
-
-int HidGuardian::getStatus() {
- return hgStatus;
-}
-
-void HidGuardian::setStatus(int s) {
-
- wchar_t buf[64];
-
- if (s < STATUS_NOTINSTALLED || s > STATUS_ENABLED)
- return;
-
- if (s == STATUS_ENABLED && queryService() == SERVICE_STOPPED) {
- hgStatus = s;
- if (startService()) {
- whitelist(GetCurrentProcessId());
- if (currentVid != 0)
- setDevice(currentVid, currentPid);
- }
- else {
- text(L"HG: Service failed to start");
- text(L"HG: Open HidGuardian settings to attempt repair");
- SetWindowTextW(installWnd, L"Repair");
- EnableWindow(installWnd, true);
- goto updatestatus;
- }
- }
- else if (s == STATUS_DISABLED && queryService() == SERVICE_RUNNING) {
- unWhitelist(GetCurrentProcessId());
- if (currentVid != 0)
- removeDevice(currentVid, currentPid, true);
- stopService();
- hgStatus = s;
- }
-
- EnableWindow(installWnd, s == STATUS_NOTINSTALLED);
- updatestatus:
- StringCchPrintfW(buf, 64, L"Status: %s", statuses[hgStatus]);
- SendMessage(statusWnd, WM_SETTEXT, NULL, (LPARAM)buf);
- SendMessage(enabledWnd, BM_SETCHECK, s == STATUS_ENABLED ? BST_CHECKED : BST_UNCHECKED, NULL);
- EnableWindow(svcWnd, s > STATUS_NOTINSTALLED);
- EnableWindow(enabledWnd, s > STATUS_NOTINSTALLED);
-
-
-}
-
-int HidGuardian::refreshStatus() {
-
- ULONG s, problem;
- GUID classGuid = GUID_DEVCLASS_SYSTEM;
-
- hgStatus = STATUS_NOTINSTALLED;
-
- HDEVINFO devInfo = SetupDiGetClassDevsW(&classGuid, NULL, NULL, DIGCF_PRESENT);
-
- if (devInfo == INVALID_HANDLE_VALUE)
- return hgStatus;
-
- SP_DEVINFO_DATA devInfoData = { 0 };
- devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
-
- int idx = 0;
- bool found = false;
- wchar_t buf[64];
- DWORD type, required;
-
- for (idx = 0; SetupDiEnumDeviceInfo(devInfo, idx, &devInfoData); idx++) {
- if (
- !SetupDiGetDeviceRegistryPropertyW(
- devInfo, &devInfoData, SPDRP_HARDWAREID, &type,
- (PBYTE)buf, sizeof(buf), &required
- )
- )
- continue;
-
- if (wcscmp(buf, HG_HARDWARE_ID) == 0) {
- found = true;
- break;
- }
-
- }
-
- if (!found)
- goto release;
-
- if (CM_Get_DevNode_Status(&s, &problem, devInfoData.DevInst, 0) != CR_SUCCESS) {
- text(L"HG: Failed to get status");
- goto release;
- }
-
- if (s & DN_STARTED) {
- if (enabled)
- hgStatus = STATUS_ENABLED;
- else
- hgStatus = STATUS_DISABLED;
- }
-
-release:
-
- SetupDiDestroyDeviceInfoList(devInfo);
- setStatus(hgStatus);
- return hgStatus;
-
-}
-
-void HidGuardian::setEnabled(bool en) {
-
- enabled = en;
-
- if (en && hgStatus == STATUS_DISABLED)
- setStatus(STATUS_ENABLED);
- else if (!en && hgStatus == STATUS_ENABLED)
- setStatus(STATUS_DISABLED);
-
-}
-
-wchar_t *HidGuardian::unpackInstaller64() {
-
- HRSRC hrsrc = FindResourceW(hInst, (LPCWSTR)IDR_HIDG64, RT_RCDATA);
-
- if (hrsrc == NULL) {
- text(L"HG: Failed to locate 64 bit installer resource");
- return nullptr;
- }
-
- DWORD size = SizeofResource(hInst, hrsrc);
- HGLOBAL hGlb = LoadResource(hInst, hrsrc);
-
- if (hGlb == NULL) {
- text(L"HG: Failed to load 64 bit installer resource");
- return nullptr;
- }
-
- BYTE *rbuf = (BYTE *)LockResource(hGlb);
-
- if (rbuf == NULL) {
- text(L"HG: Failed to lock 64 bit installer resource");
- return nullptr;
- }
-
- wchar_t tmpPath[MAX_PATH];
-
- if (!GetTempPathW(MAX_PATH, tmpPath))
- return nullptr;
-
- wchar_t *tmpFile = new wchar_t[MAX_PATH];
- StringCchPrintf(tmpFile, MAX_PATH, L"%s%s", tmpPath, HG_INSTALLER_NAME);
-
- HANDLE file =
- CreateFile(
- tmpFile, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
- );
-
- if (file == INVALID_HANDLE_VALUE) {
- text(L"HG: Failed to create temp file at %s", tmpFile);
- goto delTmpFile;
- }
-
- DWORD written;
- if (!WriteFile(file, rbuf, size, &written, NULL)) {
- text(L"HG: Failed to write to temp file at %s", tmpFile);
- CloseHandle(file);
- goto delTmpFile;
- }
-
- CloseHandle(file);
- return tmpFile;
-
-delTmpFile:
- delete[] tmpFile;
- return nullptr;
-
-}
-
-bool HidGuardian::exInstaller64(wchar_t *path, wchar_t *infPath) {
-
- wchar_t cmdLine[MAX_PATH];
- StringCchCopyW(cmdLine, MAX_PATH, infPath);
-
- text(L"HG: Launching install helper...");
-
- SHELLEXECUTEINFOW sei = { 0 };
- sei.cbSize = sizeof(SHELLEXECUTEINFOW);
- sei.lpVerb = L"runas";
- sei.lpFile = path;
- sei.lpParameters = cmdLine;
- sei.nShow = SW_NORMAL;
- sei.fMask = SEE_MASK_NOCLOSEPROCESS;
-
- if (!ShellExecuteExW(&sei)) {
- if (GetLastError() == ERROR_CANCELLED)
- text(L"HG: Install cancelled");
- else
- text(L"HG: ShellExecute failed: %d", GetLastError());
- return false;
- }
-
- DWORD exitcode = 0;
-
- WaitForSingleObject(sei.hProcess, INFINITE);
- GetExitCodeProcess(sei.hProcess, &exitcode);
- CloseHandle(sei.hProcess);
-
- if (exitcode != 0) {
- if (exitcode > INSTALLER_MAX_ERRORCODE)
- text(L"HG: Unknown error from installer");
- else {
- wchar_t msg[128];
- StringCchPrintfW(msg, 128, L"HG: %s", installerErrors[exitcode]);
- text(msg);
- }
- return false;
- }
-
- text(L"HG: Installed");
- return true;
-
-}
-
-wchar_t *HidGuardian::download() {
-
- DWORD size = 0, inBuf = 0, written = 0;
- wchar_t tmpPath[MAX_PATH];
- HANDLE file;
- BYTE *buf;
- wchar_t *ret = nullptr, *tmpFile = nullptr;
-
- HINTERNET session =
- WinHttpOpen(
- L"irFFB/1.4",
- WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
- WINHTTP_NO_PROXY_NAME,
- WINHTTP_NO_PROXY_BYPASS,
- 0
- );
-
- if (session == NULL) {
- text(L"HG: Failed to open http session");
- return nullptr;
- }
-
- HINTERNET connect =
- WinHttpConnect(session, HG_DOWNLOAD_SITE, INTERNET_DEFAULT_HTTPS_PORT, 0);
-
- if (connect == NULL) {
- text(L"HG: Failed to connect");
- return nullptr;
- }
-
- HINTERNET request =
- WinHttpOpenRequest(
- connect, L"GET",
- HG_DOWNLOAD_PATH,
- NULL,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- WINHTTP_FLAG_SECURE
- );
-
- if (request == NULL) {
- text(L"HG: Failed to open request");
- return nullptr;
- }
-
- if (
- !WinHttpSendRequest(
- request,
- WINHTTP_NO_ADDITIONAL_HEADERS, 0,
- WINHTTP_NO_REQUEST_DATA, 0,
- 0, NULL
- )
- ) {
- text(L"HG: Failed to send request");
- return nullptr;
- }
-
- if (
- !WinHttpReceiveResponse(request, NULL)
- ) {
- text(L"HG: Failed to receive response");
- return nullptr;
- }
-
- if (!GetTempPathW(MAX_PATH, tmpPath))
- return nullptr;
-
- tmpFile = new wchar_t[MAX_PATH];
- srand(GetTickCount());
- StringCchPrintf(tmpFile, MAX_PATH, L"%shidg%x.zip", tmpPath, rand());
-
- file =
- CreateFile(
- tmpFile, GENERIC_WRITE, 0, NULL,
- CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
- );
-
- if (file == INVALID_HANDLE_VALUE) {
- text(L"HG: Failed to create temp file at %s", tmpFile);
- return nullptr;
- }
-
- text(L"HG: Dowloading..");
-
- do {
-
- size = 0;
-
- if (!WinHttpQueryDataAvailable(request, &size))
- goto close;
-
- if (size == 0)
- break;
-
- buf = new BYTE[size + 1];
-
- if (buf == NULL)
- goto close;
-
- ZeroMemory(buf, size + 1);
-
- if (!WinHttpReadData(request, buf, size, &inBuf))
- goto close;
-
- WriteFile(file, buf, inBuf, &written, NULL);
-
- delete[] buf;
-
- } while (size > 0);
-
- zipPath = tmpFile;
-
-close:
- CloseHandle(file);
-
- if (zipPath == nullptr && tmpFile != nullptr)
- delete[] tmpFile;
-
- return zipPath;
-
-}
-
-wchar_t *HidGuardian::unzip(wchar_t *zipPath) {
-
- IShellDispatch *isd = nullptr;
-
- VARIANT zipFile, folder, item, options;
-
- Folder *zipFileFolder = nullptr, *destFolder = nullptr;
- FolderItems *zipItems = nullptr;
-
- IDispatch *itemI;
-
- wchar_t tmpPath[MAX_PATH], *ret = nullptr, *tmpFile = nullptr;
-
- CoInitialize(NULL);
- if (
- CoCreateInstance(
- CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&isd
- ) != S_OK
- ) {
- text(L"HG: Failed to cocreateinstance of shell server");
- return false;
- }
-
- zipFile.vt = VT_BSTR;
- zipFile.bstrVal = _bstr_t(zipPath);
- isd->NameSpace(zipFile, &zipFileFolder);
-
- if (!zipFileFolder) {
- text(L"HG: Failed to set folder NS to %s", zipPath);
- goto releaseIsd;
- }
-
- if (!GetTempPathW(MAX_PATH, tmpPath))
- goto releaseZipFolder;
-
- int len = wcslen(tmpPath) + 32;
- tmpFile = new wchar_t[len];
- StringCchPrintf(tmpFile, len, L"%shidg%x", tmpPath, rand());
-
- if (!CreateDirectoryW(tmpFile, NULL)) {
- text(L"HG: Failed to create dir at %s", tmpFile);
- goto releaseZipFolder;
- }
-
- folder.vt = VT_BSTR;
- folder.bstrVal = _bstr_t(tmpFile);
- isd->NameSpace(folder, &destFolder);
-
- if (!destFolder) {
- text(L"HG: Failed to set folder NS to %s", tmpFile);
- goto releaseZipFolder;
- }
-
- zipFileFolder->Items(&zipItems);
-
- if (!zipItems) {
- text(L"HG: Failed to enum zip items");
- goto releaseDestFolder;
- }
-
- zipItems->QueryInterface(IID_IDispatch, (void **)&itemI);
-
- item.vt = VT_DISPATCH;
- item.pdispVal = itemI;
-
- options.vt = VT_I4;
- options.lVal = 1024 | 512 | 16 | 4;
-
- text(L"HG: Decompressing...");
-
- if (destFolder->CopyHere(item, options) == S_OK)
- fldPath = tmpFile;
-
- itemI->Release();
- zipItems->Release();
-releaseDestFolder:
- destFolder->Release();
-releaseZipFolder:
- zipFileFolder->Release();
-releaseIsd:
- isd->Release();
-
- if (fldPath == nullptr && tmpFile != nullptr)
- delete[] tmpFile;
-
- return fldPath;
-
-}
-
-bool HidGuardian::doInstall(wchar_t *infPath) {
-
- GUID classGuid;
- wchar_t hwIds[64], className[MAX_CLASS_NAME_LEN];
- HDEVINFO devInfo;
- SP_DEVINFO_DATA devInfoData;
- bool ret = false;
-
- ZeroMemory(hwIds, sizeof(hwIds));
- StringCchCopy(hwIds, 64, HG_HARDWARE_ID);
-
- if (!SetupDiGetINFClass(infPath, &classGuid, className, MAX_CLASS_NAME_LEN, 0)) {
- text(L"HG: Failed to get INF class from %s", infPath);
- return false;
- }
-
- devInfo = SetupDiCreateDeviceInfoList(&classGuid, NULL);
- if (devInfo == INVALID_HANDLE_VALUE) {
- text(L"HG: Failed to create DeviceInfoList");
- return false;
- }
-
- devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
- if (
- !SetupDiCreateDeviceInfoW(
- devInfo, className, &classGuid, NULL, NULL, DICD_GENERATE_ID, &devInfoData
- )
- ) {
- text(L"HG: Failed to create DeviceInfo");
- goto end;
- }
-
- if (
- !SetupDiSetDeviceRegistryProperty(
- devInfo, &devInfoData, SPDRP_HARDWAREID, (LPBYTE)hwIds,
- (wcslen(hwIds) + 2) * sizeof(wchar_t)
- )
- ) {
- text(L"HG: Failed to set device registry property");
- goto end;
- }
-
- if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfo, &devInfoData)) {
- text(L"HG: Class installer failed");
- goto end;
- }
-
- text(L"HG: className is %s", className);
-
- ret = true;
-
-end:
- SetupDiDestroyDeviceInfoList(devInfo);
- return ret;
-
-}
-
-bool HidGuardian::installFilter() {
-
- GUID classGuid;
- DWORD numGuids;
- bool ret = false;
-
- if (!SetupDiClassGuidsFromNameEx(L"HIDClass", &classGuid, 1, &numGuids, NULL, NULL)) {
- text(L"HG: Error getting HIDClass GUID");
- return false;
- }
-
- HKEY key = SetupDiOpenClassRegKeyExW(&classGuid, KEY_WRITE, DIOCR_INSTALLER, NULL, NULL);
-
- if (key == INVALID_HANDLE_VALUE) {
- text(L"HG: Failed to open class reg key");
- return false;
- }
-
- wchar_t *multiSz = getRegMultiSz(key, REGSTR_VAL_UPPERFILTERS);
- wchar_t *newMultiSz = prependToMultiSz(multiSz, HG_FILTER_NAME);
-
- if (newMultiSz != nullptr)
- ret = (
- RegSetValueExW(
- key, REGSTR_VAL_UPPERFILTERS, 0, REG_MULTI_SZ,
- (LPBYTE)newMultiSz, multiSzLen(newMultiSz)
- ) == NO_ERROR
- );
- else
- ret = true;
-
- if (multiSz != nullptr)
- delete[] multiSz;
- if (newMultiSz != nullptr)
- delete[] newMultiSz;
- RegCloseKey(key);
- return ret;
-
-}
-
-bool HidGuardian::updateDriver(wchar_t *infPath) {
-
- HMODULE newDevMod = LoadLibrary(L"newdev.dll");
- UpdateDriverProto updateFn;
-
- if (!newDevMod) {
- text(L"HG: Failed to LoadLibrary newdev.dll");
- return false;
- }
-
- updateFn = (UpdateDriverProto)GetProcAddress(newDevMod, "UpdateDriverForPlugAndPlayDevicesW");
-
- if (!updateFn) {
- text(L"HG: Failed to find UpdateDriverForPlugAndPlayDevicesW");
- return false;
- }
-
- if (!updateFn(NULL, HG_HARDWARE_ID, infPath, INSTALLFLAG_FORCE, NULL)) {
- text(L"HG: Failed to update HG driver");
- return false;
- }
-
- return true;
-
-}
-
-void HidGuardian::cleanupInstall() {
-
- if (zipPath != nullptr)
- DeleteFileW(zipPath);
-
- if (fldPath == nullptr)
- return;
-
- *(fldPath + wcslen(fldPath) + 1) = '\0';
-
- SHFILEOPSTRUCT sfo = { 0 };
- sfo.wFunc = FO_DELETE;
- sfo.pFrom = fldPath;
- sfo.fFlags = FOF_NO_UI;
- SHFileOperationW(&sfo);
-
-}
-
-bool HidGuardian::installService() {
-
- SC_HANDLE scm, svc;
- wchar_t path[MAX_PATH];
- SERVICE_DESCRIPTIONW desc = { L"irFFB HidGuardian service" };
- PSECURITY_DESCRIPTOR sd;
- bool ret = false;
-
- wchar_t *sddl =
- L"D:"
- L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)" // default permissions for local system
- L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)" // default permissions for administrators
- L"(A;;CCLCSWLOCRRC;;;AU)" // default permissions for authenticated users
- L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)" // default permissions for power users
- L"(A;;RPWP;;;IU)"; // allow interactive users to start and stop
-
- StringCchCopy(path, MAX_PATH, L"\"");
-
- if (!GetModuleFileNameW(NULL, path + 1, MAX_PATH - 1)) {
- text(L"HG: Service install - failed to locate module");
- return ret;
- }
-
- StringCchCatW(path, MAX_PATH, L"\" service");
-
- scm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-
- if (scm == nullptr) {
- text(L"HG: Failed to open service manager");
- return ret;
- }
-
- svc =
- CreateServiceW(
- scm, SVCNAME, L"irFFB HG Service", SERVICE_ALL_ACCESS,
- SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
- SERVICE_ERROR_NORMAL, path,
- NULL, NULL, NULL, NULL, NULL
- );
-
- if (svc == nullptr) {
- text(L"HG: Failed to create service");
- goto closeScm;
- }
-
- ChangeServiceConfig2W(svc, SERVICE_CONFIG_DESCRIPTION, &desc);
-
- if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl, SDDL_REVISION_1, &sd, NULL)) {
- text(L"HG: Failed to convert security descriptor");
- goto closeSvc;
- }
-
- if (!SetServiceObjectSecurity(svc, DACL_SECURITY_INFORMATION, sd)) {
- text(L"HG: Failed to set service DACLs");
- goto freeSd;
- }
-
- ret = true;
-
- text(L"HG: irFFB HG service installed");
-
-freeSd:
- LocalFree(sd);
-closeSvc:
- CloseServiceHandle(svc);
-closeScm:
- CloseServiceHandle(scm);
- setSvcStatus(queryService());
- return ret;
-
-}
-
-void HidGuardian::repairService() {
-
- HKEY regKey;
- wchar_t path[MAX_PATH];
-
- if (!isElevated()) {
- elevate(CMDLINE_HGREPAIR);
- return;
- }
-
- StringCbCopyW(path, MAX_PATH, L"\"");
-
- GetModuleFileNameW(NULL, path + 1, MAX_PATH - 2);
-
- StringCchCatW(path, MAX_PATH, L"\" ");
- StringCchCatW(path, MAX_PATH, CMDLINE_HGSVC);
-
- DWORD len = wcslen(path) + 1;;
-
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, HG_SERVICE_KEY, 0, KEY_WRITE, ®Key)) {
- text(L"HG: Failed to open irFFBsvc registry key");
- return;
- }
-
-
- if (RegSetValueExW(regKey, L"ImagePath", 0, REG_EXPAND_SZ, (BYTE *)&path, len * sizeof(wchar_t))) {
- text(L"HG: Failed to update irFFBsvc registry key");
- return;
- }
-
- text(L"HG: Repairing service image path");
-
- RegCloseKey(regKey);
- SetWindowTextW(installWnd, L"Install");
- EnableWindow(installWnd, false);
- setStatus(hgStatus);
-
-}
-
-int HidGuardian::queryService() {
-
- SC_HANDLE scm, svc;
- SERVICE_STATUS_PROCESS status;
- DWORD needed;
- int ret = -1;
-
- scm = OpenSCManagerW(NULL, NULL, STANDARD_RIGHTS_READ);
-
- if (scm == nullptr) {
- text(L"HG: Failed to open service manager");
- return ret;
- }
-
- svc = OpenServiceW(scm, SVCNAME, SERVICE_QUERY_STATUS);
-
- if (svc == nullptr) {
-
- if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
- goto closeScm;
- else {
- text(L"HG: Failed to open service");
- goto closeScm;
- }
-
- }
-
- if (
- !QueryServiceStatusEx(
- svc, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(status), &needed
- )
- ) {
- text(L"HG: Failed to query service");
- goto closeSvc;
- }
-
- ret = status.dwCurrentState;
-
-closeSvc:
- CloseServiceHandle(svc);
-closeScm:
- CloseServiceHandle(scm);
- return ret;
-
-}
-
-bool HidGuardian::startService() {
-
- SC_HANDLE scm, svc;
- LPCWSTR arg = CMDLINE_HGSVC;
- bool ret = false;
-
- if (queryService() != SERVICE_STOPPED)
- return true;
-
- scm = OpenSCManagerW(NULL, NULL, STANDARD_RIGHTS_READ|STANDARD_RIGHTS_EXECUTE);
-
- if (scm == nullptr) {
- text(L"HG: Failed to open service manager");
- return false;
- }
-
- svc = OpenServiceW(scm, SVCNAME, SERVICE_START);
-
- if (svc == nullptr) {
-
- if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
- goto closeScm;
- else {
- text(L"HG: Failed to open service");
- goto closeScm;
- }
-
- }
-
- if (StartService(svc, 1, &arg)) {
- for (int i = 0; i < 10; i++) {
- if (queryService() == SERVICE_RUNNING) {
- ret = true;
- break;
- }
- Sleep(200);
- }
- Sleep(500);
- }
-
- setSvcStatus(queryService());
-
- CloseServiceHandle(svc);
-closeScm:
- CloseServiceHandle(scm);
- return ret;
-
-}
-
-void HidGuardian::stopService() {
-
- SC_HANDLE scm, svc;
- SERVICE_STATUS status;
- wchar_t *arg = L"service";
-
- if (queryService() != SERVICE_RUNNING)
- return;
-
- scm = OpenSCManagerW(NULL, NULL, STANDARD_RIGHTS_READ|STANDARD_RIGHTS_EXECUTE);
-
- if (scm == nullptr) {
- text(L"HG: Failed to open service manager");
- return;
- }
-
- svc = OpenServiceW(scm, SVCNAME, SERVICE_STOP);
-
- if (svc == nullptr) {
-
- if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
- goto closeScm;
- else {
- text(L"HG: Failed to open service");
- goto closeScm;
- }
-
- }
-
- Sleep(500);
-
- if (!ControlService(svc, SERVICE_CONTROL_STOP, &status))
- text(L"HG: Failed to stop service");
- else {
- for (int i = 0; i < 10; i++) {
- if (queryService() == SERVICE_STOPPED)
- break;
- Sleep(500);
- }
- }
-
- setSvcStatus(queryService());
-
- CloseServiceHandle(svc);
-closeScm:
- CloseServiceHandle(scm);
-
-}
-
-void HidGuardian::setSvcStatus(int status) {
-
- wchar_t buf[64];
- wchar_t *sTxt;
-
- serviceStatus = status;
-
- switch (status) {
- case -1: sTxt = L"Not installed"; break;
- case SERVICE_STOP_PENDING: sTxt = L"Stopping"; break;
- case SERVICE_STOPPED: sTxt = L"Stopped"; break;
- case SERVICE_START_PENDING: sTxt = L"Starting"; break;
- case SERVICE_RUNNING: sTxt = L"Running"; break;
- default: sTxt = L"Unknown";
- }
-
- StringCchPrintfW(buf, 64, L"Service: %s", sTxt);
- SendMessage(svcWnd, WM_SETTEXT, NULL, (LPARAM)buf);
-
-}
-
-UINT HidGuardian::sendSvcMsg(pipeMsg *msg) {
-
- DWORD written, mode = PIPE_READMODE_MESSAGE;
- UINT ret = HG_SVC_RET_ERROR;
- UINT resp;
-
- if (msg == nullptr) {
- text(L"HG: null service pipe msg");
- return HG_SVC_RET_ERROR;
- }
-
- if (serviceStatus != SERVICE_RUNNING)
- return HG_SVC_RET_ERROR;
-
- DWORD size =
- (
- msg->cmd == HG_CMD_WHITELIST_ADD ||
- msg->cmd == HG_CMD_WHITELIST_DEL
- ) ?
- PIPE_MSG_SIZE_PID : PIPE_MSG_SIZE_HWID;
-
- HANDLE pipe =
- CreateFileW(
- HG_SVC_PIPE,
- GENERIC_READ|GENERIC_WRITE,
- 0,
- NULL,
- OPEN_EXISTING,
- 0,
- NULL
- );
-
- if (pipe == INVALID_HANDLE_VALUE) {
- text(L"HG: Error opening service pipe: %d", GetLastError());
- return HG_SVC_RET_ERROR;
- }
-
- if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) {
- text(L"HG: Error setting service pipe mode");
- goto closePipe;
- }
-
- if (!WriteFile(pipe, msg, size, &written, NULL)) {
- text(L"HG: Error writing to service pipe");
- goto closePipe;
- }
-
- for (int i = 0; i < 10; i++) {
-
- if (!PeekNamedPipe(pipe, NULL, 0, NULL, &written, NULL)) {
- text(L"HG: Error peeking service pipe");
- goto closePipe;
- }
-
- if (written >= sizeof(resp))
- break;
-
- Sleep(50);
-
- }
-
- if (written < sizeof(resp)) {
- text(L"HG: Timed out reading from service pipe");
- goto closePipe;
- }
-
- if (!ReadFile(pipe, &resp, sizeof(resp), &written, NULL)) {
- text(L"HG: Error reading from service pipe");
- goto closePipe;
- }
-
- ret = resp;
-
-closePipe:
- CloseHandle(pipe);
- return ret;
-
-}
-
-bool HidGuardian::isElevated() {
-
- HANDLE token;
- TOKEN_ELEVATION elevation;
- DWORD retSize = sizeof(TOKEN_ELEVATION);
- bool ret = false;
-
- if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
- if (
- GetTokenInformation(
- token, TokenElevation, &elevation, sizeof(elevation), &retSize
- )
- ) {
- if (elevation.TokenIsElevated)
- ret = true;
- }
- CloseHandle(token);
- }
-
- return ret;
-
-}
-
-void HidGuardian::elevate(wchar_t *param) {
-
- wchar_t modPath[MAX_PATH];
-
- if (!GetModuleFileNameW(NULL, modPath, MAX_PATH))
- return;
-
- SHELLEXECUTEINFOW sei;
- ZeroMemory(&sei, sizeof(SHELLEXECUTEINFOW));
- sei.cbSize = sizeof(SHELLEXECUTEINFOW);
- sei.lpVerb = L"runas";
- sei.lpFile = modPath;
- sei.lpParameters = param;
- sei.nShow = SW_NORMAL;
-
- if (!ShellExecuteExW(&sei)) {
- if (GetLastError() == ERROR_CANCELLED)
- text(L"HG: Installation cancelled");
- else
- text(L"HG: ShellExecute failed");
- }
- else
- exit(0);
-
-}
-
-void HidGuardian::readSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
-
- if (key == NULL) {
- enabled = true;
- return;
- }
-
- enabled = Settings::getRegSetting(key, L"hgEnabled", true);
- RegCloseKey(key);
-
-}
-
-void HidGuardian::writeSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
-
- if (key == NULL)
- return;
-
- Settings::setRegSetting(key, L"hgEnabled", enabled);
- RegCloseKey(key);
-
-}
-
-// Static reg helpers
-
-wchar_t *HidGuardian::getRegMultiSz(HKEY key, LPCTSTR val) {
-
- wchar_t *buf = new wchar_t[1024];
- LONG ret;
- DWORD type, len = 1022 * sizeof(wchar_t);
-
- ret = RegQueryValueEx(key, val, NULL, &type, (PBYTE)buf, &len);
- while (ret != NO_ERROR) {
- if (GetLastError() != ERROR_MORE_DATA)
- goto fail;
- if (type != REG_MULTI_SZ)
- goto fail;
- delete[] buf;
- buf = new wchar_t[len / sizeof(wchar_t) + 2];
- ret = RegQueryValueEx(key, val, NULL, &type, (PBYTE)buf, &len);
- }
-
- buf[len / sizeof(wchar_t)] = '\0';
- buf[len / sizeof(wchar_t) + 1] = '\0';
-
- return buf;
-
-fail:
- delete[] buf;
- return nullptr;
-
-}
-
-wchar_t *HidGuardian::prependToMultiSz(wchar_t *multiSz, wchar_t *value) {
-
- wchar_t *ptr, *scan, *buf = nullptr;
- size_t len, bufLen;
-
- if (multiSz == NULL) {
- bufLen = wcslen(value) + 2;
- buf = new wchar_t[bufLen];
- StringCchCopyW(buf, bufLen, value);
- ptr = buf + bufLen - 1;
- }
- else {
-
- for (scan = multiSz; scan[0]; scan += wcslen(scan) + 1)
- if (!wcscmp(value, scan))
- return nullptr;
-
- bufLen = scan - multiSz + wcslen(value) + 2;
- buf = new wchar_t[bufLen];
- ptr = buf;
-
- StringCchCopyW(ptr, bufLen, value);
- len = wcslen(value) + 1;
- ptr += len;
- bufLen -= len;
-
- for (scan = multiSz; scan[0]; scan += len) {
- StringCchCopy(ptr, bufLen, scan);
- len = wcslen(ptr) + 1;
- ptr += len;
- bufLen -= len;
- }
-
- }
-
- *ptr = '\0';
-
- return buf;
-
-}
-
-wchar_t *HidGuardian::removeFromMultiSz(wchar_t *multiSz, wchar_t *value) {
-
- wchar_t *buf, *ptr, *scan;
- bool matched = false;
- size_t len, oldlen = multiSzLen(multiSz);
-
- if (!oldlen)
- return nullptr;
-
- ptr = buf = new wchar_t[oldlen];
-
- for (scan = multiSz; scan[0]; scan += len) {
-
- len = wcslen(scan) + 1;
-
- if (wcscmp(value, scan)) {
- StringCchCopy(ptr, oldlen, scan);
- oldlen -= len;
- ptr += len;
- }
- else
- matched = true;
-
- }
-
- if (!matched) {
- delete[] buf;
- return nullptr;
- }
-
- *ptr = '\0';
- return buf;
-
-}
-
-size_t HidGuardian::multiSzLen(wchar_t *multiSz) {
-
- wchar_t *scan;
-
- if (multiSz == nullptr)
- return 0;
-
- for (scan = multiSz; scan[0]; scan += wcslen(scan) + 1) {};
- return (++scan - multiSz) * sizeof(wchar_t);
-
-}
-
-// Service stuff
-
-void WINAPI HidGuardian::SvcMain(DWORD argc, LPTSTR argv) {
-
- svcStatusHandle = RegisterServiceCtrlHandlerW(SVCNAME, svcCtrlHandler);
-
- if (svcStatusHandle == INVALID_HANDLE_VALUE) {
- svcReportError(L"Failed to register ctrl handler");
- return;
- }
-
- svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
- svcStatus.dwServiceSpecificExitCode = 0;
- svcReportStatus(SERVICE_START_PENDING, NO_ERROR, 0);
-
- svcStopEvent = CreateEventW(NULL, true, false, L"irFFBsvcStopEvent");
- if (svcStopEvent == INVALID_HANDLE_VALUE) {
- svcReportError(L"Failed to create service stop event");
- svcReportStatus(SERVICE_STOPPED, SERVICE_ERROR_CRITICAL, 0);
- return;
- }
-
- if (!CreateThread(NULL, 0, pipeServerThread, NULL, 0, NULL)) {
- svcReportError(L"Failed to start pipe server thread");
- svcReportStatus(SERVICE_STOPPED, SERVICE_ERROR_CRITICAL, 0);
- return;
- }
-
- svcReportStatus(SERVICE_RUNNING, NO_ERROR, 0);
- WaitForSingleObject(svcStopEvent, INFINITE);
- svcReportStatus(SERVICE_STOPPED, NO_ERROR, 0);
-
-}
-
-void WINAPI HidGuardian::svcCtrlHandler(DWORD ctrl) {
-
- if (ctrl != SERVICE_CONTROL_STOP)
- return;
-
- svcReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
- SetEvent(svcStopEvent);
-
-}
-
-void HidGuardian::svcReportStatus(DWORD status, DWORD exitCode, DWORD waitHint) {
-
- svcStatus.dwCurrentState = status;
- svcStatus.dwWin32ExitCode = exitCode;
- svcStatus.dwWaitHint = waitHint;
- svcStatus.dwControlsAccepted = (status == SERVICE_START_PENDING ? 0 : SERVICE_ACCEPT_STOP);
-
- SetServiceStatus(svcStatusHandle, &svcStatus);
-
-}
-
-void HidGuardian::svcReportError(wchar_t *msg) {
-
- HANDLE evtSrc = RegisterEventSourceW(NULL, SVCNAME);
- LPCTSTR str[] = { SVCNAME, msg };
-
- ReportEventW(evtSrc, EVENTLOG_ERROR_TYPE, 0, 0xC0020001L, NULL, 2, 0, str, NULL);
- DeregisterEventSource(evtSrc);
-
-}
-
-UINT HidGuardian::svcAddDevice(wchar_t *dev) {
-
- HKEY key;
- UINT ret = HG_SVC_RET_ERROR;
-
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, HG_PARAMS_KEY, 0, KEY_ALL_ACCESS, &key)) {
- svcReportError(L"Failed to open HG parameters key");
- return ret;
- }
-
- wchar_t *devices = getRegMultiSz(key, HG_DEVICES_VALUE_NAME);
- wchar_t *newDevices = prependToMultiSz(devices, dev);
-
- if (newDevices != nullptr) {
- if (RegSetValueExW(key, HG_DEVICES_VALUE_NAME, 0, REG_MULTI_SZ, (BYTE *)newDevices, multiSzLen(newDevices)))
- svcReportError(L"Failed to add device");
- else
- ret = HG_SVC_RET_SUCCESS;
- }
- else
- ret = HG_SVC_RET_EXISTS;
-
- if (devices != nullptr)
- delete[] devices;
- if (newDevices != nullptr)
- delete[] newDevices;
-
- RegCloseKey(key);
- return ret;
-
-}
-
-UINT HidGuardian::svcDelDevice(wchar_t *dev) {
-
- HKEY key;
- UINT ret = HG_SVC_RET_ERROR;
-
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, HG_PARAMS_KEY, 0, KEY_ALL_ACCESS, &key)) {
- svcReportError(L"Failed to open HG parameters key");
- return ret;
- }
-
- wchar_t *devices = getRegMultiSz(key, HG_DEVICES_VALUE_NAME);
-
- if (devices == nullptr)
- goto closeKey;
-
- wchar_t *newDevices = removeFromMultiSz(devices, dev);
-
- if (newDevices == nullptr)
- goto done;
-
- if (RegSetValueExW(key, HG_DEVICES_VALUE_NAME, 0, REG_MULTI_SZ, (BYTE *)newDevices, multiSzLen(newDevices))) {
- svcReportError(L"Failed to remove device");
- goto done;
- }
-
- ret = HG_SVC_RET_SUCCESS;
-
-done:
- if (devices != nullptr)
- delete[] devices;
- if (newDevices != nullptr)
- delete[] newDevices;
-closeKey:
- RegCloseKey(key);
- return ret;
-
-}
-
-UINT HidGuardian::svcAddWlist(UINT pid) {
-
- HKEY key, wlKey, pidKey;
- wchar_t name[MAX_PATH];
- DWORD nameLen = MAX_PATH;
- int idx = 0;
- UINT ret = HG_SVC_RET_ERROR;
-
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, HG_PARAMS_KEY, 0, KEY_ALL_ACCESS, &key)) {
- svcReportError(L"Failed to oepn HG parameters key");
- return ret;
- }
-
- if (
- RegCreateKeyExW(
- key, HG_WHITELIST_SUBKEY, 0, NULL, REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS, NULL, &wlKey, NULL
- )
- ) {
- svcReportError(L"Failed to create/open whitelist key");
- RegCloseKey(key);
- return ret;
- }
-
- while (ret == ERROR_SUCCESS) {
- nameLen = MAX_PATH;
- ret = RegEnumKeyEx(wlKey, idx++, name, &nameLen, 0, NULL, NULL, NULL);
- if (ret != ERROR_SUCCESS)
- break;
- if (_wtoi(name) == pid) {
- ret = HG_SVC_RET_EXISTS;
- goto done;
- }
- }
-
- if (_itow_s(pid, name, 10)) {
- svcReportError(L"Invalid whitelist pid");
- goto done;
- }
-
- if (
- RegCreateKeyExW(
- wlKey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS, NULL, &pidKey, NULL
- )
- ) {
- svcReportError(L"Failed to create whitelist subkey");
- goto done;
- }
-
- RegCloseKey(pidKey);
- ret = HG_SVC_RET_SUCCESS;
-
-done:
- RegCloseKey(wlKey);
- RegCloseKey(key);
- return ret;
-
-}
-
-UINT HidGuardian::svcDelWlist(UINT pid) {
-
- HKEY key;
- UINT ret = HG_SVC_RET_ERROR;
- wchar_t str[MAX_PATH];
-
- StringCchCopy(str, MAX_PATH, HG_PARAMS_KEY);
- StringCchCat(str, MAX_PATH, L"\\");
- StringCchCat(str, MAX_PATH, HG_WHITELIST_SUBKEY);
-
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, str, 0, KEY_ALL_ACCESS, &key)) {
- svcReportError(L"Failed to open HG whitelist key");
- return ret;
- }
-
- if (_itow_s(pid, str, 10)) {
- svcReportError(L"Invalid whitelist pid");
- goto done;
- }
-
- if (!RegDeleteKeyExW(key, str, KEY_ALL_ACCESS, 0))
- ret = HG_SVC_RET_SUCCESS;
-
-done:
- RegCloseKey(key);
- return ret;
-
-}
-
-
-DWORD WINAPI HidGuardian::pipeServerThread(LPVOID arg) {
-
- HANDLE pipe;
- SECURITY_ATTRIBUTES sa;
- wchar_t *sddl =
- L"D:"
- L"(A;;GARCSDWDWOFA;;;SY)" // full control for localsystem
- L"(A;;GARCSDWDWOFA;;;BA)" // full control for admins
- L"(A;;GRRCFR;;;AU)" // read for authenticated users
- L"(A;;GARCFA;;;IU)"; // rwx for interactive users
-
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = false;
-
- if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(sddl, SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) {
- svcReportError(L"Error converting pipe security descriptor");
- return 1;
- }
-
- while (true) {
-
- pipe =
- CreateNamedPipeW(
- HG_SVC_PIPE,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
- PIPE_UNLIMITED_INSTANCES,
- sizeof(UINT),
- sizeof(pipeMsg),
- 0,
- &sa
- );
-
- if (pipe == INVALID_HANDLE_VALUE) {
- svcReportError(L"Error creating named pipe server");
- return 1;
- }
-
- if (!ConnectNamedPipe(pipe, NULL))
- if (GetLastError() != ERROR_PIPE_CONNECTED) {
- svcReportError(L"Error connecting named pipe");
- CloseHandle(pipe);
- continue;
- }
-
- if (!CreateThread(NULL, 0, pipeWorkerThread, (LPVOID)pipe, 0, NULL)) {
- svcReportError(L"Error creating pipe worker thread");
- CloseHandle(pipe);
- }
-
- }
-
- return 0;
-
-}
-
-DWORD WINAPI HidGuardian::pipeWorkerThread(LPVOID arg) {
-
- HANDLE pipe = (HANDLE)arg;
- pipeMsg msg;
- DWORD len;
- UINT resp = HG_SVC_RET_ERROR;
-
- if (pipe == NULL) {
- svcReportError(L"Pipe worker thread got NULL pipe");
- return 1;
- }
-
- while (true) {
-
- if (!ReadFile(pipe, &msg, sizeof(msg), &len, NULL))
- break;
-
- if (len != PIPE_MSG_SIZE_PID && len != PIPE_MSG_SIZE_HWID)
- break;
-
- switch (msg.cmd) {
-
- case HG_CMD_WHITELIST_ADD:
- resp = svcAddWlist(msg.id.pid);
- break;
- case HG_CMD_WHITELIST_DEL:
- resp = svcDelWlist(msg.id.pid);
- break;
- case HG_CMD_DEVICE_ADD:
- resp = svcAddDevice(msg.id.hwid);
- break;
- case HG_CMD_DEVICE_DEL:
- resp = svcDelDevice(msg.id.hwid);
- break;
- default:
- svcReportError(L"Pipe worker, received unknown cmd");
- }
-
- if (!WriteFile(pipe, &resp, sizeof(resp), &len, NULL))
- break;
-
- }
-
- return 0;
-
-}
-
-
diff --git a/irFFB/hidguardian.h b/irFFB/hidguardian.h
deleted file mode 100644
index 91b337a..0000000
--- a/irFFB/hidguardian.h
+++ /dev/null
@@ -1,145 +0,0 @@
-#pragma once
-
-#include "stdafx.h"
-#include "irFFB.h"
-#include "Settings.h"
-
-#define STATUS_NOTINSTALLED 0
-#define STATUS_DISABLED 1
-#define STATUS_ENABLED 2
-
-#define HG_DOWNLOAD_SITE L"github.com"
-#define HG_DOWNLOAD_PATH L"/nlp80/irFFB/raw/master/HidGuardian_signed_Win7-10_x86_x64_latest.zip"
-#define HG_HARDWARE_ID L"Root\\HidGuardian"
-#define HG_FILTER_NAME L"HidGuardian"
-#define HG_INSTALLER_NAME L"irFFB_hg64.exe"
-#define HG_PARAMS_KEY L"SYSTEM\\CurrentControlSet\\Services\\HidGuardian\\Parameters"
-#define HG_SERVICE_KEY L"SYSTEM\\CurrentControlSet\\Services\\irFFBsvc"
-#define HG_WHITELIST_SUBKEY L"Whitelist"
-#define HG_DEVICES_VALUE_NAME L"AffectedDevices"
-#define HG_HWID_FMT L"HID\\VID_%04hx&PID_%04hx"
-#define HG_SVC_PIPE L"\\\\.\\pipe\\irFFB"
-
-#define HG_CMD_WHITELIST_ADD 1
-#define HG_CMD_WHITELIST_DEL 2
-#define HG_CMD_DEVICE_ADD 3
-#define HG_CMD_DEVICE_DEL 4
-
-#define HG_SVC_RET_ERROR 0
-#define HG_SVC_RET_SUCCESS 1
-#define HG_SVC_RET_EXISTS 2
-
-typedef BOOL(WINAPI *UpdateDriverProto)(HWND, LPCTSTR, LPCTSTR, DWORD, PBOOL);
-
-#define INSTALLER_MAX_ERRORCODE 11
-
-static wchar_t *installerErrors[] = {
- L"Success",
- L"Missing INF path argument",
- L"Failed to get class from INF",
- L"Failed to create devInfo list",
- L"Failed to create devInfo",
- L"Failed to set dev reg property",
- L"Failed to call class installer",
- L"Failed to open class reg key",
- L"Failed to set filter reg value",
- L"Failed to loadlibrary newdev.dll",
- L"Failed to locate UpdateDriverForPlugAndPlayDevices",
- L"UpdateDriverForPlugAndPlayDevices failed"
-};
-
-static wchar_t *statuses[] = {
- L"Not installed", L"Disabled", L"Enabled"
-};
-
-#pragma pack(push, 1)
-typedef struct {
- UINT cmd;
- union {
- UINT pid;
- wchar_t hwid[32];
- } id;
-} pipeMsg;
-#pragma pack(pop)
-
-#define PIPE_MSG_SIZE_PID 2 * sizeof(UINT)
-#define PIPE_MSG_SIZE_HWID sizeof(pipeMsg)
-
-class HidGuardian {
-
-public:
- static HidGuardian *init(DWORD);
- ATOM registerClass(HINSTANCE);
- void createWindow(HINSTANCE);
- static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
- void install(void);
- void repairService(void);
- bool isEnabled(void);
- void setDevice(WORD, WORD);
- void removeDevice(WORD, WORD, bool);
- void whitelist(DWORD);
- void unWhitelist(DWORD);
- void stop(DWORD);
-
- static void WINAPI SvcMain(DWORD, LPTSTR);
- static void svcReportError(wchar_t *);
-
-private:
- HidGuardian(DWORD);
- int getStatus(void);
- void setStatus(int);
- int refreshStatus(void);
- void setEnabled(bool);
-
- wchar_t *unpackInstaller64();
- bool exInstaller64(wchar_t *, wchar_t *);
- wchar_t *download(void);
- wchar_t *unzip(wchar_t *);
- bool doInstall(wchar_t *);
- bool installFilter(void);
- bool updateDriver(wchar_t *);
- void cleanupInstall(void);
- bool installService(void);
- int queryService(void);
- bool startService(void);
- void stopService(void);
- void setSvcStatus(int);
- UINT sendSvcMsg(pipeMsg *);
- bool isElevated(void);
- void elevate(wchar_t *);
- void readSettings(void);
- void writeSettings(void);
-
- static wchar_t *getRegMultiSz(HKEY, LPCTSTR);
- static wchar_t *prependToMultiSz(wchar_t *, wchar_t *);
- static wchar_t *removeFromMultiSz(wchar_t *, wchar_t *);
- static size_t multiSzLen(wchar_t *);
-
- static void WINAPI svcCtrlHandler(DWORD);
- static void svcReportStatus(DWORD, DWORD, DWORD);
- static DWORD WINAPI pipeServerThread(LPVOID);
- static DWORD WINAPI pipeWorkerThread(LPVOID);
- static UINT svcAddDevice(wchar_t *);
- static UINT svcDelDevice(wchar_t *);
- static UINT svcAddWlist(UINT);
- static UINT svcDelWlist(UINT);
-
- static HidGuardian *instance;
-
- static SERVICE_STATUS_HANDLE svcStatusHandle;
- static SERVICE_STATUS svcStatus;
- static HANDLE svcStopEvent;
-
- wchar_t *windowClass = L"HidGuardian";
- wchar_t *zipPath = nullptr;
- wchar_t *fldPath = nullptr;
- int hgStatus = STATUS_NOTINSTALLED;
- int serviceStatus = SERVICE_STOPPED;
- bool classIsRegistered = false;
- bool enabled = true;
- WORD currentVid = 0, currentPid = 0;
-
- HINSTANCE hInst = nullptr;
- HWND mainWnd, statusWnd, svcWnd, installWnd, enabledWnd;
-
-};
\ No newline at end of file
diff --git a/irFFB/irFFB.cpp b/irFFB/irFFB.cpp
index 001f011..bced496 100644
--- a/irFFB/irFFB.cpp
+++ b/irFFB/irFFB.cpp
@@ -17,13 +17,13 @@ along with this program. If not, see .
#include "irFFB.h"
#include "Settings.h"
-#include "jetseat.h"
-#include "fan.h"
-#include "hidguardian.h"
#include "public.h"
#include "yaml_parser.h"
#include "vjoyinterface.h"
-
+#include "shlwapi.h"
+#include
+#include
+#include
#define MAX_LOADSTRING 100
#define STATUS_CONNECTED_PART 0
@@ -52,7 +52,7 @@ CRITICAL_SECTION effectCrit;
DIJOYSTATE joyState;
DWORD axes[1] = { DIJOFS_X };
-LONG dir[1] = { 0 };
+LONG dir[1] = { 0 };
DIPERIODIC pforce;
DIEFFECT dieff;
@@ -60,75 +60,74 @@ LogiLedData logiLedData;
DIEFFESCAPE logiEscape;
Settings settings;
-JetSeat *jetseat;
-Fan *fan;
-HidGuardian *hidGuardian;
+
float firc6[] = {
- 0.1295867f, 0.2311436f, 0.2582509f, 0.1923936f, 0.1156718f, 0.0729534f
+ 0.1295867f, 0.2311436f, 0.2582509f, 0.1923936f, 0.1156718f, 0.0729534f
};
float firc12[] = {
- 0.0322661f, 0.0696877f, 0.0967984f, 0.1243019f, 0.1317534f, 0.1388793f,
- 0.1129315f, 0.0844297f, 0.0699100f, 0.0567884f, 0.0430215f, 0.0392321f
+ 0.0322661f, 0.0696877f, 0.0967984f, 0.1243019f, 0.1317534f, 0.1388793f,
+ 0.1129315f, 0.0844297f, 0.0699100f, 0.0567884f, 0.0430215f, 0.0392321f
};
char car[MAX_CAR_NAME];
understeerCoefs usteerCoefs[] = {
- { "astonmartin dbr9", 46.0f, 78.0f },
- { "audirs3lms", 40.0f, 70.0f },
- { "audir8gt3", 52.0f, 78.0f },
- { "bmwm8gte", 46.0f, 78.0f },
- { "bmwm4gt4", 40.0f, 70.0f },
- { "bmwz4gt3", 54.0f, 80.0f },
- { "bmwm4gt3", 37.5f, 82.0f },
- { "c6r", 40.5f, 82.0f },
- { "c8rvettegte", 48.0f, 78.0f },
- { "dallaraf3", 38.0f, 102.0f },
- { "dallarair18", 44.0f, 110.0f },
- { "dallarap217", 44.0f, 110.0f },
- { "ferrari488gt3", 52.0f, 78.0f },
- { "ferrarievogt3", 54.0f, 80.0f },
- { "ferrari488gte", 44.0f, 82.0f },
- { "fordgt gt3", 52.0f, 78.0f },
- { "formulamazda", 34.5f, 96.0f },
- { "formularenault20", 34.5f, 96.0f },
- { "formularenault35", 44.0f, 110.0f },
- { "formulavee", 23.0f, 68.0f },
- { "fr500s", 40.0f, 70.0f },
- { "hondacivictyper", 40.0f, 70.0f },
- { "hpdarx01c", 44.0f, 110.0f },
- { "hyundaielantracn7", 40.0f, 70.0f },
- { "indypropm18", 34.5f, 100.0f },
- { "lamborghinievogt3", 52.0f, 78.0f },
- { "lotus49", 23.8f, 70.0f },
- { "lotus79", 27.8f, 104.0f },
- { "mclaren570sgt4", 40.0f, 70.0f },
- { "mclarenmp4", 52.0f, 78.0f },
- { "mclarenmp430", 38.0f, 110.0f },
- { "mercedesamggt3", 37.5f, 82.0f },
- { "mercedesw12", 48.0f, 120.0f },
- { "mx5 mx52016", 36.0f, 96.0f },
- { "nissangtpzxt", 44.0f, 110.0f },
- { "porsche718gt4", 40.0f, 70.0f },
- { "porsche911cup", 46.0f, 88.0f },
- { "porsche992cup", 48.0f, 90.0f },
- { "porsche911rgt3", 52.0f, 80.0f },
- { "porsche991rsr", 42.0f, 72.0f },
- { "radical sr8", 40.0f, 100.0f },
- { "rt2000", 25.0f, 86.0f },
- { "rufrt12r track", 46.0f, 88.0f },
- { "specracer", 25.0f, 86.0f },
- { "usf2000usf17", 34.5f, 96.0f },
- { "v8supercars fordmustanggt", 52.0f, 78.0f },
- { "v8supercars holden2019", 52.0f, 78.0f },
- { "williamsfw31", 38.0f, 110.0f }
+ { "astonmartin dbr9", 46.0f, 78.0f },
+ { "audirs3lms", 40.0f, 70.0f },
+ { "audir8gt3", 52.0f, 78.0f },
+ { "bmwm8gte", 46.0f, 78.0f },
+ { "bmwm4gt4", 40.0f, 70.0f },
+ { "bmwz4gt3", 54.0f, 80.0f },
+ { "bmwm4gt3", 37.5f, 82.0f },
+ { "c6r", 40.5f, 82.0f },
+ { "c8rvettegte", 48.0f, 78.0f },
+ { "dallaraf3", 38.0f, 102.0f },
+ { "dallarair18", 44.0f, 110.0f },
+ { "dallarap217", 44.0f, 110.0f },
+ { "ferrari488gt3", 52.0f, 78.0f },
+ { "ferrarievogt3", 54.0f, 80.0f },
+ { "ferrari488gte", 44.0f, 82.0f },
+ { "fordgt gt3", 52.0f, 78.0f },
+ { "formulamazda", 34.5f, 96.0f },
+ { "formularenault20", 34.5f, 96.0f },
+ { "formularenault35", 44.0f, 110.0f },
+ { "formulavee", 23.0f, 68.0f },
+ { "fr500s", 40.0f, 70.0f },
+ { "hondacivictyper", 40.0f, 70.0f },
+ { "hpdarx01c", 44.0f, 110.0f },
+ { "hyundaielantracn7", 40.0f, 70.0f },
+ { "indypropm18", 34.5f, 100.0f },
+ { "lamborghinievogt3", 52.0f, 78.0f },
+ { "lotus49", 23.8f, 70.0f },
+ { "lotus79", 27.8f, 104.0f },
+ { "mclaren570sgt4", 40.0f, 70.0f },
+ { "mclarenmp4", 52.0f, 78.0f },
+ { "mclarenmp430", 38.0f, 110.0f },
+ { "mercedesamggt3", 37.5f, 82.0f },
+ { "mercedesw12", 48.0f, 120.0f },
+ { "mx5 mx52016", 36.0f, 96.0f },
+ { "nissangtpzxt", 44.0f, 110.0f },
+ { "porsche718gt4", 40.0f, 70.0f },
+ { "porsche911cup", 46.0f, 88.0f },
+ { "porsche992cup", 48.0f, 90.0f },
+ { "porsche911rgt3", 52.0f, 80.0f },
+ { "porsche991rsr", 42.0f, 72.0f },
+ { "radical sr8", 40.0f, 100.0f },
+ { "rt2000", 25.0f, 86.0f },
+ { "rufrt12r track", 46.0f, 88.0f },
+ { "specracer", 25.0f, 86.0f },
+ { "usf2000usf17", 34.5f, 96.0f },
+ { "v8supercars fordmustanggt", 52.0f, 78.0f },
+ { "v8supercars holden2019", 52.0f, 78.0f },
+ { "williamsfw31", 38.0f, 110.0f },
+ { "dummy", 0.0f, 0.0f }
};
int force = 0;
-volatile float suspForce = 0.0f;
+volatile float suspForce = 0.0f;
volatile float yawForce[DIRECT_INTERP_SAMPLES];
__declspec(align(16)) volatile float suspForceST[DIRECT_INTERP_SAMPLES];
-bool onTrack = false, stopped = true, deviceChangePending = false, logiWheel = false;
+bool onTrack = false, stopped = true, deviceChangePending = false, logiWheel = false, sleepSpin = false;
volatile int ffbMag = 0;
volatile bool nearStops = false;
@@ -137,2163 +136,2499 @@ int numButtons = 0, numPov = 0, vjButtons = 0, vjPov = 0;
UINT samples, clippedSamples;
HANDLE wheelEvent = CreateEvent(nullptr, false, false, L"WheelEvent");
-HANDLE ffbEvent = CreateEvent(nullptr, false, false, L"FFBEvent");
+HANDLE ffbEvent = CreateEvent(nullptr, false, false, L"FFBEvent");
+
+#define ID_SMOOTHPROGRESSCTRL 402
-HWND mainWnd, textWnd, statusWnd;
+int progressClippingMax = 500;
+HWND mainWnd, textWnd, statusWnd, overlayWnd, currentForceWnd, clippingForceWnd, currentForceOverlayWnd, clippingForceOverlayWnd, overlayMoveWnd;
LARGE_INTEGER freq;
int vjDev = 1;
FFB_DATA ffbPacket;
+RTL_OSVERSIONINFOW winVer;
-float *floatvarptr(const char *data, const char *name) {
- int idx = irsdk_varNameToIndex(name);
- if (idx >= 0)
- return (float *)(data + irsdk_getVarHeaderEntry(idx)->offset);
- else
- return nullptr;
+DWORD windowInitialExtendedState = NULL;
+
+
+float* floatvarptr(const char* data, const char* name) {
+ int idx = irsdk_varNameToIndex(name);
+ if (idx >= 0)
+ return (float*)(data + irsdk_getVarHeaderEntry(idx)->offset);
+ else
+ return nullptr;
}
-int *intvarptr(const char *data, const char *name) {
- int idx = irsdk_varNameToIndex(name);
- if (idx >= 0)
- return (int *)(data + irsdk_getVarHeaderEntry(idx)->offset);
- else
- return nullptr;
+int* intvarptr(const char* data, const char* name) {
+ int idx = irsdk_varNameToIndex(name);
+ if (idx >= 0)
+ return (int*)(data + irsdk_getVarHeaderEntry(idx)->offset);
+ else
+ return nullptr;
}
-bool *boolvarptr(const char *data, const char *name) {
- int idx = irsdk_varNameToIndex(name);
- if (idx >= 0)
- return (bool *)(data + irsdk_getVarHeaderEntry(idx)->offset);
- else
- return nullptr;
+bool* boolvarptr(const char* data, const char* name) {
+ int idx = irsdk_varNameToIndex(name);
+ if (idx >= 0)
+ return (bool*)(data + irsdk_getVarHeaderEntry(idx)->offset);
+ else
+ return nullptr;
+}
+
+bool IsSavedDisplayActive()
+{
+ // Check if we have a monitor
+ bool has = false;
+
+ // Iterate over all displays and check if we have a valid one.
+ // If the device ID contains the string default_monitor no monitor is attached.
+ DISPLAY_DEVICE dd;
+ dd.cb = sizeof(dd);
+ int deviceIndex = 0;
+ while (EnumDisplayDevices(0, deviceIndex, &dd, 0))
+ {
+ std::wstring deviceName = dd.DeviceName;
+ int monitorIndex = 0;
+ while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &dd, 0))
+ {
+ size_t len = _tcslen(dd.DeviceID);
+ for (size_t i = 0; i < len; ++i)
+ dd.DeviceID[i] = _totlower(dd.DeviceID[i]);
+
+ has = has || ((len > 10 && _tcsstr(dd.DeviceID, L"default_monitor") == nullptr) && dd.StateFlags & DISPLAY_DEVICE_ACTIVE);
+
+ ++monitorIndex;
+ }
+ ++deviceIndex;
+ }
+
+ return has;
+}
+
+
+RTL_OSVERSIONINFOW GetRealOSVersion() {
+ HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
+ if (hMod) {
+ RtlGetVersionPtr fxPtr = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
+ if (fxPtr != nullptr) {
+ RTL_OSVERSIONINFOW rovi = { 0 };
+ rovi.dwOSVersionInfoSize = sizeof(rovi);
+ if (STATUS_SUCCESS == fxPtr(&rovi)) {
+ return rovi;
+ }
+ }
+ }
+ RTL_OSVERSIONINFOW rovi = { 0 };
+ return rovi;
}
// Thread that reads the wheel, writes to vJoy and updates the DI effect
DWORD WINAPI readWheelThread(LPVOID lParam) {
- UNREFERENCED_PARAMETER(lParam);
-
- HRESULT res;
- JOYSTICK_POSITION vjData;
- DWORD *hats[] = { &vjData.bHats, &vjData.bHatsEx1, &vjData.bHatsEx2, &vjData.bHatsEx3 };
- ResetVJD(vjDev);
- LONG lastX;
- LARGE_INTEGER lastTime, time, elapsed;
- float vel[DIRECT_INTERP_SAMPLES] = { 0.0f }, fd[4] = { 0.0f };
- int velIdx = 0, vi = 0, fdIdx = 0;
- float d = 0.0f;
+ UNREFERENCED_PARAMETER(lParam);
- lastTime.QuadPart = 0;
+ HRESULT res;
+ JOYSTICK_POSITION vjData;
+ DWORD* hats[] = { &vjData.bHats, &vjData.bHatsEx1, &vjData.bHatsEx2, &vjData.bHatsEx3 };
+ ResetVJD(vjDev);
+ LONG lastX;
+ LARGE_INTEGER lastTime, time, elapsed;
+ float vel[DIRECT_INTERP_SAMPLES] = { 0.0f }, fd[4] = { 0.0f };
+ int velIdx = 0, vi = 0, fdIdx = 0;
+ float d = 0.0f;
- while (true) {
+ lastTime.QuadPart = 0;
- DWORD signaled = WaitForSingleObject(wheelEvent, 1);
+ while (true) {
- if (!ffdevice)
- continue;
+ DWORD signaled = WaitForSingleObject(wheelEvent, 1);
- if (signaled == WAIT_OBJECT_0) {
+ if (!ffdevice)
+ continue;
- res = ffdevice->GetDeviceState(sizeof(joyState), &joyState);
- if (res != DI_OK) {
- debug(L"GetDeviceState returned: 0x%x, requesting reacquire", res);
- reacquireDIDevice();
- continue;
- }
+ if (signaled == WAIT_OBJECT_0) {
- vjData.wAxisX = joyState.lX;
- vjData.wAxisY = joyState.lY;
- vjData.wAxisZ = joyState.lZ;
- vjData.wAxisXRot = joyState.lRx;
- vjData.wAxisYRot = joyState.lRy;
- vjData.wAxisZRot = joyState.lRz;
+ res = ffdevice->GetDeviceState(sizeof(joyState), &joyState);
+ if (res != DI_OK) {
+ debug(L"GetDeviceState returned: 0x%x, requesting reacquire", res);
+ reacquireDIDevice();
+ continue;
+ }
- if (vjButtons > 0)
- for (int i = 0; i < numButtons; i++) {
- if (joyState.rgbButtons[i])
- vjData.lButtons |= 1 << i;
- else
- vjData.lButtons &= ~(1 << i);
- }
+ vjData.wAxisX = joyState.lX;
+ vjData.wAxisY = joyState.lY;
+ vjData.wAxisZ = joyState.lZ;
+ vjData.wAxisXRot = joyState.lRx;
+ vjData.wAxisYRot = joyState.lRy;
+ vjData.wAxisZRot = joyState.lRz;
- // This could be wrong, untested..
- if (vjPov > 0)
- for (int i = 0; i < numPov && i < 4; i++)
- *hats[i] = joyState.rgdwPOV[i];
+ if (vjButtons > 0)
+ for (int i = 0; i < numButtons; i++) {
+ if (joyState.rgbButtons[i])
+ vjData.lButtons |= 1 << i;
+ else
+ vjData.lButtons &= ~(1 << i);
+ }
- UpdateVJD(vjDev, (PVOID)&vjData);
+ // This could be wrong, untested..
+ if (vjPov > 0)
+ for (int i = 0; i < numPov && i < 4; i++)
+ *hats[i] = joyState.rgdwPOV[i];
- if (effect == nullptr)
- continue;
+ UpdateVJD(vjDev, (PVOID)&vjData);
+
+ if (effect == nullptr)
+ continue;
- if (settings.getDampingFactor() != 0.0f || nearStops) {
+ if (settings.getDampingFactor() != 0.0f || nearStops) {
- QueryPerformanceCounter(&time);
+ QueryPerformanceCounter(&time);
- if (lastTime.QuadPart != 0) {
- elapsed.QuadPart = (time.QuadPart - lastTime.QuadPart) * 1000000;
- elapsed.QuadPart /= freq.QuadPart;
- vel[velIdx] = (float)(joyState.lX - lastX) / elapsed.QuadPart;
- }
+ if (lastTime.QuadPart != 0) {
+ elapsed.QuadPart = (time.QuadPart - lastTime.QuadPart) * 1000000;
+ elapsed.QuadPart /= freq.QuadPart;
+ vel[velIdx] = (float)(joyState.lX - lastX) / elapsed.QuadPart;
+ }
- lastTime.QuadPart = time.QuadPart;
- lastX = joyState.lX;
+ lastTime.QuadPart = time.QuadPart;
+ lastX = joyState.lX;
- vi = velIdx;
+ vi = velIdx;
- if (++velIdx > DIRECT_INTERP_SAMPLES - 1)
- velIdx = 0;
+ if (++velIdx > DIRECT_INTERP_SAMPLES - 1)
+ velIdx = 0;
- fd[fdIdx] = vel[vi++] * firc6[0];
- for (int i = 1; i < DIRECT_INTERP_SAMPLES; i++) {
- if (vi > DIRECT_INTERP_SAMPLES - 1)
- vi = 0;
- fd[fdIdx] += vel[vi++] * firc6[i];
- }
+ fd[fdIdx] = vel[vi++] * firc6[0];
+ for (int i = 1; i < DIRECT_INTERP_SAMPLES; i++) {
+ if (vi > DIRECT_INTERP_SAMPLES - 1)
+ vi = 0;
+ fd[fdIdx] += vel[vi++] * firc6[i];
+ }
- if (++fdIdx > 3)
- fdIdx = 0;
+ if (++fdIdx > 3)
+ fdIdx = 0;
- d = (fd[0] + fd[1] + fd[2] + fd[3]) / 4.0f;
+ d = (fd[0] + fd[1] + fd[2] + fd[3]) / 4.0f;
- if (nearStops)
- d *= DAMPING_MULTIPLIER_STOPS;
- else
- d *= DAMPING_MULTIPLIER * settings.getDampingFactor();
+ if (nearStops)
+ d *= DAMPING_MULTIPLIER_STOPS;
+ else
+ d *= DAMPING_MULTIPLIER * settings.getDampingFactor();
- }
- else
- d = 0.0f;
+ }
+ else
+ d = 0.0f;
- }
+ }
- pforce.lOffset = ffbMag;
- pforce.lOffset += (int)d;
+ pforce.lOffset = ffbMag;
+ pforce.lOffset += (int)d;
- if (pforce.lOffset > DI_MAX)
- pforce.lOffset = DI_MAX;
- else if (pforce.lOffset < -DI_MAX)
- pforce.lOffset = -DI_MAX;
+ if (pforce.lOffset > DI_MAX)
+ pforce.lOffset = DI_MAX;
+ else if (pforce.lOffset < -DI_MAX)
+ pforce.lOffset = -DI_MAX;
- EnterCriticalSection(&effectCrit);
+ EnterCriticalSection(&effectCrit);
- if (effect == nullptr) {
- LeaveCriticalSection(&effectCrit);
- continue;
- }
+ if (effect == nullptr) {
+ LeaveCriticalSection(&effectCrit);
+ continue;
+ }
- HRESULT hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_NORESTART);
- if (hr != DI_OK) {
- debug(L"SetParameters returned 0x%x, requesting reacquire", hr);
- reacquireDIDevice();
- }
+ HRESULT hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_NORESTART);
+ if (hr != DI_OK) {
+ debug(L"SetParameters returned 0x%x, requesting reacquire", hr);
+ reacquireDIDevice();
+ }
- LeaveCriticalSection(&effectCrit);
+ LeaveCriticalSection(&effectCrit);
- }
+ }
}
// Calculate FFB samples for the direct modes
DWORD WINAPI directFFBThread(LPVOID lParam) {
- UNREFERENCED_PARAMETER(lParam);
- int16_t mag;
-
- float s;
- int r;
- __declspec(align(16)) float prod[12];
- float lastSuspForce = 0, lastYawForce = 0;
- LARGE_INTEGER start;
-
- while (true) {
-
- bool use360 = settings.getUse360ForDirect();
-
- // Signalled when force has been updated
- WaitForSingleObject(ffbEvent, INFINITE);
-
- if (
- settings.getFfbType() != FFBTYPE_DIRECT_FILTER &&
- settings.getFfbType() != FFBTYPE_DIRECT_FILTER_720
- )
- continue;
-
- if (((ffbPacket.data[0] & 0xF0) >> 4) != vjDev)
- continue;
-
- mag = (ffbPacket.data[3] << 8) + ffbPacket.data[2];
-
- QueryPerformanceCounter(&start);
-
- // sign extend
- force = mag;
-
- s = (float)force;
+ UNREFERENCED_PARAMETER(lParam);
+ int16_t mag;
+
+ float s;
+ int r;
+ __declspec(align(16)) float prod[12];
+ float lastSuspForce = 0, lastYawForce = 0;
+ LARGE_INTEGER start;
+
+
+ while (true) {
+
+ bool use360 = settings.getUse360ForDirect();
+
+ // Signalled when force has been updated
+ WaitForSingleObject(ffbEvent, INFINITE);
+
+ if (
+ settings.getFfbType() != FFBTYPE_DIRECT_FILTER &&
+ settings.getFfbType() != FFBTYPE_DIRECT_FILTER_720
+ )
+ continue;
+
+ if (((ffbPacket.data[0] & 0xF0) >> 4) != vjDev)
+ continue;
+
+ mag = (ffbPacket.data[3] << 8) + ffbPacket.data[2];
+
+ QueryPerformanceCounter(&start);
+
+ // sign extend
+ force = mag;
+
+ s = (float)force;
+
+ if (!use360)
+ s += scaleTorque(suspForce);
+
+ if (settings.getFfbType() == FFBTYPE_DIRECT_FILTER_720) {
+
+ prod[0] = s * firc12[0];
+ {
+ __m128 mp0 = _mm_load_ps(prod);
+ __m128 mp1 = _mm_load_ps(prod + 4);
+ __m128 mp2 = _mm_load_ps(prod + 8);
+ mp0 = _mm_add_ps(_mm_add_ps(mp0, mp1), mp2);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ r = _mm_cvttss_si32(mp0);
+ }
+ /*_asm {
+ movaps xmm0, xmmword ptr prod
+ movaps xmm1, xmmword ptr prod+16
+ movaps xmm2, xmmword ptr prod+32
+ addps xmm0, xmm1
+ addps xmm0, xmm2
+ haddps xmm0, xmm0
+ haddps xmm0, xmm0
+ cvttss2si eax, xmm0
+ mov dword ptr r, eax
+ }*/
+
+ if (use360)
+ r += scaleTorque(lastSuspForce + (suspForceST[0] - lastSuspForce) / 2.0f);
+
+ r += scaleTorque(lastYawForce + (yawForce[0] - lastYawForce) / 2.0f);
+
+ setFFB(r);
+
+ for (int i = 1; i < DIRECT_INTERP_SAMPLES * 2 - 1; i++) {
+
+ prod[i] = s * firc12[i];
+ {
+ __m128 mp0 = _mm_load_ps(prod);
+ __m128 mp1 = _mm_load_ps(prod + 4);
+ __m128 mp2 = _mm_load_ps(prod + 8);
+ mp0 = _mm_add_ps(_mm_add_ps(mp0, mp1), mp2);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ r = _mm_cvttss_si32(mp0);
+ }
+ /*
+ _asm {
+ movaps xmm0, xmmword ptr prod
+ movaps xmm1, xmmword ptr prod + 16
+ movaps xmm2, xmmword ptr prod + 32
+ addps xmm0, xmm1
+ addps xmm0, xmm2
+ haddps xmm0, xmm0
+ haddps xmm0, xmm0
+ cvttss2si eax, xmm0
+ mov dword ptr r, eax
+ }
+ */
+ int idx = (i - 1) >> 1;
+ bool odd = i & 1;
+
+ if (use360)
+ r +=
+ scaleTorque(
+ odd ?
+ suspForceST[idx] :
+ suspForceST[idx] + (suspForceST[idx + 1] - suspForceST[idx]) / 2.0f
+ );
+
+ r +=
+ scaleTorque(
+ odd ?
+ yawForce[idx] :
+ yawForce[idx] + (yawForce[idx + 1] - yawForce[idx]) / 2.0f
+ );
+
+ //nanosleep(1380 * i);
+
+ sleepSpinUntil(&start, 1000, 1380 * i);
+ setFFB(r);
+
+ }
+
+ prod[DIRECT_INTERP_SAMPLES * 2 - 1] = s * firc12[DIRECT_INTERP_SAMPLES * 2 - 1];
+ __m128 mp0 = _mm_load_ps(prod);
+ __m128 mp1 = _mm_load_ps(prod + 4);
+ __m128 mp2 = _mm_load_ps(prod + 8);
+ mp0 = _mm_add_ps(_mm_add_ps(mp0, mp1), mp2);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ mp0 = _mm_hadd_ps(mp0, mp0);
+ r = _mm_cvttss_si32(mp0);
+ /*_asm {
+ movaps xmm0, xmmword ptr prod
+ movaps xmm1, xmmword ptr prod + 16
+ movaps xmm2, xmmword ptr prod + 32
+ addps xmm0, xmm1
+ addps xmm0, xmm2
+ haddps xmm0, xmm0
+ haddps xmm0, xmm0
+ cvttss2si eax, xmm0
+ mov dword ptr r, eax
+ }*/
+
+ if (use360)
+ r += scaleTorque(suspForceST[DIRECT_INTERP_SAMPLES - 1]);
+
+ r += scaleTorque(yawForce[DIRECT_INTERP_SAMPLES - 1]);
+
+ //nanosleep(1380 * (DIRECT_INTERP_SAMPLES * 2 - 1));
+ sleepSpinUntil(&start, 1000, 1380 * (DIRECT_INTERP_SAMPLES * 2 - 1));
+ setFFB(r);
+
+ lastSuspForce = suspForceST[DIRECT_INTERP_SAMPLES - 1];
+ lastYawForce = yawForce[DIRECT_INTERP_SAMPLES - 1];
+
+ continue;
+
+ }
+
+ prod[0] = s * firc6[0];
+ r = (int)(prod[0] + prod[1] + prod[2] + prod[3] + prod[4] + prod[5]) +
+ scaleTorque(yawForce[0]);
+
+ if (use360)
+ r += scaleTorque(suspForceST[0]);
+
+ setFFB(r);
+
+ for (int i = 1; i < DIRECT_INTERP_SAMPLES; i++) {
+
+ prod[i] = s * firc6[i];
+ r = (int)(prod[0] + prod[1] + prod[2] + prod[3] + prod[4] + prod[5]) +
+ scaleTorque(yawForce[i]);
+
+ if (use360)
+ r += scaleTorque(suspForceST[i]);
+
+ sleepSpinUntil(&start, 2000, 2760 * i);
+ //nanosleep(2760 * i);
+ setFFB(r);
+ }
+ }
+
+ return 0;
- if (!use360)
- s += scaleTorque(suspForce);
+}
- if (settings.getFfbType() == FFBTYPE_DIRECT_FILTER_720) {
+void resetForces() {
+ debug(L"Resetting forces");
+ suspForce = 0;
+ for (int i = 0; i < DIRECT_INTERP_SAMPLES; i++) {
+ suspForceST[i] = 0;
+ yawForce[i] = 0;
+ }
+ force = 0;
+ setFFB(0);
+}
- prod[0] = s * firc12[0];
+boolean getCarName() {
- _asm {
- movaps xmm0, xmmword ptr prod
- movaps xmm1, xmmword ptr prod+16
- movaps xmm2, xmmword ptr prod+32
- addps xmm0, xmm1
- addps xmm0, xmm2
- haddps xmm0, xmm0
- haddps xmm0, xmm0
- cvttss2si eax, xmm0
- mov dword ptr r, eax
- }
+ char buf[64];
+ const char* ptr;
+ int len = -1, carIdx = -1;
- if (use360)
- r += scaleTorque(lastSuspForce + (suspForceST[0] - lastSuspForce) / 2.0f);
+ car[0] = 0;
- r += scaleTorque(lastYawForce + (yawForce[0] - lastYawForce) / 2.0f);
+ // Get car idx
+ if (!parseYaml(irsdk_getSessionInfoStr(), "DriverInfo:DriverCarIdx:", &ptr, &len))
+ return false;
- setFFB(r);
+ if (len < 0 || len > sizeof(buf) - 1)
+ return false;
- for (int i = 1; i < DIRECT_INTERP_SAMPLES * 2 - 1; i++) {
+ memcpy(buf, ptr, len);
+ buf[len] = 0;
+ carIdx = atoi(buf);
- prod[i] = s * firc12[i];
+ // Get car path
+ sprintf_s(buf, "DriverInfo:Drivers:CarIdx:{%d}CarPath:", carIdx);
+ if (!parseYaml(irsdk_getSessionInfoStr(), buf, &ptr, &len))
+ return false;
+ if (len < 0 || len > sizeof(car) - 1)
+ return false;
- _asm {
- movaps xmm0, xmmword ptr prod
- movaps xmm1, xmmword ptr prod + 16
- movaps xmm2, xmmword ptr prod + 32
- addps xmm0, xmm1
- addps xmm0, xmm2
- haddps xmm0, xmm0
- haddps xmm0, xmm0
- cvttss2si eax, xmm0
- mov dword ptr r, eax
- }
+ memcpy(car, ptr, len);
+ car[len] = 0;
- int idx = (i - 1) >> 1;
- bool odd = i & 1;
+ return true;
- if (use360)
- r +=
- scaleTorque(
- odd ?
- suspForceST[idx] :
- suspForceST[idx] + (suspForceST[idx + 1] - suspForceST[idx]) / 2.0f
- );
+}
- r +=
- scaleTorque(
- odd ?
- yawForce[idx] :
- yawForce[idx] + (yawForce[idx + 1] - yawForce[idx]) / 2.0f
- );
+float getCarRedline() {
- sleepSpinUntil(&start, 0, 1380 * i);
- setFFB(r);
+ char buf[64];
+ const char* ptr;
+ int len = -1;
- }
+ if (parseYaml(irsdk_getSessionInfoStr(), "DriverInfo:DriverCarRedLine:", &ptr, &len)) {
- prod[DIRECT_INTERP_SAMPLES * 2 - 1] = s * firc12[DIRECT_INTERP_SAMPLES * 2 - 1];
- _asm {
- movaps xmm0, xmmword ptr prod
- movaps xmm1, xmmword ptr prod + 16
- movaps xmm2, xmmword ptr prod + 32
- addps xmm0, xmm1
- addps xmm0, xmm2
- haddps xmm0, xmm0
- haddps xmm0, xmm0
- cvttss2si eax, xmm0
- mov dword ptr r, eax
- }
+ if (len < 0 || len > sizeof(buf) - 1)
+ return 8000.0f;
- if (use360)
- r += scaleTorque(suspForceST[DIRECT_INTERP_SAMPLES - 1]);
+ memcpy(buf, ptr, len);
+ buf[len] = 0;
+ return strtof(buf, NULL);
+ }
- r += scaleTorque(yawForce[DIRECT_INTERP_SAMPLES - 1]);
+ return 8000.0f;
- sleepSpinUntil(&start, 0, 1380 * (DIRECT_INTERP_SAMPLES * 2 - 1));
- setFFB(r);
+}
- lastSuspForce = suspForceST[DIRECT_INTERP_SAMPLES - 1];
- lastYawForce = yawForce[DIRECT_INTERP_SAMPLES - 1];
+bool getBuildInCarUsteerCoeffs(char* car) {
- continue;
+ if (settings.getUndersteerlatAccelDiv() > 0 && settings.getUndersteerYawRateMult() > 0)
+ {
+ return true;
+ }
+ for (int i = 0; i < sizeof(usteerCoefs) / sizeof(usteerCoefs[0]); i++)
+ if (!strcmp(car, usteerCoefs[i].car))
+ {
+ debug(L"We have understeer coeffs for car %s", car);
+ settings.setUndersteerYawRateMult(usteerCoefs[i].yawRateMult, (HWND)-1);
+ settings.setUndersteerlatAccelDiv(usteerCoefs[i].latAccelDiv, (HWND)-1);
+ return true;
+ }
- }
-
- prod[0] = s * firc6[0];
- r = (int)(prod[0] + prod[1] + prod[2] + prod[3] + prod[4] + prod[5]) +
- scaleTorque(yawForce[0]);
+ debug(L"No understeer coeffs for car %s", car);
+ return false;
- if (use360)
- r += scaleTorque(suspForceST[0]);
+}
- setFFB(r);
+void clippingReport() {
- for (int i = 1; i < DIRECT_INTERP_SAMPLES; i++) {
+ float clippedPerCent = samples > 0 ? (float)clippedSamples * 100.0f / samples : 0.0f;
+ text(L"%.02f%% of samples were clipped", clippedPerCent);
+ if (clippedPerCent > 2.5f)
+ text(L"Consider increasing max force to reduce clipping");
+ samples = clippedSamples = 0;
- prod[i] = s * firc6[i];
- r = (int)(prod[0] + prod[1] + prod[2] + prod[3] + prod[4] + prod[5]) +
- scaleTorque(yawForce[i]);
+}
- if (use360)
- r += scaleTorque(suspForceST[i]);
+void logiRpmLed(float* rpm, float redline) {
- sleepSpinUntil(&start, 2000, 2760 * i);
- setFFB(r);
+ logiLedData.rpmData.rpm = *rpm / (redline * 0.90f);
+ logiLedData.rpmData.rpmFirstLed = 0.65f;
+ logiLedData.rpmData.rpmRedLine = 1.0f;
- }
+ ffdevice->Escape(&logiEscape);
- }
+}
- return 0;
+void deviceChange() {
-}
+ debug(L"Device change notification");
+ if (!onTrack) {
+ debug(L"Not on track, processing device change");
+ deviceChangePending = false;
+ enumDirectInput();
+ if (!settings.isFfbDevicePresent())
+ releaseDirectInput();
+ }
+ else {
+ debug(L"Deferring device change processing whilst on track");
+ deviceChangePending = true;
+ }
-void resetForces() {
- debug(L"Resetting forces");
- suspForce = 0;
- for (int i = 0; i < DIRECT_INTERP_SAMPLES; i++) {
- suspForceST[i] = 0;
- yawForce[i] = 0;
- }
- force = 0;
- setFFB(0);
}
-boolean getCarName() {
-
- char buf[64];
- const char *ptr;
- int len = -1, carIdx = -1;
+DWORD getDeviceVidPid(LPDIRECTINPUTDEVICE8 dev) {
- car[0] = 0;
+ DIPROPDWORD dipdw;
+ dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+ dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dipdw.diph.dwObj = 0;
+ dipdw.diph.dwHow = DIPH_DEVICE;
- // Get car idx
- if (!parseYaml(irsdk_getSessionInfoStr(), "DriverInfo:DriverCarIdx:", &ptr, &len))
- return false;
+ if (dev == nullptr)
+ return 0;
- if (len < 0 || len > sizeof(buf) - 1)
- return false;
-
- memcpy(buf, ptr, len);
- buf[len] = 0;
- carIdx = atoi(buf);
+ if (!SUCCEEDED(dev->GetProperty(DIPROP_VIDPID, &dipdw.diph)))
+ return 0;
- // Get car path
- sprintf_s(buf, "DriverInfo:Drivers:CarIdx:{%d}CarPath:", carIdx);
- if (!parseYaml(irsdk_getSessionInfoStr(), buf, &ptr, &len))
- return false;
- if (len < 0 || len > sizeof(car) - 1)
- return false;
+ return dipdw.dwData;
- memcpy(car, ptr, len);
- car[len] = 0;
+}
- return true;
-
+void minimise() {
+ debug(L"Minimising window");
+ Shell_NotifyIcon(NIM_ADD, &niData);
+ ShowWindow(mainWnd, SW_HIDE);
}
-float getCarRedline() {
+void restore() {
+ debug(L"Restoring window");
+ Shell_NotifyIcon(NIM_DELETE, &niData);
+ ShowWindow(mainWnd, SW_SHOW);
+ BringWindowToTop(mainWnd);
+ SetForegroundWindow(mainWnd);
+}
- char buf[64];
- const char *ptr;
- int len = -1;
+int APIENTRY wWinMain(
+ _In_ HINSTANCE hInstance,
+ _In_opt_ HINSTANCE hPrevInstance,
+ _In_ LPWSTR lpCmdLine,
+ _In_ int nCmdShow
+) {
- if (parseYaml(irsdk_getSessionInfoStr(), "DriverInfo:DriverCarRedLine:", &ptr, &len)) {
+ UNREFERENCED_PARAMETER(hPrevInstance);
+
+ globalMutex = CreateMutex(NULL, false, L"Global\\irFFB_Mutex");
+
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ exit(0);
+
+ INITCOMMONCONTROLSEX ccEx;
+
+ HANDLE handles[1];
+ char* data = nullptr;
+ bool irConnected = false;
+ MSG msg;
+
+ float* swTorque = nullptr, * swTorqueST = nullptr, * steer = nullptr, * steerMax = nullptr;
+ float* speed = nullptr, * throttle = nullptr, * rpm = nullptr;
+ float* LFshockDeflST = nullptr, * RFshockDeflST = nullptr, * CFshockDeflST = nullptr;
+ float* LRshockDeflST = nullptr, * RRshockDeflST = nullptr;
+ float* vX = nullptr, * vY = nullptr;
+ float* latAccel = nullptr, * yawRate = nullptr;
+ float LFshockDeflLast = -10000, RFshockDeflLast = -10000, CFshockDeflLast = -10000;
+ float LRshockDeflLast = -10000, RRshockDeflLast = -10000;
+ bool* isOnTrack = nullptr;
+ int* trackSurface = nullptr, * gear = nullptr;
+
+ bool inGarage = false;
+ int numHandles = 0, dataLen = 0, lastGear = 0;
+ int STnumSamples = 0, STmaxIdx = 0, lastTrackSurface = -1;
+ float halfSteerMax = 0, lastTorque = 0, lastSuspForce = 0, redline;
+ float yaw = 0.0f, yawFilter[DIRECT_INTERP_SAMPLES];
+
+ ccEx.dwICC = ICC_WIN95_CLASSES | ICC_BAR_CLASSES | ICC_STANDARD_CLASSES;
+ ccEx.dwSize = sizeof(ccEx);
+ InitCommonControlsEx(&ccEx);
+
+ HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_IRFFB));
+#ifdef _M_X64
+ LoadStringW(hInstance, IDS_APP_TITLE_64, szTitle, MAX_LOADSTRING);
+#else// _M_X64
+ LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
+#endif
+
+
+ LoadStringW(hInstance, IDC_IRFFB, szWindowClass, MAX_LOADSTRING);
+ MyRegisterClass(hInstance);
+
+ // Setup DI FFB effect
+ pforce.dwMagnitude = 0;
+ pforce.dwPeriod = INFINITE;
+ pforce.dwPhase = 0;
+ pforce.lOffset = 0;
+
+ ZeroMemory(&dieff, sizeof(dieff));
+ dieff.dwSize = sizeof(DIEFFECT);
+ dieff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
+ dieff.dwDuration = INFINITE;
+ dieff.dwSamplePeriod = 0;
+ dieff.dwGain = DI_FFNOMINALMAX;
+ dieff.dwTriggerButton = DIEB_NOTRIGGER;
+ dieff.dwTriggerRepeatInterval = 0;
+ dieff.cAxes = 1;
+ dieff.rgdwAxes = axes;
+ dieff.rglDirection = dir;
+ dieff.lpEnvelope = NULL;
+ dieff.cbTypeSpecificParams = sizeof(DIPERIODIC);
+ dieff.lpvTypeSpecificParams = &pforce;
+ dieff.dwStartDelay = 0;
+
+ ZeroMemory(&logiLedData, sizeof(logiLedData));
+ logiLedData.size = sizeof(logiLedData);
+ logiLedData.version = 1;
+ ZeroMemory(&logiEscape, sizeof(logiEscape));
+ logiEscape.dwSize = sizeof(DIEFFESCAPE);
+ logiEscape.dwCommand = 0;
+ logiEscape.lpvInBuffer = &logiLedData;
+ logiEscape.cbInBuffer = sizeof(logiLedData);
+
+ InitializeCriticalSection(&effectCrit);
+
+ if (!InitInstance(hInstance, nCmdShow))
+ return FALSE;
+
+ memset(car, 0, sizeof(car));
+ setCarStatus(car);
+ setConnectedStatus(false);
+ setOnTrackStatus(false);
+
+ settings.readGenericSettings();
+ settings.readRegSettings(car);
+ // Hack! try set better sleep resulution with undocumented NtSetTimerResolution, no error checking or nothing for now
+ ULONG CurrentResolution = 0;
+ ULONG MininumResolution = 0;
+ ULONG MaximumResolution = 0;
+ if (STATUS_SUCCESS == NtQueryTimerResolution(&MininumResolution, &MaximumResolution, &CurrentResolution))
+ {
+ NtSetTimerResolution(MaximumResolution, TRUE, &CurrentResolution);
+ }
+ else
+ {
+ text(L"Unable to set high resolution timer, reverting to old sleep routine");
+ }
+
+ sleepSpin = CurrentResolution == 0 || CurrentResolution > 10000;
+
+ winVer = GetRealOSVersion();
+
+ if (winVer.dwMajorVersion < 10 || (winVer.dwMajorVersion == 10 && winVer.dwBuildNumber < 17134) || sleepSpin)
+ {
+ settings.setUseAltTimer(true);
+ EnableWindow(settings.getAltTimerWnd(), FALSE);
+ }
+
+ if (settings.getShowForceOverlay())
+ {
+ SetLayeredWindowAttributes(overlayWnd, 0, settings.getOverlayTransparency(), LWA_ALPHA);
+ SetWindowPos(overlayWnd, NULL, settings.getWindowPosX(), settings.getWindowPosY(), 200, OVERLAY_WINDOW_HEIGHT - 20, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE);
+ EnableWindow(overlayMoveWnd, TRUE);
+ }
+ if (RegisterHotKey(mainWnd, 1, MOD_ALT | MOD_CONTROL | MOD_NOREPEAT, VK_UP))
+ {
+ text(L"Max force+ Hotkey 'ALT + CONTROL + UP' registered");
+ }
+ if (RegisterHotKey(mainWnd, 2, MOD_ALT | MOD_CONTROL | MOD_NOREPEAT, VK_DOWN))
+ {
+ text(L"Max force- Hotkey 'ALT + CONTROL + DOWN' registered");
+ }
+
+ //int posX = settings.getWindowPosX();
+ //int posY = settings.getWindowPosY();
+ //RECT workArea;
+ //SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
+ //posX += workArea.left;
+ //posY += workArea.top;
+
+ // make sure the window is not completely out of sight
+ /*int max_x = GetSystemMetrics(SM_CXSCREEN) -
+ GetSystemMetrics(SM_CXICON);
+ int max_y = GetSystemMetrics(SM_CYSCREEN) -
+ GetSystemMetrics(SM_CYICON);
+
+ posX = min(posX, max_x);
+ posY = min(posY, max_y);
+
+ SetWindowPos(mainWnd, nullptr, posX, posY, 864, 760, 0);*/
+
+ if (settings.getStartMinimised())
+ minimise();
+ else
+ {
+ restore();
+ }
+
+ enumDirectInput();
+
+ LARGE_INTEGER start;
+ QueryPerformanceFrequency(&freq);
+
+ initVJD();
+ SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
+
+ SetThreadPriority(
+ CreateThread(NULL, 0, readWheelThread, NULL, 0, NULL), THREAD_PRIORITY_HIGHEST
+ );
+ SetThreadPriority(
+ CreateThread(NULL, 0, directFFBThread, NULL, 0, NULL), THREAD_PRIORITY_HIGHEST
+ );
+
+ debug(L"Init complete, entering mainloop");
+
+ while (TRUE) {
+
+ DWORD res;
+ const irsdk_header* hdr = NULL;
+
+ if (
+ irsdk_startup() && (hdr = irsdk_getHeader()) &&
+ hdr->status & irsdk_stConnected && hdr->bufLen != dataLen && hdr->bufLen != 0
+ ) {
+
+ debug(L"New iRacing session");
+
+ handles[0] = hDataValidEvent;
+ numHandles = 1;
+
+ if (data != NULL)
+ free(data);
+
+ dataLen = irsdk_getHeader()->bufLen;
+ data = (char*)malloc(dataLen);
+ setConnectedStatus(true);
+
+ if (getCarName() && settings.getUseCarSpecific()) {
+ setCarStatus(car);
+ settings.readSettingsForCar(car);
+ }
+ else
+ setCarStatus(nullptr);
+
+ redline = getCarRedline();
+ debug(L"Redline is %d rpm", (int)redline);
+
+ getBuildInCarUsteerCoeffs(car);
+
+ // Inform iRacing of the maxForce setting
+ irsdk_broadcastMsg(irsdk_BroadcastFFBCommand, irsdk_FFBCommand_MaxForce, (float)settings.getMaxForce());
+
+ swTorque = floatvarptr(data, "SteeringWheelTorque");
+ swTorqueST = floatvarptr(data, "SteeringWheelTorque_ST");
+ steer = floatvarptr(data, "SteeringWheelAngle");
+ steerMax = floatvarptr(data, "SteeringWheelAngleMax");
+ speed = floatvarptr(data, "Speed");
+ throttle = floatvarptr(data, "Throttle");
+ rpm = floatvarptr(data, "RPM");
+ gear = intvarptr(data, "Gear");
+ isOnTrack = boolvarptr(data, "IsOnTrack");
+
+ trackSurface = intvarptr(data, "PlayerTrackSurface");
+ vX = floatvarptr(data, "VelocityX");
+ vY = floatvarptr(data, "VelocityY");
+
+ latAccel = floatvarptr(data, "LatAccel");
+ yawRate = floatvarptr(data, "YawRate");
+
+ RFshockDeflST = floatvarptr(data, "RFshockDefl_ST");
+ LFshockDeflST = floatvarptr(data, "LFshockDefl_ST");
+ LRshockDeflST = floatvarptr(data, "LRshockDefl_ST");
+ RRshockDeflST = floatvarptr(data, "RRshockDefl_ST");
+ CFshockDeflST = floatvarptr(data, "CFshockDefl_ST");
+
+ int swTorqueSTidx = irsdk_varNameToIndex("SteeringWheelTorque_ST");
+ STnumSamples = irsdk_getVarHeaderEntry(swTorqueSTidx)->count;
+ STmaxIdx = STnumSamples - 1;
+
+ lastTorque = 0.0f;
+ onTrack = false;
+ resetForces();
+ irConnected = true;
+ timeBeginPeriod(1);
- if (len < 0 || len > sizeof(buf) - 1)
- return 8000.0f;
-
- memcpy(buf, ptr, len);
- buf[len] = 0;
- return strtof(buf, NULL);
- }
-
- return 8000.0f;
+ }
+
+ res = MsgWaitForMultipleObjects(numHandles, handles, FALSE, 1000, QS_ALLINPUT);
+
+ QueryPerformanceCounter(&start);
+
+ if (numHandles > 0 && res == numHandles - 1 && irsdk_getNewData(data)) {
+
+ if (onTrack && !*isOnTrack) {
+ debug(L"No longer on track");
+ onTrack = false;
+ setOnTrackStatus(onTrack);
+ lastTorque = lastSuspForce = 0.0f;
+ resetForces();
+ clippingReport();
+ }
+
+ else if (!onTrack && *isOnTrack) {
+ debug(L"Now on track");
+ onTrack = true;
+ setOnTrackStatus(onTrack);
+ RFshockDeflLast = LFshockDeflLast =
+ LRshockDeflLast = RRshockDeflLast =
+ CFshockDeflLast = -10000.0f;
+ clippedSamples = samples = lastGear = 0;
+ memset(yawFilter, 0, DIRECT_INTERP_SAMPLES * sizeof(float));
+ irsdk_broadcastMsg(irsdk_BroadcastFFBCommand, irsdk_FFBCommand_MaxForce, (float)settings.getMaxForce());
+ }
+
+ if (*trackSurface != lastTrackSurface) {
+ debug(L"Track surface is now: %d", *trackSurface);
+ lastTrackSurface = *trackSurface;
+ }
+
+ if (ffdevice && logiWheel)
+ logiRpmLed(rpm, redline);
+
+ yaw = 0.0f;
+
+ if (*speed > 2.0f) {
+
+ float bumpsFactor = settings.getBumpsFactor();
+ float sopFactor = settings.getSopFactor();
+ float sopOffset = settings.getSopOffset();
+
+ bool use360 = settings.getUse360ForDirect();
+ int ffbType = settings.getFfbType();
+
+ if (*speed > 5.0f) {
+
+ float halfMaxForce = (float)(settings.getMaxForce() >> 1);
+ float r = *vY / *vX;
+ float sa, asa, ar = abs(r);
+ float reqSteer, uSteer;
+
+ if (*vX < 0.0f)
+ r = -r;
+
+ if (ar > 1.0f) {
+ sa = csignf(0.785f, r);
+ asa = 0.785f;
+ yaw = minf(maxf(sa * sopFactor, -halfMaxForce), halfMaxForce);
+ }
+ else {
+ sa = 0.78539816339745f * r + 0.273f * r * (1.0f - ar);
+ asa = abs(sa);
+ if (asa > sopOffset) {
+ sa -= csignf(sopOffset, sa);
+ yaw =
+ minf(
+ maxf(
+ sa * (2.0f - asa) * sopFactor,
+ -halfMaxForce
+ ),
+ halfMaxForce
+ );
+ }
+ }
+
+ if (settings.getUndersteerFactor() > 0.0f && settings.getUndersteerYawRateMult() > 0 && settings.getUndersteerlatAccelDiv() > 0) {
+
+ reqSteer = abs((*yawRate * settings.getUndersteerYawRateMult()) / *speed + *latAccel / settings.getUndersteerlatAccelDiv());
+ uSteer = minf(abs(*steer) - reqSteer - USTEER_MIN_OFFSET - settings.getUndersteerOffset(), 1.0f);
+
+ if (uSteer > 0.0f)
+ yaw -= uSteer * settings.getUndersteerFactor() * USTEER_MULTIPLIER * *swTorque;
+
+ }
+
+ }
+
+ if (LFshockDeflST != nullptr && RFshockDeflST != nullptr && bumpsFactor != 0.0f)
+ {
+
+ if (LFshockDeflLast != -10000.0f) {
+
+ if (ffbType != FFBTYPE_DIRECT_FILTER || use360) {
+
+ __m128 xmm0 = _mm_loadu_ps(LFshockDeflST);
+ __m128 xmm1 = _mm_loadu_ps(RFshockDeflST);
+ __m128 xmm2 = _mm_load_ps(LFshockDeflST);
+ __m128 xmm3 = _mm_load_ps(RFshockDeflST);
+ xmm0 = (__m128)_mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(xmm0), 4));
+ __m128 xmm4 = _mm_load_ss(&LFshockDeflLast);
+ xmm1 = (__m128)_mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(xmm1), 4));
+ __m128 xmm5 = _mm_load_ss(&RFshockDeflLast);
+ xmm0 = _mm_move_ss(xmm0, xmm4);
+ xmm2 = _mm_sub_ps(xmm2, xmm0);
+ xmm1 = _mm_move_ss(xmm1, xmm5);
+ xmm3 = _mm_sub_ps(xmm3, xmm1);
+ xmm4 = _mm_loadu_ps((float*)LFshockDeflST + 12);
+ xmm1 = _mm_loadl_pi(xmm1, (const __m64*)LFshockDeflST + 16);
+ xmm1 = _mm_sub_ps(xmm1, xmm4);
+ xmm5 = _mm_loadu_ps((float*)RFshockDeflST + 12);
+ xmm0 = _mm_loadl_pi(xmm0, (const __m64*)RFshockDeflST + 16);
+ xmm0 = _mm_sub_ps(xmm0, xmm4);
+ xmm3 = _mm_load_ss(&bumpsFactor);
+ xmm1 = _mm_sub_ps(xmm1, xmm0);
+ xmm3 = _mm_unpacklo_ps(xmm3, xmm3);
+ xmm3 = _mm_unpacklo_ps(xmm3, xmm3);
+ xmm2 = _mm_mul_ps(xmm2, xmm3);
+ xmm1 = _mm_mul_ps(xmm1, xmm3);
+ _mm_store_ps((float*)suspForceST, xmm2);
+ _mm_storel_pi((__m64*)suspForceST + 16, xmm1);
+ }
+ else if (bumpsFactor != 0.0f) {
+ suspForce =
+ (
+ (LFshockDeflST[STmaxIdx] - LFshockDeflLast) -
+ (RFshockDeflST[STmaxIdx] - RFshockDeflLast)
+ ) * bumpsFactor * 0.25f;
+ }
+ else {
+ suspForce =
+ (
+ (LFshockDeflST[STmaxIdx] - LFshockDeflLast) -
+ (RFshockDeflST[STmaxIdx] - RFshockDeflLast)
+ * 0.25f);
+ }
+
+ }
+
+ RFshockDeflLast = RFshockDeflST[STmaxIdx];
+ LFshockDeflLast = LFshockDeflST[STmaxIdx];
+
+ }
+ else if (CFshockDeflST != nullptr && bumpsFactor != 0.0f) {
+
+ if (CFshockDeflLast != -10000.0f) {
+
+ if (ffbType != FFBTYPE_DIRECT_FILTER || use360){
+
+ __m128 xmm1;
+ __m128 xmm0 = _mm_loadu_ps(CFshockDeflST);
+ __m128 xmm2 = _mm_load_ps(CFshockDeflST);
+ __m128 xmm3 = _mm_load_ss(&bumpsFactor);
+ xmm0 = (__m128)_mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(xmm0), 4));
+ __m128 xmm4 = _mm_load_ss(&CFshockDeflLast);
+ xmm3 = _mm_unpacklo_ps(xmm3, xmm3);
+ xmm0 = _mm_move_ss(xmm0, xmm4);
+ xmm2 = _mm_sub_ps(xmm2, xmm0);
+ xmm4 = _mm_loadu_ps((float*)CFshockDeflST + 12);
+ xmm1 = _mm_loadl_pi(xmm1, (const __m64*)CFshockDeflST + 16);
+ xmm3 = _mm_unpacklo_ps(xmm3, xmm3);
+ xmm1 = _mm_sub_ps(xmm1, xmm4);
+ xmm2 = _mm_mul_ps(xmm2, xmm3);
+ xmm1 = _mm_mul_ps(xmm1, xmm3);
+ _mm_store_ps((float*)suspForceST, xmm2);
+ _mm_storel_pi((__m64*)suspForceST + 16, xmm1);
+ }
+ else if(bumpsFactor != 0.0f)
+ suspForce = (CFshockDeflST[STmaxIdx] - CFshockDeflLast) * bumpsFactor * 0.25f;
+ else
+ CFshockDeflLast = CFshockDeflST[STmaxIdx];
+
+ }
+
+ CFshockDeflLast = CFshockDeflST[STmaxIdx];
+
+ }
+
+ stopped = false;
+
+ }
+ else
+ stopped = true;
+
+ for (int i = 0; i < DIRECT_INTERP_SAMPLES; i++) {
+
+ yawFilter[i] = yaw * firc6[i];
+
+ yawForce[i] =
+ yawFilter[0] + yawFilter[1] + yawFilter[2] +
+ yawFilter[3] + yawFilter[4] + yawFilter[5];
+
+ }
+
+ halfSteerMax = *steerMax / 2.0f;
+ if (abs(halfSteerMax) < 8.0f && abs(*steer) > halfSteerMax - STOPS_MAXFORCE_RAD * 2.0f)
+ nearStops = true;
+ else
+ nearStops = false;
+
+ if (
+ !*isOnTrack ||
+ settings.getFfbType() == FFBTYPE_DIRECT_FILTER ||
+ settings.getFfbType() == FFBTYPE_DIRECT_FILTER_720
+ )
+ continue;
+
+ // Bump stops
+ if (abs(halfSteerMax) < 8.0f && abs(*steer) > halfSteerMax) {
+
+ float factor, invFactor;
+
+ if (*steer > 0) {
+ factor = (-(*steer - halfSteerMax)) / STOPS_MAXFORCE_RAD;
+ factor = maxf(factor, -1.0f);
+ invFactor = 1.0f + factor;
+ }
+ else {
+ factor = (-(*steer + halfSteerMax)) / STOPS_MAXFORCE_RAD;
+ factor = minf(factor, 1.0f);
+ invFactor = 1.0f - factor;
+ }
+
+ setFFB((int)(factor * DI_MAX + scaleTorque(*swTorque) * invFactor));
+ continue;
+
+ }
+
+ // Telemetry FFB
+ switch (settings.getFfbType()) {
+
+ case FFBTYPE_360HZ: {
+
+ for (int i = 0; i < STmaxIdx; i++) {
+ setFFB(scaleTorque(swTorqueST[i] + suspForceST[i] + yawForce[i]));
+ sleepSpinUntil(&start, 2000, 2760 * (i + 1));
+ //nanosleep(2760 * (i + 1));
+ }
+ setFFB(
+ scaleTorque(
+ swTorqueST[STmaxIdx] + suspForceST[STmaxIdx] + yawForce[STmaxIdx]
+ )
+ );
+
+ }
+ break;
+
+ case FFBTYPE_360HZ_INTERP: {
+
+ float diff = (swTorqueST[0] - lastTorque) / 2.0f;
+ float sdiff = (suspForceST[0] - lastSuspForce) / 2.0f;
+ int force, iMax = STmaxIdx << 1;
+
+ setFFB(
+ scaleTorque(
+ lastTorque + diff + lastSuspForce + sdiff + yawForce[0]
+ )
+ );
+
+ for (int i = 0; i < iMax; i++) {
+
+ int idx = i >> 1;
+
+ if (i & 1) {
+ diff = (swTorqueST[idx + 1] - swTorqueST[idx]) / 2.0f;
+ sdiff = (suspForceST[idx + 1] - suspForceST[idx]) / 2.0f;
+ force =
+ scaleTorque(
+ swTorqueST[idx] + diff + suspForceST[idx] +
+ sdiff + yawForce[idx]
+ );
+ }
+ else
+ force =
+ scaleTorque(
+ swTorqueST[idx] + suspForceST[idx] + yawForce[idx]
+ );
+
+ //nanosleep(1380 * (i + 1));
+ sleepSpinUntil(&start, 1000, 1380 * (i + 1));
+ setFFB(force);
+
+ }
+
+ //nanosleep(1380 * (iMax + 1));
+ sleepSpinUntil(&start, 1000, 1380 * (iMax + 1));
+ setFFB(
+ scaleTorque(
+ swTorqueST[STmaxIdx] + suspForceST[STmaxIdx] + yawForce[STmaxIdx]
+ )
+ );
+ lastTorque = swTorqueST[STmaxIdx];
+ lastSuspForce = suspForceST[STmaxIdx];
+
+ }
+ break;
+
+ }
+
+
+ }
+
+ // Did we lose iRacing?
+ if (numHandles > 0 && !(hdr->status & irsdk_stConnected)) {
+ debug(L"Disconnected from iRacing");
+ numHandles = 0;
+ dataLen = 0;
+ if (data != NULL) {
+ free(data);
+ data = NULL;
+ }
+ resetForces();
+ onTrack = false;
+ setOnTrackStatus(onTrack);
+ setConnectedStatus(false);
+ timeEndPeriod(1);
+ if (settings.getUseCarSpecific() && car[0] != 0)
+ settings.writeSettingsForCar(car);
+ }
+
+ // Window messages
+ if (res == numHandles) {
+
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ if (msg.message == WM_QUIT)
+ DestroyWindow(mainWnd);
+ if (!IsDialogMessage(mainWnd, &msg)) {
+ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ }
+
+ }
+
+ return (int)msg.wParam;
}
-understeerCoefs *getCarUsteerCoeffs(char *car) {
-
- for (int i = 0; i < sizeof(usteerCoefs) / sizeof(usteerCoefs[0]); i++)
- if (!strcmp(car, usteerCoefs[i].car)) {
- debug(L"We have understeer coeffs for car %s", car);
- return &usteerCoefs[i];
- }
+ATOM MyRegisterClass(HINSTANCE hInstance) {
- debug(L"No understeer coeffs for car %s", car);
- return nullptr;
+ WNDCLASSEXW wcex;
-}
+ wcex.cbSize = sizeof(WNDCLASSEX);
-void clippingReport() {
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = hInstance;
+ wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_IRFFB);
+ wcex.lpszClassName = szWindowClass;
+ wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
- float clippedPerCent = samples > 0 ? (float)clippedSamples * 100.0f / samples : 0.0f;
- text(L"%.02f%% of samples were clipped", clippedPerCent);
- if (clippedPerCent > 2.5f)
- text(L"Consider increasing max force to reduce clipping");
- samples = clippedSamples = 0;
+ return RegisterClassExW(&wcex);
}
-void logiRpmLed(float *rpm, float redline) {
-
- logiLedData.rpmData.rpm = *rpm / (redline * 0.90f);
- logiLedData.rpmData.rpmFirstLed = 0.65f;
- logiLedData.rpmData.rpmRedLine = 1.0f;
+LRESULT CALLBACK EditWndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR subId, DWORD_PTR rData) {
- ffdevice->Escape(&logiEscape);
+ if (msg == WM_CHAR) {
-}
+ wchar_t buf[8];
-void deviceChange() {
+ if (subId == EDIT_FLOAT) {
- debug(L"Device change notification");
- if (!onTrack) {
- debug(L"Not on track, processing device change");
- deviceChangePending = false;
- enumDirectInput();
- if (!settings.isFfbDevicePresent())
- releaseDirectInput();
- }
- else {
- debug(L"Deferring device change processing whilst on track");
- deviceChangePending = true;
- }
+ if (GetWindowTextW(wnd, buf, 8) && StrChrIW(buf, L'.') && wParam == '.')
+ return 0;
-}
+ if (
+ !(
+ (wParam >= L'0' && wParam <= L'9') ||
+ wParam == L'.' ||
+ wParam == VK_RETURN ||
+ wParam == VK_DELETE ||
+ wParam == VK_BACK
+ )
+ )
+ return 0;
-DWORD getDeviceVidPid(LPDIRECTINPUTDEVICE8 dev) {
+ LRESULT ret = DefSubclassProc(wnd, msg, wParam, lParam);
- DIPROPDWORD dipdw;
- dipdw.diph.dwSize = sizeof(DIPROPDWORD);
- dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- dipdw.diph.dwObj = 0;
- dipdw.diph.dwHow = DIPH_DEVICE;
+ wchar_t* end;
+ float val = 0.0f;
- if (dev == nullptr)
- return 0;
+ GetWindowText(wnd, buf, 8);
+ val = wcstof(buf, &end);
+ if (end - buf == wcslen(buf))
+ SendMessage(GetParent(wnd), WM_EDIT_VALUE, reinterpret_cast(val), (LPARAM)wnd);
- if (!SUCCEEDED(dev->GetProperty(DIPROP_VIDPID, &dipdw.diph)))
- return 0;
+ return ret;
- return dipdw.dwData;
+ }
+ else {
-}
+ if (
+ !(
+ (wParam >= L'0' && wParam <= L'9') ||
+ wParam == VK_RETURN ||
+ wParam == VK_DELETE ||
+ wParam == VK_BACK
+ )
+ )
+ return 0;
-void minimise() {
- debug(L"Minimising window");
- Shell_NotifyIcon(NIM_ADD, &niData);
- ShowWindow(mainWnd, SW_HIDE);
-}
+ LRESULT ret = DefSubclassProc(wnd, msg, wParam, lParam);
+ GetWindowText(wnd, buf, 8);
+ int val = _wtoi(buf);
+ SendMessage(GetParent(wnd), WM_EDIT_VALUE, (WPARAM)val, (LPARAM)wnd);
+ return ret;
-void restore() {
- debug(L"Restoring window");
- Shell_NotifyIcon(NIM_DELETE, &niData);
- ShowWindow(mainWnd, SW_SHOW);
- BringWindowToTop(mainWnd);
-}
+ }
-int APIENTRY wWinMain(
- _In_ HINSTANCE hInstance,
- _In_opt_ HINSTANCE hPrevInstance,
- _In_ LPWSTR lpCmdLine,
- _In_ int nCmdShow
-) {
+ }
- UNREFERENCED_PARAMETER(hPrevInstance);
-
- if (StrStrW(lpCmdLine, CMDLINE_HGSVC)) {
-
- SERVICE_TABLE_ENTRYW SvcDispatchTable[] = {
- { SVCNAME, (LPSERVICE_MAIN_FUNCTION)HidGuardian::SvcMain },
- { NULL, NULL }
- };
-
- if (!StartServiceCtrlDispatcherW(SvcDispatchTable)) {
- HidGuardian::svcReportError(L"Failed to start service ctrl dispatcher");
- exit(1);
- }
-
- exit(0);
-
- }
-
- globalMutex = CreateMutex(NULL, false, L"Global\\irFFB_Mutex");
-
- if (GetLastError() == ERROR_ALREADY_EXISTS)
- exit(0);
-
- INITCOMMONCONTROLSEX ccEx;
-
- HANDLE handles[1];
- char *data = nullptr;
- bool irConnected = false;
- MSG msg;
-
- float *swTorque = nullptr, *swTorqueST = nullptr, *steer = nullptr, *steerMax = nullptr;
- float *speed = nullptr, *throttle = nullptr, *rpm = nullptr;
- float *LFshockDeflST = nullptr, *RFshockDeflST = nullptr, *CFshockDeflST = nullptr;
- float *LRshockDeflST = nullptr, *RRshockDeflST = nullptr;
- float *vX = nullptr, *vY = nullptr;
- float *latAccel = nullptr, *yawRate = nullptr;
- float LFshockDeflLast = -10000, RFshockDeflLast = -10000, CFshockDeflLast = -10000;
- float LRshockDeflLast = -10000, RRshockDeflLast = -10000;
- bool *isOnTrack = nullptr;
- int *trackSurface = nullptr, *gear = nullptr;
-
- bool inGarage = false;
- int numHandles = 0, dataLen = 0, lastGear = 0;
- int STnumSamples = 0, STmaxIdx = 0, lastTrackSurface = -1;
- float halfSteerMax = 0, lastTorque = 0, lastSuspForce = 0, redline;
- float yaw = 0.0f, yawFilter[DIRECT_INTERP_SAMPLES];
-
- understeerCoefs *usCoefs;
-
- ccEx.dwICC = ICC_WIN95_CLASSES | ICC_BAR_CLASSES | ICC_STANDARD_CLASSES;
- ccEx.dwSize = sizeof(ccEx);
- InitCommonControlsEx(&ccEx);
-
- HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_IRFFB));
-
- LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
- LoadStringW(hInstance, IDC_IRFFB, szWindowClass, MAX_LOADSTRING);
- MyRegisterClass(hInstance);
-
- // Setup DI FFB effect
- pforce.dwMagnitude = 0;
- pforce.dwPeriod = INFINITE;
- pforce.dwPhase = 0;
- pforce.lOffset = 0;
-
- ZeroMemory(&dieff, sizeof(dieff));
- dieff.dwSize = sizeof(DIEFFECT);
- dieff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
- dieff.dwDuration = INFINITE;
- dieff.dwSamplePeriod = 0;
- dieff.dwGain = DI_FFNOMINALMAX;
- dieff.dwTriggerButton = DIEB_NOTRIGGER;
- dieff.dwTriggerRepeatInterval = 0;
- dieff.cAxes = 1;
- dieff.rgdwAxes = axes;
- dieff.rglDirection = dir;
- dieff.lpEnvelope = NULL;
- dieff.cbTypeSpecificParams = sizeof(DIPERIODIC);
- dieff.lpvTypeSpecificParams = &pforce;
- dieff.dwStartDelay = 0;
-
- ZeroMemory(&logiLedData, sizeof(logiLedData));
- logiLedData.size = sizeof(logiLedData);
- logiLedData.version = 1;
- ZeroMemory(&logiEscape, sizeof(logiEscape));
- logiEscape.dwSize = sizeof(DIEFFESCAPE);
- logiEscape.dwCommand = 0;
- logiEscape.lpvInBuffer = &logiLedData;
- logiEscape.cbInBuffer = sizeof(logiLedData);
-
- InitializeCriticalSection(&effectCrit);
-
- if (!InitInstance(hInstance, nCmdShow))
- return FALSE;
-
- hidGuardian = HidGuardian::init(GetCurrentProcessId());
- if (StrStrW(lpCmdLine, CMDLINE_HGINST))
- hidGuardian->install();
- else if (StrStrW(lpCmdLine, CMDLINE_HGREPAIR))
- hidGuardian->repairService();
-
- fan = Fan::init();
- jetseat = JetSeat::init();
- if (!jetseat) {
- DeleteMenu(GetMenu(mainWnd), ID_SETTINGS_JETSEAT, MF_BYCOMMAND);
- DrawMenuBar(mainWnd);
- }
-
- memset(car, 0, sizeof(car));
- setCarStatus(car);
- setConnectedStatus(false);
- setOnTrackStatus(false);
- settings.readGenericSettings();
- settings.readRegSettings(car);
-
- if (settings.getStartMinimised())
- minimise();
- else
- restore();
-
- enumDirectInput();
-
- LARGE_INTEGER start;
- QueryPerformanceFrequency(&freq);
-
- initVJD();
- SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
-
- SetThreadPriority(
- CreateThread(NULL, 0, readWheelThread, NULL, 0, NULL), THREAD_PRIORITY_HIGHEST
- );
- SetThreadPriority(
- CreateThread(NULL, 0, directFFBThread, NULL, 0, NULL), THREAD_PRIORITY_HIGHEST
- );
-
- debug(L"Init complete, entering mainloop");
-
- while (TRUE) {
-
- DWORD res;
- const irsdk_header *hdr = NULL;
-
- if (
- irsdk_startup() && (hdr = irsdk_getHeader()) &&
- hdr->status & irsdk_stConnected && hdr->bufLen != dataLen && hdr->bufLen != 0
- ) {
-
- debug(L"New iRacing session");
-
- handles[0] = hDataValidEvent;
- numHandles = 1;
-
- if (data != NULL)
- free(data);
-
- dataLen = irsdk_getHeader()->bufLen;
- data = (char *)malloc(dataLen);
- setConnectedStatus(true);
-
- if (getCarName() && settings.getUseCarSpecific()) {
- setCarStatus(car);
- settings.readSettingsForCar(car);
- }
- else
- setCarStatus(nullptr);
-
- redline = getCarRedline();
- debug(L"Redline is %d rpm", (int)redline);
-
- usCoefs = getCarUsteerCoeffs(car);
- EnableWindow(settings.getUndersteerWnd()->trackbar, usCoefs != nullptr);
- EnableWindow(settings.getUndersteerWnd()->value, usCoefs != nullptr);
- EnableWindow(settings.getUndersteerOffsetWnd()->trackbar, usCoefs != nullptr);
- EnableWindow(settings.getUndersteerOffsetWnd()->value, usCoefs != nullptr);
-
- // Inform iRacing of the maxForce setting
- irsdk_broadcastMsg(irsdk_BroadcastFFBCommand, irsdk_FFBCommand_MaxForce, (float)settings.getMaxForce());
-
- swTorque = floatvarptr(data, "SteeringWheelTorque");
- swTorqueST = floatvarptr(data, "SteeringWheelTorque_ST");
- steer = floatvarptr(data, "SteeringWheelAngle");
- steerMax = floatvarptr(data, "SteeringWheelAngleMax");
- speed = floatvarptr(data, "Speed");
- throttle = floatvarptr(data, "Throttle");
- rpm = floatvarptr(data, "RPM");
- gear = intvarptr(data, "Gear");
- isOnTrack = boolvarptr(data, "IsOnTrack");
-
- trackSurface = intvarptr(data, "PlayerTrackSurface");
- vX = floatvarptr(data, "VelocityX");
- vY = floatvarptr(data, "VelocityY");
-
- latAccel = floatvarptr(data, "LatAccel");
- yawRate = floatvarptr(data, "YawRate");
-
- RFshockDeflST = floatvarptr(data, "RFshockDefl_ST");
- LFshockDeflST = floatvarptr(data, "LFshockDefl_ST");
- LRshockDeflST = floatvarptr(data, "LRshockDefl_ST");
- RRshockDeflST = floatvarptr(data, "RRshockDefl_ST");
- CFshockDeflST = floatvarptr(data, "CFshockDefl_ST");
-
- int swTorqueSTidx = irsdk_varNameToIndex("SteeringWheelTorque_ST");
- STnumSamples = irsdk_getVarHeaderEntry(swTorqueSTidx)->count;
- STmaxIdx = STnumSamples - 1;
-
- lastTorque = 0.0f;
- onTrack = false;
- resetForces();
- irConnected = true;
- timeBeginPeriod(1);
-
- }
-
- res = MsgWaitForMultipleObjects(numHandles, handles, FALSE, 1000, QS_ALLINPUT);
-
- QueryPerformanceCounter(&start);
-
- if (numHandles > 0 && res == numHandles - 1 && irsdk_getNewData(data)) {
-
- if (onTrack && !*isOnTrack) {
- debug(L"No longer on track");
- onTrack = false;
- setOnTrackStatus(onTrack);
- lastTorque = lastSuspForce = 0.0f;
- resetForces();
- fan->setManualSpeed();
- clippingReport();
- }
-
- else if (!onTrack && *isOnTrack) {
- debug(L"Now on track");
- onTrack = true;
- setOnTrackStatus(onTrack);
- RFshockDeflLast = LFshockDeflLast =
- LRshockDeflLast = RRshockDeflLast =
- CFshockDeflLast = -10000.0f;
- clippedSamples = samples = lastGear = 0;
- memset(yawFilter, 0, DIRECT_INTERP_SAMPLES * sizeof(float));
- }
-
- if (*trackSurface != lastTrackSurface) {
- debug(L"Track surface is now: %d", *trackSurface);
- lastTrackSurface = *trackSurface;
- }
-
- if (jetseat && jetseat->isEnabled()) {
- if (*isOnTrack && *rpm > 0.0f) {
- jetseat->startEngineEffect();
- jetseat->updateEngineEffect(*rpm * 100.0f / redline);
- }
- else
- jetseat->stopEngineEffect();
- }
-
- if (ffdevice && logiWheel)
- logiRpmLed(rpm, redline);
-
- yaw = 0.0f;
-
- if (*speed > 2.0f) {
-
- float bumpsFactor = settings.getBumpsFactor();
- float sopFactor = settings.getSopFactor();
- float sopOffset = settings.getSopOffset();
-
- bool use360 = settings.getUse360ForDirect();
- int ffbType = settings.getFfbType();
-
- if (*speed > 5.0f) {
-
- float halfMaxForce = (float)(settings.getMaxForce() >> 1);
- float r = *vY / *vX;
- float sa, asa, ar = abs(r);
- float reqSteer, uSteer;
-
- if (*vX < 0.0f)
- r = -r;
-
- if (ar > 1.0f) {
- sa = csignf(0.785f, r);
- asa = 0.785f;
- yaw = minf(maxf(sa * sopFactor, -halfMaxForce), halfMaxForce);
- }
- else {
- sa = 0.78539816339745f * r + 0.273f * r * (1.0f - ar);
- asa = abs(sa);
- if (asa > sopOffset) {
- sa -= csignf(sopOffset, sa);
- yaw =
- minf(
- maxf(
- sa * (2.0f - asa) * sopFactor,
- -halfMaxForce
- ),
- halfMaxForce
- );
- }
- }
-
- if (jetseat && jetseat->isEnabled() && asa > sopOffset)
- jetseat->yawEffect(sa);
-
- if (usCoefs != nullptr && settings.getUndersteerFactor() > 0.0f) {
-
- reqSteer = abs((*yawRate * usCoefs->yawRateMult) / *speed + *latAccel / usCoefs->latAccelDiv);
- uSteer = minf(abs(*steer) - reqSteer - USTEER_MIN_OFFSET - settings.getUndersteerOffset(), 1.0f);
-
- if (uSteer > 0.0f)
- yaw -= uSteer * settings.getUndersteerFactor() * USTEER_MULTIPLIER * *swTorque;
-
- }
-
- }
-
- if (
- LFshockDeflST != nullptr && RFshockDeflST != nullptr && bumpsFactor != 0.0f
- ) {
-
- if (LFshockDeflLast != -10000.0f) {
-
- if (ffbType != FFBTYPE_DIRECT_FILTER || use360) {
-
- __asm {
- mov eax, LFshockDeflST
- mov ecx, RFshockDeflST
- movups xmm0, xmmword ptr [eax]
- movups xmm1, xmmword ptr [ecx]
- // xmm2 = LFdefl[0,1,2,3]
- movaps xmm2, xmm0
- // xmm3 = RFdefl[0,1,2,3]
- movaps xmm3, xmm1
- // xmm0 = LFdefl[-,0,1,2]
- pslldq xmm0, 4
- movss xmm4, LFshockDeflLast
- // xmm1 = RFdefl[-,0,1,2]
- pslldq xmm1, 4
- movss xmm5, RFshockDeflLast
- // xmm0 = LFdefl[LFlast,0,1,2]
- movss xmm0, xmm4
- // xmm6 = LFdefl[0,1,2,3]
- movaps xmm6, xmm2
- // xmm2 = LFdefl[0] - LFlast, LFdefl[1] - LFdefl[0], ...
- subps xmm2, xmm0
- // xmm1 = RFdefl[RFlast,0,1,2]
- movss xmm1, xmm5
- // xmm7 = RFdefl[0,1,2,3]
- movaps xmm7, xmm3
- // xmm3 = RFdefl[0] - RFlast, RFdefl[1] - RFdefl[0], ...
- subps xmm3, xmm1
- // xmm4 = LFdefl[3,4,5]
- movups xmm4, xmmword ptr [eax + 12]
- // xmm1 = LFdefl[4,5]
- movlps xmm1, qword ptr [eax + 16]
- // xmm1 = LFdefl[4] - LFdefl[3], LFdefl[5] - LFdefl[4]
- subps xmm1, xmm4
- // xmm5 = RFdefl[3,4,5]
- movups xmm5, xmmword ptr [ecx + 12]
- // xmm0 = RFdefl[4,5]
- movlps xmm0, qword ptr [ecx + 16]
- // xmm2 = delta[0,1,2,3]
- subps xmm2, xmm3
- // xmm0 = RFdefl[4] - RFdefl[3], RFdefl[5] - RFdefl[4]
- subps xmm0, xmm5
- // xmm3 = susTexFactor
- movss xmm3, bumpsFactor
- // xmm1 = delta[4,5]
- subps xmm1, xmm0
- unpcklps xmm3, xmm3
- unpcklps xmm3, xmm3
- // xmm2 = delta[0,1,2,3] * bumpsFactor
- mulps xmm2, xmm3
- // xmm1 = delta[4,5] * bumpsFactor
- mulps xmm1, xmm3
- // write
- movaps xmmword ptr suspForceST[0], xmm2
- movlps qword ptr suspForceST[16], xmm1
- }
-
- }
- else {
- suspForce =
- (
- (LFshockDeflST[STmaxIdx] - LFshockDeflLast) -
- (RFshockDeflST[STmaxIdx] - RFshockDeflLast)
- ) * bumpsFactor * 0.25f;
- }
-
- if (jetseat && jetseat->isEnabled()) {
- float LFd = LFshockDeflST[STmaxIdx] - LFshockDeflLast;
- float RFd = RFshockDeflST[STmaxIdx] - RFshockDeflLast;
-
- if (LFd > 0.0025f || RFd > 0.0025f)
- jetseat->fBumpEffect(LFd * 220.0f, RFd * 220.0f);
- }
-
- }
-
- RFshockDeflLast = RFshockDeflST[STmaxIdx];
- LFshockDeflLast = LFshockDeflST[STmaxIdx];
-
- }
- else if (CFshockDeflST != nullptr && bumpsFactor != 0) {
-
- if (CFshockDeflLast != -10000.0f) {
-
- if (ffbType != FFBTYPE_DIRECT_FILTER || use360)
- __asm {
- mov eax, CFshockDeflST
- movups xmm0, xmmword ptr[eax]
- // xmm3 = bumpsFactor
- movss xmm3, bumpsFactor
- // xmm2 = CFdefl[0,1,2,3]
- movaps xmm2, xmm0
- // xmm0 = CFdefl[-,1,2,3]
- pslldq xmm0, 4
- movss xmm4, CFshockDeflLast
- unpcklps xmm3, xmm3
- // xmm0 = CFdefl[CFlast,0,1,2]
- movss xmm0, xmm4
- // xmm2 = CFdefl[0] - CFlast, CFdefl[1] - CFdefl[0], ...
- subps xmm2, xmm0
- // xmm4 = CFdefl[3,4,5]
- movups xmm4, xmmword ptr[eax + 12]
- // xmm1 = CFdefl[4,5]
- movlps xmm1, qword ptr[eax + 16]
- unpcklps xmm3, xmm3
- // xmm1 = CFdefl[4] - CFdefl[3], CFdefl[5] - CFdefl[4]
- subps xmm1, xmm4
- mulps xmm2, xmm3
- mulps xmm1, xmm3
- movaps xmmword ptr suspForceST[0], xmm2
- movlps qword ptr suspForceST[16], xmm1
- }
- else
- suspForce = (CFshockDeflST[STmaxIdx] - CFshockDeflLast) * bumpsFactor * 0.25f;
-
- if (jetseat && jetseat->isEnabled()) {
- float CFd = CFshockDeflST[STmaxIdx] - CFshockDeflLast;
- if (CFd > 0.0025f)
- jetseat->fBumpEffect(CFd * 220.0f, CFd * 220.0f);
- }
-
- }
-
- CFshockDeflLast = CFshockDeflST[STmaxIdx];
-
- }
-
- if (jetseat && jetseat->isEnabled() && LRshockDeflST != nullptr) {
- float LRd = LRshockDeflST[STmaxIdx] - LRshockDeflLast;
- float RRd = RRshockDeflST[STmaxIdx] - RRshockDeflLast;
-
- if (LRd > 0.0025f || RRd > 0.0025f)
- jetseat->rBumpEffect(LRd * 220.0f, RRd * 220.0f);
-
- LRshockDeflLast = LRshockDeflST[STmaxIdx];
- RRshockDeflLast = RRshockDeflST[STmaxIdx];
- }
-
- stopped = false;
-
- }
- else
- stopped = true;
-
- if (*isOnTrack)
- fan->setSpeed(*speed);
-
- if (jetseat && jetseat->isEnabled() && *gear != lastGear) {
- jetseat->gearEffect();
- lastGear = *gear;
- }
-
- for (int i = 0; i < DIRECT_INTERP_SAMPLES; i++) {
-
- yawFilter[i] = yaw * firc6[i];
-
- yawForce[i] =
- yawFilter[0] + yawFilter[1] + yawFilter[2] +
- yawFilter[3] + yawFilter[4] + yawFilter[5];
-
- }
-
- halfSteerMax = *steerMax / 2.0f;
- if (abs(halfSteerMax) < 8.0f && abs(*steer) > halfSteerMax - STOPS_MAXFORCE_RAD * 2.0f)
- nearStops = true;
- else
- nearStops = false;
-
- if (
- !*isOnTrack ||
- settings.getFfbType() == FFBTYPE_DIRECT_FILTER ||
- settings.getFfbType() == FFBTYPE_DIRECT_FILTER_720
- )
- continue;
-
- // Bump stops
- if (abs(halfSteerMax) < 8.0f && abs(*steer) > halfSteerMax) {
-
- float factor, invFactor;
-
- if (*steer > 0) {
- factor = (-(*steer - halfSteerMax)) / STOPS_MAXFORCE_RAD;
- factor = maxf(factor, -1.0f);
- invFactor = 1.0f + factor;
- }
- else {
- factor = (-(*steer + halfSteerMax)) / STOPS_MAXFORCE_RAD;
- factor = minf(factor, 1.0f);
- invFactor = 1.0f - factor;
- }
-
- setFFB((int)(factor * DI_MAX + scaleTorque(*swTorque) * invFactor));
- continue;
-
- }
-
- // Telemetry FFB
- switch (settings.getFfbType()) {
-
- case FFBTYPE_360HZ: {
-
- for (int i = 0; i < STmaxIdx; i++) {
- setFFB(scaleTorque(swTorqueST[i] + suspForceST[i] + yawForce[i]));
- sleepSpinUntil(&start, 2000, 2760 * (i + 1));
- }
- setFFB(
- scaleTorque(
- swTorqueST[STmaxIdx] + suspForceST[STmaxIdx] + yawForce[STmaxIdx]
- )
- );
-
- }
- break;
-
- case FFBTYPE_360HZ_INTERP: {
-
- float diff = (swTorqueST[0] - lastTorque) / 2.0f;
- float sdiff = (suspForceST[0] - lastSuspForce) / 2.0f;
- int force, iMax = STmaxIdx << 1;
-
- setFFB(
- scaleTorque(
- lastTorque + diff + lastSuspForce + sdiff + yawForce[0]
- )
- );
-
- for (int i = 0; i < iMax; i++) {
-
- int idx = i >> 1;
-
- if (i & 1) {
- diff = (swTorqueST[idx + 1] - swTorqueST[idx]) / 2.0f;
- sdiff = (suspForceST[idx + 1] - suspForceST[idx]) / 2.0f;
- force =
- scaleTorque(
- swTorqueST[idx] + diff + suspForceST[idx] +
- sdiff + yawForce[idx]
- );
- }
- else
- force =
- scaleTorque(
- swTorqueST[idx] + suspForceST[idx] + yawForce[idx]
- );
-
- sleepSpinUntil(&start, 0, 1380 * (i + 1));
- setFFB(force);
-
- }
-
- sleepSpinUntil(&start, 0, 1380 * (iMax + 1));
- setFFB(
- scaleTorque(
- swTorqueST[STmaxIdx] + suspForceST[STmaxIdx] + yawForce[STmaxIdx]
- )
- );
- lastTorque = swTorqueST[STmaxIdx];
- lastSuspForce = suspForceST[STmaxIdx];
-
- }
- break;
-
- }
-
-
- }
-
- // Did we lose iRacing?
- if (numHandles > 0 && !(hdr->status & irsdk_stConnected)) {
- debug(L"Disconnected from iRacing");
- numHandles = 0;
- dataLen = 0;
- if (data != NULL) {
- free(data);
- data = NULL;
- }
- resetForces();
- onTrack = false;
- setOnTrackStatus(onTrack);
- setConnectedStatus(false);
- fan->setManualSpeed();
- timeEndPeriod(1);
- if (settings.getUseCarSpecific() && car[0] != 0)
- settings.writeSettingsForCar(car);
- }
-
- // Window messages
- if (res == numHandles) {
-
- while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- if (msg.message == WM_QUIT)
- DestroyWindow(mainWnd);
- if (!IsDialogMessage(mainWnd, &msg)) {
- if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
- }
-
- }
-
- }
-
- return (int)msg.wParam;
+ return DefSubclassProc(wnd, msg, wParam, lParam);
}
+bool CALLBACK SetFont(HWND child, LPARAM font) {
+ SendMessage(child, WM_SETFONT, font, true);
+ return true;
+}
-ATOM MyRegisterClass(HINSTANCE hInstance) {
-
- WNDCLASSEXW wcex;
-
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_IRFFB);
- wcex.lpszClassName = szWindowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
+HWND combo(HWND parent, wchar_t* name, int x, int y) {
- return RegisterClassExW(&wcex);
+ CreateWindowW(
+ L"STATIC", name,
+ WS_CHILD | WS_VISIBLE,
+ x, y, 300, 20, parent, NULL, hInst, NULL
+ );
+ return
+ CreateWindow(
+ L"COMBOBOX", nullptr,
+ CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_TABSTOP,
+ x, y + 20, 265, 240, parent, nullptr, hInst, nullptr
+ );
}
-LRESULT CALLBACK EditWndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR subId, DWORD_PTR rData) {
+sWins_t* slider(HWND parent, wchar_t* name, int x, int y, wchar_t* start, wchar_t* end, bool floatData) {
- if (msg == WM_CHAR) {
+ sWins_t* wins = (sWins_t*)malloc(sizeof(sWins_t));
- wchar_t buf[8];
+ wins->label = CreateWindowW(
+ L"STATIC", name,
+ WS_CHILD | WS_VISIBLE,
+ x, y, 100, 14, parent, NULL, hInst, NULL
+ );
- if (subId == EDIT_FLOAT) {
+ wins->value = CreateWindowW(
+ L"EDIT", L"",
+ WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_CENTER,
+ x + 220, y, 45, 18, parent, NULL, hInst, NULL
+ );
- if (GetWindowTextW(wnd, buf, 8) && StrChrIW(buf, L'.') && wParam == '.')
- return 0;
+ SetWindowSubclass(wins->value, EditWndProc, floatData ? 1 : 0, 0);
- if (
- !(
- (wParam >= L'0' && wParam <= L'9') ||
- wParam == L'.' ||
- wParam == VK_RETURN ||
- wParam == VK_DELETE ||
- wParam == VK_BACK
- )
- )
- return 0;
+ SendMessage(wins->value, EM_SETLIMITTEXT, 5, 0);
- LRESULT ret = DefSubclassProc(wnd, msg, wParam, lParam);
+ wins->trackbar = CreateWindowExW(
+ 0, TRACKBAR_CLASS, name,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND,
+ x + 40, y + 18, 170, 20,
+ parent, NULL, hInst, NULL
+ );
- wchar_t *end;
- float val = 0.0f;
+ wins->min = std::stof(start);
+ wins->max = std::stof(end);
- GetWindowText(wnd, buf, 8);
- val = wcstof(buf, &end);
- if (end - buf == wcslen(buf))
- SendMessage(GetParent(wnd), WM_EDIT_VALUE, reinterpret_cast(val), (LPARAM)wnd);
+ SendMessage(wins->trackbar, TBM_SETRANGE, (WPARAM)TRUE, MAKELONG(std::stof(start), std::stof(end)));
- return ret;
+ HWND buddyLeft = CreateWindowEx(
+ 0, L"STATIC", start,
+ SS_LEFT | WS_CHILD | WS_VISIBLE,
+ 0, 0, 40, 15, parent, NULL, hInst, NULL
+ );
+ SendMessage(wins->trackbar, TBM_SETBUDDY, (WPARAM)TRUE, (LPARAM)buddyLeft);
- }
- else {
+ HWND buddyRight = CreateWindowEx(
+ 0, L"STATIC", end,
+ SS_RIGHT | WS_CHILD | WS_VISIBLE,
+ 0, 0, 52, 15, parent, NULL, hInst, NULL
+ );
+ SendMessage(wins->trackbar, TBM_SETBUDDY, (WPARAM)FALSE, (LPARAM)buddyRight);
- if (
- !(
- (wParam >= L'0' && wParam <= L'9') ||
- wParam == VK_RETURN ||
- wParam == VK_DELETE ||
- wParam == VK_BACK
- )
- )
- return 0;
+ return wins;
- LRESULT ret = DefSubclassProc(wnd, msg, wParam, lParam);
- GetWindowText(wnd, buf, 8);
- int val = _wtoi(buf);
- SendMessage(GetParent(wnd), WM_EDIT_VALUE, (WPARAM)val, (LPARAM)wnd);
- return ret;
+}
- }
+HWND slider(HWND parent, wchar_t* name, int x, int y, int width, int height, int start, int end) {
- }
+ HWND slider = CreateWindowExW(
+ 0, TRACKBAR_CLASS, name,
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND | TBS_NOTICKS,
+ x, y, width, height,
+ parent, NULL, hInst, NULL
+ );
- return DefSubclassProc(wnd, msg, wParam, lParam);
+ SendMessage(slider, TBM_SETRANGE, (WPARAM)TRUE, MAKELONG(start, end));
+ return slider;
}
-HWND combo(HWND parent, wchar_t *name, int x, int y) {
+HWND checkbox(HWND parent, wchar_t* name, int x, int y, int width = 360, int height = 20) {
- CreateWindowW(
- L"STATIC", name,
- WS_CHILD | WS_VISIBLE,
- x, y, 300, 20, parent, NULL, hInst, NULL
- );
- return
- CreateWindow(
- L"COMBOBOX", nullptr,
- CBS_DROPDOWNLIST | WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_TABSTOP,
- x + 12, y + 26, 300, 240, parent, nullptr, hInst, nullptr
- );
+ HWND whd = CreateWindowEx(
+ 0, L"BUTTON", name,
+ BS_CHECKBOX | BS_MULTILINE | WS_CHILD | WS_TABSTOP | WS_VISIBLE,
+ x, y, width, height, parent, nullptr, hInst, nullptr
+ );
+ return whd;
}
-sWins_t *slider(HWND parent, wchar_t *name, int x, int y, wchar_t *start, wchar_t *end, bool floatData) {
-
- sWins_t *wins = (sWins_t *)malloc(sizeof(sWins_t));
+HWND groupox(HWND parent, wchar_t* name, int x, int y, int width, int height) {
- wins->label = CreateWindowW(
- L"STATIC", name,
- WS_CHILD | WS_VISIBLE,
- x, y, 300, 20, parent, NULL, hInst, NULL
- );
+ return
+ CreateWindowEx(
+ 0, L"BUTTON", name,
+ BS_GROUPBOX | BS_MULTILINE | WS_CHILD | WS_TABSTOP | WS_VISIBLE,
+ x, y, width, height, parent, nullptr, hInst, nullptr
+ );
- wins->value = CreateWindowW(
- L"EDIT", L"",
- WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_CENTER,
- x + 210, y, 50, 20, parent, NULL, hInst, NULL
- );
+}
- SetWindowSubclass(wins->value, EditWndProc, floatData ? 1 : 0, 0);
+HWND progressbar(HWND parent, wchar_t* name, int x, int y, int width, int height, int max)
+{
+
+ if (name != nullptr)
+ CreateWindowW(
+ L"STATIC", name,
+ WS_CHILD | WS_VISIBLE,
+ x, y, width, 20, parent, NULL, hInst, NULL
+ );
+
+ HWND hWnd = ::CreateWindowEx(
+ 0,
+ PROGRESS_CLASS,
+ name,
+ WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
+ x,
+ name == nullptr ? y : y + 20,
+ width,
+ height,
+ parent,
+ (HMENU)ID_SMOOTHPROGRESSCTRL,
+ hInst,
+ NULL);
+ ::SendMessage(hWnd, PBM_SETRANGE32, 0, (WPARAM)(INT)max);
+
+ return hWnd;
+}
- SendMessage(wins->value, EM_SETLIMITTEXT, 5, 0);
+void ActivateOverLayWindow()
+{
+ if (windowInitialExtendedState == NULL)
+ {
+ windowInitialExtendedState = GetWindowLongPtr(overlayWnd, GWL_EXSTYLE);
+ }
+ SetWindowPos(overlayWnd, NULL, settings.getWindowPosX(), settings.getWindowPosY(), 200, OVERLAY_WINDOW_HEIGHT, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE);
+ ShowWindow(settings.getOverlayMaxForceWnd(), SW_SHOW);
+ SetWindowLongPtr(overlayWnd, GWL_EXSTYLE, windowInitialExtendedState ^ WS_EX_LAYERED);
+}
- wins->trackbar = CreateWindowExW(
- 0, TRACKBAR_CLASS, name,
- WS_CHILD | WS_VISIBLE | WS_TABSTOP | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND,
- x + 40, y + 26, 240, 30,
- parent, NULL, hInst, NULL
- );
+void DeActivateOverlayWindow()
+{
+ if (windowInitialExtendedState == NULL)
+ {
+ windowInitialExtendedState = GetWindowLongPtr(overlayWnd, (int)GWL_EXSTYLE);
+ }
+ SetWindowLongPtr(overlayWnd, GWL_EXSTYLE, windowInitialExtendedState);
+ ShowWindow(settings.getOverlayMaxForceWnd(), SW_HIDE);
+ SetWindowPos(overlayWnd, NULL, settings.getWindowPosX(), settings.getWindowPosY(), 200, OVERLAY_WINDOW_HEIGHT - 20, SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE);
+ SetLayeredWindowAttributes(overlayWnd, 0, settings.getOverlayTransparency(), LWA_ALPHA);
+}
- HWND buddyLeft = CreateWindowEx(
- 0, L"STATIC", start,
- SS_LEFT | WS_CHILD | WS_VISIBLE,
- 0, 0, 40, 20, parent, NULL, hInst, NULL
- );
- SendMessage(wins->trackbar, TBM_SETBUDDY, (WPARAM)TRUE, (LPARAM)buddyLeft);
+void CreateOverlayWindow(HINSTANCE hInstance)
+{
- HWND buddyRight = CreateWindowEx(
- 0, L"STATIC", end,
- SS_RIGHT | WS_CHILD | WS_VISIBLE,
- 0, 0, 52, 20, parent, NULL, hInst, NULL
- );
- SendMessage(wins->trackbar, TBM_SETBUDDY, (WPARAM)FALSE, (LPARAM)buddyRight);
+ DWORD extendedStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE | WS_EX_TOPMOST;
+ overlayWnd = CreateWindowExW(extendedStyle,
+ szWindowClass, L"irFFb Overlay",
+ WS_VISIBLE | WS_POPUP,
+ //WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
+ CW_USEDEFAULT, CW_USEDEFAULT, 200, OVERLAY_WINDOW_HEIGHT,
+ NULL, NULL, hInst, NULL
+ );
- return wins;
+ currentForceOverlayWnd = progressbar(overlayWnd, nullptr, 3, 3, 150, 15, IR_MAX);
+ clippingForceOverlayWnd = progressbar(overlayWnd, nullptr, 150, 3, 46, 15, progressClippingMax);
-}
+ settings.setOverlayMaxForceWnd(slider(overlayWnd, L"max force", 4, 22, 192, 15, 5, 65));
+ SendMessage(clippingForceOverlayWnd, PBM_SETSTATE, PBST_ERROR, 0);
-HWND checkbox(HWND parent, wchar_t *name, int x, int y) {
-
- return
- CreateWindowEx(
- 0, L"BUTTON", name,
- BS_CHECKBOX | BS_MULTILINE | WS_CHILD | WS_TABSTOP | WS_VISIBLE,
- x, y, 360, 58, parent, nullptr, hInst, nullptr
- );
+ SetWindowSubclass(currentForceOverlayWnd, myNcHitTest, 0, 0);
+ SetWindowSubclass(clippingForceOverlayWnd, myNcHitTest, 0, 0);
+ SetWindowSubclass(overlayWnd, myPaint, 0, 0);
+ SetLayeredWindowAttributes(overlayWnd, 0, 255, LWA_ALPHA);
+ SetMenu(overlayWnd, NULL);
+ ShowWindow(overlayWnd, SW_HIDE);
+ UpdateWindow(overlayWnd);
}
+
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
- DEV_BROADCAST_DEVICEINTERFACE devFilter;
-
- hInst = hInstance;
-
- mainWnd = CreateWindowW(
- szWindowClass, szTitle,
- WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
- CW_USEDEFAULT, CW_USEDEFAULT, 864, 720,
- NULL, NULL, hInst, NULL
- );
-
- if (!mainWnd)
- return FALSE;
-
- memset(&niData, 0, sizeof(niData));
- niData.uVersion = NOTIFYICON_VERSION;
- niData.cbSize = NOTIFYICONDATA_V1_SIZE;
- niData.hWnd = mainWnd;
- niData.uID = 1;
- niData.uFlags = NIF_ICON | NIF_MESSAGE;
- niData.uCallbackMessage = WM_TRAY_ICON;
- niData.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALL));
-
- settings.setDevWnd(combo(mainWnd, L"FFB device:", 44, 20));
- settings.setFfbWnd(combo(mainWnd, L"FFB type:", 44, 80));
- settings.setMinWnd(slider(mainWnd, L"Min force:", 44, 154, L"0", L"20", false));
- settings.setMaxWnd(slider(mainWnd, L"Max force:", 44, 226, L"5 Nm", L"65 Nm", false));
- settings.setDampingWnd(slider(mainWnd, L"Damping:", 44, 298, L"0", L"100", true));
- settings.setBumpsWnd(slider(mainWnd, L"Suspension bumps:", 464, 40, L"0", L"100", true));
- settings.setUndersteerWnd(slider(mainWnd, L"Understeer:", 464, 100, L"0", L"100", true));
- settings.setUndersteerOffsetWnd(slider(mainWnd, L"Understeer offset:", 464, 160, L"0", L"100", true));
- settings.setSopWnd(slider(mainWnd, L"SoP effect:", 464, 220, L"0", L"100", true));
- settings.setSopOffsetWnd(slider(mainWnd, L"SoP offset:", 464, 280, L"0", L"100", true));
- settings.setUse360Wnd(
- checkbox(
- mainWnd,
- L" Use 360 Hz telemetry for suspension effects\r\n in direct modes?",
- 460, 340
- )
- );
- settings.setCarSpecificWnd(
- checkbox(mainWnd, L" Use car specific settings?", 460, 400)
- );
- settings.setReduceWhenParkedWnd(
- checkbox(mainWnd, L" Reduce force when parked?", 460, 440)
- );
- settings.setRunOnStartupWnd(
- checkbox(mainWnd, L" Run on startup?", 460, 480)
- );
- settings.setStartMinimisedWnd(
- checkbox(mainWnd, L" Start minimised?", 460, 520)
- );
- settings.setDebugWnd(
- checkbox(mainWnd, L"Debug logging?", 460, 560)
- );
-
- int statusParts[] = { 256, 424, 864 };
-
- statusWnd = CreateWindowEx(
- 0, STATUSCLASSNAME, NULL,
- WS_CHILD | WS_VISIBLE,
- 0, 0, 0, 0, mainWnd, NULL, hInst, NULL
- );
- SendMessage(statusWnd, SB_SETPARTS, 3, LPARAM(statusParts));
-
- textWnd = CreateWindowEx(
- WS_EX_CLIENTEDGE, L"EDIT", L"",
- WS_VISIBLE | WS_VSCROLL | WS_CHILD | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
- 32, 372, 376, 240,
- mainWnd, NULL, hInst, NULL
- );
- SendMessage(textWnd, EM_SETLIMITTEXT, WPARAM(256000), 0);
-
- ShowWindow(mainWnd, SW_HIDE);
- UpdateWindow(mainWnd);
-
- memset(&devFilter, 0, sizeof(devFilter));
- devFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
- devFilter.dbcc_size = sizeof(devFilter);
- devFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
- RegisterDeviceNotificationW(mainWnd, &devFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
-
- return TRUE;
+ DEV_BROADCAST_DEVICEINTERFACE devFilter;
+
+ hInst = hInstance;
+
+ mainWnd = CreateWindowW(
+ szWindowClass, szTitle,
+ WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
+ CW_USEDEFAULT, CW_USEDEFAULT, 694, 640,
+ NULL, NULL, hInst, NULL
+ );
+
+ if (!mainWnd)
+ return FALSE;
+
+
+ memset(&niData, 0, sizeof(niData));
+ niData.uVersion = NOTIFYICON_VERSION;
+ niData.cbSize = NOTIFYICONDATA_V1_SIZE;
+ niData.hWnd = mainWnd;
+ niData.uID = 1;
+ niData.uFlags = NIF_ICON | NIF_MESSAGE;
+ niData.uCallbackMessage = WM_TRAY_ICON;
+ niData.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALL));
+
+ //left side UI
+ settings.setDevWnd(combo(mainWnd, L"FFB device:", 44, 20));
+ settings.setFfbWnd(combo(mainWnd, L"FFB type:", 44, 70));
+ settings.setMinWnd(slider(mainWnd, L"Min force:", 44, 130, L"0", L"20", false));
+ settings.setMaxWnd(slider(mainWnd, L"Max force:", 44, 170, L"5 Nm", L"100 Nm", false));
+ settings.setDampingWnd(slider(mainWnd, L"Damping:", 44, 210, L"0", L"100", true));
+
+ groupox(mainWnd, L"Overlay:", 32, 250, 295, 110);
+ settings.setForceOverlayWnd(checkbox(mainWnd, L"Show overlay?", 44, 270, 180));
+ overlayMoveWnd = checkbox(mainWnd, L"Enable input?", 44, 290, 180);
+ EnableWindow(overlayMoveWnd, FALSE);
+
+ settings.setOverlayTransparencyWnd(slider(mainWnd, L"Overlay transparency:", 44, 310, L"0", L"255", false));
+
+ statusWnd = CreateWindowEx(
+ 0, STATUSCLASSNAME, NULL,
+ WS_CHILD | WS_VISIBLE,
+ 0, 0, 0, 0, mainWnd, NULL, hInst, NULL
+ );
+
+ textWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE, L"EDIT", L"",
+ WS_VISIBLE | WS_VSCROLL | WS_CHILD | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
+ 32, 370, 295, 120,
+ mainWnd, NULL, hInst, NULL
+ );
+ SendMessage(textWnd, EM_SETLIMITTEXT, WPARAM(256000), 0);
+ //right side UI
+ auto groupoxWnd = groupox(mainWnd, L"Understeer Effect:", 344, 20, 295, 210);
+ settings.setUndersteerWnd(slider(mainWnd, L"Understeer:", 364, 50, L"0", L"100", true));
+ settings.setUndersteerOffsetWnd(slider(mainWnd, L"Offset:", 364, 90, L"0", L"100", true));
+ settings.setUndersteerYawRateMultWnd(slider(mainWnd, L"Force multiplier:", 364, 130, L"0", L"60", true));
+ settings.setUndersteerlatAccelDivWnd(slider(mainWnd, L"Release force:", 364, 170, L"60", L"130", true));
+
+ settings.setBumpsWnd(slider(mainWnd, L"Suspension bumps:", 364, 240, L"0", L"100", true));
+ settings.setSopWnd(slider(mainWnd, L"SoP effect:", 364, 280, L"0", L"100", true));
+ settings.setSopOffsetWnd(slider(mainWnd, L"SoP offset:", 364, 320, L"0", L"100", true));
+ settings.setUse360Wnd(checkbox(mainWnd, L"Use 360 Hz telemetry for suspension effects\r\n in direct modes?", 360, 360, 300, 38));
+
+ settings.setCarSpecificWnd(
+ checkbox(mainWnd, L"Use car specific settings?", 360, 395)
+ );
+ settings.setReduceWhenParkedWnd(
+ checkbox(mainWnd, L"Reduce force when parked?", 360, 415)
+ );
+ settings.setRunOnStartupWnd(
+ checkbox(mainWnd, L"Run on startup?", 360, 435)
+ );
+ settings.setStartMinimisedWnd(
+ checkbox(mainWnd, L"Start minimised?", 360, 455)
+ );
+ settings.setDebugWnd(
+ checkbox(mainWnd, L"Debug logging?", 360, 475)
+ );
+
+ //spanning UI
+ currentForceWnd = progressbar(mainWnd, L"Current applied force", 32, 500, 480, 20, IR_MAX);
+ clippingForceWnd = progressbar(mainWnd, L"Clipping force", 480, 500, 160, 20, progressClippingMax);
+
+ SendMessage(clippingForceWnd, PBM_SETSTATE, PBST_ERROR, 0);
+
+ int statusParts[] = { 256, 424, 864 };
+ SendMessage(statusWnd, SB_SETPARTS, 3, LPARAM(statusParts));
+
+ BOOL value = TRUE;
+ DwmSetWindowAttribute(mainWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value));
+
+ ShowWindow(mainWnd, SW_HIDE);
+ UpdateWindow(mainWnd);
+
+ memset(&devFilter, 0, sizeof(devFilter));
+ devFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
+ devFilter.dbcc_size = sizeof(devFilter);
+ devFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ RegisterDeviceNotificationW(mainWnd, &devFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
+
+ CreateOverlayWindow(hInstance);
+
+ HFONT hFont = CreateFont(14, 0, 0, 0, FW_DONTCARE | FW_SEMIBOLD, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ DEFAULT_PITCH | FF_DONTCARE, TEXT("Microsoft Sans Serif"));
+
+ EnumChildWindows(mainWnd, (WNDENUMPROC)SetFont, (LPARAM)hFont);
+
+ return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
- HWND wnd = (HWND)lParam;
-
- switch (message) {
-
- case WM_COMMAND: {
-
- int wmId = LOWORD(wParam);
- switch (wmId) {
-
- case IDM_ABOUT:
- DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
- break;
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
- case ID_SETTINGS_JETSEAT:
- if (jetseat)
- jetseat->createWindow(hInst);
- break;
- case ID_SETTINGS_FAN:
- fan->createWindow(hInst);
- break;
- case ID_SETTINGS_HIDGUARDIAN:
- hidGuardian->createWindow(hInst);
- default:
- if (HIWORD(wParam) == CBN_SELCHANGE) {
- if (wnd == settings.getDevWnd()) {
- GUID oldDevice = settings.getFfbDevice();
- DWORD vidpid = 0;
- if (oldDevice != GUID_NULL)
- vidpid = getDeviceVidPid(ffdevice);
- settings.setFfbDevice(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
- if (vidpid != 0 && oldDevice != settings.getFfbDevice())
- hidGuardian->removeDevice(LOWORD(vidpid), HIWORD(vidpid), false);
- }
- else if (wnd == settings.getFfbWnd())
- settings.setFfbType(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
- }
- else if (HIWORD(wParam) == BN_CLICKED) {
- bool oldValue = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
- if (wnd == settings.getUse360Wnd())
- settings.setUse360ForDirect(!oldValue);
- else if (wnd == settings.getCarSpecificWnd()) {
- if (!oldValue)
- getCarName();
- settings.setUseCarSpecific(!oldValue, car);
- }
- else if (wnd == settings.getReduceWhenParkedWnd())
- settings.setReduceWhenParked(!oldValue);
- else if (wnd == settings.getRunOnStartupWnd())
- settings.setRunOnStartup(!oldValue);
- else if (wnd == settings.getStartMinimisedWnd())
- settings.setStartMinimised(!oldValue);
- else if (wnd == settings.getDebugWnd()) {
- settings.setDebug(!oldValue);
- if (settings.getDebug()) {
- debugHnd = CreateFileW(settings.getLogPath(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- int chars = SendMessageW(textWnd, WM_GETTEXTLENGTH, 0, 0);
- wchar_t *buf = new wchar_t[chars + 1], *str = buf;
- SendMessageW(textWnd, WM_GETTEXT, chars + 1, (LPARAM)buf);
- wchar_t *end = StrStrW(str, L"\r\n");
- while (end) {
- *end = '\0';
- debug(str);
- str = end + 2;
- end = StrStrW(str, L"\r\n");
- }
- delete[] buf;
- }
- else if (debugHnd != INVALID_HANDLE_VALUE) {
- CloseHandle(debugHnd);
- debugHnd = INVALID_HANDLE_VALUE;
- }
- }
- }
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- }
- break;
-
- case WM_EDIT_VALUE: {
- if (wnd == settings.getMaxWnd()->value)
- settings.setMaxForce(wParam, wnd);
- else if (wnd == settings.getMinWnd()->value)
- settings.setMinForce(wParam, wnd);
- else if (wnd == settings.getBumpsWnd()->value)
- settings.setBumpsFactor(reinterpret_cast(wParam), wnd);
- else if (wnd == settings.getDampingWnd()->value)
- settings.setDampingFactor(reinterpret_cast(wParam), wnd);
- else if (wnd == settings.getSopWnd()->value)
- settings.setSopFactor(reinterpret_cast(wParam), wnd);
- else if (wnd == settings.getSopOffsetWnd()->value)
- settings.setSopOffset(reinterpret_cast(wParam), wnd);
- }
- break;
-
-
- case WM_HSCROLL: {
- if (wnd == settings.getMaxWnd()->trackbar)
- settings.setMaxForce(SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getMinWnd()->trackbar)
- settings.setMinForce(SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getBumpsWnd()->trackbar)
- settings.setBumpsFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getDampingWnd()->trackbar)
- settings.setDampingFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getSopWnd()->trackbar)
- settings.setSopFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getSopOffsetWnd()->trackbar)
- settings.setSopOffset((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getUndersteerWnd()->trackbar)
- settings.setUndersteerFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- else if (wnd == settings.getUndersteerOffsetWnd()->trackbar)
- settings.setUndersteerOffset((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
- }
- break;
-
- case WM_CTLCOLORSTATIC: {
- SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
- return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
- }
- break;
-
- case WM_PRINTCLIENT: {
- RECT r = { 0 };
- GetClientRect(hWnd, &r);
- FillRect((HDC)wParam, &r, CreateSolidBrush(RGB(0xff, 0xff, 0xff)));
- }
- break;
-
- case WM_SIZE: {
- SendMessage(statusWnd, WM_SIZE, wParam, lParam);
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- break;
-
- case WM_POWERBROADCAST: {
- int wmId = LOWORD(wParam);
- switch (wmId) {
- case PBT_APMSUSPEND:
- debug(L"Computer is suspending, release all");
- releaseAll();
- break;
- case PBT_APMRESUMESUSPEND:
- debug(L"Computer is resuming, init all");
- initAll();
- break;
- }
- }
- break;
-
- case WM_TRAY_ICON: {
- switch (lParam) {
- case WM_LBUTTONUP:
- restore();
- break;
- case WM_RBUTTONUP: {
- HMENU trayMenu = CreatePopupMenu();
- POINT curPoint;
- AppendMenuW(trayMenu, MF_STRING, ID_TRAY_EXIT, L"Exit");
- GetCursorPos(&curPoint);
- SetForegroundWindow(hWnd);
- if (
- TrackPopupMenu(
- trayMenu, TPM_RETURNCMD | TPM_NONOTIFY,
- curPoint.x, curPoint.y, 0, hWnd, NULL
- ) == ID_TRAY_EXIT
- )
- PostQuitMessage(0);
- DestroyMenu(trayMenu);
- }
- break;
- }
-
- }
- break;
-
- case WM_DEVICECHANGE: {
- DEV_BROADCAST_HDR *hdr = (DEV_BROADCAST_HDR *)lParam;
- if (wParam != DBT_DEVICEARRIVAL && wParam != DBT_DEVICEREMOVECOMPLETE)
- return 0;
- if (hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
- return 0;
- deviceChange();
- }
- break;
-
- case WM_SYSCOMMAND: {
- switch (wParam & 0xfff0) {
- case SC_MINIMIZE:
- minimise();
- return 0;
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
- }
- break;
-
- case WM_DESTROY: {
- debug(L"Exiting");
- Shell_NotifyIcon(NIM_DELETE, &niData);
- releaseAll();
- if (settings.getUseCarSpecific() && car[0] != 0)
- settings.writeSettingsForCar(car);
- else
- settings.writeGenericSettings();
- settings.writeRegSettings();
- hidGuardian->stop(GetCurrentProcessId());
- if (debugHnd != INVALID_HANDLE_VALUE)
- CloseHandle(debugHnd);
- CloseHandle(globalMutex);
- exit(0);
- }
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
-
- return 0;
+ HWND wnd = (HWND)lParam;
+
+ switch (message) {
+
+ case WM_COMMAND: {
+
+ int wmId = LOWORD(wParam);
+ switch (wmId) {
+
+ case IDM_ABOUT:
+ DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
+ break;
+ case IDM_EXIT:
+ DestroyWindow(hWnd);
+ break;
+ default:
+ if (HIWORD(wParam) == CBN_SELCHANGE) {
+ if (wnd == settings.getDevWnd()) {
+ GUID oldDevice = settings.getFfbDevice();
+ DWORD vidpid = 0;
+ if (oldDevice != GUID_NULL)
+ vidpid = getDeviceVidPid(ffdevice);
+ settings.setFfbDevice(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
+ }
+ else if (wnd == settings.getFfbWnd())
+ settings.setFfbType(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
+ }
+ else if (HIWORD(wParam) == BN_CLICKED) {
+ bool oldValue = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
+ if (wnd == settings.getUse360Wnd())
+ settings.setUse360ForDirect(!oldValue);
+ else if (wnd == settings.getCarSpecificWnd()) {
+ if (!oldValue)
+ getCarName();
+ settings.setUseCarSpecific(!oldValue, car);
+ }
+ else if (wnd == settings.getReduceWhenParkedWnd())
+ settings.setReduceWhenParked(!oldValue);
+ else if (wnd == settings.getRunOnStartupWnd())
+ settings.setRunOnStartup(!oldValue);
+ else if (wnd == settings.getStartMinimisedWnd())
+ settings.setStartMinimised(!oldValue);
+ else if (wnd == settings.getForceOverlayWnd())
+ {
+ settings.setShowForceOverlay(!oldValue);
+ if (!oldValue)
+ {
+ EnableWindow(overlayMoveWnd, TRUE);
+ ShowWindow(overlayWnd, SW_SHOW);
+ }
+ else
+ {
+ EnableWindow(overlayMoveWnd, FALSE);
+ ShowWindow(overlayWnd, SW_HIDE);
+ }
+ }
+ else if (wnd == overlayMoveWnd)
+ {
+ if (!oldValue)
+ ActivateOverLayWindow();
+ else
+ DeActivateOverlayWindow();
+ SendMessage(overlayMoveWnd, BM_SETCHECK, !oldValue ? BST_CHECKED : BST_UNCHECKED, NULL);
+
+ }
+
+
+ else if (wnd == settings.getDebugWnd()) {
+ settings.setDebug(!oldValue);
+ if (settings.getDebug()) {
+ debugHnd = CreateFileW(settings.getLogPath().c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ int chars = SendMessageW(textWnd, WM_GETTEXTLENGTH, 0, 0);
+ wchar_t* buf = new wchar_t[chars + 1], * str = buf;
+ SendMessageW(textWnd, WM_GETTEXT, chars + 1, (LPARAM)buf);
+ wchar_t* end = StrStrW(str, L"\r\n");
+ while (end) {
+ *end = '\0';
+ debug(str);
+ str = end + 2;
+ end = StrStrW(str, L"\r\n");
+ }
+ delete[] buf;
+ }
+ else if (debugHnd != INVALID_HANDLE_VALUE) {
+ CloseHandle(debugHnd);
+ debugHnd = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ }
+ break;
+
+ case WM_EDIT_VALUE: {
+ if (wnd == settings.getMaxWnd()->value)
+ settings.setMaxForce(wParam, wnd);
+ else if (wnd == settings.getMinWnd()->value)
+ settings.setMinForce(wParam, wnd);
+ else if (wnd == settings.getBumpsWnd()->value)
+ settings.setBumpsFactor(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getDampingWnd()->value)
+ settings.setDampingFactor(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getSopWnd()->value)
+ settings.setSopFactor(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getSopOffsetWnd()->value)
+ settings.setSopOffset(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getUndersteerYawRateMultWnd()->value)
+ settings.setUndersteerYawRateMult(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getUndersteerlatAccelDivWnd()->value)
+ settings.setUndersteerlatAccelDiv(reinterpret_cast(wParam), wnd);
+ else if (wnd == settings.getOverlayTransparencyWnd()->value)
+ {
+ settings.setOverlayTransparency(reinterpret_cast(wParam), wnd);
+ SetLayeredWindowAttributes(overlayWnd, 0, settings.getOverlayTransparency(), LWA_ALPHA);
+ }
+
+ }
+ break;
+
+
+ case WM_HSCROLL: {
+ if (wnd == settings.getMaxWnd()->trackbar || wnd == settings.getOverlayMaxForceWnd())
+ settings.setMaxForce(SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getMinWnd()->trackbar)
+ settings.setMinForce(SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getBumpsWnd()->trackbar)
+ settings.setBumpsFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getDampingWnd()->trackbar)
+ settings.setDampingFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getSopWnd()->trackbar)
+ settings.setSopFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getSopOffsetWnd()->trackbar)
+ settings.setSopOffset((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getUndersteerWnd()->trackbar)
+ settings.setUndersteerFactor((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getUndersteerOffsetWnd()->trackbar)
+ settings.setUndersteerOffset((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getUndersteerYawRateMultWnd()->trackbar)
+ settings.setUndersteerYawRateMult((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getUndersteerlatAccelDivWnd()->trackbar)
+ settings.setUndersteerlatAccelDiv((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ else if (wnd == settings.getOverlayTransparencyWnd()->trackbar)
+ {
+ settings.setOverlayTransparency((float)SendMessage(wnd, TBM_GETPOS, 0, 0), wnd);
+ SetLayeredWindowAttributes(overlayWnd, 0, settings.getOverlayTransparency(), LWA_ALPHA);
+ }
+
+ }
+ break;
+
+ case WM_CTLCOLORSTATIC: {
+ SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
+ return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
+ }
+ break;
+
+ case WM_PRINTCLIENT: {
+ RECT r = { 0 };
+ GetClientRect(hWnd, &r);
+ FillRect((HDC)wParam, &r, CreateSolidBrush(RGB(0xff, 0xff, 0xff)));
+ }
+ break;
+
+ case WM_SIZE: {
+ SendMessage(statusWnd, WM_SIZE, wParam, lParam);
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ break;
+
+ case WM_POWERBROADCAST: {
+ int wmId = LOWORD(wParam);
+ switch (wmId) {
+ case PBT_APMSUSPEND:
+ debug(L"Computer is suspending, release all");
+ releaseAll();
+ break;
+ case PBT_APMRESUMESUSPEND:
+ debug(L"Computer is resuming, init all");
+ initAll();
+ break;
+ }
+ }
+ break;
+
+ case WM_TRAY_ICON: {
+ switch (lParam) {
+ case WM_LBUTTONUP:
+ restore();
+ break;
+ case WM_RBUTTONUP: {
+ HMENU trayMenu = CreatePopupMenu();
+ POINT curPoint;
+ AppendMenuW(trayMenu, MF_STRING, ID_TRAY_EXIT, L"Exit");
+ GetCursorPos(&curPoint);
+ SetForegroundWindow(hWnd);
+ if (
+ TrackPopupMenu(
+ trayMenu, TPM_RETURNCMD | TPM_NONOTIFY,
+ curPoint.x, curPoint.y, 0, hWnd, NULL
+ ) == ID_TRAY_EXIT
+ )
+ PostQuitMessage(0);
+ DestroyMenu(trayMenu);
+ }
+ break;
+ }
+
+ }
+ break;
+ case WM_WINDOWPOSCHANGED:
+ {
+ if (hWnd == overlayWnd)
+ {
+ WINDOWPOS* winPos = (WINDOWPOS*)lParam;
+ settings.setWindowPosX(winPos->x);
+ settings.setWindowPosY(winPos->y);
+ }
+ }
+ break;
+
+ case WM_DEVICECHANGE: {
+ DEV_BROADCAST_HDR* hdr = (DEV_BROADCAST_HDR*)lParam;
+ if (wParam != DBT_DEVICEARRIVAL && wParam != DBT_DEVICEREMOVECOMPLETE)
+ return 0;
+ if (hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
+ return 0;
+ deviceChange();
+ }
+ break;
+
+ case WM_SYSCOMMAND: {
+ switch (wParam & 0xfff0) {
+ case SC_MINIMIZE:
+ minimise();
+ return 0;
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ }
+ break;
+
+ case WM_DESTROY: {
+ debug(L"Exiting");
+ Shell_NotifyIcon(NIM_DELETE, &niData);
+ releaseAll();
+ if (settings.getUseCarSpecific() && car[0] != 0)
+ settings.writeSettingsForCar(car);
+ else
+ settings.writeGenericSettings();
+ settings.writeRegSettings();
+ if (debugHnd != INVALID_HANDLE_VALUE)
+ CloseHandle(debugHnd);
+ CloseHandle(globalMutex);
+ exit(0);
+ }
+ break;
+
+ case WM_NCHITTEST:
+ {
+ LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
+ if (hWnd == overlayWnd && hit == HTCLIENT)
+ hit = HTCAPTION;
+
+ return hit;
+ }
+ break;
+ case WM_HOTKEY:
+ {
+ int wmId = LOWORD(wParam);
+ if (wmId == ID_MAXFORCE_UP)
+ settings.setMaxForce(settings.getMaxForce() - 1, (HWND)-1);
+
+ if (wmId == ID_MAXFORCE_DOWN)
+ settings.setMaxForce(settings.getMaxForce() + 1, (HWND)-1);
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ return 0;
}
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
- UNREFERENCED_PARAMETER(lParam);
+ UNREFERENCED_PARAMETER(lParam);
- switch (message) {
+ switch (message) {
- case WM_INITDIALOG:
- return (INT_PTR)TRUE;
+ case WM_INITDIALOG:
+ return (INT_PTR)TRUE;
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
- EndDialog(hDlg, LOWORD(wParam));
- return (INT_PTR)TRUE;
- }
- break;
- }
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hDlg, LOWORD(wParam));
+ return (INT_PTR)TRUE;
+ }
+ break;
+ }
- return (INT_PTR)FALSE;
+ return (INT_PTR)FALSE;
}
+LRESULT CALLBACK myPaint(HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ switch (uMsg)
+ {
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ RECT rectangle;
+ HDC hdc = BeginPaint(hWnd, &ps);
+ SendMessage(hWnd, WM_ERASEBKGND, (WPARAM)GetDC(hWnd), NULL); /* Erases the background */
+ GetClientRect(hWnd, &rectangle); /* Gets the toolbar's area */
+ FillRect(GetDC(hWnd), &rectangle, (HBRUSH)(COLOR_WINDOW + 2)); /* Fills the toolbar's background white */
+ EndPaint(hWnd, &ps);
+
+ break;
+ }
+ }
+ return DefSubclassProc(hWnd, uMsg, wParam, lParam);
+}
+LRESULT CALLBACK myNcHitTest(HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ switch (uMsg)
+ {
+ case WM_NCHITTEST:
+ {
+ LRESULT hit = DefSubclassProc(hWnd, uMsg, wParam, lParam);
+ if (hit == HTCLIENT) hit = HTTRANSPARENT;
+ return hit;
+ }
+ }
+ return DefSubclassProc(hWnd, uMsg, wParam, lParam);
+}
-void text(wchar_t *fmt, ...) {
+void text(wchar_t* fmt, ...) {
- va_list argp;
- wchar_t msg[512];
- va_start(argp, fmt);
+ va_list argp;
+ wchar_t msg[512];
+ va_start(argp, fmt);
- StringCbVPrintf(msg, sizeof(msg) - 2 * sizeof(wchar_t), fmt, argp);
- va_end(argp);
- StringCbCat(msg, sizeof(msg), L"\r\n");
+ StringCbVPrintf(msg, sizeof(msg) - 2 * sizeof(wchar_t), fmt, argp);
+ va_end(argp);
+ StringCbCat(msg, sizeof(msg), L"\r\n");
- SendMessage(textWnd, EM_SETSEL, 0, -1);
- SendMessage(textWnd, EM_SETSEL, -1, 1);
- SendMessage(textWnd, EM_REPLACESEL, 0, (LPARAM)msg);
- SendMessage(textWnd, EM_SCROLLCARET, 0, 0);
+ SendMessage(textWnd, EM_SETSEL, 0, -1);
+ SendMessage(textWnd, EM_SETSEL, -1, 1);
+ SendMessage(textWnd, EM_REPLACESEL, 0, (LPARAM)msg);
+ SendMessage(textWnd, EM_SCROLLCARET, 0, 0);
- debug(msg);
+ debug(msg);
}
-void text(wchar_t *fmt, char *charstr) {
-
- int len = strlen(charstr) + 1;
- wchar_t *wstr = new wchar_t[len];
- mbstowcs_s(nullptr, wstr, len, charstr, len);
- text(fmt, wstr);
- delete[] wstr;
+void text(wchar_t* fmt, char* charstr) {
+ int len = strlen(charstr) + 1;
+ wchar_t* wstr = new wchar_t[len];
+ mbstowcs_s(nullptr, wstr, len, charstr, len);
+ text(fmt, wstr);
+ delete[] wstr;
+ return;
}
-void debug(wchar_t *msg) {
-
- if (!settings.getDebug())
- return;
-
- DWORD written;
- wchar_t buf[512];
- SYSTEMTIME lt;
-
- GetLocalTime(<);
- StringCbPrintfW(
- buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d:%02d.%03d ",
- lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds
- );
-
- StringCbCat(buf, sizeof(buf), msg);
- StringCbCat(buf, sizeof(buf), L"\r\n");
-
- if (!wcscmp(msg, debugLastMsg)) {
- debugRepeat++;
- return;
- }
- else if (debugRepeat) {
- wchar_t rm[256];
- StringCbPrintfW(rm, sizeof(rm), L"-- Last message repeated %d times --\r\n", debugRepeat);
- WriteFile(debugHnd, rm, wcslen(rm) * sizeof(wchar_t), &written, NULL);
- debugRepeat = 0;
- }
-
- StringCbCopy(debugLastMsg, sizeof(debugLastMsg), msg);
- WriteFile(debugHnd, buf, wcslen(buf) * sizeof(wchar_t), &written, NULL);
+void debug(wchar_t* msg) {
+
+ if (!settings.getDebug())
+ return;
+
+ DWORD written;
+ wchar_t buf[512];
+ SYSTEMTIME lt;
+
+ GetLocalTime(<);
+ StringCbPrintfW(
+ buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d:%02d.%03d ",
+ lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds
+ );
+
+ StringCbCat(buf, sizeof(buf), msg);
+ StringCbCat(buf, sizeof(buf), L"\r\n");
+
+ if (!wcscmp(msg, debugLastMsg)) {
+ debugRepeat++;
+ return;
+ }
+ else if (debugRepeat) {
+ wchar_t rm[256];
+ StringCbPrintfW(rm, sizeof(rm), L"-- Last message repeated %d times --\r\n", debugRepeat);
+ WriteFile(debugHnd, rm, wcslen(rm) * sizeof(wchar_t), &written, NULL);
+ debugRepeat = 0;
+ }
+
+ StringCbCopy(debugLastMsg, sizeof(debugLastMsg), msg);
+ WriteFile(debugHnd, buf, wcslen(buf) * sizeof(wchar_t), &written, NULL);
}
template
-void debug(wchar_t *fmt, T... args) {
+void debug(wchar_t* fmt, T... args) {
- if (!settings.getDebug())
- return;
+ if (!settings.getDebug())
+ return;
- wchar_t msg[512];
- StringCbPrintf(msg, sizeof(msg), fmt, args...);
- debug(msg);
+ wchar_t msg[512];
+ StringCbPrintf(msg, sizeof(msg), fmt, args...);
+ debug(msg);
}
-void setCarStatus(char *carStr) {
+void setCarStatus(char* carStr) {
- if (!carStr || carStr[0] == 0) {
- SendMessage(statusWnd, SB_SETTEXT, STATUS_CAR_PART, LPARAM(L"Car: generic"));
- return;
- }
+ if (!carStr || carStr[0] == 0) {
+ SendMessage(statusWnd, SB_SETTEXT, STATUS_CAR_PART, LPARAM(L"Car: generic"));
+ return;
+ }
- int len = strlen(carStr) + 1;
- wchar_t *wstr = new wchar_t[len + 5];
- lstrcpy(wstr, L"Car: ");
- mbstowcs_s(nullptr, wstr + 5, len, carStr, len);
- SendMessage(statusWnd, SB_SETTEXT, STATUS_CAR_PART, LPARAM(wstr));
- delete[] wstr;
+ int len = strlen(carStr) + 1;
+ wchar_t* wstr = new wchar_t[len + 5];
+ lstrcpy(wstr, L"Car: ");
+ mbstowcs_s(nullptr, wstr + 5, len, carStr, len);
+ SendMessage(statusWnd, SB_SETTEXT, STATUS_CAR_PART, LPARAM(wstr));
+ delete[] wstr;
}
void setConnectedStatus(bool connected) {
- SendMessage(
- statusWnd, SB_SETTEXT, STATUS_CONNECTED_PART,
- LPARAM(connected ? L"iRacing connected" : L"iRacing disconnected")
- );
+ SendMessage(
+ statusWnd, SB_SETTEXT, STATUS_CONNECTED_PART,
+ LPARAM(connected ? L"iRacing connected" : L"iRacing disconnected")
+ );
}
void setOnTrackStatus(bool onTrack) {
- SendMessage(
- statusWnd, SB_SETTEXT, STATUS_ONTRACK_PART,
- LPARAM(onTrack ? L"On track" : L"Not on track")
- );
+ SendMessage(
+ statusWnd, SB_SETTEXT, STATUS_ONTRACK_PART,
+ LPARAM(onTrack ? L"On track" : L"Not on track")
+ );
- if (!onTrack && deviceChangePending) {
- debug(L"Processing deferred device change notification");
- deviceChange();
- }
+ if (!onTrack && deviceChangePending) {
+ debug(L"Processing deferred device change notification");
+ deviceChange();
+ }
}
void setLogiWheelRange(WORD prodId) {
- if (prodId == G25PID || prodId == DFGTPID || prodId == G27PID) {
+ if (prodId == G25PID || prodId == DFGTPID || prodId == G27PID) {
- GUID hidGuid;
- HidD_GetHidGuid(&hidGuid);
+ GUID hidGuid;
+ HidD_GetHidGuid(&hidGuid);
- text(L"DFGT/G25/G27 detected, setting range using raw HID");
+ text(L"DFGT/G25/G27 detected, setting range using raw HID");
- HANDLE devInfoSet = SetupDiGetClassDevsW(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
- if (devInfoSet == INVALID_HANDLE_VALUE) {
- text(L"LogiWheel: Error enumerating HID devices");
- return;
- }
+ HANDLE devInfoSet = SetupDiGetClassDevsW(&hidGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (devInfoSet == INVALID_HANDLE_VALUE) {
+ text(L"LogiWheel: Error enumerating HID devices");
+ return;
+ }
- SP_DEVICE_INTERFACE_DATA intfData;
- SP_DEVICE_INTERFACE_DETAIL_DATA *intfDetail;
- DWORD idx = 0;
- DWORD error = 0;
- DWORD size;
+ SP_DEVICE_INTERFACE_DATA intfData;
+ SP_DEVICE_INTERFACE_DETAIL_DATA* intfDetail;
+ DWORD idx = 0;
+ DWORD error = 0;
+ DWORD size;
- while (true) {
+ while (true) {
- intfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+ intfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
- if (!SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &hidGuid, idx++, &intfData)) {
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
- break;
- continue;
- }
+ if (!SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &hidGuid, idx++, &intfData)) {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ break;
+ continue;
+ }
- if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &intfData, NULL, 0, &size, NULL))
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- text(L"LogiWheel: Error getting intf detail");
- continue;
- }
+ if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &intfData, NULL, 0, &size, NULL))
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ text(L"LogiWheel: Error getting intf detail");
+ continue;
+ }
- intfDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(size);
- intfDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+ intfDetail = (SP_DEVICE_INTERFACE_DETAIL_DATA*)malloc(size);
+ intfDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
- if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &intfData, intfDetail, size, NULL, NULL)) {
- free(intfDetail);
- continue;
- }
+ if (!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &intfData, intfDetail, size, NULL, NULL)) {
+ free(intfDetail);
+ continue;
+ }
- if (
- wcsstr(intfDetail->DevicePath, G25PATH) != NULL ||
- wcsstr(intfDetail->DevicePath, DFGTPATH) != NULL ||
- wcsstr(intfDetail->DevicePath, G27PATH) != NULL
- ) {
+ if (
+ wcsstr(intfDetail->DevicePath, G25PATH) != NULL ||
+ wcsstr(intfDetail->DevicePath, DFGTPATH) != NULL ||
+ wcsstr(intfDetail->DevicePath, G27PATH) != NULL
+ ) {
- HANDLE file = CreateFileW(
- intfDetail->DevicePath,
- GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
- );
+ HANDLE file = CreateFileW(
+ intfDetail->DevicePath,
+ GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
+ );
- if (file == INVALID_HANDLE_VALUE) {
- text(L"LogiWheel: Failed to open HID device");
- free(intfDetail);
- SetupDiDestroyDeviceInfoList(devInfoSet);
- return;
- }
+ if (file == INVALID_HANDLE_VALUE) {
+ text(L"LogiWheel: Failed to open HID device");
+ free(intfDetail);
+ SetupDiDestroyDeviceInfoList(devInfoSet);
+ return;
+ }
- DWORD written;
+ DWORD written;
- if (!WriteFile(file, LOGI_WHEEL_HID_CMD, LOGI_WHEEL_HID_CMD_LEN, &written, NULL))
- text(L"LogiWheel: Failed to write to HID device");
- else
- text(L"LogiWheel: Range set to 900 deg via raw HID");
+ if (!WriteFile(file, LOGI_WHEEL_HID_CMD, LOGI_WHEEL_HID_CMD_LEN, &written, NULL))
+ text(L"LogiWheel: Failed to write to HID device");
+ else
+ text(L"LogiWheel: Range set to 900 deg via raw HID");
- CloseHandle(file);
- free(intfDetail);
- SetupDiDestroyDeviceInfoList(devInfoSet);
- return;
+ CloseHandle(file);
+ free(intfDetail);
+ SetupDiDestroyDeviceInfoList(devInfoSet);
+ return;
- }
+ }
- free(intfDetail);
+ free(intfDetail);
- }
+ }
- text(L"Failed to locate Logitech wheel HID device, can't set range");
- SetupDiDestroyDeviceInfoList(devInfoSet);
- return;
+ text(L"Failed to locate Logitech wheel HID device, can't set range");
+ SetupDiDestroyDeviceInfoList(devInfoSet);
+ return;
- }
+ }
- text(L"Attempting to set range via LGS");
+ text(L"Attempting to set range via LGS");
- UINT msgId = RegisterWindowMessage(L"LGS_Msg_SetOperatingRange");
- if (!msgId) {
- text(L"Failed to register LGS window message, can't set range..");
- return;
- }
+ UINT msgId = RegisterWindowMessage(L"LGS_Msg_SetOperatingRange");
+ if (!msgId) {
+ text(L"Failed to register LGS window message, can't set range..");
+ return;
+ }
- HWND LGSmsgHandler =
- FindWindowW(
- L"LCore_MessageHandler_{C464822E-04D1-4447-B918-6D5EB33E0E5D}",
- NULL
- );
+ HWND LGSmsgHandler =
+ FindWindowW(
+ L"LCore_MessageHandler_{C464822E-04D1-4447-B918-6D5EB33E0E5D}",
+ NULL
+ );
- if (LGSmsgHandler == NULL) {
- text(L"Failed to locate LGS msg handler, can't set range..");
- return;
- }
+ if (LGSmsgHandler == NULL) {
+ text(L"Failed to locate LGS msg handler, can't set range..");
+ return;
+ }
- SendMessageW(LGSmsgHandler, msgId, prodId, 900);
- text(L"Range of Logitech wheel set to 900 deg via LGS");
+ SendMessageW(LGSmsgHandler, msgId, prodId, 900);
+ text(L"Range of Logitech wheel set to 900 deg via LGS");
}
-BOOL CALLBACK EnumFFDevicesCallback(LPCDIDEVICEINSTANCE diDevInst, VOID *wnd) {
+BOOL CALLBACK EnumFFDevicesCallback(LPCDIDEVICEINSTANCE diDevInst, VOID* wnd) {
- UNREFERENCED_PARAMETER(wnd);
+ UNREFERENCED_PARAMETER(wnd);
- if (lstrcmp(diDevInst->tszProductName, L"vJoy Device") == 0)
- return true;
+ if (lstrcmp(diDevInst->tszProductName, L"vJoy Device") == 0)
+ return true;
- settings.addFfbDevice(diDevInst->guidInstance, diDevInst->tszProductName);
- debug(L"Adding DI device: %s", diDevInst->tszProductName);
+ settings.addFfbDevice(diDevInst->guidInstance, diDevInst->tszProductName);
+ debug(L"Adding DI device: %s", diDevInst->tszProductName);
- return true;
+ return true;
}
-BOOL CALLBACK EnumObjectCallback(const LPCDIDEVICEOBJECTINSTANCE inst, VOID *dw) {
+BOOL CALLBACK EnumObjectCallback(const LPCDIDEVICEOBJECTINSTANCE inst, VOID* dw) {
- UNREFERENCED_PARAMETER(inst);
+ UNREFERENCED_PARAMETER(inst);
- (*(int *)dw)++;
- return DIENUM_CONTINUE;
+ (*(int*)dw)++;
+ return DIENUM_CONTINUE;
}
void enumDirectInput() {
- settings.clearFfbDevices();
-
- if (
- FAILED(
- DirectInput8Create(
- GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8,
- (VOID **)&pDI, nullptr
- )
- )
- ) {
- text(L"Failed to initialise DirectInput");
- return;
- }
-
- pDI->EnumDevices(
- DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, settings.getDevWnd(),
- DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK
- );
+ settings.clearFfbDevices();
+
+ if (
+ FAILED(
+ DirectInput8Create(
+ GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8,
+ (VOID**)&pDI, nullptr
+ )
+ )
+ ) {
+ text(L"Failed to initialise DirectInput");
+ return;
+ }
+
+ pDI->EnumDevices(
+ DI8DEVCLASS_GAMECTRL, EnumFFDevicesCallback, settings.getDevWnd(),
+ DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK
+ );
}
void initDirectInput() {
- DIDEVICEINSTANCE di;
- HRESULT hr;
-
- numButtons = numPov = 0;
- di.dwSize = sizeof(DIDEVICEINSTANCE);
-
- if (ffdevice && effect && ffdevice->GetDeviceInfo(&di) >= 0 && di.guidInstance == settings.getFfbDevice())
- return;
-
- releaseDirectInput();
-
- if (
- FAILED(
- DirectInput8Create(
- GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8,
- (VOID **)&pDI, nullptr
- )
- )
- ) {
- text(L"Failed to initialise DirectInput");
- return;
- }
-
- if (FAILED(pDI->CreateDevice(settings.getFfbDevice(), &ffdevice, nullptr))) {
- text(L"Failed to create DI device");
- text(L"Is it connected and powered on?");
- return;
- }
- if (FAILED(ffdevice->SetDataFormat(&c_dfDIJoystick))) {
- text(L"Failed to set DI device DataFormat!");
- return;
- }
- if (FAILED(ffdevice->SetCooperativeLevel(mainWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) {
- text(L"Failed to set DI device CooperativeLevel!");
- return;
- }
-
- if (FAILED(ffdevice->GetDeviceInfo(&di))) {
- text(L"Failed to get info for DI device!");
- return;
- }
-
- if (FAILED(ffdevice->EnumObjects(EnumObjectCallback, (VOID *)&numButtons, DIDFT_BUTTON))) {
- text(L"Failed to enumerate DI device buttons");
- return;
- }
-
- if (FAILED(ffdevice->EnumObjects(EnumObjectCallback, (VOID *)&numPov, DIDFT_POV))) {
- text(L"Failed to enumerate DI device povs");
- return;
- }
-
- if (FAILED(ffdevice->SetEventNotification(wheelEvent))) {
- text(L"Failed to set event notification on DI device");
- return;
- }
-
- DWORD vidpid = getDeviceVidPid(ffdevice);
- if (LOWORD(vidpid) == 0x046d) {
- logiWheel = true;
- setLogiWheelRange(HIWORD(vidpid));
- }
- else
- logiWheel = false;
-
- if (FAILED(ffdevice->Acquire())) {
- text(L"Failed to acquire DI device");
- return;
- }
-
- text(L"Acquired DI device with %d buttons and %d POV", numButtons, numPov);
-
- EnterCriticalSection(&effectCrit);
-
- if (FAILED(ffdevice->CreateEffect(GUID_Sine, &dieff, &effect, nullptr))) {
- text(L"Failed to create sine periodic effect");
- LeaveCriticalSection(&effectCrit);
- return;
- }
-
- if (!effect) {
- text(L"Effect creation failed");
- LeaveCriticalSection(&effectCrit);
- return;
- }
-
- hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
- if (hr == DIERR_NOTINITIALIZED || hr == DIERR_INPUTLOST || hr == DIERR_INCOMPLETEEFFECT || hr == DIERR_INVALIDPARAM)
- text(L"Error setting parameters of DIEFFECT: %d", hr);
-
- LeaveCriticalSection(&effectCrit);
-
- if (vidpid != 0)
- hidGuardian->setDevice(LOWORD(vidpid), HIWORD(vidpid));
+ DIDEVICEINSTANCE di;
+ HRESULT hr;
+
+ numButtons = numPov = 0;
+ di.dwSize = sizeof(DIDEVICEINSTANCE);
+
+ if (ffdevice && effect && ffdevice->GetDeviceInfo(&di) >= 0 && di.guidInstance == settings.getFfbDevice())
+ return;
+
+ releaseDirectInput();
+
+ if (
+ FAILED(
+ DirectInput8Create(
+ GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8,
+ (VOID**)&pDI, nullptr
+ )
+ )
+ ) {
+ text(L"Failed to initialise DirectInput");
+ return;
+ }
+
+ if (FAILED(pDI->CreateDevice(settings.getFfbDevice(), &ffdevice, nullptr))) {
+ text(L"Failed to create DI device");
+ text(L"Is it connected and powered on?");
+ return;
+ }
+ if (FAILED(ffdevice->SetDataFormat(&c_dfDIJoystick))) {
+ text(L"Failed to set DI device DataFormat!");
+ return;
+ }
+ if (FAILED(ffdevice->SetCooperativeLevel(mainWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) {
+ text(L"Failed to set DI device CooperativeLevel!");
+ return;
+ }
+
+ if (FAILED(ffdevice->GetDeviceInfo(&di))) {
+ text(L"Failed to get info for DI device!");
+ return;
+ }
+
+ if (FAILED(ffdevice->EnumObjects(EnumObjectCallback, (VOID*)&numButtons, DIDFT_BUTTON))) {
+ text(L"Failed to enumerate DI device buttons");
+ return;
+ }
+
+ if (FAILED(ffdevice->EnumObjects(EnumObjectCallback, (VOID*)&numPov, DIDFT_POV))) {
+ text(L"Failed to enumerate DI device povs");
+ return;
+ }
+
+ if (FAILED(ffdevice->SetEventNotification(wheelEvent))) {
+ text(L"Failed to set event notification on DI device");
+ return;
+ }
+
+ DWORD vidpid = getDeviceVidPid(ffdevice);
+ if (LOWORD(vidpid) == 0x046d) {
+ logiWheel = true;
+ setLogiWheelRange(HIWORD(vidpid));
+ }
+ else
+ logiWheel = false;
+
+ if (FAILED(ffdevice->Acquire())) {
+ text(L"Failed to acquire DI device");
+ return;
+ }
+
+ text(L"Acquired DI device with %d buttons and %d POV", numButtons, numPov);
+
+ EnterCriticalSection(&effectCrit);
+
+ if (FAILED(ffdevice->CreateEffect(GUID_Sine, &dieff, &effect, nullptr))) {
+ text(L"Failed to create sine periodic effect");
+ LeaveCriticalSection(&effectCrit);
+ return;
+ }
+
+ if (!effect) {
+ text(L"Effect creation failed");
+ LeaveCriticalSection(&effectCrit);
+ return;
+ }
+
+ hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
+ if (hr == DIERR_NOTINITIALIZED || hr == DIERR_INPUTLOST || hr == DIERR_INCOMPLETEEFFECT || hr == DIERR_INVALIDPARAM)
+ text(L"Error setting parameters of DIEFFECT: %d", hr);
+
+ LeaveCriticalSection(&effectCrit);
}
void releaseDirectInput() {
- if (effect) {
- setFFB(0);
- EnterCriticalSection(&effectCrit);
- effect->Stop();
- effect->Release();
- effect = nullptr;
- LeaveCriticalSection(&effectCrit);
- }
- if (ffdevice) {
- ffdevice->Unacquire();
- ffdevice->Release();
- ffdevice = nullptr;
- }
- if (pDI) {
- pDI->Release();
- pDI = nullptr;
- }
+ if (effect) {
+ setFFB(0);
+ EnterCriticalSection(&effectCrit);
+ effect->Stop();
+ effect->Release();
+ effect = nullptr;
+ LeaveCriticalSection(&effectCrit);
+ }
+ if (ffdevice) {
+ ffdevice->Unacquire();
+ ffdevice->Release();
+ ffdevice = nullptr;
+ }
+ if (pDI) {
+ pDI->Release();
+ pDI = nullptr;
+ }
}
void reacquireDIDevice() {
- if (ffdevice == nullptr) {
- debug(L"!! ffdevice was null during reacquire !!");
- return;
- }
+ if (ffdevice == nullptr) {
+ debug(L"!! ffdevice was null during reacquire !!");
+ return;
+ }
- HRESULT hr;
+ HRESULT hr;
- ffdevice->Unacquire();
- ffdevice->Acquire();
+ ffdevice->Unacquire();
+ ffdevice->Acquire();
- EnterCriticalSection(&effectCrit);
+ EnterCriticalSection(&effectCrit);
- if (effect == nullptr) {
- if (FAILED(ffdevice->CreateEffect(GUID_Sine, &dieff, &effect, nullptr))) {
- text(L"Failed to create periodic effect during reacquire");
- LeaveCriticalSection(&effectCrit);
- return;
- }
- }
+ if (effect == nullptr) {
+ if (FAILED(ffdevice->CreateEffect(GUID_Sine, &dieff, &effect, nullptr))) {
+ text(L"Failed to create periodic effect during reacquire");
+ LeaveCriticalSection(&effectCrit);
+ return;
+ }
+ }
- hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
- if (hr == DIERR_NOTINITIALIZED || hr == DIERR_INPUTLOST || hr == DIERR_INCOMPLETEEFFECT || hr == DIERR_INVALIDPARAM)
- text(L"Error setting parameters of DIEFFECT during reacquire: 0x%x", hr);
+ hr = effect->SetParameters(&dieff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
+ if (hr == DIERR_NOTINITIALIZED || hr == DIERR_INPUTLOST || hr == DIERR_INCOMPLETEEFFECT || hr == DIERR_INVALIDPARAM)
+ text(L"Error setting parameters of DIEFFECT during reacquire: 0x%x", hr);
- LeaveCriticalSection(&effectCrit);
+ LeaveCriticalSection(&effectCrit);
}
inline void sleepSpinUntil(PLARGE_INTEGER base, UINT sleep, UINT offset) {
- LARGE_INTEGER time;
- LONGLONG until = base->QuadPart + (offset * freq.QuadPart) / 1000000;
-
- std::this_thread::sleep_for(std::chrono::microseconds(sleep));
- do {
- _asm { pause };
- QueryPerformanceCounter(&time);
- } while (time.QuadPart < until);
+ if (!settings.getUseAltTimer()) {
+ nanosleep(offset);
+ }
+ else {
+ int i = 0;
+ LARGE_INTEGER time;
+ LONGLONG until = base->QuadPart + (offset * freq.QuadPart) / 1000000;
+
+ if (!sleepSpin || sleep > 1000)
+ std::this_thread::sleep_for(std::chrono::microseconds(sleep));
+
+ QueryPerformanceCounter(&time);
+ while (time.QuadPart < until) {
+ _mm_pause();
+ QueryPerformanceCounter(&time);
+ // i++;
+ }
+ }
+ //text(L"Paused for %d", i);
+}
+inline void nanosleep(LONGLONG ns) {
+ /* Declarations */
+ HANDLE timer; /* Timer handle */
+ LARGE_INTEGER li; /* Time defintion */
+ /* Create timer */
+
+ if (!(timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS))) {
+ return;
+ }
+
+ li.QuadPart = -ns;
+ if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) {
+ CloseHandle(timer);
+ return;
+ }
+ /* Start & wait for timer */
+ WaitForSingleObject(timer, INFINITE);
+ /* Clean resources */
+ CloseHandle(timer);
+ /* Slept without problems */
+ return;
}
+
inline int scaleTorque(float t) {
- return (int)(t * settings.getScaleFactor());
+ return (int)(t * settings.getScaleFactor());
}
inline void setFFB(int mag) {
- if (!effect)
- return;
-
- if (mag <= -IR_MAX) {
- mag = -IR_MAX;
- clippedSamples++;
- }
- else if (mag >= IR_MAX) {
- mag = IR_MAX;
- clippedSamples++;
- }
-
- samples++;
- int minForce = settings.getMinForce();
-
- if (stopped && settings.getReduceWhenParked())
- mag /= 4;
- else if (minForce) {
- if (mag > 0 && mag < minForce)
- mag = minForce;
- else if (mag < 0 && mag > -minForce)
- mag = -minForce;
- }
-
- ffbMag = mag;
-
+ if (!effect)
+ return;
+
+ int clippedAmmount = 0;
+
+ if (mag <= -IR_MAX)
+ {
+ clippedAmmount = mag - -IR_MAX;
+ mag = -IR_MAX;
+ clippedSamples++;
+ }
+ else if (mag >= IR_MAX) {
+ clippedAmmount = mag - IR_MAX;
+ mag = IR_MAX;
+ clippedSamples++;
+ }
+
+ samples++;
+ int minForce = settings.getMinForce();
+
+ if (stopped && settings.getReduceWhenParked())
+ mag /= 4;
+ else if (minForce) {
+ if (mag > 0 && mag < minForce)
+ mag = minForce;
+ else if (mag < 0 && mag > -minForce)
+ mag = -minForce;
+ }
+
+ ffbMag = mag;
+
+ ::SendMessage(currentForceWnd, PBM_SETPOS, (WPARAM)(INT)abs(mag), 0);
+ if (clippedAmmount > progressClippingMax)
+ {
+ progressClippingMax = clippedAmmount;
+ ::SendMessage(clippingForceWnd, PBM_SETRANGE32, 0, (WPARAM)(INT)progressClippingMax);
+ ::SendMessage(clippingForceOverlayWnd, PBM_SETRANGE32, 0, (WPARAM)(INT)progressClippingMax);
+ }
+
+ ::SendMessage(clippingForceWnd, PBM_SETPOS, (WPARAM)(INT)abs(clippedAmmount), 0);
+
+ if (settings.getShowForceOverlay())
+ {
+ ::SendMessage(currentForceOverlayWnd, PBM_SETPOS, (WPARAM)(INT)abs(mag), 0);
+ ::SendMessage(clippingForceOverlayWnd, PBM_SETPOS, (WPARAM)(INT)abs(clippedAmmount), 0);
+ }
}
bool initVJD() {
- WORD verDrv;
- int maxVjDev;
- VjdStat vjdStatus = VJD_STAT_UNKN;
-
- if (!vJoyEnabled()) {
- text(L"vJoy not enabled!");
- return false;
- }
- else
- text(L"vJoy driver version %04x init OK", &verDrv);
-
- vjDev = 1;
-
- if (!GetvJoyMaxDevices(&maxVjDev)) {
- text(L"Failed to determine max number of vJoy devices");
- return false;
- }
-
- while (vjDev <= maxVjDev) {
-
- vjdStatus = GetVJDStatus(vjDev);
-
- if (vjdStatus == VJD_STAT_BUSY || vjdStatus == VJD_STAT_MISS)
- goto NEXT;
- if (!GetVJDAxisExist(vjDev, HID_USAGE_X))
- goto NEXT;
- if (!IsDeviceFfb(vjDev))
- goto NEXT;
- if (
- !IsDeviceFfbEffect(vjDev, HID_USAGE_CONST) ||
- !IsDeviceFfbEffect(vjDev, HID_USAGE_SINE) ||
- !IsDeviceFfbEffect(vjDev, HID_USAGE_DMPR) ||
- !IsDeviceFfbEffect(vjDev, HID_USAGE_FRIC) ||
- !IsDeviceFfbEffect(vjDev, HID_USAGE_SPRNG)
- ) {
- text(L"vjDev %d: Not all required FFB effects are enabled", vjDev);
- text(L"Enable all FFB effects to use this device");
- goto NEXT;
- }
- break;
-
-NEXT:
- vjDev++;
-
- }
-
- if (vjDev > maxVjDev) {
- text(L"Failed to find suitable vJoy device!");
- text(L"Create a device with an X axis and all FFB effects enabled");
- return false;
- }
-
- memset(&ffbPacket, 0 ,sizeof(ffbPacket));
-
- if (vjdStatus == VJD_STAT_OWN) {
- RelinquishVJD(vjDev);
- vjdStatus = GetVJDStatus(vjDev);
- }
- if (vjdStatus == VJD_STAT_FREE) {
- if (!AcquireVJD(vjDev, ffbEvent, &ffbPacket)) {
- text(L"Failed to acquire vJoy device %d!", vjDev);
- return false;
- }
- }
- else {
- text(L"ERROR: vJoy device %d status is %d", vjDev, vjdStatus);
- return false;
- }
-
- vjButtons = GetVJDButtonNumber(vjDev);
- vjPov = GetVJDContPovNumber(vjDev);
- vjPov += GetVJDDiscPovNumber(vjDev);
-
- text(L"Acquired vJoy device %d", vjDev);
- ResetVJD(vjDev);
-
- return true;
+ SHORT verDrv;
+ int maxVjDev;
+ VjdStat vjdStatus = VJD_STAT_UNKN;
+
+ if (!vJoyEnabled()) {
+ text(L"vJoy not enabled!");
+ return false;
+ }
+ else {
+ verDrv = GetvJoyVersion();
+ text(L"vJoy driver version %04x init OK", verDrv);
+ }
+
+
+ vjDev = 1;
+
+ if (!GetvJoyMaxDevices(&maxVjDev)) {
+ text(L"Failed to determine max number of vJoy devices");
+ return false;
+ }
+
+ while (vjDev <= maxVjDev) {
+
+ vjdStatus = GetVJDStatus(vjDev);
+
+ if (vjdStatus == VJD_STAT_BUSY || vjdStatus == VJD_STAT_MISS)
+ goto NEXT;
+ if (!GetVJDAxisExist(vjDev, HID_USAGE_X))
+ goto NEXT;
+ if (!IsDeviceFfb(vjDev))
+ goto NEXT;
+ if (
+ !IsDeviceFfbEffect(vjDev, HID_USAGE_CONST) ||
+ !IsDeviceFfbEffect(vjDev, HID_USAGE_SINE) ||
+ !IsDeviceFfbEffect(vjDev, HID_USAGE_DMPR) ||
+ !IsDeviceFfbEffect(vjDev, HID_USAGE_FRIC) ||
+ !IsDeviceFfbEffect(vjDev, HID_USAGE_SPRNG)
+ ) {
+ text(L"vjDev %d: Not all required FFB effects are enabled", vjDev);
+ text(L"Enable all FFB effects to use this device");
+ goto NEXT;
+ }
+ break;
+
+ NEXT:
+ vjDev++;
+
+ }
+
+ if (vjDev > maxVjDev) {
+ text(L"Failed to find suitable vJoy device!");
+ text(L"Create a device with an X axis and all FFB effects enabled");
+ return false;
+ }
+
+ memset(&ffbPacket, 0, sizeof(ffbPacket));
+
+ if (vjdStatus == VJD_STAT_OWN) {
+ RelinquishVJD(vjDev);
+ vjdStatus = GetVJDStatus(vjDev);
+ }
+ if (vjdStatus == VJD_STAT_FREE) {
+ if (!AcquireVJD(vjDev, ffbEvent, &ffbPacket)) {
+ text(L"Failed to acquire vJoy device %d!", vjDev);
+ return false;
+ }
+ }
+ else {
+ text(L"ERROR: vJoy device %d status is %d", vjDev, vjdStatus);
+ return false;
+ }
+
+ vjButtons = GetVJDButtonNumber(vjDev);
+ vjPov = GetVJDContPovNumber(vjDev);
+ vjPov += GetVJDDiscPovNumber(vjDev);
+
+ text(L"Acquired vJoy device %d", vjDev);
+ ResetVJD(vjDev);
+
+ return true;
}
void initAll() {
- initVJD();
- initDirectInput();
+ initVJD();
+ initDirectInput();
}
void releaseAll() {
- releaseDirectInput();
-
- if (fan)
- fan->setSpeed(0);
+ releaseDirectInput();
- RelinquishVJD(vjDev);
+ RelinquishVJD(vjDev);
- irsdk_shutdown();
+ irsdk_shutdown();
}
diff --git a/irFFB/irFFB.h b/irFFB/irFFB.h
index 24fb883..d01d1d5 100644
--- a/irFFB/irFFB.h
+++ b/irFFB/irFFB.h
@@ -21,14 +21,14 @@ along with this program. If not, see .
#include "stdafx.h"
#include "irsdk_defines.h"
-#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken = '6595b64144ccf1df' language = '*'\"")
+
#define MAX_FFB_DEVICES 16
#define DI_MAX 10000
#define IR_MAX 9996
#define MINFORCE_MULTIPLIER 100
#define MIN_MAXFORCE 5
-#define MAX_MAXFORCE 300
+#define MAX_MAXFORCE 100
#define BUMPSFORCE_MULTIPLIER 1.6f
#define LOADFORCE_MULTIPLIER 0.08f
#define LONGLOAD_STDPOWER 4
@@ -41,9 +41,9 @@ along with this program. If not, see .
#define DIRECT_INTERP_SAMPLES 6
#define SETTINGS_KEY L"Software\\irFFB\\Settings"
#define RUN_ON_STARTUP_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"
-#define INI_PATH L"\\irFFB.ini"
-#define INI_SCAN_FORMAT "%[^:]:%d:%d:%d:%f:%f:%d:%d:%f:%f:%f:%f"
-#define INI_PRINT_FORMAT "%s:%d:%d:%d:%0.1f:%0.1f:%d:%d:%0.1f:%0.1f:%0.1f:%0.1f\r"
+#define INI_PATH L"irFFB.ini"
+#define INI_SCAN_FORMAT "%[^:]:%d:%d:%d:%f:%f:%d:%d:%f:%f:%f:%f:%f:%f"
+#define INI_PRINT_FORMAT "%s:%d:%d:%d:%0.1f:%0.1f:%d:%d:%0.1f:%0.1f:%0.1f:%0.1f:%0.1f:%0.1f\r"
#define MAX_CAR_NAME 32
#define MAX_LATENCY_TIMES 32
#define LATENCY_MIN_DX 60
@@ -53,6 +53,8 @@ along with this program. If not, see .
#define EDIT_INT 0
#define EDIT_FLOAT 1
#define ID_TRAY_EXIT 40000
+#define ID_MAXFORCE_UP 1
+#define ID_MAXFORCE_DOWN 2
#define SVCNAME L"irFFBsvc"
#define CMDLINE_HGSVC L"service"
@@ -70,6 +72,17 @@ along with this program. If not, see .
#define LOGI_WHEEL_HID_CMD "\x00\xf8\x81\x84\x03\x00\x00\x00\x00"
#define LOGI_WHEEL_HID_CMD_LEN 9
+#define OVERLAY_WINDOW_HEIGHT 41
+
+extern "C" NTSYSAPI NTSTATUS NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
+
+extern "C" NTSYSAPI NTSTATUS NTAPI NtQueryTimerResolution(PULONG MininumResolution, PULONG MaximumResolution, PULONG CurrentResolution);
+
+typedef LONG NTSTATUS, * PNTSTATUS;
+#define STATUS_SUCCESS (0x00000000)
+
+typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
+
enum ffbType {
FFBTYPE_360HZ,
FFBTYPE_360HZ_INTERP,
@@ -82,6 +95,8 @@ typedef struct sWins {
HWND trackbar;
HWND label;
HWND value;
+ float min;
+ float max;
} sWins_t;
struct LogiRpmData {
@@ -102,17 +117,30 @@ struct understeerCoefs {
float latAccelDiv;
};
+RTL_OSVERSIONINFOW GetRealOSVersion();
+
DWORD WINAPI readWheelThread(LPVOID);
DWORD WINAPI directFFBThread(LPVOID);
ATOM MyRegisterClass(HINSTANCE);
+
BOOL InitInstance(HINSTANCE, int);
+LRESULT CALLBACK myNcHitTest(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
+LRESULT CALLBACK myPaint(HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK WndProcOverlay(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
HWND combo(HWND, wchar_t *, int, int);
sWins_t *slider(HWND, wchar_t *, int, int, wchar_t *, wchar_t *, bool);
-HWND checkbox(HWND, wchar_t *, int, int);
+HWND slider(HWND, wchar_t*, int, int, int, int, int, int);
+HWND checkbox(HWND, wchar_t *, int, int, int, int);
+HWND groupox(HWND, wchar_t*, int, int, int, int);
+HWND progressbar(HWND, wchar_t*, int, int, int, int, int);
+
+void ActivateOverLayWindow();
+void DeActivateOverlayWindow();
+void CreateOverlayWindow(HINSTANCE);
bool initVJD();
void text(wchar_t *, ...);
@@ -127,6 +155,7 @@ void initDirectInput();
void releaseDirectInput();
void reacquireDIDevice();
inline void sleepSpinUntil(PLARGE_INTEGER, UINT, UINT);
+inline void nanosleep(LONGLONG);
inline int scaleTorque(float);
inline void setFFB(int);
void initAll();
diff --git a/irFFB/irFFB.rc b/irFFB/irFFB.rc
index 6a4e128..46a6d03 100644
Binary files a/irFFB/irFFB.rc and b/irFFB/irFFB.rc differ
diff --git a/irFFB/irFFB.vcxproj b/irFFB/irFFB.vcxproj
index 58e9451..afa1fa9 100644
--- a/irFFB/irFFB.vcxproj
+++ b/irFFB/irFFB.vcxproj
@@ -34,9 +34,9 @@
Application
false
- v142
true
Unicode
+ v142
Application
@@ -75,6 +75,7 @@
true
+ $(ProjectName)64
true
@@ -83,6 +84,7 @@
false
+ $(ProjectName)64
@@ -92,11 +94,13 @@
Disabled
WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
All
+ stdcpp17
+ stdc17
Windows
true
- dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;%(AdditionalDependencies)
+ dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;ntdll.lib;Version.lib;dwmapi.lib;%(AdditionalDependencies)
@@ -106,10 +110,13 @@
Level3
Disabled
_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ stdcpp17
+ stdc17
Windows
true
+ dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;ntdll.lib;dwmapi.lib;%(AdditionalDependencies)
@@ -128,13 +135,16 @@
All
StreamingSIMDExtensions2
None
+ stdcpp17
+ /Zc:strictStrings- %(AdditionalOptions)
+ stdc17
Windows
No
true
true
- dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;%(AdditionalDependencies)
+ dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;ntdll.lib;dwmapi.lib;%(AdditionalDependencies)
NoErrorReport
UseLinkTimeCodeGeneration
true
@@ -149,30 +159,26 @@
true
true
NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
+ stdcpp17
+ stdc17
Windows
true
true
true
+ dxguid.lib;dinput8.lib;shlwapi.lib;wbemuuid.lib;comctl32.lib;winhttp.lib;ntdll.lib;dwmapi.lib;%(AdditionalDependencies)
-
-
-
-
-
-
-
@@ -190,12 +196,6 @@
-
-
- Document
-
-
-
diff --git a/irFFB/irFFB.vcxproj.filters b/irFFB/irFFB.vcxproj.filters
index f91a12c..eb42c73 100644
--- a/irFFB/irFFB.vcxproj.filters
+++ b/irFFB/irFFB.vcxproj.filters
@@ -30,18 +30,9 @@
Source Files
-
- Source Files
-
-
- Source Files
-
Source Files
-
- Source Files
-
@@ -68,21 +59,9 @@
Header Files
-
- Header Files
-
-
- Header Files
-
-
- Header Files
-
Header Files
-
- Header Files
-
@@ -97,10 +76,4 @@
Resource Files
-
-
- Resource Files
-
-
-
\ No newline at end of file
diff --git a/irFFB/irsdk_utils.cpp b/irFFB/irsdk_utils.cpp
index 819e31f..ca071c8 100644
--- a/irFFB/irsdk_utils.cpp
+++ b/irFFB/irsdk_utils.cpp
@@ -322,7 +322,7 @@ unsigned int irsdk_getBroadcastMsgID()
void irsdk_broadcastMsg(irsdk_BroadcastMsg msg, int var1, int var2, int var3)
{
- irsdk_broadcastMsg(msg, var1, MAKELONG(var2, var3));
+ irsdk_broadcastMsg(msg, var1, (int)MAKELONG(var2, var3));
}
void irsdk_broadcastMsg(irsdk_BroadcastMsg msg, int var1, float var2)
diff --git a/irFFB/jetseat.cpp b/irFFB/jetseat.cpp
deleted file mode 100644
index 91e49ff..0000000
--- a/irFFB/jetseat.cpp
+++ /dev/null
@@ -1,600 +0,0 @@
-#include "jetseat.h"
-
-JetSeat *JetSeat::instance = nullptr;
-
-JetSeat *JetSeat::init() {
-
- JetSeat *js = new JetSeat();
- if (js->initialise())
- return js;
-
- return nullptr;
-
-}
-
-JetSeat::JetSeat() {
- instance = this;
-}
-
-JetSeat::~JetSeat() {
-
- UINT status;
-
- if (FAILED(jetseat->uwGetStatus(&status)))
- return;
-
- if (status == UW_STATUS_IN_USE)
- jetseat->uwClose();
-
-}
-
-bool JetSeat::initialise() {
-
- readSettings();
-
- if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED)))
- return false;
-
- CoInitializeSecurity(
- NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
- );
-
- HRESULT hr = CoCreateInstance(CLSID_Uberwoorf, NULL, CLSCTX_ALL, IID_IUberwoorf, (void **)&jetseat);
- if (FAILED(hr))
- return false;
-
- if (enabled)
- return open();
-
- return true;
-
-}
-
-bool JetSeat::open() {
-
- UINT uwOpenStatus;
- if (FAILED(jetseat->uwOpen(&uwOpenStatus))) {
- text(L"JetSeat found but open failed");
- return false;
- }
-
- jetseat->uwReset();
- text(L"JetSeat init OK");
- return initEffects();
-
-}
-
-bool JetSeat::initEffects() {
-
- effect_handles[GW_LEG_LEFT] = createEffect(UW_SIT_LEFT);
- effect_handles[GW_LEG_RIGHT] = createEffect(UW_SIT_RIGHT);
- effect_handles[GW_LEG_BOTH] = createEffect(UW_SIT);
- effect_handles[GW_SLIDE_LEFT] = createSlideEffect(UW_SIT_LEFT);
- effect_handles[GW_SLIDE_RIGHT] = createSlideEffect(UW_SIT_RIGHT);
- effect_handles[GW_ALL_LEFT] = createEffect(UW_LEFT);
- effect_handles[GW_ALL_RIGHT] = createEffect(UW_RIGHT);
- effect_handles[GW_ALL_BOTH] = createEffect(UW_ALL_ZONES);
- effect_handles[GW_BACK_LEFT] = createEffect(UW_BACK_LOW_LEFT);
- effect_handles[GW_BACK_RIGHT] = createEffect(UW_BACK_LOW_RIGHT);
- effect_handles[GW_BACK_BOTH] = createEffect(UW_BACK_LOW);
-
- for (int i = GW_LEG_LEFT; i <= GW_BACK_BOTH; i++)
- if (effect_handles[i] < 0) {
- text(L"Create effect %d failed\n", i);
- return false;
- }
-
- createEngineEffect();
-
- text(L"JetSeat effects initialised");
- startEffect(GW_BACK_BOTH, 100, 1);
-
- return true;
-
-}
-
-ATOM JetSeat::registerClass(HINSTANCE hInstance) {
-
- WNDCLASSEXW wcex;
-
- wcex.cbSize = sizeof(WNDCLASSEX);
-
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = wndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = 0;
- wcex.lpszClassName = windowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
-
- return RegisterClassExW(&wcex);
-
-}
-
-void JetSeat::effectControls(
- wchar_t *effect, int x, int y, HWND *placeWnd, sWins_t *gainWnd, HINSTANCE hInst
-) {
-
- wchar_t gain[64];
- swprintf_s(gain, L"%s gain:", effect);
-
- if (placeWnd != nullptr) {
-
- wchar_t eff[64];
- swprintf_s(eff, L"%s effect location:", effect);
-
- CreateWindowW(
- L"STATIC", eff,
- WS_CHILD | WS_VISIBLE,
- x, y, 200, 20, mainWnd, NULL, hInst, NULL
- );
-
- *placeWnd = CreateWindow(
- L"COMBOBOX", nullptr,
- CBS_DROPDOWN | WS_CHILD | WS_VISIBLE | WS_TABSTOP,
- x, y + 40, 200, 100, mainWnd, nullptr, hInst, nullptr
- );
-
- for (int i = 0; i <= ALL; i++)
- SendMessage(*placeWnd, CB_ADDSTRING, 0, LPARAM(effectPlaces[i]));
-
- }
-
- gainWnd->value = CreateWindowW(
- L"STATIC", gain,
- WS_CHILD | WS_VISIBLE,
- x + 256, y, 200, 20, mainWnd, NULL, hInst, NULL
- );
-
- gainWnd->trackbar = CreateWindowEx(
- 0, TRACKBAR_CLASS, gain,
- WS_CHILD | WS_VISIBLE | TBS_AUTOTICKS | TBS_TOOLTIPS | TBS_TRANSPARENTBKGND,
- x + 256, y + 40, 320, 30,
- mainWnd, NULL, hInst, NULL
- );
-
- HWND buddyLeft = CreateWindowEx(
- 0, L"STATIC", L"0",
- SS_LEFT | WS_CHILD | WS_VISIBLE,
- 0, 0, 20, 20, mainWnd, NULL, hInst, NULL
- );
-
- SendMessage(gainWnd->trackbar, TBM_SETBUDDY, (WPARAM)TRUE, (LPARAM)buddyLeft);
-
- HWND buddyRight = CreateWindowEx(
- 0, L"STATIC", L"100",
- SS_RIGHT | WS_CHILD | WS_VISIBLE,
- 0, 0, 30, 20, mainWnd, NULL, hInst, NULL
- );
-
- SendMessage(gainWnd->trackbar, TBM_SETBUDDY, (WPARAM)FALSE, (LPARAM)buddyRight);
-
-}
-
-void JetSeat::createWindow(HINSTANCE hInst) {
-
- if (!classIsRegistered) {
- registerClass(hInst);
- classIsRegistered = true;
- }
-
- mainWnd = CreateWindowW(
- windowClass, windowClass, WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
- CW_USEDEFAULT, CW_USEDEFAULT, 712, 480,
- NULL, NULL, hInst, NULL
- );
-
- if (!mainWnd)
- return;
-
- enableWnd = CreateWindowEx(
- 0, L"BUTTON", L"Enable irFFB control",
- BS_CHECKBOX | BS_MULTILINE | WS_CHILD | WS_VISIBLE,
- 40, 260, 180, 58, mainWnd, nullptr, hInst, nullptr
- );
- effectControls(L"Engine", 40, 30, &enginePlaceWnd, &engineGainWnd, hInst);
- effectControls(L"Gear shift", 40, 130, &gearPlaceWnd, &gearGainWnd, hInst);
- effectControls(L"Bumps", 40, 230, nullptr, &bumpsGainWnd, hInst);
- effectControls(L"Slide", 40, 330, nullptr, &yawGainWnd, hInst);
-
- readSettings();
-
- ShowWindow(mainWnd, SW_SHOWNORMAL);
- UpdateWindow(mainWnd);
-
- return;
-
-}
-
-LRESULT CALLBACK JetSeat::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-
- switch (message) {
-
- case WM_COMMAND: {
- int wmId = LOWORD(wParam);
- switch (wmId) {
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
- default:
- if (HIWORD(wParam) == CBN_SELCHANGE) {
- if ((HWND)lParam == instance->gearPlaceWnd)
- instance->setGearPlace(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
- else if ((HWND)lParam == instance->enginePlaceWnd) {
- instance->setEnginePlace(SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0));
- }
- }
- else if (HIWORD(wParam) == BN_CLICKED) {
- bool oldValue = SendMessage((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED;
- if ((HWND)lParam == instance->enableWnd)
- instance->setEnabled(!oldValue);
- }
- break;
- }
- }
- break;
-
- case WM_HSCROLL: {
- if ((HWND)lParam == instance->gearGainWnd.trackbar)
- instance->gearGain = (float)(SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
- else if ((HWND)lParam == instance->bumpsGainWnd.trackbar)
- instance->bumpsGain = (float)(SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
- else if ((HWND)lParam == instance->engineGainWnd.trackbar)
- instance->engineGain = (float)(SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
- else if ((HWND)lParam == instance->yawGainWnd.trackbar)
- instance->yawGain = (float)(SendMessage((HWND)lParam, TBM_GETPOS, 0, 0));
- }
- break;
-
- case WM_CTLCOLORSTATIC: {
- SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
- return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
- }
- break;
-
- case WM_PAINT: {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- EndPaint(hWnd, &ps);
- }
- break;
-
- case WM_DESTROY: {
- instance->writeSettings();
- }
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
-
- }
-
- return 0;
-
-}
-
-void JetSeat::setGearPlace(int loc) {
- SendMessage(gearPlaceWnd, CB_SETCURSEL, loc, 0);
- gearPlace = effectLocation(loc);
-}
-int JetSeat::getGearPlace() {
- return effectSetting(gearPlace);
-}
-
-void JetSeat::setEnginePlace(int loc) {
- SendMessage(enginePlaceWnd, CB_SETCURSEL, loc, 0);
- enginePlace = effectLocation(loc);
- switch (enginePlace) {
- case GW_LEG_BOTH: {
- engineLeft = UW_SIT_LEFT;
- engineRight = UW_SIT_RIGHT;
- }
- break;
- case GW_BACK_BOTH: {
- engineLeft = UW_BACK_LOW_LEFT;
- engineRight = UW_BACK_LOW_RIGHT;
- }
- break;
- case GW_ALL_BOTH: {
- engineLeft = UW_LEFT;
- engineRight = UW_RIGHT;
- }
- break;
- }
- if (engineOn)
- stopEngineEffect();
-}
-int JetSeat::getEnginePlace() {
- return effectSetting(enginePlace);
-}
-
-void JetSeat::setGearGain(float gain) {
- gearGain = gain;
- SendMessage(gearGainWnd.trackbar, TBM_SETPOS, TRUE, (int)gain);
- SendMessage(gearGainWnd.trackbar, TBM_SETPOSNOTIFY, 0, (int)gain);
- swprintf_s(strbuf, L"Gear shift gain [ %d ]", (int)gain);
- SendMessage(gearGainWnd.value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-void JetSeat::setEngineGain(float gain) {
- engineGain = gain;
- SendMessage(engineGainWnd.trackbar, TBM_SETPOS, TRUE, (int)gain);
- SendMessage(engineGainWnd.trackbar, TBM_SETPOSNOTIFY, 0, (int)gain);
- swprintf_s(strbuf, L"Engine gain [ %d ]", (int)gain);
- SendMessage(engineGainWnd.value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-void JetSeat::setBumpsGain(float gain) {
- bumpsGain = gain;
- SendMessage(bumpsGainWnd.trackbar, TBM_SETPOS, TRUE, (int)gain);
- SendMessage(bumpsGainWnd.trackbar, TBM_SETPOSNOTIFY, 0, (int)gain);
- swprintf_s(strbuf, L"Bumps gain [ %d ]", (int)gain);
- SendMessage(bumpsGainWnd.value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-void JetSeat::setYawGain(float gain) {
- yawGain = gain;
- SendMessage(yawGainWnd.trackbar, TBM_SETPOS, TRUE, (int)gain);
- SendMessage(yawGainWnd.trackbar, TBM_SETPOSNOTIFY, 0, (int)gain);
- swprintf_s(strbuf, L"Slide gain [ %d ]", (int)gain);
- SendMessage(yawGainWnd.value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-
-void JetSeat::setEnabled(bool en) {
-
- UINT status;
-
- enabled = en;
- SendMessage(enableWnd, BM_SETCHECK, en ? BST_CHECKED : BST_UNCHECKED, NULL);
- EnableWindow(gearPlaceWnd, en);
- EnableWindow(gearGainWnd.trackbar, en);
- EnableWindow(gearGainWnd.value, en);
- EnableWindow(enginePlaceWnd, en);
- EnableWindow(engineGainWnd.trackbar, en);
- EnableWindow(engineGainWnd.value, en);
- EnableWindow(bumpsGainWnd.trackbar, en);
- EnableWindow(bumpsGainWnd.value, en);
- EnableWindow(yawGainWnd.trackbar, en);
- EnableWindow(yawGainWnd.value, en);
-
- if (!jetseat)
- return;
-
- if (FAILED(jetseat->uwGetStatus(&status))) {
- text(L"Failed to get JetSeat status");
- enabled = false;
- return;
- }
-
- if (!en && status == UW_STATUS_IN_USE) {
- jetseat->uwClose();
- text(L"JetSeat closed");
- return;
- }
-
- else if (en && status == UW_STATUS_READY) {
- if (open())
- return;
- else
- enabled = false;
- }
-
-}
-
-bool JetSeat::isEnabled() {
- return enabled;
-}
-
-int JetSeat::effectLocation(int idx) {
-
- switch (idx) {
- case LEGS: return GW_LEG_BOTH;
- case BACK: return GW_BACK_BOTH;
- case ALL: return GW_ALL_BOTH;
- }
-
- return GW_ALL_BOTH;
-
-}
-
-int JetSeat::effectSetting(int loc) {
-
- switch (loc) {
- case GW_LEG_BOTH: return LEGS;
- case GW_BACK_BOTH: return BACK;
- case GW_ALL_BOTH: return ALL;
- }
-
- return ALL;
-
-}
-
-int JetSeat::createEffect(UINT zones) {
-
- UINT handle, vib;
- UINT dur[2] = { 0, 100 };
- BYTE amp[2] = { 255, 255 };
-
- jetseat->uwCreateEffect(&handle);
- jetseat->uwSetVibration(handle, zones, dur, amp, 2, &vib);
-
- return handle;
-
-}
-
-int JetSeat::createSlideEffect(UINT zones) {
-
- UINT handle, vib;
- UINT dur[6] = { 0, 50, 50, 75, 75, 125 };
- BYTE amp[6] = { 255, 255, 0, 0, 255, 255 };
-
- jetseat->uwCreateEffect(&handle);
- jetseat->uwSetVibration(handle, zones, dur, amp, 6, &vib);
-
- return handle;
-
-}
-
-void JetSeat::createEngineEffect() {
-
- UINT dur[2] = { 150, 150 };
- BYTE amp[2] = { 0, 0 };
-
- jetseat->uwCreateEffect(&engineEffect);
- jetseat->uwSetVibration(engineEffect, engineLeft, dur, amp, 2, &engineVibL1);
- jetseat->uwSetVibration(engineEffect, engineRight, dur, amp, 2, &engineVibL2);
- jetseat->uwSetVibration(engineEffect, engineLeft, dur, amp, 2, &engineVibR1);
- jetseat->uwSetVibration(engineEffect, engineRight, dur, amp, 2, &engineVibR2);
-
-}
-
-void JetSeat::startEffect(int effect, float gain, int count) {
-
- gain = minf(gain, 100);
- jetseat->uwSetEffectGain(effect_handles[effect], (UINT)gain);
- jetseat->uwStartEffect(effect_handles[effect], count);
-
-}
-
-void JetSeat::stopEffect(int effect) {
-
- jetseat->uwStopEffect(effect_handles[effect]);
-
-}
-
-void JetSeat::startEngineEffect() {
-
- if (engineGain == 0.0f || engineOn)
- return;
- jetseat->uwStartEffect(engineEffect, INFINITE);
- engineOn = true;
- engineCounter = 0;
-
-}
-
-void JetSeat::stopEngineEffect() {
-
- if (!jetseat || !engineOn)
- return;
- jetseat->uwStopEffect(engineEffect);
- engineOn = false;
-
-}
-
-void JetSeat::updateEngineEffect(float rpmPerCent) {
-
- if (engineGain == 0 || !engineOn || engineCounter++ < 10)
- return;
-
- UINT intervalsOn[2];
- UINT intervalsOff[2];
- BYTE amps[2] = { 0, 0 };
- BYTE ampsZero[2] = { 0, 0 };
-
- engineCounter = 0;
-
- UINT on = (UINT)(rpmPerCent * 3.0f);
-
- if (on < 60)
- on = 60;
-
- int amp = (int)(engineGain * 2.55f);
-
- int space = 150 - on;
- UINT delay = space > 0 ? space >> 1 : 0;
-
- amps[0] = amps[1] = amp > 255 ? 255 : amp;
-
- intervalsOff[0] = 0;
- intervalsOn[0] = delay;
- intervalsOn[1] = delay + on;
- intervalsOff[1] = 300 - on - delay;
-
- jetseat->uwUpdateVibration(engineEffect, engineVibL1, engineLeft, intervalsOn, amps, 2);
- jetseat->uwUpdateVibration(engineEffect, engineVibR1, engineRight, intervalsOff, ampsZero, 2);
-
- intervalsOff[0] = delay + on;
- intervalsOn[0] = 300 - on - delay;
- intervalsOff[1] = 300;
- intervalsOn[1] = 300 - delay;
- jetseat->uwUpdateVibration(engineEffect, engineVibL2, engineLeft, intervalsOff, ampsZero, 2);
- jetseat->uwUpdateVibration(engineEffect, engineVibR2, engineRight, intervalsOn, amps, 2);
-
-}
-
-void JetSeat::gearEffect() {
- if (gearGain > 0.0f)
- startEffect(gearPlace, gearGain, 1);
-}
-
-void JetSeat::fBumpEffect(float l, float r) {
- if (bumpsGain == 0.0f)
- return;
- startEffect(GW_LEG_LEFT, l * bumpsGain, 1);
- startEffect(GW_LEG_RIGHT, r * bumpsGain, 1);
-}
-
-void JetSeat::rBumpEffect(float l, float r) {
- if (bumpsGain == 0.0f)
- return;
- startEffect(GW_BACK_RIGHT, l * bumpsGain, 1);
- startEffect(GW_BACK_RIGHT, r * bumpsGain, 1);
-}
-
-void JetSeat::yawEffect(float f) {
- if (yawGain == 0.0f)
- return;
- if (f > 0.0f)
- startEffect(GW_SLIDE_LEFT, f * 5.0f * yawGain, 3);
- else
- startEffect(GW_SLIDE_RIGHT, -f * 5.0f * yawGain, 3);
-}
-
-void JetSeat::readSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
-
- if (key == NULL) {
- setGearPlace(BACK);
- setEnginePlace(ALL);
- setGearGain(80);
- setEngineGain(0);
- setBumpsGain(80);
- setYawGain(80);
- setEnabled(true);
- return;
- }
-
- setGearPlace(Settings::getRegSetting(key, L"jsGearPlace", BACK));
- setEnginePlace(Settings::getRegSetting(key, L"jsEnginePlace", ALL));
- setGearGain(Settings::getRegSetting(key, L"jsGearGain", 80.0f));
- setEngineGain(Settings::getRegSetting(key, L"jsEngineGain", 0.0f));
- setBumpsGain(Settings::getRegSetting(key, L"jsBumpsGain", 80.0f));
- setYawGain(Settings::getRegSetting(key, L"jsYawGain", 80.0f));
- setEnabled(Settings::getRegSetting(key, L"jsEnabled", true));
-
- RegCloseKey(key);
-
-}
-
-void JetSeat::writeSettings() {
-
- HKEY key = Settings::getSettingsRegKey();
-
- if (key == NULL)
- return;
-
- Settings::setRegSetting(key, L"jsGearPlace", gearPlace);
- Settings::setRegSetting(key, L"jsEnginePlace", enginePlace);
- Settings::setRegSetting(key, L"jsGearGain", gearGain);
- Settings::setRegSetting(key, L"jsEngineGain", engineGain);
- Settings::setRegSetting(key, L"jsBumpsGain", bumpsGain);
- Settings::setRegSetting(key, L"jsYawGain", yawGain);
- Settings::setRegSetting(key, L"jsEnabled", enabled);
-
- RegCloseKey(key);
-
-}
-
diff --git a/irFFB/jetseat.h b/irFFB/jetseat.h
deleted file mode 100644
index 527cd40..0000000
--- a/irFFB/jetseat.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-#include
-#include
-#include
-#include
-
-#include "stdafx.h"
-#include "irFFB.h"
-#include "settings.h"
-#include "IUberwoorf.h"
-
-
-#define MAX_JETSEAT_EFFECTS 16
-#define GW_LEG_LEFT 1
-#define GW_LEG_RIGHT 2
-#define GW_LEG_BOTH 3
-#define GW_SLIDE_LEFT 4
-#define GW_SLIDE_RIGHT 5
-#define GW_ALL_LEFT 6
-#define GW_ALL_RIGHT 7
-#define GW_ALL_BOTH 8
-#define GW_BACK_LEFT 9
-#define GW_BACK_RIGHT 10
-#define GW_BACK_BOTH 11
-
-#define LEGS 0
-#define BACK 1
-#define ALL 2
-
-class JetSeat {
-
- public:
- static JetSeat *init();
- bool isEnabled();
- void createWindow(HINSTANCE);
- void startEngineEffect();
- void stopEngineEffect();
- void updateEngineEffect(float);
- void gearEffect();
- void fBumpEffect(float, float);
- void rBumpEffect(float, float);
- void yawEffect(float);
-
- private:
- JetSeat();
- ~JetSeat();
- bool initialise();
- bool open();
- bool initEffects();
- ATOM registerClass(HINSTANCE);
- void effectControls(wchar_t *, int, int, HWND *, sWins_t *, HINSTANCE);
- static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
- void setGearPlace(int);
- int getGearPlace();
- void setEnginePlace(int);
- int getEnginePlace();
- void setGearGain(float);
- void setEngineGain(float);
- void setBumpsGain(float);
- void setYawGain(float);
- void setEnabled(bool);
- int effectLocation(int);
- int effectSetting(int);
- int createEffect(UINT);
- int createSlideEffect(UINT);
- void createEngineEffect();
- void startEffect(int, float, int);
- void stopEffect(int);
- void readSettings();
- void writeSettings();
-
- static JetSeat *instance;
-
- wchar_t *windowClass = L"JetSeat Configuration";
-
- HWND mainWnd, gearPlaceWnd, enginePlaceWnd, enableWnd;
- sWins_t gearGainWnd, bumpsGainWnd, engineGainWnd, yawGainWnd;
-
- UINT effect_handles[MAX_JETSEAT_EFFECTS];
- wchar_t *effectPlaces[3] = { L"Legs", L"Back", L"All" };
- IUberwoorf *jetseat = nullptr;
- UINT engineEffect, engineVibL1, engineVibL2, engineVibR1, engineVibR2;
- UINT engineLeft = UW_BACK_LOW_LEFT, engineRight = UW_BACK_LOW_RIGHT;
- bool enabled = true, engineOn = false, classIsRegistered = false;
-
- int gearPlace, enginePlace, engineCounter = 0;
- float gearGain = 100, bumpsGain = 100, yawGain = 100, engineGain = 0;
- wchar_t strbuf[64];
-
-};
\ No newline at end of file
diff --git a/irFFB/resource.h b/irFFB/resource.h
index 3e62833..86b1fae 100644
--- a/irFFB/resource.h
+++ b/irFFB/resource.h
@@ -7,18 +7,19 @@
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
+#define IDS_APP_TITLE_64 104
#define IDM_EXIT 105
#define IDI_IRFFB 107
#define IDI_SMALL 108
#define IDC_IRFFB 109
#define IDR_MAINFRAME 128
+#define IDC_SYSLINK1 1001
#define IDR_HIDG64 8192
#define ID_SETTINGS_JETSEAT 32774
#define ID_SETTINGS_FAN 32775
#define ID_SETTINGS_HIDGUARDIAN 32778
#define ID_SETTINGS_TRACTIONLOSS 32779
#define IDC_STATIC -1
-#define IDC_SYSLINK1 1001
// Next default values for new objects
//
diff --git a/irFFB/settings.cpp b/irFFB/settings.cpp
index 122289e..03b2882 100644
--- a/irFFB/settings.cpp
+++ b/irFFB/settings.cpp
@@ -2,7 +2,9 @@
#include
#include
#include
-
+#include
+#include
+namespace fs = std::filesystem;
HKEY Settings::getSettingsRegKey() {
HKEY key;
@@ -96,7 +98,7 @@ void Settings::setMinWnd(sWins_t *wnd) {
void Settings::setMaxWnd(sWins_t *wnd) {
maxWnd = wnd;
- SendMessage(maxWnd->trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(MIN_MAXFORCE, 65));
+ SendMessage(maxWnd->trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(MIN_MAXFORCE, 100));
}
void Settings::setBumpsWnd(sWins_t *wnd) { bumpsWnd = wnd; }
@@ -105,12 +107,24 @@ void Settings::setSopWnd(sWins_t *wnd) { sopWnd = wnd; }
void Settings::setSopOffsetWnd(sWins_t *wnd) { sopOffsetWnd = wnd; }
void Settings::setUndersteerWnd(sWins_t *wnd) { understeerWnd = wnd; }
void Settings::setUndersteerOffsetWnd(sWins_t *wnd) { understeerOffsetWnd = wnd; }
+void Settings::setUndersteerYawRateMultWnd(sWins_t* wnd) { understeerYawRateMultWnd = wnd; }
+void Settings::setUndersteerlatAccelDivWnd(sWins_t* wnd) { understeerlatAccelDivWnd = wnd; }
+void Settings::setOverlayTransparencyWnd(sWins_t* wnd) { overlayTransparencyWnd = wnd;}
void Settings::setUse360Wnd(HWND wnd) { use360Wnd = wnd; }
void Settings::setReduceWhenParkedWnd(HWND wnd) { reduceWhenParkedWnd = wnd; }
void Settings::setCarSpecificWnd(HWND wnd) { carSpecificWnd = wnd; }
void Settings::setRunOnStartupWnd(HWND wnd) { runOnStartupWnd = wnd; }
void Settings::setStartMinimisedWnd(HWND wnd) { startMinimisedWnd = wnd; }
void Settings::setDebugWnd(HWND wnd) { debugWnd = wnd; }
+void Settings::setAltTimerWnd(HWND wnd) { altTimerWnd = wnd; }
+void Settings::setForceOverlayWnd(HWND wnd) { forceOverlayWnd = wnd; }
+
+void Settings::setOverlayMaxForceWnd(HWND wnd)
+{
+ overlayMaxForceWnd = wnd;
+ SendMessage(overlayMaxForceWnd, TBM_SETRANGE, TRUE, MAKELPARAM(MIN_MAXFORCE, 65));
+}
+
void Settings::clearFfbDevices() {
memset(ffdevices, 0, sizeof(ffdevices));
@@ -178,6 +192,7 @@ bool Settings::setMaxForce(int max, HWND wnd) {
swprintf_s(strbuf, L"%d", max);
SendMessage(maxWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
}
+ SendMessage(getOverlayMaxForceWnd(), TBM_SETPOS, TRUE, maxForce);
scaleFactor = (float)DI_MAX / maxForce;
irsdk_broadcastMsg(
irsdk_BroadcastFFBCommand, irsdk_FFBCommand_MaxForce, (float)maxForce
@@ -264,6 +279,63 @@ bool Settings::setUndersteerOffset(float offset, HWND wnd) {
return true;
}
+bool Settings::setUndersteerYawRateMult(float mul, HWND wnd)
+{
+ if (mul < understeerYawRateMultWnd->min || mul > understeerYawRateMultWnd->max)
+ return false;
+
+ understeerYawRateMult = mul;
+ if (wnd != understeerYawRateMultWnd->trackbar)
+ SendMessage(understeerYawRateMultWnd->trackbar, TBM_SETPOS, TRUE, (int)mul);
+ if (wnd != understeerYawRateMultWnd->value) {
+ swprintf_s(strbuf, L"%.1f", mul);
+ SendMessage(understeerYawRateMultWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
+ }
+ return true;
+}
+
+bool Settings::setUndersteerlatAccelDiv(float div, HWND wnd)
+{
+ if (div < understeerlatAccelDivWnd->min || div > understeerlatAccelDivWnd->max)
+ return false;
+ understeerlatAccelDiv = div;
+ if (wnd != understeerlatAccelDivWnd->trackbar)
+ SendMessage(understeerlatAccelDivWnd->trackbar, TBM_SETPOS, TRUE, (int)div);
+ if (wnd != understeerlatAccelDivWnd->value) {
+ swprintf_s(strbuf, L"%.1f", div);
+ SendMessage(understeerlatAccelDivWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
+ }
+ return true;
+}
+
+bool Settings::setOverlayTransparency(float transparency, HWND wnd)
+{
+ if (transparency < overlayTransparencyWnd->min || transparency > overlayTransparencyWnd->max)
+ return false;
+ overlayTransparency = transparency;
+ if (wnd != overlayTransparencyWnd->trackbar)
+ SendMessage(overlayTransparencyWnd->trackbar, TBM_SETPOS, TRUE, (int)transparency);
+ if (wnd != overlayTransparencyWnd->value) {
+ swprintf_s(strbuf, L"%.1f", transparency);
+ SendMessage(overlayTransparencyWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
+ }
+ return true;
+}
+
+void Settings::enableOverlayTransparencyWnd()
+{
+ EnableWindow(overlayTransparencyWnd->label, TRUE);
+ EnableWindow(overlayTransparencyWnd->value, TRUE);
+ EnableWindow(overlayTransparencyWnd->trackbar, TRUE);
+}
+
+void Settings::disableOverlayTransparencyWnd()
+{
+ EnableWindow(overlayTransparencyWnd->label, FALSE);
+ EnableWindow(overlayTransparencyWnd->value, FALSE);
+ EnableWindow(overlayTransparencyWnd->trackbar, FALSE);
+}
+
void Settings::setUse360ForDirect(bool set) {
use360ForDirect = set;
SendMessage(use360Wnd, BM_SETCHECK, set ? BST_CHECKED : BST_UNCHECKED, NULL);
@@ -287,7 +359,6 @@ void Settings::setUseCarSpecific(bool set, char *car) {
useCarSpecific = set;
SendMessage(carSpecificWnd, BM_SETCHECK, set ? BST_CHECKED : BST_UNCHECKED, NULL);
writeCarSpecificSetting();
-
}
void Settings::setReduceWhenParked(bool reduce) {
@@ -331,6 +402,22 @@ void Settings::setDebug(bool enabled) {
SendMessage(debugWnd, BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, NULL);
}
+void Settings::setUseAltTimer(bool enabled)
+{
+ useAltTimer = enabled;
+ SendMessage(altTimerWnd, BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, NULL);
+}
+
+void Settings::setShowForceOverlay(bool enabled)
+{
+ showForceOverlay = enabled;
+ SendMessage(forceOverlayWnd, BM_SETCHECK, enabled ? BST_CHECKED : BST_UNCHECKED, NULL);
+ if (enabled)
+ enableOverlayTransparencyWnd();
+ else
+ disableOverlayTransparencyWnd();
+}
+
float Settings::getBumpsSetting() {
return sqrt(bumpsFactor / BUMPSFORCE_MULTIPLIER);
}
@@ -365,7 +452,12 @@ void Settings::readRegSettings(char *car) {
setReduceWhenParked(true);
setStartMinimised(false);
setRunOnStartup(false);
+ setUseAltTimer(false);
setUseCarSpecific(false, car);
+ setShowForceOverlay(false);
+ setWindowPosX(30);
+ setWindowPosY(30);
+ setOverlayTransparency(255.0f, (HWND)-1);
return;
}
@@ -377,8 +469,12 @@ void Settings::readRegSettings(char *car) {
setReduceWhenParked(getRegSetting(key, L"reduceWhenParked", true));
setRunOnStartup(getRegSetting(key, L"runOnStartup", false));
setStartMinimised(getRegSetting(key, L"startMinimised", false));
+ setUseAltTimer(getRegSetting(key, L"useAltTimer", false));
setUseCarSpecific(getRegSetting(key, L"useCarSpecific", false), car);
-
+ setShowForceOverlay(getRegSetting(key, L"showForceOverlay", false));
+ setWindowPosX(getRegSetting(key, L"windowPosX", 30));
+ setWindowPosY(getRegSetting(key, L"windowPosY", 30));
+ setOverlayTransparency(getRegSetting(key, L"overlayTransparency", 255.0f), (HWND)-1);
RegCloseKey(key);
}
@@ -400,6 +496,9 @@ void Settings::readGenericSettings() {
setUndersteerFactor(0.0f, (HWND)-1);
setUndersteerOffset(0.0f, (HWND)-1);
setUse360ForDirect(true);
+ setUndersteerlatAccelDiv(60.0f, (HWND)-1);
+ setUndersteerYawRateMult(0.0f, (HWND)-1);
+
return;
}
@@ -413,7 +512,9 @@ void Settings::readGenericSettings() {
setUndersteerFactor(getRegSetting(key, L"understeerFactor", 0.0f), (HWND)-1);
setUndersteerOffset(getRegSetting(key, L"understeerOffset", 0.0f), (HWND)-1);
setUse360ForDirect(getRegSetting(key, L"use360ForDirect", true));
-
+ setUndersteerlatAccelDiv(getRegSetting(key, L"understeerlatAccelDiv", 60.0f), (HWND)-1);
+ setUndersteerYawRateMult(getRegSetting(key, L"understeerYawRateMult", 0.0f), (HWND)-1);
+
RegCloseKey(key);
}
@@ -435,7 +536,11 @@ void Settings::writeRegSettings() {
setRegSetting(key, L"reduceWhenParked", getReduceWhenParked());
setRegSetting(key, L"runOnStartup", getRunOnStartup());
setRegSetting(key, L"startMinimised", getStartMinimised());
-
+ setRegSetting(key, L"windowPosX", getWindowPosX());
+ setRegSetting(key, L"windowPosY", getWindowPosY());
+ setRegSetting(key, L"useAltTimer", getUseAltTimer());
+ setRegSetting(key, L"showForceOverlay", getShowForceOverlay());
+ setRegSetting(key, L"overlayTransparency", getOverlayTransparency());
RegCloseKey(key);
}
@@ -457,6 +562,8 @@ void Settings::writeGenericSettings() {
setRegSetting(key, L"use360ForDirect", use360ForDirect);
setRegSetting(key, L"understeerFactor", understeerFactor);
setRegSetting(key, L"understeerOffset", understeerOffset);
+ setRegSetting(key, L"understeerlatAccelDiv", understeerlatAccelDiv);
+ setRegSetting(key, L"understeerYawRateMult", understeerYawRateMult);
RegCloseKey(key);
@@ -464,9 +571,9 @@ void Settings::writeGenericSettings() {
void Settings::readSettingsForCar(char *car) {
- PWSTR path = getIniPath();
+ std::wstring path = getIniPath();
- if (path == nullptr) {
+ if (path.empty()) {
text(L"Failed to locate documents folder, can't read ini");
return;
}
@@ -477,7 +584,7 @@ void Settings::readSettingsForCar(char *car) {
char carName[MAX_CAR_NAME];
int type = 2, min = 0, max = 45, longLoad = 1, use360 = 1;
float bumps = 0.0f, damping = 0.0f, yaw = 0.0f, yawOffset = 0.0f;
- float understeer = 0.0f, understeerOffset = 0.0f;
+ float understeer = 0.0f, understeerOffset = 0.0f, understeerYawRateMult = 0.0f, understeerlatAccelDiv = 0.0f;
memset(carName, 0, sizeof(carName));
@@ -487,7 +594,7 @@ void Settings::readSettingsForCar(char *car) {
line.c_str(), INI_SCAN_FORMAT,
carName, sizeof(carName),
&type, &min, &max, &bumps, &damping, &longLoad, &use360, &yaw,
- &yawOffset, &understeer, &understeerOffset
+ &yawOffset, &understeer, &understeerOffset, &understeerYawRateMult, &understeerlatAccelDiv
) < 8
)
continue;
@@ -510,25 +617,25 @@ void Settings::readSettingsForCar(char *car) {
setUndersteerFactor(understeer, (HWND)-1);
setUndersteerOffset(understeerOffset, (HWND)-1);
setUse360ForDirect(use360 > 0);
-
+ setUndersteerYawRateMult(understeerYawRateMult, (HWND)-1);
+ setUndersteerlatAccelDiv(understeerlatAccelDiv, (HWND)-1);
DONE:
iniFile.close();
- delete[] path;
}
void Settings::writeSettingsForCar(char *car) {
- PWSTR path = getIniPath();
+ std::wstring path = getIniPath();
- if (path == nullptr) {
+ if (path.empty()) {
text(L"Failed to locate documents folder, can't write ini");
return;
}
- PWSTR tmpPath = new wchar_t[lstrlen(path) + 5];
- lstrcpy(tmpPath, path);
- lstrcat(tmpPath, L".tmp");
+ std::wstring tmpPath(path);
+ tmpPath.append(L".tmp");
+
std::ifstream iniFile(path);
std::ofstream tmpFile(tmpPath);
@@ -537,7 +644,7 @@ void Settings::writeSettingsForCar(char *car) {
char carName[MAX_CAR_NAME], buf[256];
int type = 2, min = 0, max = 45, longLoad = 1, use360 = 1;
float bumps = 0.0f, damping = 0.0f, yaw = 0.0f, yawOffset = 0.0f;
- float understeer = 0.0f, understeerOffset = 0.0f;
+ float understeer = 0.0f, understeerOffset = 0.0f, understeerYawRateMult = 0.0f, understeerlatAccelDiv = 0.0f;
bool written = false, iniPresent = iniFile.good();
text(L"Writing settings for car %s", car);
@@ -553,7 +660,7 @@ void Settings::writeSettingsForCar(char *car) {
line.c_str(), INI_SCAN_FORMAT,
carName, sizeof(carName),
&type, &min, &max, &bumps, &damping, &longLoad, &use360,
- &yaw, &yawOffset, &understeer, &understeerOffset
+ &yaw, &yawOffset, &understeer, &understeerOffset, &understeerYawRateMult, &understeerlatAccelDiv
) < 8
) {
strcpy_s(buf, line.c_str());
@@ -569,7 +676,8 @@ void Settings::writeSettingsForCar(char *car) {
buf, INI_PRINT_FORMAT,
car, ffbType, getMinForceSetting(), maxForce, getBumpsSetting(),
dampingFactor, 1, use360ForDirect, sopFactor, getSopOffsetSetting(),
- understeerFactor, getUndersteerOffsetSetting()
+ understeerFactor, getUndersteerOffsetSetting(), getUndersteerYawRateMult(),
+ getUndersteerlatAccelDiv()
);
writeWithNewline(tmpFile, buf);
written = true;
@@ -609,7 +717,8 @@ void Settings::writeSettingsForCar(char *car) {
buf, INI_PRINT_FORMAT,
car, ffbType, getMinForceSetting(), maxForce, getBumpsSetting(),
dampingFactor, 1, use360ForDirect, sopFactor, getSopOffsetSetting(),
- understeerFactor, getUndersteerOffsetSetting()
+ understeerFactor, getUndersteerOffsetSetting(), getUndersteerYawRateMult(),
+ getUndersteerlatAccelDiv()
);
writeWithNewline(tmpFile, buf);
@@ -617,11 +726,9 @@ void Settings::writeSettingsForCar(char *car) {
iniFile.close();
tmpFile.close();
- if (!MoveFileEx(tmpPath, path, MOVEFILE_REPLACE_EXISTING))
+ if (!MoveFileEx(tmpPath.c_str(), path.c_str(), MOVEFILE_REPLACE_EXISTING))
text(L"Failed to update ini file, error %d", GetLastError());
- delete[] path;
- delete[] tmpPath;
}
@@ -635,50 +742,51 @@ wchar_t *Settings::ffbTypeString(int type) {
}
}
-PWSTR Settings::getIniPath() {
+std::wstring Settings::getIniPath() {
PWSTR docsPath;
- wchar_t *path;
-
if (SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &docsPath) != S_OK)
- return nullptr;
-
- path = new wchar_t[lstrlen(docsPath) + lstrlen(INI_PATH) + 1];
+ return std::wstring(L"");
- lstrcpyW(path, docsPath);
- lstrcatW(path, INI_PATH);
+ fs::path fsPath = { docsPath };
CoTaskMemFree(docsPath);
+ fsPath.append("irFFB");
+ if (!fs::exists(fsPath))
+ {
+ fs::create_directory(fsPath);
+ }
- return path;
-
+ fsPath.append(INI_PATH);
+ ::debug((wchar_t*)fsPath.wstring().c_str(), L"");
+ return fsPath.wstring();
}
-PWSTR Settings::getLogPath() {
+std::wstring Settings::getLogPath() {
PWSTR docsPath;
- wchar_t buf[64];
- wchar_t *path;
SYSTEMTIME lt;
if (SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &docsPath) != S_OK)
- return nullptr;
+ return std::wstring(L"");
- GetLocalTime(<);
-
- lstrcpyW(buf, L"\\irFFB-");
- int len = wcslen(buf) * sizeof(wchar_t);
- StringCbPrintf(
- buf + wcslen(buf), sizeof(buf) - len, L"%d-%02d-%02d-%02d-%02d-%02d.log",
- lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond
- );
+ fs::path fsPath = { docsPath };
+ CoTaskMemFree(docsPath);
+ fsPath.append("irFFB");
+ fsPath.append("Log");
+ if (!fs::exists(fsPath))
+ {
+ fs::create_directories(fsPath);
+ }
- path = new wchar_t[lstrlen(docsPath) + lstrlen(buf) + 1];
+ GetLocalTime(<);
- lstrcpyW(path, docsPath);
- lstrcatW(path, buf);
- CoTaskMemFree(docsPath);
+ char logfile[256];
+ sprintf_s(logfile, 256, "irFFB-%d-%02d-%02d-%02d-%02d-%02d.log", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
+ std::string fmtFileName(logfile);
+ fsPath.append(fmtFileName);
- return path;
+ ::debug((wchar_t*)fsPath.wstring().c_str(), L"");
+ return fsPath.wstring();
}
diff --git a/irFFB/stdafx.h b/irFFB/stdafx.h
index 26c803f..5020314 100644
--- a/irFFB/stdafx.h
+++ b/irFFB/stdafx.h
@@ -7,7 +7,7 @@
#include "targetver.h"
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include
@@ -34,6 +34,12 @@
#include
#include
#include
+#include
+#include
+
+#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
+#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
+#endif
#define DIRECTINPUT_VERSION 0x0800
#include
@@ -44,3 +50,24 @@
#include
+#ifdef _UNICODE
+
+#if defined _M_IX86
+
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+
+#elif defined _M_IA64
+
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+
+#elif defined _M_X64
+
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+
+#else
+
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+
+#endif
+
+#endif
diff --git a/irFFB/tractionloss.cpp b/irFFB/tractionloss.cpp
deleted file mode 100644
index 7a995bf..0000000
--- a/irFFB/tractionloss.cpp
+++ /dev/null
@@ -1,527 +0,0 @@
-#include
-
-#include "irFFB.h"
-#include "tractionloss.h"
-
-TractionLoss *TractionLoss::instance = nullptr;
-
-TractionLoss *TractionLoss::init() {
- return new TractionLoss();
-}
-
-TractionLoss::TractionLoss() {
-
- if (FAILED(CoInitializeEx(0, COINIT_MULTITHREADED)))
- return;
-
- CoInitializeSecurity(
- NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
- RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
- );
-
- instance = this;
- readSettings();
- enumSerialPorts();
-
-}
-
-ATOM TractionLoss::registerClass(HINSTANCE hInstance) {
-
- WNDCLASSEXW wcex;
-
- wcex.cbSize = sizeof(WNDCLASSEX);
-
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = wndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IRFFB));
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = 0;
- wcex.lpszClassName = windowClass;
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
-
- return RegisterClassExW(&wcex);
-
-}
-
-void TractionLoss::createWindow(HINSTANCE hInst) {
-
- if (!classIsRegistered) {
- registerClass(hInst);
- classIsRegistered = true;
- }
-
- mainWnd = CreateWindowW(
- windowClass, windowClass, WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
- CW_USEDEFAULT, CW_USEDEFAULT, 440, 360,
- NULL, NULL, hInst, NULL
- );
-
- if (!mainWnd)
- return;
-
- portWnd = combo(mainWnd, L"TL controller port:", 40, 40);
- minAngleWnd = slider(mainWnd, L"Min angle:", 40, 120, L"0", L"50", false);
- SendMessage(minAngleWnd->trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(0, 50));
- stepsPerDegWnd = slider(mainWnd, L"Steps per deg:", 40, 200, L"0", L"500", false);
- SendMessage(stepsPerDegWnd->trackbar, TBM_SETRANGE, TRUE, MAKELPARAM(0, 500));
-
- ShowWindow(mainWnd, SW_SHOWNORMAL);
- UpdateWindow(mainWnd);
- enumSerialPorts();
- readSettings();
-
- return;
-
-}
-
-LRESULT CALLBACK TractionLoss::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
-
- HWND wnd = (HWND)lParam;
-
- switch (message) {
-
- case WM_COMMAND: {
- int wmId = LOWORD(wParam);
- switch (wmId) {
- case IDM_EXIT:
- DestroyWindow(hWnd);
- break;
- default:
- if (HIWORD(wParam) == CBN_SELCHANGE) {
- if (wnd == instance->portWnd) {
- int idx = (int)SendMessage(wnd, CB_GETCURSEL, 0, 0);
- if (idx >= 0 && idx < instance->numPorts) {
- instance->tlPort = instance->ports[idx].dev;
- instance->initPort();
- }
- }
- }
- break;
- }
- }
-
- case WM_HSCROLL: {
- if (wnd == instance->minAngleWnd->trackbar) {
- wchar_t strbuf[8];
- int angle = SendMessage(wnd, TBM_GETPOS, 0, 0);
- swprintf_s(strbuf, L"%d", angle);
- instance->setMinAngle(angle);
- SendMessage(instance->minAngleWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
- }
- else if (wnd == instance->stepsPerDegWnd->trackbar) {
- wchar_t strbuf[8];
- int steps = SendMessage(wnd, TBM_GETPOS, 0, 0);
- swprintf_s(strbuf, L"%d", steps);
- instance->setStepsPerDeg(steps);
- SendMessage(instance->stepsPerDegWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
- }
- }
- break;
-
- case WM_EDIT_VALUE: {
- if (wnd == instance->minAngleWnd->value) {
- instance->setMinAngle(wParam);
- SendMessage(instance->minAngleWnd->trackbar, TBM_SETPOS, true, wParam);
- }
- else if (wnd == instance->stepsPerDegWnd->value) {
- instance->setStepsPerDeg(wParam);
- SendMessage(instance->stepsPerDegWnd->trackbar, TBM_SETPOS, true, wParam);
- }
- }
- break;
-
- case WM_CTLCOLORSTATIC: {
- SetBkColor((HDC)wParam, RGB(0xff, 0xff, 0xff));
- return (LRESULT)CreateSolidBrush(RGB(0xff, 0xff, 0xff));
- }
- break;
-
- case WM_PAINT: {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- EndPaint(hWnd, &ps);
- }
- break;
-
- case WM_DESTROY: {
- instance->writeSettings();
- }
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
-
- }
-
- return 0;
-
-}
-
-void TractionLoss::setMinAngle(int angle) {
- if (angle < 0 || angle > 50) return;
- minAngle = angle / 10.0f;
- if (minAngleWnd == nullptr) return;
- SendMessage(minAngleWnd->trackbar, TBM_SETPOS, TRUE, angle);
- swprintf_s(strbuf, L"%d", angle);
- SendMessage(minAngleWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-
-void TractionLoss::setStepsPerDeg(int steps) {
- if (steps < 0 || steps > 500) return;
- stepsPerDeg = steps / 10.0f;
- if (stepsPerDegWnd == nullptr) return;
- SendMessage(stepsPerDegWnd->trackbar, TBM_SETPOS, TRUE, steps);
- swprintf_s(strbuf, L"%d", steps);
- SendMessage(stepsPerDegWnd->value, WM_SETTEXT, NULL, LPARAM(strbuf));
-}
-
-
-void TractionLoss::enumSerialPorts() {
-
- UINT portsSize = numPorts = 0;
-
- IWbemLocator *locator = NULL;
- if (
- FAILED(
- CoCreateInstance(
- CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
- IID_IWbemLocator, reinterpret_cast(&locator)
- )
- )
- ) {
- text(L"Failed to CoCreateInstance of WbemLocator");
- return;
- }
-
- IWbemServices *services = NULL;
- if (
- FAILED(
- locator->ConnectServer(
- _bstr_t("\\\\.\\root\\cimv2"), NULL, NULL, NULL, 0, NULL, NULL, &services
- )
- )
- ) {
- text(L"Failed to connect to cimv2 server");
- locator->Release();
- return;
- }
-
- IEnumWbemClassObject *classObject = NULL;
- HRESULT hr = services->ExecQuery(
- _bstr_t("WQL"), _bstr_t("SELECT * FROM Win32_SerialPort"),
- WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &classObject
- );
-
- if (FAILED(hr)) {
- _com_error err(hr);
- text(L"SerialPort query failed: %s", err.ErrorMessage());
- services->Release();
- locator->Release();
- return;
- }
-
- hr = WBEM_S_NO_ERROR;
-
- while (hr == WBEM_S_NO_ERROR) {
-
- ULONG num = 0;
- IWbemClassObject *obj[16];
-
- if (
- SUCCEEDED(
- classObject->Next(
- WBEM_INFINITE, 16, reinterpret_cast(obj), &num
- )
- )
- ) {
-
- UINT i = 0;
-
- if (num == 0)
- break;
-
- portsSize += sizeof(port) * num;
- ports = (port *)realloc(ports, portsSize);
-
- for (ULONG n = 0; n < num; n++) {
-
- VARIANT name;
- HRESULT hrGet = obj[n]->Get(L"DeviceID", 0, &name, NULL, NULL);
-
- if (
- SUCCEEDED(hrGet) && (name.vt == VT_BSTR) && (wcslen(name.bstrVal) > 3)
- ) {
-
- if (_wcsnicmp(name.bstrVal, L"COM", 3) != 0)
- continue;
-
- VARIANT fname;
- ports[numPorts + i].dev = (wchar_t *)malloc((lstrlen(name.bstrVal) + 5) * sizeof(wchar_t));
- lstrcpy(ports[numPorts + i].dev, L"\\\\.\\");
- lstrcat(ports[numPorts + i].dev, name.bstrVal);
- if (
- FAILED(obj[n]->Get(L"Name", 0, &fname, NULL, NULL)) ||
- fname.vt != VT_BSTR
- )
- ports[numPorts + i].name = StrDupW(name.bstrVal);
- else
- ports[numPorts + i].name = StrDupW(fname.bstrVal);
-
- SendMessage(
- portWnd, CB_ADDSTRING, 0,
- LPARAM(ports[numPorts + i].name)
- );
-
- if (tlPort != nullptr && _wcsnicmp(ports[numPorts + i].dev, tlPort, 128) == 0) {
- SendMessage((HWND)portWnd, CB_SETCURSEL, numPorts + i, 0);
- if (tlHandle == INVALID_HANDLE_VALUE)
- initPort();
- }
-
- i++;
-
- }
-
- obj[n]->Release();
-
- }
-
- numPorts += i;
-
- }
- }
-
- classObject->Release();
- services->Release();
- locator->Release();
-
-}
-
-void TractionLoss::initPort() {
-
- byte buf[] = { '[', 'r', 'd', 'S', ']' };
-
- DWORD written;
- COMSTAT comstat;
- DWORD errors;
-
- if (tlPort == nullptr)
- return;
-
- wchar_t *settings = L"500000,n,8,1";
-
- if (tlHandle != INVALID_HANDLE_VALUE)
- CloseHandle(tlHandle);
-
- tlHandle = CreateFile(
- tlPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0
- );
-
- DCB dcb;
-
- memset(&dcb, 0, sizeof(dcb));
- dcb.DCBlength = sizeof(dcb);
- if (!BuildCommDCB(settings, &dcb)) {
- text(L"Error building TL control port parameters");
- CloseHandle(tlHandle);
- tlHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- dcb.fAbortOnError = FALSE;
- dcb.fDtrControl = TRUE;
-
- if (!SetCommState(tlHandle, &dcb)) {
- text(L"Error setting TL control port parameters");
- CloseHandle(tlHandle);
- tlHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- COMMTIMEOUTS timeouts;
- memset(&timeouts, 0, sizeof(timeouts));
- timeouts.WriteTotalTimeoutConstant = 10;
- timeouts.ReadTotalTimeoutConstant = 1000;
- SetCommTimeouts(tlHandle, &timeouts);
-
- Sleep(1000);
-
- if (!WriteFile(tlHandle, buf, 5, &written, NULL)) {
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(tlHandle, &errors, &comstat);
- text(L"Error writing to TL control port");
- tlHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- memset(buf, 0, 5);
-
- for (int i = 0; i < 5; i++)
- if (!ReadFile(tlHandle, buf + i, 1, &written, NULL))
- break;
-
- if (buf[4] != ']') {
- text(L"Error talking to SMC, correct port?");
- CloseHandle(tlHandle);
- tlHandle = INVALID_HANDLE_VALUE;
- return;
- }
-
- minPos = buf[3] + 12;
- maxPos = 1023 - minPos;
- maxDelta = maxPos - minPos;
-
- text(L"Connected to TL control port, max delta: %hd", maxDelta);
-
-}
-
-void TractionLoss::setEnabled(bool enabled) {
-
- static byte buf[5] = { '[', 0, 0, 0, ']' };
-
- DWORD written;
- COMSTAT comstat;
- DWORD errors;
-
- if (tlHandle == INVALID_HANDLE_VALUE)
- return;
-
- isEnabled = enabled;
-
- if (!enabled) {
-
- buf[1] = 'A';
- buf[2] = 512 >> 8;
- buf[3] = 0;
-
- if (!WriteFile(tlHandle, buf, 5, &written, NULL)) {
- text(L"Error writing to TL port: %d", GetLastError());
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(tlHandle, &errors, &comstat);
- }
-
- }
-
- buf[1] = 'N';
- buf[2] = 0;
- buf[3] = enabled ? 1 : 0;
-
- if (!WriteFile(tlHandle, buf, 5, &written, NULL)) {
- text(L"Error writing to TL port: %d", GetLastError());
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(tlHandle, &errors, &comstat);
- }
-
- if (enabled) {
-
- buf[1] = 'e';
- buf[2] = 'n';
- buf[3] = '1';
-
- if (!WriteFile(tlHandle, buf, 5, &written, NULL)) {
- text(L"Error writing to TL port: %d", GetLastError());
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(tlHandle, &errors, &comstat);
- }
-
- text(L"TL enabled");
-
- }
- else {
- text(L"TL disabled");
- }
-
-}
-
-void TractionLoss::setAngle(float angle) {
-
- static byte buf[] = { '[', 'A', 0, 0, ']' };
-
- DWORD written;
- COMSTAT comstat;
- DWORD errors;
-
- if (tlHandle == INVALID_HANDLE_VALUE)
- return;
-
- int16_t pos = 512 + (int16_t)(angle * 57.2958f * stepsPerDeg);
-
- if (pos > maxPos) pos = maxPos;
- else if (pos < minPos) pos = minPos;
-
- buf[2] = pos >> 8;
- buf[3] = pos & 0xff;
-
- if (!WriteFile(tlHandle, buf, 5, &written, NULL)) {
- text(L"Error writing to TL control port: %d", GetLastError());
- if (GetLastError() != ERROR_IO_PENDING)
- ClearCommError(tlHandle, &errors, &comstat);
- }
-
-}
-
-void TractionLoss::readSettings() {
-
- HKEY regKey;
- DWORD val;
- DWORD sz = sizeof(val);
-
- if (tlPort != nullptr)
- delete[] tlPort;
-
- tlPort = new wchar_t[128];
- DWORD tlPortSize = 128 * sizeof(wchar_t);
-
- if (!RegOpenKeyEx(HKEY_CURRENT_USER, SETTINGS_KEY, 0, KEY_ALL_ACCESS, ®Key)) {
-
- if (RegGetValueW(regKey, nullptr, L"tlPort", RRF_RT_REG_SZ, nullptr, tlPort, &tlPortSize)) {
- delete[] tlPort;
- tlPort = nullptr;
- }
- if (RegGetValueW(regKey, nullptr, L"tlMinAngle", RRF_RT_REG_DWORD, nullptr, (BYTE *)&val, &sz))
- setMinAngle(35);
- else
- setMinAngle(val);
- if (RegGetValueW(regKey, nullptr, L"tlStepsPerDeg", RRF_RT_REG_DWORD, nullptr, (BYTE *)&val, &sz))
- setStepsPerDeg(350);
- else
- setStepsPerDeg(val);
-
- }
- else {
- delete[] tlPort;
- tlPort = nullptr;
- setMinAngle(35);
- setStepsPerDeg(350);
- }
-
-}
-
-void TractionLoss::writeSettings() {
-
- HKEY regKey;
- DWORD sz = sizeof(int);
- DWORD tlPortSz = 0;
- DWORD minAngleVal = (DWORD)(minAngle * 10.0f);
- DWORD stepsPerDegVal = (DWORD)(stepsPerDeg * 10.0f);
-
- if (tlPort)
- tlPortSz = (lstrlen(tlPort) + 1) * sizeof(wchar_t);
-
- RegCreateKeyEx(
- HKEY_CURRENT_USER, SETTINGS_KEY, 0, nullptr,
- REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, ®Key, nullptr
- );
-
- if (!RegOpenKeyEx(HKEY_CURRENT_USER, SETTINGS_KEY, 0, KEY_ALL_ACCESS, ®Key)) {
- if (tlPort)
- RegSetValueEx(regKey, L"tlPort", 0, REG_SZ, (BYTE *)tlPort, tlPortSz);
- RegSetValueEx(regKey, L"tlMinAngle", 0, REG_DWORD, (BYTE *)&minAngleVal, sz);
- RegSetValueEx(regKey, L"tlStepsPerDeg", 0, REG_DWORD, (BYTE *)&stepsPerDegVal, sz);
- }
-
-}
\ No newline at end of file
diff --git a/irFFB/tractionloss.h b/irFFB/tractionloss.h
deleted file mode 100644
index 31f31f3..0000000
--- a/irFFB/tractionloss.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#pragma once
-
-#include
-#include
-
-#include "stdafx.h"
-#include "irFFB.h"
-#include "fan.h"
-
-class TractionLoss
-{
-
- public:
- static TractionLoss *init();
- void createWindow(HINSTANCE);
- float getMinAngle() { return minAngle / 57.2958f; };
- void setAngle(float);
- void setEnabled(bool enable);
- private:
- TractionLoss();
- ATOM registerClass(HINSTANCE);
- static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
- void setMinAngle(int);
- void setStepsPerDeg(int);
- void enumSerialPorts();
- void initPort();
- void readSettings();
- void writeSettings();
-
- static TractionLoss *instance;
-
- wchar_t *windowClass = L"Traction Loss settings";
- HWND mainWnd, portWnd;
- sWins_t *minAngleWnd = nullptr, *stepsPerDegWnd = nullptr;
- int numPorts = 0;
- wchar_t *tlPort = nullptr;
- port *ports = nullptr;
- HANDLE tlHandle = INVALID_HANDLE_VALUE;
- wchar_t strbuf[64];
- bool classIsRegistered = false;
- bool isEnabled = false;
- int16_t minPos = 0, maxPos = 0, maxDelta = 0;
- float minAngle, stepsPerDeg;
-
-};
-