From bae2cbb8354b671320a14cbc883628cb49eaee7f Mon Sep 17 00:00:00 2001 From: lumir-sliva Date: Sun, 3 May 2026 21:12:21 +0200 Subject: [PATCH] Add MOZA AB6 / AB9 FFB Base support The MOZA AB6 (PID 0x1002) and AB9 (PID 0x1000) flight bases expose a standard DirectInput FFB device with all 11 effect types (ConstantForce, RampForce, Sine, Square, Triangle, SawtoothUp/Down, Spring, Damper, Inertia, Friction). EDForceFeedback talks to them through the existing SharpDX path with no code changes; only the device entries and per-event mappings need to be configured. Empirical setup detail not documented anywhere upstream: the AB6/AB9 firmware silently swallows DirectInput effect writes unless MOZA Cockpit is running concurrently with "Integrated FFB" toggled ON in Cockpit's Basic Settings. With that toggle, Cockpit's filter relays the effects to the motor. README and the new settings files note this requirement. The bundled settingsMozaAB6.json / settingsMozaAB9.json map all 28 status flags from EliteAPI's GameStatus (Docked, Landed, Gear, Shields, Supercruise, FlightAssist, Hardpoints, Winging, Lights, CargoScoop, SilentRunning, Scooping, SrvHandbreak, SrvTurrent, SrvNearShip, SrvDriveAssist, MassLocked, FsdCharging, FsdCooldown, LowFuel, Overheating, HasLatlong, InDanger, InInterdiction, InMothership, InFighter, InSRV, AnalysisMode, NightVision, InNoFireZone, IsRunning, InMainMenu) to the bundled .ffe files. Tested end-to-end on the AB6: Status.MassLocked:False triggers VibrateSide.ffe and the stick reacts. Issue #35 establishes the AB9 entry; this expands to AB6, the full status-event set, and the missing Cockpit / Integrated FFB documentation. Github-Issue: #35 --- EDForceFeedback/settings.json | 4 +- EDForceFeedback/settingsMozaAB6.json | 99 +++++++++++++++++++++ EDForceFeedback/settingsMozaAB9.json | 99 +++++++++++++++++++++ EDForceFeedbackConsole/settings.json | 4 +- EDForceFeedbackConsole/settingsMozaAB6.json | 99 +++++++++++++++++++++ EDForceFeedbackConsole/settingsMozaAB9.json | 99 +++++++++++++++++++++ README.md | 13 +++ 7 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 EDForceFeedback/settingsMozaAB6.json create mode 100644 EDForceFeedback/settingsMozaAB9.json create mode 100644 EDForceFeedbackConsole/settingsMozaAB6.json create mode 100644 EDForceFeedbackConsole/settingsMozaAB9.json diff --git a/EDForceFeedback/settings.json b/EDForceFeedback/settings.json index bc946fe..c1bb239 100644 --- a/EDForceFeedback/settings.json +++ b/EDForceFeedback/settings.json @@ -7,7 +7,9 @@ "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", - "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB toggled on)", + "MOZA AB6 FFB Base": "ProductGuid = 1002346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB6 FFB Base' (requires MOZA Cockpit + Integrated FFB toggled on)" }, "Devices": [ diff --git a/EDForceFeedback/settingsMozaAB6.json b/EDForceFeedback/settingsMozaAB6.json new file mode 100644 index 0000000..641d94b --- /dev/null +++ b/EDForceFeedback/settingsMozaAB6.json @@ -0,0 +1,99 @@ +{ + "_NOTES_BEFORE_USE": [ + "MOZA AB6 FFB Base requires MOZA Cockpit running concurrently with", + "'Integrated FFB' toggled ON in Basic Settings. Without that toggle the", + "AB6 firmware silently swallows DirectInput effect writes.", + "", + "Run EDForceFeedback.exe AS ADMINISTRATOR. UAC-elevated cooperative", + "level is required to acquire FFB exclusively.", + "", + "Rename this file to settings.json (or pass it on the command line) to", + "apply. Rename the existing settings.json out of the way first." + ], + + "KnownWorkingDevices": { + "NOTES": "ProductGuid + ProductName values for devices known to work with this program.", + "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944", + "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", + "Saitek Cyborg 3D": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", + "Saitek Cyborg Evo": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)", + "MOZA AB6 FFB Base": "ProductGuid = 1002346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB6 FFB Base' (requires MOZA Cockpit + Integrated FFB)" + }, + + "Devices": [ + { + "ProductGuid": "1002346e-0000-0000-0000-504944564944", + "ProductName": "MOZA AB6 FFB Base", + "AutoCenter": true, + "ForceFeedbackGain": 10000, + + "StatusEvents": [ + { "Event": "Status.Docked:True", "ForceFile": "Dock.ffe", "Duration": 2000 }, + { "Event": "Status.Docked:False", "ForceFile": "Dock.ffe", "Duration": 2000 }, + + { "Event": "Status.Landed:True", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + { "Event": "Status.Landed:False", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + + { "Event": "Status.Gear:True", "ForceFile": "Gear.ffe", "Duration": 3000 }, + { "Event": "Status.Gear:False", "ForceFile": "Gear.ffe", "Duration": 3000 }, + + { "Event": "Status.Hardpoints:True", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + { "Event": "Status.Hardpoints:False", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + + { "Event": "Status.CargoScoop:True", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + { "Event": "Status.CargoScoop:False", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + + { "Event": "Status.Lights:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.Lights:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Shields:True", "ForceFile": "Vibrate.ffe", "Duration": 500 }, + { "Event": "Status.Shields:False", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.Supercruise:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.Supercruise:False", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.FsdCharging:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.FsdCooldown:True", "ForceFile": "VibrateSide.ffe", "Duration": 2000 }, + { "Event": "Status.FsdCooldown:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.MassLocked:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.MassLocked:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.LowFuel:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.LowFuel:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Overheating:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.Overheating:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Scooping:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.SilentRunning:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.SilentRunning:False", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + + { "Event": "Status.NightVision:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.NightVision:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.AnalysisMode:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.AnalysisMode:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.FlightAssist:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.FlightAssist:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InDanger:True", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.InInterdiction:True", "ForceFile": "Hardpoints.ffe", "Duration": 2500 }, + + { "Event": "Status.InNoFireZone:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InMothership:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InFighter:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InSRV:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.SrvHandbreak:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.SrvTurrent:True", "ForceFile": "Vibrate.ffe", "Duration": 250 } + ] + } + ] +} diff --git a/EDForceFeedback/settingsMozaAB9.json b/EDForceFeedback/settingsMozaAB9.json new file mode 100644 index 0000000..530fac9 --- /dev/null +++ b/EDForceFeedback/settingsMozaAB9.json @@ -0,0 +1,99 @@ +{ + "_NOTES_BEFORE_USE": [ + "MOZA AB9 FFB Base requires MOZA Cockpit running concurrently with", + "'Integrated FFB' toggled ON in Basic Settings. Without that toggle the", + "AB6 firmware silently swallows DirectInput effect writes.", + "", + "Run EDForceFeedback.exe AS ADMINISTRATOR. UAC-elevated cooperative", + "level is required to acquire FFB exclusively.", + "", + "Rename this file to settings.json (or pass it on the command line) to", + "apply. Rename the existing settings.json out of the way first." + ], + + "KnownWorkingDevices": { + "NOTES": "ProductGuid + ProductName values for devices known to work with this program.", + "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944", + "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", + "Saitek Cyborg 3D": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", + "Saitek Cyborg Evo": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)" + }, + + "Devices": [ + { + "ProductGuid": "1000346e-0000-0000-0000-504944564944", + "ProductName": "MOZA AB9 FFB Base", + "AutoCenter": true, + "ForceFeedbackGain": 10000, + + "StatusEvents": [ + { "Event": "Status.Docked:True", "ForceFile": "Dock.ffe", "Duration": 2000 }, + { "Event": "Status.Docked:False", "ForceFile": "Dock.ffe", "Duration": 2000 }, + + { "Event": "Status.Landed:True", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + { "Event": "Status.Landed:False", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + + { "Event": "Status.Gear:True", "ForceFile": "Gear.ffe", "Duration": 3000 }, + { "Event": "Status.Gear:False", "ForceFile": "Gear.ffe", "Duration": 3000 }, + + { "Event": "Status.Hardpoints:True", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + { "Event": "Status.Hardpoints:False", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + + { "Event": "Status.CargoScoop:True", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + { "Event": "Status.CargoScoop:False", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + + { "Event": "Status.Lights:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.Lights:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Shields:True", "ForceFile": "Vibrate.ffe", "Duration": 500 }, + { "Event": "Status.Shields:False", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.Supercruise:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.Supercruise:False", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.FsdCharging:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.FsdCooldown:True", "ForceFile": "VibrateSide.ffe", "Duration": 2000 }, + { "Event": "Status.FsdCooldown:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.MassLocked:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.MassLocked:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.LowFuel:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.LowFuel:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Overheating:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.Overheating:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Scooping:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.SilentRunning:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.SilentRunning:False", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + + { "Event": "Status.NightVision:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.NightVision:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.AnalysisMode:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.AnalysisMode:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.FlightAssist:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.FlightAssist:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InDanger:True", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.InInterdiction:True", "ForceFile": "Hardpoints.ffe", "Duration": 2500 }, + + { "Event": "Status.InNoFireZone:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InMothership:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InFighter:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InSRV:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.SrvHandbreak:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.SrvTurrent:True", "ForceFile": "Vibrate.ffe", "Duration": 250 } + ] + } + ] +} diff --git a/EDForceFeedbackConsole/settings.json b/EDForceFeedbackConsole/settings.json index 32c20ac..c2efbf4 100644 --- a/EDForceFeedbackConsole/settings.json +++ b/EDForceFeedbackConsole/settings.json @@ -7,7 +7,9 @@ "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", "Saitek Cyborg 3D Force Stick": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", "Saitek Cyborg Evo Force Stick": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", - "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU" + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB toggled on)", + "MOZA AB6 FFB Base": "ProductGuid = 1002346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB6 FFB Base' (requires MOZA Cockpit + Integrated FFB toggled on)" }, "Devices": [ diff --git a/EDForceFeedbackConsole/settingsMozaAB6.json b/EDForceFeedbackConsole/settingsMozaAB6.json new file mode 100644 index 0000000..641d94b --- /dev/null +++ b/EDForceFeedbackConsole/settingsMozaAB6.json @@ -0,0 +1,99 @@ +{ + "_NOTES_BEFORE_USE": [ + "MOZA AB6 FFB Base requires MOZA Cockpit running concurrently with", + "'Integrated FFB' toggled ON in Basic Settings. Without that toggle the", + "AB6 firmware silently swallows DirectInput effect writes.", + "", + "Run EDForceFeedback.exe AS ADMINISTRATOR. UAC-elevated cooperative", + "level is required to acquire FFB exclusively.", + "", + "Rename this file to settings.json (or pass it on the command line) to", + "apply. Rename the existing settings.json out of the way first." + ], + + "KnownWorkingDevices": { + "NOTES": "ProductGuid + ProductName values for devices known to work with this program.", + "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944", + "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", + "Saitek Cyborg 3D": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", + "Saitek Cyborg Evo": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)", + "MOZA AB6 FFB Base": "ProductGuid = 1002346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB6 FFB Base' (requires MOZA Cockpit + Integrated FFB)" + }, + + "Devices": [ + { + "ProductGuid": "1002346e-0000-0000-0000-504944564944", + "ProductName": "MOZA AB6 FFB Base", + "AutoCenter": true, + "ForceFeedbackGain": 10000, + + "StatusEvents": [ + { "Event": "Status.Docked:True", "ForceFile": "Dock.ffe", "Duration": 2000 }, + { "Event": "Status.Docked:False", "ForceFile": "Dock.ffe", "Duration": 2000 }, + + { "Event": "Status.Landed:True", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + { "Event": "Status.Landed:False", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + + { "Event": "Status.Gear:True", "ForceFile": "Gear.ffe", "Duration": 3000 }, + { "Event": "Status.Gear:False", "ForceFile": "Gear.ffe", "Duration": 3000 }, + + { "Event": "Status.Hardpoints:True", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + { "Event": "Status.Hardpoints:False", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + + { "Event": "Status.CargoScoop:True", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + { "Event": "Status.CargoScoop:False", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + + { "Event": "Status.Lights:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.Lights:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Shields:True", "ForceFile": "Vibrate.ffe", "Duration": 500 }, + { "Event": "Status.Shields:False", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.Supercruise:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.Supercruise:False", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.FsdCharging:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.FsdCooldown:True", "ForceFile": "VibrateSide.ffe", "Duration": 2000 }, + { "Event": "Status.FsdCooldown:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.MassLocked:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.MassLocked:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.LowFuel:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.LowFuel:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Overheating:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.Overheating:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Scooping:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.SilentRunning:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.SilentRunning:False", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + + { "Event": "Status.NightVision:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.NightVision:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.AnalysisMode:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.AnalysisMode:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.FlightAssist:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.FlightAssist:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InDanger:True", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.InInterdiction:True", "ForceFile": "Hardpoints.ffe", "Duration": 2500 }, + + { "Event": "Status.InNoFireZone:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InMothership:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InFighter:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InSRV:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.SrvHandbreak:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.SrvTurrent:True", "ForceFile": "Vibrate.ffe", "Duration": 250 } + ] + } + ] +} diff --git a/EDForceFeedbackConsole/settingsMozaAB9.json b/EDForceFeedbackConsole/settingsMozaAB9.json new file mode 100644 index 0000000..530fac9 --- /dev/null +++ b/EDForceFeedbackConsole/settingsMozaAB9.json @@ -0,0 +1,99 @@ +{ + "_NOTES_BEFORE_USE": [ + "MOZA AB9 FFB Base requires MOZA Cockpit running concurrently with", + "'Integrated FFB' toggled ON in Basic Settings. Without that toggle the", + "AB6 firmware silently swallows DirectInput effect writes.", + "", + "Run EDForceFeedback.exe AS ADMINISTRATOR. UAC-elevated cooperative", + "level is required to acquire FFB exclusively.", + "", + "Rename this file to settings.json (or pass it on the command line) to", + "apply. Rename the existing settings.json out of the way first." + ], + + "KnownWorkingDevices": { + "NOTES": "ProductGuid + ProductName values for devices known to work with this program.", + "Xbox One For Windows": "ProductGuid = 02dd045e-0000-0000-0000-504944564944", + "MSFF2": "ProductGuid = 001b045e-0000-0000-0000-504944564944 ProductName = 'SideWinder Force Feedback 2 Joystick'", + "Saitek Cyborg 3D": "ProductGuid = ff1206a3-0000-0000-0000-504944564944", + "Saitek Cyborg Evo": "ProductGuid = ffb506a3-0000-0000-0000-504944564944", + "Teensy Boards": "ProductGuid = 230028de-0000-0000-0000-504944564944 ProductName = IMU", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)", + "MOZA AB9 FFB Base": "ProductGuid = 1000346e-0000-0000-0000-504944564944 ProductName = 'MOZA AB9 FFB Base' (requires MOZA Cockpit + Integrated FFB)" + }, + + "Devices": [ + { + "ProductGuid": "1000346e-0000-0000-0000-504944564944", + "ProductName": "MOZA AB9 FFB Base", + "AutoCenter": true, + "ForceFeedbackGain": 10000, + + "StatusEvents": [ + { "Event": "Status.Docked:True", "ForceFile": "Dock.ffe", "Duration": 2000 }, + { "Event": "Status.Docked:False", "ForceFile": "Dock.ffe", "Duration": 2000 }, + + { "Event": "Status.Landed:True", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + { "Event": "Status.Landed:False", "ForceFile": "Hardpoints.ffe", "Duration": 1500 }, + + { "Event": "Status.Gear:True", "ForceFile": "Gear.ffe", "Duration": 3000 }, + { "Event": "Status.Gear:False", "ForceFile": "Gear.ffe", "Duration": 3000 }, + + { "Event": "Status.Hardpoints:True", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + { "Event": "Status.Hardpoints:False", "ForceFile": "Hardpoints.ffe", "Duration": 2000 }, + + { "Event": "Status.CargoScoop:True", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + { "Event": "Status.CargoScoop:False", "ForceFile": "Cargo.ffe", "Duration": 2000 }, + + { "Event": "Status.Lights:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.Lights:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Shields:True", "ForceFile": "Vibrate.ffe", "Duration": 500 }, + { "Event": "Status.Shields:False", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.Supercruise:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.Supercruise:False", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.FsdCharging:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.FsdCooldown:True", "ForceFile": "VibrateSide.ffe", "Duration": 2000 }, + { "Event": "Status.FsdCooldown:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.MassLocked:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + { "Event": "Status.MassLocked:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.LowFuel:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.LowFuel:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Overheating:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.Overheating:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.Scooping:True", "ForceFile": "VibrateSide.ffe", "Duration": 1500 }, + + { "Event": "Status.SilentRunning:True", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + { "Event": "Status.SilentRunning:False", "ForceFile": "VibrateSide.ffe", "Duration": 500 }, + + { "Event": "Status.NightVision:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.NightVision:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.AnalysisMode:True", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + { "Event": "Status.AnalysisMode:False", "ForceFile": "Vibrate.ffe", "Duration": 200 }, + + { "Event": "Status.FlightAssist:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.FlightAssist:False", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InDanger:True", "ForceFile": "VibrateSide.ffe", "Duration": 1000 }, + + { "Event": "Status.InInterdiction:True", "ForceFile": "Hardpoints.ffe", "Duration": 2500 }, + + { "Event": "Status.InNoFireZone:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.InMothership:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InFighter:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.InSRV:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + + { "Event": "Status.SrvHandbreak:True", "ForceFile": "Vibrate.ffe", "Duration": 250 }, + { "Event": "Status.SrvTurrent:True", "ForceFile": "Vibrate.ffe", "Duration": 250 } + ] + } + ] +} diff --git a/README.md b/README.md index 94c0da0..4f91e31 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,19 @@ It has been tested with the following devices: [Saitek Cyborg 3D Force Stick](https://www.yumpu.com/en/document/view/38049421/cyborg-force-manualqxd-saitekcom) +[MOZA AB6 FFB Base](https://mozaracing.com/products/ab6-bundle) and [MOZA AB9 FFB Base](https://mozaracing.com/products/ab9-base) — see the MOZA setup notes below. + +##### MOZA AB6 / AB9 setup + +The MOZA flight bases expose a standard DirectInput FFB device, but the firmware +silently swallows DirectInput effect writes unless **MOZA Cockpit** is running +concurrently with **Integrated FFB** toggled ON in Cockpit's Basic Settings page. +With that toggle, Cockpit's filter relays the effects to the motor. + +Use `settingsMozaAB6.json` (or `settingsMozaAB9.json`) as a starting point — they +register the device by ProductGuid and map all 28 status flags to the bundled +`.ffe` files. Run `EDForceFeedback.exe` as administrator. + ### Usage 1. Connect your joystick/gamepad and run the EDForceFeedback.exe program. 2. Start Elite Dangerous