* Fixed indentation.
authorUrban Wallasch <urban.wallasch@freenet.de>
Sun, 21 Jul 2019 19:08:02 +0000 (21:08 +0200)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sun, 21 Jul 2019 19:08:02 +0000 (21:08 +0200)
telemetry.cpp

index 52d7ec16b14a73e3543216c3bcb045ee36f0f50f..342303eb60fb03b05c4b015fd4765791ac4fe4cd 100644 (file)
@@ -71,6 +71,7 @@ bool init_shm(void)
     if ( (void *)-1 == (shmhnd = shmat(shmid, NULL, 0)) )
         return false;
     telemetry = static_cast<struct telemetry_state_t *>(shmhnd);
+    memset(telemetry, 0, sizeof *telemetry);
     return true;
 }
 
@@ -99,230 +100,230 @@ void log_line(const char *const text, ...)
 
 SCSAPI_VOID telemetry_frame_start(const scs_event_t UNUSED(event), const void *const event_info, const scs_context_t UNUSED(context))
 {
-       const struct scs_telemetry_frame_start_t *const info = static_cast<const scs_telemetry_frame_start_t *>(event_info);
+    const struct scs_telemetry_frame_start_t *const info = static_cast<const scs_telemetry_frame_start_t *>(event_info);
 
-       // The following processing of the timestamps is done so the output
-       // from this plugin has continuous time, it is not necessary otherwise.
+    // The following processing of the timestamps is done so the output
+    // from this plugin has continuous time, it is not necessary otherwise.
 
-       // When we just initialized itself, assume that the time started
-       // just now.
+    // When we just initialized itself, assume that the time started
+    // just now.
 
-       if (last_timestamp == static_cast<scs_timestamp_t>(-1)) {
-               last_timestamp = info->paused_simulation_time;
-       }
+    if (last_timestamp == static_cast<scs_timestamp_t>(-1)) {
+        last_timestamp = info->paused_simulation_time;
+    }
 
-       // The timer might be sometimes restarted (e.g. after load) while
-       // we want to provide continuous time on our output.
+    // The timer might be sometimes restarted (e.g. after load) while
+    // we want to provide continuous time on our output.
 
-       if (info->flags & SCS_TELEMETRY_FRAME_START_FLAG_timer_restart) {
-               last_timestamp = 0;
-       }
+    if (info->flags & SCS_TELEMETRY_FRAME_START_FLAG_timer_restart) {
+        last_timestamp = 0;
+    }
 
-       // Advance the timestamp by delta since last frame.
+    // Advance the timestamp by delta since last frame.
 
-       telemetry->timestamp += (info->paused_simulation_time - last_timestamp);
-       last_timestamp = info->paused_simulation_time;
+    telemetry->timestamp += (info->paused_simulation_time - last_timestamp);
+    last_timestamp = info->paused_simulation_time;
 
-       // The raw values.
+    // The raw values.
 
-       telemetry->raw_rendering_timestamp = info->render_time;
-       telemetry->raw_simulation_timestamp = info->simulation_time;
-       telemetry->raw_paused_simulation_timestamp = info->paused_simulation_time;
+    telemetry->raw_rendering_timestamp = info->render_time;
+    telemetry->raw_simulation_timestamp = info->simulation_time;
+    telemetry->raw_paused_simulation_timestamp = info->paused_simulation_time;
 }
 
 SCSAPI_VOID telemetry_frame_end(const scs_event_t UNUSED(event), const void *const UNUSED(event_info), const scs_context_t UNUSED(context))
 {
-       if (output_paused) {
-               return;
-       }
-
-       // The header.
-
-       if (print_header) {
-               print_header = false;
-               log_line("timestamp[us];raw rendering timestamp[us];raw simulation timestamp[us];raw paused simulation timestamp[us];heading[deg];pitch[deg];roll[deg];speed[km/s];cc[km/s]rpm;gear");
-       }
-
-       // The data line.
-
-       log_print("%" SCS_PF_U64 ";%" SCS_PF_U64 ";%" SCS_PF_U64 ";%" SCS_PF_U64, telemetry->timestamp, telemetry->raw_rendering_timestamp, telemetry->raw_simulation_timestamp, telemetry->raw_paused_simulation_timestamp);
-       if (telemetry->orientation_available) {
-               log_print(";%f;%f;%f", telemetry->heading, telemetry->pitch, telemetry->roll);
-       }
-       else {
-               log_print(";---;---;---");
-       }
-       log_line(
-               ";%3.2f;%3.2f;%f;%d",
-               telemetry->speed * 3.6,
-               telemetry->cc * 3.6,
-               telemetry->rpm,
-               telemetry->gear
-       );
+    if (output_paused) {
+        return;
+    }
+
+    // The header.
+
+    if (print_header) {
+        print_header = false;
+        log_line("timestamp[us];raw rendering timestamp[us];raw simulation timestamp[us];raw paused simulation timestamp[us];heading[deg];pitch[deg];roll[deg];speed[km/s];cc[km/s]rpm;gear");
+    }
+
+    // The data line.
+
+    log_print("%" SCS_PF_U64 ";%" SCS_PF_U64 ";%" SCS_PF_U64 ";%" SCS_PF_U64, telemetry->timestamp, telemetry->raw_rendering_timestamp, telemetry->raw_simulation_timestamp, telemetry->raw_paused_simulation_timestamp);
+    if (telemetry->orientation_available) {
+        log_print(";%f;%f;%f", telemetry->heading, telemetry->pitch, telemetry->roll);
+    }
+    else {
+        log_print(";---;---;---");
+    }
+    log_line(
+        ";%3.2f;%3.2f;%f;%d",
+        telemetry->speed * 3.6,
+        telemetry->cc * 3.6,
+        telemetry->rpm,
+        telemetry->gear
+    );
 }
 
 SCSAPI_VOID telemetry_pause(const scs_event_t event, const void *const UNUSED(event_info), const scs_context_t UNUSED(context))
 {
-       output_paused = (event == SCS_TELEMETRY_EVENT_paused);
-       if (output_paused) {
-               log_line("Telemetry paused");
-       }
-       else {
-               log_line("Telemetry unpaused");
-       }
-       print_header = true;
+    output_paused = (event == SCS_TELEMETRY_EVENT_paused);
+    if (output_paused) {
+        log_line("Telemetry paused");
+    }
+    else {
+        log_line("Telemetry unpaused");
+    }
+    print_header = true;
 }
 
 SCSAPI_VOID telemetry_configuration(const scs_event_t event, const void *const event_info, const scs_context_t UNUSED(context))
 {
-       // Here we just print the configuration info.
-
-       const struct scs_telemetry_configuration_t *const info = static_cast<const scs_telemetry_configuration_t *>(event_info);
-       log_line("Configuration: %s", info->id);
-
-       for (const scs_named_value_t *current = info->attributes; current->name; ++current) {
-               log_print("  %s", current->name);
-               if (current->index != SCS_U32_NIL) {
-                       log_print("[%u]", static_cast<unsigned>(current->index));
-               }
-               log_print(" : ");
-               switch (current->value.type) {
-                       case SCS_VALUE_TYPE_INVALID: {
-                               log_line("none");
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_bool: {
-                               log_line("bool = %s", current->value.value_bool.value ? "true" : "false");
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_s32: {
-                               log_line("s32 = %d", static_cast<int>(current->value.value_s32.value));
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_u32: {
-                               log_line("u32 = %u", static_cast<unsigned>(current->value.value_u32.value));
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_u64: {
-                               log_line("u64 = %" SCS_PF_U64, current->value.value_u64.value);
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_float: {
-                               log_line("float = %f", current->value.value_float.value);
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_double: {
-                               log_line("double = %f", current->value.value_double.value);
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_fvector: {
-                               log_line(
-                                       "fvector = (%f,%f,%f)",
-                                       current->value.value_fvector.x,
-                                       current->value.value_fvector.y,
-                                       current->value.value_fvector.z
-                               );
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_dvector: {
-                               log_line(
-                                       "dvector = (%f,%f,%f)",
-                                       current->value.value_dvector.x,
-                                       current->value.value_dvector.y,
-                                       current->value.value_dvector.z
-                               );
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_euler: {
-                               log_line(
-                                       "euler = h:%f p:%f r:%f",
-                                       current->value.value_euler.heading * 360.0f,
-                                       current->value.value_euler.pitch * 360.0f,
-                                       current->value.value_euler.roll * 360.0f
-                               );
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_fplacement: {
-                               log_line(
-                                       "fplacement = (%f,%f,%f) h:%f p:%f r:%f",
-                                       current->value.value_fplacement.position.x,
-                                       current->value.value_fplacement.position.y,
-                                       current->value.value_fplacement.position.z,
-                                       current->value.value_fplacement.orientation.heading * 360.0f,
-                                       current->value.value_fplacement.orientation.pitch * 360.0f,
-                                       current->value.value_fplacement.orientation.roll * 360.0f
-                               );
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_dplacement: {
-                               log_line(
-                                       "dplacement = (%f,%f,%f) h:%f p:%f r:%f",
-                                       current->value.value_dplacement.position.x,
-                                       current->value.value_dplacement.position.y,
-                                       current->value.value_dplacement.position.z,
-                                       current->value.value_dplacement.orientation.heading * 360.0f,
-                                       current->value.value_dplacement.orientation.pitch * 360.0f,
-                                       current->value.value_dplacement.orientation.roll * 360.0f
-                               );
-                               break;
-                       }
-                       case SCS_VALUE_TYPE_string: {
-                               log_line("string = %s", current->value.value_string.value);
-                               break;
-                       }
-                       default: {
-                               log_line("unknown");
-                               break;
-                       }
-               }
-       }
-
-       print_header = true;
+    // Here we just print the configuration info.
+
+    const struct scs_telemetry_configuration_t *const info = static_cast<const scs_telemetry_configuration_t *>(event_info);
+    log_line("Configuration: %s", info->id);
+
+    for (const scs_named_value_t *current = info->attributes; current->name; ++current) {
+        log_print("  %s", current->name);
+        if (current->index != SCS_U32_NIL) {
+            log_print("[%u]", static_cast<unsigned>(current->index));
+        }
+        log_print(" : ");
+        switch (current->value.type) {
+            case SCS_VALUE_TYPE_INVALID: {
+                log_line("none");
+                break;
+            }
+            case SCS_VALUE_TYPE_bool: {
+                log_line("bool = %s", current->value.value_bool.value ? "true" : "false");
+                break;
+            }
+            case SCS_VALUE_TYPE_s32: {
+                log_line("s32 = %d", static_cast<int>(current->value.value_s32.value));
+                break;
+            }
+            case SCS_VALUE_TYPE_u32: {
+                log_line("u32 = %u", static_cast<unsigned>(current->value.value_u32.value));
+                break;
+            }
+            case SCS_VALUE_TYPE_u64: {
+                log_line("u64 = %" SCS_PF_U64, current->value.value_u64.value);
+                break;
+            }
+            case SCS_VALUE_TYPE_float: {
+                log_line("float = %f", current->value.value_float.value);
+                break;
+            }
+            case SCS_VALUE_TYPE_double: {
+                log_line("double = %f", current->value.value_double.value);
+                break;
+            }
+            case SCS_VALUE_TYPE_fvector: {
+                log_line(
+                    "fvector = (%f,%f,%f)",
+                    current->value.value_fvector.x,
+                    current->value.value_fvector.y,
+                    current->value.value_fvector.z
+                );
+                break;
+            }
+            case SCS_VALUE_TYPE_dvector: {
+                log_line(
+                    "dvector = (%f,%f,%f)",
+                    current->value.value_dvector.x,
+                    current->value.value_dvector.y,
+                    current->value.value_dvector.z
+                );
+                break;
+            }
+            case SCS_VALUE_TYPE_euler: {
+                log_line(
+                    "euler = h:%f p:%f r:%f",
+                    current->value.value_euler.heading * 360.0f,
+                    current->value.value_euler.pitch * 360.0f,
+                    current->value.value_euler.roll * 360.0f
+                );
+                break;
+            }
+            case SCS_VALUE_TYPE_fplacement: {
+                log_line(
+                    "fplacement = (%f,%f,%f) h:%f p:%f r:%f",
+                    current->value.value_fplacement.position.x,
+                    current->value.value_fplacement.position.y,
+                    current->value.value_fplacement.position.z,
+                    current->value.value_fplacement.orientation.heading * 360.0f,
+                    current->value.value_fplacement.orientation.pitch * 360.0f,
+                    current->value.value_fplacement.orientation.roll * 360.0f
+                );
+                break;
+            }
+            case SCS_VALUE_TYPE_dplacement: {
+                log_line(
+                    "dplacement = (%f,%f,%f) h:%f p:%f r:%f",
+                    current->value.value_dplacement.position.x,
+                    current->value.value_dplacement.position.y,
+                    current->value.value_dplacement.position.z,
+                    current->value.value_dplacement.orientation.heading * 360.0f,
+                    current->value.value_dplacement.orientation.pitch * 360.0f,
+                    current->value.value_dplacement.orientation.roll * 360.0f
+                );
+                break;
+            }
+            case SCS_VALUE_TYPE_string: {
+                log_line("string = %s", current->value.value_string.value);
+                break;
+            }
+            default: {
+                log_line("unknown");
+                break;
+            }
+        }
+    }
+
+    print_header = true;
 }
 
 // Handling of individual channels.
 
 SCSAPI_VOID telemetry_store_orientation(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
 {
-       assert(context);
-       telemetry_state_t *const state = static_cast<telemetry_state_t *>(context);
-
-       // This callback was registered with the SCS_TELEMETRY_CHANNEL_FLAG_no_value flag
-       // so it is called even when the value is not available.
-
-       if (! value) {
-               state->orientation_available = false;
-               return;
-       }
-
-       assert(value);
-       assert(value->type == SCS_VALUE_TYPE_euler);
-       state->orientation_available = true;
-       state->heading = value->value_euler.heading * 360.0f;
-       state->pitch = value->value_euler.pitch * 360.0f;
-       state->roll = value->value_euler.roll * 360.0f;
+    assert(context);
+    telemetry_state_t *const state = static_cast<telemetry_state_t *>(context);
+
+    // This callback was registered with the SCS_TELEMETRY_CHANNEL_FLAG_no_value flag
+    // so it is called even when the value is not available.
+
+    if (! value) {
+        state->orientation_available = false;
+        return;
+    }
+
+    assert(value);
+    assert(value->type == SCS_VALUE_TYPE_euler);
+    state->orientation_available = true;
+    state->heading = value->value_euler.heading * 360.0f;
+    state->pitch = value->value_euler.pitch * 360.0f;
+    state->roll = value->value_euler.roll * 360.0f;
 }
 
 SCSAPI_VOID telemetry_store_float(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
 {
-       // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
-       // so this callback is only called when a valid value is available.
+    // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
+    // so this callback is only called when a valid value is available.
 
-       assert(value);
-       assert(value->type == SCS_VALUE_TYPE_float);
-       assert(context);
-       *static_cast<float *>(context) = value->value_float.value;
+    assert(value);
+    assert(value->type == SCS_VALUE_TYPE_float);
+    assert(context);
+    *static_cast<float *>(context) = value->value_float.value;
 }
 
 SCSAPI_VOID telemetry_store_s32(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
 {
-       // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
-       // so this callback is only called when a valid value is available.
+    // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
+    // so this callback is only called when a valid value is available.
 
-       assert(value);
-       assert(value->type == SCS_VALUE_TYPE_s32);
-       assert(context);
-       *static_cast<int *>(context) = value->value_s32.value;
+    assert(value);
+    assert(value->type == SCS_VALUE_TYPE_s32);
+    assert(context);
+    *static_cast<int *>(context) = value->value_s32.value;
 }
 
 /**
@@ -332,108 +333,107 @@ SCSAPI_VOID telemetry_store_s32(const scs_string_t name, const scs_u32_t index,
  */
 SCSAPI_RESULT scs_telemetry_init(const scs_u32_t version, const scs_telemetry_init_params_t *const params)
 {
-       // We currently support only one version.
-
-       if (version != SCS_TELEMETRY_VERSION_1_00) {
-               return SCS_RESULT_unsupported;
-       }
-
-       const scs_telemetry_init_params_v100_t *const version_params = static_cast<const scs_telemetry_init_params_v100_t *>(params);
-       if (! init_shm()) {
-               version_params->common.log(SCS_LOG_TYPE_error, "Unable to initialize the log file");
-               return SCS_RESULT_generic_error;
-       }
-
-       // Check application version. Note that this example uses fairly basic channels which are likely to be supported
-       // by any future SCS trucking game however more advanced application might want to at least warn the user if there
-       // is game or version they do not support.
-
-       log_line("Game '%s' %u.%u", version_params->common.game_id, SCS_GET_MAJOR_VERSION(version_params->common.game_version), SCS_GET_MINOR_VERSION(version_params->common.game_version));
-
-       if (strcmp(version_params->common.game_id, SCS_GAME_ID_EUT2) == 0) {
-
-               // Bellow the minimum version there might be some missing features (only minor change) or
-               // incompatible values (major change).
-
-               const scs_u32_t MINIMAL_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_1_00;
-               if (version_params->common.game_version < MINIMAL_VERSION) {
-                       log_line("WARNING: Too old version of the game, some features might behave incorrectly");
-               }
-
-               // Future versions are fine as long the major version is not changed.
-
-               const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_CURRENT;
-               if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
-                       log_line("WARNING: Too new major version of the game, some features might behave incorrectly");
-               }
-       }
-       else if (strcmp(version_params->common.game_id, SCS_GAME_ID_ATS) == 0) {
-
-               // Bellow the minimum version there might be some missing features (only minor change) or
-               // incompatible values (major change).
-
-               const scs_u32_t MINIMAL_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_1_00;
-               if (version_params->common.game_version < MINIMAL_VERSION) {
-                       log_line("WARNING: Too old version of the game, some features might behave incorrectly");
-               }
-
-               // Future versions are fine as long the major version is not changed.
-
-               const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_CURRENT;
-               if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
-                       log_line("WARNING: Too new major version of the game, some features might behave incorrectly");
-               }
-       }
-       else {
-               log_line("WARNING: Unsupported game, some features or values might behave incorrectly");
-       }
-
-       // Register for events. Note that failure to register those basic events
-       // likely indicates invalid usage of the api or some critical problem. As the
-       // example requires all of them, we can not continue if the registration fails.
-
-       const bool events_registered =
-               (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_start, telemetry_frame_start, NULL) == SCS_RESULT_ok) &&
-               (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_end, telemetry_frame_end, NULL) == SCS_RESULT_ok) &&
-               (version_params->register_for_event(SCS_TELEMETRY_EVENT_paused, telemetry_pause, NULL) == SCS_RESULT_ok) &&
-               (version_params->register_for_event(SCS_TELEMETRY_EVENT_started, telemetry_pause, NULL) == SCS_RESULT_ok)
-       ;
-       if (! events_registered) {
-
-               // Registrations created by unsuccessfull initialization are
-               // cleared automatically so we can simply exit.
-
-               version_params->common.log(SCS_LOG_TYPE_error, "Unable to register event callbacks");
-               return SCS_RESULT_generic_error;
-       }
-
-       // Register for the configuration info. As this example only prints the retrieved
-       // data, it can operate even if that fails.
-
-       version_params->register_for_event(SCS_TELEMETRY_EVENT_configuration, telemetry_configuration, NULL);
-
-       // Register for channels. The channel might be missing if the game does not support
-       // it (SCS_RESULT_not_found) or if does not support the requested type
-       // (SCS_RESULT_unsupported_type). For purpose of this example we ignore the failues
-       // so the unsupported channels will remain at theirs default value.
-
-       version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_world_placement, SCS_U32_NIL, SCS_VALUE_TYPE_euler, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_orientation, &telemetry);
-       version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_speed, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->speed);
-       version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_rpm, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->rpm);
-       version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_gear, SCS_U32_NIL, SCS_VALUE_TYPE_s32, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_s32, &telemetry->gear);
-       version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_cruise_control, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->cc);
+    // We currently support only one version.
+
+    if (version != SCS_TELEMETRY_VERSION_1_00) {
+        return SCS_RESULT_unsupported;
+    }
+
+    const scs_telemetry_init_params_v100_t *const version_params = static_cast<const scs_telemetry_init_params_v100_t *>(params);
+    if (! init_shm()) {
+        version_params->common.log(SCS_LOG_TYPE_error, "Unable to initialize the log file");
+        return SCS_RESULT_generic_error;
+    }
+
+    // Check application version. Note that this example uses fairly basic channels which are likely to be supported
+    // by any future SCS trucking game however more advanced application might want to at least warn the user if there
+    // is game or version they do not support.
+
+    log_line("Game '%s' %u.%u", version_params->common.game_id, SCS_GET_MAJOR_VERSION(version_params->common.game_version), SCS_GET_MINOR_VERSION(version_params->common.game_version));
+
+    if (strcmp(version_params->common.game_id, SCS_GAME_ID_EUT2) == 0) {
+
+        // Bellow the minimum version there might be some missing features (only minor change) or
+        // incompatible values (major change).
+
+        const scs_u32_t MINIMAL_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_1_00;
+        if (version_params->common.game_version < MINIMAL_VERSION) {
+            log_line("WARNING: Too old version of the game, some features might behave incorrectly");
+        }
+
+        // Future versions are fine as long the major version is not changed.
+
+        const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_CURRENT;
+        if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
+            log_line("WARNING: Too new major version of the game, some features might behave incorrectly");
+        }
+    }
+    else if (strcmp(version_params->common.game_id, SCS_GAME_ID_ATS) == 0) {
+
+        // Bellow the minimum version there might be some missing features (only minor change) or
+        // incompatible values (major change).
+
+        const scs_u32_t MINIMAL_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_1_00;
+        if (version_params->common.game_version < MINIMAL_VERSION) {
+            log_line("WARNING: Too old version of the game, some features might behave incorrectly");
+        }
+
+        // Future versions are fine as long the major version is not changed.
+
+        const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_CURRENT;
+        if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
+            log_line("WARNING: Too new major version of the game, some features might behave incorrectly");
+        }
+    }
+    else {
+        log_line("WARNING: Unsupported game, some features or values might behave incorrectly");
+    }
+
+    // Register for events. Note that failure to register those basic events
+    // likely indicates invalid usage of the api or some critical problem. As the
+    // example requires all of them, we can not continue if the registration fails.
+
+    const bool events_registered =
+        (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_start, telemetry_frame_start, NULL) == SCS_RESULT_ok) &&
+        (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_end, telemetry_frame_end, NULL) == SCS_RESULT_ok) &&
+        (version_params->register_for_event(SCS_TELEMETRY_EVENT_paused, telemetry_pause, NULL) == SCS_RESULT_ok) &&
+        (version_params->register_for_event(SCS_TELEMETRY_EVENT_started, telemetry_pause, NULL) == SCS_RESULT_ok)
+    ;
+    if (! events_registered) {
+
+        // Registrations created by unsuccessfull initialization are
+        // cleared automatically so we can simply exit.
+
+        version_params->common.log(SCS_LOG_TYPE_error, "Unable to register event callbacks");
+        return SCS_RESULT_generic_error;
+    }
+
+    // Register for the configuration info. As this example only prints the retrieved
+    // data, it can operate even if that fails.
+
+    version_params->register_for_event(SCS_TELEMETRY_EVENT_configuration, telemetry_configuration, NULL);
+
+    // Register for channels. The channel might be missing if the game does not support
+    // it (SCS_RESULT_not_found) or if does not support the requested type
+    // (SCS_RESULT_unsupported_type). For purpose of this example we ignore the failues
+    // so the unsupported channels will remain at theirs default value.
+
+    version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_world_placement, SCS_U32_NIL, SCS_VALUE_TYPE_euler, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_orientation, &telemetry);
+    version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_speed, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->speed);
+    version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_rpm, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->rpm);
+    version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_gear, SCS_U32_NIL, SCS_VALUE_TYPE_s32, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_s32, &telemetry->gear);
+    version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_cruise_control, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->cc);
     version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_fuel_average_consumption, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &telemetry->fc_avg);
 
