Force Feedback Replay Tool for testing and comparing FFB device drivers. This tool allows you to record Force Feedback commands generated by drivers and compare them against reference captures.
- Play Scenarios: Execute predefined Force Feedback test scenarios
- Record Output: Capture driver output to files for analysis
- Compare Drivers: Compare driver outputs against reference captures
- Multiple Drivers: Support for SDL and SIMAGIC HID drivers
- YAML Configuration: Easy-to-read scenario definition format
- Rust: Install from rustup.rs
- Visual Studio Build Tools: Required for building native dependencies
- Download from Visual Studio Downloads
- Select "Desktop development with C++" workload
- CMake: Required for building SDL3
- Download from cmake.org
- Or install via Chocolatey:
choco install cmake
- USBPcap: Required to capture USB traffic when using SDL driver
- Download from desowin.org/usbpcap
- Restart may be required after installation
-
Rust: Install from rustup.rs
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Build dependencies:
sudo apt update sudo apt install build-essential pkg-config cmake
-
SDL3 development libraries:
# For Ubuntu 24.04+ (if available in repos) sudo apt install libsdl3-dev # Alternative: Build SDL3 from source git clone https://github.com/libsdl-org/SDL.git -b SDL3 cd SDL mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release make -j$(nproc) sudo make install sudo ldconfig
-
USB capture tools: Required to capture USB traffic when using SDL driver
sudo apt install tcpdump sudo modprobe usbmon
Note: Running with SDL capture requires root/sudo privileges.
# Clone the repository
git clone <repository-url>
cd ffb_replay
# Build in release mode (recommended)
cargo build --release
# The binary will be at: target/release/ffb_replay (or ffb_replay.exe on Windows)For development:
cargo build
# Binary at: target/debug/ffb_replayRecord driver output to a file in the runs/ directory:
Make sure to stop simpro (from tray also) and wireshark before recording
If you a lot of packets for each command, simpro is likely running
If you don't see any -> wireshark is likely running
ffb_replay record --scenario scenarios/simple_test.yaml --output simple_test.txt
# Use specific driver (default is sdl)
ffb_replay record --scenario scenarios/simple_test.yaml --output simple_sdl.txt --driver sdl
ffb_replay record --scenario scenarios/simple_test.yaml --output simple_simagic.txt --driver simagicCompare current driver output with a previously recorded file:
ffb_replay compare --scenario scenarios/simple_test.yaml --compare simple_test.txt
# Use specific driver
ffb_replay compare --scenario scenarios/condition_test.yaml --compare condition_ref.txt --driver simagic--scenario,-s: Path to scenario YAML file (required)--output,-o: Output file name, saved inruns/directory (required)--driver,-d: Driver to use:sdlorsimagic(default:sdl)
--scenario,-s: Path to scenario YAML file (required)--compare,-c: Capture file name inruns/directory to compare against (required)--driver,-d: Driver to use:sdlorsimagic(default:sdl)
# Record a comprehensive test using SDL driver
ffb_replay record -s scenarios/comprehensive_test.yaml -o comprehensive_sdl.txt -d sdl
# Record the same test using SIMAGIC driver
ffb_replay record -s scenarios/comprehensive_test.yaml -o comprehensive_simagic.txt -d simagic
# Compare SIMAGIC output against reference
ffb_replay compare -s scenarios/comprehensive_test.yaml -c comprehensive_reference.txt -d simagic
# Test condition effects (spring, damper, friction, inertia)
ffb_replay record -s scenarios/condition_test.yaml -o condition_output.txt
# Test envelope effects
ffb_replay record -s scenarios/envelope_test.yaml -o envelope_output.txt
# Test vibration effects
ffb_replay record -s scenarios/vibration_test.yaml -o vibration_output.txtffb_replay/
├── src/
│ ├── main.rs # CLI application entry point
│ ├── driver.rs # FfbDriver trait definition
│ ├── effects.rs # FFB effect types and definitions
│ ├── error.rs # Error types
│ └── drivers/
│ ├── mod.rs # Drivers module
│ ├── sdl_driver.rs # SDL3-based driver implementation
│ └── simagic_driver.rs # SIMAGIC HID protocol driver
├── scenarios/ # Test scenario definitions (YAML)
│ ├── simple_test.yaml
│ ├── condition_test.yaml
│ ├── envelope_test.yaml
│ ├── vibration_test.yaml
│ ├── comprehensive_test.yaml
│ └── racing_demo.yaml
├── runs/ # Output directory for recordings
│ └── .gitkeep
├── Cargo.toml
└── README.md
Scenarios are defined in YAML format. Each scenario consists of steps with effects and optional delays.
name: "Test Scenario"
description: "Description of what this scenario tests"
repeat_count: 1 # Number of times to repeat (default: 1)
loop_forever: false # Set to true for infinite loop (default: false)
steps:
- delay_before: 0 # Milliseconds to wait before this step
effect:
type: constant # Effect type
duration: 1000 # Duration in milliseconds
magnitude: 5000 # Force magnitude (-10000 to 10000)type: constant
duration: 1000
magnitude: 5000 # -10000 to 10000type: periodic
duration: 2000
wave_type: sine # sine, square, triangle, sawtooth_up, sawtooth_down
magnitude: 8000 # 0 to 10000
period: 100 # Period in milliseconds
offset: 0 # -10000 to 10000
phase: 0 # 0 to 36000 (hundredths of degrees)type: condition
duration: 3000
condition_type: spring # spring, damper, friction, inertia
x_axis:
offset: 0 # -10000 to 10000
positive_coefficient: 10000 # 0 to 10000
negative_coefficient: 10000 # 0 to 10000
positive_saturation: 10000 # 0 to 10000
negative_saturation: 10000 # 0 to 10000
dead_band: 0 # 0 to 10000type: ramp
duration: 2000
start_magnitude: -5000 # -10000 to 10000
end_magnitude: 5000 # -10000 to 10000envelope:
attack_time: 200 # Milliseconds
attack_level: 0 # 0 to 10000
fade_time: 200 # Milliseconds
fade_level: 0 # 0 to 10000- Uses SDL3 Haptic API
- Cross-platform support
- Works with any FFB device supported by SDL3
- Recommended for general testing
- Direct HID protocol implementation
- Generates HID reports based on reverse-engineered protocol
- Currently operates in simulation mode (generates reports without sending to hardware)
- Useful for comparing protocol implementations
cargo testcargo build --releaseThe codebase is organized around the FfbDriver trait which defines the interface for all FFB drivers:
pub trait FfbDriver {
fn initialize(&mut self) -> FFBResult<()>;
fn apply_effect(&mut self, effect: &Effect) -> FFBResult<()>;
fn stop_all_effects(&mut self) -> FFBResult<()>;
fn shutdown(&mut self) -> FFBResult<()>;
fn name(&self) -> &str;
fn as_any(&self) -> &dyn Any;