commit cb00061d434acf9e72eeeadb956a3d82a05c154a Author: Mihai Dinculescu Date: Sat Oct 1 17:00:52 2022 +0100 Extract from msfs-2020-gps-link diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c63b766 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,482 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bindgen" +version = "0.60.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clang-sys" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "3.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +dependencies = [ + "atty", + "bitflags", + "clap_lex", + "indexmap", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "env_logger" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.134" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" + +[[package]] +name = "libloading" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "num_enum" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "once_cell" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" + +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "proc-macro-crate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +dependencies = [ + "once_cell", + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "serde" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "simconnect-sdk" +version = "0.1.0" +dependencies = [ + "bindgen", + "num_enum", + "tracing", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" + +[[package]] +name = "thiserror" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + +[[package]] +name = "tracing" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" + +[[package]] +name = "which" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" +dependencies = [ + "either", + "libc", + "once_cell", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2ef7fb0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "simconnect-sdk" +version = "0.1.0" +authors = ["Mihai Dinculescu "] +edition = "2021" +description = "SimConnect SDK for Rust" +license = "MIT" + +[build-dependencies] +bindgen = "0.60" + +[dependencies] +num_enum = "0.5" +tracing = "0.1" diff --git a/README.md b/README.md new file mode 100644 index 0000000..8f5eb0c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# SimConnect SDK in Rust + +WIP diff --git a/SimConnect.dll b/SimConnect.dll new file mode 100644 index 0000000..da40b73 Binary files /dev/null and b/SimConnect.dll differ diff --git a/SimConnect.h b/SimConnect.h new file mode 100644 index 0000000..edf7c6a --- /dev/null +++ b/SimConnect.h @@ -0,0 +1,780 @@ +//----------------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- + +#ifndef _SIMCONNECT_H_ +#define _SIMCONNECT_H_ + +#pragma once + +#ifdef _MSFS_WASM + #ifndef SIMCONNECT_WASM_MODULE + #define SIMCONNECT_WASM_MODULE "env" + #endif +#endif + +#ifndef DWORD_MAX +#define DWORD_MAX 0xFFFFFFFF +#endif + +#include + +typedef DWORD SIMCONNECT_OBJECT_ID; + +//---------------------------------------------------------------------------- +// Constants +//---------------------------------------------------------------------------- + +static const DWORD SIMCONNECT_UNUSED = DWORD_MAX; // special value to indicate unused event, ID +static const DWORD SIMCONNECT_OBJECT_ID_USER = 0; // proxy value for User vehicle ObjectID + +static const float SIMCONNECT_CAMERA_IGNORE_FIELD = FLT_MAX; //Used to tell the Camera API to NOT modify the value in this part of the argument. + +static const DWORD SIMCONNECT_CLIENTDATA_MAX_SIZE = 8192; // maximum value for SimConnect_CreateClientData dwSize parameter + + +// Notification Group priority values +static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST = 1; // highest priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_HIGHEST_MASKABLE = 10000000; // highest priority that allows events to be masked +static const DWORD SIMCONNECT_GROUP_PRIORITY_STANDARD = 1900000000; // standard priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_DEFAULT = 2000000000; // default priority +static const DWORD SIMCONNECT_GROUP_PRIORITY_LOWEST = 4000000000; // priorities lower than this will be ignored + +//Weather observations Metar strings +static const DWORD MAX_METAR_LENGTH = 2000; + +// Maximum thermal size is 100 km. +static const float MAX_THERMAL_SIZE = 100000; +static const float MAX_THERMAL_RATE = 1000; + +// SIMCONNECT_DATA_INITPOSITION.Airspeed +static const DWORD INITPOSITION_AIRSPEED_CRUISE = -1; // aircraft's cruise airspeed +static const DWORD INITPOSITION_AIRSPEED_KEEP = -2; // keep current airspeed + +// AddToClientDataDefinition dwSizeOrType parameter type values +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT8 = -1; // 8-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT16 = -2; // 16-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT32 = -3; // 32-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_INT64 = -4; // 64-bit integer number +static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT32 = -5; // 32-bit floating-point number (float) +static const DWORD SIMCONNECT_CLIENTDATATYPE_FLOAT64 = -6; // 64-bit floating-point number (double) + +// AddToClientDataDefinition dwOffset parameter special values +static const DWORD SIMCONNECT_CLIENTDATAOFFSET_AUTO = -1; // automatically compute offset of the ClientData variable + +// Open ConfigIndex parameter special value +static const DWORD SIMCONNECT_OPEN_CONFIGINDEX_LOCAL = -1; // ignore SimConnect.cfg settings, and force local connection + +//---------------------------------------------------------------------------- +// Enum definitions +//---------------------------------------------------------------------------- + +//these came from substituteMacros +#define SIMCONNECT_REFSTRUCT struct +#define SIMCONNECT_STRUCT struct +#define SIMCONNECT_STRING(name, size) char name[size] +#define SIMCONNECT_GUID GUID +#define SIMCONNECT_STRINGV(name) char name[1] +#define SIMCONNECT_DATAV(name, id, count) DWORD name +#define SIMCONNECT_FIXEDTYPE_DATAV(type, name, count, cliMarshalAs, cliType) type name[1] +#define SIMCONNECT_GUID GUID +#define SIMCONNECT_ENUM enum +#define SIMCONNECT_ENUM_FLAGS typedef DWORD +#define SIMCONNECT_USER_ENUM typedef DWORD + + +// Receive data types +SIMCONNECT_ENUM SIMCONNECT_RECV_ID { + SIMCONNECT_RECV_ID_NULL, + SIMCONNECT_RECV_ID_EXCEPTION, + SIMCONNECT_RECV_ID_OPEN, + SIMCONNECT_RECV_ID_QUIT, + SIMCONNECT_RECV_ID_EVENT, + SIMCONNECT_RECV_ID_EVENT_OBJECT_ADDREMOVE, + SIMCONNECT_RECV_ID_EVENT_FILENAME, + SIMCONNECT_RECV_ID_EVENT_FRAME, + SIMCONNECT_RECV_ID_SIMOBJECT_DATA, + SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE, + SIMCONNECT_RECV_ID_WEATHER_OBSERVATION, + SIMCONNECT_RECV_ID_CLOUD_STATE, + SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID, + SIMCONNECT_RECV_ID_RESERVED_KEY, + SIMCONNECT_RECV_ID_CUSTOM_ACTION, + SIMCONNECT_RECV_ID_SYSTEM_STATE, + SIMCONNECT_RECV_ID_CLIENT_DATA, + SIMCONNECT_RECV_ID_EVENT_WEATHER_MODE, + SIMCONNECT_RECV_ID_AIRPORT_LIST, + SIMCONNECT_RECV_ID_VOR_LIST, + SIMCONNECT_RECV_ID_NDB_LIST, + SIMCONNECT_RECV_ID_WAYPOINT_LIST, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED, + SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED, + SIMCONNECT_RECV_ID_EVENT_RACE_END, + SIMCONNECT_RECV_ID_EVENT_RACE_LAP, +#ifdef ENABLE_SIMCONNECT_EXPERIMENTAL + SIMCONNECT_RECV_ID_PICK, +#endif //ENABLE_SIMCONNECT_EXPERIMENTAL +}; + + + +// Data data types +SIMCONNECT_ENUM SIMCONNECT_DATATYPE { + SIMCONNECT_DATATYPE_INVALID, // invalid data type + SIMCONNECT_DATATYPE_INT32, // 32-bit integer number + SIMCONNECT_DATATYPE_INT64, // 64-bit integer number + SIMCONNECT_DATATYPE_FLOAT32, // 32-bit floating-point number (float) + SIMCONNECT_DATATYPE_FLOAT64, // 64-bit floating-point number (double) + SIMCONNECT_DATATYPE_STRING8, // 8-byte string + SIMCONNECT_DATATYPE_STRING32, // 32-byte string + SIMCONNECT_DATATYPE_STRING64, // 64-byte string + SIMCONNECT_DATATYPE_STRING128, // 128-byte string + SIMCONNECT_DATATYPE_STRING256, // 256-byte string + SIMCONNECT_DATATYPE_STRING260, // 260-byte string + SIMCONNECT_DATATYPE_STRINGV, // variable-length string + + SIMCONNECT_DATATYPE_INITPOSITION, // see SIMCONNECT_DATA_INITPOSITION + SIMCONNECT_DATATYPE_MARKERSTATE, // see SIMCONNECT_DATA_MARKERSTATE + SIMCONNECT_DATATYPE_WAYPOINT, // see SIMCONNECT_DATA_WAYPOINT + SIMCONNECT_DATATYPE_LATLONALT, // see SIMCONNECT_DATA_LATLONALT + SIMCONNECT_DATATYPE_XYZ, // see SIMCONNECT_DATA_XYZ + + SIMCONNECT_DATATYPE_MAX // enum limit +}; + +// Exception error types +SIMCONNECT_ENUM SIMCONNECT_EXCEPTION { + SIMCONNECT_EXCEPTION_NONE, + + SIMCONNECT_EXCEPTION_ERROR, + SIMCONNECT_EXCEPTION_SIZE_MISMATCH, + SIMCONNECT_EXCEPTION_UNRECOGNIZED_ID, + SIMCONNECT_EXCEPTION_UNOPENED, + SIMCONNECT_EXCEPTION_VERSION_MISMATCH, + SIMCONNECT_EXCEPTION_TOO_MANY_GROUPS, + SIMCONNECT_EXCEPTION_NAME_UNRECOGNIZED, + SIMCONNECT_EXCEPTION_TOO_MANY_EVENT_NAMES, + SIMCONNECT_EXCEPTION_EVENT_ID_DUPLICATE, + SIMCONNECT_EXCEPTION_TOO_MANY_MAPS, + SIMCONNECT_EXCEPTION_TOO_MANY_OBJECTS, + SIMCONNECT_EXCEPTION_TOO_MANY_REQUESTS, + SIMCONNECT_EXCEPTION_WEATHER_INVALID_PORT, + SIMCONNECT_EXCEPTION_WEATHER_INVALID_METAR, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_GET_OBSERVATION, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_CREATE_STATION, + SIMCONNECT_EXCEPTION_WEATHER_UNABLE_TO_REMOVE_STATION, + SIMCONNECT_EXCEPTION_INVALID_DATA_TYPE, + SIMCONNECT_EXCEPTION_INVALID_DATA_SIZE, + SIMCONNECT_EXCEPTION_DATA_ERROR, + SIMCONNECT_EXCEPTION_INVALID_ARRAY, + SIMCONNECT_EXCEPTION_CREATE_OBJECT_FAILED, + SIMCONNECT_EXCEPTION_LOAD_FLIGHTPLAN_FAILED, + SIMCONNECT_EXCEPTION_OPERATION_INVALID_FOR_OBJECT_TYPE, + SIMCONNECT_EXCEPTION_ILLEGAL_OPERATION, + SIMCONNECT_EXCEPTION_ALREADY_SUBSCRIBED, + SIMCONNECT_EXCEPTION_INVALID_ENUM, + SIMCONNECT_EXCEPTION_DEFINITION_ERROR, + SIMCONNECT_EXCEPTION_DUPLICATE_ID, + SIMCONNECT_EXCEPTION_DATUM_ID, + SIMCONNECT_EXCEPTION_OUT_OF_BOUNDS, + SIMCONNECT_EXCEPTION_ALREADY_CREATED, + SIMCONNECT_EXCEPTION_OBJECT_OUTSIDE_REALITY_BUBBLE, + SIMCONNECT_EXCEPTION_OBJECT_CONTAINER, + SIMCONNECT_EXCEPTION_OBJECT_AI, + SIMCONNECT_EXCEPTION_OBJECT_ATC, + SIMCONNECT_EXCEPTION_OBJECT_SCHEDULE, +}; + +// Object types +SIMCONNECT_ENUM SIMCONNECT_SIMOBJECT_TYPE { + SIMCONNECT_SIMOBJECT_TYPE_USER, + SIMCONNECT_SIMOBJECT_TYPE_ALL, + SIMCONNECT_SIMOBJECT_TYPE_AIRCRAFT, + SIMCONNECT_SIMOBJECT_TYPE_HELICOPTER, + SIMCONNECT_SIMOBJECT_TYPE_BOAT, + SIMCONNECT_SIMOBJECT_TYPE_GROUND, +}; + +// EventState values +SIMCONNECT_ENUM SIMCONNECT_STATE { + SIMCONNECT_STATE_OFF, + SIMCONNECT_STATE_ON, +}; + +// Object Data Request Period values +SIMCONNECT_ENUM SIMCONNECT_PERIOD { + SIMCONNECT_PERIOD_NEVER, + SIMCONNECT_PERIOD_ONCE, + SIMCONNECT_PERIOD_VISUAL_FRAME, + SIMCONNECT_PERIOD_SIM_FRAME, + SIMCONNECT_PERIOD_SECOND, +}; + + +SIMCONNECT_ENUM SIMCONNECT_MISSION_END { + SIMCONNECT_MISSION_FAILED, + SIMCONNECT_MISSION_CRASHED, + SIMCONNECT_MISSION_SUCCEEDED +}; + +// ClientData Request Period values +SIMCONNECT_ENUM SIMCONNECT_CLIENT_DATA_PERIOD { + SIMCONNECT_CLIENT_DATA_PERIOD_NEVER, + SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, + SIMCONNECT_CLIENT_DATA_PERIOD_VISUAL_FRAME, + SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, + SIMCONNECT_CLIENT_DATA_PERIOD_SECOND, +}; + +SIMCONNECT_ENUM SIMCONNECT_TEXT_TYPE { + SIMCONNECT_TEXT_TYPE_SCROLL_BLACK, + SIMCONNECT_TEXT_TYPE_SCROLL_WHITE, + SIMCONNECT_TEXT_TYPE_SCROLL_RED, + SIMCONNECT_TEXT_TYPE_SCROLL_GREEN, + SIMCONNECT_TEXT_TYPE_SCROLL_BLUE, + SIMCONNECT_TEXT_TYPE_SCROLL_YELLOW, + SIMCONNECT_TEXT_TYPE_SCROLL_MAGENTA, + SIMCONNECT_TEXT_TYPE_SCROLL_CYAN, + SIMCONNECT_TEXT_TYPE_PRINT_BLACK=0x0100, + SIMCONNECT_TEXT_TYPE_PRINT_WHITE, + SIMCONNECT_TEXT_TYPE_PRINT_RED, + SIMCONNECT_TEXT_TYPE_PRINT_GREEN, + SIMCONNECT_TEXT_TYPE_PRINT_BLUE, + SIMCONNECT_TEXT_TYPE_PRINT_YELLOW, + SIMCONNECT_TEXT_TYPE_PRINT_MAGENTA, + SIMCONNECT_TEXT_TYPE_PRINT_CYAN, + SIMCONNECT_TEXT_TYPE_MENU=0x0200, +}; + +SIMCONNECT_ENUM SIMCONNECT_TEXT_RESULT { + SIMCONNECT_TEXT_RESULT_MENU_SELECT_1, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_2, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_3, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_4, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_5, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_6, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_7, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_8, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_9, + SIMCONNECT_TEXT_RESULT_MENU_SELECT_10, + SIMCONNECT_TEXT_RESULT_DISPLAYED = 0x00010000, + SIMCONNECT_TEXT_RESULT_QUEUED, + SIMCONNECT_TEXT_RESULT_REMOVED, + SIMCONNECT_TEXT_RESULT_REPLACED, + SIMCONNECT_TEXT_RESULT_TIMEOUT, +}; + +SIMCONNECT_ENUM SIMCONNECT_WEATHER_MODE { + SIMCONNECT_WEATHER_MODE_THEME, + SIMCONNECT_WEATHER_MODE_RWW, + SIMCONNECT_WEATHER_MODE_CUSTOM, + SIMCONNECT_WEATHER_MODE_GLOBAL, +}; + +SIMCONNECT_ENUM SIMCONNECT_FACILITY_LIST_TYPE { + SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, + SIMCONNECT_FACILITY_LIST_TYPE_WAYPOINT, + SIMCONNECT_FACILITY_LIST_TYPE_NDB, + SIMCONNECT_FACILITY_LIST_TYPE_VOR, + SIMCONNECT_FACILITY_LIST_TYPE_COUNT // invalid +}; + + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_VOR_FLAGS; // flags for SIMCONNECT_RECV_ID_VOR_LIST + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_NAV_SIGNAL = 0x00000001; // Has Nav signal + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_LOCALIZER = 0x00000002; // Has localizer + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_GLIDE_SLOPE = 0x00000004; // Has Nav signal + static const DWORD SIMCONNECT_RECV_ID_VOR_LIST_HAS_DME = 0x00000008; // Station has DME + + + +// bits for the Waypoint Flags field: may be combined +SIMCONNECT_ENUM_FLAGS SIMCONNECT_WAYPOINT_FLAGS; + static const DWORD SIMCONNECT_WAYPOINT_NONE = 0x00; + static const DWORD SIMCONNECT_WAYPOINT_SPEED_REQUESTED = 0x04; // requested speed at waypoint is valid + static const DWORD SIMCONNECT_WAYPOINT_THROTTLE_REQUESTED = 0x08; // request a specific throttle percentage + static const DWORD SIMCONNECT_WAYPOINT_COMPUTE_VERTICAL_SPEED = 0x10; // compute vertical to speed to reach waypoint altitude when crossing the waypoint + static const DWORD SIMCONNECT_WAYPOINT_ALTITUDE_IS_AGL = 0x20; // AltitudeIsAGL + static const DWORD SIMCONNECT_WAYPOINT_ON_GROUND = 0x00100000; // place this waypoint on the ground + static const DWORD SIMCONNECT_WAYPOINT_REVERSE = 0x00200000; // Back up to this waypoint. Only valid on first waypoint + static const DWORD SIMCONNECT_WAYPOINT_WRAP_TO_FIRST = 0x00400000; // Wrap around back to first waypoint. Only valid on last waypoint. + static const DWORD SIMCONNECT_WAYPOINT_ALWAYS_BACKUP = 0x00800000; // Go from first waypoint to last one moving only backwards + static const DWORD SIMCONNECT_WAYPOINT_KEEP_LAST_HEADING = 0x01000000; // Object doesn't only go from waypoint to waypoint using position but it will also keep the same heading computed on the last 2 waypoints + static const DWORD SIMCONNECT_WAYPOINT_YIELD_TO_USER = 0x02000000; // Object will never be too close of the player. If waypoints pass too close of the player, the object will stop and wait + static const DWORD SIMCONNECT_WAYPOINT_CAN_REVERSE = 0x04000000; // This flags handle the behaviour of the object if it can't reach a waypoint. By default, it will take a other way and try to reach this point again. With this flag, object will try some stuff to reach this waypoint in a better condition (moving backwards...) + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_EVENT_FLAG; + static const DWORD SIMCONNECT_EVENT_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_EVENT_FLAG_FAST_REPEAT_TIMER = 0x00000001; // set event repeat timer to simulate fast repeat + static const DWORD SIMCONNECT_EVENT_FLAG_SLOW_REPEAT_TIMER = 0x00000002; // set event repeat timer to simulate slow repeat + static const DWORD SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY = 0x00000010; // interpret GroupID parameter as priority value + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_REQUEST_FLAG; + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested data when value(s) change + static const DWORD SIMCONNECT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested data in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_DATA_SET_FLAG; + static const DWORD SIMCONNECT_DATA_SET_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CREATE_CLIENT_DATA_FLAG; + static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CREATE_CLIENT_DATA_FLAG_READ_ONLY = 0x00000001; // permit only ClientData creator to write into ClientData + + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_REQUEST_FLAG; + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED = 0x00000001; // send requested ClientData when value(s) change + static const DWORD SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_TAGGED = 0x00000002; // send requested ClientData in tagged format + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_CLIENT_DATA_SET_FLAG; + static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_DEFAULT = 0x00000000; + static const DWORD SIMCONNECT_CLIENT_DATA_SET_FLAG_TAGGED = 0x00000001; // data is in tagged format + + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_VIEW_SYSTEM_EVENT_DATA; // dwData contains these flags for the "View" System Event + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D = 0x00000001; // 2D Panels in cockpit view + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL = 0x00000002; // Virtual (3D) panels in cockpit view + static const DWORD SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL = 0x00000004; // Orthogonal (Map) view + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_SOUND_SYSTEM_EVENT_DATA; // dwData contains these flags for the "Sound" System Event + static const DWORD SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER = 0x00000001; // Sound Master + + +#ifdef ENABLE_SIMCONNECT_EXPERIMENTAL + +SIMCONNECT_ENUM_FLAGS SIMCONNECT_PICK_FLAGS +{ + SIMCONNECT_PICK_GROUND = 0x01, // pick ground/ pick result item is ground location + SIMCONNECT_PICK_AI = 0x02, // pick AI / pick result item is AI, (dwSimObjectID is valid) + SIMCONNECT_PICK_SCENERY = 0x04, // pick scenery/ pick result item is scenery object (hSceneryObject is valid) + SIMCONNECT_PICK_ALL = SIMCONNECT_PICK_SCENERY | SIMCONNECT_PICK_AI | SIMCONNECT_PICK_GROUND, // pick all / (not valid on pick result item) + SIMCONNECT_PICK_COORDSASPIXELS = 0x08, +}; + +#endif //ENABLE_SIMCONNECT_EXPERIMENTAL + +//---------------------------------------------------------------------------- +// User-defined enums +//---------------------------------------------------------------------------- + +SIMCONNECT_USER_ENUM SIMCONNECT_NOTIFICATION_GROUP_ID; //client-defined notification group ID +SIMCONNECT_USER_ENUM SIMCONNECT_INPUT_GROUP_ID; //client-defined input group ID +SIMCONNECT_USER_ENUM SIMCONNECT_DATA_DEFINITION_ID; //client-defined data definition ID +SIMCONNECT_USER_ENUM SIMCONNECT_DATA_REQUEST_ID; //client-defined request data ID + +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_EVENT_ID; //client-defined client event ID +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_ID; //client-defined client data ID +SIMCONNECT_USER_ENUM SIMCONNECT_CLIENT_DATA_DEFINITION_ID; //client-defined client data definition ID + + +//---------------------------------------------------------------------------- +// Struct definitions +//---------------------------------------------------------------------------- + +#pragma pack(push, 1) + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV +{ + DWORD dwSize; // record size + DWORD dwVersion; // interface version + DWORD dwID; // see SIMCONNECT_RECV_ID +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EXCEPTION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EXCEPTION +{ + DWORD dwException; // see SIMCONNECT_EXCEPTION + static const DWORD UNKNOWN_SENDID = 0; + DWORD dwSendID; // see SimConnect_GetLastSentPacketID + static const DWORD UNKNOWN_INDEX = DWORD_MAX; + DWORD dwIndex; // index of parameter that was source of error +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_OPEN : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_OPEN +{ + SIMCONNECT_STRING( szApplicationName, 256); + DWORD dwApplicationVersionMajor; + DWORD dwApplicationVersionMinor; + DWORD dwApplicationBuildMajor; + DWORD dwApplicationBuildMinor; + DWORD dwSimConnectVersionMajor; + DWORD dwSimConnectVersionMinor; + DWORD dwSimConnectBuildMajor; + DWORD dwSimConnectBuildMinor; + DWORD dwReserved1; + DWORD dwReserved2; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_QUIT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_QUIT +{ +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_EVENT +{ + static const DWORD UNKNOWN_GROUP = DWORD_MAX; + DWORD uGroupID; + DWORD uEventID; + DWORD dwData; // uEventID-dependent context +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FILENAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME +{ + SIMCONNECT_STRING( szFileName, MAX_PATH); // uEventID-dependent context + DWORD dwFlags; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_OBJECT_ADDREMOVE : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FILENAME +{ + SIMCONNECT_SIMOBJECT_TYPE eObjType; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_FRAME : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_FRAME +{ + float fFrameRate; + float fSimSpeed; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SERVER_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SERVER_STARTED +{ + // No event specific data, for now +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_CLIENT_STARTED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_CLIENT_STARTED +{ + // No event specific data, for now +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_MULTIPLAYER_SESSION_ENDED : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_MULTIPLAYER_SESSION_ENDED +{ + // No event specific data, for now +}; + +// SIMCONNECT_DATA_RACE_RESULT +SIMCONNECT_STRUCT SIMCONNECT_DATA_RACE_RESULT +{ + DWORD dwNumberOfRacers; // The total number of racers + SIMCONNECT_GUID MissionGUID; // The name of the mission to execute, NULL if no mission + SIMCONNECT_STRING( szPlayerName, MAX_PATH); // The name of the player + SIMCONNECT_STRING( szSessionType, MAX_PATH); // The type of the multiplayer session: "LAN", "GAMESPY") + SIMCONNECT_STRING( szAircraft, MAX_PATH); // The aircraft type + SIMCONNECT_STRING( szPlayerRole, MAX_PATH); // The player role in the mission + double fTotalTime; // Total time in seconds, 0 means DNF + double fPenaltyTime; // Total penalty time in seconds + DWORD dwIsDisqualified; // non 0 - disqualified, 0 - not disqualified +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_END : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_END +{ + DWORD dwRacerNumber; // The index of the racer the results are for + SIMCONNECT_DATA_RACE_RESULT RacerData; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_RACE_LAP : public SIMCONNECT_RECV_EVENT // when dwID == SIMCONNECT_RECV_ID_EVENT_RACE_LAP +{ + DWORD dwLapIndex; // The index of the lap the results are for + SIMCONNECT_DATA_RACE_RESULT RacerData; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA +{ + DWORD dwRequestID; + DWORD dwObjectID; + DWORD dwDefineID; + DWORD dwFlags; // SIMCONNECT_DATA_REQUEST_FLAG + DWORD dwentrynumber; // if multiple objects returned, this is number out of . + DWORD dwoutof; // note: starts with 1, not 0. + DWORD dwDefineCount; // data count (number of datums, *not* byte count) + SIMCONNECT_DATAV( dwData, dwDefineID, ); // data begins here, dwDefineCount data items +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_SIMOBJECT_DATA_BYTYPE +{ +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLIENT_DATA : public SIMCONNECT_RECV_SIMOBJECT_DATA // when dwID == SIMCONNECT_RECV_ID_CLIENT_DATA +{ +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WEATHER_OBSERVATION : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_WEATHER_OBSERVATION +{ + DWORD dwRequestID; + SIMCONNECT_STRINGV( szMetar); // Variable length string whose maximum size is MAX_METAR_LENGTH +}; + +static const int SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH = 64; +static const int SIMCONNECT_CLOUD_STATE_ARRAY_SIZE = SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH*SIMCONNECT_CLOUD_STATE_ARRAY_WIDTH; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CLOUD_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_CLOUD_STATE +{ + DWORD dwRequestID; + DWORD dwArraySize; + SIMCONNECT_FIXEDTYPE_DATAV(BYTE, rgbData, dwArraySize, U1 /*member of UnmanagedType enum*/ , System::Byte /*cli type*/); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_ASSIGNED_OBJECT_ID : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_ASSIGNED_OBJECT_ID +{ + DWORD dwRequestID; + DWORD dwObjectID; +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_RESERVED_KEY : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY +{ + SIMCONNECT_STRING( szChoiceReserved, 30); + SIMCONNECT_STRING( szReservedKey, 50); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_SYSTEM_STATE : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_SYSTEM_STATE +{ + DWORD dwRequestID; + DWORD dwInteger; + float fFloat; + SIMCONNECT_STRING( szString, MAX_PATH); +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_CUSTOM_ACTION : public SIMCONNECT_RECV_EVENT +{ + SIMCONNECT_GUID guidInstanceId; // Instance id of the action that executed + DWORD dwWaitForCompletion; // Wait for completion flag on the action + SIMCONNECT_STRINGV( szPayLoad); // Variable length string payload associated with the mission action. +}; + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_EVENT_WEATHER_MODE : public SIMCONNECT_RECV_EVENT +{ + // No event specific data - the new weather mode is in the base structure dwData member. +}; + +// SIMCONNECT_RECV_FACILITIES_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_FACILITIES_LIST : public SIMCONNECT_RECV +{ + DWORD dwRequestID; + DWORD dwArraySize; + DWORD dwEntryNumber; // when the array of items is too big for one send, which send this is (0..dwOutOf-1) + DWORD dwOutOf; // total number of transmissions the list is chopped into +}; + +// SIMCONNECT_DATA_FACILITY_AIRPORT +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_AIRPORT +{ + SIMCONNECT_STRING(Icao, 9); // ICAO of the object + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // meters +}; + +// SIMCONNECT_RECV_AIRPORT_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_AIRPORT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_AIRPORT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_AIRPORT /*cli type*/); +}; + + +// SIMCONNECT_DATA_FACILITY_WAYPOINT +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_WAYPOINT : public SIMCONNECT_DATA_FACILITY_AIRPORT +{ + float fMagVar; // Magvar in degrees +}; + +// SIMCONNECT_RECV_WAYPOINT_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_WAYPOINT_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_WAYPOINT, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_WAYPOINT /*cli type*/); +}; + +// SIMCONNECT_DATA_FACILITY_NDB +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_NDB : public SIMCONNECT_DATA_FACILITY_WAYPOINT +{ + DWORD fFrequency; // frequency in Hz +}; + +// SIMCONNECT_RECV_NDB_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_NDB_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_NDB, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_NDB /*cli type*/); +}; + +// SIMCONNECT_DATA_FACILITY_VOR +SIMCONNECT_REFSTRUCT SIMCONNECT_DATA_FACILITY_VOR : public SIMCONNECT_DATA_FACILITY_NDB +{ + DWORD Flags; // SIMCONNECT_VOR_FLAGS + float fLocalizer; // Localizer in degrees + double GlideLat; // Glide Slope Location (deg, deg, meters) + double GlideLon; + double GlideAlt; + float fGlideSlopeAngle; // Glide Slope in degrees +}; + +// SIMCONNECT_RECV_VOR_LIST +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_VOR_LIST : public SIMCONNECT_RECV_FACILITIES_LIST +{ + SIMCONNECT_FIXEDTYPE_DATAV(SIMCONNECT_DATA_FACILITY_VOR, rgData, dwArraySize, U1 /*member of UnmanagedType enum*/, SIMCONNECT_DATA_FACILITY_VOR /*cli type*/); +}; + +#ifdef ENABLE_SIMCONNECT_EXPERIMENTAL + +SIMCONNECT_REFSTRUCT SIMCONNECT_RECV_PICK : public SIMCONNECT_RECV // when dwID == SIMCONNECT_RECV_ID_RESERVED_KEY +{ + HANDLE hContext; + DWORD dwFlags; // + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // feet + int xPos; //reserved + int yPos; //reserved; + DWORD dwSimObjectID; + HANDLE hSceneryObject; + DWORD dwentrynumber; // if multiple objects returned, this is number out of . + DWORD dwoutof; // note: starts with 1, not 0. +}; + +#endif //ENABLE_SIMCONNECT_EXPERIMENTAL + + +// SIMCONNECT_DATATYPE_INITPOSITION +SIMCONNECT_STRUCT SIMCONNECT_DATA_INITPOSITION +{ + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // feet + double Pitch; // degrees + double Bank; // degrees + double Heading; // degrees + DWORD OnGround; // 1=force to be on the ground + DWORD Airspeed; // knots +}; + + +// SIMCONNECT_DATATYPE_MARKERSTATE +SIMCONNECT_STRUCT SIMCONNECT_DATA_MARKERSTATE +{ + SIMCONNECT_STRING( szMarkerName, 64); + DWORD dwMarkerState; +}; + +// SIMCONNECT_DATATYPE_WAYPOINT +SIMCONNECT_STRUCT SIMCONNECT_DATA_WAYPOINT +{ + double Latitude; // degrees + double Longitude; // degrees + double Altitude; // feet + unsigned long Flags; + double ktsSpeed; // knots + double percentThrottle; +}; + +// SIMCONNECT_DATA_LATLONALT +SIMCONNECT_STRUCT SIMCONNECT_DATA_LATLONALT +{ + double Latitude; + double Longitude; + double Altitude; +}; + +// SIMCONNECT_DATA_XYZ +SIMCONNECT_STRUCT SIMCONNECT_DATA_XYZ +{ + double x; + double y; + double z; +}; + +#pragma pack(pop) + +//---------------------------------------------------------------------------- +// End of Struct definitions +//---------------------------------------------------------------------------- + +typedef void (CALLBACK *DispatchProc)(SIMCONNECT_RECV* pData, DWORD cbData, void* pContext); + +#if !defined(SIMCONNECTAPI) + #ifdef _MSFS_WASM + #ifdef __INTELLISENSE__ + #define MODULE_EXPORT + #define SIMCONNECTAPI extern "C" HRESULT + #else + #define MODULE_EXPORT __attribute__( ( visibility( "default" ) ) ) + #define SIMCONNECTAPI extern "C" __attribute__((import_module(SIMCONNECT_WASM_MODULE))) HRESULT + #endif + #else + #define MODULE_EXPORT + #define SIMCONNECTAPI extern "C" HRESULT __stdcall + #endif +#endif + +SIMCONNECTAPI SimConnect_MapClientEventToSimEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * EventName = ""); +SIMCONNECTAPI SimConnect_TransmitClientEvent(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD dwData, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_EVENT_FLAG Flags); +SIMCONNECTAPI SimConnect_SetSystemEventState(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, SIMCONNECT_STATE dwState); +SIMCONNECTAPI SimConnect_AddClientEventToNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID, BOOL bMaskable = FALSE); +SIMCONNECTAPI SimConnect_RemoveClientEvent(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, SIMCONNECT_CLIENT_EVENT_ID EventID); +SIMCONNECTAPI SimConnect_SetNotificationGroupPriority(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD uPriority); +SIMCONNECTAPI SimConnect_ClearNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID); +SIMCONNECTAPI SimConnect_RequestNotificationGroup(HANDLE hSimConnect, SIMCONNECT_NOTIFICATION_GROUP_ID GroupID, DWORD dwReserved = 0, DWORD Flags = 0); +SIMCONNECTAPI SimConnect_AddToDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, const char * DatumName, const char * UnitsName, SIMCONNECT_DATATYPE DatumType = SIMCONNECT_DATATYPE_FLOAT64, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); +SIMCONNECTAPI SimConnect_ClearDataDefinition(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID); +SIMCONNECTAPI SimConnect_RequestDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_PERIOD Period, SIMCONNECT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); +SIMCONNECTAPI SimConnect_RequestDataOnSimObjectType(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_DATA_DEFINITION_ID DefineID, DWORD dwRadiusMeters, SIMCONNECT_SIMOBJECT_TYPE type); +SIMCONNECTAPI SimConnect_SetDataOnSimObject(HANDLE hSimConnect, SIMCONNECT_DATA_DEFINITION_ID DefineID, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_SET_FLAG Flags, DWORD ArrayCount, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_MapInputEventToClientEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition, SIMCONNECT_CLIENT_EVENT_ID DownEventID, DWORD DownValue = 0, SIMCONNECT_CLIENT_EVENT_ID UpEventID = (SIMCONNECT_CLIENT_EVENT_ID)SIMCONNECT_UNUSED, DWORD UpValue = 0, BOOL bMaskable = FALSE); +SIMCONNECTAPI SimConnect_SetInputGroupPriority(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD uPriority); +SIMCONNECTAPI SimConnect_RemoveInputEvent(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, const char * szInputDefinition); +SIMCONNECTAPI SimConnect_ClearInputGroup(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID); +SIMCONNECTAPI SimConnect_SetInputGroupState(HANDLE hSimConnect, SIMCONNECT_INPUT_GROUP_ID GroupID, DWORD dwState); +SIMCONNECTAPI SimConnect_RequestReservedKey(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * szKeyChoice1 = "", const char * szKeyChoice2 = "", const char * szKeyChoice3 = ""); +SIMCONNECTAPI SimConnect_SubscribeToSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID, const char * SystemEventName); +SIMCONNECTAPI SimConnect_UnsubscribeFromSystemEvent(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID EventID); +SIMCONNECTAPI SimConnect_WeatherRequestInterpolatedObservation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt); +SIMCONNECTAPI SimConnect_WeatherRequestObservationAtStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); +SIMCONNECTAPI SimConnect_WeatherRequestObservationAtNearestStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon); +SIMCONNECTAPI SimConnect_WeatherCreateStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO, const char * szName, float lat, float lon, float alt); +SIMCONNECTAPI SimConnect_WeatherRemoveStation(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szICAO); +SIMCONNECTAPI SimConnect_WeatherSetObservation(HANDLE hSimConnect, DWORD Seconds, const char * szMETAR); +SIMCONNECTAPI SimConnect_WeatherSetModeServer(HANDLE hSimConnect, DWORD dwPort, DWORD dwSeconds); +SIMCONNECTAPI SimConnect_WeatherSetModeTheme(HANDLE hSimConnect, const char * szThemeName); +SIMCONNECTAPI SimConnect_WeatherSetModeGlobal(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_WeatherSetModeCustom(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_WeatherSetDynamicUpdateRate(HANDLE hSimConnect, DWORD dwRate); +SIMCONNECTAPI SimConnect_WeatherRequestCloudState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float minLat, float minLon, float minAlt, float maxLat, float maxLon, float maxAlt, DWORD dwFlags = 0); +SIMCONNECTAPI SimConnect_WeatherCreateThermal(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, float lat, float lon, float alt, float radius, float height, float coreRate = 3.0f, float coreTurbulence = 0.05f, float sinkRate = 3.0f, float sinkTurbulence = 0.2f, float coreSize = 0.4f, float coreTransitionSize = 0.1f, float sinkLayerSize = 0.4f, float sinkTransitionSize = 0.1f); +SIMCONNECTAPI SimConnect_WeatherRemoveThermal(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID); +SIMCONNECTAPI SimConnect_AICreateParkedATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, const char * szAirportID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateEnrouteATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, int iFlightNumber, const char * szFlightPlanPath, double dFlightPlanPosition, BOOL bTouchAndGo, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateNonATCAircraft(HANDLE hSimConnect, const char * szContainerTitle, const char * szTailNumber, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AICreateSimulatedObject(HANDLE hSimConnect, const char * szContainerTitle, SIMCONNECT_DATA_INITPOSITION InitPos, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AIReleaseControl(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AIRemoveObject(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_AISetAircraftFlightPlan(HANDLE hSimConnect, SIMCONNECT_OBJECT_ID ObjectID, const char * szFlightPlanPath, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_ExecuteMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); +SIMCONNECTAPI SimConnect_CompleteCustomMissionAction(HANDLE hSimConnect, const GUID guidInstanceId); +SIMCONNECTAPI SimConnect_Close(HANDLE hSimConnect); +SIMCONNECTAPI SimConnect_RetrieveString(SIMCONNECT_RECV * pData, DWORD cbData, void * pStringV, char ** pszString, DWORD * pcbString); +SIMCONNECTAPI SimConnect_GetLastSentPacketID(HANDLE hSimConnect, DWORD * pdwError); +SIMCONNECTAPI SimConnect_Open(HANDLE * phSimConnect, LPCSTR szName, HWND hWnd, DWORD UserEventWin32, HANDLE hEventHandle, DWORD ConfigIndex); +SIMCONNECTAPI SimConnect_CallDispatch(HANDLE hSimConnect, DispatchProc pfcnDispatch, void * pContext); +SIMCONNECTAPI SimConnect_GetNextDispatch(HANDLE hSimConnect, SIMCONNECT_RECV ** ppData, DWORD * pcbData); +SIMCONNECTAPI SimConnect_RequestResponseTimes(HANDLE hSimConnect, DWORD nCount, float * fElapsedSeconds); +SIMCONNECTAPI SimConnect_InsertString(char * pDest, DWORD cbDest, void ** ppEnd, DWORD * pcbStringV, const char * pSource); +SIMCONNECTAPI SimConnect_CameraSetRelative6DOF(HANDLE hSimConnect, float fDeltaX, float fDeltaY, float fDeltaZ, float fPitchDeg, float fBankDeg, float fHeadingDeg); +SIMCONNECTAPI SimConnect_MenuAddItem(HANDLE hSimConnect, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, DWORD dwData); +SIMCONNECTAPI SimConnect_MenuDeleteItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID); +SIMCONNECTAPI SimConnect_MenuAddSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const char * szMenuItem, SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID, DWORD dwData); +SIMCONNECTAPI SimConnect_MenuDeleteSubItem(HANDLE hSimConnect, SIMCONNECT_CLIENT_EVENT_ID MenuEventID, const SIMCONNECT_CLIENT_EVENT_ID SubMenuEventID); +SIMCONNECTAPI SimConnect_RequestSystemState(HANDLE hSimConnect, SIMCONNECT_DATA_REQUEST_ID RequestID, const char * szState); +SIMCONNECTAPI SimConnect_SetSystemState(HANDLE hSimConnect, const char * szState, DWORD dwInteger, float fFloat, const char * szString); +SIMCONNECTAPI SimConnect_MapClientDataNameToID(HANDLE hSimConnect, const char * szClientDataName, SIMCONNECT_CLIENT_DATA_ID ClientDataID); +SIMCONNECTAPI SimConnect_CreateClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, DWORD dwSize, SIMCONNECT_CREATE_CLIENT_DATA_FLAG Flags); +SIMCONNECTAPI SimConnect_AddToClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, DWORD dwOffset, DWORD dwSizeOrType, float fEpsilon = 0, DWORD DatumID = SIMCONNECT_UNUSED); +SIMCONNECTAPI SimConnect_ClearClientDataDefinition(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID); +SIMCONNECTAPI SimConnect_RequestClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_DATA_REQUEST_ID RequestID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_PERIOD Period = SIMCONNECT_CLIENT_DATA_PERIOD_ONCE, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG Flags = 0, DWORD origin = 0, DWORD interval = 0, DWORD limit = 0); +SIMCONNECTAPI SimConnect_SetClientData(HANDLE hSimConnect, SIMCONNECT_CLIENT_DATA_ID ClientDataID, SIMCONNECT_CLIENT_DATA_DEFINITION_ID DefineID, SIMCONNECT_CLIENT_DATA_SET_FLAG Flags, DWORD dwReserved, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_FlightLoad(HANDLE hSimConnect, const char * szFileName); +SIMCONNECTAPI SimConnect_FlightSave(HANDLE hSimConnect, const char * szFileName, const char * szTitle, const char * szDescription, DWORD Flags); +SIMCONNECTAPI SimConnect_FlightPlanLoad(HANDLE hSimConnect, const char * szFileName); +SIMCONNECTAPI SimConnect_Text(HANDLE hSimConnect, SIMCONNECT_TEXT_TYPE type, float fTimeSeconds, SIMCONNECT_CLIENT_EVENT_ID EventID, DWORD cbUnitSize, void * pDataSet); +SIMCONNECTAPI SimConnect_SubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); +SIMCONNECTAPI SimConnect_UnsubscribeToFacilities(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type); +SIMCONNECTAPI SimConnect_RequestFacilitiesList(HANDLE hSimConnect, SIMCONNECT_FACILITY_LIST_TYPE type, SIMCONNECT_DATA_REQUEST_ID RequestID); + +#endif // _SIMCONNECT_H_ diff --git a/SimConnect.lib b/SimConnect.lib new file mode 100644 index 0000000..561f59e Binary files /dev/null and b/SimConnect.lib differ diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..1d77f04 --- /dev/null +++ b/build.rs @@ -0,0 +1,60 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + println!("cargo:rerun-if-changed=wrapper.h"); + println!("cargo:rerun-if-changed=SimConnect.dll"); + println!("cargo:rerun-if-changed=SimConnect.lib"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + let binary_name = "SimConnect"; + let binary_name_dll = &format!("{binary_name}.dll"); + + let simconnect_path = PathBuf::from(env::current_dir().unwrap().to_str().unwrap()); + let simconnect_dir = simconnect_path.as_path().to_str().unwrap(); + println!("cargo:rustc-link-search={}", simconnect_dir); + println!("cargo:rustc-link-lib={}", binary_name); + + // copy the dll + let mut source_path = PathBuf::from(simconnect_dir); + source_path.push(binary_name_dll); + + let mut target_path = out_path.clone(); + target_path.pop(); + target_path.pop(); + target_path.pop(); + target_path.push(binary_name_dll); + + std::fs::copy(source_path.as_path(), target_path.as_path()).unwrap(); + + let bindings = bindgen::Builder::default() + .header("wrapper.h") + .parse_callbacks(Box::new(bindgen::CargoCallbacks)) + .clang_args(&["-x", "c++"]) + .allowlist_function("SimConnect_Open") + .allowlist_function("SimConnect_Close") + .allowlist_function("SimConnect_MapClientEventToSimEvent") + .allowlist_function("SimConnect_AddClientEventToNotificationGroup") + .allowlist_function("SimConnect_SetNotificationGroupPriority") + .allowlist_function("SimConnect_CallDispatch") + .allowlist_function("SimConnect_GetNextDispatch") + .allowlist_function("SimConnect_AddToDataDefinition") + .allowlist_function("SimConnect_RequestDataOnSimObject") + .allowlist_function("SimConnect_SubscribeToFacilities") + .allowlist_function("SimConnect_RequestFacilitiesList") + .allowlist_type("SIMCONNECT_RECV") + .allowlist_type("SIMCONNECT_RECV_ID") + .allowlist_type("SIMCONNECT_RECV_EVENT") + .allowlist_type("SIMCONNECT_RECV_SIMOBJECT_DATA") + .allowlist_type("SIMCONNECT_RECV_AIRPORT_LIST") + .allowlist_type("SIMCONNECT_CLIENT_DATA_PERIOD") + .allowlist_type("SIMCONNECT_RECV_OPEN") + .allowlist_type("SIMCONNECT_RECV_EXCEPTION") + .allowlist_var("SIMCONNECT_DATA_REQUEST_FLAG_CHANGED") + .generate() + .expect("Unable to generate bindings"); + + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/src/bindings.rs b/src/bindings.rs new file mode 100644 index 0000000..8ba1e73 --- /dev/null +++ b/src/bindings.rs @@ -0,0 +1,7 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(dead_code)] +#![allow(clippy::upper_case_acronyms)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/src/helpers.rs b/src/helpers.rs new file mode 100644 index 0000000..ee6da5b --- /dev/null +++ b/src/helpers.rs @@ -0,0 +1,14 @@ +use std::ffi::CString; + +pub fn fixed_c_str_to_string(data: &[i8]) -> String { + let u8slice = unsafe { &*(data as *const _ as *const [u8]) }; + + let mut value = u8slice.to_vec(); + + let pos = value.iter().position(|c| *c == 0).unwrap_or(value.len()); + + value.truncate(pos); + let icao = unsafe { CString::from_vec_unchecked(value) }; + + icao.to_str().unwrap().to_string() +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..14e43bd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,303 @@ +use helpers::fixed_c_str_to_string; +use std::ffi::c_void; +use std::{convert::TryFrom, fmt::Debug}; + +mod bindings; +mod helpers; + +macro_rules! success { + ($hr:expr) => {{ + let hr = $hr; + if hr != 0 { + return Err(hr); + } + }}; +} + +macro_rules! ok_if_fail { + ($hr:expr, $ret:expr) => {{ + let hr = $hr; + let ret = $ret; + if hr != 0 { + return Ok(ret); + } + }}; +} + +macro_rules! as_c_string { + ($target:expr) => { + std::ffi::CString::new($target) + .expect("failed to create CString") + .as_ptr() + }; +} + +#[derive(Debug)] +pub struct SimConnect { + pub handle: std::ptr::NonNull, +} + +impl SimConnect { + #[tracing::instrument(name = "SimConnect::new")] + pub fn new(name: &str) -> Result { + let mut handle = std::ptr::null_mut(); + + success!(unsafe { + bindings::SimConnect_Open( + &mut handle, + as_c_string!(name), + std::ptr::null_mut(), + 0, + std::ptr::null_mut(), + 0, + ) + }); + + Ok(Self { + handle: std::ptr::NonNull::new(handle) + .expect("ERROR: SimConnect_Open returned null pointer on success"), + }) + } + + #[tracing::instrument(name = "SimConnect::register_event")] + pub fn register_event(&self, event: Event) -> Result<(), i32> { + success!(unsafe { + bindings::SimConnect_MapClientEventToSimEvent( + self.handle.as_ptr(), + event as u32, + event.into_c_char(), + ) + }); + + let group = Group::Group0; + + success!(unsafe { + bindings::SimConnect_AddClientEventToNotificationGroup( + self.handle.as_ptr(), + group as u32, + event as u32, + 0, + ) + }); + + success!(unsafe { + bindings::SimConnect_SetNotificationGroupPriority(self.handle.as_ptr(), group as u32, 1) + }); + + Ok(()) + } + + #[tracing::instrument(name = "SimConnect::add_to_data_definition")] + pub fn add_to_data_definition( + &self, + request_id: u32, + datum_name: &str, + units_name: &str, + ) -> Result<(), i32> { + unsafe { + success!(bindings::SimConnect_AddToDataDefinition( + self.handle.as_ptr(), + request_id, + as_c_string!(datum_name), + as_c_string!(units_name), + bindings::SIMCONNECT_DATATYPE_SIMCONNECT_DATATYPE_FLOAT64, + 0.0, + u32::MAX, + )); + } + + Ok(()) + } + + #[tracing::instrument(name = "SimConnect::request_data_on_sim_object")] + pub fn request_data_on_sim_object( + &self, + request_id: u32, + period: PeriodEnum, + condition: ConditionEnum, + ) -> Result<(), i32> { + unsafe { + let (simconnect_period, simconnect_interval) = match period { + PeriodEnum::VisualFrame { interval } => ( + bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_VISUAL_FRAME, + interval, + ), + PeriodEnum::Second => (bindings::SIMCONNECT_PERIOD_SIMCONNECT_PERIOD_SECOND, 0), + }; + + let simconnect_flags: u32 = match condition { + ConditionEnum::None => 0, + ConditionEnum::Changed => bindings::SIMCONNECT_DATA_REQUEST_FLAG_CHANGED, + }; + + success!(bindings::SimConnect_RequestDataOnSimObject( + self.handle.as_ptr(), + request_id, + request_id, + request_id, + simconnect_period, + simconnect_flags, + 0, + simconnect_interval, + 0, + )); + } + + Ok(()) + } + + #[tracing::instrument(name = "SimConnect::subscribe_to_airport_list")] + pub fn subscribe_to_airport_list(&self, request_id: u32) -> Result<(), i32> { + unsafe { + success!(bindings::SimConnect_SubscribeToFacilities( + self.handle.as_ptr(), + bindings::SIMCONNECT_FACILITY_LIST_TYPE_SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, + request_id, + )); + } + + Ok(()) + } + + #[tracing::instrument(name = "SimConnect::request_airport_list")] + pub fn request_airport_list(&self, request_id: u32) -> Result<(), i32> { + unsafe { + success!(bindings::SimConnect_RequestFacilitiesList( + self.handle.as_ptr(), + bindings::SIMCONNECT_FACILITY_LIST_TYPE_SIMCONNECT_FACILITY_LIST_TYPE_AIRPORT, + request_id, + )); + } + + Ok(()) + } + + pub fn get_next_dispatch(&self) -> Result, i32> { + let mut data_buf: *mut bindings::SIMCONNECT_RECV = std::ptr::null_mut(); + let mut size_buf: bindings::DWORD = 32; + let size_buf_pointer: *mut bindings::DWORD = &mut size_buf; + + unsafe { + ok_if_fail!( + bindings::SimConnect_GetNextDispatch( + self.handle.as_ptr(), + &mut data_buf, + size_buf_pointer + ), + None + ); + }; + + let result = match unsafe { (*data_buf).dwID as i32 } { + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_OPEN => Some(Notification::Open), + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_QUIT => Some(Notification::Quit), + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EVENT => { + let event = unsafe { *(data_buf as *const bindings::SIMCONNECT_RECV_EVENT) }; + let event = Event::try_from(event.uEventID).expect("Unrecognized event"); + Some(Notification::Event(event)) + } + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_SIMOBJECT_DATA => { + let event: &bindings::SIMCONNECT_RECV_SIMOBJECT_DATA = unsafe { + std::mem::transmute_copy( + &(data_buf as *const bindings::SIMCONNECT_RECV_SIMOBJECT_DATA), + ) + }; + + let data_addr = std::ptr::addr_of!(event.dwData); + + Some(Notification::Data(event.dwDefineID, data_addr)) + } + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_AIRPORT_LIST => { + let event: &bindings::SIMCONNECT_RECV_AIRPORT_LIST = unsafe { + std::mem::transmute_copy( + &(data_buf as *const bindings::SIMCONNECT_RECV_AIRPORT_LIST), + ) + }; + + let data = event + .rgData + .iter() + .map(|data| AirportData { + icao: fixed_c_str_to_string(&data.Icao), + lat: data.Latitude, + lon: data.Longitude, + alt: data.Altitude, + }) + .collect::>(); + + Some(Notification::AirportList(data)) + } + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_EXCEPTION => { + let event = unsafe { *(data_buf as *const bindings::SIMCONNECT_RECV_EXCEPTION) }; + Some(Notification::Exception(event.dwException)) + } + bindings::SIMCONNECT_RECV_ID_SIMCONNECT_RECV_ID_NULL => None, + _ => panic!("Got unrecognized notification: {}", unsafe { + (*data_buf).dwID as i32 + }), + }; + + Ok(result) + } +} + +pub enum Notification { + Open, + Event(Event), + Data(u32, *const u32), + AirportList(Vec), + Quit, + Exception(u32), +} + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub struct AirportData { + icao: String, + lat: f64, + lon: f64, + alt: f64, +} + +#[derive(Debug, Copy, Clone, num_enum::TryFromPrimitive)] +#[repr(u32)] +pub enum Event { + Brakes, + BrakesLeft, + AxisLeftBrakeSet, +} + +#[derive(Debug, Clone)] +pub enum PeriodEnum { + VisualFrame { interval: u32 }, + Second, +} + +#[derive(Debug, Clone)] +pub enum ConditionEnum { + None, + Changed, +} + +use std::os::raw::c_char; +impl Event { + fn into_c_char(self) -> *const c_char { + match self { + Event::Brakes => "BRAKES\0".as_ptr() as *const c_char, + Event::BrakesLeft => "BRAKES_LEFT\0".as_ptr() as *const c_char, + Event::AxisLeftBrakeSet => "AXIS_LEFT_BRAKE_SET\0".as_ptr() as *const c_char, + } + } +} + +#[derive(Copy, Clone)] +#[repr(u32)] +enum Group { + Group0, +} + +impl Drop for SimConnect { + fn drop(&mut self) { + let _ = unsafe { bindings::SimConnect_Close(self.handle.as_ptr()) }; + } +} diff --git a/wrapper.h b/wrapper.h new file mode 100644 index 0000000..a01217a --- /dev/null +++ b/wrapper.h @@ -0,0 +1,2 @@ +#include "Windows.h" +#include "C:\MSFS SDK\SimConnect SDK\include\SimConnect.h"