├── .gitignore ├── EDForceFeedback.sln ├── EDForceFeedback ├── App.config ├── EDForceFeedback.csproj ├── FFUtils │ ├── FFConst.exe │ ├── csFeedback.exe │ ├── fedit.exe │ └── pid1_01.pdf ├── Forces │ ├── Cargo.ffe │ ├── CenterSpringXY.ffe │ ├── Damper.ffe │ ├── Dock.ffe │ ├── Gear.ffe │ ├── Hardpoints.ffe │ ├── Landed.ffe │ ├── SuperCruise.ffe │ ├── Vibrate.ffe │ └── VibrateSide.ffe ├── Form1.Designer.cs ├── Form1.cs ├── Form1.resx ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── settings.Xbox.json ├── settings.json ├── settingsMSFFB2.json ├── settingsXboxAndCyborg.json └── settingsXboxAndMSFFB2.json ├── EDForceFeedbackConsole ├── App.config ├── EDForceFeedbackConsole.csproj ├── FFUtils │ ├── FFConst.exe │ ├── csFeedback.exe │ ├── fedit.exe │ └── pid1_01.pdf ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Forces │ ├── Cargo.ffe │ ├── CenterSpringXY.ffe │ ├── Damper.ffe │ ├── Dock.ffe │ ├── Gear.ffe │ ├── Hardpoints.ffe │ ├── Landed.ffe │ ├── SuperCruise.ffe │ ├── Vibrate.ffe │ └── VibrateSide.ffe ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── appsettings.json ├── settings.Xbox.json ├── settings.bak.json ├── settings.json ├── settingsMSFFB2.json ├── settingsXboxAndCyborg.json └── settingsXboxAndMSFFB2.json ├── ForceFeedback.PNG ├── ForceFeedbackSharpDx ├── ForceFeedbackController.cs └── ForceFeedbackSharpDx.csproj ├── Journals ├── Client.cs ├── Device.cs ├── DeviceEvents.cs ├── EventConfiguration.cs ├── Journals.csproj └── Settings.cs ├── LICENSE ├── README.md ├── TestForceFeedback ├── App.config ├── EliteAPIMock.cs ├── EliteShipMock.cs ├── EliteStatusMock.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── Forces │ ├── Cargo.ffe │ ├── CenterSpringXY.ffe │ ├── Damper.ffe │ ├── Dock.ffe │ ├── Gear.ffe │ ├── Hardpoints.ffe │ ├── Landed.ffe │ ├── Vibrate.ffe │ └── VibrateSide.ffe ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── TestForceFeedback.csproj └── packages.config └── events.txt /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /EDForceFeedback.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.13.35828.75 d17.13 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ForceFeedbackSharpDx", "ForceFeedbackSharpDx\ForceFeedbackSharpDx.csproj", "{D3C53E08-943F-4DD8-9939-6CD5858E28AC}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Journals", "Journals\Journals.csproj", "{CF2E9959-F6FE-4E26-89E9-AF7DFAB9099E}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EDForceFeedback", "EDForceFeedback\EDForceFeedback.csproj", "{072E80F0-C235-44F2-B93B-747C488B490A}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestForceFeedback", "TestForceFeedback\TestForceFeedback.csproj", "{574005ED-6B12-4092-AC48-71B5B302F8AD}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EFF6C1F9-7DEC-431E-8F1B-823AC8CAE114}" 15 | ProjectSection(SolutionItems) = preProject 16 | README.md = README.md 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {D3C53E08-943F-4DD8-9939-6CD5858E28AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {D3C53E08-943F-4DD8-9939-6CD5858E28AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {D3C53E08-943F-4DD8-9939-6CD5858E28AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {D3C53E08-943F-4DD8-9939-6CD5858E28AC}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {CF2E9959-F6FE-4E26-89E9-AF7DFAB9099E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {CF2E9959-F6FE-4E26-89E9-AF7DFAB9099E}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {CF2E9959-F6FE-4E26-89E9-AF7DFAB9099E}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {CF2E9959-F6FE-4E26-89E9-AF7DFAB9099E}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {072E80F0-C235-44F2-B93B-747C488B490A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {072E80F0-C235-44F2-B93B-747C488B490A}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {072E80F0-C235-44F2-B93B-747C488B490A}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {072E80F0-C235-44F2-B93B-747C488B490A}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {574005ED-6B12-4092-AC48-71B5B302F8AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {574005ED-6B12-4092-AC48-71B5B302F8AD}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {574005ED-6B12-4092-AC48-71B5B302F8AD}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 | {574005ED-6B12-4092-AC48-71B5B302F8AD}.Release|Any CPU.Build.0 = Release|Any CPU 41 | EndGlobalSection 42 | GlobalSection(SolutionProperties) = preSolution 43 | HideSolutionNode = FALSE 44 | EndGlobalSection 45 | GlobalSection(ExtensibilityGlobals) = postSolution 46 | SolutionGuid = {F09A2414-F647-4782-8D23-17387CCD776D} 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /EDForceFeedback/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /EDForceFeedback/EDForceFeedback.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {072E80F0-C235-44F2-B93B-747C488B490A} 8 | Exe 9 | EDForceFeedback 10 | EDForceFeedback 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | false 18 | publish\ 19 | true 20 | Disk 21 | false 22 | Foreground 23 | 7 24 | Days 25 | false 26 | false 27 | true 28 | 0 29 | 2.5.0.%2a 30 | false 31 | true 32 | 33 | 34 | 35 | AnyCPU 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | AnyCPU 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | true 53 | 54 | 55 | 56 | ..\packages\Microsoft.Extensions.Configuration.9.0.3\lib\net462\Microsoft.Extensions.Configuration.dll 57 | True 58 | 59 | 60 | ..\packages\Microsoft.Extensions.Configuration.Abstractions.9.0.3\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll 61 | True 62 | 63 | 64 | ..\packages\Microsoft.Extensions.Configuration.Binder.9.0.3\lib\net462\Microsoft.Extensions.Configuration.Binder.dll 65 | True 66 | 67 | 68 | ..\packages\Microsoft.Extensions.Configuration.CommandLine.9.0.3\lib\net462\Microsoft.Extensions.Configuration.CommandLine.dll 69 | True 70 | 71 | 72 | ..\packages\Microsoft.Extensions.Configuration.Json.9.0.3\lib\net462\Microsoft.Extensions.Configuration.Json.dll 73 | True 74 | 75 | 76 | ..\packages\Microsoft.Extensions.Configuration.UserSecrets.9.0.3\lib\net462\Microsoft.Extensions.Configuration.UserSecrets.dll 77 | True 78 | 79 | 80 | ..\packages\Microsoft.Extensions.DependencyInjection.9.0.3\lib\net462\Microsoft.Extensions.DependencyInjection.dll 81 | True 82 | 83 | 84 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.3\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll 85 | True 86 | 87 | 88 | ..\packages\Microsoft.Extensions.FileProviders.Abstractions.9.0.3\lib\net462\Microsoft.Extensions.FileProviders.Abstractions.dll 89 | True 90 | 91 | 92 | ..\packages\Microsoft.Extensions.FileProviders.Physical.9.0.3\lib\net462\Microsoft.Extensions.FileProviders.Physical.dll 93 | True 94 | 95 | 96 | ..\packages\Microsoft.Extensions.FileSystemGlobbing.9.0.3\lib\net462\Microsoft.Extensions.FileSystemGlobbing.dll 97 | True 98 | 99 | 100 | ..\packages\Microsoft.Extensions.Hosting.9.0.3\lib\net462\Microsoft.Extensions.Hosting.dll 101 | True 102 | 103 | 104 | ..\packages\Microsoft.Extensions.Hosting.Abstractions.9.0.3\lib\net462\Microsoft.Extensions.Hosting.Abstractions.dll 105 | True 106 | 107 | 108 | ..\packages\Microsoft.Extensions.Logging.9.0.3\lib\net462\Microsoft.Extensions.Logging.dll 109 | True 110 | 111 | 112 | ..\packages\Microsoft.Extensions.Logging.Abstractions.9.0.3\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll 113 | True 114 | 115 | 116 | ..\packages\Microsoft.Extensions.Logging.Configuration.9.0.3\lib\net462\Microsoft.Extensions.Logging.Configuration.dll 117 | True 118 | 119 | 120 | ..\packages\Microsoft.Extensions.Logging.Console.9.0.3\lib\net462\Microsoft.Extensions.Logging.Console.dll 121 | True 122 | 123 | 124 | ..\packages\Microsoft.Extensions.Logging.EventLog.9.0.3\lib\net462\Microsoft.Extensions.Logging.EventLog.dll 125 | True 126 | 127 | 128 | ..\packages\Microsoft.Extensions.Logging.EventSource.9.0.3\lib\net462\Microsoft.Extensions.Logging.EventSource.dll 129 | True 130 | 131 | 132 | ..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.9.0.3\lib\net462\Microsoft.Extensions.Options.ConfigurationExtensions.dll 133 | True 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Always 154 | 155 | 156 | Always 157 | 158 | 159 | Always 160 | 161 | 162 | Always 163 | 164 | 165 | Always 166 | 167 | 168 | Always 169 | 170 | 171 | Always 172 | 173 | 174 | Always 175 | 176 | 177 | Always 178 | 179 | 180 | Always 181 | 182 | 183 | 184 | Always 185 | 186 | 187 | Always 188 | 189 | 190 | Always 191 | 192 | 193 | Always 194 | 195 | 196 | Always 197 | 198 | 199 | Always 200 | 201 | 202 | Always 203 | 204 | 205 | Always 206 | 207 | 208 | 209 | 210 | {cf2e9959-f6fe-4e26-89e9-af7dfab9099e} 211 | Journals 212 | 213 | 214 | 215 | 216 | False 217 | Microsoft .NET Framework 4.8 %28x86 and x64%29 218 | true 219 | 220 | 221 | False 222 | .NET Framework 3.5 SP1 223 | false 224 | 225 | 226 | 227 | 228 | 4.7.0 229 | 230 | 231 | 9.0.3 232 | 233 | 234 | 13.0.3 235 | 236 | 237 | 3.2.46 238 | 239 | 240 | 9.0.0 241 | 242 | 243 | 3.0.0 244 | 245 | 246 | 2.1.0 247 | 248 | 249 | 6.0.0 250 | 251 | 252 | 4.2.0 253 | 254 | 255 | 9.0.3 256 | 257 | 258 | 4.6.0 259 | 260 | 261 | 4.3.1 262 | 263 | 264 | 4.3.0 265 | 266 | 267 | 4.3.1 268 | 269 | 270 | 9.0.3 271 | 272 | 273 | 4.6.0 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /EDForceFeedback/FFUtils/FFConst.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/FFUtils/FFConst.exe -------------------------------------------------------------------------------- /EDForceFeedback/FFUtils/csFeedback.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/FFUtils/csFeedback.exe -------------------------------------------------------------------------------- /EDForceFeedback/FFUtils/fedit.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/FFUtils/fedit.exe -------------------------------------------------------------------------------- /EDForceFeedback/FFUtils/pid1_01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/FFUtils/pid1_01.pdf -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Cargo.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Cargo.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/CenterSpringXY.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/CenterSpringXY.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Damper.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Damper.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Dock.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Dock.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Gear.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Gear.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Hardpoints.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Hardpoints.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Landed.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Landed.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/SuperCruise.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/SuperCruise.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/Vibrate.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/Vibrate.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Forces/VibrateSide.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedback/Forces/VibrateSide.ffe -------------------------------------------------------------------------------- /EDForceFeedback/Form1.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace EDForceFeedback 2 | { 3 | partial class Form1 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.statusLabel = new System.Windows.Forms.Label(); 32 | this.testButton = new System.Windows.Forms.Button(); 33 | this.SuspendLayout(); 34 | // 35 | // statusLabel 36 | // 37 | this.statusLabel.AutoSize = true; 38 | this.statusLabel.Location = new System.Drawing.Point(20, 12); 39 | this.statusLabel.Name = "statusLabel"; 40 | this.statusLabel.Size = new System.Drawing.Size(147, 15); 41 | this.statusLabel.TabIndex = 0; 42 | this.statusLabel.Text = "EDForceFeedback Window"; 43 | // 44 | // testButton 45 | // 46 | this.testButton.Location = new System.Drawing.Point(400, 8); 47 | this.testButton.Name = "testButton"; 48 | this.testButton.Size = new System.Drawing.Size(75, 23); 49 | this.testButton.TabIndex = 1; 50 | this.testButton.Text = "Test"; 51 | this.testButton.UseVisualStyleBackColor = true; 52 | this.testButton.Click += new System.EventHandler(this.button1_Click); 53 | // 54 | // Form1 55 | // 56 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 57 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 58 | this.ClientSize = new System.Drawing.Size(487, 49); 59 | this.Controls.Add(this.testButton); 60 | this.Controls.Add(this.statusLabel); 61 | this.Name = "Form1"; 62 | this.Text = "EDForceFeedback"; 63 | this.Load += new System.EventHandler(this.Form1_Load); 64 | this.ResumeLayout(false); 65 | this.PerformLayout(); 66 | 67 | } 68 | 69 | #endregion 70 | 71 | private Label statusLabel; 72 | private Button testButton; 73 | } 74 | } -------------------------------------------------------------------------------- /EDForceFeedback/Form1.cs: -------------------------------------------------------------------------------- 1 | using Journals; 2 | using Microsoft.Extensions.Logging; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows.Forms; 5 | using System.Xml.Linq; 6 | 7 | namespace EDForceFeedback 8 | { 9 | public partial class Form1 : Form 10 | { 11 | private Client _client; 12 | private Settings _settings; 13 | public Form1(Client client, Settings settings) 14 | { 15 | InitializeComponent(); 16 | 17 | _client = client; 18 | _settings = settings; 19 | } 20 | 21 | private void Form1_Load(object sender, EventArgs e) 22 | { 23 | Task.Run(async () => await _client.Initialize(_settings).ConfigureAwait(false)).ContinueWith(t => 24 | { 25 | var result = "Uknown state"; 26 | if (t.IsCanceled) result = "Task cancelled"; 27 | else if (t.IsFaulted) result = $"Exception {t.Exception.InnerException?.Message}"; 28 | else result = _client.StatusText; 29 | 30 | statusLabel.Invoke((MethodInvoker)delegate { 31 | statusLabel.Text = result; 32 | }); 33 | }); 34 | 35 | } 36 | 37 | private void button1_Click(object sender, EventArgs e) 38 | { 39 | _client.TestEffect(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /EDForceFeedback/Form1.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | text/microsoft-resx 50 | 51 | 52 | 2.0 53 | 54 | 55 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 56 | 57 | 58 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 59 | 60 | -------------------------------------------------------------------------------- /EDForceFeedback/Program.cs: -------------------------------------------------------------------------------- 1 | using Journals; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.IO; 5 | using System.Threading.Tasks; 6 | 7 | namespace EDForceFeedback 8 | { 9 | static public class Program 10 | { 11 | static private async Task Main(string[] args) 12 | { 13 | var fileName = $"{Directory.GetCurrentDirectory()}\\settings.json"; 14 | 15 | // Check if a settings file was specified 16 | if (args?.Length == 1) 17 | { 18 | if (args[0].CompareTo("-h") == 0 || args[0].CompareTo("help") == 0) 19 | { 20 | Console.WriteLine("EDForceFeedBack: EDForceFeedback.exe is a console program that runs during a Elite Dangerous session."); 21 | Console.WriteLine("It watches the ED log files and responds to game events by playing a force feedback editor (.ffe) file."); 22 | Console.WriteLine(); 23 | Console.WriteLine("Usage:"); 24 | Console.WriteLine("EDForceFeedback.exe -h Output this help."); 25 | Console.WriteLine(@"EDForceFeedback.exe c:\settings.json Override the default settings file and use this instead."); 26 | Console.WriteLine($"EDForceFeedback.exe Will default to the settings file {Directory.GetCurrentDirectory()}\\settings.json"); 27 | return; 28 | } 29 | else 30 | { 31 | fileName = args[0]; 32 | } 33 | } 34 | 35 | Console.WriteLine($"Using setting file: {fileName}"); 36 | 37 | var settings = JsonConvert.DeserializeObject(File.ReadAllText(fileName)); 38 | 39 | var client = new Client(); 40 | 41 | await client.Initialize(settings).ConfigureAwait(false); 42 | 43 | while (true) 44 | await Task.Delay(5000).ConfigureAwait(false); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /EDForceFeedback/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EDForceFeedback")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EDForceFeedback")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("072e80f0-c235-44f2-b93b-747c488b490a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EDForceFeedback/settings.Xbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | } 101 | ] 102 | } 103 | -------------------------------------------------------------------------------- /EDForceFeedback/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 16 | "ProductName": "SideWinder Force Feedback 2 Joystick", 17 | "AutoCenter": true, 18 | "ForceFeedbackGain": 10000, 19 | 20 | "StatusEvents": [ 21 | { 22 | "Event": "Status.Docked:True", 23 | "ForceFile": "Dock.ffe", 24 | "Duration": 2000 25 | }, 26 | { 27 | "Event": "Status.Docked:False", 28 | "ForceFile": "Dock.ffe", 29 | "Duration": 2000 30 | }, 31 | { 32 | "Event": "Status.Gear:True", 33 | "ForceFile": "Gear.ffe", 34 | "Duration": 3000 35 | }, 36 | { 37 | "Event": "Status.Gear:False", 38 | "ForceFile": "Gear.ffe", 39 | "Duration": 3000 40 | }, 41 | { 42 | "Event": "Status.Lights:True", 43 | "ForceFile": "Vibrate.ffe", 44 | "Duration": 250 45 | }, 46 | { 47 | "Event": "Status.Lights:False", 48 | "ForceFile": "Vibrate.ffe", 49 | "Duration": 250 50 | }, 51 | { 52 | "Event": "Status.Hardpoints:True", 53 | "ForceFile": "Hardpoints.ffe", 54 | "Duration": 2000 55 | }, 56 | { 57 | "Event": "Status.Hardpoints:False", 58 | "ForceFile": "Hardpoints.ffe", 59 | "Duration": 2000 60 | }, 61 | { 62 | "Event": "Status.Landed:True", 63 | "ForceFile": "Hardpoints.ffe", 64 | "Duration": 1500 65 | }, 66 | { 67 | "Event": "Status.Landed:False", 68 | "ForceFile": "Hardpoints.ffe", 69 | "Duration": 1500 70 | }, 71 | { 72 | "Event": "Status.LowFuel:True", 73 | "ForceFile": "VibrateSide.ffe", 74 | "Duration": 500 75 | }, 76 | { 77 | "Event": "Status.LowFuel:False", 78 | "ForceFile": "VibrateSide.ffe", 79 | "Duration": 500 80 | }, 81 | { 82 | "Event": "Status.CargoScoop:True", 83 | "ForceFile": "Cargo.ffe", 84 | "Duration": 2000 85 | }, 86 | { 87 | "Event": "Status.CargoScoop:False", 88 | "ForceFile": "Cargo.ffe", 89 | "Duration": 2000 90 | }, 91 | { 92 | "Event": "Status.Overheating:True", 93 | "ForceFile": "VibrateSide.ffe", 94 | "Duration": 250 95 | }, 96 | { 97 | "Event": "Status.Overheating:False", 98 | "ForceFile": "VibrateSide.ffe", 99 | "Duration": 250 100 | } 101 | ] 102 | } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /EDForceFeedback/settingsMSFFB2.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 16 | "ProductName": "SideWinder Force Feedback 2 Joystick", 17 | "AutoCenter": true, 18 | "ForceFeedbackGain": 10000, 19 | 20 | "StatusEvents": [ 21 | { 22 | "Event": "Status.Docked:True", 23 | "ForceFile": "Dock.ffe", 24 | "Duration": 2000 25 | }, 26 | { 27 | "Event": "Status.Docked:False", 28 | "ForceFile": "Dock.ffe", 29 | "Duration": 2000 30 | }, 31 | { 32 | "Event": "Status.Gear:True", 33 | "ForceFile": "Gear.ffe", 34 | "Duration": 3000 35 | }, 36 | { 37 | "Event": "Status.Gear:False", 38 | "ForceFile": "Gear.ffe", 39 | "Duration": 3000 40 | }, 41 | { 42 | "Event": "Status.Lights:True", 43 | "ForceFile": "Vibrate.ffe", 44 | "Duration": 250 45 | }, 46 | { 47 | "Event": "Status.Lights:False", 48 | "ForceFile": "Vibrate.ffe", 49 | "Duration": 250 50 | }, 51 | { 52 | "Event": "Status.Hardpoints:True", 53 | "ForceFile": "Hardpoints.ffe", 54 | "Duration": 2000 55 | }, 56 | { 57 | "Event": "Status.Hardpoints:False", 58 | "ForceFile": "Hardpoints.ffe", 59 | "Duration": 2000 60 | }, 61 | { 62 | "Event": "Status.Landed:True", 63 | "ForceFile": "Hardpoints.ffe", 64 | "Duration": 1500 65 | }, 66 | { 67 | "Event": "Status.Landed:False", 68 | "ForceFile": "Hardpoints.ffe", 69 | "Duration": 1500 70 | }, 71 | { 72 | "Event": "Status.LowFuel:True", 73 | "ForceFile": "VibrateSide.ffe", 74 | "Duration": 500 75 | }, 76 | { 77 | "Event": "Status.LowFuel:False", 78 | "ForceFile": "VibrateSide.ffe", 79 | "Duration": 500 80 | }, 81 | { 82 | "Event": "Status.CargoScoop:True", 83 | "ForceFile": "Cargo.ffe", 84 | "Duration": 2000 85 | }, 86 | { 87 | "Event": "Status.CargoScoop:False", 88 | "ForceFile": "Cargo.ffe", 89 | "Duration": 2000 90 | }, 91 | { 92 | "Event": "Status.Overheating:True", 93 | "ForceFile": "VibrateSide.ffe", 94 | "Duration": 250 95 | }, 96 | { 97 | "Event": "Status.Overheating:False", 98 | "ForceFile": "VibrateSide.ffe", 99 | "Duration": 250 100 | } 101 | ] 102 | } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /EDForceFeedback/settingsXboxAndCyborg.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | }, 101 | { 102 | "ProductGuid": "ff1206a3-0000-0000-0000-504944564944", 103 | "ProductName": "", 104 | "AutoCenter": true, 105 | "ForceFeedbackGain": 10000, 106 | 107 | "StatusEvents": [ 108 | { 109 | "Event": "Status.Docked:True", 110 | "ForceFile": "Dock.ffe", 111 | "Duration": 2000 112 | }, 113 | { 114 | "Event": "Status.Docked:False", 115 | "ForceFile": "Dock.ffe", 116 | "Duration": 2000 117 | }, 118 | { 119 | "Event": "Status.Gear:True", 120 | "ForceFile": "Gear.ffe", 121 | "Duration": 3000 122 | }, 123 | { 124 | "Event": "Status.Gear:False", 125 | "ForceFile": "Gear.ffe", 126 | "Duration": 3000 127 | }, 128 | { 129 | "Event": "Status.Lights:True", 130 | "ForceFile": "Vibrate.ffe", 131 | "Duration": 250 132 | }, 133 | { 134 | "Event": "Status.Lights:False", 135 | "ForceFile": "Vibrate.ffe", 136 | "Duration": 250 137 | }, 138 | { 139 | "Event": "Status.Hardpoints:True", 140 | "ForceFile": "Hardpoints.ffe", 141 | "Duration": 2000 142 | }, 143 | { 144 | "Event": "Status.Hardpoints:False", 145 | "ForceFile": "Hardpoints.ffe", 146 | "Duration": 2000 147 | }, 148 | { 149 | "Event": "Status.Landed:True", 150 | "ForceFile": "Hardpoints.ffe", 151 | "Duration": 1500 152 | }, 153 | { 154 | "Event": "Status.Landed:False", 155 | "ForceFile": "Hardpoints.ffe", 156 | "Duration": 1500 157 | }, 158 | { 159 | "Event": "Status.LowFuel:True", 160 | "ForceFile": "VibrateSide.ffe", 161 | "Duration": 500 162 | }, 163 | { 164 | "Event": "Status.LowFuel:False", 165 | "ForceFile": "VibrateSide.ffe", 166 | "Duration": 500 167 | }, 168 | { 169 | "Event": "Status.CargoScoop:True", 170 | "ForceFile": "Cargo.ffe", 171 | "Duration": 2000 172 | }, 173 | { 174 | "Event": "Status.CargoScoop:False", 175 | "ForceFile": "Cargo.ffe", 176 | "Duration": 2000 177 | }, 178 | { 179 | "Event": "Status.Overheating:True", 180 | "ForceFile": "VibrateSide.ffe", 181 | "Duration": 250 182 | }, 183 | { 184 | "Event": "Status.Overheating:False", 185 | "ForceFile": "VibrateSide.ffe", 186 | "Duration": 250 187 | } 188 | ] 189 | } 190 | ] 191 | } 192 | -------------------------------------------------------------------------------- /EDForceFeedback/settingsXboxAndMSFFB2.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | }, 101 | { 102 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 103 | "ProductName": "SideWinder Force Feedback 2 Joystick", 104 | "AutoCenter": true, 105 | "ForceFeedbackGain": 10000, 106 | 107 | "StatusEvents": [ 108 | { 109 | "Event": "Status.Docked:True", 110 | "ForceFile": "Dock.ffe", 111 | "Duration": 2000 112 | }, 113 | { 114 | "Event": "Status.Docked:False", 115 | "ForceFile": "Dock.ffe", 116 | "Duration": 2000 117 | }, 118 | { 119 | "Event": "Status.Gear:True", 120 | "ForceFile": "Gear.ffe", 121 | "Duration": 3000 122 | }, 123 | { 124 | "Event": "Status.Gear:False", 125 | "ForceFile": "Gear.ffe", 126 | "Duration": 3000 127 | }, 128 | { 129 | "Event": "Status.Lights:True", 130 | "ForceFile": "Vibrate.ffe", 131 | "Duration": 250 132 | }, 133 | { 134 | "Event": "Status.Lights:False", 135 | "ForceFile": "Vibrate.ffe", 136 | "Duration": 250 137 | }, 138 | { 139 | "Event": "Status.Hardpoints:True", 140 | "ForceFile": "Hardpoints.ffe", 141 | "Duration": 2000 142 | }, 143 | { 144 | "Event": "Status.Hardpoints:False", 145 | "ForceFile": "Hardpoints.ffe", 146 | "Duration": 2000 147 | }, 148 | { 149 | "Event": "Status.Landed:True", 150 | "ForceFile": "Hardpoints.ffe", 151 | "Duration": 1500 152 | }, 153 | { 154 | "Event": "Status.Landed:False", 155 | "ForceFile": "Hardpoints.ffe", 156 | "Duration": 1500 157 | }, 158 | { 159 | "Event": "Status.LowFuel:True", 160 | "ForceFile": "VibrateSide.ffe", 161 | "Duration": 500 162 | }, 163 | { 164 | "Event": "Status.LowFuel:False", 165 | "ForceFile": "VibrateSide.ffe", 166 | "Duration": 500 167 | }, 168 | { 169 | "Event": "Status.CargoScoop:True", 170 | "ForceFile": "Cargo.ffe", 171 | "Duration": 2000 172 | }, 173 | { 174 | "Event": "Status.CargoScoop:False", 175 | "ForceFile": "Cargo.ffe", 176 | "Duration": 2000 177 | }, 178 | { 179 | "Event": "Status.Overheating:True", 180 | "ForceFile": "VibrateSide.ffe", 181 | "Duration": 250 182 | }, 183 | { 184 | "Event": "Status.Overheating:False", 185 | "ForceFile": "VibrateSide.ffe", 186 | "Duration": 250 187 | } 188 | ] 189 | } 190 | ] 191 | } 192 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/EDForceFeedbackConsole.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {072E80F0-C235-44F2-B93B-747C488B490A} 9 | Exe 10 | EDForceFeedback 11 | EDForceFeedback 12 | v4.8 13 | 512 14 | true 15 | true 16 | 17 | 18 | false 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 3.1.0.%2a 31 | false 32 | true 33 | 34 | 35 | AnyCPU 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | DEBUG;TRACE 41 | prompt 42 | 4 43 | 44 | 45 | AnyCPU 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | true 53 | 54 | 55 | 56 | ..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll 57 | 58 | 59 | ..\packages\Microsoft.Extensions.Configuration.5.0.0\lib\net461\Microsoft.Extensions.Configuration.dll 60 | 61 | 62 | ..\packages\Microsoft.Extensions.Configuration.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Configuration.Abstractions.dll 63 | 64 | 65 | ..\packages\Microsoft.Extensions.Configuration.Binder.5.0.0\lib\net461\Microsoft.Extensions.Configuration.Binder.dll 66 | 67 | 68 | ..\packages\Microsoft.Extensions.Configuration.CommandLine.5.0.0\lib\net461\Microsoft.Extensions.Configuration.CommandLine.dll 69 | 70 | 71 | ..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.5.0.0\lib\net461\Microsoft.Extensions.Configuration.EnvironmentVariables.dll 72 | 73 | 74 | ..\packages\Microsoft.Extensions.Configuration.FileExtensions.5.0.0\lib\net461\Microsoft.Extensions.Configuration.FileExtensions.dll 75 | 76 | 77 | ..\packages\Microsoft.Extensions.Configuration.Json.5.0.0\lib\net461\Microsoft.Extensions.Configuration.Json.dll 78 | 79 | 80 | ..\packages\Microsoft.Extensions.Configuration.UserSecrets.5.0.0\lib\net461\Microsoft.Extensions.Configuration.UserSecrets.dll 81 | 82 | 83 | ..\packages\Microsoft.Extensions.DependencyInjection.5.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll 84 | 85 | 86 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.Abstractions.dll 87 | 88 | 89 | ..\packages\Microsoft.Extensions.FileProviders.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.FileProviders.Abstractions.dll 90 | 91 | 92 | ..\packages\Microsoft.Extensions.FileProviders.Physical.5.0.0\lib\net461\Microsoft.Extensions.FileProviders.Physical.dll 93 | 94 | 95 | ..\packages\Microsoft.Extensions.FileSystemGlobbing.5.0.0\lib\net461\Microsoft.Extensions.FileSystemGlobbing.dll 96 | 97 | 98 | ..\packages\Microsoft.Extensions.Hosting.5.0.0\lib\net461\Microsoft.Extensions.Hosting.dll 99 | 100 | 101 | ..\packages\Microsoft.Extensions.Hosting.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Hosting.Abstractions.dll 102 | 103 | 104 | ..\packages\Microsoft.Extensions.Logging.5.0.0\lib\net461\Microsoft.Extensions.Logging.dll 105 | 106 | 107 | ..\packages\Microsoft.Extensions.Logging.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll 108 | 109 | 110 | ..\packages\Microsoft.Extensions.Logging.Configuration.5.0.0\lib\net461\Microsoft.Extensions.Logging.Configuration.dll 111 | 112 | 113 | ..\packages\Microsoft.Extensions.Logging.Console.5.0.0\lib\net461\Microsoft.Extensions.Logging.Console.dll 114 | 115 | 116 | ..\packages\Microsoft.Extensions.Logging.Debug.5.0.0\lib\net461\Microsoft.Extensions.Logging.Debug.dll 117 | 118 | 119 | ..\packages\Microsoft.Extensions.Logging.EventLog.5.0.0\lib\net461\Microsoft.Extensions.Logging.EventLog.dll 120 | 121 | 122 | ..\packages\Microsoft.Extensions.Logging.EventSource.5.0.0\lib\net461\Microsoft.Extensions.Logging.EventSource.dll 123 | 124 | 125 | ..\packages\Microsoft.Extensions.Options.5.0.0\lib\net461\Microsoft.Extensions.Options.dll 126 | 127 | 128 | ..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.5.0.0\lib\net461\Microsoft.Extensions.Options.ConfigurationExtensions.dll 129 | 130 | 131 | ..\packages\Microsoft.Extensions.Primitives.5.0.1\lib\net461\Microsoft.Extensions.Primitives.dll 132 | 133 | 134 | ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll 135 | 136 | 137 | ..\packages\protobuf-net.3.0.101\lib\net461\protobuf-net.dll 138 | 139 | 140 | ..\packages\protobuf-net.Core.3.0.101\lib\net461\protobuf-net.Core.dll 141 | 142 | 143 | ..\packages\Serilog.2.5.0\lib\net46\Serilog.dll 144 | 145 | 146 | ..\packages\Serilog.Extensions.Logging.2.0.2\lib\net461\Serilog.Extensions.Logging.dll 147 | 148 | 149 | ..\packages\Serilog.Extensions.Logging.File.2.0.0\lib\net461\Serilog.Extensions.Logging.File.dll 150 | 151 | 152 | ..\packages\Serilog.Formatting.Compact.1.0.0\lib\net45\Serilog.Formatting.Compact.dll 153 | 154 | 155 | ..\packages\Serilog.Sinks.Async.1.1.0\lib\net45\Serilog.Sinks.Async.dll 156 | 157 | 158 | ..\packages\Serilog.Sinks.File.3.2.0\lib\net45\Serilog.Sinks.File.dll 159 | 160 | 161 | ..\packages\Serilog.Sinks.RollingFile.3.3.0\lib\net45\Serilog.Sinks.RollingFile.dll 162 | 163 | 164 | ..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll 165 | 166 | 167 | ..\packages\SharpDX.DirectInput.4.2.0\lib\net45\SharpDX.DirectInput.dll 168 | 169 | 170 | 171 | ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll 172 | 173 | 174 | ..\packages\System.Collections.Immutable.1.7.1\lib\net461\System.Collections.Immutable.dll 175 | 176 | 177 | 178 | 179 | 180 | ..\packages\System.Diagnostics.DiagnosticSource.5.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll 181 | 182 | 183 | ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll 184 | True 185 | True 186 | 187 | 188 | ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll 189 | 190 | 191 | 192 | ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll 193 | 194 | 195 | ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll 196 | True 197 | True 198 | 199 | 200 | ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll 201 | 202 | 203 | ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll 204 | True 205 | True 206 | 207 | 208 | ..\packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll 209 | True 210 | True 211 | 212 | 213 | ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll 214 | True 215 | True 216 | 217 | 218 | ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll 219 | True 220 | True 221 | 222 | 223 | ..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll 224 | 225 | 226 | ..\packages\System.Text.Json.5.0.0\lib\net461\System.Text.Json.dll 227 | 228 | 229 | ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll 230 | 231 | 232 | ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | Always 249 | 250 | 251 | Always 252 | 253 | 254 | Always 255 | 256 | 257 | Always 258 | 259 | 260 | Always 261 | 262 | 263 | Always 264 | 265 | 266 | Always 267 | 268 | 269 | Always 270 | 271 | 272 | Always 273 | 274 | 275 | Always 276 | 277 | 278 | Always 279 | 280 | 281 | Always 282 | 283 | 284 | Always 285 | 286 | 287 | 288 | Always 289 | 290 | 291 | Always 292 | 293 | 294 | Always 295 | 296 | 297 | Always 298 | 299 | 300 | Always 301 | 302 | 303 | 304 | 305 | {cf2e9959-f6fe-4e26-89e9-af7dfab9099e} 306 | Journals 307 | 308 | 309 | 310 | 311 | False 312 | Microsoft .NET Framework 4.8 %28x86 and x64%29 313 | true 314 | 315 | 316 | False 317 | .NET Framework 3.5 SP1 318 | false 319 | 320 | 321 | 322 | 323 | 324 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 325 | 326 | 327 | 328 | 329 | 330 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FFUtils/FFConst.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/FFUtils/FFConst.exe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FFUtils/csFeedback.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/FFUtils/csFeedback.exe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FFUtils/fedit.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/FFUtils/fedit.exe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FFUtils/pid1_01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/FFUtils/pid1_01.pdf -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 13 | 14 | 15 | 16 | 17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 18 | 19 | 20 | 21 | 22 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks. 23 | 24 | 25 | 26 | 27 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks. 28 | 29 | 30 | 31 | 32 | The order of preloaded assemblies, delimited with line breaks. 33 | 34 | 35 | 36 | 37 | 38 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. 39 | 40 | 41 | 42 | 43 | Controls if .pdbs for reference assemblies are also embedded. 44 | 45 | 46 | 47 | 48 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. 49 | 50 | 51 | 52 | 53 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. 54 | 55 | 56 | 57 | 58 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. 59 | 60 | 61 | 62 | 63 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. 64 | 65 | 66 | 67 | 68 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 69 | 70 | 71 | 72 | 73 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. 74 | 75 | 76 | 77 | 78 | A list of unmanaged 32 bit assembly names to include, delimited with |. 79 | 80 | 81 | 82 | 83 | A list of unmanaged 64 bit assembly names to include, delimited with |. 84 | 85 | 86 | 87 | 88 | The order of preloaded assemblies, delimited with |. 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 97 | 98 | 99 | 100 | 101 | A comma-separated list of error codes that can be safely ignored in assembly verification. 102 | 103 | 104 | 105 | 106 | 'false' to turn off automatic generation of the XML Schema file. 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Cargo.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Cargo.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/CenterSpringXY.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/CenterSpringXY.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Damper.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Damper.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Dock.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Dock.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Gear.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Gear.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Hardpoints.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Hardpoints.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Landed.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Landed.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/SuperCruise.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/SuperCruise.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/Vibrate.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/Vibrate.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Forces/VibrateSide.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/EDForceFeedbackConsole/Forces/VibrateSide.ffe -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using Journals; 2 | using Microsoft.Extensions.Logging; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace EDForceFeedback 12 | { 13 | static public class Program 14 | { 15 | static private async Task Main(string[] args) 16 | { 17 | var fileName = $"{Directory.GetCurrentDirectory()}\\settings.json"; 18 | 19 | // Check if a settings file was specified 20 | if (args?.Length == 1) 21 | { 22 | if (args[0].CompareTo("-h") == 0 || args[0].CompareTo("help") == 0) 23 | { 24 | Console.WriteLine("EDForceFeedBack: EDForceFeedback.exe is a console program that runs during a Elite Dangerous session."); 25 | Console.WriteLine("It watches the ED log files and responds to game events by playing a force feedback editor (.ffe) file."); 26 | Console.WriteLine(); 27 | Console.WriteLine("Usage:"); 28 | Console.WriteLine("EDForceFeedback.exe -h Output this help."); 29 | Console.WriteLine(@"EDForceFeedback.exe c:\settings.json Override the default settings file and use this instead."); 30 | Console.WriteLine($"EDForceFeedback.exe Will default to the settings file {Directory.GetCurrentDirectory()}\\settings.json"); 31 | return; 32 | } 33 | else 34 | { 35 | fileName = args[0]; 36 | } 37 | } 38 | 39 | Console.WriteLine($"Using setting file: {fileName}"); 40 | 41 | var settings = JsonConvert.DeserializeObject(File.ReadAllText(fileName)); 42 | 43 | var client = new Client(); 44 | 45 | await client.Initialize(settings).ConfigureAwait(false); 46 | 47 | while (true) 48 | await Task.Delay(5000).ConfigureAwait(false); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EDForceFeedback")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EDForceFeedback")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("072e80f0-c235-44f2-b93b-747c488b490a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Events": [ 3 | { 4 | "Event": "Gear", 5 | "ForceFile": "Gear.ffe", 6 | "Duration": 2000 7 | }, 8 | { 9 | "Event": "Dock", 10 | "ForceFile": "Gear.ffe", 11 | "Duration": 2000 12 | } 13 | 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settings.Xbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | } 101 | ] 102 | } 103 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settings.bak.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 16 | "ProductName": "SideWinder Force Feedback 2 Joystick", 17 | "AutoCenter": true, 18 | "ForceFeedbackGain": 10000, 19 | 20 | "StatusEvents": [ 21 | { 22 | "Event": "Status.Docked:True", 23 | "ForceFile": "Dock.ffe", 24 | "Duration": 2000 25 | }, 26 | { 27 | "Event": "Status.Docked:False", 28 | "ForceFile": "Dock.ffe", 29 | "Duration": 2000 30 | }, 31 | { 32 | "Event": "Status.Gear:True", 33 | "ForceFile": "Gear.ffe", 34 | "Duration": 3000 35 | }, 36 | { 37 | "Event": "Status.Gear:False", 38 | "ForceFile": "Gear.ffe", 39 | "Duration": 3000 40 | }, 41 | { 42 | "Event": "Status.Lights:True", 43 | "ForceFile": "Vibrate.ffe", 44 | "Duration": 250 45 | }, 46 | { 47 | "Event": "Status.Lights:False", 48 | "ForceFile": "Vibrate.ffe", 49 | "Duration": 250 50 | }, 51 | { 52 | "Event": "Status.Hardpoints:True", 53 | "ForceFile": "Hardpoints.ffe", 54 | "Duration": 2000 55 | }, 56 | { 57 | "Event": "Status.Hardpoints:False", 58 | "ForceFile": "Hardpoints.ffe", 59 | "Duration": 2000 60 | }, 61 | { 62 | "Event": "Status.Landed:True", 63 | "ForceFile": "Hardpoints.ffe", 64 | "Duration": 1500 65 | }, 66 | { 67 | "Event": "Status.Landed:False", 68 | "ForceFile": "Hardpoints.ffe", 69 | "Duration": 1500 70 | }, 71 | { 72 | "Event": "Status.LowFuel:True", 73 | "ForceFile": "VibrateSide.ffe", 74 | "Duration": 500 75 | }, 76 | { 77 | "Event": "Status.LowFuel:False", 78 | "ForceFile": "VibrateSide.ffe", 79 | "Duration": 500 80 | }, 81 | { 82 | "Event": "Status.CargoScoop:True", 83 | "ForceFile": "Cargo.ffe", 84 | "Duration": 2000 85 | }, 86 | { 87 | "Event": "Status.CargoScoop:False", 88 | "ForceFile": "Cargo.ffe", 89 | "Duration": 2000 90 | }, 91 | { 92 | "Event": "Status.Overheating:True", 93 | "ForceFile": "VibrateSide.ffe", 94 | "Duration": 250 95 | }, 96 | { 97 | "Event": "Status.Overheating:False", 98 | "ForceFile": "VibrateSide.ffe", 99 | "Duration": 250 100 | }, 101 | { 102 | "Event": "EliteAPI.Event.Models.SupercruiseEntryEvent", 103 | "ForceFile": "VibrateSide.ffe", 104 | "Duration": 250 105 | } 106 | ] 107 | } 108 | ] 109 | } 110 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | } 101 | ] 102 | } 103 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settingsMSFFB2.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 16 | "ProductName": "SideWinder Force Feedback 2 Joystick", 17 | "AutoCenter": true, 18 | "ForceFeedbackGain": 10000, 19 | 20 | "StatusEvents": [ 21 | { 22 | "Event": "Status.Docked:True", 23 | "ForceFile": "Dock.ffe", 24 | "Duration": 2000 25 | }, 26 | { 27 | "Event": "Status.Docked:False", 28 | "ForceFile": "Dock.ffe", 29 | "Duration": 2000 30 | }, 31 | { 32 | "Event": "Status.Gear:True", 33 | "ForceFile": "Gear.ffe", 34 | "Duration": 3000 35 | }, 36 | { 37 | "Event": "Status.Gear:False", 38 | "ForceFile": "Gear.ffe", 39 | "Duration": 3000 40 | }, 41 | { 42 | "Event": "Status.Lights:True", 43 | "ForceFile": "Vibrate.ffe", 44 | "Duration": 250 45 | }, 46 | { 47 | "Event": "Status.Lights:False", 48 | "ForceFile": "Vibrate.ffe", 49 | "Duration": 250 50 | }, 51 | { 52 | "Event": "Status.Hardpoints:True", 53 | "ForceFile": "Hardpoints.ffe", 54 | "Duration": 2000 55 | }, 56 | { 57 | "Event": "Status.Hardpoints:False", 58 | "ForceFile": "Hardpoints.ffe", 59 | "Duration": 2000 60 | }, 61 | { 62 | "Event": "Status.Landed:True", 63 | "ForceFile": "Hardpoints.ffe", 64 | "Duration": 1500 65 | }, 66 | { 67 | "Event": "Status.Landed:False", 68 | "ForceFile": "Hardpoints.ffe", 69 | "Duration": 1500 70 | }, 71 | { 72 | "Event": "Status.LowFuel:True", 73 | "ForceFile": "VibrateSide.ffe", 74 | "Duration": 500 75 | }, 76 | { 77 | "Event": "Status.LowFuel:False", 78 | "ForceFile": "VibrateSide.ffe", 79 | "Duration": 500 80 | }, 81 | { 82 | "Event": "Status.CargoScoop:True", 83 | "ForceFile": "Cargo.ffe", 84 | "Duration": 2000 85 | }, 86 | { 87 | "Event": "Status.CargoScoop:False", 88 | "ForceFile": "Cargo.ffe", 89 | "Duration": 2000 90 | }, 91 | { 92 | "Event": "Status.Overheating:True", 93 | "ForceFile": "VibrateSide.ffe", 94 | "Duration": 250 95 | }, 96 | { 97 | "Event": "Status.Overheating:False", 98 | "ForceFile": "VibrateSide.ffe", 99 | "Duration": 250 100 | } 101 | ] 102 | } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settingsXboxAndCyborg.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | }, 101 | { 102 | "ProductGuid": "ff1206a3-0000-0000-0000-504944564944", 103 | "ProductName": "", 104 | "AutoCenter": true, 105 | "ForceFeedbackGain": 10000, 106 | 107 | "StatusEvents": [ 108 | { 109 | "Event": "Status.Docked:True", 110 | "ForceFile": "Dock.ffe", 111 | "Duration": 2000 112 | }, 113 | { 114 | "Event": "Status.Docked:False", 115 | "ForceFile": "Dock.ffe", 116 | "Duration": 2000 117 | }, 118 | { 119 | "Event": "Status.Gear:True", 120 | "ForceFile": "Gear.ffe", 121 | "Duration": 3000 122 | }, 123 | { 124 | "Event": "Status.Gear:False", 125 | "ForceFile": "Gear.ffe", 126 | "Duration": 3000 127 | }, 128 | { 129 | "Event": "Status.Lights:True", 130 | "ForceFile": "Vibrate.ffe", 131 | "Duration": 250 132 | }, 133 | { 134 | "Event": "Status.Lights:False", 135 | "ForceFile": "Vibrate.ffe", 136 | "Duration": 250 137 | }, 138 | { 139 | "Event": "Status.Hardpoints:True", 140 | "ForceFile": "Hardpoints.ffe", 141 | "Duration": 2000 142 | }, 143 | { 144 | "Event": "Status.Hardpoints:False", 145 | "ForceFile": "Hardpoints.ffe", 146 | "Duration": 2000 147 | }, 148 | { 149 | "Event": "Status.Landed:True", 150 | "ForceFile": "Hardpoints.ffe", 151 | "Duration": 1500 152 | }, 153 | { 154 | "Event": "Status.Landed:False", 155 | "ForceFile": "Hardpoints.ffe", 156 | "Duration": 1500 157 | }, 158 | { 159 | "Event": "Status.LowFuel:True", 160 | "ForceFile": "VibrateSide.ffe", 161 | "Duration": 500 162 | }, 163 | { 164 | "Event": "Status.LowFuel:False", 165 | "ForceFile": "VibrateSide.ffe", 166 | "Duration": 500 167 | }, 168 | { 169 | "Event": "Status.CargoScoop:True", 170 | "ForceFile": "Cargo.ffe", 171 | "Duration": 2000 172 | }, 173 | { 174 | "Event": "Status.CargoScoop:False", 175 | "ForceFile": "Cargo.ffe", 176 | "Duration": 2000 177 | }, 178 | { 179 | "Event": "Status.Overheating:True", 180 | "ForceFile": "VibrateSide.ffe", 181 | "Duration": 250 182 | }, 183 | { 184 | "Event": "Status.Overheating:False", 185 | "ForceFile": "VibrateSide.ffe", 186 | "Duration": 250 187 | } 188 | ] 189 | } 190 | ] 191 | } 192 | -------------------------------------------------------------------------------- /EDForceFeedbackConsole/settingsXboxAndMSFFB2.json: -------------------------------------------------------------------------------- 1 | { 2 | "KnownWorkingDevices": { 3 | "NOTES": "These are the ProductGuid and ProductNames values for devices known to work with this program.", 4 | "NOTES1": "Replace the ProductGuid or ProductName value below with the device values listed here.", 5 | "NOTES2": "The device search will match on either value", 6 | "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944 ProductName = 'Controller (Xbox One For Windows)'", 7 | "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", 8 | "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", 9 | "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", 10 | "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" 11 | }, 12 | 13 | "Devices": [ 14 | { 15 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 16 | "ProductName": "Controller (Xbox One For Windows)", 17 | 18 | "StatusEvents": [ 19 | { 20 | "Event": "Status.Docked:True", 21 | "ForceFile": "Dock.ffe", 22 | "Duration": 2000 23 | }, 24 | { 25 | "Event": "Status.Docked:False", 26 | "ForceFile": "Dock.ffe", 27 | "Duration": 2000 28 | }, 29 | { 30 | "Event": "Status.Gear:True", 31 | "ForceFile": "Gear.ffe", 32 | "Duration": 3000 33 | }, 34 | { 35 | "Event": "Status.Gear:False", 36 | "ForceFile": "Gear.ffe", 37 | "Duration": 3000 38 | }, 39 | { 40 | "Event": "Status.Lights:True", 41 | "ForceFile": "Vibrate.ffe", 42 | "Duration": 250 43 | }, 44 | { 45 | "Event": "Status.Lights:False", 46 | "ForceFile": "Vibrate.ffe", 47 | "Duration": 250 48 | }, 49 | { 50 | "Event": "Status.Hardpoints:True", 51 | "ForceFile": "Hardpoints.ffe", 52 | "Duration": 2000 53 | }, 54 | { 55 | "Event": "Status.Hardpoints:False", 56 | "ForceFile": "Hardpoints.ffe", 57 | "Duration": 2000 58 | }, 59 | { 60 | "Event": "Status.Landed:True", 61 | "ForceFile": "Hardpoints.ffe", 62 | "Duration": 1500 63 | }, 64 | { 65 | "Event": "Status.Landed:False", 66 | "ForceFile": "Hardpoints.ffe", 67 | "Duration": 1500 68 | }, 69 | { 70 | "Event": "Status.LowFuel:True", 71 | "ForceFile": "VibrateSide.ffe", 72 | "Duration": 500 73 | }, 74 | { 75 | "Event": "Status.LowFuel:False", 76 | "ForceFile": "VibrateSide.ffe", 77 | "Duration": 500 78 | }, 79 | { 80 | "Event": "Status.CargoScoop:True", 81 | "ForceFile": "Cargo.ffe", 82 | "Duration": 2000 83 | }, 84 | { 85 | "Event": "Status.CargoScoop:False", 86 | "ForceFile": "Cargo.ffe", 87 | "Duration": 2000 88 | }, 89 | { 90 | "Event": "Status.Overheating:True", 91 | "ForceFile": "VibrateSide.ffe", 92 | "Duration": 250 93 | }, 94 | { 95 | "Event": "Status.Overheating:False", 96 | "ForceFile": "VibrateSide.ffe", 97 | "Duration": 250 98 | } 99 | ] 100 | }, 101 | { 102 | "ProductGuid": "001b045e-0000-0000-0000-504944564944", 103 | "ProductName": "SideWinder Force Feedback 2 Joystick", 104 | "AutoCenter": true, 105 | "ForceFeedbackGain": 10000, 106 | 107 | "StatusEvents": [ 108 | { 109 | "Event": "Status.Docked:True", 110 | "ForceFile": "Dock.ffe", 111 | "Duration": 2000 112 | }, 113 | { 114 | "Event": "Status.Docked:False", 115 | "ForceFile": "Dock.ffe", 116 | "Duration": 2000 117 | }, 118 | { 119 | "Event": "Status.Gear:True", 120 | "ForceFile": "Gear.ffe", 121 | "Duration": 3000 122 | }, 123 | { 124 | "Event": "Status.Gear:False", 125 | "ForceFile": "Gear.ffe", 126 | "Duration": 3000 127 | }, 128 | { 129 | "Event": "Status.Lights:True", 130 | "ForceFile": "Vibrate.ffe", 131 | "Duration": 250 132 | }, 133 | { 134 | "Event": "Status.Lights:False", 135 | "ForceFile": "Vibrate.ffe", 136 | "Duration": 250 137 | }, 138 | { 139 | "Event": "Status.Hardpoints:True", 140 | "ForceFile": "Hardpoints.ffe", 141 | "Duration": 2000 142 | }, 143 | { 144 | "Event": "Status.Hardpoints:False", 145 | "ForceFile": "Hardpoints.ffe", 146 | "Duration": 2000 147 | }, 148 | { 149 | "Event": "Status.Landed:True", 150 | "ForceFile": "Hardpoints.ffe", 151 | "Duration": 1500 152 | }, 153 | { 154 | "Event": "Status.Landed:False", 155 | "ForceFile": "Hardpoints.ffe", 156 | "Duration": 1500 157 | }, 158 | { 159 | "Event": "Status.LowFuel:True", 160 | "ForceFile": "VibrateSide.ffe", 161 | "Duration": 500 162 | }, 163 | { 164 | "Event": "Status.LowFuel:False", 165 | "ForceFile": "VibrateSide.ffe", 166 | "Duration": 500 167 | }, 168 | { 169 | "Event": "Status.CargoScoop:True", 170 | "ForceFile": "Cargo.ffe", 171 | "Duration": 2000 172 | }, 173 | { 174 | "Event": "Status.CargoScoop:False", 175 | "ForceFile": "Cargo.ffe", 176 | "Duration": 2000 177 | }, 178 | { 179 | "Event": "Status.Overheating:True", 180 | "ForceFile": "VibrateSide.ffe", 181 | "Duration": 250 182 | }, 183 | { 184 | "Event": "Status.Overheating:False", 185 | "ForceFile": "VibrateSide.ffe", 186 | "Duration": 250 187 | } 188 | ] 189 | } 190 | ] 191 | } 192 | -------------------------------------------------------------------------------- /ForceFeedback.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/ForceFeedback.PNG -------------------------------------------------------------------------------- /ForceFeedbackSharpDx/ForceFeedbackController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using SharpDX; 3 | using SharpDX.DirectInput; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Threading.Tasks; 8 | 9 | namespace ForceFeedbackSharpDx 10 | { 11 | public class ForceFeedbackController : IDisposable 12 | { 13 | private const uint WINDOW_HANDLE_ERROR = 0x80070006; 14 | 15 | private Joystick joystick = null; 16 | private DirectInput directInput = null; 17 | private readonly Dictionary knownEffects = new Dictionary(); 18 | private readonly Dictionary> fileEffects = new Dictionary>(); 19 | public ILogger Logger { get; set; } 20 | 21 | public String StatusText; 22 | 23 | public bool Initialize( 24 | string productGuid, 25 | string productName, 26 | string forceFilesFolder, 27 | bool autoCenter, 28 | int forceFeedbackGain, 29 | int deadzone = 0, 30 | int saturation = 10000) 31 | { 32 | // Initialize DirectInput 33 | if (directInput != null) 34 | { 35 | directInput.Dispose(); 36 | directInput = null; 37 | } 38 | 39 | directInput = new DirectInput(); 40 | 41 | var product = new Guid(productGuid); 42 | 43 | // Find a Joystick Guid 44 | var joystickGuid = Guid.Empty; 45 | var joystickName = String.Empty; 46 | 47 | var directInputDevices = new List(); 48 | 49 | directInputDevices.AddRange(directInput.GetDevices()); 50 | 51 | // Filtered 52 | //directInputDevices.AddRange(directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices)); 53 | //directInputDevices.AddRange(directInput.GetDevices(DeviceType.Gamepad, DeviceEnumerationFlags.AllDevices)); 54 | //directInputDevices.AddRange(directInput.GetDevices(DeviceType.Driving, DeviceEnumerationFlags.AllDevices)); 55 | 56 | foreach (var deviceInstance in directInputDevices) 57 | { 58 | Logger?.LogDebug($"DeviceName: {deviceInstance.ProductName}: ProductGuid {deviceInstance.ProductGuid}"); 59 | 60 | if (deviceInstance.ProductGuid == product || deviceInstance.ProductName == productName) 61 | { 62 | joystickGuid = deviceInstance.InstanceGuid; 63 | joystickName = deviceInstance.ProductName; 64 | break; 65 | } 66 | } 67 | 68 | // If Joystick not found, throws an error 69 | if (joystickGuid == Guid.Empty) 70 | { 71 | Logger?.LogDebug("No matching Joystick/Gamepad/Wheel found. {deviceInstance.ProductName} {productGuid}"); 72 | return false; 73 | } 74 | 75 | // Instantiate the joystick 76 | joystick = new Joystick(directInput, joystickGuid); 77 | 78 | Logger?.LogDebug("Found Joystick/Gamepad {0}", joystickName); 79 | 80 | // Query all suported ForceFeedback effects 81 | var allEffects = joystick.GetEffects(); 82 | foreach (var effectInfo in allEffects) 83 | { 84 | knownEffects.Add(effectInfo.Name, effectInfo); 85 | Logger?.LogDebug("Effect available {0}", effectInfo.Name); 86 | } 87 | 88 | // Load all of the effect files 89 | var forcesFolder = new DirectoryInfo(forceFilesFolder); 90 | 91 | foreach (var file in forcesFolder.GetFiles("*.ffe")) 92 | { 93 | var effectsFromFile = joystick.GetEffectsInFile(file.FullName, EffectFileFlags.ModidyIfNeeded); 94 | fileEffects.Add(file.Name.Trim().ToLower(), new List(effectsFromFile)); 95 | Logger?.LogDebug($"File Effect available {file.Name}"); 96 | } 97 | 98 | // Set BufferSize in order to use buffered data. 99 | joystick.Properties.BufferSize = 128; 100 | 101 | // DirectX requires a window handle to set the CooperativeLevel 102 | var handle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; 103 | 104 | try 105 | { 106 | // Exclusive is required to control the forces 107 | joystick.SetCooperativeLevel(handle, CooperativeLevel.Exclusive | CooperativeLevel.Background); 108 | } 109 | catch (SharpDX.SharpDXException ex) when ((uint)ex.HResult == WINDOW_HANDLE_ERROR) 110 | { 111 | Logger?.LogDebug(" Unable to access window handle. Do not run EDForceFeedback.exe in a console window."); 112 | StatusText = "Unable to access window handle"; 113 | return false; 114 | } 115 | 116 | try 117 | { 118 | // Autocenter: For the MSFF2 joystick this value is a spring force that plays in the background. 119 | // If all effects are stopped. The spring will stop too. Reset will turn it back on. 120 | joystick.Properties.AutoCenter = autoCenter; 121 | } 122 | catch (SharpDXException) 123 | { 124 | // Some devices do not support this setting. 125 | } 126 | 127 | // Acquire the joystick 128 | joystick.Acquire(); 129 | 130 | SetActuators(true); 131 | 132 | joystick.Properties.DeadZone = deadzone; 133 | joystick.Properties.Saturation = saturation; 134 | joystick.Properties.ForceFeedbackGain = forceFeedbackGain; 135 | 136 | StatusText = $"{joystickName}: Aquired"; 137 | 138 | return true; 139 | } 140 | 141 | private void PlayEffect(Effect effect) 142 | { 143 | // See if our effects are playing. If not play them 144 | if (effect.Status != EffectStatus.Playing) 145 | { 146 | Logger?.LogDebug($"Effect {effect.Guid} starting"); 147 | effect.Start(1, EffectPlayFlags.NoDownload); 148 | } 149 | } 150 | 151 | public void PlayEffects(IEnumerable effects) 152 | { 153 | foreach (var effect in effects) 154 | PlayEffect(effect); 155 | } 156 | 157 | /// 158 | /// Stop any effects that were started from the PlayFileEffect() method. 159 | /// 160 | /// 161 | public void StopEffects(IEnumerable effects, bool dispose = true) 162 | { 163 | if (effects == null) 164 | return; 165 | 166 | foreach (var effect in effects) 167 | { 168 | try { effect.Stop(); } 169 | catch (SharpDXException) { } 170 | } 171 | 172 | if (dispose) 173 | { 174 | foreach (var effect in effects) 175 | effect?.Dispose(); 176 | } 177 | 178 | //Reset(); // This will kill all effects 179 | } 180 | 181 | /// 182 | /// Stop all effects. Reset to Default. Note: This reenables the center spring if autocenter is set. 183 | /// 184 | public void Reset() 185 | { 186 | joystick.SendForceFeedbackCommand(ForceFeedbackCommand.Reset); 187 | } 188 | 189 | /// 190 | /// Stop all effects. Note: This will disable the autocenter effect. To reenable call Reset(). 191 | /// 192 | public void StopAllEffects() 193 | { 194 | joystick.SendForceFeedbackCommand(ForceFeedbackCommand.StopAll); 195 | } 196 | 197 | /// 198 | /// Set the actuators on/off 199 | /// 200 | public void SetActuators(bool on = true) 201 | { 202 | try 203 | { 204 | if (on) 205 | joystick.SendForceFeedbackCommand(ForceFeedbackCommand.SetActuatorsOn); 206 | else 207 | joystick.SendForceFeedbackCommand(ForceFeedbackCommand.SetActuatorsOff); 208 | } 209 | catch(Exception ex) 210 | { 211 | Logger?.LogError($"Exception {ex.Message}"); 212 | } 213 | } 214 | 215 | /// 216 | /// Returns the effects in the effect file. Caller must dispose of the object when completed. 217 | /// 218 | /// 219 | /// 220 | public List GetEffectFromFile(string name) 221 | { 222 | try 223 | { 224 | var fileEffect = fileEffects[name.Trim().ToLower()]; 225 | 226 | // Create a new List<> of effects 227 | return fileEffect.ConvertAll(x => new Effect(joystick, x.Guid, x.Parameters)); 228 | } 229 | catch (KeyNotFoundException ex) 230 | { 231 | Logger?.LogError($"GetEffectFromFile Key: '{name}' Not Found Exception", ex); 232 | } 233 | catch (Exception ex) 234 | { 235 | Logger?.LogError("GetEffectFromFile Exception", ex); 236 | } 237 | return null; 238 | } 239 | 240 | /// 241 | /// Copy the effect file and begin playing it. If the duration is greater than zero the effect will play for that many milliseconds 242 | /// and then be stopped. 243 | /// 244 | /// Effect file name 245 | /// Zero and below will play until stopped. Above zero will play for that many milliseconds. Default: 250. 246 | /// The effects being played as a List or null if the effect file was not found. 247 | public List PlayFileEffect(string name, int duration = 250) 248 | { 249 | try 250 | { 251 | var fileEffect = fileEffects[name.Trim().ToLower()]; 252 | 253 | // Create a new List<> of effects 254 | var forceEffects = fileEffect.ConvertAll(x => new Effect(joystick, x.Guid, x.Parameters)); 255 | 256 | _ = Task.Run(async () => 257 | { 258 | PlayEffects(forceEffects); 259 | if (duration > 0) 260 | { 261 | await Task.Delay(duration).ConfigureAwait(false); 262 | StopEffects(forceEffects); 263 | } 264 | else 265 | { 266 | // Wait a moment, effects don't seem to play if we exit fast 267 | await Task.Delay(100).ConfigureAwait(false); 268 | } 269 | }).ContinueWith(t => 270 | { 271 | if (t.IsCanceled) Logger?.LogDebug($"Effect {name} cancelled"); 272 | else if (t.IsFaulted) Logger?.LogDebug($"Effect {name} Exception {t.Exception.InnerException?.Message}"); 273 | else Logger?.LogDebug($"Effect {name} complete"); 274 | }); 275 | 276 | return forceEffects; 277 | } 278 | catch(KeyNotFoundException ex) 279 | { 280 | Logger?.LogError($"PlayFileEffect Key: '{name}' Not Found Exception", ex); 281 | } 282 | catch (Exception ex) 283 | { 284 | Logger?.LogError("PlayFileEffect Exception", ex); 285 | } 286 | 287 | return null; 288 | } 289 | 290 | public void Dispose() 291 | { 292 | joystick?.Unacquire(); 293 | joystick?.Dispose(); 294 | joystick = null; 295 | directInput?.Dispose(); 296 | directInput = null; 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /ForceFeedbackSharpDx/ForceFeedbackSharpDx.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | d3981932-571e-4587-9ab1-a84feafe7953 6 | x86 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Journals/Client.cs: -------------------------------------------------------------------------------- 1 | using ForceFeedbackSharpDx; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace Journals 10 | { 11 | public class Client 12 | { 13 | private EliteAPI.Abstractions.IEliteDangerousApi eliteAPI; 14 | //private IShip ship; 15 | private ILogger logger; 16 | private IHost host; 17 | 18 | private readonly List Devices = new List(); 19 | 20 | public async Task Initialize(Settings settings) 21 | { 22 | // Inject the logger and EliteApi services into host 23 | host = Host.CreateDefaultBuilder() 24 | .ConfigureServices((context, service) => 25 | { 26 | service.AddEliteApi(); 27 | service.AddTransient(); 28 | service.AddLogging(builder => 29 | builder.AddSimpleConsole(options => { options.SingleLine = true; options.TimestampFormat = "hh:mm:ss "; }).SetMinimumLevel(LogLevel.Debug)); 30 | }) 31 | .Build(); 32 | 33 | // Get the services from the Host object 34 | eliteAPI = host.Services.GetService(); 35 | //ship = host.Services.GetService(); 36 | logger = host.Services.GetRequiredService>(); 37 | 38 | foreach (var device in settings.Devices) 39 | { 40 | var ffDevice = new ForceFeedbackController() { Logger = logger }; 41 | if (ffDevice.Initialize( 42 | device.ProductGuid, 43 | device.ProductName, 44 | @".\Forces", 45 | device.AutoCenter, 46 | device.ForceFeedbackGain) == false) 47 | { 48 | logger.LogError($"Device Initialization failed: {device.ProductGuid}: {device.ProductName}"); 49 | continue; 50 | } 51 | 52 | var deviceEvents = new DeviceEvents 53 | { 54 | EventSettings = device.StatusEvents.ToDictionary(v => v.Event, v => v), 55 | Device = ffDevice 56 | }; 57 | 58 | Devices.Add(deviceEvents); 59 | } 60 | 61 | // Start the api 62 | await eliteAPI.StartAsync().ConfigureAwait(false); 63 | 64 | eliteAPI.Events.OnAny( e => Events_AllEvent(e)); 65 | 66 | eliteAPI.Events.On(e => FindEffect($"Status.Docked:{e.Value}")); 67 | eliteAPI.Events.On(e => FindEffect($"Status.Landed:{e.Value}")); 68 | 69 | eliteAPI.Events.On(e => ShipStatusEvent(e)); 70 | 71 | //ship.Gear.OnChange += (obj, eventArgs) => FindEffect($"Status.Gear:{eventArgs}"); 72 | //ship.Shields.OnChange += (obj, eventArgs) => FindEffect($"Status.Shields:{eventArgs}"); 73 | //ship.Supercruise.OnChange += (obj, eventArgs) => FindEffect($"Status.Supercruise:{eventArgs}"); 74 | //ship.FlightAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.FlightAssist:{eventArgs}"); 75 | //ship.Hardpoints.OnChange += (obj, eventArgs) => FindEffect($"Status.Hardpoints:{eventArgs}"); 76 | //ship.Winging.OnChange += (obj, eventArgs) => FindEffect($"Status.Winging:{eventArgs}"); 77 | //ship.Lights.OnChange += (obj, eventArgs) => FindEffect($"Status.Lights:{eventArgs}"); 78 | //ship.CargoScoop.OnChange += (obj, eventArgs) => FindEffect($"Status.CargoScoop:{eventArgs}"); 79 | //ship.SilentRunning.OnChange += (obj, eventArgs) => FindEffect($"Status.SilentRunning:{eventArgs}"); 80 | //ship.Scooping.OnChange += (obj, eventArgs) => FindEffect($"Status.Scooping:{eventArgs}"); 81 | //ship.SrvHandbreak.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHandbreak:{eventArgs}"); 82 | //ship.SrvTurrent.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvTurrent:{eventArgs}"); 83 | //ship.SrvNearShip.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvNearShip:{eventArgs}"); 84 | //ship.SrvDriveAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvDriveAssist:{eventArgs}"); 85 | //ship.MassLocked.OnChange += (obj, eventArgs) => FindEffect($"Status.MassLocked:{eventArgs}"); 86 | //ship.FsdCharging.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCharging:{eventArgs}"); 87 | //ship.FsdCooldown.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCooldown:{eventArgs}"); 88 | //ship.LowFuel.OnChange += (obj, eventArgs) => FindEffect($"Status.LowFuel:{eventArgs}"); 89 | //ship.Overheating.OnChange += (obj, eventArgs) => FindEffect($"Status.Overheating:{eventArgs}"); 90 | //ship.HasLatLong.OnChange += (obj, eventArgs) => FindEffect($"Status.HasLatLong:{eventArgs}"); 91 | //ship.InDanger.OnChange += (obj, eventArgs) => FindEffect($"Status.InDanger:{eventArgs}"); 92 | //ship.InInterdiction.OnChange += (obj, eventArgs) => FindEffect($"Status.InInterdiction:{eventArgs}"); 93 | //ship.InMothership.OnChange += (obj, eventArgs) => FindEffect($"Status.InMothership:{eventArgs}"); 94 | //ship.InFighter.OnChange += (obj, eventArgs) => FindEffect($"Status.InFighter:{eventArgs}"); 95 | //ship.InSrv.OnChange += (obj, eventArgs) => FindEffect($"Status.InSrv:{eventArgs}"); 96 | //ship.AnalysisMode.OnChange += (obj, eventArgs) => FindEffect($"Status.AnalysisMode:{eventArgs}"); 97 | //ship.NightVision.OnChange += (obj, eventArgs) => FindEffect($"Status.NightVision:{eventArgs}"); 98 | //ship.AltitudeFromAverageRadius.OnChange += (obj, eventArgs) => FindEffect($"Status.AltitudeFromAverageRadius:{eventArgs}"); 99 | //ship.FsdJump.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdJump:{eventArgs}"); 100 | //ship.SrvHighBeam.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHighBeam:{eventArgs}"); 101 | 102 | 103 | //ship.Docked.OnChange += (obj, eventArgs) => FindEffect($"Status.Docked:{eventArgs}"); 104 | //ship.Landed.OnChange += (obj, eventArgs) => FindEffect($"Status.Landed:{eventArgs}"); 105 | //ship.Gear.OnChange += (obj, eventArgs) => FindEffect($"Status.Gear:{eventArgs}"); 106 | //ship.Shields.OnChange += (obj, eventArgs) => FindEffect($"Status.Shields:{eventArgs}"); 107 | //ship.Supercruise.OnChange += (obj, eventArgs) => FindEffect($"Status.Supercruise:{eventArgs}"); 108 | //ship.FlightAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.FlightAssist:{eventArgs}"); 109 | //ship.Hardpoints.OnChange += (obj, eventArgs) => FindEffect($"Status.Hardpoints:{eventArgs}"); 110 | //ship.Winging.OnChange += (obj, eventArgs) => FindEffect($"Status.Winging:{eventArgs}"); 111 | //ship.Lights.OnChange += (obj, eventArgs) => FindEffect($"Status.Lights:{eventArgs}"); 112 | //ship.CargoScoop.OnChange += (obj, eventArgs) => FindEffect($"Status.CargoScoop:{eventArgs}"); 113 | //ship.SilentRunning.OnChange += (obj, eventArgs) => FindEffect($"Status.SilentRunning:{eventArgs}"); 114 | //ship.Scooping.OnChange += (obj, eventArgs) => FindEffect($"Status.Scooping:{eventArgs}"); 115 | //ship.SrvHandbreak.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHandbreak:{eventArgs}"); 116 | //ship.SrvTurrent.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvTurrent:{eventArgs}"); 117 | //ship.SrvNearShip.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvNearShip:{eventArgs}"); 118 | //ship.SrvDriveAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvDriveAssist:{eventArgs}"); 119 | //ship.MassLocked.OnChange += (obj, eventArgs) => FindEffect($"Status.MassLocked:{eventArgs}"); 120 | //ship.FsdCharging.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCharging:{eventArgs}"); 121 | //ship.FsdCooldown.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCooldown:{eventArgs}"); 122 | //ship.LowFuel.OnChange += (obj, eventArgs) => FindEffect($"Status.LowFuel:{eventArgs}"); 123 | //ship.Overheating.OnChange += (obj, eventArgs) => FindEffect($"Status.Overheating:{eventArgs}"); 124 | //ship.HasLatLong.OnChange += (obj, eventArgs) => FindEffect($"Status.HasLatLong:{eventArgs}"); 125 | //ship.InDanger.OnChange += (obj, eventArgs) => FindEffect($"Status.InDanger:{eventArgs}"); 126 | //ship.InInterdiction.OnChange += (obj, eventArgs) => FindEffect($"Status.InInterdiction:{eventArgs}"); 127 | //ship.InMothership.OnChange += (obj, eventArgs) => FindEffect($"Status.InMothership:{eventArgs}"); 128 | //ship.InFighter.OnChange += (obj, eventArgs) => FindEffect($"Status.InFighter:{eventArgs}"); 129 | //ship.InSrv.OnChange += (obj, eventArgs) => FindEffect($"Status.InSrv:{eventArgs}"); 130 | //ship.AnalysisMode.OnChange += (obj, eventArgs) => FindEffect($"Status.AnalysisMode:{eventArgs}"); 131 | //ship.NightVision.OnChange += (obj, eventArgs) => FindEffect($"Status.NightVision:{eventArgs}"); 132 | //ship.AltitudeFromAverageRadius.OnChange += (obj, eventArgs) => FindEffect($"Status.AltitudeFromAverageRadius:{eventArgs}"); 133 | //ship.FsdJump.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdJump:{eventArgs}"); 134 | //ship.SrvHighBeam.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHighBeam:{eventArgs}"); 135 | } 136 | 137 | private void ShipStatusEvent(dynamic e) 138 | { 139 | logger.LogDebug($"Event {e}"); 140 | } 141 | 142 | private void Events_AllEvent(dynamic e) 143 | { 144 | var eventKey = e.ToString(); 145 | FindEffect(eventKey); 146 | } 147 | 148 | private void FindEffect(string eventKey) 149 | { 150 | logger.LogDebug($"Event {eventKey}"); 151 | 152 | foreach (var device in Devices) 153 | { 154 | if (device.EventSettings.ContainsKey(eventKey)) 155 | { 156 | var eventConfig = device.EventSettings[eventKey]; 157 | var result = device.Device?.PlayFileEffect(eventConfig.ForceFile, eventConfig.Duration); 158 | } 159 | } 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Journals/Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Journals 6 | { 7 | public class Device 8 | { 9 | public string ProductGuid { get; set; } 10 | public string ProductName { get; set; } 11 | public bool AutoCenter { get; set; } = true; 12 | public int ForceFeedbackGain { get; set; } = 10000; 13 | public List StatusEvents { get; set; } = new List(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Journals/DeviceEvents.cs: -------------------------------------------------------------------------------- 1 | using ForceFeedbackSharpDx; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Journals 7 | { 8 | public class DeviceEvents 9 | { 10 | public ForceFeedbackController Device { get; set; } 11 | public Dictionary EventSettings { get; set; } = new Dictionary(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Journals/EventConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Journals 6 | { 7 | public class EventConfiguration 8 | { 9 | public string Event { get; set; } 10 | public string ForceFile { get; set; } 11 | public int Duration { get; set; } = 250; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Journals/Journals.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Journals/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Journals 6 | { 7 | public class Settings 8 | { 9 | public List Devices { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 bobhelander 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EDForceFeedback 2 | Elite Dangerous Force Feedback with a Microsoft Force Feedback 2 Joystick (MSFFB2) 3 | 4 | ### Description 5 | EDForceFeedback.exe is a console program that runs during a Elite Dangerous session. It watches the ED log files and responds to game events by playing a force feedback editor (.ffe) file. 6 | 7 | It has been tested with the following devices: 8 | 9 | [Microsoft XBox One Controller](https://en.wikipedia.org/wiki/Xbox_One_controller) running the [XInput modification](https://steamcommunity.com/discussions/forum/1/541907867790900215/) 10 | 11 | [Microsoft Sidewinder Force Feedback 2](https://en.wikipedia.org/wiki/Microsoft_SideWinder#Force_Feedback_2) joystick. 12 | 13 | [Saitek Cyborg 3D Force Stick](https://www.yumpu.com/en/document/view/38049421/cyborg-force-manualqxd-saitekcom) 14 | 15 | ### Usage 16 | 1. Connect your joystick/gamepad and run the EDForceFeedback.exe program. 17 | 2. Start Elite Dangerous 18 | 3. In-game events like deploy/retract hardpoints and deploy/retract landing gear will send the configured forces to the joystick. 19 | 20 | ### Configuration 21 | 22 | The `settings.json` file contains the device and the forces that will be played when an event occurs. Multiple different devices can be configured with different effects for each device. 23 | 24 | Included in the package are several different examples of different configurations. 25 | 26 | ###### Devices 27 | 28 | 29 | "Devices": [ 30 | { 31 | "ProductGuid": "02dd045e-0000-0000-0000-504944564944", 32 | "ProductName": "Controller (Xbox One For Windows)", 33 | 34 | "StatusEvents": [ 35 | ... 36 | 37 | Each device and the configured effects for the device has it's own section. If the device guid or product name are unknown, you may attempt to use the values the program outputs for the connected devices while it is initializing. 38 | 39 | ###### ProductGuid & ProductName 40 | 41 | Both values are searched against the list during initialization. If either is found the device is selected. 42 | 43 | ###### Autocenter 44 | 45 | The Microsoft Force Feedback device sometimes turns off the autocenter value after playing an effect. Setting this value to true, resets the centering spring. 46 | 47 | ###### ForceFeedbackGain 48 | 49 | This value is the strenth of the effects. The valid range is 0-10000. 50 | 51 | ###### StatusEvents 52 | 53 | Each event can have a different force played for the on or off state. The on/off state for the "Docked" event is the following events "Status.Docked:True" happens when the ship is docked and "Status.Docked:False" happens when the ship takes off. 54 | 55 | { 56 | "Event": "Status.Docked:True", 57 | "ForceFile": "Dock.ffe", 58 | "Duration": 2000 59 | } 60 | 61 | ###### Event 62 | The `"Event"` Field
63 | The [EliteAPI](https://github.com/EliteAPI/EliteAPI) StatusEvent name and state to respond to.
64 | The format is: Status.*StatusEventName*:*[True or False]* 65 | 66 | ###### ForceFile 67 | The `"ForceFile"` Field
68 | The name of the force file (.ffe) to play when this event is detected. The force files can be found under the .\Forces folder. There is a force file editor included under the .\FFUtils folder. See the *Creating And Editing* forces section for more information. 69 | 70 | ###### Duration 71 | The `"Duration"` Field
72 | This is how long the force will be played. The value is in milliseconds (1 Second = 1000 milliseconds). The forces will be stopped after this amount of time even if the .ffe file is configured to play longer. 73 | 74 | ##### Additional Events 75 | The `settings.json` [json](https://www.json.org/) file only has a few of the status events defined. Additional status events are provided by the [EliteAPI](https://github.com/EliteAPI/EliteAPI) and can be added to the `StatusEvents` array in the settings file. During game play, the console window will output the names of the events that were detected. You can use these names to add additional forces. 76 | 77 | ### Creating and Editing Forces 78 | On startup all .ffe files in the .\Forces folder will be loaded. To create new forces use `fedit.exe` and save the file in the .\Forces folder. 79 | 80 | ###### .\FFUtils 81 | These are Microsoft utilities to edit and configure force feedback devices. They may get removed from this location. They can be found in various locations on the internet. They were part of the DirectX DirectInput developer packages. 82 | 83 | csFeedback.exe 84 | fedit.exe 85 | FFConst.exe 86 | 87 | ###### fedit.exe 88 | This utility allows you to build your own custom forces. For an example, open the Cargo.ffe file. The forces can overlay and played before, after, and simultaneously to create complex movement and effects.
89 | 90 | Enjoy! - Bob (CMDR Axe_) 91 | -------------------------------------------------------------------------------- /TestForceFeedback/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /TestForceFeedback/EliteAPIMock.cs: -------------------------------------------------------------------------------- 1 | using EliteAPI.Abstractions; 2 | using EliteAPI.Options.Bindings.Models; 3 | using EliteAPI.Status.Backpack.Abstractions; 4 | using EliteAPI.Status.Cargo.Abstractions; 5 | using EliteAPI.Status.Commander.Abstractions; 6 | using EliteAPI.Status.Market.Abstractions; 7 | using EliteAPI.Status.Modules.Abstractions; 8 | using EliteAPI.Status.NavRoute.Abstractions; 9 | using EliteAPI.Status.Outfitting.Abstractions; 10 | using EliteAPI.Status.Ship.Abstractions; 11 | using EliteAPI.Status.Shipyard.Abstractions; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Linq; 15 | using System.Text; 16 | using System.Threading.Tasks; 17 | 18 | namespace TestForceFeedback 19 | { 20 | public class EliteAPIMock : IEliteDangerousApi 21 | { 22 | public string Version => throw new NotImplementedException(); 23 | 24 | public EliteAPI.Event.Handler.EventHandler Events => throw new NotImplementedException(); 25 | 26 | public IShip Ship => throw new NotImplementedException(); 27 | 28 | public ICommander Commander => throw new NotImplementedException(); 29 | 30 | public IBackpack Backpack => throw new NotImplementedException(); 31 | 32 | public IShipyard Shipyard => throw new NotImplementedException(); 33 | 34 | public INavRoute NavRoute => throw new NotImplementedException(); 35 | 36 | public ICargo Cargo => throw new NotImplementedException(); 37 | 38 | public IMarket Market => throw new NotImplementedException(); 39 | 40 | public IModules Modules => throw new NotImplementedException(); 41 | 42 | public IOutfitting Outfitting => throw new NotImplementedException(); 43 | 44 | public IBindings Bindings => throw new NotImplementedException(); 45 | 46 | public bool IsInitialized => throw new NotImplementedException(); 47 | 48 | public bool IsRunning => throw new NotImplementedException(); 49 | 50 | public bool HasCatchedUp => throw new NotImplementedException(); 51 | 52 | public event System.EventHandler OnCatchedUp; 53 | public event System.EventHandler OnStart; 54 | public event System.EventHandler OnStop; 55 | public event EventHandler OnError; 56 | 57 | public Task InitializeAsync() 58 | { 59 | throw new NotImplementedException(); 60 | } 61 | 62 | public Task StartAsync() 63 | { 64 | throw new NotImplementedException(); 65 | } 66 | 67 | public Task StopAsync() 68 | { 69 | throw new NotImplementedException(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /TestForceFeedback/EliteShipMock.cs: -------------------------------------------------------------------------------- 1 | using EliteAPI.Status; 2 | using EliteAPI.Status.Abstractions; 3 | using EliteAPI.Status.Ship; 4 | using EliteAPI.Status.Ship.Abstractions; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace TestForceFeedback 12 | { 13 | public class EliteShipMock : EliteStatusMock, IShip 14 | { 15 | /// 16 | public StatusProperty Available { get; } = new StatusProperty(false); 17 | 18 | /// 19 | public StatusProperty Docked { get; } = new StatusProperty(false); 20 | 21 | /// 22 | public StatusProperty Landed { get; } = new StatusProperty(false); 23 | 24 | /// 25 | public StatusProperty Gear { get; } = new StatusProperty(false); 26 | 27 | /// 28 | public StatusProperty Shields { get; } = new StatusProperty(false); 29 | 30 | /// 31 | public StatusProperty Supercruise { get; } = new StatusProperty(false); 32 | /// 33 | public StatusProperty FlightAssist { get; } = new StatusProperty(false); 34 | 35 | /// 36 | public StatusProperty Hardpoints { get; } = new StatusProperty(false); 37 | 38 | /// 39 | public StatusProperty Winging { get; } = new StatusProperty(false); 40 | 41 | /// 42 | public StatusProperty Lights { get; } = new StatusProperty(false); 43 | 44 | /// 45 | public StatusProperty CargoScoop { get; } = new StatusProperty(false); 46 | 47 | /// 48 | public StatusProperty SilentRunning { get; } = new StatusProperty(false); 49 | 50 | /// 51 | public StatusProperty Scooping { get; } = new StatusProperty(false); 52 | 53 | /// 54 | public StatusProperty SrvHandbreak { get; } = new StatusProperty(false); 55 | 56 | /// 57 | public StatusProperty SrvTurrent { get; } = new StatusProperty(false); 58 | 59 | /// 60 | public StatusProperty SrvNearShip { get; } = new StatusProperty(false); 61 | 62 | /// 63 | public StatusProperty SrvDriveAssist { get; } = new StatusProperty(false); 64 | 65 | /// 66 | public StatusProperty MassLocked { get; } = new StatusProperty(false); 67 | 68 | /// 69 | public StatusProperty FsdCharging { get; } = new StatusProperty(false); 70 | 71 | /// 72 | public StatusProperty FsdCooldown { get; } = new StatusProperty(false); 73 | 74 | /// 75 | public StatusProperty LowFuel { get; } = new StatusProperty(false); 76 | 77 | /// 78 | public StatusProperty Overheating { get; } = new StatusProperty(false); 79 | 80 | /// 81 | public StatusProperty HasLatLong { get; } = new StatusProperty(false); 82 | 83 | /// 84 | public StatusProperty InDanger { get; } = new StatusProperty(false); 85 | 86 | /// 87 | public StatusProperty InInterdiction { get; } = new StatusProperty(false); 88 | 89 | /// 90 | public StatusProperty InMothership { get; } = new StatusProperty(false); 91 | 92 | /// 93 | public StatusProperty InFighter { get; } = new StatusProperty(false); 94 | 95 | /// 96 | public StatusProperty InSrv { get; } = new StatusProperty(false); 97 | 98 | /// 99 | public StatusProperty AnalysisMode { get; } = new StatusProperty(false); 100 | 101 | /// 102 | public StatusProperty NightVision { get; } = new StatusProperty(false); 103 | 104 | /// 105 | public StatusProperty AltitudeFromAverageRadius { get; } = new StatusProperty(false); 106 | 107 | /// 108 | public StatusProperty FsdJump { get; } = new StatusProperty(false); 109 | 110 | /// 111 | public StatusProperty SrvHighBeam { get; } = new StatusProperty(false); 112 | 113 | public StatusProperty Flags => throw new NotImplementedException(); 114 | 115 | public StatusProperty Pips => throw new NotImplementedException(); 116 | 117 | public StatusProperty FireGroup => throw new NotImplementedException(); 118 | 119 | public StatusProperty GuiFocus => throw new NotImplementedException(); 120 | 121 | public StatusProperty Fuel => throw new NotImplementedException(); 122 | 123 | public StatusProperty Cargo => throw new NotImplementedException(); 124 | 125 | public StatusProperty LegalState => throw new NotImplementedException(); 126 | 127 | public StatusProperty Latitude => throw new NotImplementedException(); 128 | 129 | public StatusProperty Altitude => throw new NotImplementedException(); 130 | 131 | public StatusProperty Longitude => throw new NotImplementedException(); 132 | 133 | public StatusProperty Heading => throw new NotImplementedException(); 134 | 135 | public StatusProperty Body => throw new NotImplementedException(); 136 | 137 | public StatusProperty BodyRadius => throw new NotImplementedException(); 138 | 139 | /// 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /TestForceFeedback/EliteStatusMock.cs: -------------------------------------------------------------------------------- 1 | using EliteAPI.Status.Abstractions; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace TestForceFeedback 9 | { 10 | public class EliteStatusMock : IStatus 11 | { 12 | //private IRawStatus _rawStatus; 13 | 14 | /// 15 | public event EventHandler OnChange; 16 | 17 | /// 18 | public string ToJson() 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | 23 | void IStatus.TriggerOnChange(IRawStatus status) 24 | { 25 | OnChange?.Invoke(this, status); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TestForceFeedback/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /TestForceFeedback/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 13 | 14 | 15 | 16 | 17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 18 | 19 | 20 | 21 | 22 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks. 23 | 24 | 25 | 26 | 27 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks. 28 | 29 | 30 | 31 | 32 | The order of preloaded assemblies, delimited with line breaks. 33 | 34 | 35 | 36 | 37 | 38 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. 39 | 40 | 41 | 42 | 43 | Controls if .pdbs for reference assemblies are also embedded. 44 | 45 | 46 | 47 | 48 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. 49 | 50 | 51 | 52 | 53 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. 54 | 55 | 56 | 57 | 58 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. 59 | 60 | 61 | 62 | 63 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. 64 | 65 | 66 | 67 | 68 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 69 | 70 | 71 | 72 | 73 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. 74 | 75 | 76 | 77 | 78 | A list of unmanaged 32 bit assembly names to include, delimited with |. 79 | 80 | 81 | 82 | 83 | A list of unmanaged 64 bit assembly names to include, delimited with |. 84 | 85 | 86 | 87 | 88 | The order of preloaded assemblies, delimited with |. 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 97 | 98 | 99 | 100 | 101 | A comma-separated list of error codes that can be safely ignored in assembly verification. 102 | 103 | 104 | 105 | 106 | 'false' to turn off automatic generation of the XML Schema file. 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Cargo.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Cargo.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/CenterSpringXY.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/CenterSpringXY.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Damper.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Damper.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Dock.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Dock.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Gear.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Gear.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Hardpoints.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Hardpoints.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Landed.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Landed.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/Vibrate.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/Vibrate.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Forces/VibrateSide.ffe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bobhelander/EDForceFeedback/e5a23dca26507aa9b123912e81ea124b6fd11240/TestForceFeedback/Forces/VibrateSide.ffe -------------------------------------------------------------------------------- /TestForceFeedback/Program.cs: -------------------------------------------------------------------------------- 1 | using EliteAPI.Abstractions; 2 | using ForceFeedbackSharpDx; 3 | using Journals; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using Microsoft.Extensions.Logging; 7 | using Newtonsoft.Json; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.IO; 11 | using System.Linq; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | 15 | namespace TestForceFeedback 16 | { 17 | internal static class Program 18 | { 19 | //static string feedbackGuid = "001b045e-0000-0000-0000-504944564944"; // MS ForceFeedBack 2 20 | //static string feedbackProduct = "SideWinder Force Feedback 2 Joystick"; // MS ForceFeedBack 2 21 | 22 | static string feedbackGuid = "02dd045e-0000-0000-0000-504944564944"; // XBOX One 23 | static string feedbackProduct = "Controller (Xbox One For Windows)"; // XBOX One 24 | 25 | static void Main_bak(string[] args) 26 | { 27 | var msffb2 = new ForceFeedbackController(); 28 | msffb2.Initialize(feedbackGuid, feedbackProduct, @".\Forces", false, 10000); 29 | 30 | Console.ReadKey(); 31 | 32 | Console.WriteLine("Damper.ffe"); 33 | var effects = msffb2.PlayFileEffect("Damper.ffe", -1); 34 | 35 | Console.ReadKey(); 36 | 37 | Console.WriteLine("SetActuators(false)"); 38 | msffb2.SetActuators(false); 39 | 40 | Console.ReadKey(); 41 | 42 | Console.WriteLine("SetActuators(true)"); 43 | msffb2.SetActuators(true); 44 | 45 | Console.ReadKey(); 46 | 47 | Console.WriteLine("VibrateSide.ffe"); 48 | var vibrate = msffb2.PlayFileEffect("VibrateSide.ffe", -1); 49 | 50 | Console.ReadKey(); 51 | 52 | Console.WriteLine("StopEffects"); 53 | msffb2.StopEffects(effects); 54 | msffb2.StopEffects(vibrate); 55 | 56 | Console.ReadKey(); 57 | 58 | Console.WriteLine("CenterSpringXY.ffe"); 59 | var centerEffects = msffb2.PlayFileEffect("CenterSpringXY.ffe", -1); 60 | 61 | Console.ReadKey(); 62 | 63 | if (centerEffects != null) 64 | { 65 | Console.WriteLine("Gain = 5000"); 66 | var effectParams = centerEffects[0].GetParameters(SharpDX.DirectInput.EffectParameterFlags.Gain); 67 | 68 | effectParams.Gain = 5000; 69 | 70 | centerEffects[0].SetParameters(effectParams, SharpDX.DirectInput.EffectParameterFlags.Gain | SharpDX.DirectInput.EffectParameterFlags.NoRestart); 71 | 72 | Console.ReadKey(); 73 | 74 | Console.WriteLine("Gain = 10000"); 75 | effectParams.Gain = 10000; 76 | 77 | centerEffects[0].SetParameters(effectParams, SharpDX.DirectInput.EffectParameterFlags.Gain | SharpDX.DirectInput.EffectParameterFlags.NoRestart); 78 | 79 | Console.ReadKey(); 80 | } 81 | 82 | Console.WriteLine("StopEffects(centerEffects)"); 83 | msffb2.StopEffects(centerEffects); 84 | 85 | Console.ReadKey(); 86 | /* 87 | msffb2.PlayFileEffect("VibrateSide.ffe"); 88 | //msffb2.PlayFileEffect("VibrateSide.ffe"); 89 | // msffb2.PlayFileEffect("VibrateSide.ffe"); 90 | 91 | Console.ReadKey(); 92 | 93 | msffb2.PlayFileEffect("Landed.ffe"); 94 | 95 | Console.ReadKey(); 96 | 97 | msffb2.PlayFileEffect("Gear.ffe"); 98 | 99 | //msffb2.CenterOff(); 100 | 101 | Console.ReadKey(); 102 | */ 103 | } 104 | 105 | public static IServiceCollection AddEliteAPI(this IServiceCollection services) 106 | { 107 | // EliteAPI 108 | services.AddSingleton(); 109 | services.AddSingleton(); 110 | return services; 111 | } 112 | 113 | 114 | static void Main(string[] args) 115 | { 116 | var fileName = $"{Directory.GetCurrentDirectory()}\\settings.json"; 117 | 118 | // Check if a settings file was specified 119 | if (args?.Length == 1) 120 | { 121 | if (args[0].CompareTo("-h") == 0 || args[0].CompareTo("help") == 0) 122 | { 123 | Console.WriteLine("EDForceFeedBack: EDForceFeedback.exe is a console program that runs during a Elite Dangerous session."); 124 | Console.WriteLine("It watches the ED log files and responds to game events by playing a force feedback editor (.ffe) file."); 125 | Console.WriteLine(); 126 | Console.WriteLine("Usage:"); 127 | Console.WriteLine("EDForceFeedback.exe -h Output this help."); 128 | Console.WriteLine(@"EDForceFeedback.exe c:\settings.json Override the default settings file and use this instead."); 129 | Console.WriteLine($"EDForceFeedback.exe Will default to the settings file {Directory.GetCurrentDirectory()}\\settings.json"); 130 | return; 131 | } 132 | else 133 | { 134 | fileName = args[0]; 135 | } 136 | } 137 | 138 | Console.WriteLine($"Using setting file: {fileName}"); 139 | 140 | var settings = JsonConvert.DeserializeObject(File.ReadAllText(fileName)); 141 | 142 | IEliteDangerousApi eliteAPI; 143 | EliteAPI.Status.Ship.Abstractions.IShip ship; 144 | ILogger logger; 145 | IHost host; 146 | 147 | List Devices = new List(); 148 | 149 | // Inject the logger and EliteApi services into host 150 | host = Host.CreateDefaultBuilder() 151 | .ConfigureServices((context, service) => 152 | { 153 | service.AddEliteAPI(); 154 | service.AddTransient(); 155 | service.AddLogging(builder => 156 | builder.AddSimpleConsole(options => { options.SingleLine = true; options.TimestampFormat = "hh:mm:ss "; }).SetMinimumLevel(LogLevel.Debug)); 157 | }) 158 | .Build(); 159 | 160 | // Get the services from the Host object 161 | eliteAPI = host.Services.GetService(); 162 | ship = host.Services.GetService(); 163 | logger = host.Services.GetRequiredService>(); 164 | 165 | foreach (var device in settings.Devices) 166 | { 167 | var ffDevice = new ForceFeedbackController() { Logger = logger }; 168 | if (ffDevice.Initialize( 169 | device.ProductGuid, 170 | device.ProductName, 171 | @".\Forces", 172 | device.AutoCenter, 173 | device.ForceFeedbackGain) == false) 174 | { 175 | logger.LogError($"Device Initialization failed: {device.ProductGuid}: {device.ProductName}"); 176 | continue; 177 | } 178 | 179 | var deviceEvents = new DeviceEvents 180 | { 181 | EventSettings = device.StatusEvents.ToDictionary(v => v.Event, v => v), 182 | Device = ffDevice 183 | }; 184 | 185 | Devices.Add(deviceEvents); 186 | } 187 | 188 | 189 | // Start the api 190 | //await eliteAPI.StartAsync().ConfigureAwait(false); 191 | 192 | //eliteAPI.Events.AllEvent += Events_AllEvent; 193 | 194 | ship.Docked.OnChange += (obj, eventArgs) => FindEffect($"Status.Docked:{eventArgs}", Devices); 195 | ship.Landed.OnChange += (obj, eventArgs) => FindEffect($"Status.Landed:{eventArgs}", Devices); 196 | ship.Gear.OnChange += (obj, eventArgs) => FindEffect($"Status.Gear:{eventArgs}", Devices); 197 | ship.Shields.OnChange += (obj, eventArgs) => FindEffect($"Status.Shields:{eventArgs}", Devices); 198 | ship.Supercruise.OnChange += (obj, eventArgs) => FindEffect($"Status.Supercruise:{eventArgs}", Devices); 199 | ship.FlightAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.FlightAssist:{eventArgs}", Devices); 200 | ship.Hardpoints.OnChange += (obj, eventArgs) => FindEffect($"Status.Hardpoints:{eventArgs}", Devices); 201 | ship.Winging.OnChange += (obj, eventArgs) => FindEffect($"Status.Winging:{eventArgs}", Devices); 202 | ship.Lights.OnChange += (obj, eventArgs) => FindEffect($"Status.Lights:{eventArgs}", Devices); 203 | ship.CargoScoop.OnChange += (obj, eventArgs) => FindEffect($"Status.CargoScoop:{eventArgs}", Devices); 204 | ship.SilentRunning.OnChange += (obj, eventArgs) => FindEffect($"Status.SilentRunning:{eventArgs}", Devices); 205 | ship.Scooping.OnChange += (obj, eventArgs) => FindEffect($"Status.Scooping:{eventArgs}", Devices); 206 | ship.SrvHandbreak.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHandbreak:{eventArgs}", Devices); 207 | ship.SrvTurrent.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvTurrent:{eventArgs}", Devices); 208 | ship.SrvNearShip.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvNearShip:{eventArgs}", Devices); 209 | ship.SrvDriveAssist.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvDriveAssist:{eventArgs}", Devices); 210 | ship.MassLocked.OnChange += (obj, eventArgs) => FindEffect($"Status.MassLocked:{eventArgs}", Devices); 211 | ship.FsdCharging.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCharging:{eventArgs}", Devices); 212 | ship.FsdCooldown.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdCooldown:{eventArgs}", Devices); 213 | ship.LowFuel.OnChange += (obj, eventArgs) => FindEffect($"Status.LowFuel:{eventArgs}", Devices); 214 | ship.Overheating.OnChange += (obj, eventArgs) => FindEffect($"Status.Overheating:{eventArgs}", Devices); 215 | ship.HasLatLong.OnChange += (obj, eventArgs) => FindEffect($"Status.HasLatLong:{eventArgs}", Devices); 216 | ship.InDanger.OnChange += (obj, eventArgs) => FindEffect($"Status.InDanger:{eventArgs}", Devices); 217 | ship.InInterdiction.OnChange += (obj, eventArgs) => FindEffect($"Status.InInterdiction:{eventArgs}", Devices); 218 | ship.InMothership.OnChange += (obj, eventArgs) => FindEffect($"Status.InMothership:{eventArgs}", Devices); 219 | ship.InFighter.OnChange += (obj, eventArgs) => FindEffect($"Status.InFighter:{eventArgs}", Devices); 220 | ship.InSrv.OnChange += (obj, eventArgs) => FindEffect($"Status.InSrv:{eventArgs}", Devices); 221 | ship.AnalysisMode.OnChange += (obj, eventArgs) => FindEffect($"Status.AnalysisMode:{eventArgs}", Devices); 222 | ship.NightVision.OnChange += (obj, eventArgs) => FindEffect($"Status.NightVision:{eventArgs}", Devices); 223 | ship.AltitudeFromAverageRadius.OnChange += (obj, eventArgs) => FindEffect($"Status.AltitudeFromAverageRadius:{eventArgs}", Devices); 224 | ship.FsdJump.OnChange += (obj, eventArgs) => FindEffect($"Status.FsdJump:{eventArgs}", Devices); 225 | ship.SrvHighBeam.OnChange += (obj, eventArgs) => FindEffect($"Status.SrvHighBeam:{eventArgs}", Devices); 226 | 227 | while (true) 228 | { 229 | Console.WriteLine("0: Quit"); 230 | Console.WriteLine("1: Docked (true)"); 231 | Console.WriteLine("2: Landed (true)"); 232 | Console.WriteLine("3: Gear (deployed)"); 233 | Console.WriteLine("4: Gear (retracted)"); 234 | Console.WriteLine("5: Hardpoints (deployed)"); 235 | Console.WriteLine("6: Hardpoints (retracted)"); 236 | Console.WriteLine("7: Overheating"); 237 | 238 | var key = Console.ReadKey(); 239 | if (key.KeyChar == '0') 240 | break; 241 | switch (key.KeyChar) 242 | { 243 | case '1': 244 | ship.Docked.OnChange.Invoke(null, true); 245 | break; 246 | case '2': 247 | ship.Landed.OnChange.Invoke(null, true); 248 | break; 249 | case '3': 250 | ship.Gear.OnChange.Invoke(null, true); 251 | break; 252 | case '4': 253 | ship.Gear.OnChange.Invoke(null, false); 254 | break; 255 | case '5': 256 | ship.Hardpoints.OnChange.Invoke(null, true); 257 | break; 258 | case '6': 259 | ship.Hardpoints.OnChange.Invoke(null, false); 260 | break; 261 | case '7': 262 | ship.Overheating.OnChange.Invoke(null, true); 263 | break; 264 | } 265 | } 266 | } 267 | 268 | //private static void Events_AllEvent(object sender, dynamic e) 269 | //{ 270 | // var eventKey = e.ToString(); 271 | // FindEffect(eventKey); 272 | //} 273 | 274 | private static void FindEffect(string eventKey, IEnumerable Devices) 275 | { 276 | foreach (var device in Devices) 277 | { 278 | if (device.EventSettings.ContainsKey(eventKey)) 279 | { 280 | var eventConfig = device.EventSettings[eventKey]; 281 | var result = device.Device?.PlayFileEffect(eventConfig.ForceFile, eventConfig.Duration); 282 | } 283 | } 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /TestForceFeedback/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestForceFeedback")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestForceFeedback")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("574005ed-6b12-4092-ac48-71b5b302f8ad")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestForceFeedback/TestForceFeedback.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {574005ED-6B12-4092-AC48-71B5B302F8AD} 8 | Exe 9 | TestForceFeedback 10 | TestForceFeedback 11 | v4.8 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll 38 | 39 | 40 | ..\packages\Microsoft.Extensions.DependencyInjection.5.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll 41 | 42 | 43 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.DependencyInjection.Abstractions.dll 44 | 45 | 46 | ..\packages\Microsoft.Extensions.Logging.5.0.0\lib\net461\Microsoft.Extensions.Logging.dll 47 | 48 | 49 | ..\packages\Microsoft.Extensions.Logging.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Logging.Abstractions.dll 50 | 51 | 52 | ..\packages\Microsoft.Extensions.Options.5.0.0\lib\net461\Microsoft.Extensions.Options.dll 53 | 54 | 55 | ..\packages\Microsoft.Extensions.Primitives.5.0.0\lib\net461\Microsoft.Extensions.Primitives.dll 56 | 57 | 58 | ..\packages\SharpDX.4.2.0\lib\net45\SharpDX.dll 59 | 60 | 61 | ..\packages\SharpDX.DirectInput.4.2.0\lib\net45\SharpDX.DirectInput.dll 62 | 63 | 64 | 65 | 66 | ..\packages\System.Diagnostics.DiagnosticSource.5.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll 67 | 68 | 69 | ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | Always 87 | 88 | 89 | Always 90 | 91 | 92 | Always 93 | 94 | 95 | Always 96 | 97 | 98 | Always 99 | 100 | 101 | Always 102 | 103 | 104 | Always 105 | 106 | 107 | Always 108 | 109 | 110 | Always 111 | 112 | 113 | 114 | 115 | {D3C53E08-943F-4DD8-9939-6CD5858E28AC} 116 | ForceFeedbackSharpDx 117 | 118 | 119 | 120 | 121 | 9.0.3 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /TestForceFeedback/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | --------------------------------------------------------------------------------