id: 1a89aae8a5d04697be40c46532e2668f
parent_id: 
item_type: 1
item_id: 877a753ad06a40e08059834d8c8fb438
item_updated_time: 1780734451507
title_diff: "[{\"diffs\":[[1,\"DiRT Rally 1 & 2.0 — UDP Telemetry Protocol Specification\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":57}]"
body_diff: "[{\"diffs\":[[1,\"# DiRT Rally 1 & 2.0 — UDP Telemetry Protocol Specification\\\n\\\n> **Games**: DiRT Rally (2015), DiRT Rally 2.0 (2019) by Codemasters\\\n> **Engine**: EGO Engine (Codemasters proprietary)\\\n> **Parser status**: ❌ Not implemented in rusty-telemetry\\\n> **Platform**: Windows (DR1 also on Linux/Proton)\\\n> **Importance**: HIGH — second rally sim in scope, key differentiator alongside AC Rally\\\n\\\n---\\\n\\\n## Overview\\\n\\\nBoth DiRT Rally games use the **Codemasters UDP telemetry format** — the same protocol family used by the F1 game series (F1 2016–2024). No handshake needed. The game broadcasts binary packets to a configured IP:port.\\\n\\\n| Property | DiRT Rally 1 | DiRT Rally 2.0 |\\\n|---|---|---|\\\n| **Default Port** | 20777 | 20777 |\\\n| **Format** | Binary, little-endian | Binary, little-endian |\\\n| **Update Rate** | Configurable (up to 60 Hz) | Configurable (up to 60 Hz) |\\\n| **Direction** | Game → Target IP:Port | Game → Target IP:Port |\\\n| **Handshake** | None | None |\\\n| **Packet Types** | 1 (all-in-one) | Multiple (physics, participants, lap data, etc.) |\\\n\\\n---\\\n\\\n## Cross-References\\\n\\\n- **AC original protocol**: [Assetto Corsa — UDP Telemetry Protocol Specification](joplin://aed9f3be040943048273a16e05a8100f)\\\n- **ACC protocol**: [ACC — UDP Telemetry Protocol Specification](joplin://6ae7005d9810437093d63470cff98b59)\\\n- **AC EVO status**: [AC EVO — Telemetry Status & Research](joplin://2171d34ab9c1431ea3a979d30d206e23)\\\n- **AC Rally status**: [AC Rally — Telemetry Status & Research](joplin://b7b331aa87544b6ebe5db5b8d7bcd2a0)\\\n- **PCARS protocol**: [Project CARS 1 & 2 — UDP Telemetry Protocol Specification](joplin://c6bd2c45938246fa9d61776deae9874b)\\\n- **Main project plan**: [Sim Racing Telemetry Analysis Platform — Project Plan](joplin://6c0dcb2a567348fd9796f50c790082e4)\\\n\\\n---\\\n\\\n## Configuration\\\n\\\n### DiRT Rally 1\\\n- File: `My Games\\\\DiRT Rally\\\\hardwaresettings\\\\hardware_settings_config.xml`\\\n- Or in-game: Options → Telemetry → Enable\\\n- Settings:\\\n  ```xml\\\n  <motion>\\\n    <udp enabled=\\\"true\\\" ip=\\\"127.0.0.1\\\" port=\\\"20777\\\" delay=\\\"1\\\" />\\\n  </motion>\\\n  ```\\\n\\\n### DiRT Rally 2.0\\\n- File: `My Games\\\\DiRT Rally 2.0\\\\hardwaresettings\\\\hardware_settings_config.xml`\\\n- Or in-game: Options → Telemetry → Enable\\\n- Settings:\\\n  ```xml\\\n  <motion>\\\n    <udp enabled=\\\"true\\\" ip=\\\"127.0.0.1\\\" port=\\\"20777\\\" delay=\\\"1\\\" />\\\n  </motion>\\\n  ```\\\n\\\n### rusty-telemetry Bind Strategy\\\n- Bind UDP socket to `0.0.0.0:20777`\\\n- Game sends to `127.0.0.1:20777`\\\n- No registration or handshake needed\\\n\\\n---\\\n\\\n## DiRT Rally 1 — Telemetry Packet\\\n\\\n### Single Packet Format (All-in-One)\\\n\\\nTotal size: **~175 bytes**\\\n\\\n| Offset | Size | Type | Field | Notes |\\\n|---|---|---|---|---|\\\n| 0 | 4 | float32_le | time | Session time (seconds) |\\\n| 4 | 4 | float32_le | lap_time | Current lap time (seconds) |\\\n| 8 | 4 | float32_le | lap_distance | Distance into current lap (meters) |\\\n| 12 | 4 | float32_le | total_distance | Total distance (meters) |\\\n| 16 | 4 | float32_le | x_position | World position X |\\\n| 20 | 4 | float32_le | y_position | World position Y (up) |\\\n| 24 | 4 | float32_le | z_position | World position Z |\\\n| 28 | 4 | float32_le | speed | Speed (m/s) |\\\n| 32 | 4 | float32_le | x_velocity | World velocity X |\\\n| 36 | 4 | float32_le | y_velocity | World velocity Y |\\\n| 40 | 4 | float32_le | z_velocity | World velocity Z |\\\n| 44 | 4 | float32_le | x_roll | Roll vector X |\\\n| 48 | 4 | float32_le | y_roll | Roll vector Y |\\\n| 52 | 4 | float32_le | z_roll | Roll vector Z |\\\n| 56 | 4 | float32_le | x_pitch | Pitch vector X |\\\n| 60 | 4 | float32_le | y_pitch | Pitch vector Y |\\\n| 64 | 4 | float32_le | z_pitch | Pitch vector Z |\\\n| 68 | 4 | float32_le | x_suspension | Suspension position FL (meters) |\\\n| 72 | 4 | float32_le | x_suspension | Suspension position FR |\\\n| 76 | 4 | float32_le | x_suspension | Suspension position RL |\\\n| 80 | 4 | float32_le | x_suspension | Suspension position RR |\\\n| 84 | 4 | float32_le | x_velocity | Suspension velocity FL |\\\n| 88 | 4 | float32_le | x_velocity | Suspension velocity FR |\\\n| 92 | 4 | float32_le | x_velocity | Suspension velocity RL |\\\n| 96 | 4 | float32_le | x_velocity | Suspension velocity RR |\\\n| 100 | 4 | float32_le | x_wheel_speed | Wheel speed FL (m/s) |\\\n| 104 | 4 | float32_le | x_wheel_speed | Wheel speed FR |\\\n| 108 | 4 | float32_le | x_wheel_speed | Wheel speed RL |\\\n| 112 | 4 | float32_le | x_wheel_speed | Wheel speed RR |\\\n| 116 | 4 | float32_le | throttle | Throttle input 0.0–1.0 |\\\n| 120 | 4 | float32_le | steer | Steering -1.0 to 1.0 |\\\n| 124 | 4 | float32_le | brake | Brake input 0.0–1.0 |\\\n| 128 | 4 | float32_le | clutch | Clutch input 0.0–1.0 |\\\n| 132 | 4 | float32_le | handbrake | Handbrake 0.0–1.0 |\\\n| 136 | 1 | uint8 | gear | Current gear (0=N, 1-6=forward, -1=reverse) |\\\n| 137 | 4 | float32_le | g_force_lateral | Lateral G-force |\\\n| 141 | 4 | float32_le | g_force_longitudinal | Longitudinal G-force |\\\n| 145 | 4 | float32_le | lap | Current lap number |\\\n| 149 | 4 | float32_le | rpm | Engine RPM |\\\n| 153 | 4 | float32_le | slip_front | Front slip ratio |\\\n| 157 | 4 | float32_le | slip_rear | Rear slip ratio |\\\n| 161 | 4 | float32_le | x_angular_vel | Angular velocity X |\\\n| 165 | 4 | float32_le | y_angular_vel | Angular velocity Y |\\\n| 169 | 4 | float32_le | z_angular_vel | Angular velocity Z |\\\n\\\n> **Note**: DR1 packet format has minor variations depending on game version. Some community implementations report slightly different sizes (150–175 bytes). Verify against live captures.\\\n\\\n---\\\n\\\n## DiRT Rally 2.0 — Multi-Packet Format\\\n\\\nDR2 uses a **multi-packet model** similar to the F1 game series. The first byte of every packet is the **packet ID** that determines the structure.\\\n\\\n### Packet Header (all packets)\\\n\\\n| Offset | Size | Type | Field | Notes |\\\n|---|---|---|---|---|\\\n| 0 | 1 | uint8 | packet_id | Packet type identifier |\\\n| 1 | 1 | uint8 | packet_format | Game format version |\\\n\\\n### Packet Types\\\n\\\n| Packet ID | Name | Description |\\\n|---|---|---|\\\n| 0 | Motion | Car physics, suspension, G-forces |\\\n| 1 | Session | Session info, track, conditions |\\\n| 2 | Lap Data | Lap times, splits, best laps |\\\n| 3 | Event | Race events (start, finish, DNF) |\\\n| 4 | Participants | Driver info |\\\n| 5 | Car Setups | Setup data (tyres, suspension) |\\\n| 6 | Car Telemetry | Speed, RPM, gear, inputs, temps |\\\n| 7 | Car Status | Damage, fuel, tyre wear, DRS |\\\n\\\n> **Note**: DR2 shares the same protocol family as Codemasters F1 games but may not include all packet types. Rally-specific data (surface type, stage progress) is mixed into the existing packet types.\\\n\\\n### Packet 0: Motion Data\\\n\\\n| Offset | Size | Type | Field | Notes |\\\n|---|---|---|---|---|\\\n| 0 | 1 | uint8 | packet_id = 0 | |\\\n| 1 | 1 | uint8 | packet_format | |\\\n| 2 | 4 | float32_le | x_position | World X |\\\n| 6 | 4 | float32_le | y_position | World Y (up) |\\\n| 10 | 4 | float32_le | z_position | World Z |\\\n| 14 | 4 | float32_le | x_velocity | World velocity X |\\\n| 18 | 4 | float32_le | y_velocity | World velocity Y |\\\n| 22 | 4 | float32_le | z_velocity | World velocity Z |\\\n| 26 | 4 | float32_le | x_pitch | Pitch vector X |\\\n| 30 | 4 | float32_le | y_pitch | Pitch vector Y |\\\n| 34 | 4 | float32_le | z_pitch | Pitch vector Z |\\\n| 38 | 4 | float32_le | x_roll | Roll vector X |\\\n| 42 | 4 | float32_le | y_roll | Roll vector Y |\\\n| 46 | 4 | float32_le | z_roll | Roll vector Z |\\\n| 50 | 4 | float32_le | x_yaw | Yaw vector X |\\\n| 54 | 4 | float32_le | y_yaw | Yaw vector Y |\\\n| 58 | 4 | float32_le | z_yaw | Yaw vector Z |\\\n| 62 | 4 | float32_le | x_angular_vel | Angular velocity X |\\\n| 66 | 4 | float32_le | y_angular_vel | Angular velocity Y |\\\n| 70 | 4 | float32_le | z_angular_vel | Angular velocity Z |\\\n| 74 | 4 | float32_le | g_force_lateral | Lateral G |\\\n| 78 | 4 | float32_le | g_force_longitudinal | Longitudinal G |\\\n| 82 | 4 | float32_le | g_force_vertical | Vertical G |\\\n| 86 | 16 | float32_le × 4 | suspension_position | Per-wheel (FL, FR, RL, RR) |\\\n| 102 | 16 | float32_le × 4 | suspension_velocity | Per-wheel |\\\n| 118 | 16 | float32_le × 4 | suspension_acceleration | Per-wheel |\\\n| 134 | 16 | float32_le × 4 | wheel_speed | Per-wheel (m/s) |\\\n| 150 | 4 | float32_le | wheel_slip_ratio | Combined or front? (varies) |\\\n\\\n### Packet 6: Car Telemetry\\\n\\\n| Offset | Size | Type | Field | Notes |\\\n|---|---|---|---|---|\\\n| 0 | 1 | uint8 | packet_id = 6 | |\\\n| 1 | 1 | uint8 | packet_format | |\\\n| 2 | 4 | float32_le | speed | Speed (m/s) |\\\n| 6 | 2 | uint16_le | rpm | Engine RPM |\\\n| 8 | 2 | uint16_le | gear | Current gear |\\\n| 10 | 2 | uint16_le | suggested_gear | AI suggested gear |\\\n| 12 | 1 | uint8 | throttle | 0–255 |\\\n| 13 | 1 | int8 | steer | -127 to 127 |\\\n| 14 | 1 | uint8 | brake | 0–255 |\\\n| 15 | 1 | uint8 | clutch | 0–255 |\\\n| 16 | 1 | uint8 | handbrake | 0–255 |\\\n| 17 | 1 | uint8 | fuel | Fuel remaining 0–255 |\\\n| 18 | 4 | float32_le | engine_temp | Engine temperature (°C) |\\\n| 22 | 8 | uint16_le × 4 | brake_temp | Brake temp per wheel (°C) |\\\n| 30 | 8 | uint16_le × 4 | tyre_surface_temp | Tyre surface temp per wheel (°C) |\\\n| 38 | 8 | uint16_le × 4 | tyre_inner_temp | Tyre inner temp per wheel (°C) |\\\n| 46 | 8 | float32_le × 4 | tyre_pressure | Tyre pressure per wheel (PSI) |\\\n| 54 | 8 | float32_le × 4 | surface_type | Per-wheel surface type |\\\n\\\n### Surface Type Enumeration (DR2 Specific)\\\n\\\n```\\\n0 = Tarmac\\\n1 = Gravel\\\n2 = Mud\\\n3 = Snow\\\n4 = Ice\\\n5 = Grass\\\n6 = Sand/Dirt\\\n7 = Cobblestone\\\n```\\\n\\\nThis is **critical for rally coaching** — per-wheel surface type enables surface adaptation analysis.\\\n\\\n---\\\n\\\n## Rally-Specific Data in DiRT Rally\\\n\\\n### What DR1/DR2 Provide for Rally Coaching\\\n\\\n| Use Case | DR1 | DR2 | Data Source |\\\n|---|---|---|---|\\\n| **Surface detection** | ❌ | ✅ Per-wheel | surface_type in telemetry packet |\\\n| **Suspension analysis** | ✅ Position + velocity | ✅ Position + velocity + acceleration | Motion packet |\\\n| **Stage progress** | ✅ lap_distance | ✅ lap_distance | Treat stage as single lap |\\\n| **G-forces** | ✅ 2-axis | ✅ 3-axis | Motion packet |\\\n| **Wheel speeds** | ✅ Per-wheel | ✅ Per-wheel | Motion/telemetry |\\\n| **Tyre temperatures** | ❌ | ✅ Surface + inner | Telemetry packet |\\\n| **Tyre pressures** | ❌ | ✅ Per-wheel PSI | Telemetry packet |\\\n| **Handbrake input** | ✅ | ✅ | Telemetry packet |\\\n| **Car damage** | ❌ | ✅ (limited) | Status packet |\\\n| **Fuel** | ❌ | ✅ | Telemetry packet |\\\n| **World position** | ✅ | ✅ | Motion packet |\\\n| **Full orientation** | ❌ | ✅ Pitch + Roll + Yaw | Motion packet |\\\n| **Angular velocity** | ✅ 3-axis | ✅ 3-axis | Motion packet |\\\n| **Brake temps** | ❌ | ✅ Per-wheel | Telemetry packet |\\\n| **Multi-car** | ❌ | ❌ | Player car only |\\\n\\\n### Advantages over AC Rally (for coaching)\\\n\\\n1. **Available NOW** — both games are released and working\\\n2. **Per-wheel surface type** — the single most important rally coaching field\\\n3. **Suspension detail** — position + velocity + acceleration per wheel\\\n4. **Tyre thermal data** — surface + inner temps per wheel\\\n5. **Handbrake input** — critical for rally technique analysis\\\n6. **3-axis G-forces** — including vertical (jumps!)\\\n7. **Proven protocol** — same format as F1 series, well-documented by community\\\n\\\n### Limitations\\\n\\\n1. **No co-driver/pace note sync** — no way to correlate calls with data\\\n2. **No stage metadata** — stage name, surface type overview, stage length not in packets\\\n3. **No multi-car** — only player car data\\\n4. **No slip ratio/angle** — no tyre slip physics detail (unlike AC Telemetry Tool)\\\n5. **No spline position** — must calculate from world coordinates\\\n6. **No tyre wear model** — no degradation tracking\\\n\\\n---\\\n\\\n## Data Depth Comparison\\\n\\\n### vs AC Telemetry Tool (10101)\\\n\\\n| Capability | AC Telemetry Tool | DR2 UDP |\\\n|---|---|---|\\\n| Rate | 60 Hz | Up to 60 Hz |\\\n| G-forces | ✅ 3-axis | ✅ 3-axis |\\\n| Tyre slip detail | ✅ Ratio + angle + nd_slip | ❌ |\\\n| Tyre temps | ✅ Core temps | ✅ Surface + inner |\\\n| Surface type | ❌ | ✅ **Per-wheel** |\\\n| Handbrake | ❌ | ✅ |\\\n| Suspension | ✅ Ride height F/R | ✅ Per-wheel pos + vel + acc |\\\n| Tyre pressures | ❌ | ✅ Per-wheel PSI |\\\n| World position | ✅ | ✅ |\\\n| Velocity vectors | ✅ 3D world + local | ✅ 3D world |\\\n| Full orientation | ❌ | ✅ Pitch + Roll + Yaw |\\\n| Multi-car | ✅ | ❌ |\\\n| Damage | ❌ | ✅ (limited) |\\\n\\\n### vs AC Rally (Unknown Protocol)\\\n\\\n| Capability | AC Rally (predicted) | DR2 UDP (proven) |\\\n|---|---|---|\\\n| **Status** | Unknown (EA) | ✅ Working |\\\n| Surface type | Unknown | ✅ Per-wheel |\\\n| Tyre temps | Unknown | ✅ Per-wheel |\\\n| Suspension detail | Unknown | ✅ Per-wheel 3-axis |\\\n| Co-driver sync | Unknown | ❌ |\\\n| Pace note data | Unknown | ❌ |\\\n| Stage metadata | Unknown | ❌ |\\\n| Community tools | None | Multiple (SimHub, etc.) |\\\n\\\n---\\\n\\\n## Rust Implementation Plan\\\n\\\n### Recommended Port\\\n\\\n| Port | Use |\\\n|---|---|\\\n| 20777 | DiRT Rally 1 & 2 primary telemetry |\\\n\\\n### Parser Architecture\\\n\\\n```\\\nsrc/\\\n  parser_dirt_rally.rs    — Unified DR1 + DR2 parser\\\n```\\\n\\\n### Auto-Detection Strategy\\\n\\\n1. If packet size ~175 bytes and starts with a float (time > 0) → **DR1 format**\\\n2. If packet byte 0 is 0–7 (packet_id) and byte 1 is a known format version → **DR2 format**\\\n3. DR2 packets are dispatched by packet_id to type-specific parsers\\\n\\\n### Implementation Steps\\\n\\\n1. **DR1 parser**: Single all-in-one packet, straightforward binary parsing\\\n2. **DR2 packet dispatcher**: Read byte 0 for packet_id\\\n3. **DR2 Motion parser** (packet 0): Position, velocity, orientation, suspension, G-forces\\\n4. **DR2 Telemetry parser** (packet 6): Speed, RPM, gear, inputs, tyre temps, surface type\\\n5. **DR2 Session parser** (packet 1): Track info, conditions\\\n6. **DR2 Lap Data parser** (packet 2): Stage/lap times\\\n7. **DR2 Status parser** (packet 7): Damage, fuel\\\n\\\n### Estimated Effort\\\n\\\n- **DR1**: ~2 days (single packet, ~175 bytes)\\\n- **DR2**: ~5 days (multiple packet types, similar to F1 protocol)\\\n- **Total**: ~7 days\\\n\\\n### Priority\\\n\\\n**HIGH** — DiRT Rally 2.0 is the only rally sim with proven, documented telemetry that includes **per-wheel surface type**. This is the rally coaching differentiator we can ship NOW, while AC Rally telemetry is still unknown.\\\n\\\n---\\\n\\\n## Live Verification Needed\\\n\\\n**No DiRT Rally data has been captured yet.** Protocol structure is based on Codemasters community documentation and F1 series references (same protocol family). Verification requires:\\\n1. DiRT Rally 1 or 2.0 installed\\\n2. UDP telemetry enabled in `hardware_settings_config.xml`\\\n3. rusty-telemetry listening on port 20777\\\n4. Packet captures to verify byte offsets\\\n\\\nDR1 is frequently on sale for ~€5 on Steam. DR2 is ~€15.\\\n\\\n---\\\n\\\n## References\\\n\\\n- Codemasters community documentation (forum posts)\\\n- F1 series UDP specs (same protocol family, well-documented)\\\n- Community implementations: Python/C# DiRT Rally telemetry tools\\\n- SimHub DR2 plugin (reference implementation)\\\n\\\n---\\\n\\\n*Created: 2026-06-06*\\\n*Status: Research phase — no live verification yet*\\\n*Next step: Purchase DR2, enable UDP, capture and verify packets*\\\n*Strategic note: This is the fastest path to rally telemetry coaching — proven protocol, available now*\"]],\"start1\":0,\"start2\":0,\"length1\":0,\"length2\":14802}]"
metadata_diff: {"new":{"id":"877a753ad06a40e08059834d8c8fb438","parent_id":"94aa3283ead4477d8449e324a27eb3d0","latitude":"0.00000000","longitude":"0.00000000","altitude":"0.0000","author":"","source_url":"","is_todo":0,"todo_due":0,"todo_completed":0,"source":"joplin-desktop","source_application":"net.cozic.joplin-desktop","application_data":"","order":1780733841418,"markup_language":1,"is_shared":0,"share_id":"","conflict_original_id":"","master_key_id":"","user_data":"","deleted_time":0},"deleted":[]}
encryption_cipher_text: 
encryption_applied: 0
updated_time: 2026-06-06T08:30:20.882Z
created_time: 2026-06-06T08:30:20.882Z
type_: 13