WEBASSEMBLY (WASM)

In order to provide both security and portability, it was decided to move away from add-ons distributed as DLLs in favour of add-ons distributed as WebAssembly modules. In order to do so without requiring a full rewrite of existing add-ons, a new platform toolset was designed for Visual Studio with the following capabilities:

• Direct compilation of C/C++ projects into WebAssembly (WASM).
• Debugging of WebAssembly modules by attaching to the game executable.
• Full support for the standard C library.
• Large support for the standard C++ library (see below).
• Low level API for 2D graphics.
• Higher level NanoVG API for 2D graphics.
• Dedicated Network API for communicating with - and retrieveing information from - external sources.
• GDI+ wrapper based on the NanoVG API to facilitate porting existing add-ons.

While WebAssembly itself is well documented, there seems to be some confusion as to how WebAssembly modules can be run outside of a web environment. To clear a few misconceptions:

• The add-ons developed in WebAssembly for Microsoft Flight Simulator are not interpreted but rather converted to native code ahead of time (as DLLs).
• WebAssembly itself doesn't offer API "X", "Y" or "Z" - it is up to its implementation to grant access to these APIs.

To help you understand the capabilities of using WASM and the functions that are available to you, please see the following sections:

If you need to debug a compiled WASM module, then there is also an extension available for Visual Studio that can help you do this as well as a WASM Debug window for viewing specific details in the simulation. Please see here for more information:

WebAssembly Modules Usage

A WebAssembly module can be used by Microsoft Flight Simulator in two different ways:

• As a standalone module if it is placed in the modules subfolder of a package - it is then automatically loaded when the package is mounted into the VFS.
• As a gauge module which can contain one more gauge callbacks.

In both cases the game will look for and execute the following module functions if they exist:

• extern "C" MSFS_CALLBACK void module_init(void): upon loading or after sign-in.
• extern "C" MSFS_CALLBACK void module_deinit(void): upon closing the game or after sign-out.

File Access

In order to access files from within an add-on, filenames can be prefixed in two ways:

• " .\": to access the files from within the add-on package. This has a read-only access.
• " \work": to access a persistent storage that the add-on can use. This is a read/write access.

Visual Studio Project Properties

When creating your WASM projects, most of the project settings will be the same as for a standard C++ project, however there are some things that should be set up with specific values, which we'll outline here:

• Configuration Properties: These can be left with their default values.
• C/C++: In this section you have the following properties which may need editing:
• General - Debug Information Format: This must be set as //clang:-g. It should be set automatically, but it is worth checking.
• General - Warning Level: Set this field to Level 3, and check your warning regularly, as clang will tell you if you do something wrong.
• General - Multi-processor Compilation: Use this field to speed up your compilation time.
• Optimization: When debugging you should set everything to false/disabled/no. For release, we recomend that you set Optimization at Maximum Optimization (Favor Speed) (/O2). Note that with the latest SDK update, we automatically optimize modules which have a value in Optimization field (/clang:-O3), and no optimization means it is debuggable. The others fields can also be set as you require.
• Linker: In the Debugging section you want to set it to "Generate Debug Info (/DEBUG)" when you are testing and debugging the module, but then for release, set it to "No".

Known Limitations

With the current releases of the game and SDK, the following limitations exist:

• The Windows API is not supported.
• C++ exceptions are not supported.
• C++ threads are not supported.
• The GDI+ wrapper is very incomplete.

Debugging

• Open your project in Visual Studio.
• Build it and copy the WebAssembly module to the panel folder of your SimObject.
• Launch Microsoft Flight Simulator.
• When the game is running, use the Debug > Attach to process command of Visual Studio.
• In the processes list, select Microsoft Flight Simulator.exe and press the Attach button.
• Build the package.
• Launch a flight with your SimObject.
• Once the game has loaded your SimObject, the breakpoints set in the project become active and you can step into your code.

Known Issues/Limitations

• The WebAssembly module must be compiled in Debug mode for C/C++ code for symbols to be visible while debugging.
• The Watch windows work with global variables and memory address. For local variables, use the Locals and Autos windows.
• Stepping into a function may display the Disassembly window instead of the original C/C++ source code.
• If you have any function in the WASM module that does not call another function (ie: it's the last function call in the stack), this function needs to have the macro WASM_FORCE_DEBUG within it, otherwise any debug output for the function will, essentially, be garbage. The image below shows an example of this:
Note that this is only required if you are not using the VS Wasm Debugger Extension.
• When a WASM module is being compiled by MSFS, the following error can appear in the console:
WASM: ERR_VALIDATION_ERROR (-4095 / fffff001)
It usually means that a function declared as "imported" in the WASM module is not found when linking the compiled module with the MSFS libraries. So, keep in mind that:
• When compiling C/C++ to WASM through the MSFS Platform Toolset in Visual Studio, functions that are declared but not implemented in the C/C++ code are automatically flagged as "imported".
• When MSFS recompiles the WASM module it must resolve all these "imported" functions (i.e. find them in the MSFS libraries)
This means that, if you declared a function in your code but forgot to implement it, the WASM module will build without any error and the function will be marked as "imported". However when Microsoft Flight Simulator tries to recompile your WASM module as a DLL, the function will not be found and you will get the error above.