A safe Rust interface for reading Assetto Corsa Evo live telemetry via Windows named shared memory.
- Dependencies and requirements
- Getting started
- Usage
- Views
- Typed enums
- Snapshots
- Raw access
- Feature flags
- Side notes
- Windows only — uses Win32 named file-mapping APIs.
- AC Evo must be running before calling
ACEvoSharedMemoryMapper::open(). - Requires Rust edition 2024.
Add the library to your project:
cargo add acevo-shared-memoryAll access goes through ACEvoSharedMemoryMapper, which opens the three named
shared-memory segments and returns typed views over each one.
use acevo_shared_memory::ACEvoSharedMemoryMapper;
let mapper = ACEvoSharedMemoryMapper::open()
.expect("AC Evo must be running");The physics page is updated every simulation step and contains raw vehicle-dynamics data: speed, gear, RPM, tyre state, G-forces, ERS, damage, and more.
use acevo_shared_memory::ACEvoSharedMemoryMapper;
let mapper = ACEvoSharedMemoryMapper::open().unwrap();
let physics = mapper.physics();
println!("Speed: {:.1} km/h", physics.raw().speedKmh);
println!("Gear: {}", physics.raw().gear);
println!("RPM: {}", physics.raw().rpms);
println!("TC on: {}", physics.tc_in_action());
println!("ABS on: {}", physics.abs_in_action());
println!("DRS: {}", physics.drs_enabled());The graphics page is updated every rendered frame and contains HUD state, driver info, flag state, lap timing, electronics settings, and more.
use acevo_shared_memory::ACEvoSharedMemoryMapper;
let mapper = ACEvoSharedMemoryMapper::open().unwrap();
let g = mapper.graphics();
println!("Driver: {} {}", g.driver_name(), g.driver_surname());
println!("Car: {}", g.car_model());
println!("Status: {:?}", g.status());
println!("Flag: {:?}", g.flag());
println!("Location: {:?}", g.car_location());
println!("Engine: {:?}", g.engine_type());
println!("Pos: {}/{}", g.raw().current_pos, g.raw().total_drivers);The static page is written once when a session loads and does not change while driving. It contains track name, session type, grip condition, and more.
use acevo_shared_memory::ACEvoSharedMemoryMapper;
let mapper = ACEvoSharedMemoryMapper::open().unwrap();
let s = mapper.static_data();
println!("Interface version: {}", s.sm_version());
println!("Game version: {}", s.ac_evo_version());
println!("Track: {} ({})", s.track(), s.track_configuration());
println!("Session: {:?}", s.session());
println!("Starting grip: {:?}", s.starting_grip());
println!("Nation: {}", s.nation());All three data views share the same View<T> foundation and expose these methods:
| Method | Return type | Description |
|---|---|---|
raw() |
&T |
Direct reference to the underlying C struct — access every protocol field |
inner() |
&T |
Alias for raw() |
snapshot() |
View<'static, T> |
Heap-allocates an owned copy that outlives the mapper |
| View | Segment name | Content | Update rate |
|---|---|---|---|
PhysicsView |
Local\acevo_pmf_physics |
Vehicle dynamics — speed, tyres, suspension | Every sim step |
GraphicsView |
Local\acevo_pmf_graphics |
HUD state, tyres, electronics, lap timing | Every frame |
StaticView |
Local\acevo_pmf_static |
Session metadata — track, session type, grip | Once at load |
| Method | Return type | Description |
|---|---|---|
auto_shifter_on() |
bool |
Automatic gearshift aid is active |
tc_in_action() |
bool |
Traction control is currently cutting power |
abs_in_action() |
bool |
ABS is currently modulating brakes |
drs_available() |
bool |
DRS can be activated in current track section |
drs_enabled() |
bool |
DRS flap is open and active |
pit_limiter_on() |
bool |
Pit-speed limiter is engaged |
ers_is_charging() |
bool |
ERS is recovering energy (not deploying) |
ignition_on() |
bool |
Ignition switch is on |
starter_engine_on() |
bool |
Starter motor is cranking the engine |
is_engine_running() |
bool |
Engine is running |
is_ai_controlled() |
bool |
Car is driven by AI |
| Method | Return type | Description |
|---|---|---|
status() |
ACEvoStatus |
Simulator operational state |
car_location() |
ACEvoCarLocation |
Current track zone the car occupies |
flag() |
ACEvoFlagType |
Flag shown to this driver |
global_flag() |
ACEvoFlagType |
Flag shown to all drivers |
engine_type() |
ACEvoEngineType |
Powertrain type |
driver_name() |
&str |
Driver first name |
driver_surname() |
&str |
Driver surname |
car_model() |
&str |
Car model identifier |
performance_mode_name() |
&str |
Active vehicle performance / power mode |
focused_car_id() |
(u64, u64) |
ID of car shown by camera |
player_car_id() |
(u64, u64) |
ID of the player's own car |
g_forces() |
(f32, f32, f32) |
Lateral / longitudinal / vertical G-forces |
time_of_day() |
(i32, i32, i32) |
In-game time as (hours, minutes, seconds) |
| Method | Return type | Description |
|---|---|---|
sm_version() |
&str |
Shared-memory interface version |
ac_evo_version() |
&str |
Game build version |
session() |
ACEvoSessionType |
Type of the current session |
session_name() |
&str |
Human-readable session name |
starting_grip() |
ACEvoStartingGrip |
Tyre grip condition at session start |
track() |
&str |
Track identifier |
track_configuration() |
&str |
Track layout variant |
nation() |
&str |
Country / nation of the event |
Protocol integer constants are exposed as Rust enums. All enums derive
Debug, Clone, Copy, PartialEq, Eq, Display, EnumString,
EnumIter, and IntoStaticStr (via strum).
Each enum has an Unknown(i32) or Other(i32) catch-all variant for
forward-compatibility with future protocol values.
| Enum | Maps to | Variants |
|---|---|---|
ACEvoStatus |
ACEVO_STATUS |
Off, Replay, Live, Pause |
ACEvoSessionType |
ACEVO_SESSION_TYPE |
Unknown (-1), TimeAttack, Race, HotStint, Cruise |
ACEvoFlagType |
ACEVO_FLAG_TYPE |
NoFlag, WhiteFlag, GreenFlag, RedFlag, BlueFlag, YellowFlag, BlackFlag, BlackWhiteFlag, CheckeredFlag, OrangeCircleFlag, RedYellowStripesFlag |
ACEvoCarLocation |
ACEVO_CAR_LOCATION |
Unassigned, Pitlane, PitEntry, PitExit, Track |
ACEvoEngineType |
ACEVO_ENGINE_TYPE |
InternalCombustion, ElectricMotor |
ACEvoStartingGrip |
ACEVO_STARTING_GRIP |
Green, Fast, Optimum |
Every enum also provides a value() -> i32 method to convert back to the
raw protocol integer:
use acevo_shared_memory::ACEvoStatus;
assert_eq!(ACEvoStatus::Live.value(), 2);
assert_eq!(ACEvoStatus::from(3), ACEvoStatus::Pause);Views borrow directly from the shared-memory mapping and carry a lifetime tied
to the ACEvoSharedMemoryMapper. Call .snapshot() to obtain a 'static
heap copy that can be stored, queued, or sent across threads:
use acevo_shared_memory::ACEvoSharedMemoryMapper;
let mapper = ACEvoSharedMemoryMapper::open().unwrap();
let snap = mapper.physics().snapshot(); // Box<SPageFilePhysics> internally
drop(mapper);
println!("Captured speed: {:.1} km/h", snap.raw().speedKmh);Every field defined in the protocol is accessible via .raw(), including
fields not yet covered by a typed accessor method:
let g = mapper.graphics().raw();
println!("Fuel: {:.2} L", g.fuel_liter_current_quantity);
println!("Lap time: {} ms", g.current_lap_time_ms);
println!("Predicted lap: {} ms", g.predicted_lap_time_ms);
println!("Gap ahead: {:.3} s", g.gap_ahead);
println!("TC level: {}", g.electronics.tc_level);| Feature | Effect |
|---|---|
serde |
Derives serde::Serialize on all views, raw C structs, and enums. Derives serde::Deserialize on snapshot views (View<'static, T>) and enums. Borrowed views can only be serialized — deserializing always produces an owned snapshot. |
Please keep in mind that at the moment this is a side project developed with no planned continuity nor schedule. Therefore support, fixes and new features cannot be guaranteed.
As stated in the LICENSE, no contributor must be considered liable for the use of this project.