-       // Set the structure with defaults.
+    // Set the structure with defaults.
 
-//     memset(&telemetry, 0, sizeof(telemetry));
-       print_header = true;
-       last_timestamp = static_cast<scs_timestamp_t>(-1);
+    print_header = true;
+    last_timestamp = static_cast<scs_timestamp_t>(-1);
 
-       // Initially the game is paused.
+    // Initially the game is paused.
 
-       output_paused = true;
-       return SCS_RESULT_ok;
+    output_paused = true;
+    return SCS_RESULT_ok;
 }
 
 /**
@@ -443,31 +443,31 @@ SCSAPI_RESULT scs_telemetry_init(const scs_u32_t version, const scs_telemetry_in
  */
 SCSAPI_VOID scs_telemetry_shutdown(void)
 {
-       // Any cleanup needed. The registrations will be removed automatically
-       // so there is no need to do that manually.
+    // Any cleanup needed. The registrations will be removed automatically
+    // so there is no need to do that manually.
 
-       release_shm();
+    release_shm();
 }
 
 // Cleanup
 
 #ifdef _WIN32
 BOOL APIENTRY DllMain(
-       HMODULE module,
-       DWORD  reason_for_call,
-       LPVOID reseved
+    HMODULE module,
+    DWORD  reason_for_call,
+    LPVOID reseved
 )
 {
-       if (reason_for_call == DLL_PROCESS_DETACH) {
-               release_shm();
-       }
-       return TRUE;
+    if (reason_for_call == DLL_PROCESS_DETACH) {
+        release_shm();
+    }
+    return TRUE;
 }
 #endif
 
 #ifdef __linux__
 void __attribute__ ((destructor)) unload(void)
 {
-       release_shm();
+    release_shm();
 }
 #endif