diff --git a/.gitignore b/.gitignore index 8f28023..a460a65 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ tests/setsimdata simd/build +.cache/ +tests/view_telemetry +simmapper_mixed.c +simmapper_old.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c152201..6c2d7e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.9) project(simapi VERSION 1.0.1 DESCRIPTION "Telemetry Mapping Library for Racing Sims") include(GNUInstallDirs) -add_library(simapi SHARED simapi/simmapper.c simapi/getpid.c simapi/mapping/acmapper.c simapi/mapping/pcars2mapper.c simapi/mapping/rf2mapper.c simapi/mapping/scs2mapper.c simapi/mapping/outgaugemapper.c) +add_library(simapi SHARED simapi/simmapper.c simapi/getpid.c simapi/mapping/acmapper.c simapi/mapping/pcars2mapper.c simapi/mapping/rf2mapper.c simapi/mapping/scs2mapper.c simapi/mapping/outgaugemapper.c simapi/mapping/dirt2mapper.c) set(SIMAPI_PUBLIC_HEADERS "simapi/simmapper.h" @@ -20,3 +20,6 @@ install(TARGETS simapi PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(FILES ${CMAKE_BINARY_DIR}/simapi.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig) + +add_executable(view_telemetry tests/view_telemetry.c) +target_link_libraries(view_telemetry simapi m) diff --git a/docs/UDP_SUPPORT.md b/docs/UDP_SUPPORT.md new file mode 100644 index 0000000..e5e1904 --- /dev/null +++ b/docs/UDP_SUPPORT.md @@ -0,0 +1,46 @@ +# UDP Telemetry Support in SimAPI + +SimAPI supports simulators that output telemetry data over UDP. This document explains the architecture and how to implement support for new UDP-based simulators. + +## Architecture Overview + +The UDP support is integrated into the `simd` daemon and the `simapi` library. + +### 1. Reception (simd) + +The `simd` daemon handles the UDP socket lifecycle: +- **Initialization**: `startudp(port)` initializes a `uv_udp_t` socket using `libuv`. +- **Callback**: `on_udp_recv` is triggered whenever a packet arrives. +- **Data Flow**: The raw buffer is passed to `simdatamap` with the `udp` flag set to `true`. + +```mermaid +graph TD + A[Simulator] -->|UDP Packet| B[simd: on_udp_recv] + B --> C[simapi: simdatamap] + C --> D[simapi: map_xxx_data] + D --> E[Shared Memory: SimData] +``` + +### 2. Mapping (simapi) + +The mapping logic resides in `simapi/mapping/`. For UDP simulators, the `base` parameter in `map_xxx_data` points to the raw packet buffer. + +- **DiRT Rally 2.0**: Uses `map_dirt_rally_2_data` to process the "extradata=3" packet. +- **Inputs**: Raw fields like throttle/brake are mapped directly to `SimData`. +- **Calculations**: Some values (like Lateral G-force or Euler angles) are derived from world vectors and velocities. + +## Implementing New UDP Simulators + +To add support for a new UDP-based simulator: + +1. **Define Packet Structure**: Create a header in `include/` (e.g., `mynewsimdata.h`) with the packed struct representing the UDP packet. +2. **Add Mapper**: Create `simapi/mapping/mynewsimmapper.c` and implement the mapping function. +3. **Update simmapper.c**: + - Add the new simulator to `SimulatorEXE` and `SimulatorAPI` enums. + - Update `getSim` to detect the running process and call `setup_udp(port)`. + - Update `simdatamap` to call your new mapper. +4. **Update simmap.h**: Add a struct for the new simulator to the `SimMap` union to persist state (if needed, e.g., for acceleration calculations). + +## Configuration + +UDP support usually requires zero-configuration in `simapi` as it automatically detects the simulator and binds to the correct port. However, ensured the simulator itself is configured to send data to `127.0.0.1` on the expected port (e.g., `20777` for DiRT Rally 2.0). diff --git a/include/dirt2data.h b/include/dirt2data.h new file mode 100644 index 0000000..4ef6837 --- /dev/null +++ b/include/dirt2data.h @@ -0,0 +1,103 @@ +#ifndef _DIRT2DATA_H +#define _DIRT2DATA_H + +#include + +#pragma pack(push, 1) + +// DiRT Rally 2.0 UDP packet structure (extradata=3) +// 66 floats (264 bytes) +/** + * @struct DR2_UDP_ExtraData3 + * @brief DiRT Rally 2.0 UDP packet structure for "extradata=3". + * + * This structure contains 66 floating point values (264 bytes total). + * Data is sent in little-endian format. + */ +typedef struct { + float runTime; /**< Total time the session has been running + (seconds) */ + float lapTime; /**< Current lap time (seconds) */ + float distance; /**< [UNVERIFIED] Total distance travelled in the session + (meters) */ + float progress; /**< Current lap progress (0.0 to 1.0, accumulative for each + lap) */ + float posX; /**< World position X (East/West) */ + float posY; /**< World position Y (Up/Down) */ + float posZ; /**< World position Z (North/South) */ + float speed; /**< Speed (m/s) */ + float velX; /**< Velocity in world X direction */ + float velY; /**< Velocity in world Y direction */ + float velZ; /**< Velocity in world Z direction */ + float rightX; /**< Local right vector X component */ + float rightY; /**< Local right vector Y component */ + float rightZ; /**< Local right vector Z component */ + float forwardX; /**< Local forward vector X component */ + float forwardY; /**< Local forward vector Y component */ + float forwardZ; /**< Local forward vector Z component */ + float suspRL; /**< Suspension position Rear Left */ + float suspRR; /**< Suspension position Rear Right */ + float suspFL; /**< Suspension position Front Left */ + float suspFR; /**< Suspension position Front Right */ + float suspVelRL; /**< Suspension velocity Rear Left */ + float suspVelRR; /**< Suspension velocity Rear Right */ + float suspVelFL; /**< Suspension velocity Front Left */ + float suspVelFR; /**< Suspension velocity Front Right */ + float wheelSpeedRL; /**< Wheel speed Rear Left (m/s) */ + float wheelSpeedRR; /**< Wheel speed Rear Right (m/s) */ + float wheelSpeedFL; /**< Wheel speed Front Left (m/s) */ + float wheelSpeedFR; /**< Wheel speed Front Right (m/s) */ + float throttle; /**< Throttle input (0.0 to 1.0) */ + float steering; /**< Steering input (-1.0 to 1.0) */ + float brake; /**< Brake input (0.0 to 1.0) */ + float clutch; /**< Clutch input (0.0 to 1.0) */ + float gear; /**< Current gear (0=neutral, 1-10=gears, -1=reverse) */ + float gForceLat; /**< Lateral G-Force (Field 34) */ + float gForceLon; /**< Longitudinal G-Force (Field 35) */ + float lap; /**< Current lap number */ + float engineRPM; /**< Engine RPM (raw value is RPM / 10) */ + float sliProSupport; /**< [UNVERIFIED] Sli-Pro support data */ + float racePos; /**< Current race position */ + float kersLevel; /**< [UNVERIFIED] KERS level (likely unused in DR2) */ + float kersMaxLevel; /**< [UNVERIFIED] KERS max level (likely unused in DR2) */ + float drs; /**< [UNVERIFIED] DRS status (likely unused in DR2) */ + float tractionControl; /**< [UNVERIFIED] Traction control setting/activity */ + float antiLockBrakes; /**< [UNVERIFIED] ABS setting/activity */ + float fuelInTank; /**< Current fuel in tank (liters) (always 0.0) */ + float fuelCapacity; /**< Fuel tank capacity (liters) (always 0.0) */ + float inPit; /**< [UNVERIFIED] Pit lane status (0=on track, 1=in pit) */ + float sector; /**< Current sector index */ + float sector1Time; /**< Time for sector 1 (seconds) */ + float sector2Time; /**< Time for sector 2 (seconds) */ + float brakesTempRL; /**< Brake temperature Rear Left (Celsius) */ + float brakesTempRR; /**< Brake temperature Rear Right (Celsius) */ + float brakesTempFL; /**< Brake temperature Front Left (Celsius) */ + float brakesTempFR; /**< Brake temperature Front Right (Celsius) */ + float tyrePressureRL; /**< Tyre pressure Rear Left (always 0.0) */ + float tyrePressureRR; /**< Tyre pressure Rear Right (always 0.0) */ + float tyrePressureFL; /**< Tyre pressure Front Left (always 0.0) */ + float tyrePressureFR; /**< Tyre pressure Front Right (always 0.0) */ + float lapsCompleted; /**< Number of laps completed */ + float totalLaps; /**< Total laps in session */ + float trackLength; /**< Track length (meters) */ + float lastLapTime; /**< Duration of the last completed lap (seconds) */ + float maxRPM; /**< Maximum engine RPM (raw value is RPM / 10) */ + float idleRPM; /**< Idle engine RPM (raw value is RPM / 10) */ + float maxGears; /**< Maximum number of gears */ +} DR2_UDP_ExtraData3; + +// Main packet structure using a union for both named field access and array +// access +struct dirt2_udp_packet { + union { + float data[66]; + DR2_UDP_ExtraData3 fields; + }; +}; + +#pragma pack(pop) + +// Note: This structure is based on DiRT Rally 2.0 extradata=3 specification. +// Gear mapping: 0=neutral, 1-10=gears, -1=reverse. + +#endif diff --git a/simapi/dirt2.h b/simapi/dirt2.h new file mode 100644 index 0000000..902e509 --- /dev/null +++ b/simapi/dirt2.h @@ -0,0 +1,22 @@ +#ifndef _DIRT2_H +#define _DIRT2_H + +#include +#include "../include/dirt2data.h" + +#define DIRT_RALLY_2_EXE "dirtrally2.exe" + +typedef struct +{ + bool has_telemetry; + struct dirt2_udp_packet dirt2_telemetry; + float last_velX; + float last_velY; + float last_velZ; + float last_runTime; + bool has_last_vel; +} +Dirt2Map; + +#endif + diff --git a/simapi/mapping/dirt2mapper.c b/simapi/mapping/dirt2mapper.c new file mode 100644 index 0000000..55a8116 --- /dev/null +++ b/simapi/mapping/dirt2mapper.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#include "../../include/dirt2data.h" +#include "../simdata.h" +#include "../simmap.h" +#include "../simmapper.h" + +#define DR2_RPM_SCALE 10.0f + +static int froundint(float f) { return (int)trunc(nearbyint(f)); } + +/** + * @brief Maps raw DiRT Rally 2.0 UDP telemetry to the universal SimData + * structure. + * + * DiRT Rally 2.0 sends UDP packets in the "extradata=3" format. This function + * extracts those fields and maps them to the common SimData format used by + * SimAPI. + * + * Key mapping highlights: + * - RPM: Scaled by 10.0 (internal game representation). + * - Gear: Shifted by +1 to match SimAPI range (0=R, 1=N, 2=1st...). + * - Euler Angles: Derived from the Forward and Right vectors provided in the + * UDP packet. + * - G-Forces: Lateral (X) and Longitudinal (Y) are provided directly by the + * game. + * + * @param simdata The target SimData structure to populate. + * @param simmap The simulator mapping context. + * @param base Raw UDP packet pointer. + */ +void map_dirt_rally_2_data(SimData *simdata, SimMap *simmap, char *base) { + if (base != NULL) { + struct dirt2_udp_packet *packet = (struct dirt2_udp_packet *)base; + + if (simmap != NULL) { + memcpy(&simmap->dirt2.dirt2_telemetry, packet, + sizeof(struct dirt2_udp_packet)); + simmap->dirt2.has_telemetry = true; + } + + // Basic telemetry + simdata->rpms = froundint(packet->fields.engineRPM * DR2_RPM_SCALE); + simdata->velocity = froundint(packet->fields.speed * 3.6f); // m/s to km/h + + // Gear mapping: game(-1..10) -> simapi(0..11) + float raw_gear = packet->fields.gear; + int gear_int = (int)raw_gear; + + if (gear_int < 0) { + simdata->gear = 0; // Reverse + } else { + simdata->gear = (uint32_t)gear_int + 1; + } + + simdata->maxrpm = froundint(packet->fields.maxRPM * DR2_RPM_SCALE); + + // Character representation of gear + if (simdata->gear == 0) { + strcpy(simdata->gearc, "R"); + } else if (simdata->gear == 1) { + strcpy(simdata->gearc, "N"); + } else { + sprintf(simdata->gearc, "%d", simdata->gear - 1); + } + + // Input mapping (already 0.0 to 1.0) + simdata->gas = (double)packet->fields.throttle; + simdata->steer = (double)packet->fields.steering; + simdata->brake = (double)packet->fields.brake; + simdata->clutch = (double)packet->fields.clutch; + + // World Velocities + simdata->worldXvelocity = (double)packet->fields.velX; + simdata->worldYvelocity = (double)packet->fields.velY; + simdata->worldZvelocity = (double)packet->fields.velZ; + + // Orientation Vectors (DiRT Rally 2.0 extradata=3 provides Right and + // Forward) + float rx = packet->fields.rightX; + float ry = packet->fields.rightY; + float rz = packet->fields.rightZ; + float fx = packet->fields.forwardX; + float fy = packet->fields.forwardY; + float fz = packet->fields.forwardZ; + + // Up Vector = Forward x Right (Cross Product) + float ux = fy * rz - fz * ry; + float uy = fz * rx - fx * rz; + float uz = fx * ry - fy * rx; + + // G-Forces / Accelerations + // Lateral and Longitudinal are provided directly by the game. + simdata->Xvelocity = (double)packet->fields.gForceLat; + simdata->Yvelocity = (double)packet->fields.gForceLon; + simdata->Zvelocity = + 0.0; // Vertical G-force not explicitly provided in 66-float struct + + // Store vectors in SimData for legacy support or debugging + simdata->tyrecontact0[0] = (double)rx; + simdata->tyrecontact0[1] = (double)ry; + simdata->tyrecontact0[2] = (double)rz; + simdata->tyrecontact1[0] = (double)ux; + simdata->tyrecontact1[1] = (double)uy; + simdata->tyrecontact1[2] = (double)uz; + simdata->tyrecontact2[0] = (double)fx; + simdata->tyrecontact2[1] = (double)fy; + simdata->tyrecontact2[2] = (double)fz; + + // Convert vectors to Euler angles (Degrees) + // 1. Yaw (Heading): Direction the car is facing in the XZ plane + simdata->heading = atan2((double)fx, (double)fz) * (180.0 / M_PI); + + // 2. Pitch (Nose Up +) + double pitch_input = fmax(-1.0f, fmin(1.0f, (double)fy)); + simdata->pitch = asin(pitch_input) * (180.0 / M_PI); + + // 3. Roll (Right side down +) + simdata->roll = atan2((double)-ry, (double)uy) * (180.0 / M_PI); + + // Wheel Speeds (m/s) + simdata->tyreRPS[0] = (double)packet->fields.wheelSpeedRL; + simdata->tyreRPS[1] = (double)packet->fields.wheelSpeedRR; + simdata->tyreRPS[2] = (double)packet->fields.wheelSpeedFL; + simdata->tyreRPS[3] = (double)packet->fields.wheelSpeedFR; + + // Game Status + // DiRT Rally 2.0 extradata=3 is typically only sent when the simulation is + // active. We set status to ACTIVEPLAY even if runTime is 0 to support Rally + // Cross countdowns where telemetry starts before the clock. + if (packet->fields.runTime >= 0) { + simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; + } else { + simdata->simstatus = SIMAPI_STATUS_MENU; + } + + // Lap and Progress + simdata->lap = (uint32_t)packet->fields.lap; + simdata->trackdistancearound = (double)packet->fields.trackLength; + simdata->playerspline = (double)packet->fields.progress; + + // Position + simdata->worldposx = (double)packet->fields.posX; + simdata->worldposy = (double)packet->fields.posY; + simdata->worldposz = (double)packet->fields.posZ; + + // Fluids + simdata->fuel = (double)packet->fields.fuelInTank; + + // Brake Temperatures + simdata->braketemp[0] = (double)packet->fields.brakesTempRL; + simdata->braketemp[1] = (double)packet->fields.brakesTempRR; + simdata->braketemp[2] = (double)packet->fields.brakesTempFL; + simdata->braketemp[3] = (double)packet->fields.brakesTempFR; + + // Tyre Pressures + simdata->tyrepressure[0] = (double)packet->fields.tyrePressureRL; + simdata->tyrepressure[1] = (double)packet->fields.tyrePressureRR; + simdata->tyrepressure[2] = (double)packet->fields.tyrePressureFL; + simdata->tyrepressure[3] = (double)packet->fields.tyrePressureFR; + + // Suspension positions + simdata->suspension[0] = (double)packet->fields.suspRL; + simdata->suspension[1] = (double)packet->fields.suspRR; + simdata->suspension[2] = (double)packet->fields.suspFL; + simdata->suspension[3] = (double)packet->fields.suspFR; + + simdata->suspvelocity[0] = (double)packet->fields.suspVelRL; + simdata->suspvelocity[1] = (double)packet->fields.suspVelRR; + simdata->suspvelocity[2] = (double)packet->fields.suspVelFL; + simdata->suspvelocity[3] = (double)packet->fields.suspVelFR; + + simdata->distance = (double)packet->fields.distance; + simdata->position = (uint32_t)packet->fields.racePos; + simdata->numlaps = (uint32_t)packet->fields.totalLaps; + simdata->playerlaps = (uint32_t)packet->fields.lapsCompleted; + simdata->sectorindex = (uint8_t)packet->fields.sector; + simdata->sector1time = (double)packet->fields.sector1Time; + simdata->sector2time = (double)packet->fields.sector2Time; + simdata->fuelcapacity = (double)packet->fields.fuelCapacity; + simdata->idlerpm = froundint(packet->fields.idleRPM * DR2_RPM_SCALE); + simdata->maxgears = (uint32_t)packet->fields.maxGears; + + // Timing + simdata->currentlapinseconds = (uint32_t)packet->fields.lapTime; + simdata->lastlapinseconds = (uint32_t)packet->fields.lastLapTime; + + // Splitting seconds into LapTime + simdata->currentlap.hours = (uint32_t)(packet->fields.lapTime / 3600); + simdata->currentlap.minutes = + (uint32_t)(((int)packet->fields.lapTime % 3600) / 60); + simdata->currentlap.seconds = (uint32_t)((int)packet->fields.lapTime % 60); + simdata->currentlap.fraction = + (uint32_t)((packet->fields.lapTime - floor(packet->fields.lapTime)) * + 1000); + + simdata->lastlap.hours = (uint32_t)(packet->fields.lastLapTime / 3600); + simdata->lastlap.minutes = + (uint32_t)(((int)packet->fields.lastLapTime % 3600) / 60); + simdata->lastlap.seconds = (uint32_t)((int)packet->fields.lastLapTime % 60); + simdata->lastlap.fraction = (uint32_t)((packet->fields.lastLapTime - + floor(packet->fields.lastLapTime)) * + 1000); + + strncpy(simdata->car, "DR2", 4); + } +} diff --git a/simapi/simapi.h b/simapi/simapi.h index 67a23dc..29cf131 100644 --- a/simapi/simapi.h +++ b/simapi/simapi.h @@ -27,6 +27,7 @@ typedef enum SIMULATORAPI_PROJECTCARS2 = 3, SIMULATORAPI_SCSTRUCKSIM2 = 4, SIMULATORAPI_OUTSIMOUTGAUGE = 5, + SIMULATORAPI_DIRT_RALLY_2 = 6, } SimulatorAPI; @@ -44,6 +45,7 @@ typedef enum SIMULATOREXE_LEMANS_ULTIMATE = 2399420, //lmu SIMULATOREXE_BEAMNG = 284160, //beamng SIMULATOREXE_LIVE_FOR_SPEED = 0000001, //lfs + SIMULATOREXE_DIRT_RALLY_2 = 690790, //dr2 } SimulatorEXE; diff --git a/simapi/simdata.h b/simapi/simdata.h index 02150c0..3391308 100755 --- a/simapi/simdata.h +++ b/simapi/simdata.h @@ -1,187 +1,190 @@ #ifndef _SIMDATA_H #define _SIMDATA_H -#include #include +#include #define MAXCARS 24 #define PROXCARS 6 -typedef enum -{ - SIMAPI_STATUS_OFF = 0, - SIMAPI_STATUS_MENU = 1, - SIMAPI_STATUS_ACTIVEPLAY = 2, -} -SIMAPI_STATUS; - -typedef enum -{ - SIMAPI_FLAG_GREEN = 0, - SIMAPI_FLAG_YELLOW = 1, - SIMAPI_FLAG_RED = 2, - SIMAPI_FLAG_CHEQUERED = 3, - SIMAPI_FLAG_BLUE = 4, - SIMAPI_FLAG_WHITE = 5, - SIMAPI_FLAG_BLACK = 6, - SIMAPI_FLAG_BLACK_WHITE = 7, - SIMAPI_FLAG_BLACK_ORANGE = 8, - SIMAPI_FLAG_ORANGE = 9 -} -SIMAPI_FLAG; - -typedef enum -{ - SIMAPI_GEAR_REVERSE = 0, - SIMAPI_GEAR_NEUTRAL = 1, - SIMAPI_GEAR_FIRST = 2, - SIMAPI_GEAR_SECOND = 3, - SIMAPI_GEAR_THIRD = 4, - SIMAPI_GEAR_FOURTH = 5, - SIMAPI_GEAR_FIFTH = 6, - SIMAPI_GEAR_SIXTH = 7, - SIMAPI_GEAR_SEVENTH = 8, - SIMAPI_GEAR_EIGHT = 9 -} -SIMAPI_GEAR; - +typedef enum { + SIMAPI_STATUS_OFF = 0, + SIMAPI_STATUS_MENU = 1, + SIMAPI_STATUS_ACTIVEPLAY = 2, +} SIMAPI_STATUS; + +typedef enum { + SIMAPI_FLAG_GREEN = 0, + SIMAPI_FLAG_YELLOW = 1, + SIMAPI_FLAG_RED = 2, + SIMAPI_FLAG_CHEQUERED = 3, + SIMAPI_FLAG_BLUE = 4, + SIMAPI_FLAG_WHITE = 5, + SIMAPI_FLAG_BLACK = 6, + SIMAPI_FLAG_BLACK_WHITE = 7, + SIMAPI_FLAG_BLACK_ORANGE = 8, + SIMAPI_FLAG_ORANGE = 9 +} SIMAPI_FLAG; + +typedef enum { + SIMAPI_GEAR_REVERSE = 0, + SIMAPI_GEAR_NEUTRAL = 1, + SIMAPI_GEAR_FIRST = 2, + SIMAPI_GEAR_SECOND = 3, + SIMAPI_GEAR_THIRD = 4, + SIMAPI_GEAR_FOURTH = 5, + SIMAPI_GEAR_FIFTH = 6, + SIMAPI_GEAR_SIXTH = 7, + SIMAPI_GEAR_SEVENTH = 8, + SIMAPI_GEAR_EIGHT = 9 +} SIMAPI_GEAR; #pragma pack(push) #pragma pack(4) -typedef struct //LapTime +typedef struct // LapTime { - uint32_t hours; - uint32_t minutes; - uint32_t seconds; - uint32_t fraction; + uint32_t hours; + uint32_t minutes; + uint32_t seconds; + uint32_t fraction; } LapTime; -typedef struct //CarData +typedef struct // CarData { - double xpos; - double ypos; - double zpos; - double carspline; - double speed; - uint32_t pos; - uint32_t lap; - uint32_t trackpos; - LapTime lastlap; - LapTime bestlap; - // not all of these are set by each sim - bool inpit; // no matter what, if you're in the pit set this - bool inpitlane; // in pit lane, actively entering or exiting, but not stopped or in garage - bool ingarage; // not always available - bool inpitentrance; // not always available - bool inpitexit; // not always available - bool inpitstopped; // not always available - char driver[128]; - char car[128]; + double xpos; + double ypos; + double zpos; + double carspline; + double speed; + uint32_t pos; + uint32_t lap; + uint32_t trackpos; + LapTime lastlap; + LapTime bestlap; + // not all of these are set by each sim + bool inpit; // no matter what, if you're in the pit set this + bool inpitlane; // in pit lane, actively entering or exiting, but not stopped + // or in garage + bool ingarage; // not always available + bool inpitentrance; // not always available + bool inpitexit; // not always available + bool inpitstopped; // not always available + char driver[128]; + char car[128]; } CarData; -typedef struct //ProximityData +typedef struct // ProximityData { - double radius; - double theta; // in degrees - uint32_t lap; + double radius; + double theta; // in degrees + uint32_t lap; } ProximityData; -typedef struct //SimData +typedef struct // SimData { - uint64_t mtick; - - uint32_t simstatus; // less than 1 is off or in menu, 2 is active - uint32_t velocity; - uint32_t rpms; - uint32_t gear; - uint32_t pulses; - uint32_t maxrpm; - uint32_t altitude; - uint32_t lap; - uint32_t position; - uint32_t numlaps; - uint32_t playerlaps; - uint32_t numcars; - char gearc[3]; - - double Xvelocity; - double Yvelocity; - double Zvelocity; - - double worldXvelocity; - double worldYvelocity; - double worldZvelocity; - - double gas; - double brake; - double fuel; - double clutch; - double steer; - double handbrake; - - double turboboost; - double turboboostperct; - double maxturbo; - - double abs; - double brakebias; - double tyreRPS[4]; - double tyrediameter[4]; - - double heading; - double worldposx; - double worldposy; - double worldposz; - - double braketemp[4]; - double tyrewear[4]; - double tyretemp[4]; - double tyrepressure[4]; - - double tyrecontact0[4]; - double tyrecontact1[4]; - double tyrecontact2[4]; - - double airdensity; - double airtemp; - double tracktemp; - - double suspension[4]; - - double trackdistancearound; - double playerspline; - double trackspline; - uint32_t playertrackpos; - uint32_t tracksamples; - - LapTime lastlap; - LapTime bestlap; - LapTime currentlap; - uint32_t currentlapinseconds; - uint32_t lastlapinseconds; - uint32_t time; - LapTime sessiontime; - uint8_t session; - uint8_t sectorindex; - uint32_t lastsectorinms; - uint8_t courseflag; - uint8_t playerflag; - - bool lapisvalid; - - char car[128]; - char track[128]; - char driver[128]; - char tyrecompound[128]; - - CarData cars[MAXCARS]; - ProximityData pd[PROXCARS]; - - uint8_t simapi; - uint64_t simexe; - bool simon; - uint8_t simapiversion; + uint64_t mtick; + + uint32_t simstatus; // less than 1 is off or in menu, 2 is active + uint32_t velocity; + uint32_t rpms; + uint32_t gear; + uint32_t pulses; + uint32_t maxrpm; + uint32_t idlerpm; + uint32_t maxgears; + uint32_t altitude; + uint32_t lap; + uint32_t position; + uint32_t numlaps; + uint32_t playerlaps; + uint32_t numcars; + char gearc[3]; + + double Xvelocity; + double Yvelocity; + double Zvelocity; + + double worldXvelocity; + double worldYvelocity; + double worldZvelocity; + + double gas; + double brake; + double fuel; + double fuelcapacity; + double clutch; + double steer; + double handbrake; + + double turboboost; + double turboboostperct; + double maxturbo; + + double abs; + double brakebias; + double tyreRPS[4]; + double tyrediameter[4]; + double distance; + + double heading; + double pitch; + double roll; + double worldposx; + double worldposy; + double worldposz; + + double braketemp[4]; + double tyrewear[4]; + double tyretemp[4]; + double tyrepressure[4]; + + double tyrecontact0[4]; + double tyrecontact1[4]; + double tyrecontact2[4]; + + double airdensity; + double airtemp; + double tracktemp; + + double suspension[4]; + double suspvelocity[4]; + + double trackdistancearound; + double playerspline; + double trackspline; + uint32_t playertrackpos; + uint32_t tracksamples; + + LapTime lastlap; + LapTime bestlap; + LapTime currentlap; + uint32_t currentlapinseconds; + uint32_t lastlapinseconds; + uint32_t time; + LapTime sessiontime; + uint8_t session; + uint8_t sectorindex; + double sector1time; + double sector2time; + uint32_t lastsectorinms; + uint8_t courseflag; + uint8_t playerflag; + + bool lapisvalid; + + char car[128]; + char track[128]; + char driver[128]; + char tyrecompound[128]; + + CarData cars[MAXCARS]; + ProximityData pd[PROXCARS]; + + uint8_t simapi; + uint64_t simexe; + bool simon; + uint8_t simapiversion; } SimData; #pragma pack(pop) diff --git a/simapi/simmap.h b/simapi/simmap.h index ee44b63..96168c9 100644 --- a/simapi/simmap.h +++ b/simapi/simmap.h @@ -5,6 +5,7 @@ #include "rf2.h" #include "pcars2.h" #include "scs2.h" +#include "dirt2.h" struct _simmap { @@ -16,6 +17,7 @@ struct _simmap RF2Map rf2; PCars2Map pcars2; SCS2Map scs2; + Dirt2Map dirt2; }; #endif diff --git a/simapi/simmapper.c b/simapi/simmapper.c index 1dd47c3..e2569b0 100755 --- a/simapi/simmapper.c +++ b/simapi/simmapper.c @@ -1,445 +1,386 @@ +#include +#include +#include +#include #include +#include #include #include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include #include -#include "simdata.h" -#include "simapi.h" -#include "simmapper.h" -#include "test.h" #include "ac.h" -#include "rf2.h" +#include "dirt2.h" +#include "outgauge.h" #include "pcars2.h" +#include "rf2.h" #include "scs2.h" -#include "outgauge.h" +#include "simapi.h" +#include "simdata.h" #include "simmap.h" +#include "simmapper.h" +#include "test.h" #include #include #if defined(OS_WIN) - #include +#include #else - #include // for *Nix directory access - #include +#include // for *Nix directory access +#include #endif -#include "getpid.h" -#include "../include/f12018.h" #include "../include/acdata.h" -#include "../include/rf2data.h" -#include "../include/pcars2data.h" +#include "../include/f12018.h" #include "../include/outgauge.h" +#include "../include/pcars2data.h" +#include "../include/rf2data.h" #include "../include/scs2data.h" +#include "getpid.h" - -SimMap* createSimMap() -{ - SimMap* ptr = malloc(sizeof(SimMap)); - ptr->fd = -1; - ptr->addr = 0; - return ptr; +SimMap *createSimMap() { + SimMap *ptr = malloc(sizeof(SimMap)); + ptr->fd = -1; + ptr->addr = 0; + return ptr; } -void* getSimMapPtr(SimMap* simmap) -{ - return simmap->addr; -} +void *getSimMapPtr(SimMap *simmap) { return simmap->addr; } -int sstrcicmp(char const *a, char const *b) -{ - for (;; a++, b++) { - int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); - if (d != 0 || !*a) - return d; - } +int sstrcicmp(char const *a, char const *b) { + for (;; a++, b++) { + int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); + if (d != 0 || !*a) + return d; + } } long long timeInMilliseconds(void) { - struct timeval tv; + struct timeval tv; - gettimeofday(&tv,NULL); - return (((long long)tv.tv_sec)*1000)+(tv.tv_usec/1000); + gettimeofday(&tv, NULL); + return (((long long)tv.tv_sec) * 1000) + (tv.tv_usec / 1000); } -bool does_sim_need_bridge(SimulatorEXE s) -{ - if(s == SIMULATOREXE_ASSETTO_CORSA || s == SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE || s == SIMULATOREXE_ASSETTO_CORSA_EVO || s == SIMULATOREXE_ASSETTO_CORSA_RALLY) - { - return true; - } +bool does_sim_need_bridge(SimulatorEXE s) { + if (s == SIMULATOREXE_ASSETTO_CORSA || + s == SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE || + s == SIMULATOREXE_ASSETTO_CORSA_EVO || + s == SIMULATOREXE_ASSETTO_CORSA_RALLY) { + return true; + } - if(s == SIMULATOREXE_AUTOMOBILISTA2) - { - return true; - } - return false; + if (s == SIMULATOREXE_AUTOMOBILISTA2) { + return true; + } + return false; } -int simapi_strtogame(const char* game) -{ - int sim = 0; - if (sstrcicmp(game, "ac") == 0) - { - sim = SIMULATOREXE_ASSETTO_CORSA; - } - else if (sstrcicmp(game, "acc") == 0) - { - sim = SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE; - } - else if (sstrcicmp(game, "ace") == 0) - { - sim = SIMULATOREXE_ASSETTO_CORSA_EVO; - } - else if (sstrcicmp(game, "acr") == 0) - { - sim = SIMULATOREXE_ASSETTO_CORSA_RALLY; - } - else if (sstrcicmp(game, "rf2") == 0) - { - sim = SIMULATOREXE_RFACTOR2; - } - else if (sstrcicmp(game, "ams2") == 0) - { - sim = SIMULATOREXE_AUTOMOBILISTA2; - } - else if (sstrcicmp(game, "et2") == 0) - { - sim = SIMULATOREXE_EUROTRUCKS2; - } - else if (sstrcicmp(game, "at") == 0) - { - sim = SIMULATOREXE_EUROTRUCKS2; - } - else if (sstrcicmp(game, "lmu") == 0) - { - sim = SIMULATOREXE_LEMANS_ULTIMATE; - } - else if (sstrcicmp(game, "lfs") == 0) - { - sim = SIMULATOREXE_LIVE_FOR_SPEED; - } - else if (sstrcicmp(game, "beamng") == 0) - { - sim = SIMULATOREXE_BEAMNG; - } - else - { - sim = 0; - } - return sim; +int simapi_strtogame(const char *game) { + int sim = 0; + if (sstrcicmp(game, "ac") == 0) { + sim = SIMULATOREXE_ASSETTO_CORSA; + } else if (sstrcicmp(game, "acc") == 0) { + sim = SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE; + } else if (sstrcicmp(game, "ace") == 0) { + sim = SIMULATOREXE_ASSETTO_CORSA_EVO; + } else if (sstrcicmp(game, "acr") == 0) { + sim = SIMULATOREXE_ASSETTO_CORSA_RALLY; + } else if (sstrcicmp(game, "rf2") == 0) { + sim = SIMULATOREXE_RFACTOR2; + } else if (sstrcicmp(game, "ams2") == 0) { + sim = SIMULATOREXE_AUTOMOBILISTA2; + } else if (sstrcicmp(game, "et2") == 0) { + sim = SIMULATOREXE_EUROTRUCKS2; + } else if (sstrcicmp(game, "at") == 0) { + sim = SIMULATOREXE_EUROTRUCKS2; + } else if (sstrcicmp(game, "lmu") == 0) { + sim = SIMULATOREXE_LEMANS_ULTIMATE; + } else if (sstrcicmp(game, "lfs") == 0) { + sim = SIMULATOREXE_LIVE_FOR_SPEED; + } else if (sstrcicmp(game, "beamng") == 0) { + sim = SIMULATOREXE_BEAMNG; + } else if (sstrcicmp(game, "dr2") == 0) { + sim = SIMULATOREXE_DIRT_RALLY_2; + } else { + sim = 0; + } + return sim; } -char* simapi_gametostr(SimulatorEXE sim) -{ - switch ( sim ) - { - case SIMULATOREXE_ASSETTO_CORSA: - return "ac"; - case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: - return "acc"; - case SIMULATOREXE_ASSETTO_CORSA_EVO: - return "ace"; - case SIMULATOREXE_ASSETTO_CORSA_RALLY: - return "acr"; - case SIMULATOREXE_RFACTOR2: - return "rf2"; - case SIMULATOREXE_LEMANS_ULTIMATE: - return "lmu"; - case SIMULATOREXE_AUTOMOBILISTA2: - return "ams2"; - case SIMULATOREXE_AMERICANTRUCKS: - return "at"; - case SIMULATOREXE_EUROTRUCKS2: - return "et2"; - case SIMULATOREXE_LIVE_FOR_SPEED: - return "lfs"; - case SIMULATOREXE_BEAMNG: - return "beamng"; - default: - return "default"; - } +char *simapi_gametostr(SimulatorEXE sim) { + switch (sim) { + case SIMULATOREXE_ASSETTO_CORSA: + return "ac"; + case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: + return "acc"; + case SIMULATOREXE_ASSETTO_CORSA_EVO: + return "ace"; + case SIMULATOREXE_ASSETTO_CORSA_RALLY: + return "acr"; + case SIMULATOREXE_RFACTOR2: + return "rf2"; + case SIMULATOREXE_LEMANS_ULTIMATE: + return "lmu"; + case SIMULATOREXE_AUTOMOBILISTA2: + return "ams2"; + case SIMULATOREXE_AMERICANTRUCKS: + return "at"; + case SIMULATOREXE_EUROTRUCKS2: + return "et2"; + case SIMULATOREXE_LIVE_FOR_SPEED: + return "lfs"; + case SIMULATOREXE_BEAMNG: + return "beamng"; + case SIMULATOREXE_DIRT_RALLY_2: + return "dr2"; + default: + return "default"; + } } -char* simapi_gametofullstr(SimulatorEXE sim) -{ - switch ( sim ) - { - case SIMULATOREXE_ASSETTO_CORSA: - return "Assetto Corsa"; - case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: - return "Assetto Corsa Competizione"; - case SIMULATOREXE_ASSETTO_CORSA_EVO: - return "Assetto Corsa EVO"; - case SIMULATOREXE_ASSETTO_CORSA_RALLY: - return "Assetto Corsa Rally"; - case SIMULATOREXE_RFACTOR2: - return "RFactor2"; - case SIMULATOREXE_LEMANS_ULTIMATE: - return "LeMans Ultimate"; - case SIMULATOREXE_AUTOMOBILISTA2: - return "Automobilista 2"; - case SIMULATOREXE_AMERICANTRUCKS: - return "American Truck Simulator"; - case SIMULATOREXE_EUROTRUCKS2: - return "Euro Truck Simulator 2"; - case SIMULATOREXE_LIVE_FOR_SPEED: - return "Live For Speed"; - case SIMULATOREXE_BEAMNG: - return "beamng"; - default: - return "default"; - } +char *simapi_gametofullstr(SimulatorEXE sim) { + switch (sim) { + case SIMULATOREXE_ASSETTO_CORSA: + return "Assetto Corsa"; + case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: + return "Assetto Corsa Competizione"; + case SIMULATOREXE_ASSETTO_CORSA_EVO: + return "Assetto Corsa EVO"; + case SIMULATOREXE_ASSETTO_CORSA_RALLY: + return "Assetto Corsa Rally"; + case SIMULATOREXE_RFACTOR2: + return "RFactor2"; + case SIMULATOREXE_LEMANS_ULTIMATE: + return "LeMans Ultimate"; + case SIMULATOREXE_AUTOMOBILISTA2: + return "Automobilista 2"; + case SIMULATOREXE_AMERICANTRUCKS: + return "American Truck Simulator"; + case SIMULATOREXE_EUROTRUCKS2: + return "Euro Truck Simulator 2"; + case SIMULATOREXE_LIVE_FOR_SPEED: + return "Live For Speed"; + case SIMULATOREXE_BEAMNG: + return "beamng"; + case SIMULATOREXE_DIRT_RALLY_2: + return "DiRT Rally 2.0"; + default: + return "default"; + } } +int droundint(double d) { return trunc(nearbyint(d)); } -int droundint(double d) -{ - return trunc(nearbyint(d)); -} - -int froundint(float f) -{ - return trunc(nearbyint(f)); -} +int froundint(float f) { return trunc(nearbyint(f)); } func_ptr_t loginfo = NULL; func_ptr_t logdebug = NULL; func_ptr_t logtrace = NULL; -void set_simapi_log_info(func_ptr_t func) { - loginfo = func; -} -void set_simapi_log_debug(func_ptr_t func) { - logdebug = func; -} -void set_simapi_log_trace(func_ptr_t func) { - logtrace = func; -} +void set_simapi_log_info(func_ptr_t func) { loginfo = func; } +void set_simapi_log_debug(func_ptr_t func) { logdebug = func; } +void set_simapi_log_trace(func_ptr_t func) { logtrace = func; } -void simapi_log(SIMAPI_LOGLEVEL sll, char* message) -{ - if(message != NULL) - { - if(sll == SIMAPI_LOGLEVEL_INFO) - { - if(loginfo != NULL) - { - loginfo(message); - } - } - if(sll == SIMAPI_LOGLEVEL_DEBUG) - { - if(logdebug != NULL) - { - logdebug(message); - } - } - if(sll == SIMAPI_LOGLEVEL_TRACE) - { - if(logtrace != NULL) - { - logtrace(message); - } - } +void simapi_log(SIMAPI_LOGLEVEL sll, char *message) { + if (message != NULL) { + if (sll == SIMAPI_LOGLEVEL_INFO) { + if (loginfo != NULL) { + loginfo(message); + } + } + if (sll == SIMAPI_LOGLEVEL_DEBUG) { + if (logdebug != NULL) { + logdebug(message); + } } + if (sll == SIMAPI_LOGLEVEL_TRACE) { + if (logtrace != NULL) { + logtrace(message); + } + } + } } -void SetProximityData(SimData* simdata, int cars, int8_t lr_flip) -{ - double carwidth = 1.8; - double maxradius = 10.0; +void SetProximityData(SimData *simdata, int cars, int8_t lr_flip) { + double carwidth = 1.8; + double maxradius = 10.0; - int proxcars = PROXCARS; - if(cars < PROXCARS) - { - proxcars = cars; - } + int proxcars = PROXCARS; + if (cars < PROXCARS) { + proxcars = cars; + } + for (int x = 0; x < proxcars; x++) { + simdata->pd[x].radius = 0.0; + simdata->pd[x].theta = 0.0; + } + if (abs(simdata->Yvelocity) < 0.0001 && abs(simdata->Xvelocity) < 0.0001) { + return; + } - for(int x = 0; x < proxcars; x++) - { - simdata->pd[x].radius = 0.0; - simdata->pd[x].theta = 0.0; - } - if(abs(simdata->Yvelocity) < 0.0001 && abs(simdata->Xvelocity) < 0.0001) - { - return; - } + double angle = + atan2(-1, 0) - atan2(simdata->worldYvelocity, simdata->worldXvelocity); + double angleD = angle * 360 / (2 * M_PI); + double angleR = angleD * M_PI / 180; - double angle = atan2(-1, 0) - atan2(simdata->worldYvelocity, simdata->worldXvelocity); - double angleD = angle * 360 / (2 * M_PI); - double angleR = angleD * M_PI / 180; - - double cosTheta = cos(angle); - double sinTheta = sin(angle); - - for(int car = 1; car < cars; car++) - { - double rawXCoordinate = simdata->cars[car].xpos - simdata->worldposx; - double rawYCoordinate = simdata->cars[car].ypos - simdata->worldposy; - - double xscore = cosTheta * rawXCoordinate - sinTheta * rawYCoordinate; - double yscore = sinTheta * rawXCoordinate + cosTheta * rawYCoordinate; - - double rads = atan2(yscore, xscore * lr_flip); - double degrees = (rads * (180 / M_PI)) + 90.0; - - double radius = sqrt((rawXCoordinate * rawXCoordinate) + (rawYCoordinate * rawYCoordinate)); - double theta = degrees; - if( theta < 0 ) - { - theta = 360 + degrees; - } - radius = radius - carwidth; + double cosTheta = cos(angle); + double sinTheta = sin(angle); - //fprintf(stderr, "rawx: %f, rawy: %f degs: %f mag: %f\n", rawXCoordinate, rawYCoordinate, theta, radius); + for (int car = 1; car < cars; car++) { + double rawXCoordinate = simdata->cars[car].xpos - simdata->worldposx; + double rawYCoordinate = simdata->cars[car].ypos - simdata->worldposy; - if(radius < maxradius) - { - int j = proxcars - 1; - if((simdata->pd[j].radius == 0) || (radius < simdata->pd[j].radius)) - { - simdata->pd[j].radius = radius; - simdata->pd[j].theta = theta; + double xscore = cosTheta * rawXCoordinate - sinTheta * rawYCoordinate; + double yscore = sinTheta * rawXCoordinate + cosTheta * rawYCoordinate; + double rads = atan2(yscore, xscore * lr_flip); + double degrees = (rads * (180 / M_PI)) + 90.0; - j--; - while(j >= 0) - { - double tempradius = simdata->pd[j+1].radius; - double temptheta = simdata->pd[j+1].theta; + double radius = sqrt((rawXCoordinate * rawXCoordinate) + + (rawYCoordinate * rawYCoordinate)); + double theta = degrees; + if (theta < 0) { + theta = 360 + degrees; + } + radius = radius - carwidth; + // fprintf(stderr, "rawx: %f, rawy: %f degs: %f mag: %f\n", rawXCoordinate, + // rawYCoordinate, theta, radius); - if((simdata->pd[j].radius == 0) || (tempradius < simdata->pd[j].radius)) - { - simdata->pd[j+1].radius = simdata->pd[j].radius; - simdata->pd[j+1].theta = simdata->pd[j].theta; + if (radius < maxradius) { + int j = proxcars - 1; + if ((simdata->pd[j].radius == 0) || (radius < simdata->pd[j].radius)) { + simdata->pd[j].radius = radius; + simdata->pd[j].theta = theta; - simdata->pd[j].radius = tempradius; - simdata->pd[j].theta = temptheta; - } - j--; - } - } - } - } -} + j--; + while (j >= 0) { + double tempradius = simdata->pd[j + 1].radius; + double temptheta = simdata->pd[j + 1].theta; + if ((simdata->pd[j].radius == 0) || + (tempradius < simdata->pd[j].radius)) { + simdata->pd[j + 1].radius = simdata->pd[j].radius; + simdata->pd[j + 1].theta = simdata->pd[j].theta; -bool does_sim_file_exist(const char* file) -{ - if (file == NULL) { return false; } - #if defined(OS_WIN) - #if defined(WIN_API) - // if you want the WinAPI, versus CRT - if (strnlen(file, MAX_PATH+1) > MAX_PATH) { - // ... throw error here or ... - return false; - } - DWORD res = GetFileAttributesA(file); - return (res != INVALID_FILE_ATTRIBUTES && - !(res & FILE_ATTRIBUTE_DIRECTORY)); - #else - // Use Win CRT - struct stat fi; - if (_stat(file, &fi) == 0) { - #if defined(S_ISSOCK) - // sockets come back as a 'file' on some systems - // so make sure it's not a socket or directory - // (in other words, make sure it's an actual file) - return !(S_ISDIR(fi.st_mode)) && - !(S_ISSOCK(fi.st_mode)); - #else - return !(S_ISDIR(fi.st_mode)); - #endif - } - return false; - #endif - #else - struct stat fi; - if (stat(file, &fi) == 0) { - #if defined(S_ISSOCK) - return !(S_ISDIR(fi.st_mode)) && - !(S_ISSOCK(fi.st_mode)); - #else - return !(S_ISDIR(fi.st_mode)); - #endif + simdata->pd[j].radius = tempradius; + simdata->pd[j].theta = temptheta; + } + j--; } - return false; - #endif + } + } + } } +bool does_sim_file_exist(const char *file) { + if (file == NULL) { + return false; + } +#if defined(OS_WIN) +#if defined(WIN_API) + // if you want the WinAPI, versus CRT + if (strnlen(file, MAX_PATH + 1) > MAX_PATH) { + // ... throw error here or ... + return false; + } + DWORD res = GetFileAttributesA(file); + return (res != INVALID_FILE_ATTRIBUTES && !(res & FILE_ATTRIBUTE_DIRECTORY)); +#else + // Use Win CRT + struct stat fi; + if (_stat(file, &fi) == 0) { +#if defined(S_ISSOCK) + // sockets come back as a 'file' on some systems + // so make sure it's not a socket or directory + // (in other words, make sure it's an actual file) + return !(S_ISDIR(fi.st_mode)) && !(S_ISSOCK(fi.st_mode)); +#else + return !(S_ISDIR(fi.st_mode)); +#endif + } + return false; +#endif +#else + struct stat fi; + if (stat(file, &fi) == 0) { +#if defined(S_ISSOCK) + return !(S_ISDIR(fi.st_mode)) && !(S_ISSOCK(fi.st_mode)); +#else + return !(S_ISDIR(fi.st_mode)); +#endif + } + return false; +#endif +} // if this becomes more necessary i will move it into it's own file -float spLineLengthToDistanceRoundTrack(float trackLength, float spLine) -{ - if (spLine < 0.0) - { - spLine -= 1; - } - return spLine * trackLength; +float spLineLengthToDistanceRoundTrack(float trackLength, float spLine) { + if (spLine < 0.0) { + spLine -= 1; + } + return spLine * trackLength; } -int setSimInfo(SimInfo* si) -{ - switch ( si->simulatorapi ) - { - - case SIMULATORAPI_ASSETTO_CORSA : - si->SimUsesUDP = false; - si->SimSupportsBasicTelemetry = true; - si->SimSupportsTyreEffects = true; - si->SimSupportsRealtimeTelemetry = true; - si->SimSupportsAdvancedUI = true; - break; - case SIMULATORAPI_RFACTOR2 : - si->SimUsesUDP = false; - si->SimSupportsBasicTelemetry = true; - si->SimSupportsTyreEffects = true; - si->SimSupportsRealtimeTelemetry = true; - si->SimSupportsAdvancedUI = true; - break; - case SIMULATORAPI_PROJECTCARS2 : - si->SimSupportsBasicTelemetry = true; - si->SimSupportsTyreEffects = true; - si->SimSupportsRealtimeTelemetry = true; - si->SimSupportsAdvancedUI = true; - break; - case SIMULATORAPI_SCSTRUCKSIM2 : - si->SimUsesUDP = false; - si->SimSupportsBasicTelemetry = true; - break; - case SIMULATORAPI_OUTSIMOUTGAUGE : - si->SimUsesUDP = true; - si->SimSupportsBasicTelemetry = true; - si->SimSupportsTyreEffects = false; - si->SimSupportsRealtimeTelemetry = false; - si->SimSupportsAdvancedUI = false; - break; - default: - si->SimSupportsBasicTelemetry = true; - } +int setSimInfo(SimInfo *si) { + switch (si->simulatorapi) { + + case SIMULATORAPI_ASSETTO_CORSA: + si->SimUsesUDP = false; + si->SimSupportsBasicTelemetry = true; + si->SimSupportsTyreEffects = true; + si->SimSupportsRealtimeTelemetry = true; + si->SimSupportsAdvancedUI = true; + break; + case SIMULATORAPI_RFACTOR2: + si->SimUsesUDP = false; + si->SimSupportsBasicTelemetry = true; + si->SimSupportsTyreEffects = true; + si->SimSupportsRealtimeTelemetry = true; + si->SimSupportsAdvancedUI = true; + break; + case SIMULATORAPI_PROJECTCARS2: + si->SimSupportsBasicTelemetry = true; + si->SimSupportsTyreEffects = true; + si->SimSupportsRealtimeTelemetry = true; + si->SimSupportsAdvancedUI = true; + break; + case SIMULATORAPI_SCSTRUCKSIM2: + si->SimUsesUDP = false; + si->SimSupportsBasicTelemetry = true; + break; + case SIMULATORAPI_OUTSIMOUTGAUGE: + si->SimUsesUDP = true; + si->SimSupportsBasicTelemetry = true; + si->SimSupportsTyreEffects = false; + si->SimSupportsRealtimeTelemetry = false; + si->SimSupportsAdvancedUI = false; + break; + case SIMULATORAPI_DIRT_RALLY_2: + si->SimUsesUDP = true; + si->SimSupportsBasicTelemetry = true; + si->SimSupportsTyreEffects = true; + si->SimSupportsRealtimeTelemetry = true; + si->SimSupportsAdvancedUI = false; + break; + default: + si->SimSupportsBasicTelemetry = true; + } - return 0; + return 0; } -void hexDump(char *desc, void *addr, int len) -{ +void hexDump(char *desc, void *addr, int len) { int i; unsigned char buff[17]; - unsigned char *pc = (unsigned char*)addr; + unsigned char *pc = (unsigned char *)addr; // Output description if given. if (desc != NULL) - printf ("%s:\n", desc); + printf("%s:\n", desc); // Process every byte in the data. for (i = 0; i < len; i++) { @@ -447,14 +388,14 @@ void hexDump(char *desc, void *addr, int len) if ((i % 16) == 0) { // Just don't print ASCII for the zeroth line. if (i != 0) - printf (" %s\n", buff); + printf(" %s\n", buff); // Output the offset. - printf (" %04x ", i); + printf(" %04x ", i); } // Now the hex code for the specific character. - printf (" %02x", pc[i]); + printf(" %02x", pc[i]); // And store a printable ASCII character for later. if ((pc[i] < 0x20) || (pc[i] > 0x7e)) @@ -466,941 +407,892 @@ void hexDump(char *desc, void *addr, int len) // Pad out last line if not exactly 16 characters. while ((i % 16) != 0) { - printf (" "); + printf(" "); i++; } // And print the final ASCII bit. - printf (" %s\n", buff); + printf(" %s\n", buff); } -SimulatorEXE getSimExe(SimInfo* si) -{ - int pid = 0; - - pid = IsProcessRunning(AC_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_ASSETTO_CORSA; - } - pid = IsProcessRunning(ACC_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE; - } - pid = IsProcessRunning(ACE_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_ASSETTO_CORSA_EVO; - } - pid = IsProcessRunning(ACR_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_ASSETTO_CORSA_RALLY; - } - pid = IsProcessRunning(RFACTOR2_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_RFACTOR2; - } - pid = IsProcessRunning(AMS2_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_AUTOMOBILISTA2; - } - pid = IsProcessRunning(EUROTRUCKS2_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_EUROTRUCKS2; - } - pid = IsProcessRunning(AMERICANTRUCKS_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_AMERICANTRUCKS; - } - pid = IsProcessRunning(LEMANS_ULTIMATE_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_LEMANS_ULTIMATE; - } - pid = IsProcessRunning(LIVE_FOR_SPEED_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_LIVE_FOR_SPEED; - } - pid = IsProcessRunning(BEAMNG_EXE); - if(pid>0) - { - si->pid = pid; - return SIMULATOREXE_BEAMNG; - } - return SIMULATOREXE_SIMAPI_TEST_NONE; -} +SimulatorEXE getSimExe(SimInfo *si) { + int pid = 0; + pid = IsProcessRunning(AC_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_ASSETTO_CORSA; + } + pid = IsProcessRunning(ACC_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE; + } + pid = IsProcessRunning(ACE_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_ASSETTO_CORSA_EVO; + } + pid = IsProcessRunning(ACR_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_ASSETTO_CORSA_RALLY; + } + pid = IsProcessRunning(RFACTOR2_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_RFACTOR2; + } + pid = IsProcessRunning(AMS2_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_AUTOMOBILISTA2; + } + pid = IsProcessRunning(EUROTRUCKS2_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_EUROTRUCKS2; + } + pid = IsProcessRunning(AMERICANTRUCKS_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_AMERICANTRUCKS; + } + pid = IsProcessRunning(LEMANS_ULTIMATE_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_LEMANS_ULTIMATE; + } + pid = IsProcessRunning(LIVE_FOR_SPEED_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_LIVE_FOR_SPEED; + } + pid = IsProcessRunning(BEAMNG_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_BEAMNG; + } + pid = IsProcessRunning(DIRT_RALLY_2_EXE); + if (pid > 0) { + si->pid = pid; + return SIMULATOREXE_DIRT_RALLY_2; + } + return SIMULATOREXE_SIMAPI_TEST_NONE; +} -SimInfo getSim(SimData* simdata, SimMap* simmap, bool force_udp, int (*setup_udp)(int), bool simd) -{ - - SimInfo si; - si.simulatorapi = -1; - si.mapapi = -1; - si.simulatorexe = 0; - si.isSimOn = false; - si.SimUsesUDP = false; - si.SimSupportsBasicTelemetry = false; - si.SimSupportsTyreEffects = false; - si.SimSupportsRealtimeTelemetry = false; - si.SimSupportsAdvancedUI = false; - - - if(simd == false) - { - if (does_sim_file_exist("/dev/shm/SIMAPI.DAT")) - { - int e = siminit(simdata, simmap, SIMULATORAPI_SIMAPI_TEST); - simdatamap(simdata, simmap, NULL, SIMULATORAPI_SIMAPI_TEST, false, NULL); - char* temp; - asprintf(&temp, "found running simapi daemon simint error %i", e); - simapi_log(SIMAPI_LOGLEVEL_TRACE, temp); - free(temp); - //simdatamap(simdata, simmap, NULL, SIMULATORAPI_SIMAPI_TEST, false, NULL); - if(simdata->simapiversion == SIMAPI_VERSION) - { - if (simdata->simon == 1) - { - simapi_log(SIMAPI_LOGLEVEL_TRACE, "status okay"); - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.simulatorexe = simdata->simexe; - si.mapapi = SIMULATORAPI_SIMAPI_TEST; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - si.SimUsesUDP = false; - } - return si; - } - else - { - char* temp; - asprintf(&temp, "skipping sim api daemon due to version mismatch. Daemon Version: %i. App Version: %i", simdata->simapiversion, SIMAPI_VERSION); - simapi_log(SIMAPI_LOGLEVEL_INFO, temp); - free(temp); - } - } - else - { - simapi_log(SIMAPI_LOGLEVEL_TRACE, "looking for running simulators"); +SimInfo getSim(SimData *simdata, SimMap *simmap, bool force_udp, + int (*setup_udp)(int), bool simd) { + + SimInfo si; + si.simulatorapi = -1; + si.mapapi = -1; + si.simulatorexe = 0; + si.isSimOn = false; + si.SimUsesUDP = false; + si.SimSupportsBasicTelemetry = false; + si.SimSupportsTyreEffects = false; + si.SimSupportsRealtimeTelemetry = false; + si.SimSupportsAdvancedUI = false; + + if (simd == false) { + if (does_sim_file_exist("/dev/shm/SIMAPI.DAT")) { + int e = siminit(simdata, simmap, SIMULATORAPI_SIMAPI_TEST); + simdatamap(simdata, simmap, NULL, SIMULATORAPI_SIMAPI_TEST, false, NULL); + char *temp; + asprintf(&temp, "found running simapi daemon simint error %i", e); + simapi_log(SIMAPI_LOGLEVEL_TRACE, temp); + free(temp); + // simdatamap(simdata, simmap, NULL, SIMULATORAPI_SIMAPI_TEST, false, + // NULL); + if (simdata->simapiversion == SIMAPI_VERSION) { + if (simdata->simon == 1) { + simapi_log(SIMAPI_LOGLEVEL_TRACE, "status okay"); + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.simulatorexe = simdata->simexe; + si.mapapi = SIMULATORAPI_SIMAPI_TEST; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + si.SimUsesUDP = false; } + return si; + } else { + char *temp; + asprintf(&temp, + "skipping sim api daemon due to version mismatch. Daemon " + "Version: %i. App Version: %i", + simdata->simapiversion, SIMAPI_VERSION); + simapi_log(SIMAPI_LOGLEVEL_INFO, temp); + free(temp); + } + } else { + simapi_log(SIMAPI_LOGLEVEL_TRACE, "looking for running simulators"); } + } - SimulatorEXE simexe = getSimExe(&si); - - switch ( simexe ) - { - case SIMULATOREXE_ASSETTO_CORSA: - case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: - case SIMULATOREXE_ASSETTO_CORSA_EVO: - case SIMULATOREXE_ASSETTO_CORSA_RALLY: - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "Found running process for Assetto Corsa"); - if (does_sim_file_exist("/dev/shm/acpmf_physics")) - { - if (does_sim_file_exist("/dev/shm/acpmf_static")) - { - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "static and physics files found"); - si.simulatorapi = SIMULATORAPI_ASSETTO_CORSA; - int error = siminit(simdata, simmap, SIMULATORAPI_ASSETTO_CORSA); - char* temp; - asprintf(&temp, "siminit error %i", error); - simapi_log(SIMAPI_LOGLEVEL_DEBUG, temp); - free(temp); - simdatamap(simdata, simmap, NULL, SIMULATORAPI_ASSETTO_CORSA, false, NULL); - - // temporary workaround for beta data from ACEvo and ACRally - if(simexe == SIMULATOREXE_ASSETTO_CORSA_EVO || simexe == SIMULATOREXE_ASSETTO_CORSA_RALLY) - { - simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; - } - - if (error == 0 && simdata->simstatus > 1) - { - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "AC Shared memory looks good"); - simdata->simon = true; - simdata->simapi = SIMULATORAPI_ASSETTO_CORSA; - simdata->simexe = simexe; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - if(simexe == SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE) - { - // support will have to be revisited for this sim - si.SimSupportsRealtimeTelemetry = false; - } - - return si; - } - } - else - { - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "Could not find static shared memory file"); - } - } - else - { - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "Could not find physics shared memory file"); - } - break; - - case SIMULATOREXE_LIVE_FOR_SPEED: - case SIMULATOREXE_BEAMNG: - int error = (*setup_udp)(30000); - error = siminitudp(simdata, simmap, SIMULATORAPI_OUTSIMOUTGAUGE); - - if(error == 0) - { - simdata->simon = true; - simdata->simapi = SIMULATORAPI_OUTSIMOUTGAUGE; - simdata->simexe = simexe; - - simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; - simdata->gear = 0; - simdata->velocity = 0; - simdata->rpms = 0; - simdata->altitude = 0; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - return si; - } - break; - - case SIMULATOREXE_RFACTOR2: - case SIMULATOREXE_LEMANS_ULTIMATE: - if (does_sim_file_exist("/dev/shm/$rFactor2SMMP_Telemetry$")) - { - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "RFactor2 telemetry file found"); - si.simulatorapi = SIMULATORAPI_RFACTOR2; - int error = siminit(simdata, simmap, SIMULATORAPI_RFACTOR2); - simdatamap(simdata, simmap, NULL, SIMULATORAPI_RFACTOR2, false, NULL); - if (error == 0) - { - //slogi("found Assetto Corsa, starting application..."); - - simdata->simon = true; - simdata->simapi = SIMULATORAPI_RFACTOR2; - simdata->simexe = simexe; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - - return si; - } - } - break; - - case SIMULATOREXE_AUTOMOBILISTA2: - if (force_udp == false) - { - if (does_sim_file_exist("/dev/shm/$pcars2$")) - { - si.simulatorapi = SIMULATORAPI_PROJECTCARS2; - int error = siminit(simdata, simmap, SIMULATORAPI_PROJECTCARS2); - simdatamap(simdata, simmap, NULL, SIMULATORAPI_PROJECTCARS2, false, NULL); - if (error == 0) - { - simdata->simon = true; - simdata->simapi = SIMULATORAPI_PROJECTCARS2; - simdata->simexe = simexe; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - - return si; - } - } - } - else - { - int error = (*setup_udp)(5606); - error = siminitudp(simdata, simmap, SIMULATORAPI_PROJECTCARS2); - if (error == 0) - { - si.simulatorapi = SIMULATORAPI_PROJECTCARS2; - si.SimUsesUDP = true; - simdatamap(simdata, simmap, NULL, SIMULATORAPI_PROJECTCARS2, true, NULL); - } - if (error == 0 && simdata->simstatus > 1) - { - simdata->simon = true; - simdata->simapi = SIMULATORAPI_PROJECTCARS2; - simdata->simexe = simexe; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - - return si; - } - } - break; - case SIMULATOREXE_EUROTRUCKS2: - case SIMULATOREXE_AMERICANTRUCKS: - if (does_sim_file_exist("/dev/shm/SCS/SCSTelemetry")) - { - si.simulatorapi = SIMULATORAPI_SCSTRUCKSIM2; - int error = siminit(simdata, simmap, SIMULATORAPI_SCSTRUCKSIM2); - simdatamap(simdata, simmap, NULL, SIMULATORAPI_SCSTRUCKSIM2, false, NULL); - if (error == 0) - { - simdata->simon = true; - simdata->simapi = SIMULATORAPI_SCSTRUCKSIM2; - simdata->simexe = simexe; - - si.isSimOn = true; - si.simulatorapi = simdata->simapi; - si.mapapi = si.simulatorapi; - si.simulatorexe = simdata->simexe; - setSimInfo(&si); - - return si; - } - } - break; - } - return si; -} + SimulatorEXE simexe = getSimExe(&si); + + switch (simexe) { + case SIMULATOREXE_ASSETTO_CORSA: + case SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE: + case SIMULATOREXE_ASSETTO_CORSA_EVO: + case SIMULATOREXE_ASSETTO_CORSA_RALLY: + simapi_log(SIMAPI_LOGLEVEL_DEBUG, + "Found running process for Assetto Corsa"); + if (does_sim_file_exist("/dev/shm/acpmf_physics")) { + if (does_sim_file_exist("/dev/shm/acpmf_static")) { + simapi_log(SIMAPI_LOGLEVEL_DEBUG, "static and physics files found"); + si.simulatorapi = SIMULATORAPI_ASSETTO_CORSA; + int error = siminit(simdata, simmap, SIMULATORAPI_ASSETTO_CORSA); + char *temp; + asprintf(&temp, "siminit error %i", error); + simapi_log(SIMAPI_LOGLEVEL_DEBUG, temp); + free(temp); + simdatamap(simdata, simmap, NULL, SIMULATORAPI_ASSETTO_CORSA, false, + NULL); + + // temporary workaround for beta data from ACEvo and ACRally + if (simexe == SIMULATOREXE_ASSETTO_CORSA_EVO || + simexe == SIMULATOREXE_ASSETTO_CORSA_RALLY) { + simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; + } -int simdatamap(SimData* simdata, SimMap* simmap, SimMap* simmap2, SimulatorAPI simulatorapi, bool udp, char* base) -{ - char* a; - char* b; - char* c; - char* d; + if (error == 0 && simdata->simstatus > 1) { + simapi_log(SIMAPI_LOGLEVEL_DEBUG, "AC Shared memory looks good"); + simdata->simon = true; + simdata->simapi = SIMULATORAPI_ASSETTO_CORSA; + simdata->simexe = simexe; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + if (simexe == SIMULATOREXE_ASSETTO_CORSA_COMPETIZIONE) { + // support will have to be revisited for this sim + si.SimSupportsRealtimeTelemetry = false; + } + + return si; + } + } else { + simapi_log(SIMAPI_LOGLEVEL_DEBUG, + "Could not find static shared memory file"); + } + } else { + simapi_log(SIMAPI_LOGLEVEL_DEBUG, + "Could not find physics shared memory file"); + } + break; + + case SIMULATOREXE_LIVE_FOR_SPEED: + case SIMULATOREXE_BEAMNG: + int error = (*setup_udp)(30000); + error = siminitudp(simdata, simmap, SIMULATORAPI_OUTSIMOUTGAUGE); + + if (error == 0) { + simdata->simon = true; + simdata->simapi = SIMULATORAPI_OUTSIMOUTGAUGE; + simdata->simexe = simexe; + + simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; + simdata->gear = 0; + simdata->velocity = 0; + simdata->rpms = 0; + simdata->altitude = 0; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + return si; + } + break; + + case SIMULATOREXE_DIRT_RALLY_2: + int dr2_error = (*setup_udp)(20777); + dr2_error = siminitudp(simdata, simmap, SIMULATORAPI_DIRT_RALLY_2); + + if (dr2_error == 0) { + simdata->simon = true; + simdata->simapi = SIMULATORAPI_DIRT_RALLY_2; + simdata->simexe = simexe; + + simdata->simstatus = SIMAPI_STATUS_ACTIVEPLAY; + + si.isSimOn = true; + si.SimUsesUDP = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + return si; + } + break; + + case SIMULATOREXE_RFACTOR2: + case SIMULATOREXE_LEMANS_ULTIMATE: + if (does_sim_file_exist("/dev/shm/$rFactor2SMMP_Telemetry$")) { + simapi_log(SIMAPI_LOGLEVEL_DEBUG, "RFactor2 telemetry file found"); + si.simulatorapi = SIMULATORAPI_RFACTOR2; + int error = siminit(simdata, simmap, SIMULATORAPI_RFACTOR2); + simdatamap(simdata, simmap, NULL, SIMULATORAPI_RFACTOR2, false, NULL); + if (error == 0) { + // slogi("found Assetto Corsa, starting application..."); + + simdata->simon = true; + simdata->simapi = SIMULATORAPI_RFACTOR2; + simdata->simexe = simexe; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + + return si; + } + } + break; + + case SIMULATOREXE_AUTOMOBILISTA2: + if (force_udp == false) { + if (does_sim_file_exist("/dev/shm/$pcars2$")) { + si.simulatorapi = SIMULATORAPI_PROJECTCARS2; + int error = siminit(simdata, simmap, SIMULATORAPI_PROJECTCARS2); + simdatamap(simdata, simmap, NULL, SIMULATORAPI_PROJECTCARS2, false, + NULL); + if (error == 0) { + simdata->simon = true; + simdata->simapi = SIMULATORAPI_PROJECTCARS2; + simdata->simexe = simexe; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + + return si; + } + } + } else { + int error = (*setup_udp)(5606); + error = siminitudp(simdata, simmap, SIMULATORAPI_PROJECTCARS2); + if (error == 0) { + si.simulatorapi = SIMULATORAPI_PROJECTCARS2; + si.SimUsesUDP = true; + simdatamap(simdata, simmap, NULL, SIMULATORAPI_PROJECTCARS2, true, + NULL); + } + if (error == 0 && simdata->simstatus > 1) { + simdata->simon = true; + simdata->simapi = SIMULATORAPI_PROJECTCARS2; + simdata->simexe = simexe; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + + return si; + } + } + break; + case SIMULATOREXE_EUROTRUCKS2: + case SIMULATOREXE_AMERICANTRUCKS: + if (does_sim_file_exist("/dev/shm/SCS/SCSTelemetry")) { + si.simulatorapi = SIMULATORAPI_SCSTRUCKSIM2; + int error = siminit(simdata, simmap, SIMULATORAPI_SCSTRUCKSIM2); + simdatamap(simdata, simmap, NULL, SIMULATORAPI_SCSTRUCKSIM2, false, NULL); + if (error == 0) { + simdata->simon = true; + simdata->simapi = SIMULATORAPI_SCSTRUCKSIM2; + simdata->simexe = simexe; + + si.isSimOn = true; + si.simulatorapi = simdata->simapi; + si.mapapi = si.simulatorapi; + si.simulatorexe = simdata->simexe; + setSimInfo(&si); + + return si; + } + } + break; + } + return si; +} - simdata->mtick = timeInMilliseconds(); +int simdatamap(SimData *simdata, SimMap *simmap, SimMap *simmap2, + SimulatorAPI simulatorapi, bool udp, char *base) { + char *a; + char *b; + char *c; + char *d; + + simdata->mtick = timeInMilliseconds(); + + switch (simulatorapi) { + case SIMULATORAPI_SIMAPI_TEST: + double tyre0 = simdata->tyrediameter[0]; + double tyre1 = simdata->tyrediameter[1]; + double tyre2 = simdata->tyrediameter[2]; + double tyre3 = simdata->tyrediameter[3]; + memcpy(simdata, simmap->addr, sizeof(SimData)); + if (simdata->simapi != SIMULATORAPI_ASSETTO_CORSA) { + simdata->tyrediameter[0] = tyre0; + simdata->tyrediameter[1] = tyre1; + simdata->tyrediameter[2] = tyre2; + simdata->tyrediameter[3] = tyre3; + } + return 0; + case SIMULATORAPI_ASSETTO_CORSA: - switch ( simulatorapi ) - { - case SIMULATORAPI_SIMAPI_TEST : - double tyre0 = simdata->tyrediameter[0]; - double tyre1 = simdata->tyrediameter[1]; - double tyre2 = simdata->tyrediameter[2]; - double tyre3 = simdata->tyrediameter[3]; - memcpy(simdata, simmap->addr, sizeof(SimData)); - if(simdata->simapi != SIMULATORAPI_ASSETTO_CORSA) - { - simdata->tyrediameter[0] = tyre0; - simdata->tyrediameter[1] = tyre1; - simdata->tyrediameter[2] = tyre2; - simdata->tyrediameter[3] = tyre3; - } - return 0; - case SIMULATORAPI_ASSETTO_CORSA : + map_assetto_corsa_data(simdata, simmap, simdata->simexe); - map_assetto_corsa_data(simdata, simmap, simdata->simexe); + break; - break; + case SIMULATORAPI_RFACTOR2: - case SIMULATORAPI_RFACTOR2 : + map_rfactor2_data(simdata, simmap); - map_rfactor2_data(simdata, simmap); + break; - break; + case SIMULATORAPI_PROJECTCARS2: - case SIMULATORAPI_PROJECTCARS2 : + map_project_cars2_data(simdata, simmap, udp, base); - map_project_cars2_data(simdata, simmap, udp, base); + break; - break; + case SIMULATORAPI_SCSTRUCKSIM2: - case SIMULATORAPI_SCSTRUCKSIM2 : + map_trucks_data(simdata, simmap); - map_trucks_data(simdata, simmap); + break; - break; + case SIMULATORAPI_OUTSIMOUTGAUGE: - case SIMULATORAPI_OUTSIMOUTGAUGE : + map_outgauge_outsim_data(simdata, simmap, simdata->simexe, base); + break; - map_outgauge_outsim_data(simdata, simmap, simdata->simexe, base); - break; - } + case SIMULATORAPI_DIRT_RALLY_2: - if (simmap2 != NULL && simmap2->addr != NULL) - { - simdmap(simmap2, simdata); - } + map_dirt_rally_2_data(simdata, simmap, base); + break; + } + if (simmap2 != NULL && simmap2->addr != NULL) { + simdmap(simmap2, simdata); + } } -int simdmap(SimMap* simmap, SimData* simdata) -{ - memcpy(simmap->addr, simdata, sizeof(SimData)); +int simdmap(SimMap *simmap, SimData *simdata) { + memcpy(simmap->addr, simdata, sizeof(SimData)); } -int siminitudp(SimData* simdata, SimMap* simmap, SimulatorAPI simulator) -{ - int error = SIMAPI_ERROR_NONE; +int siminitudp(SimData *simdata, SimMap *simmap, SimulatorAPI simulator) { + int error = SIMAPI_ERROR_NONE; - simdata->simapiversion = SIMAPI_VERSION; - return error; + simdata->simapiversion = SIMAPI_VERSION; + return error; } +int siminit(SimData *simdata, SimMap *simmap, SimulatorAPI simulator) { + // slogi("searching for simulator data..."); + int error = SIMAPI_ERROR_NONE; + + void *a; + switch (simulator) { + case SIMULATORAPI_SIMAPI_TEST: + if (simmap->hasSimApiDat == true) { + return 0; + } + simapi_log(SIMAPI_LOGLEVEL_DEBUG, "Opening universal shared memory api"); + simmap->fd = shm_open(SIMAPI_MEM_FILE, O_RDONLY, S_IRUSR | S_IWUSR); + if (simmap->fd == -1) { + return 10; + } + + simmap->addr = + mmap(NULL, sizeof(SimData), PROT_READ, MAP_SHARED, simmap->fd, 0); + if (simmap->addr == MAP_FAILED) { + return 30; + } + simmap->hasSimApiDat = true; + // slogi("found data for monocoque test..."); + break; + + case SIMULATORAPI_ASSETTO_CORSA: + + if (simmap->ac.has_physics == true) { + return 0; + } + simmap->ac.has_physics = false; + simmap->ac.has_static = false; + simmap->ac.fd_physics = + shm_open(AC_PHYSICS_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (simmap->ac.fd_physics == -1) { + // slogd("could not open Assetto Corsa physics engine"); + return SIMAPI_ERROR_NODATA; + } + simmap->ac.physics_map_addr = + mmap(NULL, sizeof(simmap->ac.ac_physics), PROT_READ, MAP_SHARED, + simmap->ac.fd_physics, 0); + if (simmap->ac.physics_map_addr == MAP_FAILED) { + // slogd("could not retrieve Assetto Corsa physics data"); + return 30; + } + simmap->ac.has_physics = true; + + simmap->ac.fd_static = + shm_open(AC_STATIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (simmap->ac.fd_static == -1) { + // slogd("could not open Assetto Corsa static data"); + return 10; + } + simmap->ac.static_map_addr = + mmap(NULL, sizeof(simmap->ac.ac_static), PROT_READ, MAP_SHARED, + simmap->ac.fd_static, 0); + if (simmap->ac.static_map_addr == MAP_FAILED) { + // slogd("could not retrieve Assetto Corsa static data"); + return 30; + } + simmap->ac.has_static = true; + + simmap->ac.fd_graphic = + shm_open(AC_GRAPHIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (simmap->ac.fd_graphic == -1) { + // slogd("could not open Assetto Corsa graphic data"); + return 10; + } + simmap->ac.graphic_map_addr = + mmap(NULL, sizeof(simmap->ac.ac_graphic), PROT_READ, MAP_SHARED, + simmap->ac.fd_graphic, 0); + if (simmap->ac.graphic_map_addr == MAP_FAILED) { + // slogd("could not retrieve Assetto Corsa static data"); + return 30; + } + simmap->ac.has_graphic = true; + // slogi("found data for Assetto Corsa..."); + simmap->ac.fd_crewchief = + shm_open(AC_CREWCHIEF_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (simmap->ac.fd_crewchief == -1) { + // slogd("could not open Assetto Corsa graphic data"); + return 10; + } + simmap->ac.crewchief_map_addr = + mmap(NULL, sizeof(simmap->ac.ac_crewchief), PROT_READ, MAP_SHARED, + simmap->ac.fd_crewchief, 0); + if (simmap->ac.crewchief_map_addr == MAP_FAILED) { + // slogd("could not retrieve Assetto Corsa static data"); + return 30; + } + simmap->ac.has_crewchief = true; + + break; + + case SIMULATORAPI_PROJECTCARS2: + + if (simmap->pcars2.has_telemetry == true) { + return 0; + } + simmap->pcars2.has_telemetry = false; + simmap->pcars2.fd_telemetry = + shm_open(PCARS2_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (simmap->pcars2.fd_telemetry == -1) { + // slogd("could not open Assetto Corsa physics engine"); + return SIMAPI_ERROR_NODATA; + } + simmap->pcars2.telemetry_map_addr = + mmap(NULL, sizeof(simmap->pcars2.pcars2_telemetry), PROT_READ, + MAP_SHARED, simmap->pcars2.fd_telemetry, 0); + if (simmap->pcars2.telemetry_map_addr == MAP_FAILED) { + // slogd("could not retrieve Assetto Corsa physics data"); + return 30; + } + simmap->pcars2.has_telemetry = true; + + break; + + case SIMULATORAPI_RFACTOR2: + + if (simmap->rf2.has_telemetry == true) { + return 0; + } + simmap->rf2.has_telemetry = false; + simmap->rf2.has_scoring = false; + simmap->rf2.fd_telemetry = + shm_open(RF2_TELEMETRY_FILE, O_RDONLY, S_IRUSR | S_IWUSR); + if (simmap->rf2.fd_telemetry == -1) { + // slogd("could not open RFactor2 Telemetry engine"); + return SIMAPI_ERROR_NODATA; + } + simmap->rf2.telemetry_map_addr = + mmap(NULL, sizeof(simmap->rf2.rf2_telemetry), PROT_READ, MAP_SHARED, + simmap->rf2.fd_telemetry, 0); + if (simmap->rf2.telemetry_map_addr == MAP_FAILED) { + // slogd("could not retrieve RFactor2 telemetry data"); + return 30; + } + simmap->rf2.has_telemetry = true; + simmap->rf2.fd_scoring = + shm_open(RF2_SCORING_FILE, O_RDONLY, S_IRUSR | S_IWUSR); + if (simmap->rf2.fd_scoring == -1) { + // slogd("could not open RFactor2 Telemetry engine"); + return SIMAPI_ERROR_NODATA; + } + simmap->rf2.scoring_map_addr = + mmap(NULL, sizeof(simmap->rf2.rf2_scoring), PROT_READ, MAP_SHARED, + simmap->rf2.fd_scoring, 0); + if (simmap->rf2.scoring_map_addr == MAP_FAILED) { + // slogd("could not retrieve RFactor2 telemetry data"); + return 30; + } + simmap->rf2.has_scoring = true; + + // slogi("found data for RFactor2..."); + break; + + case SIMULATORAPI_SCSTRUCKSIM2: + + if (simmap->scs2.has_telemetry == true) { + return 0; + } + simmap->scs2.has_telemetry = false; + simmap->scs2.fd_telemetry = + open("/dev/shm/SCS/SCSTelemetry", O_CREAT | O_RDWR, 0777); + // simmap->scs2.fd_telemetry = shm_open(SCS2_TELEMETRY_FILE, O_RDONLY, + // S_IRUSR | S_IWUSR); + if (simmap->scs2.fd_telemetry == -1) { + return SIMAPI_ERROR_NODATA; + } + simmap->scs2.telemetry_map_addr = + mmap(NULL, sizeof(simmap->scs2.scs2_telemetry), PROT_READ, MAP_SHARED, + simmap->scs2.fd_telemetry, 0); + if (simmap->scs2.telemetry_map_addr == MAP_FAILED) { + return 30; + } + simmap->scs2.has_telemetry = true; + + break; + } + simdata->simapiversion = SIMAPI_VERSION; -int siminit(SimData* simdata, SimMap* simmap, SimulatorAPI simulator) -{ - //slogi("searching for simulator data..."); - int error = SIMAPI_ERROR_NONE; - - void* a; - switch ( simulator ) - { - case SIMULATORAPI_SIMAPI_TEST : - if(simmap->hasSimApiDat == true) - { - return 0; - } - simapi_log(SIMAPI_LOGLEVEL_DEBUG, "Opening universal shared memory api"); - simmap->fd = shm_open(SIMAPI_MEM_FILE, O_RDONLY, S_IRUSR|S_IWUSR); - if (simmap->fd == -1) - { - return 10; - } - - simmap->addr = mmap(NULL, sizeof(SimData), PROT_READ, MAP_SHARED, simmap->fd, 0); - if (simmap->addr == MAP_FAILED) - { - return 30; - } - simmap->hasSimApiDat = true; - //slogi("found data for monocoque test..."); - break; - - case SIMULATORAPI_ASSETTO_CORSA : - - if(simmap->ac.has_physics == true) - { - return 0; - } - simmap->ac.has_physics=false; - simmap->ac.has_static=false; - simmap->ac.fd_physics = shm_open(AC_PHYSICS_FILE, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); - if (simmap->ac.fd_physics == -1) - { - //slogd("could not open Assetto Corsa physics engine"); - return SIMAPI_ERROR_NODATA; - } - simmap->ac.physics_map_addr = mmap(NULL, sizeof(simmap->ac.ac_physics), PROT_READ, MAP_SHARED, simmap->ac.fd_physics, 0); - if (simmap->ac.physics_map_addr == MAP_FAILED) - { - //slogd("could not retrieve Assetto Corsa physics data"); - return 30; - } - simmap->ac.has_physics=true; - - simmap->ac.fd_static = shm_open(AC_STATIC_FILE, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); - if (simmap->ac.fd_static == -1) - { - //slogd("could not open Assetto Corsa static data"); - return 10; - } - simmap->ac.static_map_addr = mmap(NULL, sizeof(simmap->ac.ac_static), PROT_READ, MAP_SHARED, simmap->ac.fd_static, 0); - if (simmap->ac.static_map_addr == MAP_FAILED) - { - //slogd("could not retrieve Assetto Corsa static data"); - return 30; - } - simmap->ac.has_static=true; - - simmap->ac.fd_graphic = shm_open(AC_GRAPHIC_FILE, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); - if (simmap->ac.fd_graphic == -1) - { - //slogd("could not open Assetto Corsa graphic data"); - return 10; - } - simmap->ac.graphic_map_addr = mmap(NULL, sizeof(simmap->ac.ac_graphic), PROT_READ, MAP_SHARED, simmap->ac.fd_graphic, 0); - if (simmap->ac.graphic_map_addr == MAP_FAILED) - { - //slogd("could not retrieve Assetto Corsa static data"); - return 30; - } - simmap->ac.has_graphic=true; - //slogi("found data for Assetto Corsa..."); - simmap->ac.fd_crewchief = shm_open(AC_CREWCHIEF_FILE, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); - if (simmap->ac.fd_crewchief == -1) - { - //slogd("could not open Assetto Corsa graphic data"); - return 10; - } - simmap->ac.crewchief_map_addr = mmap(NULL, sizeof(simmap->ac.ac_crewchief), PROT_READ, MAP_SHARED, simmap->ac.fd_crewchief, 0); - if (simmap->ac.crewchief_map_addr == MAP_FAILED) - { - //slogd("could not retrieve Assetto Corsa static data"); - return 30; - } - simmap->ac.has_crewchief=true; - - break; - - case SIMULATORAPI_PROJECTCARS2 : - - if(simmap->pcars2.has_telemetry == true) - { - return 0; - } - simmap->pcars2.has_telemetry=false; - simmap->pcars2.fd_telemetry = shm_open(PCARS2_FILE, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); - if (simmap->pcars2.fd_telemetry == -1) - { - //slogd("could not open Assetto Corsa physics engine"); - return SIMAPI_ERROR_NODATA; - } - simmap->pcars2.telemetry_map_addr = mmap(NULL, sizeof(simmap->pcars2.pcars2_telemetry), PROT_READ, MAP_SHARED, simmap->pcars2.fd_telemetry, 0); - if (simmap->pcars2.telemetry_map_addr == MAP_FAILED) - { - //slogd("could not retrieve Assetto Corsa physics data"); - return 30; - } - simmap->pcars2.has_telemetry=true; - - break; - - case SIMULATORAPI_RFACTOR2 : - - if(simmap->rf2.has_telemetry == true) - { - return 0; - } - simmap->rf2.has_telemetry=false; - simmap->rf2.has_scoring=false; - simmap->rf2.fd_telemetry = shm_open(RF2_TELEMETRY_FILE, O_RDONLY, S_IRUSR | S_IWUSR); - if (simmap->rf2.fd_telemetry == -1) - { - //slogd("could not open RFactor2 Telemetry engine"); - return SIMAPI_ERROR_NODATA; - } - simmap->rf2.telemetry_map_addr = mmap(NULL, sizeof(simmap->rf2.rf2_telemetry), PROT_READ, MAP_SHARED, simmap->rf2.fd_telemetry, 0); - if (simmap->rf2.telemetry_map_addr == MAP_FAILED) - { - //slogd("could not retrieve RFactor2 telemetry data"); - return 30; - } - simmap->rf2.has_telemetry=true; - simmap->rf2.fd_scoring = shm_open(RF2_SCORING_FILE, O_RDONLY, S_IRUSR | S_IWUSR); - if (simmap->rf2.fd_scoring == -1) - { - //slogd("could not open RFactor2 Telemetry engine"); - return SIMAPI_ERROR_NODATA; - } - simmap->rf2.scoring_map_addr = mmap(NULL, sizeof(simmap->rf2.rf2_scoring), PROT_READ, MAP_SHARED, simmap->rf2.fd_scoring, 0); - if (simmap->rf2.scoring_map_addr == MAP_FAILED) - { - //slogd("could not retrieve RFactor2 telemetry data"); - return 30; - } - simmap->rf2.has_scoring=true; - - - //slogi("found data for RFactor2..."); - break; - - case SIMULATORAPI_SCSTRUCKSIM2 : - - if(simmap->scs2.has_telemetry == true) - { - return 0; - } - simmap->scs2.has_telemetry=false; - simmap->scs2.fd_telemetry = open("/dev/shm/SCS/SCSTelemetry", O_CREAT|O_RDWR, 0777); - //simmap->scs2.fd_telemetry = shm_open(SCS2_TELEMETRY_FILE, O_RDONLY, S_IRUSR | S_IWUSR); - if (simmap->scs2.fd_telemetry == -1) - { - return SIMAPI_ERROR_NODATA; - } - simmap->scs2.telemetry_map_addr = mmap(NULL, sizeof(simmap->scs2.scs2_telemetry), PROT_READ, MAP_SHARED, simmap->scs2.fd_telemetry, 0); - if (simmap->scs2.telemetry_map_addr == MAP_FAILED) - { - return 30; - } - simmap->scs2.has_telemetry=true; - - break; - } - simdata->simapiversion = SIMAPI_VERSION; - - return error; + return error; } +int simfree(SimData *simdata, SimMap *simmap, SimulatorAPI simulator) { + int error = SIMAPI_ERROR_NONE; -int simfree(SimData* simdata, SimMap* simmap, SimulatorAPI simulator) -{ - int error = SIMAPI_ERROR_NONE; - - if(simmap->ac.has_physics==true) - { - if (munmap(simmap->ac.physics_map_addr, sizeof(simmap->ac.ac_physics)) == -1) - { - return 0101100; - } - - if (close(simmap->ac.fd_physics) == -1) - { - return 0101200; - } + if (simmap->ac.has_physics == true) { + if (munmap(simmap->ac.physics_map_addr, sizeof(simmap->ac.ac_physics)) == + -1) { + return 0101100; + } - simmap->ac.has_physics = false; + if (close(simmap->ac.fd_physics) == -1) { + return 0101200; } - if(simmap->ac.has_static==true) - { - if (munmap(simmap->ac.static_map_addr, sizeof(simmap->ac.ac_static)) == -1) - { - return 0102100; - } - if (close(simmap->ac.fd_static) == -1) - { - return 0102200; - } + simmap->ac.has_physics = false; + } + if (simmap->ac.has_static == true) { + if (munmap(simmap->ac.static_map_addr, sizeof(simmap->ac.ac_static)) == + -1) { + return 0102100; + } - simmap->ac.has_static = false; + if (close(simmap->ac.fd_static) == -1) { + return 0102200; } - if(simmap->ac.has_graphic==true) - { - if (munmap(simmap->ac.graphic_map_addr, sizeof(simmap->ac.ac_graphic)) == -1) - { - return 0103100; - } + simmap->ac.has_static = false; + } - if (close(simmap->ac.fd_graphic) == -1) - { - return 0103200; - } + if (simmap->ac.has_graphic == true) { + if (munmap(simmap->ac.graphic_map_addr, sizeof(simmap->ac.ac_graphic)) == + -1) { + return 0103100; + } - simmap->ac.has_graphic = false; + if (close(simmap->ac.fd_graphic) == -1) { + return 0103200; } - if(simmap->ac.has_crewchief==true) - { - if (munmap(simmap->ac.crewchief_map_addr, sizeof(simmap->ac.ac_crewchief)) == -1) - { - return 0104100; - } + simmap->ac.has_graphic = false; + } - if (close(simmap->ac.fd_crewchief) == -1) - { - return 0104200; - } + if (simmap->ac.has_crewchief == true) { + if (munmap(simmap->ac.crewchief_map_addr, + sizeof(simmap->ac.ac_crewchief)) == -1) { + return 0104100; + } - simmap->ac.has_crewchief = false; + if (close(simmap->ac.fd_crewchief) == -1) { + return 0104200; } - if(simmap->pcars2.has_telemetry==true) - { - if (munmap(simmap->pcars2.telemetry_map_addr, sizeof(simmap->pcars2.pcars2_telemetry)) == -1) - { - return 0201100; - } + simmap->ac.has_crewchief = false; + } - if (close(simmap->pcars2.fd_telemetry) == -1) - { - return 0201200; - } + if (simmap->pcars2.has_telemetry == true) { + if (munmap(simmap->pcars2.telemetry_map_addr, + sizeof(simmap->pcars2.pcars2_telemetry)) == -1) { + return 0201100; + } - simmap->pcars2.has_telemetry = false; + if (close(simmap->pcars2.fd_telemetry) == -1) { + return 0201200; } - if(simmap->rf2.has_telemetry==true) - { - if (munmap(simmap->rf2.telemetry_map_addr, sizeof(simmap->rf2.rf2_telemetry)) == -1) - { - return 100; - } + simmap->pcars2.has_telemetry = false; + } - if (close(simmap->rf2.fd_telemetry) == -1) - { - return 200; - } + if (simmap->rf2.has_telemetry == true) { + if (munmap(simmap->rf2.telemetry_map_addr, + sizeof(simmap->rf2.rf2_telemetry)) == -1) { + return 100; + } - simmap->rf2.has_telemetry = false; + if (close(simmap->rf2.fd_telemetry) == -1) { + return 200; } - if(simmap->rf2.has_scoring==true) - { - if (munmap(simmap->rf2.scoring_map_addr, sizeof(simmap->rf2.rf2_scoring)) == -1) - { - return 100; - } - if (close(simmap->rf2.fd_scoring) == -1) - { - return 200; - } + simmap->rf2.has_telemetry = false; + } + if (simmap->rf2.has_scoring == true) { + if (munmap(simmap->rf2.scoring_map_addr, sizeof(simmap->rf2.rf2_scoring)) == + -1) { + return 100; + } - simmap->rf2.has_scoring = false; + if (close(simmap->rf2.fd_scoring) == -1) { + return 200; } - if(simmap->scs2.has_telemetry==true) - { - if (munmap(simmap->scs2.telemetry_map_addr, sizeof(simmap->scs2.scs2_telemetry)) == -1) - { - return 100; - } + simmap->rf2.has_scoring = false; + } - if (close(simmap->scs2.fd_telemetry) == -1) - { - return 200; - } + if (simmap->scs2.has_telemetry == true) { + if (munmap(simmap->scs2.telemetry_map_addr, + sizeof(simmap->scs2.scs2_telemetry)) == -1) { + return 100; + } - simmap->scs2.has_telemetry = false; + if (close(simmap->scs2.fd_telemetry) == -1) { + return 200; } - bzero(simdata, sizeof(SimData)); - simdata->simapiversion = SIMAPI_VERSION; - return error; -} + simmap->scs2.has_telemetry = false; + } -int freesimmap(SimMap* simmap, bool issimd) -{ - simapi_log(SIMAPI_LOGLEVEL_INFO, "Freeing universal shared memory"); + if (simmap->dirt2.has_telemetry == true) { + simmap->dirt2.has_telemetry = false; + } - if(simmap->fd == -1) - { - free(simmap); - return 0; - } + bzero(simdata, sizeof(SimData)); + simdata->simapiversion = SIMAPI_VERSION; + return error; +} - if (munmap(simmap->addr, sizeof(SimData)) == -1) - { - return 100; - } - if(issimd == true) - { - shm_unlink(SIMAPI_MEM_FILE); - } +int freesimmap(SimMap *simmap, bool issimd) { + simapi_log(SIMAPI_LOGLEVEL_INFO, "Freeing universal shared memory"); - if (close(simmap->fd) == -1) - { - return 200; - } - simmap->hasSimApiDat = false; + if (simmap->fd == -1) { free(simmap); return 0; -} + } -int opensimmap(SimMap* simmap) -{ - simmap->fd = shm_open(SIMAPI_MEM_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - simapi_log(SIMAPI_LOGLEVEL_INFO, "Opening universal shared memory"); - if (simmap->fd == -1) - { - printf("open"); - return 10; - } - int res = ftruncate(simmap->fd, sizeof(SimData)); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + if (munmap(simmap->addr, sizeof(SimData)) == -1) { + return 100; + } + if (issimd == true) { + shm_unlink(SIMAPI_MEM_FILE); + } - void* addr = mmap(NULL, sizeof(SimData), PROT_WRITE, MAP_SHARED, simmap->fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - simmap->addr = addr; - return 0; + if (close(simmap->fd) == -1) { + return 200; + } + simmap->hasSimApiDat = false; + free(simmap); + return 0; } +int opensimmap(SimMap *simmap) { + simmap->fd = shm_open(SIMAPI_MEM_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + simapi_log(SIMAPI_LOGLEVEL_INFO, "Opening universal shared memory"); + if (simmap->fd == -1) { + printf("open"); + return 10; + } + int res = ftruncate(simmap->fd, sizeof(SimData)); + if (res == -1) { + printf("ftruncate"); + return 20; + } -int opensimcompatmap(SimCompatMap* compatmap) -{ - compatmap->pcars2_fd = shm_open(PCARS2_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if (compatmap->pcars2_fd == -1) - { - printf("open"); - return 10; - } - int res = ftruncate(compatmap->pcars2_fd, PCARS2_SIZE); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + void *addr = + mmap(NULL, sizeof(SimData), PROT_WRITE, MAP_SHARED, simmap->fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + simmap->addr = addr; + return 0; +} - void* addr = mmap(NULL, PCARS2_SIZE, PROT_WRITE, MAP_SHARED, compatmap->pcars2_fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - compatmap->pcars2_addr = addr; +int opensimcompatmap(SimCompatMap *compatmap) { + compatmap->pcars2_fd = + shm_open(PCARS2_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (compatmap->pcars2_fd == -1) { + printf("open"); + return 10; + } + int res = ftruncate(compatmap->pcars2_fd, PCARS2_SIZE); + if (res == -1) { + printf("ftruncate"); + return 20; + } - compatmap->acphysics_fd = shm_open(AC_PHYSICS_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if (compatmap->acphysics_fd == -1) - { - printf("open"); - return 10; - } - res = ftruncate(compatmap->acphysics_fd, AC_PHYSICS_SIZE); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + void *addr = + mmap(NULL, PCARS2_SIZE, PROT_WRITE, MAP_SHARED, compatmap->pcars2_fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + compatmap->pcars2_addr = addr; - addr = mmap(NULL, AC_PHYSICS_SIZE, PROT_WRITE, MAP_SHARED, compatmap->acphysics_fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - compatmap->acphysics_addr = addr; + compatmap->acphysics_fd = + shm_open(AC_PHYSICS_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (compatmap->acphysics_fd == -1) { + printf("open"); + return 10; + } + res = ftruncate(compatmap->acphysics_fd, AC_PHYSICS_SIZE); + if (res == -1) { + printf("ftruncate"); + return 20; + } - compatmap->acgraphics_fd = shm_open(AC_GRAPHIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if (compatmap->acgraphics_fd == -1) - { - printf("open"); - return 10; - } - res = ftruncate(compatmap->acgraphics_fd, AC_GRAPHIC_SIZE); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + addr = mmap(NULL, AC_PHYSICS_SIZE, PROT_WRITE, MAP_SHARED, + compatmap->acphysics_fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + compatmap->acphysics_addr = addr; - addr = mmap(NULL, AC_GRAPHIC_SIZE, PROT_WRITE, MAP_SHARED, compatmap->acgraphics_fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - compatmap->acgraphics_addr = addr; + compatmap->acgraphics_fd = + shm_open(AC_GRAPHIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (compatmap->acgraphics_fd == -1) { + printf("open"); + return 10; + } + res = ftruncate(compatmap->acgraphics_fd, AC_GRAPHIC_SIZE); + if (res == -1) { + printf("ftruncate"); + return 20; + } - compatmap->acstatic_fd = shm_open(AC_STATIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if (compatmap->acstatic_fd == -1) - { - printf("open"); - return 10; - } - res = ftruncate(compatmap->acstatic_fd, AC_STATIC_SIZE); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + addr = mmap(NULL, AC_GRAPHIC_SIZE, PROT_WRITE, MAP_SHARED, + compatmap->acgraphics_fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + compatmap->acgraphics_addr = addr; - addr = mmap(NULL, AC_STATIC_SIZE, PROT_WRITE, MAP_SHARED, compatmap->acstatic_fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - compatmap->acstatic_addr = addr; + compatmap->acstatic_fd = + shm_open(AC_STATIC_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (compatmap->acstatic_fd == -1) { + printf("open"); + return 10; + } + res = ftruncate(compatmap->acstatic_fd, AC_STATIC_SIZE); + if (res == -1) { + printf("ftruncate"); + return 20; + } - compatmap->accrew_fd = shm_open(AC_CREWCHIEF_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); - if (compatmap->accrew_fd == -1) - { - printf("open"); - return 10; - } - res = ftruncate(compatmap->accrew_fd, AC_CREWCHIEF_SIZE); - if (res == -1) - { - printf("ftruncate"); - return 20; - } + addr = mmap(NULL, AC_STATIC_SIZE, PROT_WRITE, MAP_SHARED, + compatmap->acstatic_fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + compatmap->acstatic_addr = addr; - addr = mmap(NULL, AC_CREWCHIEF_SIZE, PROT_WRITE, MAP_SHARED, compatmap->accrew_fd, 0); - if (addr == MAP_FAILED) - { - printf("mmap"); - return 30; - } - compatmap->accrew_addr = addr; - return 0; + compatmap->accrew_fd = + shm_open(AC_CREWCHIEF_FILE, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (compatmap->accrew_fd == -1) { + printf("open"); + return 10; + } + res = ftruncate(compatmap->accrew_fd, AC_CREWCHIEF_SIZE); + if (res == -1) { + printf("ftruncate"); + return 20; + } + + addr = mmap(NULL, AC_CREWCHIEF_SIZE, PROT_WRITE, MAP_SHARED, + compatmap->accrew_fd, 0); + if (addr == MAP_FAILED) { + printf("mmap"); + return 30; + } + compatmap->accrew_addr = addr; + return 0; } -int freesimcompatmap(SimCompatMap* compatmap) -{ - if (munmap(compatmap->acphysics_addr, AC_PHYSICS_SIZE) == -1) - { - return 100; - } - shm_unlink(AC_PHYSICS_FILE); +int freesimcompatmap(SimCompatMap *compatmap) { + if (munmap(compatmap->acphysics_addr, AC_PHYSICS_SIZE) == -1) { + return 100; + } + shm_unlink(AC_PHYSICS_FILE); - if (close(compatmap->acphysics_fd) == -1) - { - return 200; - } + if (close(compatmap->acphysics_fd) == -1) { + return 200; + } - if (munmap(compatmap->acstatic_addr, AC_STATIC_SIZE) == -1) - { - return 100; - } - shm_unlink(AC_STATIC_FILE); + if (munmap(compatmap->acstatic_addr, AC_STATIC_SIZE) == -1) { + return 100; + } + shm_unlink(AC_STATIC_FILE); - if (close(compatmap->acstatic_fd) == -1) - { - return 200; - } + if (close(compatmap->acstatic_fd) == -1) { + return 200; + } - if (munmap(compatmap->acgraphics_addr, AC_GRAPHIC_SIZE) == -1) - { - return 100; - } - shm_unlink(AC_GRAPHIC_FILE); + if (munmap(compatmap->acgraphics_addr, AC_GRAPHIC_SIZE) == -1) { + return 100; + } + shm_unlink(AC_GRAPHIC_FILE); - if (close(compatmap->acgraphics_fd) == -1) - { - return 200; - } + if (close(compatmap->acgraphics_fd) == -1) { + return 200; + } - if (munmap(compatmap->accrew_addr, AC_CREWCHIEF_SIZE) == -1) - { - return 100; - } - shm_unlink(AC_CREWCHIEF_FILE); + if (munmap(compatmap->accrew_addr, AC_CREWCHIEF_SIZE) == -1) { + return 100; + } + shm_unlink(AC_CREWCHIEF_FILE); - if (close(compatmap->accrew_fd) == -1) - { - return 200; - } + if (close(compatmap->accrew_fd) == -1) { + return 200; + } - if (munmap(compatmap->pcars2_addr, PCARS2_SIZE) == -1) - { - return 100; - } - shm_unlink(PCARS2_FILE); + if (munmap(compatmap->pcars2_addr, PCARS2_SIZE) == -1) { + return 100; + } + shm_unlink(PCARS2_FILE); - if (close(compatmap->pcars2_fd) == -1) - { - return 200; - } + if (close(compatmap->pcars2_fd) == -1) { + return 200; + } - return 0; + return 0; } diff --git a/simapi/simmapper.h b/simapi/simmapper.h index 66599ef..d379056 100644 --- a/simapi/simmapper.h +++ b/simapi/simmapper.h @@ -1,90 +1,90 @@ #ifndef _SIMMAPPER_H #define _SIMMAPPER_H -//#include "ac.h" -//#include "rf2.h" -//#include "pcars2.h" -//#include "scs2.h" +// #include "ac.h" +// #include "rf2.h" +// #include "pcars2.h" +// #include "scs2.h" #include -#include "simdata.h" #include "simapi.h" +#include "simdata.h" +typedef struct { + bool isSimOn; + bool SimUsesUDP; + bool SimSupportsBasicTelemetry; + bool SimSupportsTyreEffects; + bool SimSupportsRealtimeTelemetry; + bool SimSupportsAdvancedUI; + SimulatorAPI mapapi; + SimulatorAPI simulatorapi; + SimulatorEXE simulatorexe; + pid_t pid; +} SimInfo; -typedef struct -{ - bool isSimOn; - bool SimUsesUDP; - bool SimSupportsBasicTelemetry; - bool SimSupportsTyreEffects; - bool SimSupportsRealtimeTelemetry; - bool SimSupportsAdvancedUI; - SimulatorAPI mapapi; - SimulatorAPI simulatorapi; - SimulatorEXE simulatorexe; - pid_t pid; -} -SimInfo; - - -//typedef struct +// typedef struct //{ -// void* addr; -// int fd; -// union -// { -// ACMap* ac; -// RF2Map* rf2; -// PCars2Map* pcars2; -// SCS2Map* scs2; -// } d; -//} -//SimMap; +// void* addr; +// int fd; +// union +// { +// ACMap* ac; +// RF2Map* rf2; +// PCars2Map* pcars2; +// SCS2Map* scs2; +// } d; +// } +// SimMap; -//struct _simmap; +// struct _simmap; typedef struct _simmap SimMap; -typedef struct -{ - void* pcars2_addr; - int pcars2_fd; - void* acphysics_addr; - int acphysics_fd; - void* acgraphics_addr; - int acgraphics_fd; - void* acstatic_addr; - int acstatic_fd; - void* accrew_addr; - int accrew_fd; -} -SimCompatMap; +typedef struct { + void *pcars2_addr; + int pcars2_fd; + void *acphysics_addr; + int acphysics_fd; + void *acgraphics_addr; + int acgraphics_fd; + void *acstatic_addr; + int acstatic_fd; + void *accrew_addr; + int accrew_fd; +} SimCompatMap; bool does_sim_need_bridge(SimulatorEXE s); -SimulatorEXE getSimExe(SimInfo* si); -SimInfo getSim(SimData* simdata, SimMap* simmap, bool force_udp, int (*setup_udp)(int), bool simd); -int siminit(SimData* simdata, SimMap* simmap, SimulatorAPI simulator); -int siminitudp(SimData* simdata, SimMap* simmap, SimulatorAPI simulator); -int simdatamap(SimData* simdata, SimMap* simmap, SimMap* simmap2, SimulatorAPI simulator, bool udp, char* base); -int simfree(SimData* simdata, SimMap* simmap, SimulatorAPI simulator); +SimulatorEXE getSimExe(SimInfo *si); +SimInfo getSim(SimData *simdata, SimMap *simmap, bool force_udp, + int (*setup_udp)(int), bool simd); +int siminit(SimData *simdata, SimMap *simmap, SimulatorAPI simulator); +int siminitudp(SimData *simdata, SimMap *simmap, SimulatorAPI simulator); +int simdatamap(SimData *simdata, SimMap *simmap, SimMap *simmap2, + SimulatorAPI simulator, bool udp, char *base); +int simfree(SimData *simdata, SimMap *simmap, SimulatorAPI simulator); -int simapi_strtogame(const char* game); -char* simapi_gametostr(SimulatorEXE sim); -char* simapi_gametofullstr(SimulatorEXE sim); +int simapi_strtogame(const char *game); +char *simapi_gametostr(SimulatorEXE sim); +char *simapi_gametofullstr(SimulatorEXE sim); -SimMap* createSimMap(void); -void* getSimMapPtr(SimMap* simmap); -int simdmap(SimMap* simmap, SimData* simdata); -int opensimmap(SimMap* simmap); -int freesimmap(SimMap* simmap, bool issimd); -int opensimcompatmap(SimCompatMap* compatmap); -int freesimcompatmap(SimCompatMap* compatmap); +SimMap *createSimMap(void); +void *getSimMapPtr(SimMap *simmap); +int simdmap(SimMap *simmap, SimData *simdata); +int opensimmap(SimMap *simmap); +int freesimmap(SimMap *simmap, bool issimd); +int opensimcompatmap(SimCompatMap *compatmap); +int freesimcompatmap(SimCompatMap *compatmap); -void SetProximityData(SimData* simdata, int cars, int8_t lr_flip); +void SetProximityData(SimData *simdata, int cars, int8_t lr_flip); -void map_assetto_corsa_data(SimData* simdata, SimMap* simmap, SimulatorEXE simexe); -void map_rfactor2_data(SimData* simdata, SimMap* simmap); -void map_project_cars2_data(SimData* simdata, SimMap* simmap, bool udp, char* base); -void map_trucks_data(SimData* simdata, SimMap* simmap); -void map_outgauge_outsim_data(SimData* simdata, SimMap* simmap, SimulatorEXE simexe, char* base); +void map_assetto_corsa_data(SimData *simdata, SimMap *simmap, + SimulatorEXE simexe); +void map_rfactor2_data(SimData *simdata, SimMap *simmap); +void map_project_cars2_data(SimData *simdata, SimMap *simmap, bool udp, + char *base); +void map_trucks_data(SimData *simdata, SimMap *simmap); +void map_outgauge_outsim_data(SimData *simdata, SimMap *simmap, + SimulatorEXE simexe, char *base); +void map_dirt_rally_2_data(SimData *simdata, SimMap *simmap, char *base); #endif diff --git a/simd/simd.c b/simd/simd.c index 2594ad5..f7d29b4 100644 --- a/simd/simd.c +++ b/simd/simd.c @@ -855,9 +855,17 @@ int main(int argc, char** argv) uv_poll_t* poll; if(simds.daemon == false) { - uv_handle_set_data((uv_handle_t*) &pollt, (void*) baton); - uv_poll_init(uv_default_loop(), &pollt, 0); - uv_poll_start(&pollt, UV_READABLE, cb); + if (isatty(0)) { + uv_handle_set_data((uv_handle_t*) &pollt, (void*) baton); + int r = uv_poll_init(uv_default_loop(), &pollt, 0); + if (r == 0) { + uv_poll_start(&pollt, UV_READABLE, cb); + } else { + y_log_message(Y_LOG_LEVEL_WARNING, "Could not initialize stdin poll, interactive mode disabled"); + } + } else { + y_log_message(Y_LOG_LEVEL_INFO, "Not a TTY, interactive mode disabled"); + } } uv_run(uv_default_loop(), UV_RUN_DEFAULT); diff --git a/tests/README.md b/tests/README.md index c6b6a82..c2f9939 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,33 @@ -# simapi test tool +# simapi test tools -## compile this test tool with +## Telemetry Viewer + +A live telemetry viewer for DiRT Rally 2.0 and other simulators. Make sure the SIMD daemon is running first. + +### Compile the telemetry viewer: +``` +gcc -o view_telemetry view_telemetry.c -I ../include -I ../simapi -L /usr/local/lib -lsimapi -lm +``` + +### Run the telemetry viewer: + +**Bash/Zsh:** +```bash +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib +./view_telemetry +``` + +**Fish shell:** +```fish +set -x LD_LIBRARY_PATH /usr/local/lib +./view_telemetry +``` + +This will display live telemetry data including RPM, speed, gear, throttle/brake/clutch positions, and lap information. + +## Original setsimdata tool + +### Compile this test tool with ``` gcc -DASSETTOCORSA setsimdata.c ../simmap/mapacdata.c ../simmap/maprf2data.c -I ../simamap -o a.out ``` @@ -9,12 +36,12 @@ or gcc -DRFACTOR2 setsimdata.c ../simmap/mapacdata.c ../simmap/maprf2data.c -I ../simamap -o a.out ``` -## Load a dumped shared memory file +### Load a dumped shared memory file ``` ./setsimdata -a loadfile -f acpmf_graphics -s Graphics_dump5 ``` -## Set data +### Set data ``` setsimdata -a set -f acpmf_physics -n SPageFilePhysics_gear -t integer -v 9 ``` diff --git a/tests/view_telemetry.c b/tests/view_telemetry.c new file mode 100644 index 0000000..7c83a4a --- /dev/null +++ b/tests/view_telemetry.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include + +#include "../simapi/simdata.h" + +volatile int running = 1; + +void signal_handler(int signum) { running = 0; } + +void print_lap_time(const char *label, LapTime lt) { + printf("%s: %02u:%02u:%02u.%03u\n", label, lt.hours, lt.minutes, lt.seconds, + lt.fraction); +} + +int main(int argc, char *argv[]) { + int fd; + SimData *simdata; + + // Set up signal handler for clean exit + signal(SIGINT, signal_handler); + + printf("Opening SIMAPI.DAT shared memory...\n"); + + // Open the shared memory file + fd = open("/dev/shm/SIMAPI.DAT", O_RDONLY); + if (fd == -1) { + perror("Failed to open shared memory"); + return 1; + } + + // Map the shared memory + simdata = + (SimData *)mmap(NULL, sizeof(SimData), PROT_READ, MAP_SHARED, fd, 0); + if (simdata == MAP_FAILED) { + perror("Failed to map shared memory"); + close(fd); + return 1; + } + + printf("Connected to telemetry data. Press Ctrl+C to exit.\n"); + printf("Waiting for DiRT Rally 2.0 to start sending data...\n\n"); + + while (running) { + if (simdata->simon == 1 && simdata->simstatus >= SIMAPI_STATUS_MENU) { + printf("\033[H\033[J"); // Clear screen and move cursor to home + printf("--- DiRT Rally 2.0 Telemetry (simapi) ---\n\n"); + + printf("Vehicle:\n"); + printf(" Car: %s\n", simdata->car); + printf(" RPM: %d / %d (Idle: %d)\n", simdata->rpms, simdata->maxrpm, + simdata->idlerpm); + printf(" Speed: %d km/h\n", simdata->velocity); + printf(" Gear: %s (Max: %d)\n", simdata->gearc, simdata->maxgears); + printf(" Fuel: %.2f / %.2f L\n", simdata->fuel, simdata->fuelcapacity); + + printf("\nInputs:\n"); + printf(" Gas: %.2f | Brake: %.2f\n", simdata->gas, simdata->brake); + printf(" Clutch: %.2f | Steer: %.3f\n", simdata->clutch, + simdata->steer); + + printf("\nOrientation (Euler):\n"); + printf(" Roll: %6.1f deg\n", simdata->roll); + printf(" Pitch: %6.1f deg\n", simdata->pitch); + printf(" Yaw: %6.1f deg (Heading)\n", simdata->heading); + + printf("\nForces (G):\n"); + printf(" Lat: %6.2f | Long: %6.2f | Vert: %6.2f\n", + simdata->Xvelocity, simdata->Yvelocity, simdata->Zvelocity); + + printf("\nWheels:\n"); + printf(" Speeds (m/s): RL: %5.1f | RR: %5.1f | FL: %5.1f | FR: %5.1f\n", + simdata->tyreRPS[0], simdata->tyreRPS[1], simdata->tyreRPS[2], + simdata->tyreRPS[3]); + printf(" T-Press (PSI): RL: %5.2f | RR: %5.2f | FL: %5.2f | FR: %5.2f\n", + simdata->tyrepressure[0], simdata->tyrepressure[1], + simdata->tyrepressure[2], simdata->tyrepressure[3]); + printf(" B-Temp (C): RL: %5.1f | RR: %5.1f | FL: %5.1f | FR: %5.1f\n", + simdata->braketemp[0], simdata->braketemp[1], + simdata->braketemp[2], simdata->braketemp[3]); + + printf("\nSuspension:\n"); + printf(" Pos: RL: %6.3f | RR: %6.3f | FL: %6.3f | FR: %6.3f\n", + simdata->suspension[0], simdata->suspension[1], + simdata->suspension[2], simdata->suspension[3]); + printf(" Vel: RL: %6.3f | RR: %6.3f | FL: %6.3f | FR: %6.3f\n", + simdata->suspvelocity[0], simdata->suspvelocity[1], + simdata->suspvelocity[2], simdata->suspvelocity[3]); + + printf("\nSession & Race:\n"); + printf(" Status: %d\n", simdata->simstatus); + printf(" Lap: %d / %d (Completed: %d)\n", simdata->lap, + simdata->numlaps, simdata->playerlaps); + printf(" Position: %d\n", simdata->position); + printf(" Progress: %.3f\n", simdata->playerspline); + printf(" Distance: %.1f m (of %.1f m)\n", simdata->distance, + simdata->trackdistancearound); + printf(" Sector: %d\n", simdata->sectorindex + 1); + printf(" Sec 1: %7.3f s | Sec 2: %7.3f s\n", simdata->sector1time, + simdata->sector2time); + print_lap_time(" Current", simdata->currentlap); + print_lap_time(" Last ", simdata->lastlap); + + printf("\nDebug (World Pos):\n"); + printf(" X: %.2f | Y: %.2f | Z: %.2f\n", simdata->worldposx, + simdata->worldposy, simdata->worldposz); + + fflush(stdout); + } else { + printf("\rWaiting for game data... (Status: %d, SimOn: %d) ", + simdata->simstatus, simdata->simon); + fflush(stdout); + } + + usleep(100000); // 100ms delay + } + + printf("\n\nExiting...\n"); + + // Clean up + munmap(simdata, sizeof(SimData)); + close(fd); + + return 0; +}