Update Callbacks
The update callbacks are a way for WASM modules to better handle the Microsoft Flight Simulator 2024 frame updates so that you can run code at specific intervals and better adapt to the simulation state at any given time.
Frame Timings
In previous versions of the simulation, a frame would be split up in the following manner:

So, during the “update” part, the simulation runs first, then any RPN, and then finally the WebAssembly is executed. However, the problem with this is that it can be problematic for addons which manipulate cameras, physics, or systems, since the WASM occurs too late in the frame, which can lead to a noticeable frame shift.
In MSFS 2024, however, a frame will now be split up as follows:

We now have an initial simulation phase which is dedicated only to the physics simulation. At the end of this phase, the position of the aircraft is then determined and the simulation will formulate the new position of the camera (which will have an impact on LOD selection). This means that you can now use the Update API callbacks to target the initial phase before the final camera position is calculated to prevent any graphical issues.
For those modules that don’t change any of the physics or move the camera, the update API also has callbacks that can target before and after the simulation systems update, giving you a lot more granular control of how and when things will happen. There is also a final update phase for WebAssembly which can be used for garbage collection or anything that must be performed at the end of the update phase.
Using The Callbacks
Every callback is an exported function that the simulation looks up by name when the WASM module is loaded. You declare it with the MSFS_CALLBACK macro (and extern "C" for C++ so the name is not mangled), and the name is built from a prefix that depends on what the module is attached to (a gauge, a system, an airport or nothing at all), followed by a fixed postfix. The sections below list the names for each type of module.
A few rules apply to all of them:
- Every callback is optional and independent of the others. Export only the ones that you need.
- The update callbacks (the ones that run before/after physics, before/after systems and at the end of the frame) all receive the time elapsed since the previous frame,
dTime. Theinit,draw,killand mouse callbacks have their own signatures, which are listed in each section. - Gauge and system callbacks receive an
FsContext ctxas their first parameter, airport callbacks receive anFsWasmAirportContext* ctx, and standalone module callbacks receive no context. - Some callbacks replace an older callback. If you export the newer one, the older one is never called. See MSFS 2024 Callback Overrides for the full list.
To see how a file might be structured using these callbacks, below you can find a bare-bones schema for a standalone module (the concept is the same for gauges, systems and airports, only the names and the ctx parameter change):
#include <stdio.h>
#include "$safeprojectname$.h"
extern "C"
{
MSFS_CALLBACK void module_init(void)
{
// This is called when the module is initialized
}
MSFS_CALLBACK void module_pre_sim_physics_update(float dTime)
{
// This is called each frame before the physics part of the simulation is computed.
// dTime is the time between the previous frame and this one
}
MSFS_CALLBACK void module_post_sim_physics_update(float dTime)
{
// This is called each frame after the physics part of the simulation is computed.
// dTime is the time between the previous frame and this one
}
MSFS_CALLBACK void module_pre_sim_systems_update(float dTime)
{
// This is called each frame before the systems part of the simulation is computed.
// At this stage, the position of simobjects has already been determined.
// dTime is the time between the previous frame and this one
}
MSFS_CALLBACK void module_post_sim_systems_update(float dTime)
{
// This is called each frame after the simulation is computed.
// At this stage, simobjects' physics and systems have been determined
// dTime is the time between the previous frame and this one
}
MSFS_CALLBACK void module_late_update(float dTime)
{
// This is called each frame at the end of it, just before the draw part.
// dTime is the time between the previous frame and this one
}
MSFS_CALLBACK void module_deinit(void)
{
// This is called when the module is deinitialized
}
}Gauge Callbacks
Gauge callbacks are used by the WASM gauges that you add to an aircraft through the [VCockpitN] section of the panel.cfg. In the names below, XXX is the name of the gauge as given in that section.
Lifecycle And Input
| Function | Description |
|---|---|
bool XXX_gauge_init(FsContext ctx, sGaugeInstallData* pInstallData) | Called once when the gauge is installed. Return false if there was an error. The gauge update callbacks listed below are only registered after this has succeeded. |
bool XXX_gauge_update(FsContext ctx, float dTime) | Called once per frame while the gauge is running. Return false if there was an error. This is the older form of XXX_gauge_late_update and is ignored if that callback exists (see MSFS 2024 Callback Overrides). |
bool XXX_gauge_draw(FsContext ctx, sGaugeDrawData* pDrawData) | Called once per frame to draw the gauge. Return false if there was an error. |
bool XXX_gauge_kill(FsContext ctx) | Called when the gauge is destroyed, so that you can free resources. Return false if there was an error. |
void XXX_gauge_mouse_handler(FsContext ctx, float fX, float fY, int iFlags) | Called when the user interacts with the gauge with the mouse. The iFlags values are defined in MSFS/Types/MSFS_EventsEnum.h. If this exists, the older XXX_mouse_callback is ignored. |
Frame Update
| Function | Description |
|---|---|
bool XXX_gauge_pre_sim_physics_update(FsContext ctx, float dTime) | Called before the physics update. |
bool XXX_gauge_post_sim_physics_update(FsContext ctx, float dTime) | Called after the physics update. |
bool XXX_gauge_pre_sim_systems_update(FsContext ctx, float dTime) | Called before the systems update. |
bool XXX_gauge_post_sim_systems_update(FsContext ctx, float dTime) | Called after the systems update. |
bool XXX_gauge_late_update(FsContext ctx, float dTime) | Called at the end of the frame update, before the draw. |
Standalone Module Callbacks
Standalone modules are not attached to any gauge, system or airport, and are always loaded. They have no context parameter.
| Function | Description |
|---|---|
void module_init(void) | Called when the module is initialised. |
void module_deinit(void) | Called when the module is deinitialised. |
void module_pre_sim_physics_update(float dTime) | Called before the physics update. |
void module_post_sim_physics_update(float dTime) | Called after the physics update. |
void module_pre_sim_systems_update(float dTime) | Called before the systems update. |
void module_post_sim_systems_update(float dTime) | Called after the systems update. |
void module_late_update(float dTime) | Called at the end of the frame update, before the draw. The older Update_StandAlone function is ignored if this exists (see MSFS 2024 Callback Overrides). |
Systems Callbacks
System callbacks are used by the WASM systems that you add to an aircraft through the [WASM_SYSTEM.N] section of the systems.cfg. In the names below, XXX is the name of the system as given in that section.
| Function | Description |
|---|---|
bool XXX_system_init(FsContext ctx, sSystemInstallData* pInstallData) | Called once when the system is created. Return false if there was an error. |
bool XXX_system_update(FsContext ctx, float dTime) | Called once per frame. Return false if there was an error. This is the older form of XXX_system_late_update and is ignored if that callback exists (see MSFS 2024 Callback Overrides). |
bool XXX_system_kill(FsContext ctx) | Called before the system is destroyed. Return false if there was an error. |
bool XXX_system_pre_sim_physics_update(FsContext ctx, float dTime) | Called before the physics update. |
bool XXX_system_post_sim_physics_update(FsContext ctx, float dTime) | Called after the physics update. |
bool XXX_system_pre_sim_systems_update(FsContext ctx, float dTime) | Called before the systems update. |
bool XXX_system_post_sim_systems_update(FsContext ctx, float dTime) | Called after the systems update. |
bool XXX_system_late_update(FsContext ctx, float dTime) | Called at the end of the frame update, before the draw. |
Airport Callbacks
Airport callbacks are used by the WASM airports. They receive an FsWasmAirportContext* ctx, whose ICAO member tells you which airport the call is for.
| Function | Description |
|---|---|
bool airport_init(FsWasmAirportContext* ctx) | Called when the airport is instantiated. Return false if there was an error. The older name AirportInit is ignored if this exists (see MSFS 2024 Callback Overrides). |
bool airport_kill(FsWasmAirportContext* ctx) | Called when the airport is removed from the simulation. Return false if there was an error. The older name AirportKill is ignored if this exists (see MSFS 2024 Callback Overrides). |
bool airport_pre_sim_physics_update(FsWasmAirportContext* ctx, float dTime) | Called before the physics update. |
bool airport_post_sim_physics_update(FsWasmAirportContext* ctx, float dTime) | Called after the physics update. |
bool airport_pre_sim_systems_update(FsWasmAirportContext* ctx, float dTime) | Called before the systems update. |
bool airport_post_sim_systems_update(FsWasmAirportContext* ctx, float dTime) | Called after the systems update. |
bool airport_late_update(FsWasmAirportContext* ctx, float dTime) | Called at the end of the frame update, before the draw. This is the newer form of AirportUpdate, which is ignored if this exists (see MSFS 2024 Callback Overrides). |
MSFS 2024 Callback Overrides
Exporting some callbacks will override and prevent the functioning of other, older callbacks. The exact callbacks affected by this are listed in the sections below, based on what kind of WASM module is being created.
Gauges
| If you export | This is then ignored |
|---|---|
XXX_gauge_late_update | XXX_gauge_update |
XXX_gauge_mouse_handler | XXX_mouse_callback |
In addition, the MSFS 2020 XXX_gauge_callback is only used when none of the following are exported:
XXX_gauge_initXXX_gauge_pre_sim_physics_updateXXX_gauge_post_sim_physics_updateXXX_gauge_pre_sim_systems_updateXXX_gauge_post_sim_systems_updateXXX_gauge_late_update(or the olderXXX_gauge_update)XXX_gauge_drawXXX_gauge_kill
This means that a gauge cannot mix the two styles: as soon as it exports a single MSFS 2024 callback, XXX_gauge_callback is never called.
Systems
| If you export | This is then ignored |
|---|---|
XXX_system_late_update | XXX_system_update |
Standalone Modules
| If you export | This is then ignored |
|---|---|
module_late_update | Update_StandAlone |
Airports
| If you export | This is then ignored |
|---|---|
airport_init | AirportInit |
airport_late_update | AirportUpdate |
airport_kill | AirportKill |
MSFS 2020 Callbacks
Gauges built for MSFS 2020 use a single XXX_gauge_callback function that is called with a service id, and an older mouse callback, instead of the separate functions described in the sections above. They are still supported in MSFS 2024, but all new gauges should use the Gauge Callbacks instead.
| Function | Description |
|---|---|
bool XXX_gauge_callback(FsContext ctx, int service_id, void* pData) | The MSFS 2020 gauge callback. It is only used if the gauge exports none of XXX_gauge_init, XXX_gauge_draw, XXX_gauge_kill or the five frame update callbacks (including the older XXX_gauge_update). |
void XXX_mouse_callback(float fX, float fY, unsigned int iFlags) | The old mouse callback, with no ctx parameter. It is only used if the gauge does not export XXX_gauge_mouse_handler. |
The service_id parameter is one of the following PANEL_SERVICE values, and tells you what pData points to:
| Service Id | pData |
|---|---|
PANEL_SERVICE_PRE_INSTALL | sGaugeInstallData* |
PANEL_SERVICE_POST_INSTALL | sGaugePostInstallData* (with a ctx member) |
PANEL_SERVICE_PRE_INITIALIZE, PANEL_SERVICE_POST_INITIALIZE | NULL |
PANEL_SERVICE_PRE_UPDATE, PANEL_SERVICE_POST_UPDATE | NULL |
PANEL_SERVICE_PRE_DRAW, PANEL_SERVICE_POST_DRAW | sGaugeDrawData* |
PANEL_SERVICE_PRE_KILL, PANEL_SERVICE_POST_KILL | NULL |
